算法分析:XCTF 4th-WHCTF-2017
(编辑:jimmy 日期: 2024/12/26 浏览:3 次 )
算法分析:XCTF 4th-WHCTF-2017
1.下载附件是一个32位无壳console的exe,运行一遍发现基本逻辑就是提示输入一个字符串,输入以后通过一个判断来提示不同内容
image-20220309132114998.png
1
2.既然是exe,那先用OD跑一边
①查看是否有关键字符串
发现关键字符“Wrong!”,这个字符就在我们输入错误后提示的,可以看第一大步的图,双击找到这个字符串的引用(如下图)
image-20220309132505801.png
2
②大概分析引用“Wrong!”的代码段
image-20220309133047232.png
3
发现跳转到输出“Wrong!”函数的jnz在00401341,跳转条件就是eax不等于1,那说明只要eax只要等于1则就不跳转,执行输出“Right!flag is your input”,那现在我们需要做的就是逆推EAX的来源(如上图)
③逆推EAX的来源
00401337 |. 8B4424 08 mov eax,dword ptr ss:[esp+0x8] ; kernel32.BaseThreadInitThunk0040133B |. 83C4 08 add esp,0x80040133E |. 83F8 01 cmp eax,0x100401341 |. 75 07 jnz short 1c40a4a4.0040134A 00401343 |. 68 90A04000 push 1c40a4a4.0040A090 ; Right!flag is your input\n00401348 |. EB 05 jmp short 1c40a4a4.0040134F0040134A |> 68 C0A04000 push 1c40a4a4.0040A0C0 ; Wrong!\n0040134F |> E8 1C000000 call 1c40a4a4.00401370
阅读代码可以看到第一步跟踪到的eax是在00401337处被ss:[esp+0x8]赋值,那我们断点到00401337查看ss:[esp+0x8]的值,但是断点运行后居然没停下来而直接判断输出了“Wrong!”,(如下图)
image-20220309133848337.png
4
往上浏览代码,发现在004012D4出还有一个Wrong字符串和提示我们输入的信息,那说明这里有有一个初步的对我们输入的判断(如下图)
image-20220309134206340.png
5
004012A4 |. 68 D0A04000 push 1c40a4a4.0040A0D0 ; Please input flag:004012A9 |. E8 C2000000 call 1c40a4a4.00401370004012AE |. 8D4424 0C lea eax,dword ptr ss:[esp+0xC]004012B2 |. 50 push eax004012B3 |. 68 C8A04000 push 1c40a4a4.0040A0C8 ; %31s004012B8 |. E8 7A010000 call 1c40a4a4.00401437004012BD |. 8D7C24 14 lea edi,dword ptr ss:[esp+0x14]004012C1 |. 83C9 FF or ecx,0xFFFFFFFF004012C4 |. 33C0 xor eax,eax004012C6 |. 83C4 0C add esp,0xC004012C9 |. F2:AE repne scas byte ptr es:[edi]004012CB |. F7D1 not ecx004012CD |. 49 dec ecx004012CE |. 5F pop edi004012CF |. 83F9 13 cmp ecx,0x13004012D2 |. 74 1D je short 1c40a4a4.004012F1004012D4 |. 68 C0A04000 push 1c40a4a4.0040A0C0 ; Wrong!\n004012D9 |. E8 92000000 call 1c40a4a4.00401370004012DE |. 68 B8A04000 push 1c40a4a4.0040A0B8 ; pause004012E3 |. E8 B9000000 call 1c40a4a4.004013A1
阅读上面代码可以知道要执行输出“Wrong!”则使得004012D2处不跳转,那我们的目的是要让他不执行,所以要使得ecx等于0x13(19),经过我对004012D2处断点测试得到这个0x13(19)就是要求输入的长度等于19
那我们继续往下走,发现004012D2处的跳转跳到了004012FA1(如下图)
image-20220309134907327.png
6
那我们断点来到这个004012D2函数(记得输入19个字符)(如下图)
跳转成功以后执行了CreatfeFileA函数,第一个参数便是文件名“Your_input”,那我们执行完CreateFileA后exe就会在它所在目录创建一个叫作Your_input的文件(如果文件在则不创建),最后CreatfeFileA函数返回Your_input文件句柄值,返回的值放在eax中(通常函数返回值都是存在eax中,这里就是)
image-20220309141751019.png
7
继续往下走(如下图)
程序继续执行WriteFile函数,第一个函数便是待写入文件的文件的句柄值(hfile),第二个函数便是待写入的数据存储地址(Buffer),第三个便是要写入的字节数(nBytesToWrite ),那就可以知道exe是想把0019FF14处的内容写19个字节到刚才生成的Your_input文件中,查看0019FF14地址便可以看到写入的字符就是我们输入的19个字符
image-20220309141448868.png
8
image-20220309142842863.png
9
那我们先执行完WriteFile函数去看看是否存在Your_input文件并且写入成功了(如下图)
image-20220309143216877.png
10
打开Your_input文件以后发现里面的内容根本就不是我们写入的1234567890123456789啊,而是一些其他字符但是WriteFile写入的字符串就是1234567890123456789,所以WriteFile指定出现了问题,我们跟进WriteFile看下函数(如下图)
image-20220309143526185.png
11
跟进WriteFile内发现居然是个jmp!!!,那说明这个函数被做过手脚啊,通常这种写jmp的都是对这个函数进行了HOOK,所以,我们跳到00401080去看看到底发生了啥?(如下图)
image-20220309143820697.png
12
果然是对WriteFile函数进行了HOOK,在执行了401000、401140函数后才执行了
WriteFile函数,那决定最终写入Your_input文件的字符串重点就是在这两个函数了,所以我们就跟进401000、401140两个函数进行分析,此时为了方便分析我们采用IDA来分析
拖进IDA pro 直接按G跳转到401000(如下图)
image-20220309180546210.png
13
401000函数代码
int __cdecl sub_401000(int a1, int a2){ char i; // al char v3; // bl char v4; // cl int v5; // eax for ( i = 0; i < a2; ++i ) { if ( i == 18 ) { *(_BYTE *)(a1 + 18) ^= 0x13u; } else { if ( i % 2 ) v3 = *(_BYTE *)(i + a1) - i; else v3 = *(_BYTE *)(i + a1 + 2); *(_BYTE *)(i + a1) = i ^ v3; } } v4 = 0; if ( a2 <= 0 ) return 1; v5 = 0; while ( byte_40A030[v5] == *(_BYTE *)(v5 + a1) ) { v5 = ++v4; if ( v4 >= a2 ) return 1; } return 0;}