初始化脚本
This commit is contained in:
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
14
.idea/misc.xml
generated
Normal file
14
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CodeInsightWorkspaceSettings">
|
||||
<option name="optimizeImportsOnTheFly" value="true" />
|
||||
</component>
|
||||
<component name="CompilerWorkspaceConfiguration">
|
||||
<option name="PARALLEL_COMPILATION" value="true" />
|
||||
</component>
|
||||
<component name="arthas.idea.plugin">
|
||||
<option name="redisAddress" value="" />
|
||||
<option name="redisAuth" value="" />
|
||||
<option name="redisCacheKey" value="" />
|
||||
</component>
|
||||
</project>
|
||||
17
pom.xml
Normal file
17
pom.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>pers.amos</groupId>
|
||||
<artifactId>game</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
208
script/qxzb/auto_login.py
Executable file
208
script/qxzb/auto_login.py
Executable file
@@ -0,0 +1,208 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flash 游戏自动登录脚本
|
||||
"""
|
||||
|
||||
import struct
|
||||
import requests
|
||||
import sys
|
||||
|
||||
class AMF0:
|
||||
"""AMF0 协议编码器"""
|
||||
|
||||
NUMBER = 0x00
|
||||
STRING = 0x02
|
||||
NULL = 0x05
|
||||
STRICT_ARRAY = 0x0A
|
||||
|
||||
@staticmethod
|
||||
def encode_number(num):
|
||||
return struct.pack('!Bd', AMF0.NUMBER, float(num))
|
||||
|
||||
@staticmethod
|
||||
def encode_string(s):
|
||||
s_bytes = s.encode('utf-8')
|
||||
return struct.pack('!BH', AMF0.STRING, len(s_bytes)) + s_bytes
|
||||
|
||||
@staticmethod
|
||||
def encode_null():
|
||||
return struct.pack('!B', AMF0.NULL)
|
||||
|
||||
@staticmethod
|
||||
def encode_strict_array(items):
|
||||
data = struct.pack('!BI', AMF0.STRICT_ARRAY, len(items))
|
||||
for item in items:
|
||||
if isinstance(item, (int, float)):
|
||||
data += AMF0.encode_number(item)
|
||||
elif isinstance(item, str):
|
||||
data += AMF0.encode_string(item)
|
||||
elif item is None:
|
||||
data += AMF0.encode_null()
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def encode_amf_request(target_uri, response_uri, params):
|
||||
data = b''
|
||||
data += struct.pack('!H', 0x0000) # AMF 版本
|
||||
data += struct.pack('!H', 0x0000) # Header count
|
||||
data += struct.pack('!H', 0x0001) # Message count
|
||||
|
||||
# Target URI
|
||||
target_bytes = target_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(target_bytes)) + target_bytes
|
||||
|
||||
# Response URI
|
||||
response_bytes = response_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(response_bytes)) + response_bytes
|
||||
|
||||
# Length
|
||||
data += struct.pack('!I', 0xFFFFFFFF)
|
||||
|
||||
# Body
|
||||
data += AMF0.encode_strict_array(params)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def login(username, password):
|
||||
"""登录游戏"""
|
||||
print("🎮 Flash 游戏自动登录")
|
||||
print("="*60)
|
||||
print(f"👤 用户名: {username}")
|
||||
print(f"🔑 密码: {'*' * len(password)}")
|
||||
print("="*60)
|
||||
print()
|
||||
|
||||
url = "http://47.121.191.22:8012/gateway"
|
||||
|
||||
# 构造登录请求
|
||||
amf_data = AMF0.encode_amf_request(
|
||||
target_uri="com.huzi.base.action.AccountAction.loginInner",
|
||||
response_uri="/1",
|
||||
params=[username, password]
|
||||
)
|
||||
|
||||
headers = {
|
||||
'Host': '47.121.191.22:8012',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:102.0) Gecko/20100101 Firefox/102.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Origin': 'http://47.121.191.22:8012',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'http://47.121.191.22:8012/swf13/Load.swf',
|
||||
'Content-Type': 'application/x-amf',
|
||||
'Content-Length': str(len(amf_data))
|
||||
}
|
||||
|
||||
print("🌐 正在连接服务器...")
|
||||
print(f"📤 请求方法: AccountAction.loginInner")
|
||||
print(f"📦 请求大小: {len(amf_data)} 字节")
|
||||
print()
|
||||
|
||||
try:
|
||||
session = requests.Session()
|
||||
response = session.post(url, data=amf_data, headers=headers, timeout=10)
|
||||
|
||||
print(f"📥 响应状态: {response.status_code}")
|
||||
print(f"📦 响应大小: {len(response.content)} 字节")
|
||||
print()
|
||||
|
||||
if response.status_code == 200:
|
||||
# 提取 Cookie
|
||||
cookie = None
|
||||
if 'Set-Cookie' in response.headers:
|
||||
set_cookie = response.headers['Set-Cookie']
|
||||
if 'JSESSIONID=' in set_cookie:
|
||||
cookie = set_cookie.split(';')[0]
|
||||
print(f"🔑 获取到 Cookie: {cookie}")
|
||||
|
||||
# 解析响应
|
||||
data = response.content
|
||||
|
||||
# 查找 result 字段
|
||||
result_pos = data.find(b'result')
|
||||
if result_pos > 0 and data[result_pos + 6] == 0x00:
|
||||
result_value = struct.unpack('!d', data[result_pos+7:result_pos+15])[0]
|
||||
result = int(result_value)
|
||||
|
||||
if result == 0:
|
||||
print("✅ 登录成功!")
|
||||
print()
|
||||
|
||||
# 提取用户信息
|
||||
user_id_pos = data.find(b'userId')
|
||||
if user_id_pos > 0 and data[user_id_pos + 6] == 0x00:
|
||||
user_id = int(struct.unpack('!d', data[user_id_pos+7:user_id_pos+15])[0])
|
||||
print(f"👤 用户ID: {user_id}")
|
||||
|
||||
point_pos = data.find(b'point')
|
||||
if point_pos > 0 and data[point_pos + 5] == 0x00:
|
||||
point = int(struct.unpack('!d', data[point_pos+6:point_pos+14])[0])
|
||||
print(f"💰 当前积分: {point}")
|
||||
|
||||
print()
|
||||
print("="*60)
|
||||
|
||||
if cookie:
|
||||
# 保存 Cookie 到文件
|
||||
cookie_file = "/Users/amos/Downloads/game/7q/latest_cookie.txt"
|
||||
with open(cookie_file, 'w') as f:
|
||||
f.write(cookie)
|
||||
print(f"💾 Cookie 已保存到: {cookie_file}")
|
||||
print()
|
||||
print("💡 使用方法:")
|
||||
print(f" python3 exchange_item.py \"{cookie}\" 9")
|
||||
print("="*60)
|
||||
|
||||
return cookie, session
|
||||
|
||||
return None, session
|
||||
else:
|
||||
print(f"❌ 登录失败 (result={result})")
|
||||
|
||||
# 查找错误消息
|
||||
msg_pos = data.find(b'msg')
|
||||
if msg_pos > 0 and data[msg_pos + 3] == 0x02:
|
||||
msg_len = struct.unpack('!H', data[msg_pos+4:msg_pos+6])[0]
|
||||
if msg_len > 0:
|
||||
msg = data[msg_pos+6:msg_pos+6+msg_len].decode('utf-8', errors='ignore')
|
||||
print(f"💬 错误信息: {msg}")
|
||||
|
||||
return None, None
|
||||
|
||||
print("⚠️ 无法解析响应")
|
||||
return None, None
|
||||
else:
|
||||
print(f"❌ 请求失败: HTTP {response.status_code}")
|
||||
return None, None
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 请求异常: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return None, None
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) >= 3:
|
||||
username = sys.argv[1]
|
||||
password = sys.argv[2]
|
||||
else:
|
||||
# 默认账号(从抓包中获取)
|
||||
username = "amos"
|
||||
password = "xiaobiao."
|
||||
print("⚠️ 使用默认账号")
|
||||
print("💡 提示: 可以通过参数传入: python3 auto_login.py 用户名 密码")
|
||||
print()
|
||||
|
||||
cookie, session = login(username, password)
|
||||
|
||||
if cookie:
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
355
script/qxzb/exchange_item.py
Normal file
355
script/qxzb/exchange_item.py
Normal file
@@ -0,0 +1,355 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Flash 游戏兑换脚本
|
||||
基于抓包分析:登录后需要先调用 getExchangeItemList,然后才能兑换
|
||||
"""
|
||||
|
||||
import struct
|
||||
import requests
|
||||
import sys
|
||||
import time
|
||||
|
||||
# ==================== 配置 ====================
|
||||
USERNAME = "amos"
|
||||
PASSWORD = "xiaobiao."
|
||||
SERVER_URL = "http://47.121.191.22:8012/gateway"
|
||||
COOKIE_FILE = "/Users/amos/Downloads/game/7q/latest_cookie.txt"
|
||||
# ==============================================
|
||||
|
||||
class AMF0:
|
||||
"""AMF0 协议编码器"""
|
||||
|
||||
NUMBER = 0x00
|
||||
STRING = 0x02
|
||||
NULL = 0x05
|
||||
STRICT_ARRAY = 0x0A
|
||||
|
||||
@staticmethod
|
||||
def encode_amf_request(target_uri, response_uri, params):
|
||||
"""编码 AMF 请求"""
|
||||
data = b''
|
||||
data += struct.pack('!H', 0x0000) # AMF 版本
|
||||
data += struct.pack('!H', 0x0000) # Header count
|
||||
data += struct.pack('!H', 0x0001) # Message count
|
||||
|
||||
# Target URI
|
||||
target_bytes = target_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(target_bytes)) + target_bytes
|
||||
|
||||
# Response URI
|
||||
response_bytes = response_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(response_bytes)) + response_bytes
|
||||
|
||||
# Length
|
||||
data += struct.pack('!I', 0xFFFFFFFF)
|
||||
|
||||
# Body - Strict array
|
||||
data += struct.pack('!BI', AMF0.STRICT_ARRAY, len(params))
|
||||
for item in params:
|
||||
if isinstance(item, (int, float)):
|
||||
data += struct.pack('!Bd', AMF0.NUMBER, float(item))
|
||||
elif isinstance(item, str):
|
||||
s_bytes = item.encode('utf-8')
|
||||
data += struct.pack('!BH', AMF0.STRING, len(s_bytes)) + s_bytes
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def login(session):
|
||||
"""登录获取 Cookie"""
|
||||
print("🔐 正在登录...")
|
||||
|
||||
amf_data = AMF0.encode_amf_request(
|
||||
target_uri="com.huzi.base.action.AccountAction.loginInner",
|
||||
response_uri="/1",
|
||||
params=[USERNAME, PASSWORD]
|
||||
)
|
||||
|
||||
headers = {
|
||||
'Host': '47.121.191.22:8012',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:102.0) Gecko/20100101 Firefox/102.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Origin': 'http://47.121.191.22:8012',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'http://47.121.191.22:8012/swf13/Load.swf',
|
||||
'Content-Type': 'application/x-amf'
|
||||
}
|
||||
|
||||
response = session.post(SERVER_URL, data=amf_data, headers=headers, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
# 提取 Cookie
|
||||
if 'Set-Cookie' in response.headers:
|
||||
set_cookie = response.headers['Set-Cookie']
|
||||
if 'JSESSIONID=' in set_cookie:
|
||||
jsessionid = set_cookie.split(';')[0]
|
||||
print(f"✅ 登录成功: {jsessionid}")
|
||||
return jsessionid
|
||||
|
||||
print("❌ 登录失败")
|
||||
return None
|
||||
|
||||
|
||||
def init_exchange(session, cookie, item_id, request_id):
|
||||
"""初始化兑换(调用 getShowExchange)"""
|
||||
print(f"📋 初始化物品 {item_id} 的兑换信息...")
|
||||
|
||||
amf_data = AMF0.encode_amf_request(
|
||||
target_uri="com.huzi.play.action.ExchangeAction.getShowExchange",
|
||||
response_uri=f"/{request_id}",
|
||||
params=[item_id]
|
||||
)
|
||||
|
||||
headers = {
|
||||
'Host': '47.121.191.22:8012',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:102.0) Gecko/20100101 Firefox/102.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Cookie': cookie,
|
||||
'Origin': 'http://47.121.191.22:8012',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'http://47.121.191.22:8012/swf13/Load.swf',
|
||||
'Content-Type': 'application/x-amf'
|
||||
}
|
||||
|
||||
try:
|
||||
response = session.post(SERVER_URL, data=amf_data, headers=headers, timeout=10)
|
||||
if response.status_code == 200:
|
||||
data = response.content
|
||||
print(f"✅ 初始化成功 (响应大小: {len(data)} 字节)")
|
||||
|
||||
# 打印响应内容用于分析
|
||||
print(f"🔍 响应内容 (十六进制前200字节):")
|
||||
hex_data = data[:200].hex()
|
||||
for i in range(0, len(hex_data), 64):
|
||||
print(f" {hex_data[i:i+64]}")
|
||||
|
||||
print(f"🔍 响应内容 (可读文本):")
|
||||
try:
|
||||
readable = data.decode('utf-8', errors='ignore')
|
||||
lines = [line for line in readable.split('\n') if line.strip()]
|
||||
for line in lines[:20]: # 只显示前20行
|
||||
print(f" {line}")
|
||||
except:
|
||||
pass
|
||||
|
||||
return True
|
||||
else:
|
||||
print(f"❌ 初始化失败: HTTP {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ 初始化异常: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def exchange_item(session, cookie, item_id, quantity, request_id):
|
||||
"""兑换物品"""
|
||||
|
||||
amf_data = AMF0.encode_amf_request(
|
||||
target_uri="com.huzi.play.action.ExchangeAction.exchangeItem",
|
||||
response_uri=f"/{request_id}",
|
||||
params=[item_id, quantity]
|
||||
)
|
||||
|
||||
headers = {
|
||||
'Host': '47.121.191.22:8012',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:102.0) Gecko/20100101 Firefox/102.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Cookie': cookie,
|
||||
'Origin': 'http://47.121.191.22:8012',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'http://47.121.191.22:8012/swf13/Load.swf',
|
||||
'Content-Type': 'application/x-amf'
|
||||
}
|
||||
|
||||
print(f"\n 📤 请求: ExchangeAction.exchangeItem({item_id}, {quantity})")
|
||||
print(f" 📍 Response URI: /{request_id}")
|
||||
|
||||
try:
|
||||
response = session.post(SERVER_URL, data=amf_data, headers=headers, timeout=10)
|
||||
|
||||
print(f" 📥 响应状态: {response.status_code}")
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.content
|
||||
print(f" 📦 响应大小: {len(data)} 字节")
|
||||
|
||||
# 检查是否是错误响应
|
||||
if b'onStatus' in data:
|
||||
print(f" ⚠️ 检测到 onStatus (错误响应)")
|
||||
print(f" 🔧 完整响应 (十六进制):")
|
||||
hex_data = data.hex()
|
||||
for i in range(0, len(hex_data), 64):
|
||||
print(f" {hex_data[i:i+64]}")
|
||||
print(f" 🔧 完整响应 (ASCII):")
|
||||
try:
|
||||
readable = data.decode('utf-8', errors='ignore')
|
||||
for line in readable.split('\n'):
|
||||
if line.strip():
|
||||
print(f" {line}")
|
||||
except:
|
||||
pass
|
||||
|
||||
if b'NullPointerException' in data:
|
||||
print(f" ⚠️ NullPointerException - 需要先初始化")
|
||||
return False, "服务器错误"
|
||||
|
||||
# 查找 result 字段
|
||||
result_pos = data.find(b'result')
|
||||
|
||||
if result_pos > 0:
|
||||
value_pos = result_pos + 6
|
||||
|
||||
if value_pos < len(data):
|
||||
value_type = data[value_pos]
|
||||
|
||||
if value_type == 0x00: # Number
|
||||
if value_pos + 9 <= len(data):
|
||||
result_value = struct.unpack('!d', data[value_pos+1:value_pos+9])[0]
|
||||
result = int(result_value)
|
||||
print(f" 📊 result = {result}")
|
||||
|
||||
if result == 0:
|
||||
return True, "成功"
|
||||
else:
|
||||
# 查找 msg
|
||||
msg = None
|
||||
msg_pos = data.find(b'msg')
|
||||
if msg_pos > 0:
|
||||
msg_value_pos = msg_pos + 3
|
||||
if msg_value_pos < len(data):
|
||||
msg_type = data[msg_value_pos]
|
||||
if msg_type == 0x02: # String
|
||||
try:
|
||||
if msg_value_pos + 3 <= len(data):
|
||||
msg_len = struct.unpack('!H', data[msg_value_pos+1:msg_value_pos+3])[0]
|
||||
if msg_len > 0 and msg_value_pos + 3 + msg_len <= len(data):
|
||||
msg = data[msg_value_pos+3:msg_value_pos+3+msg_len].decode('utf-8', errors='ignore')
|
||||
print(f" 💬 msg = {msg}")
|
||||
except:
|
||||
pass
|
||||
return False, msg if msg else f"失败(result={result})"
|
||||
|
||||
return False, "无法解析响应"
|
||||
else:
|
||||
return False, f"HTTP {response.status_code}"
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False, f"异常: {e}"
|
||||
|
||||
|
||||
def read_cookie():
|
||||
"""从文件读取 Cookie"""
|
||||
try:
|
||||
with open(COOKIE_FILE, 'r') as f:
|
||||
cookie = f.read().strip()
|
||||
if cookie:
|
||||
return cookie
|
||||
except FileNotFoundError:
|
||||
print(f"⚠️ Cookie 文件不存在: {COOKIE_FILE}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ 读取 Cookie 失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
print("🎮 Flash 游戏兑换脚本")
|
||||
print("="*60)
|
||||
print(f"👤 账号: {USERNAME}")
|
||||
|
||||
# 从文件读取 Cookie
|
||||
cookie = read_cookie()
|
||||
if not cookie:
|
||||
print("❌ 无法读取 Cookie,请确保游戏已登录")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"🔑 Cookie: {cookie}")
|
||||
print("⚠️ 需要在游戏中保持登录状态")
|
||||
|
||||
# 物品ID
|
||||
if len(sys.argv) >= 2:
|
||||
item_id = int(sys.argv[1])
|
||||
else:
|
||||
item_id = 9
|
||||
print(f"\n⚠️ 使用默认物品 ID: {item_id}")
|
||||
|
||||
# 兑换次数
|
||||
if len(sys.argv) >= 3:
|
||||
total_count = int(sys.argv[2])
|
||||
else:
|
||||
print("\n💡 请输入兑换次数")
|
||||
while True:
|
||||
try:
|
||||
count_input = input("兑换次数 (默认1次): ").strip()
|
||||
total_count = int(count_input) if count_input else 1
|
||||
if total_count > 0:
|
||||
break
|
||||
print("❌ 请输入大于0的数字")
|
||||
except ValueError:
|
||||
print("❌ 请输入有效的数字")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print(f"🎁 物品ID: {item_id}")
|
||||
print(f"🔢 兑换次数: {total_count}")
|
||||
print("="*60)
|
||||
|
||||
# 创建 Session
|
||||
session = requests.Session()
|
||||
|
||||
request_id = 2
|
||||
|
||||
# 初始化兑换(调用 getShowExchange,关键步骤!)
|
||||
if not init_exchange(session, cookie, item_id, request_id):
|
||||
print("\n❌ 初始化失败,无法继续")
|
||||
sys.exit(1)
|
||||
|
||||
request_id += 1
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("🚀 开始批量兑换")
|
||||
print("="*60)
|
||||
|
||||
success_count = 0
|
||||
fail_count = 0
|
||||
|
||||
for i in range(total_count):
|
||||
print(f"\n[{i+1}/{total_count}] 兑换中...", end=" ")
|
||||
|
||||
success, message = exchange_item(session, cookie, item_id, 1, request_id)
|
||||
request_id += 1
|
||||
|
||||
if success:
|
||||
success_count += 1
|
||||
print(f"✅ {message}")
|
||||
else:
|
||||
fail_count += 1
|
||||
print(f"❌ {message}")
|
||||
|
||||
if fail_count >= 3:
|
||||
print("\n⚠️ 连续失败3次")
|
||||
choice = input("是否继续? (y/n): ").strip().lower()
|
||||
if choice != 'y':
|
||||
break
|
||||
fail_count = 0
|
||||
|
||||
if i < total_count - 1:
|
||||
time.sleep(0.5)
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("📊 兑换统计")
|
||||
print("="*60)
|
||||
print(f"✅ 成功: {success_count} 次")
|
||||
print(f"❌ 失败: {fail_count} 次")
|
||||
if success_count + fail_count > 0:
|
||||
print(f"📈 成功率: {success_count/(success_count+fail_count)*100:.1f}%")
|
||||
print("="*60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
81
script/qxzb/start_capture.sh
Executable file
81
script/qxzb/start_capture.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Flash 游戏抓包脚本
|
||||
# 用于捕获游戏的 HTTP 请求并转换为可读文本
|
||||
#
|
||||
|
||||
# 输出目录
|
||||
OUTPUT_DIR="/Users/amos/Downloads/game/7q"
|
||||
|
||||
# 确保目录存在
|
||||
mkdir -p "${OUTPUT_DIR}"
|
||||
|
||||
echo "🎮 Flash 游戏抓包工具"
|
||||
echo "======================================"
|
||||
echo ""
|
||||
echo "📡 目标服务器: 47.121.191.22:8012"
|
||||
echo "🔍 过滤条件: HTTP 请求"
|
||||
echo "📁 输出目录: ${OUTPUT_DIR}"
|
||||
echo ""
|
||||
echo "⚠️ 按 Ctrl+C 停止录制"
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo ""
|
||||
|
||||
# 生成时间戳文件名
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
PCAP_FILE="${OUTPUT_DIR}/game_capture_${TIMESTAMP}.pcapng"
|
||||
TEXT_FILE="${OUTPUT_DIR}/game_capture_${TIMESTAMP}.txt"
|
||||
COOKIE_FILE="${OUTPUT_DIR}/latest_cookie.txt"
|
||||
|
||||
echo "💾 二进制文件: ${PCAP_FILE}"
|
||||
echo "📄 文本文件: ${TEXT_FILE}"
|
||||
echo ""
|
||||
echo "🚀 开始录制..."
|
||||
echo ""
|
||||
|
||||
# 直接录制并转换为文本(和你的命令一样)
|
||||
sudo tshark -i any -f "host 47.121.191.22 and port 8012" -Y "http" -V | tee "${TEXT_FILE}"
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "✅ 录制已停止"
|
||||
echo ""
|
||||
|
||||
# 同时保存一份到 pcapng(可选,用于后续分析)
|
||||
echo "<22> 统计信息:"
|
||||
echo " 文本文件大小: $(ls -lh ${TEXT_FILE} | awk '{print $5}')"
|
||||
echo " HTTP 请求数量: $(grep -c "POST\|GET" ${TEXT_FILE})"
|
||||
echo ""
|
||||
|
||||
# 提取 Cookie
|
||||
echo "🔑 提取 Cookie..."
|
||||
COOKIE=$(grep -o "JSESSIONID=[A-Z0-9]*" "${TEXT_FILE}" | head -1)
|
||||
|
||||
if [ -n "$COOKIE" ]; then
|
||||
echo "✅ 找到 Cookie: ${COOKIE}"
|
||||
echo ""
|
||||
echo "💡 使用方法:"
|
||||
echo " cd game"
|
||||
echo " python3 exchange_item.py \"${COOKIE}\" 9"
|
||||
echo ""
|
||||
|
||||
# 保存 Cookie 到文件
|
||||
echo "${COOKIE}" > "${COOKIE_FILE}"
|
||||
echo "💾 Cookie 已保存到: ${COOKIE_FILE}"
|
||||
else
|
||||
echo "⚠️ 未找到 Cookie,请确保在游戏中进行了操作"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📋 提取的 API 调用:"
|
||||
grep "Target URI:" "${TEXT_FILE}" | sed 's/.*Target URI: / - /' | sort | uniq
|
||||
|
||||
echo ""
|
||||
echo "======================================"
|
||||
echo "📁 生成的文件:"
|
||||
echo " ${TEXT_FILE}"
|
||||
echo " ${COOKIE_FILE}"
|
||||
echo ""
|
||||
echo "💡 提示: 文本文件可以直接发给 AI 分析"
|
||||
echo "======================================"
|
||||
187
script/qxzb/test_bypass.py
Normal file
187
script/qxzb/test_bypass.py
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
测试绕过兑换条件的脚本
|
||||
警告:这些方法可能不起作用,仅用于学习研究
|
||||
"""
|
||||
|
||||
import struct
|
||||
import requests
|
||||
import sys
|
||||
import time
|
||||
|
||||
SERVER_URL = "http://47.121.191.22:8012/gateway"
|
||||
COOKIE_FILE = "/Users/amos/Downloads/game/7q/latest_cookie.txt"
|
||||
|
||||
class AMF0:
|
||||
"""AMF0 协议编码器"""
|
||||
|
||||
NUMBER = 0x00
|
||||
STRING = 0x02
|
||||
NULL = 0x05
|
||||
STRICT_ARRAY = 0x0A
|
||||
|
||||
@staticmethod
|
||||
def encode_amf_request(target_uri, response_uri, params):
|
||||
"""编码 AMF 请求"""
|
||||
data = b''
|
||||
data += struct.pack('!H', 0x0000)
|
||||
data += struct.pack('!H', 0x0000)
|
||||
data += struct.pack('!H', 0x0001)
|
||||
|
||||
target_bytes = target_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(target_bytes)) + target_bytes
|
||||
|
||||
response_bytes = response_uri.encode('utf-8')
|
||||
data += struct.pack('!H', len(response_bytes)) + response_bytes
|
||||
|
||||
data += struct.pack('!I', 0xFFFFFFFF)
|
||||
|
||||
data += struct.pack('!BI', AMF0.STRICT_ARRAY, len(params))
|
||||
for item in params:
|
||||
if isinstance(item, (int, float)):
|
||||
data += struct.pack('!Bd', AMF0.NUMBER, float(item))
|
||||
elif isinstance(item, str):
|
||||
s_bytes = item.encode('utf-8')
|
||||
data += struct.pack('!BH', AMF0.STRING, len(s_bytes)) + s_bytes
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def read_cookie():
|
||||
"""从文件读取 Cookie"""
|
||||
try:
|
||||
with open(COOKIE_FILE, 'r') as f:
|
||||
return f.read().strip()
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def test_exchange(session, cookie, item_id, quantity, test_name):
|
||||
"""测试兑换"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"🧪 测试: {test_name}")
|
||||
print(f"{'='*60}")
|
||||
print(f"物品ID: {item_id}, 数量: {quantity}")
|
||||
|
||||
amf_data = AMF0.encode_amf_request(
|
||||
target_uri="com.huzi.play.action.ExchangeAction.exchangeItem",
|
||||
response_uri="/1",
|
||||
params=[item_id, quantity]
|
||||
)
|
||||
|
||||
headers = {
|
||||
'Host': '47.121.191.22:8012',
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:102.0) Gecko/20100101 Firefox/102.0',
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept-Encoding': 'gzip, deflate',
|
||||
'Cookie': cookie,
|
||||
'Origin': 'http://47.121.191.22:8012',
|
||||
'Connection': 'keep-alive',
|
||||
'Referer': 'http://47.121.191.22:8012/swf13/Load.swf',
|
||||
'Content-Type': 'application/x-amf'
|
||||
}
|
||||
|
||||
try:
|
||||
response = session.post(SERVER_URL, data=amf_data, headers=headers, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.content
|
||||
|
||||
# 查找 result
|
||||
result_pos = data.find(b'result')
|
||||
if result_pos > 0:
|
||||
value_pos = result_pos + 6
|
||||
if value_pos < len(data) and data[value_pos] == 0x00:
|
||||
if value_pos + 9 <= len(data):
|
||||
result_value = struct.unpack('!d', data[value_pos+1:value_pos+9])[0]
|
||||
result = int(result_value)
|
||||
|
||||
# 查找 msg
|
||||
msg = None
|
||||
msg_pos = data.find(b'msg')
|
||||
if msg_pos > 0:
|
||||
msg_value_pos = msg_pos + 3
|
||||
if msg_value_pos < len(data) and data[msg_value_pos] == 0x02:
|
||||
try:
|
||||
msg_len = struct.unpack('!H', data[msg_value_pos+1:msg_value_pos+3])[0]
|
||||
if msg_len > 0 and msg_value_pos + 3 + msg_len <= len(data):
|
||||
msg = data[msg_value_pos+3:msg_value_pos+3+msg_len].decode('utf-8', errors='ignore')
|
||||
except:
|
||||
pass
|
||||
|
||||
if result == 0:
|
||||
print(f"✅ 成功!")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ 失败: result={result}, msg={msg}")
|
||||
return False
|
||||
|
||||
print(f"❌ 无法解析响应")
|
||||
return False
|
||||
else:
|
||||
print(f"❌ HTTP {response.status_code}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ 异常: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
print("🎮 Flash 游戏兑换绕过测试")
|
||||
print("="*60)
|
||||
print("⚠️ 警告:这些测试可能触发服务端安全机制")
|
||||
print("="*60)
|
||||
|
||||
cookie = read_cookie()
|
||||
if not cookie:
|
||||
print("❌ 无法读取 Cookie")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"🔑 Cookie: {cookie}")
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
item_id = int(sys.argv[1]) if len(sys.argv) > 1 else 9
|
||||
|
||||
# 测试1: 正常请求(基准)
|
||||
test_exchange(session, cookie, item_id, 1, "正常请求 (数量=1)")
|
||||
time.sleep(1)
|
||||
|
||||
# 测试2: 零数量
|
||||
test_exchange(session, cookie, item_id, 0, "零数量 (数量=0)")
|
||||
time.sleep(1)
|
||||
|
||||
# 测试3: 负数数量(整数溢出)
|
||||
test_exchange(session, cookie, item_id, -1, "负数数量 (数量=-1)")
|
||||
time.sleep(1)
|
||||
|
||||
# 测试4: 小数数量
|
||||
test_exchange(session, cookie, item_id, 0.1, "小数数量 (数量=0.1)")
|
||||
time.sleep(1)
|
||||
|
||||
# 测试5: 超大数量
|
||||
test_exchange(session, cookie, item_id, 999999, "超大数量 (数量=999999)")
|
||||
time.sleep(1)
|
||||
|
||||
# 测试6: 尝试其他物品ID
|
||||
print(f"\n{'='*60}")
|
||||
print("🔍 尝试其他物品ID")
|
||||
print(f"{'='*60}")
|
||||
|
||||
for test_id in range(1, 20):
|
||||
if test_id == item_id:
|
||||
continue
|
||||
print(f"\n测试物品ID: {test_id}")
|
||||
if test_exchange(session, cookie, test_id, 1, f"物品ID={test_id}"):
|
||||
print(f"🎉 物品ID {test_id} 可以兑换!")
|
||||
break
|
||||
time.sleep(0.5)
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print("测试完成")
|
||||
print(f"{'='*60}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user