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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 利用键盘钩子捕捉linux键盘动作,利用键盘钩子捕获Windows键盘动作[通俗易懂]

    利用键盘钩子捕捉linux键盘动作,利用键盘钩子捕获Windows键盘动作[通俗易懂]下载本文示例代码引言  在科研生产中对研制、调试操作的记录是非常有必要而且是有很重要价值的。通过对记录信息的分析,可以在事故发生后准确的分析出事故的起因、操作是否存在失误等许多重要线索。通常需要记录的信息是多种多样的,如环境温度记录、软件运行记录、文件访问记录等等。这里将以键盘信息记录为例来讲述类似的实验信息自动记录的一般实现方法。  由于需要记录当前系统下所有应用程序的键盘录入记录,因此必须采取…

    2022年5月2日
    45
  • SQL Server存储过程多角度介绍建议收藏

    什么是存储过程:存储过程(Procedure)类似于C#语言中的方法,它是SQL语句和控制流语句的预编译集合。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、逻辑控制语句

    2021年12月21日
    48
  • clientWidth、offsetWidth、区别「建议收藏」

    clientWidth、offsetWidth、区别「建议收藏」clientWidth和clientHeigh、clientTop和clientLeft1,clientWidth的实际宽度clientWidth=width+左右padding2,clientHeigh的实际高度clientHeigh=height+上下padding3,clientTop的实际宽度clientTop=boder.top(上边框的宽度)4,clientLeft的实际宽度

    2022年7月22日
    17
  • ssm整合思路与配置详解_接口整合配置

    ssm整合思路与配置详解_接口整合配置swagger2于17年停止维护,现在最新的版本为17年发布的Swagger3(OpenApi3)

    2025年6月24日
    0
  • 搜索,推荐,广告系统架构及算法技术资料大合集吐血整理——2020年终分享

    搜索,推荐,广告系统架构及算法技术资料大合集吐血整理——2020年终分享算法学习资料:AI_Tutorial各大厂架构开发学习资源;精华机器学习,NLP,图像识别等人工智能领域学习资料,搜索,推荐,广告系统架构及算法技术资料吐血整理你还在为学习算法摸不着头脑么?你还在为技术调研各种Google么?AI的牛b吹不上去?盯紧了,这里就是你的2020女朋友~。本项目会持续关注AI落地的一些优质技术资料。大家也可以去网站投稿。算法学习资料:AI_Tutorial…

    2022年6月2日
    35
  • Python读取写入TXT正确姿势[通俗易懂]

    Python2.7IDEPycharm5.0.3在憋一个豆瓣电影抓取的“大招”,分流记录一下保存过程直奔主题1.自己写入txt直接上核心代码:withopen(“douban.txt”,”w”)asf:f.write(“这是个测试!”)这句话自带文件关闭功能,所以和那些先open再write再close的方式来说,更加pythontic!结果就是这样:2.将文件输

    2022年4月9日
    50

发表回复

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

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