Pinguw
Articles10
Tags3
Categories2

Categories

Archive

MRCTF2020 VirtualTree(花指令+动态调试)

MRCTF2020 VirtualTree(花指令+动态调试)

[MRCTF2020]VirtualTree(花指令+动态调试)

32位无壳,放进IDA里,main函数很清晰,

Untitled

试着恢复一下符号表:

Untitled

看一下key的调用,找到更改key值的函数,

Untitled

结合题目,可以看出这是一个二叉树,搞一个结构体:

Untitled

回头看第一个加密函数:

Untitled

就是把key中的数据根input一个一个异或,比较简单,

把input搞成0,动调可以搞到key的数据

Untitled

1
key = "MLGPOKFCJENIHDBA"

再分析enc2:,有花指令,比较容易去掉:

Untitled

去掉后里面的加密函数是这样:

Untitled

逆向这个函数解密后发现根本解不出来,动调一下试试:

动调后发现这些函数全被更改了,汇编是这样的:

Untitled

call的那些函数是对input执行了一些简单的更改。

Untitled

Untitled

Untitled

汇编:

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
87
88
89
90
.text:004216F0 push    ebp
.text:004216F1 mov ebp, esp
.text:004216F3 push 0Ah
.text:004216F5 push 0
.text:004216F7 mov eax, offset func_add
.text:004216FC call eax ; loc_421510 //input[0] += 10
.text:004216FC
.text:004216FE add esp, 8
.text:00421701 push 2
.text:00421703 push 1
.text:00421705 mov eax, offset func_xor
.text:0042170A call eax ; loc_421510 //input[1] ^= input[2]
.text:0042170A
.text:0042170C add esp, 8
.text:0042170F push 7
.text:00421711 push 2
.text:00421713 mov eax, offset func_add
.text:00421718 call eax ; loc_421510 //input[2] += 7
.text:00421718
.text:0042171A add esp, 8
.text:0042171D push 7
.text:0042171F push 3
.text:00421721 mov eax, offset func_sub
.text:00421726 call eax ; loc_421510 //input[3] = abs(input[3] - input[7])
.text:00421726
.text:00421728 add esp, 8
.text:0042172B push 5
.text:0042172D push 4
.text:0042172F mov eax, offset func_xor
.text:00421734 call eax ; loc_421510 //input[4] ^= input[5]
.text:00421734
.text:00421736 add esp, 8
.text:00421739 push 1
.text:0042173B push 6
.text:0042173D mov eax, offset func_sub
.text:00421742 call eax ; loc_421510 //input[6] = abs(input[6] - input[1])
.text:00421742
.text:00421744 add esp, 8
.text:00421747 push 3
.text:00421749 push 7
.text:0042174B mov eax, offset func_add
.text:00421750 call eax ; loc_421510 //input[7] += 3
.text:00421750
.text:00421752 add esp, 8
.text:00421755 push 7
.text:00421757 push 8
.text:00421759 mov eax, offset func_xor
.text:0042175E call eax ; loc_421510 //input[8] ^= input[7]
.text:0042175E
.text:00421760 add esp, 8
.text:00421763 push 8
.text:00421765 push 9
.text:00421767 mov eax, offset func_sub
.text:0042176C call eax ; loc_421510 //input[9] = abs(input[9] - input[8])
.text:0042176C
.text:0042176E add esp, 8
.text:00421771 push 7
.text:00421773 push 0Ah
.text:00421775 mov eax, offset func_sub
.text:0042177A call eax ; loc_421510 //input[10] = abs(input[10] - input[7])
.text:0042177A
.text:0042177C add esp, 8
.text:0042177F push 0Ch
.text:00421781 push 0Bh
.text:00421783 mov eax, offset func_xor
.text:00421788 call eax ; loc_421510 //input[11] ^= input[12]
.text:00421788
.text:0042178A add esp, 8
.text:0042178D push 2
.text:0042178F push 0Ch
.text:00421791 mov eax, offset func_sub
.text:00421796 call eax ; loc_421510 //input[12] = abs(input[12] - input[2])
.text:00421796
.text:00421798 add esp, 8
.text:0042179B push 0Fh
.text:0042179D push 0Eh
.text:0042179F mov eax, offset func_xor
.text:004217A4 call eax ; loc_421510 //input[14] ^= input[15]
.text:004217A4
.text:004217A6 add esp, 8
.text:004217A9 push 2
.text:004217AB push 0Fh
.text:004217AD mov eax, offset func_add
.text:004217B2 call eax ; loc_421510 //input[15] += 2
.text:004217B2
.text:004217B4 add esp, 8
.text:004217B7 nop
.text:004217B8 nop
.text:004217B9 pop ebp
.text:004217BA retn

写解密代码:

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
input = [0x17, 0x63, 0x77, 0x03, 0x52, 0x2E, 0x4A, 0x28, 0x52, 0x1B, 0x17, 0x12, 0x3A, 0x0A, 0x6C, 0x62]

def add(a, b):
input[a] -= b

def xor(a, b):
input[a] ^= input[b]

def sub(a, b):
# maybe_input1.append(input[a] + input[b])
# maybe_input2.append(input[b] - input[a])
input[a] = abs(input[a] - input[b]) # 因为abs有两种可能性,全取这种可能得到的flag最正常

key = "MLGPOKFCJENIHDBA"
opcode = [1, 2, 1, 3, 2, 3, 1, 2, 3, 3, 2, 3, 2, 1] # 1表示加密中的add, 2表示xor, 3表示sub
a1 = [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 14, 15] # 第一个参数
a2 = [10, 2, 7, 7, 5, 1, 3, 7, 8, 7, 12, 2, 15, 2] # 第二个参数

for i in range(13, -1, -1):
if opcode[i] == 1:
add(a1[i], a2[i])
elif opcode[i] == 2:
xor(a1[i], a2[i])
elif opcode[i] == 3:
sub(a1[i], a2[i])

for i in range(16):
input[i] ^= ord(key[i])

for i in input:
print(chr(i), end = '')

得到flag:

Untitled

Untitled

MRCTF{@_7r3e_f0r_fuNN!}

Author:Pinguw
Link:https://pinguw.github.io/2024/04/10/Reverse/VirtualTree/
看完了吗,再去看看博主的其他文章叭:)