- 下载下来 拉入32位IDA查看主函数的伪代码。
- 看到了似曾相识的IsDebuggerPresent函数。
BOOL WINAPI IsDebuggerPresent( void );
这个函数的用途就是用来检查程序是否在ring 3调试器中运行,该函数位于Kernel32.dll中。
如果当前进程在调试器上下文中运行,则返回值为非零。
如果当前进程不在调试器上下文中运行,则返回值为零。
根据主函数, 先是一个if语句, 如果sub_40102A()函数或者IsDebuggerPresent()函数返回 Ture,则退出程序。
进入sub_40102A()函数,发现这个函数无论如何都会返回0,也就是假。
搜了一番如何绕过IsDebuggerPresent()函数检测。
用OD载入定位到IsDebuggerPresent()函数。
- 查看其调用树,在每次调用上都设断点。
- 运行,然后发现程序断在这个位置。
- 第一次先不做任何操作, 来单步看看有什么跳转么。
- 依次单步, 发现这个je跳转, 跳转已实现, 会跳过第一个messageBosA来到第二个MessageBoxA。
- 但是第二个MessageBoxA会弹出一堆乱码, 并且下方就有Heapfree来释放堆了, 再往后就没有MessageBoxA函数了,并且再走几步就会Exit退出。
- 而根据IDA的静态分析, flag应该是通过MessageBoxA函数弹出的。 所以判断这个je跳转应该不让它实现跳转才对。
- 所以直接最简单的方法, nop掉那个je跳转,或者je改为jne, 然后再次单步, 发现程序到了这个int3中断的地方就会退出程序。
- 但至于为什么这个int3中断会导致程序退出, 还没找到合适的解释。但既然它会导致退出,无奈只能nop掉它, 然后接着单步。
- 又是一个跳转, 发现这个跳转会直接跳转到Exit的位置, 所以不能让它跳转,直接nop掉。
- 这时候call了一个MessageBoxA函数,弹出了一个窗口,但是里面没有内容,这仨按钮随便选一个就行, 然后又是一个跳转。
既然第一个MessageBoxA没有弹出真正的flag个,那只能寄希望于第二个了, 而这个跳转会跳到堆释放的位置,然后结束,所以不能让它实现跳转,依然是nop掉它。
接着单步,得到flag。