PESpin1.32学习笔记之Code Redirection的处理
引:百川东到海,何时复西归?少壮不努力,老大徒伤悲。(汉乐府《长歌行》)
本文章仅讲述Code Redirection的处理方法,故加壳选项如下:
加壳的对象,依然是98记事本。
OD载入后,F8单步2次后,即可使用ESP定律,然后再F8向下走,即可来到OEP!
来到OEP后,依然可以发现IAT的地址偏移了。
依旧使用UIF来进行处理
处理完后,dump,并用Imort REC来处理
处理完后,运行,出现错误提示,郁闷~
下面来看看具体是哪出现了问题吧。(为了比较,先别关闭原来那个调试的OD)
OD载入那个dump并修复后的程序,然后不忽略任何异常
接着F9运行,中断下来了。
晕,此处的代码怎么全是空代码?无语……
看堆栈,回朔回去看看吧
回朔回的地址是00401140.
CTRL+G,输入00401140,看下代码
汗,原来是0040113B处的那个CALL出问题了。
和加壳后的程序比对一下看看。
原OD中定位到0040113B
跟随进去这个CALL
继续跟随:
哈,现在终于明白了,原来,真实的代码是:
call 004020B3
修复后,保存。还是出现错误。继续同样处理。
可以看到,被重定位的代码形式为:
CALL型(E8)和JMP型(E9)
知道了原理,我们就在原来的那个程序里来进行处理吧。
二种类型的处理:
(1)CALL型的处理
CTRL+B,查找E8,(若发现无异常,就CTRL+L继续查找)
举例来看这个:
下面来找真实的CALL地址。
跟随进入这个CALL
其实,真正的调用地址已经很明显了,是004023DD。
为了更清楚的看到,继续跟随进入
看,这才是真正的起作用的代码呀。
把那个变形CALL的修正为 CALL 004023DD
这样就修复完毕了。其他的变形CALL,用同样的方法来进行处理!
(2)JMP型的处理
CTRL+B,查找E9(若发现无异常,就CTRL+L继续查找)
举例来看这个:
很明显,代码同样变形了。变形的字节为
E9 29 F0 FF FF 90 90,一共为7个字节。
那么,真实的代码是什么呢?
跟随进这个JMP吧
可以发现,真实的代码应该为cmp dword ptr ds:,0
数一下字节数,真好为7个,和刚才所数的个数一致!
很好,因此,把地址00401150处的真实代码修正为cmp dword ptr ds:,0
其他的变形代码用同样的方法进行处理~
原理都说完了,但是可以发现,被变形的代码实在太多,虽然,修复起来难度不大,但是,劳动量实在太大,是个体力活。
如果写个脚本来处理就好多了。
哈,我自己懒得写,况且能力有限,就直接套用别的大牛写的脚本。嘿嘿~
附上Code Redirection的修复脚本:
var begin
var end
var tmp
var dest
var code
var dest2
var count
mov begin, 400000 // lowest possible jmp/call destination
mov end, 40a000 // highest possible jmp/call destination
mov start, 401000 // start here to search for jmps/calls
__jmpstart:
mov count, 0 // clear safety counter
mov tmp, start // set starting point
__findjmp:
findop tmp, #e9# // find first jmp
mov tmp, $RESULT
cmp tmp, 0
je __goon // if script couldn't find it, go on
inc tmp // get the destination of the jmp
mov dest,
add dest, tmp
add dest, 4
cmp dest, begin // check if destination is in range
jbe __findjmp
cmp dest, end
jae __findjmp
findop dest, #e9# // check if destination has syntax
sub $RESULT, dest // ?? ?? ?? ?? ?? e9 ?? ?? ?? ?? (5 bytes stolen and jmp back)
cmp $RESULT, 5 // saying, distance to next jmp must be 5
jne __findjmp // if not go on searching
dec tmp // copy first stolen byte
mov al,
mov , al
inc tmp
inc dest
mov code, // copy last 4 stolen bytes, as dword
mov , code
inc count // increment safety counter (counts restored jmps)
jmp __findjmp // let the search go on
__goon:
cmp count, 0 // continue searching jmps as long as the counter is not 0
jne __jmpstart // (make sure all have been resolved, necessary!)
mov tmp, start // reset starting point
__findcall:
findop tmp, #e8# // search calls
mov tmp, $RESULT
cmp tmp, 0
je __end
inc tmp
mov dest,
add dest, tmp
add dest, 4
cmp dest, begin // check range of destination
jbe __findcall
cmp dest, end
jae __findcall
findop dest, #e9# // check if call points to a jmp, else it's no stolen code
cmp dest, $RESULT
jne __findcall
inc dest
mov dest2, dest
mov dest2, // save destination of jmp in dest2
add dest2, dest // subtract the offset from jmp
add dest2, 4
sub dest2, tmp // calculate offset from call
sub dest2, 4
dec tmp
mov , #e8# // let there be a call
inc tmp
mov , dest2 // save new offset to destination
add tmp, 4
jmp __findcall // the search goes on :)
__end:
ret // finished
OK,跑一下脚本后,所有的变形代码一般都能修复完毕了。
此时再dump,修复,发现,程序能正常运行了,哈
此保护的处理方法就这样,脱壳到此结束。
补充一下:
修复后的程序,虽然能正常运行,但是点退出后,可能会出现错误。(我机子上这样)
原因是还有个别几个变形代码没处理好。用上面说所的方法手动处理一下吧,反正也不多。处理后,就一切正常了。
脱壳总结:
Code Redirection这个保护方式处理起来比API Redirection的保护方式相对来说简单好多,但是这个保护,更加考验一个人的耐利,因为大部分工作是体力活,同时也体现了脚本的重要性!简单小结下脱壳的步骤:ESP定律来到OEP处,然后用UIF处理IAT,处理完后,跑下Code Redirection处理脚本,接着就dump和修复,脱壳完毕!
引:
学然后知不足,教然后知困。知不足,然后能自反也;知困,然后能自强也。
——孔丘(春秋时代思想家,教育家)引自《礼记。学记》
作者:ximo
[ 本帖最后由 ximo 于 2008-12-25 11:22 编辑 ] 谢谢教程:lol 谢谢,虽然看不懂但我会继续努力学习 (***)吖的 要么不发一发就这么多 让人喘口气行不 :L 今天还要不要过外国的啥节啊,一下发了四个全来看这个了哎~~~~ 太牛拉。只能佩服,:Q :Q
记号下。膜拜超大1 :) :) :) :) :) :) 真的牛了
学习下 又学到了一招~~~ 吾爱的原创帖子 就是强俺来学习啊