逆向工程核心原理-20

逆向工程核心原理-第二十章-”内嵌补丁”练习

20.1 内嵌补丁

“内嵌补丁”是”内嵌代码补丁”的(Inline Code Patch)的简称, 插入并运行”洞穴代码(Code Cave)”的代码补丁后, 对程序打补丁.

Untitled

注意执行顺序, 再解压过后再进行洞穴代码, 因为压缩后的数据修改跟容易报错.

注意内嵌补丁, 普通的代码补丁

Untitled

20.2 练习: Patchme

先运行一下

Untitled

点击确定

Untitled

20.3 调试: 查看代码流

使用OD打开

Untitled

401007后面就是加密代码

查看字符串

Untitled

以上字符串都是经过加密的.

我们跟进上面EP第二行的调用语句

Untitled

我们继续跟进4020EF处调用40109B

Untitled

以上这些代码就是解密循环, 是对4010F5到401248区域进行异或运算解密, 跟踪4010B0调用的4010BD又看到了另一个解密函数(就在上一个调用函数的下面)

Untitled

4010C8处的异或运算解密401007到401085区域

4010DB处的异或运算解密4010F5到401248区域

可以看到第二解密的区域跟上面调用者的解密是一样的, 所以这个区域进行了双重加密

4010BD函数结束后跳回原调用函数, 接着调用了401039处的函数

Untitled

401046处的循环用于校验和计算.

  • 首先401041处初始化EDX
  • 401046处使用ADD指令从特定区域以四个字节为单位读入值
  • 进行加法运算后存储在EDX寄存器
  • 有前面可以知道, 校验跟计算区域是一个双重加密区域, 可以推断明文就在这里

然后来到OEP处, 这里我的OD好像识别错误, 并没有把这里当成指令来看

Untitled

Untitled

实际上这里是调用了API: GetModuleHandleA()

紧接着传入五个参数并调用DialogBoxParamA()函数, 注意下图不是结构体, 而是函数定义

Untitled

第四个参数lpDialogFunc用来指出DlgBoxProcedure的地址.

对应的是PUSH 4010F5, 可以知道DlProc的地址为4010F5

跟进

Untitled

Untitled

可以看到这个字符串都在双重加密的验证区域中, 所以我们修改时要注意修改后还能满足验证的条件.

20.4 代码结构

Untitled

流程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
EP进入
解密代码{
B区域异或44
A区域异或7
B区域异或11
}
解密后的A区域{
检查B区域所有的值的总和
C区域17
跳转至OEP
}


Untitled

20.5 “内嵌补丁”练习

实际要打补丁的字符串在B区域, 就是经过双重加密的区域.

步骤:

  • 找到插入代码的合适位置
  • 然后将A区域(第一个被解密的区域, 同时最后的相加检验跳转也在这个区域)的跳转目的地从OEP改为洞穴代码的起始
  • 写入洞穴代码来修改字符串

20.5.1 补丁代码设置在何处

一般有三个:

  • 设置到文件空白区域
  • 拓展(延长)最后节区, 在尾巴写入
  • 添加新节区写入

代码较少选第一种

我们使用PEview看看第一个节区头

Untitled

可以看到在磁盘中内存大小为280, 而剩下120个字节还是闲置, 所以可以在这里插入代码.

注意在虚拟内存中节区对齐的1000, 磁盘中是200, 由于我们是要向文件中写入, 所以要用磁盘实际占用的来算

Untitled

我们用HED看看

Untitled

20.5.2 制作补丁代码

使用OD, 运行到OEP处

Untitled

首先使用空格汇编执行语句, 然后再Hex区域修改后面用来存储字符串的区域

Untitled

OD把字符串当成汇编语句了, 不用担心调试器把字符串识别成代码, 因为前面会直接跳走.

我们保存以上修改, 然后在新文件中修改跳转地址

20.5.3 执行补丁代码

最后一步就是将OEP跳转改为洞穴代码了

我们前面分析知道了跳转的地址为401083, 但是注意该地址为单层加密过后的A区域.

所以我们要修改的话, 必须将跳转的地址异或7

Untitled

我们已经设置了跳转汇编代码

Untitled

知道了原本的值, 注意后面的0000不用, 因为这两个字节刚好超出了加密区域

拆成十六进制形式: E9 96 01 注意不用逆序, 逆序针对的是一个数据块, 这个是指令

通过异或转换形式: EE 91 06 这就是加密后的形式

下面我们使用新的值, 也就是F9F801

拆成十六进制形式: E9 F8 01

通过异或转换形式: EE FF 06 这就是我们要重新填入的值(起始前面不用保存, 这里的修改也可OD进行)

20.5.4 结果确认

Untitled

Untitled

文章作者: LamのCrow
文章链接: http://example.com/2022/03/29/逆向核心工程原理-第 5064c/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LamのCrow