发表于 2017-3-17 18:01

申请会员ID:IDK【未报道,账号删除】

1、申 请 I D :IDK
2、个人邮箱:278580509@qq.com


VS 2013 MFC    64位环境下解析64位PE文件



       //导出表
      CString m_ExputTable;
      //导入表
      CString m_ImportTable;
      //资源表
      CString m_ResourceTable;
      //重定位表
      CString m_RelocationeTable;
      //TLS表
      CString m_TLSTable;
      //延迟输入表
      CString m_DelayImportTable;
      //区段表
      CString m_SectionsTable;
      //数据目录表
      CString m_DataTable;







CFile file;
      BOOL bResult = file.Open(m_PEShowOpenPath, CFile::modeRead | CFile::shareDenyNone, NULL);
      CFileStatus status;
      file.GetStatus(status);

      TmpCstr = status.m_ctime.Format(_T("创建时间:%Y-%m-%d %H:%M:%S \r\n"));
      m_VaPEShowEdit += TmpCstr;

      TmpCstr = status.m_mtime.Format(_T("修改时间:%Y-%m-%d %H:%M-%S\r\n"));
      m_VaPEShowEdit += TmpCstr;

      TmpCstr = status.m_atime.Format(_T("访问时间:%Y-%m-%d %H:%M-%S\r\n"));
      m_VaPEShowEdit += TmpCstr;

      TCHAR A = { 0 };
      _stprintf_s(A, L"%u KB", status.m_size);
      TmpCstr = (_T("大小:"));
      TmpCstr += A;
      TmpCstr += (_T("\r\n"));
      m_VaPEShowEdit += TmpCstr;

      file.Close();


      HANDLE hFile = INVALID_HANDLE_VALUE;
      CString Error = _T("");
      hFile = CreateFile(m_PEShowOpenPath,
                GENERIC_READ,
                FILE_SHARE_READ,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL
                );
      if (hFile == INVALID_HANDLE_VALUE)
      {
                Error.Format(_T("错误码:%d"), GetLastError());
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                MessageBox(Error);
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return 0;
      }

      DWORD dwFileSize = GetFileSize(hFile, NULL);

      pFileData= new BYTE;

      DWORDdwReadSize = 0;
      if (!ReadFile(hFile, pFileData, dwFileSize, &dwReadSize, NULL))
      {
                Error.Format(_T("错误码:%d"), GetLastError());
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                MessageBox(Error);
                return 0;
      }

      // 使用DOS头结构指向缓冲区
      IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

      if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
      {
                MessageBox(_T("没有MZ标记"));
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return FALSE;
      }

      
      // 判断是否是有效的NT头
      // 获取Nt头
      IMAGE_NT_HEADERS* pNTHeader = (IMAGE_NT_HEADERS*)(pDosHeader->e_lfanew + (ULONG64)pDosHeader);
      
      if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
                MessageBox(_T("没有PE标记"));
                m_ControlPEShow.SetWindowTextW(m_VaPEShowEdit);
                return FALSE;
      }


      m_VaPEShowEdit += _T("\r\n");
      m_VaPEShowEdit += _T("********PE头解析***********");
      m_VaPEShowEdit += _T("\r\n");


      //获取PE头
      IMAGE_FILE_HEADER * pFileHeader = (IMAGE_FILE_HEADER *)(pDosHeader->e_lfanew + (ULONG64)pDosHeader + 4);
      //CUP
      if (pFileHeader->Machine == IMAGE_FILE_MACHINE_I386)
      {
                m_VaPEShowEdit += _T("运行平台:Intel 386");
                m_VaPEShowEdit += _T("\r\n");
      }
      else if (pFileHeader->Machine == IMAGE_FILE_MACHINE_IA64)
      {
                m_VaPEShowEdit += _T("运行平台:Intel 64");
                m_VaPEShowEdit += _T("\r\n");
      }
      else if (pFileHeader->Machine == IMAGE_FILE_MACHINE_AMD64)
      {
                m_VaPEShowEdit += _T("运行平台:AMD64 (K8)");
                m_VaPEShowEdit += _T("\r\n");
      }
      else{
                m_VaPEShowEdit += _T("运行平台:其他");
                m_VaPEShowEdit += _T("\r\n");
      }

      TmpCstr.Format(_T("文件的区块数目:%d"), pFileHeader->NumberOfSections);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      tm createTime = { 0 };
      errno_t nRet = _gmtime64_s(&createTime, (__time64_t *)&pFileHeader->TimeDateStamp);
      if (nRet==0)
      {
                TCHAR tmp = { 0 };
                _wasctime_s(tmp, &createTime);
                m_VaPEShowEdit += tmp;
                m_VaPEShowEdit += _T("\r\n");
      }
      else
      {
                TmpCstr.Format(_T("获取时间出错错误代码:%d\r\n"), nRet);
                m_VaPEShowEdit += TmpCstr;
      }
      

      TmpCstr.Format(_T("指向符号表:%d"), pFileHeader->PointerToSymbolTable);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("符号表中符号个数:%d"), pFileHeader->NumberOfSymbols);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("IMAGE_OPTIONAL_HEADER32大小:%d"), pFileHeader->SizeOfOptionalHeader);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");


      TmpCstr.Format(_T("文件属性:%d"), pFileHeader->Characteristics);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      //区块表

      // 得到第一个区段
      IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pNTHeader);

      for (int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++) {

                TCHAR tmpWchar = { 0 };

                CHAR_TO_WCHAR((CHAR*)&(pSectionHeader.Name), tmpWchar);
                TmpCstr.Format(_T("区段名: %s"), tmpWchar);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的文件偏移:%x H"), pSectionHeader.PointerToRawData);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的RVA:%x H"), pSectionHeader.VirtualAddress);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");

                TmpCstr.Format(_T("区段数据的大小:%x H"), pSectionHeader.SizeOfRawData);
                m_SectionsTable += TmpCstr;
                m_SectionsTable += _T("\r\n");
                m_SectionsTable += _T("\r\n");
                m_SectionsTable += _T("\r\n");
      }




      CString File32Or64;


      if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
                File32Or64=_T("文件类型:32位\r\n");
                m_VaPEShowEdit += File32Or64;
                AnalysisOF32BitPE();
      }
      else if (pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC){

                File32Or64 = _T("文件类型:64位\r\n");
                m_VaPEShowEdit += File32Or64;
                AnalysisOF64BitPE();

      }
DWORD PEShow::RvaToOffset(DWORD dwRva)
{
      // TODO:在此添加控件通知处理程序代码
      IMAGE_DOS_HEADER *pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

      IMAGE_NT_HEADERS *pNtHeader =   /*换行*/
                (IMAGE_NT_HEADERS*)((ULONGLONG)pDosHeader + pDosHeader->e_lfanew);

      // 得到区段个数
      DWORD   dwSectionNumber = pNtHeader->FileHeader.NumberOfSections;

      // 得到第一个区段
      IMAGE_SECTION_HEADER* pSectionHeader = IMAGE_FIRST_SECTION(pNtHeader);

      for (int i = 0; i < dwSectionNumber; ++i)
      {

                // 判断RVA是否在当前的区段中

                DWORD dwSectionEndRva =   /*换行*/
                        pSectionHeader.VirtualAddress + pSectionHeader.SizeOfRawData;

                if (dwRva >= pSectionHeader.VirtualAddress
                        && dwRva <= dwSectionEndRva) {

                        // 计算出RVA对应的文件偏移
                        // 公式:
                        // 文件偏移=RVA - 区段的起始RVA + 区段的起始文件偏移
                        DWORD dwTemp = dwRva - pSectionHeader.VirtualAddress;
                        DWORD dwOffset = dwTemp + pSectionHeader.PointerToRawData;

                        return dwOffset;
                }
      }
      return -1;
}//64位PE
void PEShow::AnalysisOF64BitPE()
{
      CString TmpCstr;

      // 得到DOS头
      IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)pFileData;

      // 得到Nt头(为了得到扩展头得先找到Nt头)
      IMAGE_NT_HEADERS64* pNtHeader =   /* 换行 */
                (IMAGE_NT_HEADERS64*)(pDosHeader->e_lfanew + (ULONG64)(pDosHeader));

      IMAGE_OPTIONAL_HEADER64* pOptionalHeader = &pNtHeader->OptionalHeader;




      m_VaPEShowEdit += _T("\r\n");
      m_VaPEShowEdit += _T("********扩展头解析***********");
      m_VaPEShowEdit += _T("\r\n");


      //获取 扩展头
      //IMAGE_OPTIONAL_HEADER* pOptionalHeader = &pNTHeader->OptionalHeader;

      TmpCstr.Format(_T("程序执行入口RVA:%x H"), pOptionalHeader->AddressOfEntryPoint);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("程序基址RVA:%x H"), pOptionalHeader->ImageBase);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("代码基址RVA:%x H"), pOptionalHeader->BaseOfCode);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      //TmpCstr.Format(_T("数据基址RVA:%x H"), pOptionalHeader->BaseOfData);
      //m_VaPEShowEdit += TmpCstr;
      //m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("内存中的区块的对齐大小:%x H"), pOptionalHeader->SectionAlignment);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("文件中的区块的对齐大小:%x H"), pOptionalHeader->FileAlignment);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("映像装入内存后的总尺寸:%x H"), pOptionalHeader->SizeOfImage);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      TmpCstr.Format(_T("所有头+区块表的尺寸大小:%x H"), pOptionalHeader->SizeOfHeaders);
      m_VaPEShowEdit += TmpCstr;
      m_VaPEShowEdit += _T("\r\n");

      m_ControlPEShow.SetWindowText(m_VaPEShowEdit);




      //数据目录表

      for (int i = 0; i < pOptionalHeader->NumberOfRvaAndSizes; i++)
      {
                m_DataTable += _T("\r\n");
                TmpCstr.Format(_T("数据的RVA:%x H      "), pOptionalHeader.DataDirectory->Size);
                m_DataTable += TmpCstr;
                TmpCstr.Format(_T("数据大小:%x H       "), pOptionalHeader.DataDirectory->VirtualAddress);
                m_DataTable += TmpCstr;
                m_DataTable += _T("\r\n");

      }




      //导出表

      // 获取到数据目录表
      IMAGE_DATA_DIRECTORY* pDataDirectory = pOptionalHeader->DataDirectory;


      //获得导出表
      DWORD dwExportTableRva = pDataDirectory.VirtualAddress;
      //将多出表的RVA转换成文件偏移

      if (dwExportTableRva == 0)
      {
                m_ExputTable = _T("没有数据");
      }
      else
      {
                ULONG64 dwExportTableOffset = RvaToOffset(dwExportTableRva);

                IMAGE_EXPORT_DIRECTORY *pExportTable = (IMAGE_EXPORT_DIRECTORY*)(dwExportTableOffset + (ULONG64)pFileData);

                ULONG64 dwNameOffset = RvaToOffset(pExportTable->Name);
                char* pDllName = (char*)(dwNameOffset + (ULONG64)pFileData);
                TCHAR ETname = { 0 };
                CHAR_TO_WCHAR(pDllName, ETname);
                m_ExputTable = ETname;
                m_ExputTable += _T("\r\n\r\n");

                // 把所有的导出的函数地址打印出来。
                // 并且,如果是以名称导出,则输出该名称
                // 如果是以序号导出,则输出该序号。
                // 将地址表的RVA转换文件偏移
                DWORD dwAddressTableOffset = RvaToOffset(pExportTable->AddressOfFunctions);
                // 得到导出地址表
                ULONG64* pAddressTable = /*换行*/
                        (ULONG64*)(dwAddressTableOffset + (ULONG64)pFileData);

                // 得到序号表的地址                                                      
                WORD* pOrdinalTable = (WORD*)((ULONG64)pFileData + RvaToOffset(pExportTable->AddressOfNameOrdinals));

                DWORD* pNameTable = (DWORD*)((ULONG64)pFileData + RvaToOffset(pExportTable->AddressOfNames));

                BOOL bIndexIsExist = FALSE; //


                for (int i = 0; i < pExportTable->NumberOfFunctions; ++i) {

                        // 打印地址
                        TmpCstr.Format(_T("虚序号[%d]   "), i);
                        m_ExputTable += TmpCstr;

                        //RVA
                        TmpCstr.Format(_T("地址(RVA):%08X H   "), pAddressTable);
                        m_ExputTable += TmpCstr;

                        bIndexIsExist = FALSE;
                        int nNameIndex = 0;
                        for (; nNameIndex < pExportTable->NumberOfNames; ++nNameIndex) {

                              // 判断地址表的下标是否存在于序号表中
                              if (i == pOrdinalTable) {
                                        bIndexIsExist = TRUE;
                                        break;
                              }
                        }

                        if (bIndexIsExist == TRUE) {
                              // 得到名称表中的RVA
                              DWORD dwNameRva = pNameTable;

                              // 将名称Rva转换成文件偏移
                              char* pFunName =
                                        (char*)((ULONG64)pFileData + RvaToOffset(dwNameRva));

                              TCHAR ETname1 = { 0 };
                              CHAR_TO_WCHAR(pFunName, ETname1);
                              TmpCstr.Format(_T("函数名:%s   "), ETname1);
                              m_ExputTable += TmpCstr;
                        }
                        else {

                              // 判断地址表当前索引到的袁术是否保存着地址
                              if (pAddressTable != 0) {
                                        // i : 是地址表中的索引号,也就是一个虚序号
                                        // 真正的序号 = 虚序号 + 序号基数
                                        TmpCstr.Format(_T("序号:[%d]   "), pExportTable->Base);
                                        m_ExputTable += TmpCstr;
                              }
                        }

                        m_ExputTable += _T("\r\n\r\n");
                }
      }


      //导入表

      //1.1获得导入表的RVA
      DWORD   dwImportTableRva = pDataDirectory.VirtualAddress;
      // 1.2 将导入表的RVA转换成文件偏移
      DWORD   dwImportTableOffset = RvaToOffset(dwImportTableRva);
      // 1.3 将导入表结构体指针指向缓冲区中的导入表
      IMAGE_IMPORT_DESCRIPTOR* pImportTable =
                (IMAGE_IMPORT_DESCRIPTOR*)((ULONG64)pFileData + dwImportTableOffset);
      //2. 遍历导入表块


      //2.1判断是否遍历到了最后一个结构体。
      while (pImportTable->Name != 0) {

                //3. 解析出导入的Dll的模块名
                //3.1 将Dll模块名的RVA转换成文件偏移
                DWORD dwNameOffset = RvaToOffset(pImportTable->Name);
                //3.2 用一个char*指针指向dll名在内存中的位置
                char* pDllName = (char*)(dwNameOffset + (ULONG64)pFileData);

                TCHAR ITname = { 0 };
                CHAR_TO_WCHAR(pDllName, ITname);
                m_ImportTable += ITname;
                m_ImportTable += _T("\r\n\r\n");

                // 4. 解析当前dll的导入函数名称
                // 4.1 得到导入名称表的地址
                pImportTable->OriginalFirstThunk; // 导入名称表
                pImportTable->FirstThunk; // 导入地址表
                // 上面说的两个表,在文件中保存的内容是完全相同的。

                DWORD dwIATOffset = RvaToOffset(pImportTable->FirstThunk);
                IMAGE_THUNK_DATA64 *pIAT = (IMAGE_THUNK_DATA64 *)((ULONG64)pFileData + dwIATOffset);

                // 4.2 遍历IAT
                //IAT是一个IMAGE_THUNK_DATA结构体数组,
                //数组是一个全0结尾。
                while (pIAT->u1.AddressOfData != 0) {



                        // 5.1 判断最高位是否是1

                        if (IMAGE_SNAP_BY_ORDINAL64(pIAT->u1.Ordinal)) {
                              // 函数是以序号导入的。
                              // 序号都是WORD类型,所以,只取它低16的值
                              TmpCstr.Format(_T("导入序号:[%d]   "), (pIAT->u1.Ordinal & 0xFFFF));
                              m_ImportTable += TmpCstr;
                        }
                        else {

                              // 函数是以名称方式导入的
                              // 字段保存着一个指向IMAGE_IMPORT_BY_NAME结构体的RVA
                              DWORD dwFunctionNameOffset = /*换行*/
                                        RvaToOffset(pIAT->u1.AddressOfData);

                              IMAGE_IMPORT_BY_NAME* pImportName = /*换行*/
                                        (IMAGE_IMPORT_BY_NAME*)((ULONG64)pFileData + dwFunctionNameOffset);


                              TCHAR FunName = { 0 };
                              CHAR_TO_WCHAR(pImportName->Name, FunName);
                              TmpCstr.Format(_T("函数名称:[%s]   "), FunName);
                              m_ImportTable += TmpCstr;
                        }

                        // 递增到下一个结构体
                        ++pIAT;
                        m_ImportTable += _T("\r\n");
                }


                m_ImportTable += _T("\r\n\r\n");
                // 递增下一个结构体
                ++pImportTable;
      }



      // 资源表

      DWORD resourcesTableOffset = RvaToOffset(pDataDirectory.VirtualAddress);

      IMAGE_RESOURCE_DIRECTORY* pRoot =
                (IMAGE_RESOURCE_DIRECTORY*)(((ULONG64)pFileData) + resourcesTableOffset);


      IMAGE_RESOURCE_DIRECTORY*    pDir2;// 资源目录
      IMAGE_RESOURCE_DIRECTORY*    pDir3;// 资源目录

      IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry1;//目录入口
      IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry2;//目录入口
      IMAGE_RESOURCE_DIRECTORY_ENTRY* pEntry3;//目录入口

      IMAGE_RESOURCE_DATA_ENTRY*      pDataEntry;// 资源数据入口
      IMAGE_RESOURCE_DIR_STRING_U*    pIdString; // 保存Id的字符串

      /* 把第一层所有的目录入口都遍历出来 */
      // 得到第一个目录入口的地址
      pEntry1 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pRoot + 1);
      for (int i = 0;
                i < pRoot->NumberOfIdEntries + pRoot->NumberOfNamedEntries;
                i++, pEntry1++) {

                //获取第一层目录入口的ID(ID就是资源的类型)
                if (pEntry1->NameIsString == 1) {
                        // NameOffset该字段的值是一个偏移
                        // 这个偏移是以资源表根目录的地址作为基址。
                        pIdString =
                              (IMAGE_RESOURCE_DIR_STRING_U*)(pEntry1->NameOffset + (ULONG64)pRoot);

                        m_ResourceTable += _T("资源类型:");
                        m_ResourceTable += pIdString->NameString;
                        m_ResourceTable += _T("\r\n\r\n");
                        //TmpCstr.Format(_T("资源类型:%s\r\n\r\n"), pIdString->NameString);
                        //m_RTEdit += TmpCstr;
                }
                else {
                        TCHAR* pType[] =
                        {
                              _T(""),          // 0
                              _T("鼠标指针"),   // 1
                              _T("位图"),   // 2
                              _T("图标"),       // 3
                              _T("菜单"),       // 4
                              _T("对话框"),      //5
                              _T("字符串列表"),//6
                              _T("字体目录"),//7
                              _T("字体"),      //8
                              _T("快捷键"),//9
                              _T("非格式化资源"),//A
                              _T("消息列表"),//B
                              _T("鼠标指针组"),//C
                              _T(""),             // D
                              _T("图标组"),//E
                              _T(""),         // F
                              _T("版本信息")//10
                        };

                        if (pEntry1->Id > 16)
                        {
                              TmpCstr.Format(_T("资源类型:%d\r\n\r\n"), pEntry1->Id);
                              m_ResourceTable += TmpCstr;
                        }
                        else
                        {
                              TmpCstr.Format(_T("资源类型:%s\r\n\r\n"), pType);
                              m_ResourceTable += TmpCstr;
                        }

                }

                // 获取第二层目录
                if (pEntry1->DataIsDirectory == 1) {

                        pDir2 = /*得到第二层资源目录*/
                              (IMAGE_RESOURCE_DIRECTORY*)(pEntry1->OffsetToDirectory + (ULONG64)pRoot);

                        // 遍历第二层资源目录的所有目录入口
                        pEntry2 = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pDir2 + 1);
                        for (int j = 0;
                              j < pDir2->NumberOfIdEntries + pDir2->NumberOfNamedEntries;
                              ++j, ++pEntry2) {

                              // 得到资源的ID
                              if (pEntry2->NameIsString == 1) {
                                        // NameOffset该字段的值是一个偏移
                                        // 这个偏移是以资源表根目录的地址作为基址。
                                        pIdString =
                                                (IMAGE_RESOURCE_DIR_STRING_U*)(pEntry2->NameOffset + (ULONG64)pRoot);

                                        TmpCstr.Format(_T(" +资源ID:%s\r\n"), pIdString->NameString);
                                        m_ResourceTable += TmpCstr;
                              }
                              else {
                                        TmpCstr.Format(_T(" +资源ID:%d\r\n"), (DWORD)pEntry2->Id);
                                        m_ResourceTable += TmpCstr;
                              }
                              // 判断第三层是目录还是数据
                              if (pEntry2->DataIsDirectory == 1) {

                                        // 得到第三层目录的地址
                                        pDir3 =
                                                (IMAGE_RESOURCE_DIRECTORY*)(pEntry2->OffsetToDirectory + (ULONG64)pRoot);

                                        // 得到第三层的第一个目录入库
                                        pEntry3 =
                                                (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(pDir3 + 1);

                                        TmpCstr.Format(_T("   +id:%d\r\n"), pEntry3->Id);
                                        m_ResourceTable += TmpCstr;
                                        // 得到数据入口
                                        pDataEntry =
                                                (IMAGE_RESOURCE_DATA_ENTRY*)(pEntry3->OffsetToData + (ULONG64)pRoot);

                                        TmpCstr.Format(_T("   +资源偏移(RVA):%x H\r\n"), pDataEntry->OffsetToData);
                                        m_ResourceTable += TmpCstr;
                                        TmpCstr.Format(_T("   +资源大小:%x H\r\n\r\n"), pDataEntry->Size);
                                        m_ResourceTable += TmpCstr;

                              }
                        }
                }
                m_ResourceTable += _T("\r\n\r\n");
      }






      //重定位表


      // 得到第一个重定位块的数组首地址(RVA)
      DWORD dwRelcationBlockOffset =
                RvaToOffset(pDataDirectory.VirtualAddress);

      // 得到第一个重定位块的地址
      IMAGE_BASE_RELOCATION* pRelcationBlock =
                (IMAGE_BASE_RELOCATION*)((ULONG64)pFileData + dwRelcationBlockOffset);

      while (TRUE)
      {
                // 判断是否是最后一个重定位块
                if (pRelcationBlock->VirtualAddress == 0 && pRelcationBlock->SizeOfBlock == 0) {
                        break;
                }
                TmpCstr.Format(_T("块开始的RVA[%x H],字节数[%x H] \r\n\r\n"), pRelcationBlock->VirtualAddress, pRelcationBlock->SizeOfBlock);
                m_RelocationeTable += TmpCstr;
                // 遍历重定位类型和偏移的数据块
                TypeOffset* pTypeOffset =
                        (TypeOffset*)((ULONG64)pRelcationBlock + sizeof(IMAGE_BASE_RELOCATION));

                DWORD   dwCount =
                        (pRelcationBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(TypeOffset);

                for (int i = 0; i < dwCount; ++i) {

                        if (pTypeOffset.Type == 3)
                        {
                              TmpCstr.Format(_T("偏移[%x H]   "), pTypeOffset.Offset);
                              m_RelocationeTable += TmpCstr;
                        }
                        // 得到需要重定位的数据
                        DWORD dwRva = pRelcationBlock->VirtualAddress + pTypeOffset.Offset;
                        DWORD dwData = RvaToOffset(dwRva);
                        DWORD* pRelData = (DWORD*)(dwData + (ULONG64)pFileData);
                        printf("+要修改的地址:\n", *pRelData);

                        TmpCstr.Format(_T("要修改的地址:[%08x H]\r\n"), *pRelData);
                        m_RelocationeTable += TmpCstr;
                }
                m_RelocationeTable += _T("\r\n\r\n");

                // 递增到下一个重定位块
                pRelcationBlock =
                        (IMAGE_BASE_RELOCATION*)((ULONG64)(pRelcationBlock)+pRelcationBlock->SizeOfBlock);
      }


      //延迟加载表

      //获得导出表
      DWORD dwDelayTableRVA = pDataDirectory.VirtualAddress;
      if (dwDelayTableRVA == 0)
      {
                m_DelayImportTable += _T("没有数据");
      }
      else
      {
                //将多出表的RVA转换成文件偏移
                DWORD dwDelayTableOffset = RvaToOffset(dwDelayTableRVA);

                IMAGE_DELAYLOAD_DESCRIPTOR *pDelayTable = (IMAGE_DELAYLOAD_DESCRIPTOR*)(dwDelayTableOffset + (ULONG64)pFileData);
                if (pDelayTable->DllNameRVA == 0x00000300)
                {
                        m_DelayImportTable = _T("没有数据\r\n");
                }
                else
                {
                        while (pDelayTable->DllNameRVA)
                        {
                              //DllName
                              WCHAR DllName = { 0 };
                              DWORD dwDelayTableNameOffset = RvaToOffset(pDelayTable->DllNameRVA);
                              ULONG64 dwName = (dwDelayTableNameOffset + (ULONG64)pFileData);
                              CHAR_TO_WCHAR((char *)dwName, DllName);


                              TmpCstr.Format(_T("DLLNameRVA:%x H   "), pDelayTable->DllNameRVA);
                              m_DelayImportTable += TmpCstr;

                              TmpCstr.Format(_T("DLLName:%s\r\n"), DllName);
                              m_DelayImportTable += TmpCstr;

                              //函数地址
                              TmpCstr.Format(_T("IAT(R)RVA:%x H   "), pDelayTable->ImportAddressTableRVA);
                              m_DelayImportTable += TmpCstr;


                              //函数名称
                              TmpCstr.Format(_T("INT(R)RVA:%x H\r\n"), pDelayTable->ImportNameTableRVA);
                              m_DelayImportTable += TmpCstr;

                              DWORD dwFunNameOffset = RvaToOffset(pDelayTable->ImportNameTableRVA);
                              DWORD dwFunName = dwFunNameOffset + (ULONG64)pFileData;

                              m_DelayImportTable += _T("-----------------------\r\n");

                              IMAGE_THUNK_DATA *pIAT = (IMAGE_THUNK_DATA *)((ULONG64)pFileData + dwFunNameOffset);

                              // 4.2 遍历IAT
                              //n是一个IMAGE_THUNK_DATA结构体数组,
                              //数组是一个全0结尾。
                              while (pIAT->u1.AddressOfData != 0) {

                                        // 5.1 判断最高位是否是1

                                        if (IMAGE_SNAP_BY_ORDINAL(pIAT->u1.Ordinal)) {
                                                // 函数是以序号导入的。
                                                // 序号都是WORD类型,所以,只取它低16的值
                                                TmpCstr.Format(_T("导入序号:%d\r\n"), (pIAT->u1.Ordinal & 0xFFFF));
                                                m_DelayImportTable += TmpCstr;
                                        }
                                        else {

                                                // 函数是以名称方式导入的
                                                // 字段保存着一个指向IMAGE_IMPORT_BY_NAME结构体的RVA
                                                DWORD dwFunctionNameOffset = /*换行*/
                                                      RvaToOffset(pIAT->u1.AddressOfData);

                                                IMAGE_IMPORT_BY_NAME* pImportName = /*换行*/
                                                      (IMAGE_IMPORT_BY_NAME*)((ULONG64)pFileData + dwFunctionNameOffset);


                                                TCHAR FunName = { 0 };
                                                CHAR_TO_WCHAR(pImportName->Name, FunName);
                                                TmpCstr.Format(_T("函数名称:%s\r\n"), FunName);
                                                m_DelayImportTable += TmpCstr;
                                        }

                                        // 递增到下一个结构体
                                        ++pIAT;
                                        m_DelayImportTable += _T("\r\n");
                              }
                              ++pDelayTable;
                        }
                }
      }



      //TSL表

      DWORD dwTLSRVA = pDataDirectory.VirtualAddress;

      if (dwTLSRVA == 0)
      {
                m_TLSTable = _T("没有数据");
      }
      else{
                //将多出表的RVA转换成文件偏移
                DWORD dwTLSOffset = RvaToOffset(dwTLSRVA);

                PIMAGE_TLS_DIRECTORY64 pTLS = PIMAGE_TLS_DIRECTORY64(dwTLSOffset + (ULONG64)pFileData);


                TmpCstr.Format(_T("StartAddressOfRawData:%x H\r\n\r\n"), pTLS->StartAddressOfRawData);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("EndAddressOfRawData:%x H\r\n\r\n"), pTLS->EndAddressOfRawData);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("AddressOfIndex:%x H\r\n\r\n"), pTLS->AddressOfIndex);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("AddressOfCallBacks:%x H\r\n\r\n"), pTLS->AddressOfCallBacks);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("SizeOfZeroFill:%x H\r\n\r\n"), pTLS->SizeOfZeroFill);
                m_TLSTable += TmpCstr;

                TmpCstr.Format(_T("Characteristics:%x H\r\n\r\n"), pTLS->Characteristics);
                m_TLSTable += TmpCstr;
      }
      
}


Hmily 发表于 2017-3-17 18:25

ID:IDK
邮箱:278580509@qq.com

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

yuedingwangji 发表于 2017-3-19 07:09

欢迎欢迎

浪迹天涯的骑士 发表于 2017-3-19 15:18

欢迎欢迎??

欢迎欢迎欢迎

swjtu_ray 发表于 2017-3-19 15:38

welcome你

滑稽小弟 发表于 2017-3-19 16:44

欢迎新人

Hmily 发表于 2017-4-8 21:07

未报到,账号删除。
页: [1]
查看完整版本: 申请会员ID:IDK【未报道,账号删除】