Monthly Archives: December 2017

yoda’s protector unpack

本文已发表在看雪论坛, 详情可见: https://bbs.pediy.com/thread-223371.htm yoda’s protector主要有两个需要注意的反调试保护:阻塞设备输入和枚举进程pid并终止调试器 文中分析的程序你可以点击此处下载: yoda_unpack.zip 阻塞设备输入 yoda 使用user32.dll中的BlockInput来屏蔽所有的输入设备的消息,比如鼠标键盘。当设备被屏蔽时你无法进行任何操作,只有阻塞设备的线程或进程可以使用相同的API填入不同的参数来解锁它 yoda protector会在使用api阻塞设备后转向脱壳/解密的进程并执行一些反调试的技巧,在脱壳结束并且所有检查通过时,yoda才会解锁设备。 一个非常简单的方法可以解除阻塞,那就是patch掉BlockInput,让它什么都不做就返回。 当我们用od载入unpackme,我们可以看到内存中只载入了两个dll 为了patch掉BlockInput,我们需要让user32.dll载入内存,在od选项中我们设置断在新的dll上 然后我们继续F9,让user32.dll导入到内存 随后我们就可以取消掉之前断在新dll的选项,然后跳到BlockInput的入口代码处 BlockInput的api就是上图的灰色代码,retn 4就是结尾,我们只需要将所有这些代码填充为nop就行 这样,api就不会进行任何操作,我们的输入设备也不会被阻塞 枚举进程并终止调试器 yoda使用CreateToolhelp32Snapshot来获取所有正在运行的进程,然后yoda会搜索启动unpackme的进程是否和unpackme自己的进程PID是否相同,如果不同,那么yoda就会终止掉该进程(如od)。如果我们像先前一样patch掉CreateToolhelp32Snapshot,程序则会产生句柄非法(Invalid_Handle)异常。这里有另外一种方式来绕过保护。yoda使用GetCurrentProcessId来获取PID,因此我们可以控制返回的PID的值来迷惑保护代码。 比如我们启动unpackme的进程是Ollydbg.exe,我们就要让GetCurrentProcessId返回Ollydbg.exe的PID,这样检查就不会出现问题(而不是unpackme的PID)。 首先我们必须知道ollydbg.exe的PID,这点我们可以启动LordPE来轻松获得 这里ollydbg.exe的PID是0x4B4,而unpackme的PID是0x1CC,我们要做的就是使得GetCurrentProcessId的返回结果是0x4B4 像之前一样,来到api的入口代码处 函数通过eax返回值,我们只需要修改eax即可 这样也就完成了。 在patch完后,还需要使用插件来隐藏Ollydbg(用HideOD等插件,避免IsDebuggerPresent的检查),之后的关键就是找OEP了。 OEP查找 oep的查找我们可以使用最后一次异常法来跟踪,按下shift+F9的最后一次异常,在堆栈窗口中出现的SE Handler,本例中是00413F50,我们跟踪进去,在00413F50设下断点,然后按下Shift+F9到达断点处。我们要记得开启HideDebugger或类似插件的反IsDebuggerPresent的选项,否则在使用最后一次异常法时会退出OD和unpackme并且无法再点击任务栏和图标。 然后在00413F79处的00404000就是我们的OEP了,dump出来修复IAT即可

Posted in unpack | Leave a comment

基于Objdump的反汇编器存在的限制

objdump总是会期望处理一个被gcc很好地编译生成的可执行文件,然而通常情况下的程序文件,有些可能就是直接由代码汇编,有些却使用了一些技巧来对抗反汇编。接下来就大致介绍一下objdump存在的一些缺陷 objdump过于依赖节区头(section headers) 一个ELF可执行文件”通常”包含正确的节区头。而对系统的程序加载器而言,有没有节区头根本无关紧要,关键是获取程序的程序头(program headers)。 故而,最常见的反汇编技巧就是丢弃/处理掉ELF文件的节区头,或是覆写掉,伪造大小等等。 一旦处理过后,objdump就会拒绝进行反汇编。 objdump不会跟踪执行流 不跟踪代码执行流,objdump可以很轻易地被玩弄,仅仅反汇编了少许行就停下。这意味着objdump无法识别函数,也无法识别误认作”数据”中的代码 另一种常见的技巧是插入垃圾指令并跳过这些指令以对齐执行流中的汇编代码。 例如:当一个指令跳转到下一条指令的中间,而objdump不会从跳转的目的地址进行汇编,而是从下一条指令继续反汇编,也就使得垃圾指令被”组合”成一条新的指令。 start: jmp label+1 label: DB 0x90 mov eax, 0xf001 对应的objdump反汇编代码如下 08048080 <start>: 8048080: e9 01 00 00 00 jmp 8048086 <label+0x1> 08048085 <label>: 8048085: 90 nop 8048086: b8 01 … Continue reading

Posted in reverse engnieering | Leave a comment