本帖最后由 monvvv 于 2020-8-26 15:34 编辑
直接IDA F5硬上(虽然有些循环被unroll了)费了亿点点时间搞好了。没怎么弄过Win32 App,有一半时间都花在了理解流程上。。。数据流:
```mermaid
sequenceDiagram
participant Group
participant Button
participant Button2
opt LBUTTONDOWN
Button2 -->> Group: Save username to WindowText
Note right of Button2: Cook mid_pwd with raw password
Button2 ->> Button: Call proc
Note right of Button: Cook raw_data<br>with mid_pwd and username
end
opt LBUTTONUP
Button ->> Group: WM_COMMAND 0xCE7
note right of Group: Cook data with raw_data
note right of Button: Check and remove tail
Button -->> Group: Save data to WindowText
Button ->> Group: WM_COMMAND 0xCE5
note right of Group: Check data and set to label
end```
加密:
[Python] 纯文本查看 复制代码 from ctypes import c_uint32
from utils import *
def parse_sn(sn):
v = []
for p in sn.split('-'):
b = bytes.fromhex(p)
assert len(b) == 4
v.extend(b)
return v
def cook_raw_sn(sn):
def f(a): return ((a ^ sn[-2]) + sn[-1]) & 0xFF
sn = list(sn)
k = chain(map(f, sn[:22]), sn[-2:])
return k
def process_mid_sn(sn):
MAGIC_KEY = [0x937ED889, 0x8E9BA899, 0x78E1C09E, 0xC9A87D8E]
# TEA-like encrypt
def process_block(a, b):
delta = 0x61C88647
a = c_uint32(a)
b = c_uint32(b)
s = c_uint32(0)
for _ in range(32):
s.value -= delta
a.value += (s.value ^ (b.value >> 5)) + \
MAGIC_KEY[0] + (MAGIC_KEY[1] ^ b.value) + (b.value << 4)
b.value += (s.value ^ (a.value >> 5)) + \
MAGIC_KEY[3] + (MAGIC_KEY[2] ^ a.value) + (a.value << 4)
return a.value, b.value
t = uint32s_to_bytes(chain(
*map(lambda ns: process_block(ns[0], ns[1]), grouper(2, bytes_to_uint32s(sn)))))
return t
def cook_username(username):
MAGIC = b'c0DebY SOLLY'
k = crc(username.encode()) + \
int.from_bytes(MAGIC[4:8], 'little') + \
int.from_bytes(MAGIC[8:], 'little')
return k & 0xFFFFFFFF
def mix_sn_and_username(username, sn):
k = cook_username(username)
delta = 0x76BDEFDB
s = c_uint32(0)
k = c_uint32(k)
l = []
for v in bytes_to_uint32s(sn):
k.value -= delta
# Reverse bytes
k.value = int.from_bytes(k.value.to_bytes(4, 'big'), 'little')
s.value = (s.value ^ v) + k.value
l.append(s.value)
return uint32s_to_bytes(l)
def process_data(data):
MAGIC_KEY = [
0x65A04939, 0x51B194D7, 0xE288C9D9,
0x077FBB77, 0xFD05CDF1, 0xA399B665
]
v = [v ^ MAGIC_KEY[i] for i, v in enumerate(bytes_to_uint32s(data))]
return uint32s_to_bytes(v)
def check(data):
data = list(data)
assert len(data) == 24
ints = list(bytes_to_uint32s(data))
if ints[-2] == 0:
return False
if ints[-2] ^ ints[-1] != 0xFFFFFFFF:
return False
if not bytes(data)[:16].decode('gbk').startswith('成'):
return False
return True
if __name__ == "__main__":
username = '123456'
sn = '95E11821-1C4A3FFE-7E978C5E-259DFD9B-BAD811D0-D6A75D31'
raw_sn = parse_sn(sn)
mid_sn = cook_raw_sn(raw_sn)
final_sn = process_mid_sn(mid_sn)
data = mix_sn_and_username(username, final_sn)
final_data = process_data(data)
print(check(final_data))
由于最后的检测太宽松导致存在多解。
解密:
[Python] 纯文本查看 复制代码 from utils import *
from ctypes import c_uint32
TARGET_DATA = list(chain('成功了,好牛逼!'.encode(
'gbk'), b'\xFF\xFF\xFF\xFF\x00\x00\x00\x00'))
def decode_data(data):
MAGIC_KEY = [
0x65A04939, 0x51B194D7, 0xE288C9D9,
0x077FBB77, 0xFD05CDF1, 0xA399B665
]
v = [v ^ MAGIC_KEY[i] for i, v in enumerate(bytes_to_uint32s(data))]
return uint32s_to_bytes(v)
def cook_username(username):
MAGIC = b'c0DebY SOLLY'
k = crc(username.encode()) + \
int.from_bytes(MAGIC[4:8], 'little') + \
int.from_bytes(MAGIC[8:], 'little')
return k & 0xFFFFFFFF
def extract_sn_from_data(username, data):
k = cook_username(username)
delta = 0x76BDEFDB
s = c_uint32(0)
k = c_uint32(k)
l = []
for v in map(c_uint32, bytes_to_uint32s(data)):
tmp = v.value
k.value -= delta
# Reverse bytes
k.value = int.from_bytes(k.value.to_bytes(4, 'big'), 'little')
v.value -= k.value
v.value ^= s.value
s.value = tmp
l.append(v.value)
return uint32s_to_bytes(l)
def decode_final_sn(sn):
MAGIC_KEY = [0x937ED889, 0x8E9BA899, 0x78E1C09E, 0xC9A87D8E]
# TEA-like decrypt
def process_block(a, b):
delta = 0x61C88647
# 0XC6EF3720 is `s`'s final value in encryption
s = c_uint32(0XC6EF3720)
a = c_uint32(a)
b = c_uint32(b)
for _ in range(32):
b.value -= (s.value ^ (a.value >> 5)) + \
MAGIC_KEY[3] + (MAGIC_KEY[2] ^ a.value) + (a.value << 4)
a.value -= (s.value ^ (b.value >> 5)) + \
MAGIC_KEY[0] + (MAGIC_KEY[1] ^ b.value) + (b.value << 4)
s.value += delta
return a.value, b.value
# ####
t = uint32s_to_bytes(chain(
*map(lambda ns: process_block(ns[0], ns[1]), grouper(2, bytes_to_uint32s(sn)))))
return t
def decode_mid_sn(sn):
sn = list(sn)
def f(a): return ((a - sn[-1]) & 0xFF) ^ sn[-2]
k = chain(map(f, sn[:22]), sn[-2:])
return k
def sn2str(sn):
def to_hex(it): return bytes(it).hex().upper()
s = str.join('-', map(to_hex, grouper(4, sn)))
return s
if __name__ == "__main__":
username = '52pojie.cn'
data = decode_data(TARGET_DATA)
final_sn = extract_sn_from_data(username, data)
mid_sn = decode_final_sn(final_sn)
sn = decode_mid_sn(mid_sn)
print(sn2str(sn))
|