PE总结9 --PE文件结构之 解析导出表

// 导出表2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdlib.h>

DWORD RVA2OffSet(DWORD dwRVA, PIMAGE_NT_HEADERS32  pNt)
{
  DWORD dwOffset = 0;
 
  //获取区段头表
  PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);

  //获取区段的数量
  DWORD dwSize = pNt->FileHeader.NumberOfSections;

  //遍历找到dwRVA所在的区段
  for (DWORD i = 0; i < dwSize; i++)
  {
     if (dwRVA>=pSection[i].VirtualAddress  &&
       dwRVA < (pSection[i].Misc.VirtualSize + pSection[i].VirtualAddress))
     {
       dwOffset = dwRVA - pSection[i].VirtualAddress + pSection[i].PointerToRawData;
       return dwOffset;
     }
  }
  return dwOffset;
}

void ShowExport(PVOID lpImage, DWORD dwSize)
{
  //获取Dos头
  PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImage;
  if (IMAGE_DOS_SIGNATURE != pDos->e_magic )
  {
     return;
  }

  //获取nt头
  PIMAGE_NT_HEADERS32 pNt = (PIMAGE_NT_HEADERS32)((DWORD)lpImage + pDos->e_lfanew);
  if (IMAGE_NT_SIGNATURE != pNt->Signature)
  {
     return;
  }

  //获取目录表
  PIMAGE_DATA_DIRECTORY pData = pNt->OptionalHeader.DataDirectory;

  //获取导出表RVA
  pData = &(pData[IMAGE_DIRECTORY_ENTRY_EXPORT]);

  //获取导出表在文件中的偏移
  DWORD dwExtOffset = RVA2OffSet(pData->VirtualAddress, pNt);
  PIMAGE_EXPORT_DIRECTORY pExpt = (PIMAGE_EXPORT_DIRECTORY)((DWORD)lpImage + dwExtOffset);

  //获取数量
  DWORD dwFunCount = pExpt->NumberOfFunctions;
  DWORD dwNameCount = pExpt->NumberOfNames;
  DWORD dwModName = pExpt->Name;

  //获取地址表
  PDWORD pEAT = (PDWORD)((DWORD)lpImage + RVA2OffSet(pExpt->AddressOfFunctions, pNt));
  //获取名称表
  PDWORD pENT = (PDWORD)((DWORD)lpImage +RVA2OffSet(pExpt->AddressOfNames, pNt));
  //获取索引表-----这里要使用WORD
  PWORD pEIT = (PWORD)((DWORD)lpImage + RVA2OffSet(pExpt->AddressOfNameOrdinals, pNt));

  for (DWORD dwOrd = 0; dwOrd < dwFunCount; dwOrd++)
  {   //这里如果没有的话是个NULL
     if (!pEAT[dwOrd])
     {
       continue;
     }

     //获取函数的实际序号
     DWORD dwID = pExpt->Base + dwOrd;

     //获取导出函数地址值
     DWORD dwFunOffset = RVA2OffSet(pEAT[dwOrd], pNt);

     printf("函数序号: %08d RVA:%p  函数偏移:%p ",
       dwID,
       pEAT[dwOrd],
       dwFunOffset);
      
     //获取函数名
     // 根据序号索引到函数名称表中的名字
     for (DWORD dwIndex = 0; dwIndex < dwNameCount; dwIndex++)
     {
       // 在序号表中查找函数的序号<span style="font-family: Arial, Helvetica, sans-serif;">------------序号表的值 对应着 地址表的下标</span>

       if (pEIT[dwIndex] == dwOrd)
       {
          // 根据序号索引到函数名称表中的名字
          DWORD dwNameOffset = RVA2OffSet(pENT[dwIndex], pNt);
          char* pFunName = (char*)((DWORD)lpImage + dwNameOffset);
          printf("函数名称: %s\n",
            pFunName);

          continue;
       }
          
     }
     printf("\n");
  }
  
}

int _tmain(int argc, _TCHAR* argv[])
{
  LPCTSTR path = L"C:\\Users\\Denny\\Desktop\\(手动查找导入导出表)\\(手动查找导入导出表)\\MFCLibrary1Dll.dll";

  HANDLE hFile = nullptr;

  if ( INVALID_HANDLE_VALUE == (hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ))
  {
     return 0;
  }

  DWORD dwSize = 0;
  if ( INVALID_FILE_SIZE == (dwSize = GetFileSize(hFile, NULL)))
  {
     CloseHandle(hFile);
     return 0;
  }

  PVOID lpFileImage = nullptr;
  if (!(lpFileImage = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE)))
  {
     CloseHandle(hFile);
     return 0;
  }

  DWORD dwRet = 0;
  //将文件内容读取到内容空间
  if (! ReadFile(hFile, lpFileImage, dwSize, &dwRet, NULL))
  {
     CloseHandle(hFile);
     VirtualFree(lpFileImage, dwSize, MEM_RELEASE);
     return 0;
  }

  ShowExport(lpFileImage, dwSize);

  system("pause");
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值