单纯修改字符串很简单,反编译出pyc后直接hook就行
settexto = QMessageBox.setText
def setText(text, p_str=None):
print("setText")
if p_str == "错误!":
p_str = "正确!"
return settexto(text, p_str)
entertain.QMessageBox.setText = setText
setWindowTitleo = QMessageBox.setWindowTitle
def setWindowTitle(title, p_str=None):
print("setWindowTitle")
if p_str == "你干嘛~":
p_str += "~~~~"
return setWindowTitleo(title, p_str)
entertain.QMessageBox.setWindowTitle = setWindowTitle
还原也不难,主要用的全是标准库,建议下次自己写加密函数
一开始随机生成了key和iv
直接修改对应py
\Lib\site-packages\Crypto\Random
def get_random_bytes(n):
print("get_random_bytes", n)
return b"0"*n
然后获取了时间戳
def toMSecsSinceEpoch(self):
print("toMSecsSinceEpoch")
return 0
entertain.QDateTime.toMSecsSinceEpoch = toMSecsSinceEpoch
aes cbc 加密上面时间
key1=b"kfmd42fjdns66ex4dmfge888qazom006"
iv1=b"dkexnf5gae426gao"
生成秘钥对
key = '''-----BEGIN PRIVATE KEY-----
。。。。。。
-----END PRIVATE KEY-----'''
rsakey = RSA.import_key(key)
def generate(size: int):
print("generate")
return rsakey
rsa加密上面加密后的内容
然后又aes加密
key2=b"zhf2g5izi2lf5hchenwo11xicm4flyol"
iv2=b"b11houruz66zc662"
取前13位当做uid
然后又aes加密uid
key3=b"zhsvb99wo555fb1cde11hao4dzpe33ca"
iv3=b"oni1hourcvbuzz66"
最后在用一开始生成随机字节加密
上面几次aes的key都可以抓包拿到
然后尝试输入key,可以发现赋值给user_key
直接尝试反汇编器
dis.dis(entertain)
主要逻辑在entertain.CaptchaApp.verify)里面
137 0 RESUME 0
139 2 LOAD_FAST 0 (self)
4 LOAD_ATTR 0 (user_key_edit)
14 LOAD_METHOD 1 (text)
36 PRECALL 0
40 CALL 0
50 STORE_FAST 1 (user_key)
141 52 LOAD_GLOBAL 5 (NULL + QMessageBox)
64 PRECALL 0
68 CALL 0
78 STORE_FAST 2 (msg)
142 80 LOAD_FAST 1 (user_key)
82 LOAD_GLOBAL 6 (encrypted_key)
94 COMPARE_OP 2 (==)
100 POP_JUMP_FORWARD_IF_FALSE 74 (to 250)
143 102 LOAD_FAST 2 (msg)
104 LOAD_METHOD 4 (setIcon)
126 LOAD_GLOBAL 4 (QMessageBox)
138 LOAD_ATTR 5 (Information)
148 PRECALL 1
152 CALL 1
162 POP_TOP
144 164 LOAD_FAST 2 (msg)
166 LOAD_METHOD 6 (setText)
188 LOAD_CONST 1 ('Success')
190 PRECALL 1
194 CALL 1
204 POP_TOP
145 206 LOAD_FAST 2 (msg)
208 LOAD_METHOD 7 (setWindowTitle)
230 LOAD_CONST 2 ('成功!')
232 PRECALL 1
236 CALL 1
246 POP_TOP
248 JUMP_FORWARD 73 (to 396)
147 >> 250 LOAD_FAST 2 (msg)
252 LOAD_METHOD 4 (setIcon)
274 LOAD_GLOBAL 4 (QMessageBox)
286 LOAD_ATTR 8 (Critical)
296 PRECALL 1
300 CALL 1
310 POP_TOP
148 312 LOAD_FAST 2 (msg)
314 LOAD_METHOD 6 (setText)
336 LOAD_CONST 3 ('错误!')
338 PRECALL 1
342 CALL 1
352 POP_TOP
149 354 LOAD_FAST 2 (msg)
356 LOAD_METHOD 7 (setWindowTitle)
378 LOAD_CONST 4 ('你干嘛~')
380 PRECALL 1
384 CALL 1
394 POP_TOP
151 >> 396 LOAD_FAST 2 (msg)
398 LOAD_METHOD 9 (exec_)
420 PRECALL 0
424 CALL 0
434 POP_TOP
436 LOAD_CONST 0 (None)
438 RETURN_VALUE
主要就是对比encrypted_key和user_key,encrypted_key是GLOBAL 的,直接获取
142 80 LOAD_FAST 1 (user_key)
82 LOAD_GLOBAL 6 (encrypted_key)
94 COMPARE_OP 2 (==)
100 POP_JUMP_FORWARD_IF_FALSE 74 (to 250)
实际上就是最后一次aes加密结果
所以直接抓包,从第一个包里面获取key3
http://wanyuanshen.fun/get_key_iv.php?key=ikun114514
{"keys":["aes_key1 = 'kfmd42fjdns66ex4dmfge888qazom006'","aes_key2 = 'zhf2g5izi2lf5hchenwo11xicm4flyol'","aes_key3 = 'zhsvb99wo555fb1cde11hao4dzpe33ca'"],"ivs":["aes_iv1 = 'dkexnf5gae426gao'","aes_iv2 = 'b11houruz66zc662'","aes_iv3 = 'oni1hourcvbuzz66'"]}
第二个包里面获取key4
POST http://wanyuanshen.fun/receive_key_iv.php HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Content-Length: 104
Content-Type: application/x-www-form-urlencoded
Host: wanyuanshen.fun
User-Agent: Python/3.11 aiohttp/3.8.4
key=22876898cd1120fabed253189e7b61dd6976779d99717a56225bad67a2de8394&iv=45134edad04f8281d8657748ca6bbd44
加密两次uid就行
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
uid = "f0eced2a1d359"
key3 = b"zhsvb99wo555fb1cde11hao4dzpe33ca"
iv3 = b"oni1hourcvbuzz66"
cipher4 = AES.new(key3, AES.MODE_CBC, iv3)
enc4 = cipher4.encrypt(pad(uid.encode(), AES.block_size))
key4 = bytes.fromhex("22876898cd1120fabed253189e7b61dd6976779d99717a56225bad67a2de8394")
iv4 = bytes.fromhex("45134edad04f8281d8657748ca6bbd44")
cipher5 = AES.new(key4, AES.MODE_CBC, iv4)
dec5 = cipher5.encrypt(enc4)
print(dec5.hex())
#643cc186d6c48261f7b081f31138f8a2