dbeaver 导出表结构_逆向工具之移动导出表

0x01 移动表目的

1、PE结构里许多表是编译器自动生成的,里面存储很多非常重要的信息,比如这次要移动的导出表记录了函数的地址,序号,函数名称,函数数量等,通俗来说,导出表相当于一张函数使用说明书,提供给函数使用。

2、在程序启动的时候,系统会根据这些表来做初始化的工作:比如将用到的DLL中的函数地址存储到IAT表中,修复IAT表。

3、很多时候,为了保护我们的程序,可以对程序的二进制代码进行加密操作,但存在的问题是:各种表的信息与客户字节的代码和数据都混在一起,如果全部进行加密,那系统在初始化程序的时候会出问题,无法加载这个程序,那加密失去意义。

0x02 导出表结构

69caa77f3ada5c82fc77dba99eb217af.png

 上图中的导出表中的AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals的值都是内存相对偏移

RVA(内存相对偏移),FOA(文件相对偏移)

0x03 移动导出表

4a668743b78bb7f8ca653ed646808df8.png

 1、将原来的dll加载进内存中,堆区新开辟一块内存,大小为原来dll大小与新增节的大小之和(新增节大小直接给了0x1000,可以通过计算来判断大小),将原来dll的数据全部拷贝到申请的内存中去,再新增一个节表,并返回新开辟内存的首地址。

2、复制AddressOfFunctions指向的函数地址表,需要将内存相对偏移转化为文件相对偏移,长度:4*NumberOfFunctions。

3、复制AddressOfNameOrdinals指向的函数序号表,需要将内存相对偏移转化为文件相对偏移,长度:2*AddressOfNames。

4、复制AddressOfNames指向的函数名称地址表,需要将内存相对偏移转化为文件相对偏移,长度:4*AddressOfNames。

5、复制所有的函数名,长度需要通过strlen()函数进行计算,复制时直接修复函数名称地址表中的地址。

6、复制IMAGEEXPORTDIRECTORY结构(导出表)。

7、修复IMAGEEXPORTDIRECTORY结构中的AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals,需要将FOA转化为RVA,并且指向IMAGEEXPORTDIRECTORY结构的指针要进行更新,否则修改的还是原来位置的导出表。

8.修复可选PE头中的导出表目录的地址值(RVA),指向新的IMAGEEXPORTDIRECTORY。

0x04 实现函数

#include #include #include #include #define SECTIONLENGTH 0x1000#define EVERYSECTIONTABLELENGTH 0x28#define SECTIONNAME ".export"#define INPUTFILENAME "D:/dynamicdll.dll"#define INPUTMODE "rb"#define OUTPUTFILENAME "D:/test.dll"#define OUTPUTMODE "wb"/*************************************************

函数功能:读取一个文件,将文件内容写入到内存中;

函数参数:无

函数返回值:pFileBuffer(LPVOID)

**************************************************/LPVOID FileBuffer() {
        FILE* pFile = NULL; //文件指针    LPVOID pFileBuffer = NULL; //存放数据内存的首地址    DWORD filesize = 0;//记录文件大小    size_t result = 0;//记录写入的返回结果    //打开一个文件    pFile = fopen(INPUTFILENAME, INPUTMODE);    if (pFile == NULL) {
            printf("打开文件失败!\n");        return NULL;    }    //统计文件的大小    fseek(pFile, 0, SEEK_END);    filesize = ftell(pFile);    fseek(pFile, 0, SEEK_SET);    //申请一块内存    pFileBuffer = malloc(filesize);    if (pFileBuffer == NULL) {
            printf("申请内存失败!\n");        fclose(pFile);        return NULL;    }    //将文件数据写入内存    result = fread(pFileBuffer, 1, filesize, pFile);    if (result != filesize) {
            printf("文件写入内存失败!\n");        fclose(pFile);        free(pFileBuffer);        return NULL;    }    fclose(pFile);    return pFileBuffer;}/*************************************************

函数功能:计算一个文件大小;

函数参数:filename(文件的绝对路径,LPSTR),mode(读取文件的形式,LPSTR)

函数返回值:filesize(int)

**************************************************/DWORD CountFileSize(LPSTR filename, LPSTR mode) {
        FILE* pFile = NULL;    LPSTR pFileBuffer = NULL;    DWORD files
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值