2024 春秋杯冬季赛 DAY1 RE wp

前言:打比赛的时候还是考虑的不够细致 vm的wp官方发了

ezre

ida打开附件 进入主函数 发现有一个md5的反调试 打个硬件断点过掉

Patr1ck wp-12

起调试dump下来随机数

Patr1ck wp-13

1
   0x3a, 0x1a, 0x2b, 0x1f, 0x6e, 0x0, 0x32, 0x45, 0x52, 0x44, 0x22, 0x55, 0x3a, 0x37, 0x7d, 0x43, 0x7b, 0x23, 0x52, 0x1c, 0x60, 0x46, 0xa, 0x7, 0x56, 0x38, 0x72, 0x79, 0x10, 0x1d, 0x52, 0x4a, 0x2f, 0x75, 0x61, 0x16, 0x75, 0x14, 0x5c, 0x41, 0x58, 0x76

程序主要逻辑

Patr1ck wp-14

Patr1ck wp-15

密文

Patr1ck wp-16

写脚本解密即可

1
2
3
4
5
6
7
8
9
10
11
enc=[  0x5C, 0x76, 0x4A, 0x78, 0x15, 0x62, 0x05, 0x7C, 0x6B, 0x21,  
0x40, 0x66, 0x5B, 0x1A, 0x48, 0x7A, 0x1E, 0x46, 0x7F, 0x28,
0x02, 0x75, 0x68, 0x2A, 0x34, 0x0C, 0x4B, 0x1D, 0x3D, 0x2E,
0x6B, 0x7A, 0x17, 0x45, 0x07, 0x75, 0x47, 0x27, 0x39, 0x78,
0x61, 0x0B]
key=[0x3a, 0x1a, 0x2b, 0x1f, 0x6e, 0x0, 0x32, 0x45, 0x52, 0x44, 0x22, 0x55, 0x3a, 0x37, 0x7d, 0x43, 0x7b, 0x23, 0x52, 0x1c, 0x60, 0x46, 0xa, 0x7, 0x56, 0x38, 0x72, 0x79, 0x10, 0x1d, 0x52, 0x4a, 0x2f, 0x75, 0x61, 0x16, 0x75, 0x14, 0x5c, 0x41, 0x58, 0x76]
flag=[]
for i in range(len(enc)):
flag.append(enc[i]^key[i])
print(chr(flag[i]),end='')
#flag{b799eb3a-59ee-4b3b-b49d-39080fc23e99}

ko0h

ida打开附件 发现逻辑是base64换码表 解出来是fakeflag 查看左边函数发现TLS0_0 跟进 有很多常规花指令 从上到下去除 这里我不全部贴出来了 好多花

Patr1ck wp-17

随后开始分析TLS0_0

Patr1ck wp-24

第一个函数是检测调试器的函数 如果有ida64 od x32dbg等字样则有调试 跟进下面的函数

Patr1ck wp-25

发现进行了魔改的RC4加密
密文

Patr1ck wp-27

写了个脚本还是没出 猜测key有问题 交叉引用发现key被替换了

Patr1ck wp-26

写解密脚本求出flag

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
def ksa(key):  
S = list(range(256))
j = 0
key_length = len(key)
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i]
return S
def prga(S, length):
i = j = 0
keystream = []
for _ in range(length):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
keystream.append(S[(S[i] + S[j]) % 256])
return keystream
def rc4(key, plaintext):
S = ksa(key)
keystream = prga(S, len(plaintext))
return bytes([(p + k) % 256 for p, k in zip(plaintext, keystream)])
key = b"DDDDAAAASSSS"
ciphertext = [0x18, 0x9C, 0x47, 0x3D, 0x3B, 0xE1, 0x29, 0x27, 0x9F, 0x34, 0x83, 0xD5, 0xED, 0xB5,0x6E, 0x59, 0x7F, 0xDE, 0x47, 0xD7, 0x65, 0x3F, 0x7A, 0x33, 0x5B, 0x64, 0xB6, 0xFA, 0x94, 0x55, 0x87, 0x42, 0x20, 0x6, 0xC, 0x69, 0xFE, 0x72, 0xA9, 0xE4, 0xD1, 0x7C]
decrypted = rc4(key, ciphertext)
print(decrypted)
#b'flag{c58868f2-a62a-584b-b1f4-91b9348a9a22}'

ezgo

ida打开附件 跟进main_main
输入为4位

Patr1ck wp-33

首先进行了一个base64

Patr1ck wp-28

Patr1ck wp-29

跟进可以发现最后对密文^0xC

Patr1ck wp-30

码表也进行了变换 在main_init_0中

Patr1ck wp-35

这里我用赛博厨子测试了一下 输入四位的情况下 输出都是8位 最后两位是== 所以想解开密文 只需要求出前六位即可
随后对密码的几位进行异或

Patr1ck wp-31

最后通过输入的密码解压压缩包

Patr1ck wp-32

直接写z3 这里当时比赛的时候我约束条件没有考虑周全 导致z3的解出现了错误 我只考虑了用zip的头去跟给定的zip文件头加约束 没考虑到别的条件 还是在赛后学习别的师傅的wp时候发现了错误 至少需要五个约束才可求出正确的password 解出来的值 对应的下标异或回去 在异或0xC 最后base64换表即可

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
80
81
82
83
84
85
86
from z3 import *  

zip_flag = [0x0E, 0xE1, 0xE5, 0xF9, 0x14]
zip_head = [0x50, 0x4b, 0x03, 0x04, 0x0C]
enc = [0x01, 0x57, 0x2C, 0x7C, 0xC7, 0x72, 0x20, 0x70, 0xA5, 0x96, 0x21,
0xDC, 0xA8, 0x76, 0x69, 0x14, 0xC5, 0x24, 0x25, 0x02, 0xB7, 0x7A,
0xFC, 0xF0, 0xC4, 0x49, 0x56, 0xC2, 0xC1, 0x95, 0xEC, 0x26, 0xCC,
0xF7, 0xFF, 0x73, 0xE1, 0x3F, 0x84, 0x46, 0xA9, 0xF9, 0x3D, 0x0E,
0x45, 0xF1, 0xDA, 0x92, 0xCE, 0x3B, 0x3C, 0xA0, 0x16, 0xBC, 0x2D,
0xBD, 0xA4, 0x32, 0x90, 0x62, 0x9D, 0x0C, 0xDE, 0xAD, 0x40, 0xCF,
0x4B, 0x4D, 0x6E, 0x79, 0xC8, 0x85, 0xD2, 0xAC, 0x99, 0xE8, 0x1E,
0xC9, 0xD4, 0x06, 0x34, 0x66, 0xB8, 0xD3, 0x13, 0xF4, 0x42, 0x1B,
0x63, 0x5F, 0x82, 0x5B, 0x91, 0x2A, 0x33, 0x5D, 0xB9, 0x7D, 0xD5,
0x6C, 0x0D, 0x28, 0x08, 0x9B, 0x18, 0x2E, 0xA2, 0x67, 0x5A, 0xE6,
0x8A, 0x19, 0x50, 0x9C, 0xB1, 0xEF, 0x1F, 0x12, 0xBA, 0x86, 0x83,
0x77, 0x60, 0x94, 0xFD, 0xF6, 0x54, 0xBF, 0xA1, 0x93, 0x03, 0xE7,
0x58, 0xE5, 0x9A, 0x7F, 0x22, 0xBE, 0xD9, 0x38, 0x27, 0x65, 0xD7,
0x23, 0xFB, 0x71, 0xFA, 0x8F, 0xF5, 0x6D, 0x51, 0x9E, 0xD6, 0x8B,
0x89, 0x11, 0xCA, 0x0F, 0x8E, 0xCB, 0xB3, 0xBB, 0xF2, 0x87, 0x75,
0x5C, 0x2F, 0x98, 0x2B, 0x1C, 0xB4, 0xC6, 0x0A, 0x4C, 0x36, 0x1A,
0x15, 0x88, 0x1D, 0xE4, 0xC3, 0x97, 0x53, 0x30, 0x4A, 0x3A, 0xB5,
0x61, 0x55, 0xC0, 0xA7, 0xDB, 0x29, 0x68, 0xE2, 0xE0, 0x10, 0x09,
0x41, 0x31, 0xF3, 0xAF, 0xB6, 0x6A, 0x6F, 0x00, 0x05, 0x0B, 0xE3,
0xD1, 0x8D, 0x47, 0x74, 0x78, 0x7B, 0x64, 0xDD, 0xAB, 0xB0, 0x39,
0x37, 0xFE, 0xED, 0x52, 0xCD, 0x81, 0xF8, 0xAA, 0x48, 0x6B, 0xD0,
0xEB, 0x8C, 0x44, 0x59, 0x17, 0x9F, 0x4F, 0xB2, 0x35, 0xA3, 0x7E,
0xEE, 0x4E, 0xDF, 0xE9, 0x07, 0x43, 0xA6, 0xAE, 0xD8, 0xEA, 0x80,
0x3E, 0x04, 0x5E]
s = Solver()
pass1, pass2, pass3, pass4, pass5, pass6 = BitVecs("pass1 pass2 pass3 pass4 pass5 pass6", 8)
enc_byte = Array('Bytes', BitVecSort(8), BitVecSort(8))
for i in range(len(enc)):
s.add(enc_byte[BitVecVal(i, 8)] == enc[i])

s.add(zip_flag[0] == zip_head[0] ^ pass1 ^ pass5 ^ enc_byte[pass1])
s.add(zip_flag[1] == zip_head[1] ^ pass2 ^ pass6 ^ enc_byte[pass2])
s.add(zip_flag[2] == zip_head[2] ^ pass3 ^ pass5 ^ enc_byte[pass3])
s.add(zip_flag[3] == zip_head[3] ^ pass4 ^ pass6 ^ enc_byte[pass4])
s.add(zip_flag[4] == zip_head[4] ^ pass5 ^ pass5 ^ enc_byte[pass5])

s.add(0xB6 == 0x50 ^ pass3 ^ pass5 ^ enc_byte[pass3])
s.add(0xB6 == 0x4B ^ pass4 ^ pass6 ^ enc_byte[pass4])
s.add(0x1D == 0x05 ^ pass5 ^ pass5 ^ enc_byte[pass5])
s.add(0x9F == 0x06 ^ pass6 ^ pass6 ^ enc_byte[pass6])

s.add((pass1 ^ 2) >= 32)
s.add((pass1 ^ 2) <= 126)
s.add(pass2 >= 32)
s.add((pass2) <= 126)
s.add((pass3 ^ 2) >= 32)
s.add((pass3 ^ 2) <= 126)
s.add((pass4 ^ 5) >= 32)
s.add((pass4 ^ 5) <= 126)
s.add((pass5 ^ 5) >= 32)
s.add((pass5 ^ 5) <= 126)
s.add((pass6 ^ 2) >= 32)
s.add((pass6 ^ 2) <= 126)

for password in [pass1, pass2, pass3, pass4, pass5, pass6]:
s.add(password >= 32)
s.add(password <= 126)

if s.check() == sat:
m = s.model()
# 提取并输出结果
keys = [m[pass1].as_long(), m[pass2].as_long(), m[pass3].as_long(),
m[pass4].as_long(), m[pass5].as_long(), m[pass6].as_long()]
print(', '.join(map(str, keys)))

password = [108, 62, 65, 98, 104, 74]
password[0]^=2
password[2]^=2
password[3]^=5
password[4]^=5
password[5]^=2
for i in range(6):
print(chr(password[i] ^ 0xC), end='')
print()
import base64
import string
string = 'b2OkaD=='
tableBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tableNew = "TSRQPONMLKJIHGFEDCBAUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
password = base64.b64decode(string.translate(str.maketrans(tableNew, tableBase64)))
print (password)
#b'oadi'

得到密码 输入进去就能打开zip压缩包 打开txt文件就有flag

Patr1ck wp-34