安全矩阵

 找回密码
 立即注册
搜索
查看: 4882|回复: 0

逆向工具之移动导出表

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-11-7 08:24:49 | 显示全部楼层 |阅读模式
原文链接:逆向工具之移动导出表

0x01 移动表目的

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

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

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

0x02 导出表结构



上图中的导出表中的AddressOfFunctions、AddressOfNames、AddressOfNameOrdinals的值都是内存相对偏移
RVA(内存相对偏移),FOA(文件相对偏移)

0x03 移动导出表




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 实现函数

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <windows.h>
  5. #define SECTIONLENGTH 0x1000
  6. #define EVERYSECTIONTABLELENGTH 0x28
  7. #define SECTIONNAME ".export"
  8. #define INPUTFILENAME "D:/dynamicdll.dll"
  9. #define INPUTMODE "rb"
  10. #define OUTPUTFILENAME "D:/test.dll"
  11. #define OUTPUTMODE "wb"

  12. /*************************************************
复制代码

函数功能:读取一个文件,将文件内容写入到内存中;
函数参数:无
函数返回值:pFileBuffer(LPVOID)


  1. **************************************************/
  2. LPVOID FileBuffer() {
  3.     FILE* pFile = NULL; //文件指针
  4.     LPVOID pFileBuffer = NULL; //存放数据内存的首地址
  5.     DWORD filesize = 0;//记录文件大小
  6.     size_t result = 0;//记录写入的返回结果

  7.     //打开一个文件
  8.     pFile = fopen(INPUTFILENAME, INPUTMODE);
  9.     if (pFile == NULL) {
  10.         printf("打开文件失败!\n");
  11.         return NULL;
  12.     }

  13.     //统计文件的大小
  14.     fseek(pFile, 0, SEEK_END);
  15.     filesize = ftell(pFile);
  16.     fseek(pFile, 0, SEEK_SET);

  17.     //申请一块内存
  18.     pFileBuffer = malloc(filesize);
  19.     if (pFileBuffer == NULL) {
  20.         printf("申请内存失败!\n");
  21.         fclose(pFile);
  22.         return NULL;
  23.     }

  24.     //将文件数据写入内存
  25.     result = fread(pFileBuffer, 1, filesize, pFile);
  26.     if (result != filesize) {
  27.         printf("文件写入内存失败!\n");
  28.         fclose(pFile);
  29.         free(pFileBuffer);
  30.         return NULL;
  31.     }

  32.     fclose(pFile);
  33.     return pFileBuffer;
  34. }

  35. /*************************************************
复制代码

函数功能:计算一个文件大小;
函数参数:filename(文件的绝对路径,LPSTR),mode(读取文件的形式,LPSTR)
函数返回值:filesize(int)


  1. **************************************************/
  2. DWORD CountFileSize(LPSTR filename, LPSTR mode) {
  3.     FILE* pFile = NULL;
  4.     LPSTR pFileBuffer = NULL;
  5.     DWORD filesize = 0;

  6.     //打开文件
  7.     pFile = fopen(filename, mode);
  8.     if (pFile == NULL) {
  9.         printf("打开文件失败!\n");
  10.         return NULL;
  11.     }

  12.     //统计文件大小
  13.     fseek(pFile, 0, SEEK_END);
  14.     filesize = ftell(pFile);
  15.     fseek(pFile, 0, SEEK_SET);

  16.     fclose(pFile);
  17.     return filesize;
  18. }


  19. /*************************************************
复制代码


函数功能:计算一个filebuffer的大小;
函数参数:pFileBuffer(LPVOID)
函数返回值:filesize(int)

  1. **************************************************/
  2. DWORD CountFileBufferSize(LPVOID pFileBuffer) {
  3.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  4.     PIMAGE_NT_HEADERS pNTHeader = NULL;
  5.     PIMAGE_FILE_HEADER pPEHeader = NULL;
  6.     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
  7.     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
  8.     DWORD filesize = 0;//记录文件大小

  9.     if (pFileBuffer == NULL) {
  10.         printf("文件写入内存失败!\n");
  11.         return NULL;
  12.     }

  13.     //判读是否具有MZ标志                                                                                            
  14.     if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE) {
  15.         printf("不具有MZ标志!\n");
  16.         free(pFileBuffer);
  17.         return 0;
  18.     }

  19.     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

  20.     //判断是否具有PE标志                                                                                            
  21.     if (*(PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE) {
  22.         printf("不具有PE标志\n");
  23.         free(pFileBuffer);
  24.         return 0;
  25.     }

  26.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
  27.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  28.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  29.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

  30.     //最后一个节头地址 + 最后一节大小
  31.     filesize = (DWORD)((pSectionHeader + pPEHeader->NumberOfSections - 1)->PointerToRawData + (pSectionHeader + pPEHeader->NumberOfSections - 1)->SizeOfRawData);
  32.     return filesize;
  33. }


  34. /*************************************************
复制代码


函数功能:PE文件尾部新增一个节;
函数参数:pFileBuffer(LPVOID)
函数返回值:pNewFileBuffer(LPVOID)


  1. **************************************************/
  2. LPVOID AddLastSection(LPVOID pFileBuffer) {
  3.     LPVOID pNewFileBuffer = NULL;
  4.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  5.     PIMAGE_NT_HEADERS pNTHeader = NULL;
  6.     PIMAGE_FILE_HEADER pPEHeader = NULL;
  7.     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
  8.     PIMAGE_SECTION_HEADER pSectionHeader = NULL;

  9.     if (pFileBuffer == NULL) {
  10.         printf("文件写入内存失败!\n");
  11.         return NULL;
  12.     }

  13.     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
  14.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
  15.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  16.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  17.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

  18.     //判断节表空间是否足够,节表后需要预留一个节表空间的位置
  19.     if (pSectionHeader->PointerToRawData - (DWORD)(pSectionHeader + pPEHeader->NumberOfSections) < 0x50) {
  20.         printf("节表空间不够!\n");
  21.         free(pFileBuffer);
  22.         return NULL;
  23.     }

  24.     //开辟新的内存
  25.     DWORD filesize = CountFileBufferSize(pFileBuffer);
  26.     pNewFileBuffer = malloc(filesize + SECTIONLENGTH);
  27.     if (pNewFileBuffer == NULL) {
  28.         printf("申请内存失败!\n");
  29.         free(pFileBuffer);
  30.         return NULL;
  31.     }

  32.     //新内存初始化为0
  33.     memset(pNewFileBuffer, 0, filesize + SECTIONLENGTH);

  34.     //拷贝原来的文件内容到新内存并释放旧文件内存
  35.     memcpy(pNewFileBuffer, pFileBuffer, filesize);
  36.     free(pFileBuffer);

  37.     //结构体指针再次初始化
  38.     pDosHeader = (PIMAGE_DOS_HEADER)pNewFileBuffer;
  39.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pNewFileBuffer + pDosHeader->e_lfanew);
  40.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  41.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  42.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

  43.     //修改sizeofimage
  44.     pOptionHeader->SizeOfImage += SECTIONLENGTH;

  45.     //copy第一个节表内容
  46.     memcpy(pSectionHeader + pPEHeader->NumberOfSections, pSectionHeader, EVERYSECTIONTABLELENGTH);

  47.     //修改新增的节表的项目
  48.     PIMAGE_SECTION_HEADER changeSection1 = pSectionHeader + pPEHeader->NumberOfSections;//新增节表首地址
  49.     PIMAGE_SECTION_HEADER changeSection2 = pSectionHeader + pPEHeader->NumberOfSections - 1;//新增节表的前一个节表首地址
  50.     changeSection1->Misc.VirtualSize = SECTIONLENGTH;//修改内存中的尺寸
  51.     changeSection1->SizeOfRawData = SECTIONLENGTH;//修改文件中的尺寸
  52.     memcpy(changeSection1, SECTIONNAME, 0x8);//修改名字

  53.     changeSection1->PointerToRawData = changeSection2->PointerToRawData + changeSection2->SizeOfRawData;
  54.     if (changeSection2->SizeOfRawData > changeSection2->Misc.VirtualSize){
  55.         changeSection1->VirtualAddress = changeSection2->VirtualAddress + changeSection2->SizeOfRawData;
  56.     }
  57.     else{
  58.         changeSection1->VirtualAddress = changeSection2->VirtualAddress + changeSection2->Misc.VirtualSize;
  59.     }

  60.     //修改NumberOfSections
  61.     pPEHeader->NumberOfSections += 1;

  62.     return pNewFileBuffer;
  63. }


  64. /*************************************************
复制代码

函数功能:将RVA的值转换成FOA;
函数参数:pFileBuffer(LPVOID),virtualAddress(LPSTR)
函数返回值:fileAddress(LPVOID)


  1. **************************************************/
  2. LPVOID RvaToFoa(LPVOID pFileBuffer, LPSTR virtualAddress) {
  3.     LPSTR sectionAddress = NULL;//记录距离节头的距离
  4.     LPSTR fileAddress = NULL;//记录文件中的偏移
  5.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  6.     PIMAGE_NT_HEADERS pNTHeader = NULL;
  7.     PIMAGE_FILE_HEADER pPEHeader = NULL;
  8.     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
  9.     PIMAGE_SECTION_HEADER pSectionHeader = NULL;

  10.     if (pFileBuffer == NULL) {
  11.         printf("文件写入内存失败!\n");
  12.         return NULL;
  13.     }

  14.     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
  15.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
  16.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  17.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  18.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

  19.     if ((DWORD)virtualAddress <= pOptionHeader->SizeOfHeaders){
  20.         return virtualAddress;
  21.     }

  22.     for (DWORD i = 1; i <= pPEHeader->NumberOfSections; i++) {
  23.         if ((DWORD)virtualAddress < pSectionHeader->VirtualAddress) {
  24.             pSectionHeader--;
  25.             break;
  26.         }
  27.         else if (i == pPEHeader->NumberOfSections){
  28.             break;
  29.         }
  30.         else{
  31.             pSectionHeader++;
  32.         }

  33.     }

  34.     //距离该节头的距离
  35.     sectionAddress = virtualAddress - pSectionHeader->VirtualAddress;
  36.     fileAddress = pSectionHeader->PointerToRawData + sectionAddress;

  37.     return (LPVOID)fileAddress;
  38. }


  39. /*************************************************
复制代码

函数功能:将FOA的值转换成RVA;
函数参数:pFileBuffer(LPVOID),virtualAddress(LPSTR)
函数返回值:fileAddress(LPVOID)


  1. **************************************************/
  2. LPVOID FoaToRva(LPVOID pFileBuffer, LPSTR fileaddress) {
  3.     LPSTR sectionAddress = NULL;//记录距离节头的距离
  4.     LPSTR virtualaddress = NULL;//记录内存中的偏移
  5.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  6.     PIMAGE_NT_HEADERS pNTHeader = NULL;
  7.     PIMAGE_FILE_HEADER pPEHeader = NULL;
  8.     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
  9.     PIMAGE_SECTION_HEADER pSectionHeader = NULL;

  10.     if (pFileBuffer == NULL) {
  11.         printf("文件写入内存失败!\n");
  12.         return NULL;
  13.     }

  14.     pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
  15.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
  16.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  17.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  18.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

  19.     if ((DWORD)fileaddress <= pOptionHeader->SizeOfHeaders){
  20.         return fileaddress;
  21.     }

  22.     for (DWORD i = 1; i <= pPEHeader->NumberOfSections; i++) {
  23.         if ((DWORD)fileaddress < pSectionHeader->PointerToRawData) {
  24.             pSectionHeader--;
  25.             break;
  26.         }
  27.         else if (i == pPEHeader->NumberOfSections){
  28.             break;
  29.         }
  30.         else{
  31.             pSectionHeader++;
  32.         }

  33.     }

  34.     //距离该节头的距离
  35.     sectionAddress = fileaddress - pSectionHeader->PointerToRawData;
  36.     virtualaddress = pSectionHeader->VirtualAddress + sectionAddress;

  37.     return (LPVOID)virtualaddress;
  38. }

  39. /*************************************************
复制代码

函数功能:移动导出表;
函数参数:pFileBuffer(LPVOID)
函数返回值:无


  1. **************************************************/
  2. void MoveExportTable(LPVOID pFileBuffer) {
  3.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  4.     PIMAGE_NT_HEADERS pNTHeader = NULL;
  5.     PIMAGE_FILE_HEADER pPEHeader = NULL;
  6.     PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
  7.     PIMAGE_SECTION_HEADER pSectionHeader = NULL;

  8.     PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;//定位目录
  9.     PIMAGE_EXPORT_DIRECTORY exportTableAddress = NULL;//定位导出表的真正位置
  10.     PDWORD addressOfFunction = NULL;//定位函数地址表的真正位置
  11.     PDWORD addressOfName = NULL;//定位函数名称地址表的真正位置
  12.     PWORD addressNameOrdinals = NULL;//定位函数序号表的真正位置
  13.     LPVOID returnAddress = NULL;//记录RVAtoFOA的返回值

  14.     if (pFileBuffer == NULL) {
  15.         printf("文件写入内存失败!\n");
  16.         return;
  17.     }

  18.     //新增一个节
  19.     LPVOID pNewFileBuffer = AddLastSection(pFileBuffer);

  20.     if (pNewFileBuffer == NULL) {
  21.         printf("新增节失败!\n");
  22.         return;
  23.     }

  24.     pDosHeader = (PIMAGE_DOS_HEADER)pNewFileBuffer;
  25.     pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pNewFileBuffer + pDosHeader->e_lfanew);
  26.     pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
  27.     pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20);
  28.     pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
  29.     pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;

  30.     //定位导出表位置
  31.     returnAddress = RvaToFoa(pNewFileBuffer, (LPSTR)(pDataDirectory->VirtualAddress));
  32.     exportTableAddress = (PIMAGE_EXPORT_DIRECTORY)((DWORD)returnAddress + (DWORD)pNewFileBuffer);

  33.     //定位函数地址表
  34.     returnAddress = RvaToFoa(pNewFileBuffer, (LPSTR)(exportTableAddress->AddressOfFunctions));
  35.     addressOfFunction = (PDWORD)((DWORD)(returnAddress)+(DWORD)pNewFileBuffer);
  36.     PDWORD pNewSection = (PDWORD)((pSectionHeader + pPEHeader->NumberOfSections - 1)->PointerToRawData + (DWORD)pNewFileBuffer);

  37.     //复制AddressOfFunctions
  38.     PDWORD repairAddressOfFunction = (PDWORD)((DWORD)pNewSection - (DWORD)pNewFileBuffer);
  39.     memcpy(pNewSection, addressOfFunction, (exportTableAddress->NumberOfFunctions) * 4);

  40.     //定位函数序号表
  41.     returnAddress = RvaToFoa(pNewFileBuffer, (LPSTR)(exportTableAddress->AddressOfNameOrdinals));
  42.     addressNameOrdinals = (PWORD)((DWORD)(returnAddress)+(DWORD)pNewFileBuffer);
  43.     pNewSection = (PDWORD)((DWORD)pNewSection + ((exportTableAddress->NumberOfFunctions) * 4));

  44.     //复制AddressOfNameOrdinals
  45.     PWORD repairAddressNameOrdinals = (PWORD)((DWORD)pNewSection - (DWORD)pNewFileBuffer);
  46.     memcpy(pNewSection, addressNameOrdinals, (exportTableAddress->NumberOfNames) * 2);

  47.     //定位函数名称地址表
  48.     returnAddress = RvaToFoa(pNewFileBuffer, (LPSTR)(exportTableAddress->AddressOfNames));
  49.     addressOfName = (PDWORD)((DWORD)(returnAddress)+(DWORD)pNewFileBuffer);
  50.     pNewSection = (PDWORD)((DWORD)pNewSection + ((exportTableAddress->NumberOfNames) * 2));

  51.     //复制AddressOfNames
  52.     PDWORD repairAddressOfName = (PDWORD)((DWORD)pNewSection - (DWORD)pNewFileBuffer);
  53.     memcpy(pNewSection, addressOfName, (exportTableAddress->NumberOfNames) * 4);

  54.     //循环复制函数名并修复函数名地址
  55.     DWORD singleFunctionNamelen = 0;//记录函数名称长度
  56.     DWORD allFuntionNamelen = 0; //记录函数名称总长度
  57.     PDWORD repairAddressName = (PDWORD)pNewSection;//用于修复函数名地址
  58.     PDWORD functionNamePtr = (PDWORD)((DWORD)pNewSection + (exportTableAddress->NumberOfNames) * 4);//用于拷贝函数名称进行偏移
  59.     PDWORD namePtr = NULL;//存储函数名的FOA

  60.     for (DWORD i = 1; i <= exportTableAddress->NumberOfNames; i++) {
  61.         //将函数名称地址表的RVA转化成FOA
  62.         returnAddress = (PBYTE)RvaToFoa(pNewFileBuffer, LPSTR(*repairAddressName));
  63.         namePtr = (PDWORD)((DWORD)returnAddress + (DWORD)pNewFileBuffer);
  64.         //尾部的0
  65.         singleFunctionNamelen = strlen((const char*)namePtr) + 1;
  66.         memcpy(functionNamePtr, (const void*)namePtr, singleFunctionNamelen);
  67.         allFuntionNamelen += singleFunctionNamelen;
  68.         *repairAddressName = (DWORD)(FoaToRva(pNewFileBuffer, (LPSTR)((DWORD)functionNamePtr - (DWORD)pNewFileBuffer)));
  69.         functionNamePtr = (PDWORD)((DWORD)functionNamePtr + singleFunctionNamelen);
  70.         repairAddressName++;
  71.     }

  72.     pNewSection = (PDWORD)((DWORD)pNewSection + (exportTableAddress->NumberOfNames) * 4 + (DWORD)allFuntionNamelen);
  73.     PBYTE repairExportTable = (PBYTE)((DWORD)pNewSection - (DWORD)pNewFileBuffer);//用于修复目录表

  74.     //复制IMAGE_EXPORT_DIRECTORY结构
  75.     memcpy(pNewSection, exportTableAddress, 0x28);

  76.     //修复IMAGE_EXPORT_DIRECTORY结构中的AddressOfFunctions、AddressOfNameOrdinals、AddressOfNames FOA→RVA
  77.     exportTableAddress = (PIMAGE_EXPORT_DIRECTORY)pNewSection;
  78.     exportTableAddress->AddressOfFunctions = (DWORD)FoaToRva(pNewFileBuffer, (LPSTR)repairAddressOfFunction);
  79.     exportTableAddress->AddressOfNameOrdinals = (DWORD)FoaToRva(pNewFileBuffer, (LPSTR)repairAddressNameOrdinals);
  80.     exportTableAddress->AddressOfNames = (DWORD)FoaToRva(pNewFileBuffer, (LPSTR)repairAddressOfName);

  81.     //修复目录项中的值,指向新的IMAGE_EXPORT_DIRECTORY
  82.     pDataDirectory->VirtualAddress = (DWORD)FoaToRva(pNewFileBuffer, (LPSTR)repairExportTable);

  83.     //存盘
  84.     FILE* pFile = NULL;
  85.     DWORD newfilesize = 0;
  86.     size_t newresult = 0;

  87.     pFile = fopen(OUTPUTFILENAME, OUTPUTMODE);
  88.     if (pFile == NULL) {
  89.         printf("打开文件失败!\n");
  90.         free(pNewFileBuffer);
  91.         return;
  92.     }

  93.     newfilesize = CountFileSize(INPUTFILENAME, INPUTMODE) + SECTIONLENGTH;
  94.     newresult = fwrite(pNewFileBuffer, 1, newfilesize, pFile);

  95.     if (newresult != newfilesize) {
  96.         printf("写入文件失败!\n");
  97.         fclose(pFile);
  98.         free(pNewFileBuffer);
  99.         return;
  100.     }

  101.     printf("存盘成功!\n");
  102.     fclose(pFile);
  103.     free(pNewFileBuffer);
  104. }

  105. int main(){
  106.     LPVOID pFileBuffer = FileBuffer();
  107.     MoveExportTable(pFileBuffer);
  108.     return 0;
  109. }
复制代码

0x05 结果展示

原来的dll




移动后的dll











回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 11:45 , Processed in 0.015953 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表