上周五下了个碧之轨迹来玩,当然是破解过的,打开之后,经典的falcom开头,接下来居然是更经典的"健康游戏忠告",真是....
立马打开od,载入发现有壳,peid查看是yoda1.02,上网看一下相关的文章,貌似是反调试的壳,在od里面运行也确实是提示检测到调试器了
单步跟了一阵,发现却和网上的描述不同,虽然都是反调试...
打开peid的userdb.txt,里面查找一下yoda的特征码,发现居然从头到尾都是问号,看来这数据库将识别不到的都归为yoda了
去掉这特征码就什么都查不到了,没办法,硬着头皮脱吧
打开"收藏"已久的<<脱壳的艺术>>看了一遍,基本了解了一下
像IsDebuggerPresent这样的Sod已经灭掉了
但是CheckRemoteDebuggerPresent还有几个,ODAdvance有选项但是却不工作的,手动修改一下也过了
但是还是会被检测到调试器
在单步的时候我发现一个地方在对比字符串,就是api的函数
这壳干脆不用GetProcAddress,直接从dll文件映射里面找
来到对比成功的地方,下断,看一下取了什么函数出来
有VirtualProtect之类的,还有反调试相关的
重要的还有一个CloseHandle,我看其调用这个函数的时候参数很可以
上网查了一下,这函数也能反调试的,就是传一个无效的句柄,具体就上百度看吧
将这个函数搞掉,接下来就用内存断点法很快就来到oep了
将上面过程写成脚本,以后轻轻一点就能直达oep
然后就是修复输入表了,脱壳的流程虽然都懂,但是一直都不知道是什么回事
这次却不同了,imprec只找到了5个无效的指针,但是程序里面确实是用了很多的api
无奈继续跟踪,从oep开始
单步跟进了2个call,结果就来到了花指令
这花指令有意思,虽然跳来跳去,但是重要的代码就3个地方:
1)
算出api入口
mov eax,XXXXXXXX
mov eax,[eax+XXXXXXXX]
lea eax,[eax+XXXXXXXX]
然后将eax放到栈顶
最后一个retn XX,就来到了api的入口
这里XXXXXXXX就是一个立即数,eax可以是esp以外的7个寄存器
而且这些花指令全在同一区段中,对于每一次调用都会有这样一段代码
2)
处理返回地址
lea eax,[eax+1]
eax代表7个寄存器
这里增加的是返回的地址
有时api调用会在后面加一个垃圾字节,然后在花指令里面处理返回地址
3)
破坏堆栈
这个没什么特征,有时会在call之前多push一两次,然后花指令里面pop回来
对付这个花指令,有个一箭三雕的方法
从call开始,使用脚本的单步进入跟踪,条件就是eip在程序代码的外面则停下来
停下来的时候,eip就是api的地址
[esp]就是返回地址,对比一下就知道有没有垃圾字节
有的话就将垃圾字节变成nop
如果没有破坏堆栈的话,esp的值应该减少了4
如果没有减少,就将call前面的push去掉
如果前面没有push,就将call变成jmp
如果esp反而增加4,就将push去掉,同时将call变成jmp
这时候call前面肯定是有push的,就这几种情况了
获得api地址之后就找块空地放着,然后再找一块空地放jmp
然后原来的call就指向这个jmp
保存之后,打开imprec,手动输入自己填充的iat,修复
弄好这里,我感觉对输入表和iat终于有相当的理解了
其实到这里还不能运行,我用od载入修复之后的程序
发现入口居然还是在原来的地方
将od设在系统入口停下
跟了一下,发现在另一个地方保存着壳的入口
将其设0,然后就能来到oep了
(之后翻加密与解密的时候发现这叫tls,不管如何,这次是停在了oep)
看看运行如何,窗口出来了,然后立马就出错,还真是兴奋了一下
立刻接上od,发现实在一个叫做读档的导出函数里面出错的
还没见过exe也有导出函数
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课