UPX脱壳详细分析

UPX脱壳详细分析文章标题】:UPX脱壳详细分析【文章作者】:index09【使用工具】:UPX+OD+Stud_PE+ImportREC——————————————————————————–【详细过程】又被R公司鄙视了,每次都被相同的理由鄙视。哭……于是决定好好学一下逆向了。首先做个幼儿级的脱壳练习,当做开始吧。网上有很多类似文章,基本只写了找OEP的过程,这里稍加分

大家好,又见面了,我是你们的朋友全栈君。

文章标题】: UPX脱壳详细分析
【文章作者】: index09
【使用工具】: UPX + OD + Stud_PE + Import REC
——————————————————————————–
【详细过程】
又被R公司鄙视了,每次都被相同的理由鄙视。哭……
于是决定好好学一下逆向了。
首先做个幼儿级的脱壳练习,当做开始吧。
网上有很多类似文章,基本只写了找OEP的过程,这里稍加分析,高手莫笑。

用UPX加密记事本,简单用Stud_PE查看一下节表信息。
No | Name      | VSize      | VOffset    | RSize      | ROffset    | Charact.   |
01 | UPX0      | 0000F000   | 00001000   | 00000000   | 00000400   | E0000080   |
02 | UPX1      | 00005000   | 00010000   | 00004600   | 00000400   | E0000040   |
03 | .rsrc     | 00008000   | 00015000   | 00007200   | 00004A00   | C0000040   |
看样子没有加密资源

OD载入后如下
01014241   . BE 00000101   MOV ESI,NOTEPAD.01010000                 ; esi = sec upx1
01014246   . 8DBE 0010FFFF LEA EDI,DWORD PTR DS:[ESI+FFFF1000]      ; edi = sec upx0
0101424C   . 57            PUSH EDI
0101424D   . 83CD FF       OR EBP,FFFFFFFF
01014250   . EB 10         JMP SHORT NOTEPAD.01014262
分别把 UPX1和UPX0节的首地址放入了esi和edi
上面看到UPX0段的RSize为0,猜想是释放解压数据的空间。而UPX1段应该就是加密的程序代码了。

继续向下看
01014258   > /8A06          MOV AL,BYTE PTR DS:[ESI]                 ; //
0101425A   . |46            INC ESI
0101425B   . |8807          MOV BYTE PTR DS:[EDI],AL
0101425D   . |47            INC EDI
0101425E   > |01DB          ADD EBX,EBX
01014260   . |75 07         JNZ SHORT NOTEPAD.01014269               ; express data in sec upx1 to sec upx0
01014262   > |8B1E          MOV EBX,DWORD PTR DS:[ESI]
01014264   . |83EE FC       SUB ESI,-4
01014267   . |11DB          ADC EBX,EBX
01014269   >^/72 ED         JB SHORT NOTEPAD.01014258
0101426B   . B8 01000000   MOV EAX,1
01014270   > 01DB          ADD EBX,EBX
01014272   . 75 07         JNZ SHORT NOTEPAD.0101427B
01014274   . 8B1E          MOV EBX,DWORD PTR DS:[ESI]
01014276   . 83EE FC       SUB ESI,-4
01014279   . 11DB          ADC EBX,EBX

…….

0101431A   > /8A07          MOV AL,BYTE PTR DS:[EDI]                 ; /
0101431C   . |47            INC EDI
0101431D   . |2C E8         SUB AL,0E8                               ; find [edi] <= 0xE9 && [edi+1] == 1
0101431F   > |3C 01         CMP AL,1
01014321   .^ 77 F7         JA SHORT NOTEPAD.0101431A
01014323   . |803F 01       CMP BYTE PTR DS:[EDI],1
01014326   .^/75 F2         JNZ SHORT NOTEPAD.0101431A               ; …………………….
01014328   . 8B07          MOV EAX,DWORD PTR DS:[EDI]
0101432A   . 8A5F 04       MOV BL,BYTE PTR DS:[EDI+4]
0101432D   . 66:C1E8 08    SHR AX,8
01014331   . C1C0 10       ROL EAX,10                               ; edi = A B C D
01014334   . 86C4          XCHG AH,AL                               ; eax = 0 C B A
01014336   . 29F8          SUB EAX,EDI
01014338   . 80EB E8       SUB BL,0E8
0101433B   . 01F0          ADD EAX,ESI                              ; eax = edi offset to sec upx0 + eax
0101433D   . 8907          MOV DWORD PTR DS:[EDI],EAX
0101433F   . 83C7 05       ADD EDI,5
01014342   . 88D8          MOV AL,BL
01014344   .^ E2 D9         LOOPD SHORT NOTEPAD.0101431F             ; …………………………………….
一大堆都是从UPX1中读取数据,做一些处理,并且放入UPX0中。
应该是UPX的解压算法。具体算法比较复杂没有详细的分析。
里面的EBX控制了每一步解压应该做的操作,十分好奇这个数是怎么出来的。改天看看UPX的源代码,看看它神奇的压缩算法。
看雪上有一篇对算法的分析,有兴趣请自行搜索。

然后来到了这里
01014346   . 8DBE 00200100 LEA EDI,DWORD PTR DS:[ESI+12000]         ; //IAT
0101434C   > 8B07          MOV EAX,DWORD PTR DS:[EDI]               ; edi = upx import table??
0101434E   . 09C0          OR EAX,EAX
01014350   . 74 3C         JE SHORT NOTEPAD.0101438E                ; jmp out
01014352   . 8B5F 04       MOV EBX,DWORD PTR DS:[EDI+4]
01014355   . 8D8430 24AE01>LEA EAX,DWORD PTR DS:[EAX+ESI+1AE24]     ; eax = lib name
0101435C   . 01F3          ADD EBX,ESI                              ; ebx = esi + 4-7 (ori IAT??)
0101435E   . 50            PUSH EAX
0101435F   . 83C7 08       ADD EDI,8
01014362   . FF96 ECAE0100 CALL DWORD PTR DS:[ESI+1AEEC]            ; loadlibrary
01014368   . 95            XCHG EAX,EBP                             ; ebp = lib handle
01014369   > 8A07          MOV AL,BYTE PTR DS:[EDI]
0101436B   . 47            INC EDI
0101436C   . 08C0          OR AL,AL
0101436E   .^ 74 DC         JE SHORT NOTEPAD.0101434C
01014370   . 89F9          MOV ECX,EDI
01014372   . 57            PUSH EDI                                 ; proc name
01014373   . 48            DEC EAX
01014374   . F2:AE         REPNE SCAS BYTE PTR ES:[EDI]
01014376   . 55            PUSH EBP                                 ; lib handle
01014377   . FF96 F0AE0100 CALL DWORD PTR DS:[ESI+1AEF0]            ; getprocaddress
0101437D   . 09C0          OR EAX,EAX
0101437F   . 74 07         JE SHORT NOTEPAD.01014388
01014381   . 8903          MOV DWORD PTR DS:[EBX],EAX
01014383   . 83C3 04       ADD EBX,4
01014386   .^ EB E1         JMP SHORT NOTEPAD.01014369               ; ……………………………………..
这里有两重循环,分别从UPX1中读取dll名称,使用LoadLibrary加载入内存。
获得句柄后,再从UPX1中读取相应函数名,使用GetProcAddress获得函数地址。
01014381   . 8903          MOV DWORD PTR DS:[EBX],EAX
这一句将函数地址填入了源程序的IAT,完成了IAT的填充。
从这段代码中可以获得IAT的RVA,为0x10000。记下来留着以后修复IAT时使用。

继续往下
0101438E   > /8BAE F4AE0100 MOV EBP,DWORD PTR DS:[ESI+1AEF4]
01014394   . 8DBE 00F0FFFF LEA EDI,DWORD PTR DS:[ESI-1000]
0101439A   . BB 00100000   MOV EBX,1000
0101439F   . 50            PUSH EAX
010143A0   . 54            PUSH ESP
010143A1   . 6A 04         PUSH 4                                   ; PAGE_EXECUTE_READWRITE
010143A3   . 53            PUSH EBX
010143A4   . 57            PUSH EDI                                 ; set file header to PAGE_EXECUTE_READWRITE
010143A5   . FFD5          CALL EBP                                 ; virtualprotect
010143A7   . 8D87 FF010000 LEA EAX,DWORD PTR DS:[EDI+1FF]
010143AD   . 8020 7F       AND BYTE PTR DS:[EAX],7F                 ; remove sec UPX0 UNINITIALIZED_DATA character
010143B0   . 8060 28 7F    AND BYTE PTR DS:[EAX+28],7F              ; remove sec UPX1 UNINITIALIZED_DATA character
010143B4   . 58            POP EAX
010143B5   . 50            PUSH EAX
010143B6   . 54            PUSH ESP
010143B7   . 50            PUSH EAX
010143B8   . 53            PUSH EBX                                 ; set to old protect
010143B9   . 57            PUSH EDI
010143BA   . FFD5          CALL EBP                                 ; virtualprotect
这里首先使用VirtualProtect把文件头设置为PAGE_EXECUTE_READWRITE,获得文件头的写权限。
然后
010143AD   . 8020 7F       AND BYTE PTR DS:[EAX],7F                 ; remove sec UPX0 UNINITIALIZED_DATA character
010143B0   . 8060 28 7F    AND BYTE PTR DS:[EAX+28],7F              ; remove sec UPX1 UNINITIALIZED_DATA character
去除了节表中UPX0和UPX1段的UNINITIALIZED_DATA属性,完成了节表的初始化。有些版本UPX并没有这段代码。
最后又用VirtualProtect恢复文件头属性。

再往下看是一个大大的JMP
010143CB   .- E9 CD2FFFFF   JMP NOTEPAD.0100739D                     ; jmp to OEP
跳转到OEP

记下OEP的RAV为739D。
使用LoadPE在OEP处Dump出镜像文件。

使用ImportREC修复一下IAT
IAT的起始地址为刚才记下的0x10000,通过观察那段内存得到IAT大小为0x344
在ImportREC的IAT Infos Needed中填入我们获得的信息,便可以成功修复。

测试一下脱出来的镜像,可以正确运行。

当然你可以在找到OEP时直接用OllyDump插件直接脱壳和修复IAT。这里只是为了练手小小的绕了个弯。
有兴趣的同学欢迎交流。

——————————————————————————–

                                                       2009年08月30日 15:59:39

为了您的安全,请只打开来源可靠的网址

打开网站    取消

来自:
http://hi.baidu.com/index09/blog/item/caf196228dc9eefad6cae211.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161694.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • DDD中的建模方法有哪些[通俗易懂]

    DDD中的建模方法有哪些[通俗易懂]一、背景在之前的文章中已经介绍了DDD相关的概念模式,DDD相关的业务技术架构,但是我们还没有找到一个核心的抓手去实践DDD。DDD的一个核心本质就是对业务建模,或者领域建模。说的很简单,但是做好确实很难,一个需求过来意淫几个实体对象就差不多解决了。深入看,全局看只在脑海中进行的建模实际上并不一定正确和稳定。因此我们需要找到正确的方法帮助对业务领域进行分析,得到建模结构,共享建模成果。二、四色建模法2.1起源&概念&要素关于四色建模的概念我们可与追溯到90年代,起源于四色原型。四色

    2022年9月2日
    5
  • pycharm配置opencv环境_pycharm opencv安装

    pycharm配置opencv环境_pycharm opencv安装1.cmdpipinstallopencv-python-ihttps://pypi.tuna.tsinghua.edu.cn/simple后续可能会报pip版本低按指示升级记得-ixxxx(同上)装完后可以在cmdpythonimportcv2试试能往下走就OK2.新建Python工程不要默认“虚拟机”那个cmdpythonimportsysprint(sys.path)找到相应的.exe…

    2025年7月8日
    5
  • java的遍历数组效率测试源码[通俗易懂]

    java的遍历数组效率测试源码[通俗易懂]packagejavatest;importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;publicclassjavatest{ publicstaticvoidmain(String[]args){ Listlist=newArrayList(); l

    2022年9月15日
    4
  • python和Java语法对比

    python和Java语法对比定义变量:java:inta=1;python:a=1#python中不需要分号结尾,python用缩进判断代码块Python定义变量的时候不需要给出类型,直接定义即可,Python会自动判断变量类型。String类型:java:Stringa=newString();a="123";python:a="123"…

    2022年7月8日
    17
  • Q1营收利润大增,Take-Two如何掘金“次世代”?[通俗易懂]

    Q1营收利润大增,Take-Two如何掘金“次世代”?[通俗易懂]8月3日美股盘后,拥有GTA和2K等知名系列游戏的Take-Two(NASDAQ:TTWO)发布了截至2020年6月30日的2020财年第一季度的业绩报告。财报公布后次日,股价跳空高开,最终股价收于177.52美元,涨幅达5.87%。回顾近期走势,TTWO已连续创下历史新高,可见其一直深受投资者青睐。(图源:雪球)以下为近期核心数据表现:由于全球疫情居家,TTWO受益颇多。本季度无论是营收、净利润,还是各产品的销量均超过市场预期。此次财报有着许多亮点值得深入讨论,而除此之外,也希望随着新品推

    2022年6月7日
    30
  • MATLAB2016b安装包

    MATLAB2016b安装包百度云盘链接:(https://pan.baidu.com/s/17NdGN-GviFWlUfMrTZA_Kw)密码:p4ue

    2022年5月29日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号