《逆向工程核心原理》读书笔记——第15章 调试UPX压缩的notepad程序
Posted 大灬白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《逆向工程核心原理》读书笔记——第15章 调试UPX压缩的notepad程序相关的知识,希望对你有一定的参考价值。
第15章 调试UPX压缩的notepad程序
本章将调试UPX压缩的notepad_upx.exe程序, 进一步了解运行时压缩的相关概念。我们的目标是通过调试一点点地跟踪代码, 最终找出原notepad.exe程序代码。 最后再简单讲解一下经过UPX压缩的文件如何通过调试器。
提示
本章示例使用的是Windows XP SP3中的notepad.exe程序。
15.1 notepad.exe的EP代码
首先看一下原notepad.exe程序的EP代码, 如图15-1所示。
在010073B2地址处调用了GetModuleHandleAO API,获取notepad.exe程序的lmageBase。然后在010073B4与010073CO地址处比较MZ与PE签名。希望各位熟记原notepad.exe的EP代码。
15.2 notepad_upx.exe的EP代码
使用OllyDbg打开notepad_upx.exe时, 弹出图15-2所示的警告消息框。
调试器判断该文件为压缩文件, 在“是”与“否"中任选一个, 显示出UPX EP代码, 如图15-3所示。
EP地址为01015330, 该处即为第二个节区的末端部分。 实际压缩的notepad源代码存在于EP地址(01015330) 的上方。
下面看一下代码的开始部分(01015330)。
01015330 > $ 60 pushad
01015331 . BE 00100101 mov esi,notepad_.01011000
01015336 . 8DBE 0000FFFF lea edi,dword ptr ds:[esi-0x10000]
首先使用PUSHAD命令将EAX~EDI寄存器的值保存到栈 , 然后分别把第二个节区的起始地址(01011000)与第一个节区的起始地址(01001000)设置到ESI与EDI寄存器。UPX文件第一个节区仅存在于内存。该处即是解压缩后保存源文件代码的地方。
调试时像这样同时设置ESI与EDI,就能预见从ESI所指缓冲区到EDI所指缓冲区的内存发生了复制。此时从Source(ESI)读取数据, 解压缩后保存到Destination(EDI)。我们的目标是跟踪图15-3中的全部UPX EP代码,并最终找到原notepad的EP代码,如图15-1所示。
提示
•代码逆向分析称源文件的 EP为OEP。
•“跟踪”一词的含义是通过逐一分析代码进行追踪。
•实际的代码逆向分析中并不会逐一跟踪执行压缩代码, 常使用自动化脚本、 特 殊技巧等找到 OEP。 但是对于初次学习运行时压缩文件的朋友而言, 逐一跟踪代码才是正确的学习方法。
15.3 跟踪UPX文件
下面开始跟踪代码, 跟踪数量庞大的代码时, 请遵循如下法则。
"遇到循环(Loop)时, 先了解作用再跳出。”
整个解压缩过程由无数循环组成。因此,只有适当跳出循环才能加快速度。
15.3.1 OllyDbg的跟踪命令
跟踪数量庞大的代码时,通常不会使用Step Into(F7)命令,而使用OllyDbg中另外提供的跟踪调试命令, 如表15-1所示。
命 令 | 快捷键 | 说 明 |
---|---|---|
Animate Into | Ctrl+F7 | 反复执行Step Into命令(画面显示) |
Animate Over | Ctrl+F8 | 反复执行Step Over命令(画面显示) |
Trace Into | Ctrl+F11 | 反复执行Step fnto命令(画面不显示) |
Trace Over | Ctrl+Fl2 | 反复执行Step Over命令(画面不显示) |
除了画面显示的之外,Animate命令与跟踪命令是类似的,由于Animate命令要把跟踪过程显示在画面中,所以执行速度略徵慢一些。而两者最大的差别在千,跟踪命令会自动在事先设置的跟踪条件处停下来,并生成日志文件。在UPX文件跟踪中将使用Animate Over(Ctrl+F8)命令。
15.3.2 循环#1
在EP代码处执行An皿ate Over(Ctrl+F8)命令,开始跟踪代码。 可以看到光标快速上下移动。
若想停止跟踪,执行Step Into(F7)命令即可。
开始跟踪代码不久后, 会遇到一个短循环。 暂停跟踪, 仔细查看相应循环,如图15-4所示。
循环次数ECX=36B,循环内容为“从EDX(01001000)中读取一个字节写入EDI(01001001)”。
EDI寄存器所指的01001000地址即是第一个节区(UPXO)的起始地址,仅存在与内存中的节区(反正内容全部为NULL)。
调试经过运行时压缩的文件时,遇到这样的循环应该跳出来。在010153E6地址处按F2键设置好断点后,按F9跳出循环。
15.3.3 循环#2
在断点处再次使用Animate Over(Ctrl+F8)命令继续跟踪代码 ,不久后遇到图15-5所示的循环(比前面那个循环略大一些)。
该循环是正式的解码循环(或称为解压缩循环)01015348-010153FD,这个循环包含了循环#1。
先从ESI所指的第二个节区(UPXl)地址中依次读取值,经过适当的运算解压缩后,将值写入EDI所指的第一个节区(UPXO)地址 。该过程中使用的指令如下:
0101534B . 8807 mov byte ptr ds:[edi],al
0101534D . 47 inc edi ; notepad_.01014D58
……
010153E0 . 8807 mov byte ptr ds:[edi],al
010153E2 . 47 inc edi ; notepad_.01014D58
……
010153F1 . 8907 mov dword ptr ds:[edi],eax
010153F3 . 83C7 04 add edi,0x4
* 解压缩后的数据在AL(EAX)中,EDI指向第一个节区的地址.
只要在01015402地址处设置好断点再运行, 即可跳出第二个循环,如图15-5所示。运行到01015402地址后,在转储窗口中可以看到解压缩后的代码已经被写入第一个节区(UPXO)区域(01007000),如图15-5中原来用NULL填充的区域:
15.3.4 循环 #3
重新跟踪代码,稍后会遇到图15-6所示的第三个循环。
该段循环代码用于恢复源代码的CALL/JMP指令(操作码:E8/E9)的destination地址:
从地址01001000到01001829逐字节sub al,0xE8,之后在01015434继续循环loopd short notepad_.0101540F跳转到0101540F。
在01015436地址处设置断点运行后即可跳出循环。到此几乎接近尾声了,只要再设置好IAT,UPX解压缩代码就结束了。
提示
对于普通的运行时压缩文件 ,源文件代码、数据、资源解压缩之后,先设置好IAT再转到OEP。
15.3.5 循环 #4
重新跟踪代码,再稍微进行一段。
图15-7深色显示的部分即为设置IAT的循环。 在01015436地址处设置EDI=Ol014000, 它指向第二个节区(UPXl)区域,该区域中保存着原notepad.exe调用的API函数名称的字符串(参考图 15-8)。
UPX压缩原notepad.exe文件时, 它会分析其IAT , 提取出程序中调用的API名称列表,形成API名称字符串。
用这些API名 称字符串调用图15-7中01015467地址处的GetProcAddress()函数,获取API的起始地址,然后把API地址输入EBX寄存器所指的原notepad.exe的IAT区域。该过程会反复进行至
API名称字符串结束,最终恢复原notepad.exe的IAT。
notepad.exe全部解压缩完成后,应该将程序的控制返回到OEP处。图15-9显示的就是跳转到OEP的代码。
另外,010154AD地址处的POPAD命令与UPX代码的第一条PUSHAD命令对应,用来把当前寄存器恢复原状(参考图15-3)。
最终,使用010154BB地址处的JMP命令跳转到OEP处,要跳转到的目标地址为0100739D ,
它就是原notepad.exe的EP地址(请各位确认)。
15.4 快速查找UPX OEP的方法
各位都像上面这样顺利完成代码跟踪了吗?代码逆向技术的初学者一定要亲自试试,这有助于调试用其他压缩器压缩的文件。但每次都使用上述方法(跳出循环)查找OEP非常麻烦,实际代码逆向分析中有一些更简单的方法可以找到OEP(以UPX压缩的文件为例)。
15.4.1 在POPAD指令后的JMP指令处设置断点
UPX压缩器的特征之一是,其EP代码被包含在PUSHAD/POPAD指令之间。并且,跳转到OEP代码的JMP指令紧接着出现在POPAD指令之后。只要在JMP指令处设置好断点,运行后就能直接找到OEP。
提示
•PUSHAD指令将8个通用寄存器(EAX~EDI)的值保存到栈。
•POPAD指令把PUSHAD命令存储在栈的值再次恢复到各个寄存器。
15.4.2 在栈中设置硬件断点
该方法也利用UPX的PUSHAD/POPAD指令的特点。在图15-3中执行01015330地址处的PUSHAD命令后,查看栈,如图15-10所示。
EAX到EDI寄存器的值依次被存储到栈。从OllyDbg的Dump窗口进入栈地址(006FFA4)。将鼠标光标准确定位到6FFA4地址,使用鼠标右键菜单设置硬件断点,如图15-11所示。
硬件断点是CPU支持的断点,最多可以设置4个。与普通断点不同的是,设置断点的指令执行完成后才暂停调试。在这种状态下运行,程序就会边解压缩边执行代码,在执行POPAD的瞬间访问设置有硬件断点的0006FFA4地址,然后暂停调试。其下方即是跳转到OEP的JMP指令(熟悉该方法的操作原理才能在以后调试各种文件时得心应手)。
以上是关于《逆向工程核心原理》读书笔记——第15章 调试UPX压缩的notepad程序的主要内容,如果未能解决你的问题,请参考以下文章
《逆向工程核心原理》读书笔记——第8章 Visual Basic编写的exe程序特征