(笔记)逆向工程核心原理——如何向已有二进制添加一段代码

  • 当向一个PE文件添加代码的时候,有三种方法:

    1. 添加到节区末尾的空白区域(代码大小有限制)
    2. 增加最后一个节区的大小(不限制代码大小)
    3. 在最后添加新节区(不会受到代码节剩余空间大小的限制,但是要修改PE头的更多字段)
      参考自:《逆向工程核心原理》

    以第二个方法为例,步骤如下(工具为HxD):
    (1) 先查看待修改程序的Section Alignment以及File Alignment。在PE文件中增加的空间要是FileAlignment的大小的倍数。先在对应区域Edit-Insert bytes:Bytecount=200添加200h个字节。由于PE装载器按照Section Alignment进行对齐Virtual Size,Section Alignment一般是1000,所以如果原本的Virtual Size和扩展的字节数的和不超过1000,就不需要单独增大Virtual Size的值。
    (2) 编辑PE头被扩展节区的对应字段:Size of Raw DataCharacteristics。这两个字段分别是修改为节区被扩展之后的大小,以及为该节区添加代码属性、可写、可执行属性。(IMAGE_SCN_CNT_CODEIMAGE_SCN_MEM_EXECUTEIMAGE_SCN_MEM_WRITE
    (3) 现在以添加TLS函数为例:先设置TLS表,对应可选头的数据目录中索引为9的内容。设置的两个字段在32位下是两个DWORD的值,其中一个代表IMAGE_TLS_DIRECTORY结构体数组的地址,第二个值代表结构体的大小。==地址即被扩展节区中新加字节的起始地址。==一般是被扩展节区的RVA+节区原始大小(对齐File Alignment后的大小)
    (4) 设置IMAGE_TLS_DIRECTORY结构体:将TLS回调函数注册到其中。下面是IMAGE_TLS_DIRECTORY结构体的定义:

    typedef struct __IMAGE_TLS_DIRECTORY64{
    	ULONGLONG StartAddressOfRawData;
    	ULONGLONG EndAddressOfRawData;
    	ULONGLONG AddressOfIndex;
    	ULONGLONG AddressOfCallBacks;
    	DWROD SizeOfZeroFill;
    	DWORD Characteristics;
    } IMAGE_TLS_DIRECTORY64;
    typedef IMAGE_TLS_DIRECTORY64* PIMAGE_TLS_DIRECTORY64;
    
    typedef struct _IMAGE_TLS_DIRECTORY32 {
    	DWORDStartAddressOfRawData;
    	DWORDEndAddressOfRawData;
    	DWORDAddressOfIndex;
    	DWORDAddressOfCallBacks;
    	DWROD SizeOfZeroFill;
    	DWORD Characteristics;
    } IMAGE_TLS_DIRECTORY64;
    typedef IMAGE_TLS_DIRECTORY32* PIMAGE_TLS_DIRECTORY32;
    
    #ifdef _WIN64
    typedef IMAGE_TLS_DIRECTORY64 IMAGE_TLS_DIRECTORY;
    typedef PIMAGE_TLS_DIRECTORY64 PIMAGE_TLS_DIRECTORY;
    #else
    typedef IMAGE_TLS_DIRECTORY32 IMAGE_TLS_DIRECTORY;
    typedef PIMAGE_TLS_DIRECTORY32 PIMAGE_TLS_DIRECTORY;
    #endif
    

    存在32为版本和64位版本。第三个字段就是回调函数数组的地址,其在文件中的地址可以通过RVA到raw address的转换查看。即RVA - RVA_BASE = RawAddress - RAW_BASE,将回调函数的地址放入该数组,即可成功注册回调函数。
    (5) 先向TLS回调函数写入C2 0C00 - RETURN 0C 命令,即不执行任何操作直接返回。

    TLS函数的返回指令不是RETN,而是RETN 0C指令,目的是函数有三个参数(大小为0C),需要修正栈,修正大小为0C。

    (6) 现在可以为TLS回调函数添加反调试功能,原理是检查PEB.BeginDebugged成员,若处于调试状态,就弹出消息框然后终止程序。一些细节如下:

    先比较Reanson参数值是否是1(DLL_PROCESS_ATTACH),不是则直接退出。
    检查PEB的成员的值,结构体在FS:[30]中,BeginDebugged成员的偏移为2,与0比较。
    给MessageBoxA传参数,中间两个参数是两个字符串所在的内存地址。
    使用Ollydbg进行编写TLS函数时,命令形式为CALL user32.MesageBoxACALL Kernal32.ExitProcess即可,Ollydbg会自动求得API的地址。前提是要调用的API在IAT中,否则则需要更多步骤。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值