第一阶段◇第三题 答案
分析流程及修改方法
点按钮,出错,下MessageBox断点拦截提示位置,分析上下文:
00418F52 /$ 55 push ebp
00418F53 |. 8BEC mov ebp, esp
00418F55 |. 83EC 20 sub esp, 20
00418F58 |. 53 push ebx
00418F59 |. 56 push esi
00418F5A |. 57 push edi
....中间略
00419101 |. FF75 FC push dword ptr [ebp-4]
00419104 |. FFD0 call eax ; 这里弹出错误对话框
00419106 |. EB 02 jmp short 0041910A
经分析,这段函数的目的就是把一些API入口位置指针加密存放起来,需要用的时候再解密之并调用。
由此,这段函数无什么用处,目的就是弹出错误,因此我们观察堆栈,分析更上一层调用,位置在:
004122E4 |> \68 10200100 push 12010
004122E9 |. 68 C8454200 push 004245C8 ; microsoft visual c++ runtime library
004122EE |. 55 push ebp
004122EF |. E8 5E6C0000 call 00418F52 ;弹出错误提示
004122F4 |. 83C4 0C add esp, 0C
我们分析这段函数的上下文,如下:
00412192 /$ 51 push ecx
00412193 |. 53 push ebx
00412194 |. 8B5C24 0C mov ebx, dword ptr [esp+C]
00412198 |. 56 push esi
00412199 |. 57 push edi
0041219A |. 33F6 xor esi, esi
....中间略
004122E4 |> \68 10200100 push 12010
004122E9 |. 68 C8454200 push 004245C8 ; microsoft visual c++ runtime library
004122EE |. 55 push ebp
004122EF |. E8 5E6C0000 call 00418F52 ; 这里弹出错误提示
004122F4 |. 83C4 0C add esp, 0C
这段函数虽然看起来比较高深,判断众多、函数也多,且最下面有写控制台操作,但本函数纯属忽悠人,观其本质,除了显示错误以外,没有别的大用。
因此我们观察更上数层调用,一直到:
00413E00 |. 56 |push esi
00413E01 |. 50 |push eax
00413E02 |. FF35 C8A04200 |push dword ptr [42A0C8] //加密函数入口地址
00413E08 |. E8 3FEFFFFF |call 00412D4C //解密参数指针,返回需要被调用的函数
00413E0D |. 59 |pop ecx
00413E0E FFD0 call eax //这里会调用上面述说的内容
目前焦点就放在了:
00413E0E call eax
我们把这个函数nop掉,点Crash按钮,这时候没有错误了,但出来一个提示:
---------------------------
TestFloag
---------------------------
PI * 2 =
---------------------------
确定
---------------------------
很明显,作者要求我们算出来这个结果。
分析上下文发现2点:
1、00413E0E call eax 这句代码应该会被执行;
2、
00413E0E call eax 这个函数里面除了产生非法操作,别的没什么用处;
据此看来,这个程序的最终流程就是肯定要执行一个非法操作。
这时候如何办呢?
观察 call eax 这里eax数据来源自:
00413E02 push dword ptr [42A0C8]
也就是 [42A0C8] 里面存放的函数入口地址,但被加密了。
静态搜索一下 [42A0C8] 这个内存位置的引用,发现:
00411DFD |. C705 C8A04200>mov dword ptr [42A0C8], 00418D69 ; 入口地址
这个地方,看起来往里面存入的函数指针为 00418D69。
重新开程序,断在:
00413E0E call eax
手工修改eax = 00418D69。 F9运行,正确结果出现:
---------------------------
TestFloag
---------------------------
PI * 2 = 6.283180
---------------------------
确定
---------------------------
整理思路,发现原因在于必须要执行:
00411DFD mov dword ptr [42A0C8], 00418D69
查找这句代码的相关引用,最终定位到:
0040F621 |. 68 5C404200 push 0042405C
0040F626 |. E8 65670000 call 00415D90 //进行校验
0040F62B |. 85C0 test eax, eax
0040F62D |. 59 pop ecx
0040F62E 74 0B je short 0040F63B ; 跳,则不会运行那句话
0040F630 |. FF7424 04 push dword ptr [esp+4]
0040F634 |. FF15 5C404200 call dword ptr [42405C] ; 填写正确的函数指针到加密位置
这样以来,我们需要观察 call 00415D90 里面,何时可以让 eax != 0。
进入分析一下,发现关键位置在这里:
00415DF5 . 8B40 24 mov eax, dword ptr [eax+24] //获取文件头一处偏移内容
00415DF8 . C1E8 1F shr eax, 1F
00415DFB . F7D0 not eax
00415DFD 83E0 01 and eax, 1
这个地方,读取得实际是文件头偏移0x22C位置的Dword进行运算,原本为 0xC0000040,经运算结果为0,导致不会运行我们那句话。
所以把这个地方修改为 0x40000040,便可以达到目的。
附件为修改后的程序。
初次参赛,参与为主,不太懂发答案格式和规则,见谅。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)