WinPE基础知识之代码解析
void CMyPE::OnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 // 打开一个文件夹选择对话框 CFileDialog dlg(TRUE); dlg.DoModal(); // 将文件路径显示到编辑框 CString path = dlg.GetFolderPath(); CString path1 = dlg.GetFileName(); m_Edit.SetWindowText(path + L"\\" + path1); // 将PE文件读到缓冲区 HANDLE hFile = CreateFile(path + L"\\" + path1, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == (HANDLE)-1) { printf("文件不存在!\n"); return; } DWORD size = GetFileSize(hFile, NULL); LPBYTE pBuff = new BYTE[size]; DWORD dwRead = 0; ReadFile(hFile, pBuff, size, &dwRead, 0); // 使用对应的结构体解析内存中的数据 IMAGE_DOS_HEADER* pDos = NULL; pDos = (IMAGE_DOS_HEADER*)pBuff; if (pDos->e_magic != IMAGE_DOS_SIGNATURE) { MessageBox(L"不是有效的PE格式!\n"); return; } // 找到NT头 IMAGE_NT_HEADERS* pNt = NULL; pNt = (IMAGE_NT_HEADERS*)(pDos->e_lfanew + pBuff); if (pNt->Signature != IMAGE_NT_SIGNATURE) { MessageBox(L"不是有效的PE格式!\n"); return; } // 找到文件头 IMAGE_FILE_HEADER pFile = pNt->FileHeader; m_FileTree.DeleteAllItems(); // 添加区段数量 CString str1; str1.Format(L"区段数量:%d", pFile.NumberOfSections); m_FileTree.InsertItem(str1, NULL, TVI_LAST); // 添加扩展头大小 CString str2; str2.Format(L"扩展头大小:%d", pFile.SizeOfOptionalHeader); m_FileTree.InsertItem(str2, NULL, TVI_LAST); // 找到扩展头 IMAGE_OPTIONAL_HEADER pOptional = pNt->OptionalHeader; m_OptTree.DeleteAllItems(); // OEP CString str3; str3.Format(L"OEP:%x", pOptional.AddressOfEntryPoint); m_OptTree.InsertItem(str3, NULL, TVI_LAST); // 镜像基址 CString str4; str4.Format(L"镜像基址:%x", pOptional.ImageBase); m_OptTree.InsertItem(str4, NULL, TVI_LAST); // 块对齐数 CString str5; str5.Format(L"块对齐数%x", pOptional.SectionAlignment); m_OptTree.InsertItem(str5, NULL, TVI_LAST); // 文件对齐数 CString str6; str6.Format(L"文件对齐数:%x", pOptional.FileAlignment); m_OptTree.InsertItem(str6, NULL, TVI_LAST); // 内存大小 CString str7; str7.Format(L"内存大小:%x", pOptional.SizeOfImage); m_OptTree.InsertItem(str7, NULL, TVI_LAST); // 找到数据目录表 m_List3.DeleteAllItems(); PIMAGE_DATA_DIRECTORY dData = pOptional.DataDirectory; DWORD dwIndex2 = 0; for (DWORD i = 0; i < pOptional.NumberOfRvaAndSizes; i++) { // 先插入一个item 到列表 m_List3.InsertItem(dwIndex2, L""); CString str8; str8.Format(L"%x", dData[i].VirtualAddress); m_List3.SetItemText(dwIndex2, 0, str8); CString str9; str9.Format(L"%x", dData[i].Size); m_List3.SetItemText(dwIndex2, 1, str9); dwIndex2++; } // 区段表 // 使用宏来找到区段头数组的首地址 // 首地址 = NT头的首地址 + NT头的总字节数 IMAGE_SECTION_HEADER* pScnHdr = NULL; // 使用宏来找到区段头数组的首地址 pScnHdr = IMAGE_FIRST_SECTION(pNt); // 得到区段头的个数 DWORD scnHdrCount = pNt->FileHeader.NumberOfSections; m_SCNTree.DeleteAllItems(); for (DWORD i = 0; i < scnHdrCount; i++) { HTREEITEM hItem; CStringW str10(pScnHdr[i].Name); hItem = m_SCNTree.InsertItem(L"区段名称:" + str10, NULL, TVI_LAST); CString str11; str11.Format(L"区段大小:%x", pScnHdr[i].Misc.VirtualSize); m_SCNTree.InsertItem(str11, hItem); CString str12; str12.Format(L"RVA:%x", pScnHdr[i].VirtualAddress); m_SCNTree.InsertItem(str12, hItem); CString str13; str13.Format(L"文件大小:%x", pScnHdr[i].SizeOfRawData); m_SCNTree.InsertItem(str13, hItem); CString str14; str14.Format(L"文件偏移:%x", pScnHdr[i].PointerToRawData); m_SCNTree.InsertItem(str14, hItem); } /*导入表*/ // 1:获取导入表的首地址 DWORD dwImpTabRva = pNt->OptionalHeader.DataDirectory[1].VirtualAddress; // 将RVA转换为FOA DWORD dwImpTabFoa = rva2foa(pNt, dwImpTabRva); // 得到导入表数组的首地址 IMAGE_IMPORT_DESCRIPTOR* pImp = (IMAGE_IMPORT_DESCRIPTOR*)(dwImpTabFoa + pBuff); // 2:遍历导入表数组,数组以0结尾 m_ImportTree.DeleteAllItems(); while (pImp->Name != 0) { // 3:在遍历出每一个导入表后,遍历它的INT或者IAT // 3.1 获取导入表DLL的名字 DWORD dwNameFoa = rva2foa(pNt, pImp->Name); char* pDllName = (char*)(dwNameFoa + pBuff); HTREEITEM hItem; CStringW str15(pDllName); hItem = m_ImportTree.InsertItem(L"模块名称:" + str15, NULL, TVI_LAST); // 3,2 从INT中得到所有的导入函数的名字/序号 IMAGE_THUNK_DATA* pInt = 0; DWORD dwIntFoa = rva2foa(pNt, pImp->OriginalFirstThunk); pInt = (IMAGE_THUNK_DATA*)(dwIntFoa + pBuff); while (pInt->u1.Function != 0) { // 判断导入的方式:序号导入还是名称导入 if (IMAGE_SNAP_BY_ORDINAL(pInt->u1.Ordinal)) { CString str16; str16.Format(L"函数序号:%x", pInt->u1.Ordinal & 0xFFFF); m_ImportTree.InsertItem(str16, hItem); } else { IMAGE_IMPORT_BY_NAME* pImpName = 0; DWORD dwNameFoa1 = rva2foa(pNt, pInt->u1.AddressOfData); pImpName = (IMAGE_IMPORT_BY_NAME*)(dwNameFoa1 + pBuff); CString str17(pImpName->Name); m_ImportTree.InsertItem(L"函数名称:" + str17, hItem); } ++pInt; } ++pImp; } /*导出表*/ // 获取导出表首地址 DWORD dwExpTabFoa = rva2foa(pNt, pNt->OptionalHeader.DataDirectory[0].VirtualAddress); m_ExportTree.DeleteAllItems(); if (pNt->OptionalHeader.DataDirectory[0].VirtualAddress) { // 定位到导出表结构 IMAGE_EXPORT_DIRECTORY* pExpTab = (IMAGE_EXPORT_DIRECTORY*)(dwExpTabFoa + pBuff); // 定位函数名称表 DWORD* pENT = (DWORD*)(rva2foa(pNt, pExpTab->AddressOfNames) + pBuff); // 定位函数序号表 WORD* pEOT = (WORD*)(rva2foa(pNt, pExpTab->AddressOfNameOrdinals) + pBuff); for (DWORD i = 0; i < pExpTab->NumberOfNames; i++) { char* pName = (char*)(rva2foa(pNt, pENT[i]) + pBuff); HTREEITEM hItem; CString str19; str19.Format(L"函数序号:%d", pEOT[i]); hItem = m_ExportTree.InsertItem(str19, NULL, TVI_LAST); CString str18(pName); m_ExportTree.InsertItem(L"函数名称:" + str18, hItem); } } /*资源表*/ // 定位到第一层目录结构 m_CtrlTree.DeleteAllItems(); if (pNt->OptionalHeader.DataDirectory[2].VirtualAddress) { IMAGE_RESOURCE_DIRECTORY* pResDir = NULL; DWORD dwResTabRva = pNt->OptionalHeader.DataDirectory[2].VirtualAddress; DWORD dwResTabFoa = rva2foa(pNt, dwResTabRva); pResDir = (IMAGE_RESOURCE_DIRECTORY*)(dwResTabFoa + pBuff); parseResources((LPBYTE)pResDir, pResDir, m_CtrlTree, 1); } /*重定位表*/ // 定位到重定位快的首地址 m_ReTree.DeleteAllItems(); if (pNt->OptionalHeader.DataDirectory[5].VirtualAddress) { DWORD dwRelTabRva = pNt->OptionalHeader.DataDirectory[5].VirtualAddress; DWORD dwRelTabFoa = rva2foa(pNt, dwRelTabRva); IMAGE_BASE_RELOCATION* pRelTab = (IMAGE_BASE_RELOCATION*)(dwRelTabFoa + pBuff); while (pRelTab->SizeOfBlock != 0) { TypeOffset* pTypeOffset = NULL; pTypeOffset = (TypeOffset*)(pRelTab + 1); DWORD dwCount = (pRelTab->SizeOfBlock - 8) / 2; CString str30; str30.Format(L"区段RVA:%x", pRelTab->VirtualAddress); HTREEITEM hItem; hItem = m_ReTree.InsertItem(str30, NULL, TVI_LAST); for (DWORD i = 0; i < dwCount; ++i) { CString str31; str31.Format(L"属性:%x", pTypeOffset[i].Type); m_ReTree.InsertItem(str31, hItem); CString str32; str32.Format(L"偏移:%x", pTypeOffset[i].Offset); m_ReTree.InsertItem(str32, hItem); } // 得到下一个重定位快的首地址 pRelTab = (IMAGE_BASE_RELOCATION*)((LPBYTE)pRelTab + pRelTab->SizeOfBlock); } } /*TLS表*/ // 定位到TLS的首地址 m_TLSTree.DeleteAllItems(); if (pNt->OptionalHeader.DataDirectory[9].VirtualAddress) { DWORD dwTLSTabRva = pNt->OptionalHeader.DataDirectory[9].VirtualAddress; DWORD dwTLSTabFoa = rva2foa(pNt, dwTLSTabRva); IMAGE_TLS_DIRECTORY* pTLSTab = (IMAGE_TLS_DIRECTORY*)(dwTLSTabFoa + pBuff); CString str33; str33.Format(L"数据块开始VA:%x", pTLSTab->StartAddressOfRawData); m_TLSTree.InsertItem(str33, NULL, TVI_LAST); CString str34; str34.Format(L"数据块结束VA:%x", pTLSTab->EndAddressOfRawData); m_TLSTree.InsertItem(str34, NULL, TVI_LAST); CString str35; str35.Format(L"回调表VA:%x", pTLSTab->AddressOfCallBacks); m_TLSTree.InsertItem(str35, NULL, TVI_LAST); } }