UPX脱壳逐一跟踪分析

写在前面

之前看到的UPX脱壳文章都只是教了方法,对UPX的原理少有提及。看了《逆核》的UPX脱壳一章后,俺尝试把UPX脱壳与PE文件结构的知识结合起来整理了一些(也可联系压缩器Paker的知识)。
分析样本来自BUUCTF:Reverse题目“新年快乐”(本文将寻找样本的OEP)

OD跟踪命令

可能会用到的几个跟踪命令:

命令 快捷键 作用
Animate Into Ctrl+F7 反复执行Step Into命令(画面显示)
Animate Over Ctrl+F8 反复执行Step Over命令(画面显示)
Trace Into Ctrl+F11 反复执行Step Into命令(画面不显示)
Trace Over Ctrl+F12 反复执行Step Over命令(画面不显示)
停止跟踪 F7

Animate:执行时画面会跟着光标移动一直显示;
Trace:会在事先设置好的跟踪条件处停下,并生成日志文件。
跟踪命令适合用在大型代码,一好处是容易发现短循环。
我分析时只是使用了F8/F7/F4。

先结合PE知识分析

一般情况下,分析压缩后的UPX壳,可以看到第一个节区的名称为UPX0,SizeOfRawData=0,而VirtualSize=1000h(大于0),第二个节区UPX1,它的PointerToRawData和第一个节区的相同。也就是说,第一个节区在文件中是不占用空间的,只有运行时才分配大小。
其实,第二个节区含有解压代码和将被解压的代码(压缩前的代码),在加载过程中,第二个节区的解压代码运行,将被解压代码解压到第一个节区。最后到达EP执行代码。

分析“新年快乐.exe”

  1. 打开:
    打开程序后

  2. 根据上文,下面会先执行解压代码,这个代码在UPX1节区,在此节区设置内存访问断点。
    Memory map

  3. F9几次,就能在UPX1看到经典pushad了。
    解压代码 4. F8一会可以在下面不远处发现一个循环
    循环1
    大致作用:从ESI(指向UPX1)中读取一个字节写入EDI(指向UPX0)
    需要F4跳出循环的话记得先删除刚刚下的内存断点,继续F8

  4. 提示:后面遇到的这个循环得跳出去
    循环

  5. 走出上面循环就会到这,这里的循环比较重要。它有一个像重定位表的作用,会把机器码为E8和E9(CALL/JMP指令)后跟的地址修改。重要循环

0040E3C2    5E              pop esi                                  ; 新年快乐.<ModuleEntryPoint>
0040E3C3    89F7            mov edi,esi     			//EDI=ESI                         ; 新年快乐.00401000
0040E3C5    B9 4A000000     mov ecx,0x4A	
0040E3CA    8A07            mov al,byte ptr ds:[edi]		//0101540A 取EDI的值进行对比
0040E3CC    47              inc edi                                  ; 新年快乐.00401006
0040E3CD    2C E8           sub al,0xE8
0040E3CF    3C 01           cmp al,0x1
0040E3D1  ^ 77 F7           ja short 新年快乐.0040E3CA		//判断取出来的值是否是E8/E9
0040E3D3    803F 00         cmp byte ptr ds:[edi],0x0
0040E3D6  ^ 75 F2           jnz short 新年快乐.0040E3CA
0040E3D8    8B07            mov eax,dword ptr ds:[edi]		//需要修改的地址
0040E3DA    8A5F 04         mov bl,byte ptr ds:[edi+0x4]
0040E3DD    66:C1E8 08      shr ax,0x8
0040E3E1    C1C0 10         rol eax,0x10
0040E3E4    86C4            xchg ah,al
0040E3E6    29F8            sub eax,edi                              ; 新年快乐.00401006
0040E3E8    80EB E8         sub bl,0xE8
0040E3EB    01F0            add eax,esi                              ; 新年快乐.00401000
0040E3ED    8907            mov dword ptr ds:[edi],eax		//处理后的新地址放入EDI
0040E3EF    83C7 05         add edi,0x5
0040E3F2    88D8            mov al,bl
0040E3F4  ^ E2 D9           loopd short 新年快乐.0040E3CF
  1. 走出循环后,下面来到这,设置IAT表
    IAT
    40E3F6处执行后ESI = 401000(第一个节区),EDI = 40D000(第二个节区)
    API名字
    在这里插入图片描述
    GetProcAddress可以根据函数名称获取地址:GetProcAddress
    按照书中的说法,此段程序会根据API名称,用GetProcAddress()函数获取API函数的地址,然后把地址输入到EBX指向的原IAT区域。
  2. 设置完IAT表,差不多会到程序入口点。我的想法是要到程序入口点所在的第一节区,需要有一个大的往上跳转,如是分析,然后有:
    最后
    401280就是程序的OEP

本人是菜鸡,调试能力有限,如有错误的地方麻烦指出。

这篇文章非工具脱UPX壳,也涉及PE知识:
https://my.oschina.net/u/1171187/blog/1143063
(侵权则删)

猜你喜欢

转载自blog.csdn.net/qq_50536062/article/details/114457858