SMC 逆向分析

DebugMe

打开程序可以看到程序就只是弹出了一段对话:

1
2
I heard you like bugs so I put bugs in your debugger so you can have bugs while you debug!!!
Seriously though try and find the flag, you will find it in your debugger!!!

大致判断出是一个自解密,在调试过程中可以直接得到

字符串里看到有对应的字符串,但是没有交叉引用,同时也有对指针的加密解密过程,因此推断可能是一个SMC,对应的区段已经被加密过,在调试过程中进行还原。

拖入010查看节区数发现有14个节区,感觉有点不对劲,进行了一下简单调试发现似乎有反调试,直接程序无法开跑。

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
char mainCRTStartup_0()
{
int v0; // eax
unsigned __int64 v1; // rax
int v2; // ebx
unsigned __int64 v3; // rax
int (__cdecl *v4)(int, const char **, const char **); // eax

LOBYTE(v0) = NtCurrentPeb()->BeingDebugged; // 反调试?
if ( !(_BYTE)v0 )
{
LOBYTE(v0) = NtCurrentPeb()->NtGlobalFlag;
if ( !(_BYTE)v0 )
{
v1 = __rdtsc();
v2 = v1;
v3 = __rdtsc();
v0 = v3 - v2;
if ( v0 <= 1000 )
{
v4 = main;
do
{
*(_BYTE *)v4 ^= 0x5Cu;//因该是加密部分,同时也是解密
v4 = (int (__cdecl *)(int, const char **, const char **))((char *)v4 + 1);
}
while ( (int)v4 <= (int)sub_401791 );
mingw_app_type = 0;
__security_init_cookie();
LOBYTE(v0) = __tmainCRTStartup();
}
}
}
return v0;
}

在上面看到大致加密因该是采用了异或的方式进行的处理,讲字节码进行异或0x5C (92)

接下来就是找到对应加密的节区,节区长度,对其进行解密,可能要写idc脚本?(不会写😢)于是只能找到后到010进行手动修复。

后面发现可以自己解密,如果想要保持解密后的状态就要自己写解密脚本或者010手动修复了

通过不断的打断点判断哪里之前会遇到反调试,最终程序停在了这个函数处mainCRTStartup_0,也就是上面代码块的内容,其会对v0进行判断,看其是否为假,如果为真则证明触发反调试,其值被设置为了1,也就是常见的反调试判断eax是否为0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
; 10:   if ( !(_BYTE)v0 )
.text:0040890D mov dl, al
.text:0040890F cmp al, 0 ; al为1触发反调试
.text:00408911 jnz short loc_408992 ; 退出解密
.text:00408911
.text:00408913 jmp $+5
.text:00408913
.text:00408918 ; ---------------------------------------------------------------------------
.text:00408918 ; 12: LOBYTE(v0) = NtCurrentPeb()->NtGlobalFlag;
.text:00408918
.text:00408918 loc_408918: ; CODE XREF: _mainCRTStartup_0+F↑j
.text:00408918 xor eax, eax
.text:0040891A xor edx, edx
.text:0040891C mov eax, large fs:30h
.text:00408922 mov al, [eax+68h]
.text:00408925 ; 13: if ( !(_BYTE)v0 )
.text:00408925 mov dl, al
.text:00408927 cmp al, 0
.text:00408929 jnz short loc_408992 ; 退出解密

我们通过set ip进行绕过这个判断状态,进入到if函数内部,内部中仍然有一个if ( !(_BYTE)v0 )判断是否处于调试状态,仍然通过set ip进行绕过,进行解密完毕后就进入了如下函数

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
91
92
93
94
int __tmainCRTStartup()
{
void *v0; // esp
void *v1; // esp
int v2; // eax
_BYTE v4[84]; // [esp+10h] [ebp-78h] BYREF
int v5; // [esp+64h] [ebp-24h]
LONG *v6; // [esp+68h] [ebp-20h]
LONG Exchange; // [esp+6Ch] [ebp-1Ch]
LONG v8; // [esp+70h] [ebp-18h]
int v9; // [esp+74h] [ebp-14h]
BOOL v10; // [esp+78h] [ebp-10h]
void *i; // [esp+7Ch] [ebp-Ch]

v10 = 0;
memset(&v4[16], 0, 0x44u);
v0 = alloca(48);
v1 = alloca(48);
i = v4;
memset(v4, 204, 0x20u);
if ( mingw_app_type )
GetStartupInfoA((LPSTARTUPINFOA)&v4[16]); // 获取启动信息,来判断是否被调试
v8 = 0;
Exchange = *(_DWORD *)(NtCurrentTeb() + 4);
v9 = 0;
while ( 1 )
{
v8 = InterlockedCompareExchange(&__native_startup_lock, Exchange, 0);
if ( !v8 )
break;
if ( v8 == Exchange )
{
v9 = 1;
break;
}
Sleep(0x3E8u);
}
if ( __native_startup_state == 1 )
{
_amsg_exit(31);
}
else if ( __native_startup_state )
{
has_cctor = 1;
}
else
{
__native_startup_state = 1;
_initterm(&__crt_xc_end__, &__xi_z);
}
if ( __native_startup_state == 1 )
{
_initterm(&__crt_xc_start__, &__xc_z);
__native_startup_state = 2;
}
if ( !v9 )
{
v6 = &__native_startup_lock;
v5 = 0;
v5 = _InterlockedExchange(&__native_startup_lock, 0);
}
if ( __dyn_tls_init_callback )
__dyn_tls_init_callback(0, 2, 0);
_pei386_runtime_relocator(); // 解密
__mingw_oldexcpt_handler = (int)SetUnhandledExceptionFilter(_gnu_exception_handler);
__mingw_prepare_except_for_msvcr80_and_higher();
fpreset();
if ( mingw_app_type )
{
for ( i = __acmdln; *(char *)i > 32 || *(_BYTE *)i && v10; i = (char *)i + 1 )
{
if ( *(_BYTE *)i == 34 )
v10 = !v10;
}
while ( *(_BYTE *)i && *(char *)i <= 32 )
i = (char *)i + 1;
__mingw_winmain_hInstance = 0x400000;
__mingw_winmain_lpCmdLine = (int)i;
if ( (v4[60] & 1) != 0 )
v2 = *(unsigned __int16 *)&v4[64];
else
v2 = 10;
__mingw_winmain_nShowCmd = v2; // 调用控制台
}
duplicate_ppstrings(_bss_start__, &argv);
__main();
___initenv = envp;
mainret = main(_bss_start__, (const char **)argv, (const char **)envp);// 启动主程序
if ( !managedapp )
exit(mainret);
if ( !has_cctor )
_cexit();
return mainret;
}

此时进入主函数main可以看到大部分数据已经被修复好了

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
_main:                        ; CODE XREF: ___tmainCRTStartup+2C3↑p
.text:00401620 ; DATA XREF: _mainCRTStartup_0+6A↓o
.text:00401620 push ebp
.text:00401621 mov ebp, esp
.text:00401623 xor eax, eax
.text:00401625 xor edx, edx
.text:00401627 mov eax, large fs:30h
.text:0040162D mov al, [eax+2]
.text:00401630 mov dl, al
.text:00401632 cmp al, 0
.text:00401634 jnz short _d
.text:00401634
.text:00401636 jmp $+5
.text:00401636
.text:0040163B ; ---------------------------------------------------------------------------
.text:0040163B
.text:0040163B _G: ; CODE XREF: .text:00401636↑j
.text:0040163B xor eax, eax
.text:0040163D xor edx, edx
.text:0040163F mov eax, large fs:30h
.text:00401645 mov al, [eax+68h]
.text:00401648 mov dl, al
.text:0040164A cmp al, 0
.text:0040164C jnz short _d
.text:0040164C
.text:0040164E rdtsc
.text:00401650 mov ebx, eax
.text:00401652 push ecx
.text:00401653 pop ecx
.text:00401654 add edi, edi
.text:00401656 sub edi, edi
.text:00401658 push esi
.text:00401659 pop esi
.text:0040165A add ecx, ecx
.text:0040165C sub ecx, ecx
.text:0040165E push esi
.text:0040165F pop esi
.text:00401660 add edi, edi
.text:00401662 sub edi, edi
.text:00401664 push ecx
.text:00401665 pop ecx
.text:00401666 add ecx, ecx
.text:00401668 sub ecx, ecx
.text:0040166A add edi, edi
.text:0040166C sub edi, edi
.text:0040166E push esi
.text:0040166F pop esi
.text:00401670 rdtsc
.text:00401672 sub eax, ebx
.text:00401674 cmp eax, 3E8h
.text:00401679 jg short _d
.text:00401679
.text:0040167B jmp _n
.text:0040167B
.text:00401680 ; ---------------------------------------------------------------------------
.text:00401680
.text:00401680 _d: ; CODE XREF: .text:00401634↑j
.text:00401680 ; .text:0040164C↑j
.text:00401680 ; .text:00401679↑j
.text:00401680 push offset __data_start__ ; "Looks like your doing something naughty"...
.text:00401685 call _printf
.text:00401685
.text:0040168A add esp, 4
.text:00401690 mov esp, ebp
.text:00401692 pop ebp
.text:00401693 retn
.text:00401693
.text:00401694 ; ---------------------------------------------------------------------------
.text:00401694
.text:00401694 _n: ; CODE XREF: .text:0040167B↑j
.text:00401694 push offset m1 ; "I heard you like bugs so I put bugs in "...
.text:00401699 call _printf
.text:00401699
.text:0040169E add esp, 4
.text:004016A4 push offset m2 ; "Seriously though try and find the flag,"...
.text:004016A9 call _printf
.text:004016A9
.text:004016AE add esp, 4
.text:004016B4 xor eax, eax
.text:004016B6 mov eax, 6A253E2Dh
.text:004016BB push eax
.text:004016BC jmp $+5
.text:004016BC
.text:004016C1 ; ---------------------------------------------------------------------------
.text:004016C1
.text:004016C1 _lol: ; CODE XREF: .text:004016BC↑j
.text:004016C1 sub eax, 560C29FCh
.text:004016C6 push eax
.text:004016C7 jmp $+5
.text:004016C7
.text:004016CC ; ---------------------------------------------------------------------------
.text:004016CC
.text:004016CC _yaya: ; CODE XREF: .text:004016C7↑j
.text:004016CC and eax, 41414141h
.text:004016D1 and eax, 3E3E3E3Eh
.text:004016D6 mov eax, 6A253E2Dh
.text:004016DB sub eax, 49FD1BF4h
.text:004016E0 push eax
.text:004016E1 jmp $+5
.text:004016E1
.text:004016E6 ; ---------------------------------------------------------------------------
.text:004016E6
.text:004016E6 _lala: ; CODE XREF: .text:004016E1↑j
.text:004016E6 xor eax, eax
.text:004016E8 mov eax, 6A253E2Dh
.text:004016ED sub eax, 2B1124FFh
.text:004016F2 push eax
.text:004016F3 jmp $+5
.text:004016F3
.text:004016F8 ; ---------------------------------------------------------------------------
.text:004016F8
.text:004016F8 _dsfghtgf: ; CODE XREF: .text:004016F3↑j
.text:004016F8 and eax, 41414141h
.text:004016FD and eax, 3E3E3E3Eh
.text:00401702 mov eax, 6A253E2Dh
.text:00401707 sub eax, 5E190004h
.text:0040170C push eax
.text:0040170D jmp $+5
.text:0040170D
.text:00401712 ; ---------------------------------------------------------------------------
.text:00401712
.text:00401712 _ertrwe: ; CODE XREF: .text:0040170D↑j
.text:00401712 and eax, 41414141h
.text:00401717 and eax, 3E3E3E3Eh
.text:0040171C mov eax, 6A253E2Dh
.text:00401721 add eax, 0DE9D64Dh
.text:00401726 push eax
.text:00401727 jmp $+5
.text:00401727
.text:0040172C ; ---------------------------------------------------------------------------
.text:0040172C
.text:0040172C _kjnjk: ; CODE XREF: .text:00401727↑j
.text:0040172C xor eax, eax
.text:0040172E mov eax, 6A253E2Dh
.text:00401733 sub eax, 2B003419h
.text:00401738 push eax
.text:00401739 jmp $+5
.text:00401739
.text:0040173E ; ---------------------------------------------------------------------------
.text:0040173E
.text:0040173E _qsacb: ; CODE XREF: .text:00401739↑j
.text:0040173E and eax, 41414141h
.text:00401743 and eax, 3E3E3E3Eh
.text:00401748 mov eax, 6A253E2Dh
.text:0040174D sub eax, 3E001C06h
.text:00401752 push eax
.text:00401753 jmp $+5
.text:00401753
.text:00401758 ; ---------------------------------------------------------------------------
.text:00401758
.text:00401758 _tftrtftc: ; CODE XREF: .text:00401753↑j
.text:00401758 and eax, 41414141h
.text:0040175D and eax, 3E3E3E3Eh
.text:00401762 mov eax, 6A253E2Dh
.text:00401767 sub eax, 42AA050Eh
.text:0040176C push eax
.text:0040176D jmp $+5
.text:0040176D
.text:00401772 ; ---------------------------------------------------------------------------
.text:00401772
.text:00401772 _sup: ; CODE XREF: .text:0040176D↑j
.text:00401772 push esp
.text:00401773 pop esi
.text:00401774 xor edx, edx
.text:00401776 mov edi, esi
.text:00401778 mov edx, edi
.text:0040177A cld
.text:0040177B mov ecx, 24h ; '$'
.text:00401780 mov ebx, 4Bh ; 'K'
.text:00401785 xor eax, eax
.text:00401787 push eax
.text:00401787
.text:00401788
.text:00401788 _l: ; CODE XREF: .text:0040178C↓j
.text:00401788 lodsb
.text:00401789 xor eax, ebx
.text:0040178B stosb
.text:0040178C loop _l
.text:0040178C
.text:0040178E mov esp, ebp
.text:00401790 pop ebp
.text:00401790
.text:00401791

试图生成一下函数,按一下P进行生成

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned __int64 v3; // rax
int v4; // ebx
unsigned __int64 v5; // rax
char *v7; // esi
_BYTE *v8; // edi
int v9; // ecx
char v10; // al
_DWORD v11[9]; // [esp-24h] [ebp-24h] BYREF

if ( NtCurrentPeb()->BeingDebugged )
return printf("Looks like your doing something naughty. Stop it!!!\n");
if ( LOBYTE(NtCurrentPeb()->NtGlobalFlag) )
return printf("Looks like your doing something naughty. Stop it!!!\n");
v3 = __rdtsc();
v4 = v3;
v5 = __rdtsc();
if ( (int)v5 - v4 > 1000 )
return printf("Looks like your doing something naughty. Stop it!!!\n");
printf("I heard you like bugs so I put bugs in your debugger so you can have bugs while you debug!!!\n");
printf("Seriously though try and find the flag, you will find it in your debugger!!!\n");
v11[8] = 1780825645;
v11[7] = 337187889;
v11[6] = 539501113;
v11[5] = 1058281774;
v11[4] = 202128937;
v11[3] = 2014254202;
v11[2] = 1059392020;
v11[1] = 740631079;
v11[0] = 662386975;
v7 = (char *)v11;
v8 = v11;
v9 = 36;
do
{
v10 = *v7++;
*v8++ = v10 ^ 0x4B;
--v9;
}
while ( v9 );
return sub_401791(0, v11);
}

可以很清楚的看到程序执行的过程了,对其进行分析即可!

主要的加密过程还是异或,其实可以直接自己计算的,但是异或具有对称性,我们直接借助调试器进行解密即可

需要注意的是程序在里面还是有反调试,会弹出对应的语句注意绕过即可

1
Looks like your doing something naughty. Stop it!!!

最终可以得到FLAG

1
Tr0lling_Ant1_D3buGGeR_trickz_R_fun!

SMC 逆向分析
https://equinox-shame.github.io/2022/04/12/DebugMe/
作者
梓曰
发布于
2022年4月12日
许可协议