测试文件: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
#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>::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