本文共 19788 字,大约阅读时间需要 65 分钟。
#include#include #include #include #include using namespace std;DWORD dwFileSize;BYTE* g_pFileImageBase = 0;PIMAGE_NT_HEADERS g_pNt = 0;DWORD RVAtoFOA(DWORD dwRVA);//显示pe头//参数为内存映射首地址void myPE() { OPENFILENAME stOF; HANDLE hFile, hMapFile; DWORD totalSize; //文件大小 LPVOID lpMemory; //内存映像文件在内存的起始位置 char szFileName[MAX_PATH] = { 0 }; //要打开的文件路径及名称名 char bufTemp1[10]; //每个字符的十六进制字节码 char bufTemp2[20]; //第一列 char lpServicesBuffer[100]; //一行的所有内容 char bufDisplay[50]; //第三列ASCII码字符 DWORD dwCount; //计数,逢16则重新计 DWORD dwCount1; //地址顺号 DWORD dwBlanks; //最后一行空格数 char szExtPe[] = TEXT("PE Files\0*.exe;*.dll;*.scr;*.fon;*.drv\0All Files(*.*)\0*.*\0\0"); RtlZeroMemory(&stOF, sizeof(stOF)); stOF.lStructSize = sizeof(stOF); //stOF.hwndOwner = (HWND)GetModuleHandle(NULL); stOF.lpstrFilter = szExtPe; stOF.lpstrFile = szFileName; stOF.nMaxFile = MAX_PATH; stOF.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; if (GetOpenFileName(&stOF)) //让用户选择打开的文件 { hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); //如果是无效的句柄 if (hFile == INVALID_HANDLE_VALUE) { printf("文件打开失败\n"); return; } //获取文件大小 dwFileSize = GetFileSize(hFile, NULL); g_pFileImageBase = new BYTE[dwFileSize]{}; DWORD dwRead; //将文件读取到内存中 bool bRet =ReadFile(hFile, g_pFileImageBase, dwFileSize, &dwRead, NULL); //如果读取失败就返回 if (!bRet) { delete[] g_pFileImageBase; } //关闭句柄 CloseHandle(hFile);/dos头/// //typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header // WORD e_magic; // Magic number // WORD e_cblp; // Bytes on last page of file // WORD e_cp; // Pages in file // WORD e_crlc; // Relocations // WORD e_cparhdr; // Size of header in paragraphs // WORD e_minalloc; // Minimum extra paragraphs needed // WORD e_maxalloc; // Maximum extra paragraphs needed // WORD e_ss; // Initial (relative) SS value // WORD e_sp; // Initial SP value // WORD e_csum; // Checksum // WORD e_ip; // Initial IP value // WORD e_cs; // Initial (relative) CS value // WORD e_lfarlc; // File address of relocation table // WORD e_ovno; // Overlay number // WORD e_res[4]; // Reserved words // WORD e_oemid; // OEM identifier (for e_oeminfo) // WORD e_oeminfo; // OEM information; e_oemid specific // WORD e_res2[10]; // Reserved words // LONG e_lfanew; // File address of new exe header //} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;/dos头/// //使用PIMAGE_DOS_HEADER(占64字节)解释前64个字节 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)g_pFileImageBase; //判断PE文件的标识是否正确,有一个不对,那么它就不是PE文件 if (pDos->e_magic != IMAGE_DOS_SIGNATURE)//0x5A4D('MZ') { return ; } cout << "---------------------------DOS头(_IMAGE_DOS_HEADER)------------------------------- "<< endl; cout << hex << "WORD e_magic: " << pDos->e_magic << endl; cout << hex << "WORD e_cblp: " << pDos->e_cblp << endl; cout << hex << "WORD e_cp: " << pDos->e_cp << endl; cout << hex << "WORD e_cblp: " << pDos->e_cblp << endl; cout << hex << "WORD e_cparhdr: " << pDos->e_cparhdr << endl; cout << hex << "WORD e_minalloc: " << pDos->e_minalloc << endl; cout << hex << "WORD e_ss: " << pDos->e_ss << endl; cout << hex << "WORD e_sp: " << pDos->e_sp << endl; cout << hex << "WORD e_csum: " << pDos->e_csum << endl; cout << hex << "WORD e_ip: " << pDos->e_ip << endl; cout << hex << "WORD e_cs: " << pDos->e_cs << endl; cout << hex << "WORD e_lfarlc: " << pDos->e_lfarlc << endl; cout << hex << "WORD e_ovno: " << pDos->e_ovno << endl; cout << hex << "WORD e_res[4]: " << *(pDos->e_res) << endl; cout << hex << "WORD e_oemid: " << pDos->e_oemid << endl; cout << hex << "WORD e_oeminfo: " << pDos->e_oeminfo << endl; cout << hex << "WORD e_res2[10]: " << *(pDos->e_res2) << endl; cout << hex << "WORD e_lfanew: " << pDos->e_lfanew << endl;/NT头/// /*typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;*/ g_pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + g_pFileImageBase); if (g_pNt->Signature != IMAGE_NT_SIGNATURE)//0x00004550('PE') { return ; } cout << "---------------------------NT头(PIMAGE_NT_HEADERS)------------------------------- " << endl; cout << hex << "DWORD Signature; " << g_pNt->Signature << endl; cout << hex << "IMAGE_FILE_HEADER FileHeader; " << &g_pNt->OptionalHeader << endl; cout << hex << "IMAGE_OPTIONAL_HEADER32 OptionalHeader; " << &g_pNt->OptionalHeader << endl;/FILE头/// /*typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;*/ PIMAGE_FILE_HEADER mytmf = &(g_pNt->FileHeader); cout << "---------------------------FILE头(IMAGE_FILE_HEADER )----------------------------- " << endl; cout << hex << "WORD Machine; " << mytmf->Machine << endl; cout << hex << "WORD NumberOfSections; " << mytmf->NumberOfSections << endl; cout << hex << "DWORD TimeDateStamp; " << mytmf->TimeDateStamp << endl; cout << hex << "DWORD PointerToSymbolTable; " << mytmf->PointerToSymbolTable << endl; cout << hex << "DWORD NumberOfSymbols; " << mytmf->NumberOfSymbols << endl; cout << hex << "WORD SizeOfOptionalHeader; " << mytmf->SizeOfOptionalHeader << endl; cout << hex << "WORD Characteristics; " << mytmf->Characteristics << endl; /Optional头/// // // Optional header format. // //typedef struct _IMAGE_OPTIONAL_HEADER { // // // // Standard fields. // // // WORD Magic; // BYTE MajorLinkerVersion; // BYTE MinorLinkerVersion; // DWORD SizeOfCode; // DWORD SizeOfInitializedData; // DWORD SizeOfUninitializedData; // DWORD AddressOfEntryPoint; // DWORD BaseOfCode; // DWORD BaseOfData; // // // // NT additional fields. // // // DWORD ImageBase; // DWORD SectionAlignment; // DWORD FileAlignment; // WORD MajorOperatingSystemVersion; // WORD MinorOperatingSystemVersion; // WORD MajorImageVersion; // WORD MinorImageVersion; // WORD MajorSubsystemVersion; // WORD MinorSubsystemVersion; // DWORD Win32VersionValue; // DWORD SizeOfImage; // DWORD SizeOfHeaders; // DWORD CheckSum; // WORD Subsystem; // WORD DllCharacteristics; // DWORD SizeOfStackReserve; // DWORD SizeOfStackCommit; // DWORD SizeOfHeapReserve; // DWORD SizeOfHeapCommit; // DWORD LoaderFlags; // DWORD NumberOfRvaAndSizes; // IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; PIMAGE_OPTIONAL_HEADER32 myoption = &(g_pNt->OptionalHeader); cout << "---------------------------OPTIONAL头(PIMAGE_OPTIONAL_HEADER32 )-------------------------------------------------- " << endl; cout << "---------------------------------------Standard fields.------------------------------------------------------------- " << endl; cout << hex << "WORD Magic; " << myoption->Magic << endl; cout << hex << "BYTE MajorLinkerVersion; " << myoption->MajorLinkerVersion << endl; cout << hex << "BYTE MinorLinkerVersion; " << myoption->MinorLinkerVersion << endl; cout << hex << "DWORD SizeOfCode; " << myoption->SizeOfCode << endl; cout << hex << "DWORD SizeOfInitializedData; " << myoption->SizeOfInitializedData << endl; cout << hex << "DWORD SizeOfUninitializedData; " << myoption->SizeOfUninitializedData << endl; cout << hex << "DWORD AddressOfEntryPoint; " << myoption->AddressOfEntryPoint << endl; cout << hex << "DWORD BaseOfCode; " << myoption->BaseOfCode << endl; cout << hex << "DWORD BaseOfData; " << myoption->BaseOfData << endl; cout << "----------------------------------------- NT additional fields.----------------------------------------------------- " << endl; cout << hex << "DWORD ImageBase; " << myoption->ImageBase << endl; cout << hex << "DWORD SectionAlignment; " << myoption->SectionAlignment << endl; cout << hex << "DWORD FileAlignment; " << myoption->FileAlignment << endl; cout << hex << "WORD MajorOperatingSystemVersion; " << myoption->MajorOperatingSystemVersion << endl; cout << hex << "WORD MinorOperatingSystemVersion; " << myoption->MinorOperatingSystemVersion << endl; cout << hex << "WORD MajorImageVersion; " << myoption->MajorImageVersion << endl; cout << hex << "DWORD SectionAlignment; " << myoption->SectionAlignment << endl; cout << hex << "WORD MinorImageVersion; " << myoption->MinorImageVersion << endl; cout << hex << "WORD MajorSubsystemVersion; " << myoption->MajorSubsystemVersion << endl; cout << hex << "WORD MinorSubsystemVersion; " << myoption->MinorSubsystemVersion << endl; cout << hex << "DWORD Win32VersionValue; " << myoption->Win32VersionValue << endl; cout << hex << "DWORD SizeOfImage; " << myoption->SizeOfImage << endl; cout << hex << "DWORD SizeOfHeaders; " << myoption->SizeOfHeaders << endl; cout << hex << "DWORD CheckSum; " << myoption->CheckSum << endl; cout << hex << "WORD Subsystem; " << myoption->Subsystem << endl; cout << hex << "WORD DllCharacteristics; " << myoption->DllCharacteristics << endl; cout << hex << "DWORD SizeOfStackReserve; " << myoption->SizeOfStackReserve << endl; cout << hex << "DWORD SizeOfStackCommit; " << myoption->SizeOfStackCommit << endl; cout << hex << "DWORD SizeOfHeapReserve; " << myoption->SizeOfHeapReserve << endl; cout << hex << "DWORD SizeOfHeapCommit; " << myoption->SizeOfHeapCommit << endl; cout << hex << "DWORD LoaderFlags; " << myoption->LoaderFlags << endl; cout << hex << "DWORD NumberOfRvaAndSizes; " << myoption->NumberOfRvaAndSizes << endl; cout << hex << "IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];" << &(myoption->DataDirectory) << endl; /所有区段表头 /*typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;*/ //所有区表头都在一起 //大文件头中找区段数 int nCountOfSection = g_pNt->FileHeader.NumberOfSections; //取第一个区表头 PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(g_pNt); //循环 for (int i = 0; i < nCountOfSection; i++) { cout << "----------------------第"< <<"个-----PIMAGE_SECTION_HEADER头(PIMAGE_OPTIONAL_HEADER32 )----------------------------- " << endl; cout << "BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; " << pSec->Name << endl; cout << hex << "DWORD PhysicalAddress; " << pSec->Misc.PhysicalAddress << endl; cout << hex << "DWORD VirtualSize; " << pSec->Misc.VirtualSize << endl; cout << hex << "DWORD VirtualAddress; " << pSec->VirtualAddress << endl; cout << hex << "DWORD SizeOfRawData; " << pSec->SizeOfRawData << endl; cout << hex << "DWORD PointerToRawData; " << pSec->PointerToRawData << endl; cout << hex << "DWORD PointerToRelocations; " << pSec->PointerToRelocations << endl; cout << hex << "WORD PointerToLinenumbers; " << pSec->PointerToLinenumbers << endl; cout << hex << "WORD NumberOfRelocations; " << pSec->NumberOfRelocations << endl; cout << hex << "DWORD NumberOfLinenumbers; " << pSec->NumberOfLinenumbers << endl; cout << hex << "DWORD Characteristics; " << pSec->Characteristics << endl; cout << hex << "在文件中相对文件偏移; " << RVAtoFOA(pSec->VirtualAddress) << endl; //下一个区表头首地址 ++pSec; } /导出表/// //typedef struct _IMAGE_EXPORT_DIRECTORY { // DWORD Characteristics; // DWORD TimeDateStamp; // WORD MajorVersion; // WORD MinorVersion; // DWORD Name; // DWORD Base; // DWORD NumberOfFunctions; // DWORD NumberOfNames; // DWORD AddressOfFunctions; // RVA from base of image // DWORD AddressOfNames; // RVA from base of image // DWORD AddressOfNameOrdinals; // RVA from base of image //} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; //找到导出表 也就是第一个表下标为0 DWORD dwExportRVA =g_pNt->OptionalHeader.DataDirectory[0].VirtualAddress; //获取在文件中的位置 PIMAGE_EXPORT_DIRECTORY pExport =(PIMAGE_EXPORT_DIRECTORY)(RVAtoFOA(dwExportRVA) + g_pFileImageBase); //模块名字 char* pName = (char*)(RVAtoFOA(pExport->Name) + g_pFileImageBase); printf("%s\n", pName); //地址表中的个数 DWORD dwCountOfFuntions = pExport->NumberOfFunctions; //名称表中的个数 DWORD dwCountOfNames = pExport->NumberOfNames; //地址表地址 PDWORD pAddrOfFuntion = (PDWORD)(RVAtoFOA(pExport->AddressOfFunctions) + g_pFileImageBase); //名称表地址 PDWORD pAddrOfName = (PDWORD)(RVAtoFOA(pExport->AddressOfNames) + g_pFileImageBase); //序号表地址 PWORD pAddrOfOrdial = (PWORD)(RVAtoFOA(pExport->AddressOfNameOrdinals) + g_pFileImageBase); //base值 DWORD dwBase = pExport->Base; //遍历地址表中的元素 cout << "-----------------------------------------导出表中的导出函数与导出序号-------------------------------------------------- " << endl; if (dwExportRVA == 0) { printf("没有导出表\n"); //return; } else { for (int i = 0; i < dwCountOfFuntions;i++) { //地址表中可能存在无用的值(就是为0的值) if (pAddrOfFuntion[i] == 0) { continue; } //根据序号表中是否有值(地址表的下标值), //来判断是否是名称导出 bool bRet = false; for (int j = 0; j < dwCountOfNames;j++) { //i为地址表下标j为序号表的下标(值为地址表下标) //判断是否在序号表中 if (i == pAddrOfOrdial[j]) { //因为序号表与名称表的位置一一对应 //取出名称表中的名称地址RVA DWORD dwNameRVA = pAddrOfName[j]; char* pFunName = (char*)(RVAtoFOA(dwNameRVA) + g_pFileImageBase); printf("%04d %s 0x%08x\n", i + dwBase, pFunName, pAddrOfFuntion[i]); bRet = true; break; } } if (!bRet) { //序号表中没有,说明是以序号导出的 printf("%04d %08X\n", i + dwBase, pAddrOfFuntion[i]); } } } /导出表/// //typedef struct _IMAGE_IMPORT_DESCRIPTOR { // union { // DWORD Characteristics; // 0 for terminating null import descriptor // DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) // } DUMMYUNIONNAME; // DWORD TimeDateStamp; // 0 if not bound, // // -1 if bound, and real date\time stamp // // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // // O.W. date/time stamp of DLL bound to (Old BIND) // DWORD ForwarderChain; // -1 if no forwarders // DWORD Name; // DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) //} IMAGE_IMPORT_DESCRIPTOR; //typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR; cout << "-----------------------------------------导入表中的导入函数与导入模块-------------------------------------------------- " << endl; //找到导入表 也就是第二个下标为1 DWORD dwImpotRVA = g_pNt->OptionalHeader.DataDirectory[1].VirtualAddress; //在文件中的位置 DWORD dwImportInFile = (DWORD)(RVAtoFOA(dwImpotRVA) + g_pFileImageBase); PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)dwImportInFile; //遍历每一个导入表 通过最后一个为0作为判断条件 if (dwImpotRVA == 0) { printf("没有导入表\n"); return; } else { while (pImport->Name) { //函数名称地址 PIMAGE_THUNK_DATA pFirsThunk = (PIMAGE_THUNK_DATA)(RVAtoFOA(pImport->FirstThunk) + g_pFileImageBase); //模块名 char* pName = (char*)(RVAtoFOA(pImport->Name) + g_pFileImageBase); printf("导入模块名字%s\n", pName); //也是通过最后一个为0作为判断条件 while (pFirsThunk->u1.AddressOfData) { //判断导入方式 if (IMAGE_SNAP_BY_ORDINAL32(pFirsThunk->u1.AddressOfData)) { //说明是序号导入(低16位是其序号) printf("\t\t%04X \n", pFirsThunk->u1.Ordinal & 0xFFFF); } else { //名称导入 PIMAGE_IMPORT_BY_NAME pImportName = (PIMAGE_IMPORT_BY_NAME)(RVAtoFOA(pFirsThunk->u1.AddressOfData) + g_pFileImageBase); printf("\t\t%04X %s \n", pImportName->Hint, pImportName->Name); } // pFirsThunk++; } pImport++; } } return ; }}//void _openFile();DWORD RVAtoFOA(DWORD dwRVA){ //此RVA落在哪个区段中 //找到所在区段后, //减去所在区段的起始位置,加上在文件中的起始位置 //大文件头中找区段数 int nCountOfSection = g_pNt->FileHeader.NumberOfSections; //区段表头 PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(g_pNt); //在扩展头中找到块对齐数 DWORD dwSecAligment = g_pNt->OptionalHeader.SectionAlignment; //循环 for (int i = 0; i < nCountOfSection; i++) { //求在内存中的真实大小 //Misc.VirtualSize % dwSecAligment如果是0代表刚好对齐否则就先对齐(非0就是真) //Misc.VirtualSize / dwSecAligment * dwSecAligment + dwSecAligment //最后加上余数的对齐 DWORD dwRealVirSize = pSec->Misc.VirtualSize % dwSecAligment ? pSec->Misc.VirtualSize / dwSecAligment * dwSecAligment + dwSecAligment : pSec->Misc.VirtualSize; //区段中的相对虚拟地址转文件偏移 思路是 用要转换的地址与各个区 //段起始地址做比较如果落在一个区段中(大于起始地址小于起始地址加区段最大偏移和), //就用要转换的相对虚拟地址减去区段的起始地址的相对虚拟地址, //得到了这个地址相对这个区段偏移,再用得到的这个偏移加上区段在文件中的偏移的起始位置 //(pointerToRawData字段)就是他在文件中的文件偏移 if (dwRVA >= pSec->VirtualAddress && dwRVA < pSec->VirtualAddress + dwRealVirSize) { //FOA = RVA - 内存中区段的起始位置 + 在文件中区段的起始位置 return dwRVA - pSec->VirtualAddress + pSec->PointerToRawData; } //下一个区段地址 pSec++; }}int main() { myPE(); cin.get();}
转载于:https://blog.51cto.com/haidragon/2104466