测试文件:https://adworld.xctf.org.cn/media/task/attachments/c6cf449ae4b7498eba5027c533386a40.exe
1.准备
获取信息:
- 32位文件
2.IDA打开
反汇编main函数
1 void sub_401100()
2 {
3 signed int v0; // esi
4 signed int v1; // esi
5 unsigned int v2; // edi
6 void **v3; // ebx
7 void **v4; // eax
8 int v5; // ecx
9 int v6; // ST04_4
10 int v7; // ST08_4
11 int v8; // ST0C_4
12 int v9; // eax
13 int v10; // ST0C_4
14 char *v11; // esi
15 int v12; // ecx
16 void **v13; // eax
17 int v14; // eax
18 int v15; // ST0C_4
19 int v16; // eax
20 int v17; // ST0C_4
21 int v18; // eax
22 int v19; // ST0C_4
23 int v20; // eax
24 int v21; // ST0C_4
25 int v22; // eax
26 int v23; // ST0C_4
27 int v24; // eax
28 int v25; // ST0C_4
29 int v26; // eax
30 int v27; // ST0C_4
31 int v28; // eax
32 int v29; // [esp-4h] [ebp-13Ch]
33 int Dst; // [esp+14h] [ebp-124h]
34 char v31[4]; // [esp+20h] [ebp-118h]
35 char v32; // [esp+24h] [ebp-114h]
36 int v33; // [esp+5Ch] [ebp-DCh]
37 char v34; // [esp+61h] [ebp-D7h]
38 int v35; // [esp+64h] [ebp-D4h]
39 int v36; // [esp+68h] [ebp-D0h]
40 char v37; // [esp+6Ch] [ebp-CCh]
41 FILE *File; // [esp+70h] [ebp-C8h]
42 char v39; // [esp+84h] [ebp-B4h]
43 void *v40; // [esp+CCh] [ebp-6Ch]
44 int v41; // [esp+DCh] [ebp-5Ch]
45 unsigned int v42; // [esp+E0h] [ebp-58h]
46 void *v43; // [esp+E4h] [ebp-54h]
47 unsigned int v44; // [esp+F4h] [ebp-44h]
48 unsigned int v45; // [esp+F8h] [ebp-40h]
49 void *Memory[4]; // [esp+FCh] [ebp-3Ch]
50 unsigned int v47; // [esp+10Ch] [ebp-2Ch]
51 unsigned int v48; // [esp+110h] [ebp-28h]
52 __int128 v49; // [esp+114h] [ebp-24h]
53 __int16 v50; // [esp+124h] [ebp-14h]
54 char v51; // [esp+126h] [ebp-12h]
55 int v52; // [esp+134h] [ebp-4h]
56
57 v45 = 15;
58 v44 = 0;
59 LOBYTE(v43) = 0;
60 v52 = 0;
61 v42 = 15;
62 v41 = 0;
63 LOBYTE(v40) = 0;
64 LOBYTE(v52) = 1;
65 v0 = 0;
66 v47 = 'dime';
67 LOWORD(v48) = 'a';
68 *(_OWORD *)Memory = xmmword_40528C; // htadimehtadimeht
69 v50 = '.<';
70 v51 = 0;
71 v49 = xmmword_4052A4; // <<<....++++---->
72 do
73 {
74 sub_4021E0(&v40, 1u, (*((_BYTE *)Memory + v0) ^ *((_BYTE *)&v49 + v0)) + 22);
75 ++v0;
76 }
77 while ( v0 < 18 );
78 v1 = 0;
79 v48 = 15;
80 v47 = 0;
81 LOBYTE(Memory[0]) = 0;
82 LOBYTE(v52) = 2;
83 v2 = v42;
84 v3 = (void **)v40;
85 do
86 {
87 v4 = &v40;
88 if ( v2 >= 0x10 )
89 v4 = v3;
90 sub_4021E0(Memory, 1u, *((_BYTE *)v4 + v1++) + 9);
91 }
92 while ( v1 < 18 );
93 memset(&Dst, 0, 0xB8u);
94 sub_401620(v5, v6, v7, v8);
95 LOBYTE(v52) = 3;
96 if ( v31[*(_DWORD *)(Dst + 4)] & 6 )
97 {
98 v9 = sub_402A00(std::cerr, "?W?h?a?t h?a?p?p?e?n?", sub_402C50);
99 std::basic_ostream<char,std::char_traits<char>>::operator<<(v9, v10);
100 exit(-1);
101 }
102 sub_402E90(&Dst, &v43);
103 v11 = &v32;
104 if ( File )
105 {
106 if ( !(unsigned __int8)sub_4022F0(&v32) )
107 v11 = 0;
108 if ( fclose(File) )
109 v11 = 0;
110 }
111 else
112 {
113 v11 = 0;
114 }
115 v37 = 0;
116 v34 = 0;
117 std::basic_streambuf<char,std::char_traits<char>>::_Init(&v32);
118 v35 = dword_408590;
119 File = 0;
120 v36 = dword_408594;
121 v33 = 0;
122 if ( !v11 )
123 std::basic_ios<char,std::char_traits<char>>::setstate((char *)&Dst + *(_DWORD *)(Dst + 4), 2, 0);
124 v13 = Memory;
125 if ( v48 >= 0x10 )
126 v13 = (void **)Memory[0];
127 if ( sub_4020C0(&v43, v12, v44, (int)v13, v47) )
128 {
129 v28 = sub_402A00(std::cout, "=W=r=o=n=g=K=e=y=", sub_402C50);
130 }
131 else
132 {
133 v14 = sub_402A00(std::cout, "|------------------------------|", sub_402C50);
134 std::basic_ostream<char,std::char_traits<char>>::operator<<(v14, v15);
135 v16 = sub_402A00(std::cout, "|==============================|", sub_402C50);
136 std::basic_ostream<char,std::char_traits<char>>::operator<<(v16, v17);
137 v18 = sub_402A00(std::cout, "|==============================|", sub_402C50);
138 std::basic_ostream<char,std::char_traits<char>>::operator<<(v18, v19);
139 v20 = sub_402A00(std::cout, "|==============================|", sub_402C50);
140 std::basic_ostream<char,std::char_traits<char>>::operator<<(v20, v21);
141 v22 = sub_402A00(std::cout, "\\ /\\ /\\ /\\ /\\==============|", sub_402C50);
142 std::basic_ostream<char,std::char_traits<char>>::operator<<(v22, v23);
143 v24 = sub_402A00(std::cout, " \\/ \\/ \\/ \\/ \\=============|", sub_402C50);
144 std::basic_ostream<char,std::char_traits<char>>::operator<<(v24, v25);
145 v26 = sub_402A00(std::cout, " |-------------|", sub_402C50);
146 std::basic_ostream<char,std::char_traits<char>>::operator<<(v26, v27);
147 std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_402C50);
148 v28 = sub_402A00(std::cout, "Congrats You got it!", sub_402C50);
149 }
150 std::basic_ostream<char,std::char_traits<char>>::operator<<(v28, v29);
151 sub_401570(&v39);
152 std::basic_ios<char,std::char_traits<char>>::~basic_ios<char,std::char_traits<char>>(&v39);
153 if ( v48 >= 0x10 )
154 sub_402630(Memory[0], v48 + 1);
155 if ( v2 >= 0x10 )
156 sub_402630(v3, v2 + 1);
157 if ( v45 >= 0x10 )
158 sub_402630(v43, v45 + 1);
159 }
知识兔
第74行调用sub_4021E0函数的最后一个参数生成了一个字符传入。连起来生成字符串
#include <iostream>
#define _BYTE unsigned char
using namespace std;
int main()
{
const char* Memory = "themidathemidathemid";
const char* v50 = ">----++++....<<<<.";
signed int v0 = 0;
char str;
do {
str = (*(Memory + v0) ^ *(v50 + v0)) + 22;
cout << str;
++v0;
} while (v0 < 18);
system("PAUSE");
return 0;
}
知识兔
`[^VZe`uYaY]`s^joY
3.OD打开
程序打开输出是这样
使用OD打开之后,定位到字符串处,发现前面有条指令是可以跳过这段字符串输出的
00211233 . 8B40 04 mov eax,dword ptr ds:[eax+0x4]
00211236 . F68405 E8FEFF>test byte ptr ss:[ebp+eax-0x118],0x6
0021123E 74 25 je Xkey.00211265
00211240 . 8B0D C8502100 mov ecx,dword ptr ds:[<&MSVCP140.std::ce>; MSVCP140.std::cerr
00211246 . BA E4522100 mov edx,key.002152E4 ; ASCII "?W?h?a?t h?a?p?p?e?n?"
0021124B . 68 502C2100 push key.00212C50
00211250 . E8 AB170000 call key.00212A00
00211255 . 8BC8 mov ecx,eax
00211257 . FF15 98502100 call dword ptr ds:[<&MSVCP140.std::basic>; MSVCP140.std::basic_ostream<wchar_t,std::char_traits<wchar_t> >::operator<<
0021125D . 6A FF push -0x1 ; /status = FFFFFFFF (-1.)
0021125F . FF15 68512100 call dword ptr ds:[<&api-ms-win-crt-runt>; \exit
知识兔
因此我们可以判断出,这段字符串就是个烟雾弹,让我们不能进入真正的程序的,而真正的key就在下面。
4.代码分析
if ( v48 >= 0x10 )
v13 = (void **)Memory[0];
if ( sub_4020C0(&v43, v12, v44, (int)v13, v47) )
{
v28 = sub_402A00(std::cout, "=W=r=o=n=g=K=e=y=", sub_402C50);
}
else
{
...
知识兔
通过这段代码我们可以知道,sub_4020C0函数就藏着key,OD中找到对应的代码,设置断点
00211317 . FF75 D4 push dword ptr ss:[ebp-0x2C]
0021131A . 0F4345 C4 cmovnb eax,dword ptr ss:[ebp-0x3C]
0021131E . 50 push eax
0021131F . FF75 BC push dword ptr ss:[ebp-0x44]
00211322 . 51 push ecx
00211323 . 8D4D AC lea ecx,dword ptr ss:[ebp-0x54]
00211326 . E8 950D0000 call key.002120C0
知识兔
前面都是函数的参数,运行到断点处
在寄存器处,我们找到了我们需要的key
5.get flag!
idg_cni~bjbfi|gsxb