“内嵌补丁”是“内嵌代码补丁”(InlineCodePatch)的简称,难以直接修改指定代码时,插人并运行被称为“洞穴代码”(Code Cave)的补丁代码后,对程序打补丁。
用处:常用于对象程序经过运行时压缩(或加密处理)而难以直接修改的情况
如图:
这是典型的运行时压缩代码(或者加密代码)。EP代码先把加密的OEP代码解密,然后跳转到OEP代码处。
但是如果 要打补丁的代码存在于被加密的OEP区域 则是很难打补丁的(即使知道代码位置), 因为解码过程中很可能解出完全不同的结果
解决办法:右图
即每次运行时都会运行另外的补丁代码对进程内存的代码打补丁,这种方法就被称为 内嵌代码补丁 或者 内嵌补丁 法
对象 | 代码补丁 | 内嵌补丁 |
---|---|---|
对象 | 文件 | 文件 & 内存 |
次数 | 1次 | 文件中 1 次,内存中每次运行时 |
方法 | 直接 (直接对指定位置打补丁) | 间接 (提前设置漏洞代码,在内存中对指定区域解密时打补丁) |
401007之后就是加密代码
先找字符串
可以发现都是加密的
先进入第一个函数内部看看
这里就是一个循环解密的代码
004010A3 |> /8033 44 /xor byte ptr ds:[ebx],0x44
使用上面的命令对特定区域(4010F5--401248)解密。跟踪进入地址4010b0处的call命令调用函数(4010bd)可以看到另外两个解密循环
地址4010C8处的XOR命令用来解密401007~401085区域,然后再使用4010DB地址处的XOR 命令对4010F5~401248区域解密。该区域与图中解密区域一致,由此可知该区域经过双重加密处理。
4010BD函数调用完毕后遇到4010B6地址处的CALL401039命令
跟踪进人被调用的函数(401039),看到图中代码。
401039函数中需要注意的是位于401046地址处的校验和计算循环。首先使用401041地址处的MOV EDX,0
命令,将0代入(初始化)EDX。然后使用401046地址处的ADD命令,从特定地址区域(4010F5~401248)以4个字节为单位依次读入值,进行加法运算后,将累加结果存储到EDX 寄存器。
循环结束时,EDX寄存器中存储着某个特定值,这就是校验和值。由前面的讲解可知,该校验和计算区域是一个双重加密区域。可以推测出,我们要修改的字符串就存在于此。
EDX寄存器为4个字节大小,像这样向其中不断加上4个字节的值,就会发生溢出(overflow)问题。一般的校验和计算中常常忽略该溢出问题,使用最后一个保存在EDX的值。
位于地址401062~401068处的CMP/JE命令用来将计算得到的校验和(存储在EDX寄存器的)值与31EB8DB0比较,若相同(表示代码未被改动过),则由401083地址处的JMP指令跳转到OEP (40120.)处;若不同,则输出错误信息“CrC of this file has been modified!!!”,终止程序。
这种校验和计算方法常常用来验证特定区域的代码/数据是否被改动过。只要指定区域中的一个字节发生改变,校验和值就会改变。所以更改了指定区域中的代码/数据时,一定要修改校验和比较相关部分。
图中显示的是OEP代码,用来运行对话框。执行位于40123E
地址处的 CALL user32.DialogBoxParamAO
命令后,即弹出对话框。下面是DialogBoxParamAOAPI的定义。
INT_PTR WINAPI DialogBoxParam(
__in_opt HINSTANCE hInstance,
__in LPCTSTR lpTemplateName,
__in_opt HWND hWndParent,
__in_opt DLGPROC lpDialogFunc,
__in LPARAM dwInitParam
);