PE学习(11) 移动导出表到新增节

导出表中最重要的是三张表AddressOfFunctionsAddressOfNamesAddressOfNameOrdinals,分别存储了函数地址,函数名称,函数序号,前文实现了按照函数名称查找以及按照序号查找

导出函数名称表的移动是一个难点,导出函数名称表中存储的导出函数名称偏移地址RVA,需要根据地址再进行访问函数名称。整体步骤如下:

 

测试

自己编写一个最简单的DLL文件

生成DLL后进行测试

发现新DLL可以正常运行

 

新增节

之前的文章中提到过新增节的内容,这里重新写一下相关的内容

定义一个新增节的函数,第一个参数是原文件指针;第二个参数是修改后的文件指针,一个LPVOID指针;第三个参数是原文件的大小,最后一个参数是新增节需要的大小

复制一份原来的文件

解析头部

拿到最后一节和新节的节表结构体指针

之前提到过只有节表剩余大小大于80字节才可以新增,因为一个节表大小为40,需要流出零一份全0节表来表示节表完全结束,因此一共需要80字节大小,当不足80字节可以整体上提PE头部

构造新节表的结构体,节表的Name要求是8个字节长度

新节的对齐前大小按照内存对齐来对齐,认为所有部分都是有效内存

新节的VA是上一节的VA加上一节自身的大小(确保对齐)

新节的SizeOFRawData按照文件对齐来对齐

新节的PointerToRawData按照上一节的PointerToRawDataSizeOfRawData对齐

其他属性不重要

给新增节分配内存并初始化

刷新指针

节的数量加一,且SizeOfImage参数增加新节按照内存对齐的大小

拷贝新节,返回新节大小

 

移动导出表

解析头部并拿到导出表的三个主要表

需要计算新增节的大小,并传递到新增节函数进行新增

首先是函数地址表四字节,函数名和序号表分别是两和四字节

统计所有函数名字符串大小,注意需要多加1因为字符串以00结尾

计算并加入导出表结构的大小,最后按照文件对齐来对齐,得到大小作为新增节参数

修改新增节属性为可读,含已初始化数据

计算得到新文件Buffer的导出表地址

复制三张子表信息到新节,并保留新子表的指针

遍历函数名称表,字符串地址转为FOA后获得,复制字符串长度+1 (00) 到新节中,新节指针偏移增加继续遍历

复制节表,修改三张子表的RVA

修改数据目录的导出表指向新节的导出表

 

完整代码