2021西湖论剑两道逆向题目WP

TacticalArmed

函数sub_401160反调试,通过清空Dr7寄存器反调试。直接nop掉调用反调试的地方即可bypass。

反调试部分

接下来main函数先申请一段执行内存,然后对内存进行修改,最后添加ret指令返回。

申请shellcode执行的内存

通过调试,查看这一块执行的指令内容

执行的shellcode内容

经过分析,发现这一块指令执行的处理流程正是tea加密算法,其中四个密钥地址是405000到40500C,dump下来是[0x7CE45630, 0x58334908, 0x66398867, 0xC35195B1]。魔数是2 ** 32 - 0x7E5A96D2 = 0x81a5692e。结合代码,轮数是33。由于加密一次之后,没有对dword ptr ds:[405748]置0,因此在解密的时候,后面的数据都要累加前面的最终值。
解密代码:

tea解密算法代码

运行结果:

运行得到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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from ctypes import *
import struct

def decrypt(v, k, num):
v0, v1 = c_uint32(v[0]), c_uint32(v[1])
delta = 0x81a5692e
k0, k1, k2, k3 = k[0], k[1], k[2], k[3]

total = c_uint32(delta * 33 * num)
for i in range(33):
v1.value -= ((v0.value<<4) + k2) ^ (v0.value + total.value) ^ ((v0.value>>5) + k3)
v0.value -= ((v1.value<<4) + k0) ^ (v1.value + total.value) ^ ((v1.value>>5) + k1)
total.value -= delta

return v0.value, v1.value


# test
if __name__ == "__main__":
# ```
# 422F1DED 1485E472 035578D5 BF6B80A2
# 97D77245 2DAE75D1 665FA963 292E6D74
# 9795FCC1 0BB5C8E9 FFFFFFFF 00000001
# ```
# 待加密的明文,两个32位整型,即64bit的明文数据
value = [0x422F1DED, 0x1485E472, 0x35578D5, 0xBF6B80A2, 0x97D77245, 0x2DAE75D1, 0x665FA963, 0x292E6D74, 0x9795FCC1, 0x0BB5C8E9]
# 四个key,每个是32bit,即密钥长度为128bit
key = [0x7CE45630, 0x58334908, 0x66398867, 0xC35195B1]
# print("Data is : ", hex(value[0]), hex(value[1]))
# res = encrypt(value, key)
# print("Encrypted data is : ", hex(res[0]), hex(res[1]))
flag = b'DASCTF{'
res = decrypt(value[0:2], key, 1)
flag += struct.pack('<I', res[0]) + struct.pack('<I', res[1])
res = decrypt(value[2:4], key, 2)
flag += struct.pack('<I', res[0]) + struct.pack('<I', res[1])
res = decrypt(value[4:6], key, 3)
flag += struct.pack('<I', res[0]) + struct.pack('<I', res[1])
res = decrypt(value[6:8], key, 4)
flag += struct.pack('<I', res[0]) + struct.pack('<I', res[1])
res = decrypt(value[8:10], key, 5)
flag += struct.pack('<I', res[0]) + struct.pack('<I', res[1])
flag += b'}'
print(flag)

ROR

查看程序发现是个编码表编码算法,通过编码表逆运算,数组下标转换为二进制格式,爆破偏移为0,再组合二进制数据转为字符

IDA截图

解题代码:

解题代码截图

运行结果:

运行得到flag

附代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def get_flag_bytes(nums):
num_bins = [bin(i)[2:].rjust(8, '0') for i in nums]
flag_num_b = [['0' for l in range(8)] for i in range(8)]
for i in range(8):
for l in range(8):
flag_num_b[l][i] = num_bins[i][l]
return bytes([int(''.join(flag_num_b[i]),2) for i in range(8)])


flag_num = [0, 181, 122, 206, 37, 108, 7, 223, 0, 251, 124, 38, 75, 62, 134, 154, 0, 255, 37, 144, 255, 28, 56, 176, 0, 231, 60, 121, 225, 144, 251, 30, 0, 204, 179, 51, 78, 145, 65, 222]

flag = b''

for i in range(5):
flag += get_flag_bytes(flag_num[8*i:(i+1)*8])

print(flag)

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!