0xgame_week4_somewp

吐槽

强网被冲烂了,一堆破事,0xweek4没打完,阿西,继续努力

Reverse

绯想天则

unity逆向基于mono,分析dll

winflag被搬了,rsa加密

第二段对应公钥,第三段对应私钥

解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding
import base64

# 您提供的数据
private_key_xml = """<RSAKeyValue>
<Modulus>jR+j5ZyLvbOyQRZgJQtHl5slRSQ4igoTQrKrwnmIwOcrkc48RQ6qD6wFXYAbFmiu34YpO638surG2dFemO0+vSoJuFksK70amen3pdilSgUukdFZ3SEJ/7QoeWls40exLsVPn3zWclN5b1ESaL4TN0MpC9lJUuWqkwiYSU2fZYQg9Z7S05RcVtl0JgK9O/DmLjW6+t6RdUAyo+9gsPXdGNOd/f4LyOTbj0iaWg2aCGfZhz3UtqACS2q6L9p1a9L3vYgLNpp1GnUcZnA+CVfhzcCWTHQ4X7hTuJsyysFEm/6tei3uBKYq6/HnTrmo2rSZxKS/GuExRO3A9hmyD+PEcw==</Modulus>
<Exponent>AQAB</Exponent>
<P>+6YUEMyFZlINlnZYRznRU0qU2Krb4QaFCUnNhFsL37y55rnz0/hLfLSA2FistQiMLy0Yz01fkxOTtwwkWkHikRu7KFi7vQzTg/KbdKNnHJ11huemk0DuwxDghj+3uNC30heSA6NFlF47zlge8AY2J+iQ8JpgJNsrfZYNRZ5txD0=</P>
<Q>j5BSrK3Li9VaBvRn2UGMf8q2N0J7tbaRvQonHhU1uBQYlhifttmK5wr1PurZHsb7tiNIv0RluM9HaUbQ/CczqLskVKJNkwpVyGM2rydiqbZ/KaP00ytTiR7Hxd0GUC06Syfi2h1VwaEewAOTkRUo/DuKYugPSaiyqARipyhfRm8=</Q>
<DP>0lwCagiNevscYKqNIP0z/mxaAMTTCUhp7VnEct+pDV62CClpqcflUlmRW0jFFpAOn2ETXDdRraCv2lRMDycEPkjwKsoCJgaSyboEOXxetYzqsdrzZCTjciypg4/ABL506yrI5EGX6G7dj6AaPIr0umeuwXJK7IRJ1rGYZpoJKAE=</DP>
<DQ>HA4BCfughj/4KtnCHYOguCxd9WiJklYOHtoIEOnmKIXM1DAVrf7PFR1gFZ6BNXF/KPW2NqJgGoBvHRSYrF3gy31euSdKb4yafOFeg1X4AuBF81Y19rpFxcr9ER6DKFHeTWeK/kKzSnZ48t8ADF8NNlVQUsm0ixlraEgLG01ZaQM=</DQ>
<InverseQ>qZwSExM5GW+CsTtvN2DPmwQtLf7cTA2DwY+8+4bnR7X0MTqssUDNtc8l+HD3uml9BRg9m4t1PoY+qGsh5qEtFsITBvt0pqNM5mdg8WrB1e85Xzpdvsfqvv1PN3KsDjduzkY0SazVBlur+OX86JTF3jSLFeFkornO1ckHcApqU54=</InverseQ>
<D>LABbh/IhmAp5X9XsMGCt99VF76L1hgTSMI+pAkAGpa7uZM3a+OUznSNToO2ahIgrTkJ0hMkg62BMlAm15xTB5RVAZpxXK2QQ8UCEGM/N6aBn/ss5q7rrdTDlFcYLT2pBEoYu51lzO75PNKggh0wMjcSA/dLIC/LUFngtk12Cf5IRwsdn0Kc2aoiiHU0NtvWklLZGkzcs4VL5FI7n1yDeIS9I+lKA14dJUCEhAltfMMiTSq+vpzoSedOcc8V0v9O9mjef8W62DasLusKxCCQi6PzsLA7ul2yLuOWTi1oysnrUVZryOWTvMr2V3GC0wfGRdXajd6qwwKVvGUt72egeEQ==</D>
</RSAKeyValue>"""

cipher_text_base64 = "TxDTykBFS+ewdHSIKSRRw63i4/7Os3pHqvC/WOnnFPKupfz0VpUqFRVEgtOdfJLdcxNKBvc67E/nIqU4dz8L88DZB9xVaKawdDgJ8c3EhI//r1aZkzbN2hURFdsS1UoF932XT9wPW61TsXPX7UyFAG4IInifxQr6KU7hyQNHIkpBkYsTgp/wxH5/g6IKEff8H/zEjbLcalck5k/r3vG8DeBQkhZUQ4I5HfIyetUBAmZyr8sZkygErKxVaF6vWZZtoPBkLzCxY0WIoaYcTfp+n5q1dUBDOshvXhVf1M3KGokZL2PqXT9K9Gv91d8aazXq7MV1iqCN4AwWAeFPn8OIYg=="

def decrypt_rsa_xml(private_key_xml, cipher_text_base64):
# 解析 XML(简单方式:提取 Base64 内容)
from xml.etree import ElementTree as ET
root = ET.fromstring(private_key_xml)

def b64decode_tag(tag_name):
tag = root.find(tag_name)
if tag is not None:
return base64.b64decode(tag.text)
return None

modulus = b64decode_tag('Modulus')
exponent = b64decode_tag('Exponent')
p = b64decode_tag('P')
q = b64decode_tag('Q')
dp = b64decode_tag('DP')
dq = b64decode_tag('DQ')
inverse_q = b64decode_tag('InverseQ')
d = b64decode_tag('D')

# 将字节转换为整数(大端格式)
def bytes_to_int(b):
return int.from_bytes(b, 'big')

n = bytes_to_int(modulus)
e = bytes_to_int(exponent)
d = bytes_to_int(d)
p = bytes_to_int(p)
q = bytes_to_int(q)
dp = bytes_to_int(dp)
dq = bytes_to_int(dq)
iq = bytes_to_int(inverse_q)

# 构造 RSA 私钥
private_key = rsa.RSAPrivateNumbers(
p=p,
q=q,
d=d,
dmp1=dp,
dmq1=dq,
iqmp=iq,
public_numbers=rsa.RSAPublicNumbers(e=e, n=n)
).private_key()

# 解密
cipher_data = base64.b64decode(cipher_text_base64)
plain_data = private_key.decrypt(
cipher_data,
padding.PKCS1v15() # 对应 C# 的 fOAEP: false
)

return plain_data.decode('utf-8')

# 执行解密
try:
plaintext = decrypt_rsa_xml(private_key_xml, cipher_text_base64)
print("解密成功!")
print("明文:", plaintext)
except Exception as ex:
print("解密失败:", str(ex))
# 0xGame{TenshiSamaSaiko_IWANNATENSHIFUMO_INESBATTLE}

镜渊折枝

apk,解包后aes加密,native层的compare方法

对密文做了个处理

iv在secret.bin,frida跑下提取相关内容,注意hook时机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Java.perform(function(){
function bytesToHex(bytes) {
if (bytes === null || bytes.length === 0) return "(null)";
let hex = '';
for (let i = 0; i < bytes.length; i++) {
let b = bytes[i] & 0xff;
hex += ('0' + b.toString(16)).slice(-2);
}
return hex;
};
console.log("hook 开始!");
let FlagChecker = Java.use("com.example.easynative.FlagChecker");
console.log("[+] 成功找到 FlagChecker 类!");
FlagChecker["encrypt"].implementation = function (plainText, key, iv) {
console.log("========================================");
console.log("[+] encrypt 被调用!");
console.log(` plainText: ${plainText}`);
console.log(` key (hex): ${bytesToHex(key)}`);
console.log(` iv (hex) : ${bytesToHex(iv)}`);
let result = this["encrypt"](plainText, key, iv);
console.log(` result (hex): ${bytesToHex(result)}`);
console.log("========================================");
return result;
};
});

// ========================================
// [+] encrypt 被调用!
// plainText: 0xgame{114514}
// key (hex): 307867616d652d5365637265744b6579
// iv (hex) : 8aa5610c74411b11a35368de56bf6ab3
// result (hex): 38ebb85938fe0ae0422fdd0a3729
// ========================================

注意CTR模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from Crypto.Cipher import AES
import binascii

# enc = [0x38, 0xEA, 0x9A, 0x5A, 0x3C, 0xFB, 0xC, 0x98, 0x1A, 0x66,
# 0x8B, 0x46, 0x6A, 0x6, 0x19, 0x8, 0x41, 0xCB, 0x36, 0x9E,
# 0x16, 0xC5, 0xBE, 0x2F, 0xF0, 0x9D, 0xBF, 0xA7, 0x34, 0x67,
# 0x51, 0x4C, 0xE5, 0xC2, 0x78, 0xA5, 0xF, 0x35, 0xFC, 0x1D,
# 0x39, 0x8B, 0x49, 0x38, 0x34, 0x69, 0x30, 0xF7, 0x0, 0x0]
#
# for i in range(len(enc)):
# enc[i]^=i
# print(f'{enc[i]:02x}',end='')
# # print(enc)

key_hex = '307867616d652d5365637265744b6579'
iv_hex = '8aa5610c74411b11a35368de56bf6ab3'
enc_hex = '38eb985938fe0a9f126f814d660b170751da248d02d0a838e884a5bc287a4f53c5e35a862b10da3a11a2631318441ed83031'

# 转为字节
key = binascii.unhexlify(key_hex)
iv = binascii.unhexlify(iv_hex)
ciphertext = binascii.unhexlify(enc_hex)

# 创建 AES CTR 解密器
cipher = AES.new(key, AES.MODE_CTR, nonce=iv[:8], initial_value=iv[8:])

# 解密
plaintext = cipher.decrypt(ciphertext)

# 输出结果
print("🔑 Key (ASCII):", key.decode('utf-8', errors='ignore'))
print("🔐 IV (Hex):", iv_hex)
print("🔒 Ciphertext (Hex):", enc_hex)
print("🔓 Plaintext (UTF-8):", plaintext.decode('utf-8', errors='replace'))
# 0xGame{Native_1s_also_1nt3r3st1ng_ef492d80a257c}

花鸟风月

调试定位入口点去花

标准 jz/jnz + E8

第一次漏了一些地方,主要是第一个加密处理导致解密没成功

sub 8

call $+5

分析加密

patch v11推断前面为key处理

解密

key,跑挺久的,移位异或导致非线性了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from z3 import *
def rol(x,n):
# 确保移位在0-31范围内
# n&=31
return (x<<n) | LShR(x,32-n) #LShR是Z3中的逻辑右移(无符号右移)

solver=Solver()
key=BitVec('key',32)
v11=BitVec(0x81428113,32)

shifts=[(i*13)%32 for i in range(10)]
# print(shifts)
# [0, 13, 26, 7, 20, 1, 14, 27, 8, 21]

for i in range(10):
v11=(0x1421043*v11+0x43298815) & 0xFFFFFFFF
key_tmp=rol(key,shifts[i])
v11^=key_tmp

solver.add(v11==0xa745da5d)

if solver.check() == sat:
model = solver.model()
key_value=model[key].as_long & 0xffffffff
print(f'key_hex: {key_value:08x}')
else:
print('无解')
# key(hex): 98BF3B77

b64有改动,第二个与第三个换位了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import base64
enc='MAPDc3GtPQ34vM3pNBb1PWGxccHtvxH1NVa9JPTtacS57IilN5uxJSW5Iwm='
key=0x98BF3B77
e1=list(enc)
for i in range(0,len(enc),4):
e1[i+1],e1[i+2]=e1[i+2],e1[i+1]
string=''.join(e1)
e2=base64.b64decode(string)
e2=bytearray(e2)
for i in range(44):
key_tmp=(key>>(8*(i%4))) & 0xFF
e2[i]^=((key_tmp>>4) | (key_tmp<<4)) & 0xFF
e2[i]^=key_tmp
print(chr(e2[i]),end='')
#0xGame{e8778581-e94f-48d5-943e-69ff46f54d1f}

0xgame_week4_somewp
https://alenirving.github.io/2025/10/31/0xgame_week4_somewp/
作者
Ma5k
许可协议
CC-BY-NC-SA