标 题: 【原创】UPXLOCK1.01主程序的脱壳与优化
作 者: xukehang
目标:UPX LOCK v1.01
下载:http://www.hanzify.org/?Go=Show::List&ID=11188
工具:OllyDBG,Lordpe,FixRes,ImportREC v1.6F,PE Explorer 1.98,winhex
说明:我是只小菜鸟,参考了很多大侠的文章,特别是caocong大哥的
脱壳优化教程,在此向各位表示感谢!同时有疏漏错误的地方,
请大家指出来,共同学习!本文适合于新手,高手略过。
由于权限不够不能贴图片,所以将教程以及相关文件打包上传于下列
网址,需要的朋友请下载!
http://www.live-share.com/files/74361/__byxukehang.rar.html
1、用OD脱壳
设置OD调试选项,不忽略“int3中断异常”,其它全部打勾,并用插件IsDebuggerPresent 1.40隐藏OD,载入程序,“确定”略过入口点预警,
继续分析代码选“否”,停在这里。
0041C087 > /EB 01 jmp short upxlock.0041C08A //入口点
0041C089 |F660 E8 mul byte ptr [eax-18]
0041C08C 0000 add [eax], al
0041C08E 0000 add [eax], al
0041C090 8B1C24 mov ebx, [esp]
0041C093 83C3 12 add ebx, 12
Shift+F9运行程序,两次int3中断后,来到这里
0041DF17 2BDB sub ebx, ebx //来到这里
0041DF19 64:8F03 pop dword ptr fs:[ebx]
0041DF1C 58 pop eax
0041DF1D 5D pop ebp
0041DF1E 2BFF sub edi, edi
0041DF20 EB 01 jmp short upxlock.0041DF23
看堆栈区:
0012FF98 0012FFE0 指针到下一个 SEH 记录
0012FF9C 0041DF88 SE 句柄
0012FFA0 00019CF5
0012FFA4 0041DB1D 返回到 upxlock.0041DB1D 来自 upxlock.0041DB21
在SE 句柄0041DF88处下F2断点,shift+F9运行到这里,然后取消该处断点。
0041DF82 48 dec eax
0041DF83 74 31 je short upxlock.0041DFB6
0041DF85 40 inc eax
0041DF86 EB 0F jmp short upxlock.0041DF97
0041DF88 EB 01 jmp short upxlock.0041DF8B //在这里下断F2
0041DF8A FF2B jmp far fword ptr [ebx]
ALT+M打开内存窗口,在代码段下“内存访问断点”,为什么该程序的代码段在第二个区段而不是第一个区段呢?(因为本程序是在UPX压缩壳的基础上进行二次加密的,加密后程序的EP段为最后一个区段,那么解密时,先由UPXlock壳处 运行到UPX壳处,最后运行到OEP处,而UPX压缩的程序代码段一般在第二个区段)
内存映射,项目 21
地址=00409000
大小=00007000 (28672.)
属主=upxlock 00400000
区段=????
包含=代码
类型=Imag 01001040
访问=RWE
初始访问=RWE
设置好断点后,然后shift+F9,程序断在下列地方:
0040F52A FFD5 call near ebp
0040F52C 58 pop eax
0040F52D 61 popad //断在这里,很明显的upx解压地方
0040F52E 8D4424 80 lea eax, [esp-80]
0040F532 6A 00 push 0
0040F534 39C4 cmp esp, eax
0040F536 ^ 75 FA jnz short upxlock.0040F532 //此处改寄存器Z值,不跳转
0040F538 83EC 80 sub esp, -80
0040F53B - E9 9420FFFF jmp upxlock.004015D4 //此处跳到OEP
我们把代码往上拖,可以看到UPX入口特征码处:
0040F3B0 60 pushad //典型的UPX入口点处
0040F3B1 BE 00904000 mov esi, upxlock.00409000
0040F3B6 8DBE 0080FFFF lea edi, [esi+FFFF8000]
0040F3BC 57 push edi
0040F3BD 83CD FF or ebp, FFFFFFFF
0040F3C0 EB 10 jmp short upxlock.0040F3D2
其OEP为
004015D4 E8 170B0000 call upxlock.004020F0;//程序OEP
//与一般的OEP处特征码push ebp相差很多,但确实为OEP处,jmp到kernel32.GetCommandLineA,估计为支持带参数运行!
004015D9 33DB xor ebx, ebx
004015DB 8BF8 mov edi, eax
004015DD 33C0 xor eax, eax
004015DF 8A07 mov al, [edi]
004015E1 3C 22 cmp al, 22
在这里用Lordpe dump;另外查找IAT,CTRL+B,输入FF25,找到两处。
将地址进行排序,结果为:
403000-4030B4 以4为间隔,RVA:3000,大小为B4+4=B8
41E2D6-41E3FB 以5为间隔,不是IAT
保存一下树文件,供以后修复时使用
点击“修复抓取文件”修复转存文件,双击程序可以正常运行!
3、优化
用pexplorer打开文件,显示区段头。
显示4,5,6为垃圾区段;
其实它显示不正确,真真垃圾区段为2,3,4,5
6为有用区段,绝对不能删除。
********************************************************************
其实我们用OD载入dump_.exe文件,ALT+M打开内存窗口,在每个区段下F2断点,F9运行,如果能够断下,说明为有用区段;如果不能断下,直接运行,即为垃圾区段。很明显1(包含OEP),.rsrc(包含资源),.mackt(包含输入表)肯定为有用区段,这几个不用测试,测试其它的区段就可以了:
结果为2、3、4、5为垃圾区段。
*********************************************************************
方式一:
用lordpe删除这几个区段,然后在重建即可以。
最后大小为62.5 KB
方式二:
方式一的 资源段 不是最后一个区段,修改资源的时候可能出现错误,所以我们把它挪到最后一个区段中:将6区段往前移,与1区段结合,然后为 IAT段,最后为 资源段
1》从上图可知,我们先用lordpe将6区段保存为磁盘文件,然后用winhex打开dump_.exe,从0x9000开始删除后面所有的数据,且将偏移0x1E0到0xFFF的数据全部用0来填充,最后保存。
2》用lp载入保存后的文件,先将区段的数目设为1,保存,然后从磁盘载入我们刚才保存的6区段。
3》接着用lp添加一个区段,命名为.idata,虚拟大小设置为0x1000,在用winhex打开该文件,在末尾粘贴0x1000字节的数据,用来存放IAT区段
打开imprec1.6F,随便选择一个进程如ctfmon.exe,载入我们原来保存的树文件,
注意取消“增加一个新的块”,在RVA处输入0000C0000,点击“修复抓取文件”即可
4》增加资源段,
5》用lordpe载入磁盘文件rsrc.bin,到这里装配完成,要修改一些pe参数才可以运行,将镜像大小改为16000,代码基址改为1000,数据基址改为9000
6》运行一下出错,提示4020F0引用41E37C的错误提示
因为41E37C是原来6区段的数据1C000-XXX
而我们把6区段前移到9000-XXX
所以在指令4020F0处的41E37C应该为41E37C-(1C000-9000)40B37C
同理改动其它的数据为相应正确值。
保存后,运行可以正常打开,但是点击“关于”,程序出错,原因同上!
按照上述修改后,即可正常运行。最后优化一下,文件大小为63.0KB
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法