吾爱破解培训第九课:短兵相接–深入浅出探讨脱壳细节(下)
程序的导入表,是静态可见的,包含了导入的dll名字,和他的导入函数
壳会在加壳的时候,把导入表这个结构给拿出来
然后自己加密,或者改变结构
壳改了以后,系统就找不到导入表了,也就无法给我们的程序填充所需要的函数地址。
加过壳的程序一定可以运行的。
所以填充过程被取代了,这个过程被在壳段完成。
脱壳的时候直接dump,软件导入表是不在的,iat所填充的函数地址是当前系统的地址,所以这个程序可能只能在脱壳的机器运行,换台机器就失败了。
解决这个问题,导入表,
IMREC
IAT的地址值=》生成一份导入表,然后让程序使用新的导入表,那么程序就可以跨系统,在各个机器上用。
编写OD脚本
OD插件: Script Functions
脚本的指令
sti 相当于f7
sto 相当于f8
bp 地址 下断点
run 相当于f9
MSG “文字” 弹出对话框
ret 结束
bphws esp,”r” 硬件断点
运用栈平衡找oep的手段
首先要执行一条压栈指令,来改变栈,然后等以后再次读入这个栈内容的时候,就说明有栈平衡的迹象,那么就很有可能是一个栈恢复
一般来说压缩壳只有有一次恢复,然后就到oep了,所以利用这个特性我们来找oep
IAT修复
CTRl+G搜索
FF15
FF25
数据窗口找IAT起始和终点,值有明显00000000分界
UPX脚本
mov iat_b,00432000 mov iat_e,00432554 ;iat_b=00432000
sti ;pushad bphws esp,"r" ;hr esp run sti sti sti ;到了jnz bp eip ; @LOOP: run cmp esp,eax jnz @LOOP sti sti sti
MSG "到OEP了"
@IAT_LOOP: mov iat,[iat_b] cmp iat,0 je @NEXT_LOOP
mov api,[iat+1] mov [iat_b],api ;重建iat
@NEXT_LOOP: add iat_b,4 cmp iat_b,iat_e jne @IAT_LOOP
MSG "OK IAT 修复已经完成" ret
;mov iat,[iat_b] ;意思就是把00432000内存里面值拿出来,而不是拿出来00432000 ;mov iat,iat_b ;iat_b = 00432000 ;iat = 00432000 ;mov iat,[iat_b] ;iat = 00960306
;0045775E 39C4 cmp esp,eax ;00457760 ^ 75 FA jnz short upx的大?0045775C
;UPX的壳段代码是差不多的,那么这个脚本就可以用来找这个upx版本所有加壳程序的OEP,而且不用管ASLR的问题
;00432554 00000000
|
实例破解
查壳
tElock壳
脱壳
二次内存镜象法
OD载入,按M打开内存窗口
找到.rdata,F2下断点,shift+F9运行
再次打开内存窗口,找到.text,F2下断点,shift+F9运行,即可到达OEP
tElock脱壳修复IAT脚本
bc bpmc bphwcall
GPI MAINBASE //获取mainbase(00400000) (.text) mov DOS_HEADER , $RESULT mov E_LFANEW , [DOS_HEADER + 3C] mov NT_HEADER , DOS_HEADER + E_LFANEW mov SEC_HEADER , NT_HEADER + F8
mov SEC_ADRESS , [SEC_HEADER + C] add SEC_ADRESS , DOS_HEADER mov Sec1_Addr , SEC_ADRESS //取地址 mov SEC_SIZE , [SEC_HEADER + 8] mov Sec1_Size , SEC_SIZE //取大小
add SEC_HEADER , 28 mov SEC_ADRESS , [SEC_HEADER + C] add SEC_ADRESS , DOS_HEADER mov Sec2_Addr , SEC_ADRESS mov SEC_SIZE , [SEC_HEADER + 8] mov Sec2_Size , SEC_SIZE
bprm Sec_Addr , Sec1_Size //内存断点 esto bprm Sec_Addr , Sec2_Size esto bprm Sec1_Addr , Sec1_Size esto bpmc mov OEP , eip msg "Reached OEP!" //到OEP
AskIATStart: //0047D024 IAT表起始 ask "Please Enter Start of IAT, In This DEMO : 0047D024" cmp $RESULT , 0 je AskIATStart mov IAT_START , $RESULT
AskIATStart: //0047D5FC IAT表结束 ask "Please Enter End of IAT, In This DEMO : 0047D5FC" cmp $RESULT , 0 je AskIATStart mov IAT_START , $RESULT
mov PTR_IAT , IAT_START Fix_IAT: mov ADR_IAT , [PTA_IAT] cmp ADR_IAT , 0 //判断是否为0 je Fix_Next gn ADR_IAT //判断是否需要修复 cmp $RESULT , 0 jne Fix_Next mov eip , ADR_IAT //把eip地址换为IAT地址 rtr sti mov [PTR_IAT] , eip Fix_Next add PTR_IAT , 4 cmp PTR_IAT , IAT_END ja Finish jmp Fix_IAT
Finish: mov eip , OEP msg "All Fixed" ret
|