• 标 题:较完善的旧版Acprotect1.0x-1.2x脱壳脚本
  • 作 者:David
  • 时 间:2004-12-20,20:58
  • 链 接:http://bbs.pediy.com

历时7小时写成,要兼容各版本Ac,语言,处理方法,哎,累。

环境,Win2k/xp,UnkillOD,Flyod1.10,脚本器0.92,忽略除内存异常外的全部异常.

// Acprotect OEP or FOEP and Patch IAT  v0.3
// 作者: Mr.David
// 主页: www.chinadfcg.com

msg "请设置OD异常设置不忽略内存异常,其它全部忽略,然后从菜单处继续运行脚本"

pause

dbh  //隐藏调试器

var cbase

gmi eip, CODEBASE
mov cbase, $RESULT    
log cbase            //记录代码段基地址,一般是401000

var k
var imgbase

gmi eip,MODULEBASE      //模块基地址400000
mov imgbase,$RESULT
mov k,imgbase
add k,3C               //40003C
mov k,[k]
add k,imgbase         
add k,f8              //第一区段名
log k
add k,8              //地址加8字节的偏移就是区段大小      
mov k,[k]           //401000处第一区段大小
log k        

var addr1           //通用临时变量

var addr2
mov addr2,ebp      //保存ebp=12fff0判断后面是否到达OEP 或 FOEP

var addr3
sub ebp,30        //实际取ebp=12ffc0判断后面是否到达OEP 或 FOEP
mov addr3,ebp
add ebp,30      //修改了寄存器值得还原

var addr6      //Replace Code判断变量

Msg "请耐心等候IAT处理"

gpa "GlobalAlloc","kernel32.dll"
mov addr1,$RESULT                    //捷径 API断点GlobalAlloc
bp addr1
run
bc addr1    //Clear break point  //取消断点

gpa "GetProcAddress","kernel32.dll"
mov addr1,$RESULT                  //AC敏感捷径 API断点GetProcAddress
add addr1,5                       //GetProcAddress+5
bp addr1     

eoe end2      //Acprotect1.10 Build123之C语言篇的IAT处理在INT1中断前面,设置INT1陷阱             
esto

loop:                      //循环标记

Bc addr1
rtu                      //Alt+F9
cmp eip,70000000       //判断是否在系统领空

ja loop              //地址大于70000000则循环

find eip,#0BC0#     //查找特征指令 or eax,eax 以定位处理MessageBoxA的位置
                   //有些版本这里返回后还要bp GetProcAddress+5 中断一次后返回才处理IAT,如记事本                                                   
                
            
cmp eip,$RESULT  //如果当前返回指令是 or eax,eax 则需要继续中断处理

je BGPA  //跳到标签BGPA即是 Bp GetProcAddress 缩写

Back1:  //返回或正常流程

find eip,#750A#    //特征指令  
mov addr1,$RESULT 
repl addr1, #750A#, #EB??#,10      //有病治病,无病强身,处理MessageBoxA

find eip,#7F??#    //特征指令     //jg xxxxx 不确定调转路径用7F??,处理IAT
mov addr1,$RESULT 
repl addr1, #7F??#, #EB??#,10     //有病治病,无病强身  //这里结束处理IAT 是否加密


//下面开始分界,有些Acprotect有Replace Code,有些没有,给脚本编写加大难度,这里处理方法不同。

cmp addr6,1  //如果确认没有Replace Code,则直接跳到取OEP位置代码处
je label69

gpa "GlobalAlloc","kernel32.dll"
mov addr1,$RESULT                    //如果要寻找Replace Code处理位置就得继续下捷径 API断点GlobalAlloc
bp addr1

eoe end
run  //INT1陷阱,异常则去end处理

bpmc //内存不中断执行这里则清除内存断点。
bc addr1  //清除GlobalAlloc断点。
rtu

label32: //这里我们寻找Replace Code位置。

find eip,#8BF8#    //如果当前返回点代码就是mov edi,eax,则可确认就是Replace Code位置,否则循环。
cmp eip,$RESULT 
je label77       //如果发现mov edi,eax则跳出循环。

label66:
gpa "GlobalAlloc","kernel32.dll"
mov addr1,$RESULT                    //捷径 API断点GlobalAlloc
bp addr1
run
rtu
jmp label32

label77:

bc addr1

Msg "IAT已经修复,想狸猫换太子吗?请修改信息框处EAX值,处理完从菜单处继续运行!"
pause

label69:

bprm cbase, k //然后就是跳OEP或FOEP了,内存镜像断点

esto //Shift+F9


label444:  //这里我用一个条件判断OEP OR FOEP,有些AC壳到OEP或FOEP时候EBP一般是12fff0,或是12ffc0,401000处中断一般都是OEP。

cmp eip,401000           //汇编比较常用

je label333

cmp ebp,addr2         //12fff0一般没有抽代码 

je label333

cmp ebp,addr3       //12ffc0,抽代码常见

je label333

cmp ebp,12fff2    //12fff2,VB类

je label333

var addr4

add addr4,1

cmp addr4,70   //定义循环上限,如果Code段执行70行代码仍然无法发现OEP则认为死循环。

ja Sorry

esto

jmp label444  //循环直到条件成立,当然有些AC版本会跑飞。
   
label333:
        
Msg "IAT已经修复,FOEP请补上被盗字节"
cmt eip,"OEP Or Next Shell To Get,Please dumped it,Enjoy!"
bpmc
ret


BGPA:  //继续GetProcAddress+5中断

gpa "GetProcAddress","kernel32.dll"
mov addr1,$RESULT                    //捷径 API断点GetProcAddress+5
add addr1,5
bp addr1
run

bc addr1
rtu

jmp Back1


end:      //INT1

coe
bprm 401000, k //内存镜像断点     //意外情况,没有Replace Code的程序,这时要跳FOEP了,得拦住
bc addr1 //清除GlobalAlloc断点

jmp label444


Sorry:

Msg "估计脚本陷入死循环,提前结束。"
ret

end2:   //INT1

coe
mov addr6,1 //如果INT1在IAT处理以前,这些版本的AC一般没有Replace Code,赋标记1让他直接去内存镜像断点处。
esto

jmp loop