历时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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)