C語言——PE檔案解析(完整版)
阿新 • • 發佈:2019-02-01
此次PE檔案解析的內容:PE頭、節表、匯入表、匯出表、重定位表
語言:C語言
編譯器:VS2013
執行環境:win10
注:由於時間(懶)關係,備註的比較少,看不懂的地方,歡迎留言一起交流,也歡迎指正不當之處
#include <stdio.h> #include <windows.h> IMAGE_DOS_HEADER DosHeader; PIMAGE_DOS_HEADER pDosHeader; IMAGE_NT_HEADERS NtHeader; PIMAGE_NT_HEADERS pNtHeader; IMAGE_FILE_HEADER FileHeader; PIMAGE_FILE_HEADER pFileHeader; IMAGE_OPTIONAL_HEADER OptionHeader; PIMAGE_OPTIONAL_HEADER pOptionHeader; PIMAGE_DATA_DIRECTORY pDataDirectory; IMAGE_SECTION_HEADER SectionHeader; //char * filepath = "PETool.exe"; //char * filepath = "notepad.exe"; //char * filepath = "sxs.dll"; //char * filepath = "SciLexer.dll"; char * filepath = "msgsc.dll"; //char * filepath = "NppExport.dll"; //char * filepath = "symsrv.dll"; long e_lfanew; //void HextoChar(char strHex[8]); DWORD RvaToRwa(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva); DWORD RvaToName(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva); void main(int argc, char * agrv[]) { HANDLE hFile = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); PVOID pbFile = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (hFile == INVALID_HANDLE_VALUE || hMapping == NULL || pbFile == NULL) { printf("\n========THE FILE IS NOT EXCTING===========\n"); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } if (hMapping != NULL) { CloseHandle(hMapping); } if (pbFile != NULL) { UnmapViewOfFile(pbFile); } } /*開始列印DOS頭*/ puts("=================PE DOS HEADER=================="); pDosHeader = (PIMAGE_DOS_HEADER)pbFile; printf("e_magic:%0X ", pDosHeader->e_magic); //列印"MZ"標誌 char arry_dosheader_e_magic[sizeof(pDosHeader->e_magic)]; memcpy(arry_dosheader_e_magic, &pDosHeader->e_magic, sizeof(pDosHeader->e_magic)); for (int i = 0; i < sizeof(pDosHeader->e_magic) && arry_dosheader_e_magic[i] != '\0'; i++) { printf("%c", arry_dosheader_e_magic[i]); } printf("\ne_cblp:%04X\n", pDosHeader->e_cblp); printf("e_cp:%04X\n", pDosHeader->e_cp); printf("e_crlc:%04X\n", pDosHeader->e_crlc); printf("e_cparhdr:%04X\n", pDosHeader->e_cparhdr); printf("e_minalloc:%04X\n", pDosHeader->e_minalloc); printf("e_maxalloc:%04X\n", pDosHeader->e_maxalloc); printf("e_ss:%04X\n", pDosHeader->e_ss); printf("e_sp:%04X\n", pDosHeader->e_sp); printf("e_csum:%04X\n", pDosHeader->e_csum); printf("e_ip:%04X\n", pDosHeader->e_ip); printf("e_cs:%04X\n", pDosHeader->e_cs); printf("e_lfarlc:%04X\n", pDosHeader->e_lfarlc); printf("e_ovno:%04X\n", pDosHeader->e_ovno); printf("e_res[4]:%016X\n", pDosHeader->e_res[1]); printf("e_oemid:%04X\n", pDosHeader->e_oemid); printf("e_oemid:%04X\n", pDosHeader->e_oeminfo); printf("e_res[10]:%020X\n", pDosHeader->e_res[1]); printf("e_lfanew:%08X\n", pDosHeader->e_lfanew); e_lfanew = pDosHeader->e_lfanew; pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pbFile + pDosHeader->e_lfanew); /*開始列印NT頭*/ puts("\n=================PE NT HEADER=================="); printf("Signature:%0X ", pNtHeader->Signature); //列印"PE"標誌 char arry_nt_Signature[sizeof(pNtHeader->Signature)]; memcpy(arry_nt_Signature, &pNtHeader->Signature, sizeof(pNtHeader->Signature)); for (int i = 0; i < sizeof(pNtHeader->Signature) && arry_nt_Signature[i] != '\0'; i++) { printf("%c", arry_nt_Signature[i]); } /*開始列印FILE頭*/ puts("\n\n=================PE FILE HEADER=================="); printf("Machine:%04X\n", pNtHeader->FileHeader.Machine); printf("NumberOfSections:%04X\n", pNtHeader->FileHeader.NumberOfSections); printf("TimeDateStamp:%08X\n", pNtHeader->FileHeader.TimeDateStamp); printf("PointerToSymbolTable:%08X\n", pNtHeader->FileHeader.PointerToSymbolTable); printf("NumberOfSymbols:%08X\n", pNtHeader->FileHeader.NumberOfSymbols); printf("SizeOfOptionalHeader:%04X\n", pNtHeader->FileHeader.SizeOfOptionalHeader); printf("Characteristics:%04X\n", pNtHeader->FileHeader.Characteristics); /*開始列印OPTIONAL頭*/ puts("\n=================PE OPTIONAL HEADER=================="); printf("Machine:%04X\n", pNtHeader->OptionalHeader.Magic); printf("MajorLinkerVersion:%02X\n", pNtHeader->OptionalHeader.MajorLinkerVersion); printf("MinorLinkerVersion:%02X\n", pNtHeader->OptionalHeader.MinorLinkerVersion); printf("SizeOfCode:%08X\n", pNtHeader->OptionalHeader.SizeOfCode); printf("SizeOfInitializedData:%08X\n", pNtHeader->OptionalHeader.SizeOfInitializedData); printf("SizeOfUninitializedData:%08X\n", pNtHeader->OptionalHeader.SizeOfUninitializedData); printf("AddressOfEntryPoint:%08X\n", pNtHeader->OptionalHeader.AddressOfEntryPoint); printf("BaseOfCode:%08X\n", pNtHeader->OptionalHeader.BaseOfCode); printf("BaseOfData:%08X\n", pNtHeader->OptionalHeader.BaseOfData); printf("ImageBase:%08X\n", pNtHeader->OptionalHeader.ImageBase); printf("SectionAlignment:%08X\n", pNtHeader->OptionalHeader.SectionAlignment); printf("FileAlignment:%08X\n", pNtHeader->OptionalHeader.FileAlignment); printf("MajorOperatingSystemVersion:%04X\n", pNtHeader->OptionalHeader.MajorOperatingSystemVersion); printf("MinorOperatingSystemVersion:%04X\n", pNtHeader->OptionalHeader.MinorOperatingSystemVersion); printf("MajorImageVersion:%04X\n", pNtHeader->OptionalHeader.MajorImageVersion); printf("MinorImageVersion:%04X\n", pNtHeader->OptionalHeader.MinorImageVersion); printf("MajorSubsystemVersion:%04X\n", pNtHeader->OptionalHeader.MajorSubsystemVersion); printf("MinorSubsystemVersion:%04X\n", pNtHeader->OptionalHeader.MinorSubsystemVersion); printf("Win32VersionValue:%08X\n", pNtHeader->OptionalHeader.Win32VersionValue); printf("SizeOfImage:%08X\n", pNtHeader->OptionalHeader.SizeOfImage); printf("SizeOfHeaders:%08X\n", pNtHeader->OptionalHeader.SizeOfHeaders); printf("CheckSum:%08X\n", pNtHeader->OptionalHeader.CheckSum); printf("Subsystem:%04X\n", pNtHeader->OptionalHeader.Subsystem); printf("DllCharacteristics:%04X\n", pNtHeader->OptionalHeader.DllCharacteristics); printf("SizeOfStackReserve:%08X\n", pNtHeader->OptionalHeader.SizeOfStackReserve); printf("SizeOfStackCommit:%08X\n", pNtHeader->OptionalHeader.SizeOfStackCommit); printf("SizeOfHeapReserve:%08X\n", pNtHeader->OptionalHeader.SizeOfHeapReserve); printf("SizeOfHeapCommit:%08X\n", pNtHeader->OptionalHeader.SizeOfHeapCommit); printf("LoaderFlags:%08X\n", pNtHeader->OptionalHeader.LoaderFlags); printf("NumberOfRvaAndSizes:%08X\n", pNtHeader->OptionalHeader.NumberOfRvaAndSizes); /*開始列印資料目錄表*/ puts("\n=================PE IMAGE_DATA_DIRECTORY HEADER=================="); pDataDirectory = &(pNtHeader->OptionalHeader.DataDirectory); printf("Table Name\t\tVirtualAddress\t\tSize\n\n"); printf("Export Table\t\t%08X\t\t%08X\n", pDataDirectory[0].VirtualAddress, pDataDirectory[0].Size); printf("Import Table\t\t%08X\t\t%08X\n", pDataDirectory[1].VirtualAddress, pDataDirectory[1].Size); printf("Resources Table\t\t%08X\t\t%08X\n", pDataDirectory[2].VirtualAddress, pDataDirectory[2].Size); printf("Exception Table\t\t%08X\t\t%08X\n", pDataDirectory[3].VirtualAddress, pDataDirectory[3].Size); printf("Security Table\t\t%08X\t\t%08X\n", pDataDirectory[4].VirtualAddress, pDataDirectory[4].Size); printf("Base relocation Table\t%08X\t\t%08X\n", pDataDirectory[5].VirtualAddress, pDataDirectory[5].Size); printf("Debug Table\t\t%08X\t\t%08X\n", pDataDirectory[6].VirtualAddress, pDataDirectory[6].Size); printf("Copyrught Table\t\t%08X\t\t%08X\n", pDataDirectory[7].VirtualAddress, pDataDirectory[7].Size); printf("Global Ptr Table\t%08X\t\t%08X\n", pDataDirectory[8].VirtualAddress, pDataDirectory[8].Size); printf("TLS Table\t\t%08X\t\t%08X\n", pDataDirectory[9].VirtualAddress, pDataDirectory[9].Size); printf("Load config Table\t%08X\t\t%08X\n", pDataDirectory[10].VirtualAddress, pDataDirectory[10].Size); printf("Bound Import Table\t%08X\t\t%08X\n", pDataDirectory[11].VirtualAddress, pDataDirectory[11].Size); printf("IAT Table\t\t%08X\t\t%08X\n", pDataDirectory[12].VirtualAddress, pDataDirectory[12].Size); printf("Delay Import Table\t%08X\t\t%08X\n", pDataDirectory[13].VirtualAddress, pDataDirectory[13].Size); printf("COM descriptor Table\t%08X\t\t%08X\n", pDataDirectory[14].VirtualAddress, pDataDirectory[14].Size); printf("Retention Table\t\t%08X\t\t%08X\n", pDataDirectory[15].VirtualAddress, pDataDirectory[15].Size); PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader); /*開始列印SECTION頭*/ puts("\n=================PE SECTION HEADER=================="); for (int count = 0; count < pNtHeader->FileHeader.NumberOfSections; count++) { //列印節區標誌 printf("\n----------------"); char arry_section_text[sizeof(pSectionHeader->Name)]; memcpy(arry_section_text, &pSectionHeader->Name, sizeof(pSectionHeader->Name)); for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++) { printf("%c", arry_section_text[i]); } printf("----------------\n"); printf("Name\t\t\t"); for (int i = 0; i < sizeof(pSectionHeader->Name) && arry_section_text[i] != '\0'; i++) { printf("%c", arry_section_text[i]); } //printf("=============%s", pSectionHeader->Name); printf("\nVirtualSize\t\t%08X\n", pSectionHeader->Misc.VirtualSize); printf("VirtualAddress\t\t%08X\n", pSectionHeader->VirtualAddress); printf("SizeOfRawData\t\t%08X\n", pSectionHeader->SizeOfRawData); printf("PointerToRawData\t%08X\n", pSectionHeader->PointerToRawData); printf("PointerToRelocation\t%08X\n", pSectionHeader->PointerToRelocations); printf("PointerToLinenumbers\t%08X\n", pSectionHeader->PointerToLinenumbers); printf("NumberOfRelocations\t%04X\n", pSectionHeader->NumberOfRelocations); printf("NumberOfLinenumbers\t%04X\n", pSectionHeader->NumberOfLinenumbers); printf("Characteristics\t\t%08X\n", pSectionHeader->Characteristics); pSectionHeader++; } ///*列印匯入表*/ puts("\n=======================================Import Table=================================\n"); DWORD Importe_table_offset = RvaToRwa(pNtHeader, (DWORD)pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); PIMAGE_IMPORT_DESCRIPTOR pImportDirectory = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pbFile + Importe_table_offset); DWORD Importe_table_offset_Name = (DWORD)pbFile + RvaToRwa(pNtHeader, pImportDirectory->Name); //printf("\n-------------------------%s----------------------------\n", Importe_table_offset_Name); //printf("%s", Importe_table_offset_Name); while (TRUE) { if (pImportDirectory->OriginalFirstThunk == 0 && pImportDirectory->TimeDateStamp == 0 && pImportDirectory->ForwarderChain == 0 && pImportDirectory->Name == 0 && pImportDirectory->FirstThunk == 0) { break; } DWORD Importe_table_offset_Name = (DWORD)pbFile + RvaToRwa(pNtHeader, pImportDirectory->Name); printf("\n-------------------------%s----------------------------\n", Importe_table_offset_Name); printf("\nTrunk Rva\tTrunk Rwa\tTrunk value\tHint\tFounction_Name/Founction_Num\n"); DWORD Importe_table_offset_OriginalFirstThunk = (DWORD)pbFile + RvaToRwa(pNtHeader, pImportDirectory->OriginalFirstThunk); DWORD * pTrunkData = (DWORD*)Importe_table_offset_OriginalFirstThunk; int n = 0; while (pTrunkData[n] != 0) { DWORD TrunkData = pTrunkData[n]; DWORD Trunk_RVA = pImportDirectory->OriginalFirstThunk; if (TrunkData < IMAGE_ORDINAL_FLAG32) { PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pbFile + RvaToRwa(pNtHeader, TrunkData)); printf("\n%08X\t%08X\t%08X\t%04X\t%s\n", Trunk_RVA, RvaToRwa(pNtHeader, Trunk_RVA), TrunkData, pImportByName->Hint, pImportByName->Name); } else { DWORD funum = (DWORD)(TrunkData - IMAGE_ORDINAL_FLAG32); printf("\n%08X\t%08X\t%08X\t——\t%d\n", Trunk_RVA, RvaToRwa(pNtHeader, Trunk_RVA), TrunkData, funum); //printf("fountion_num:%d", funum); } n++; (Trunk_RVA) += sizeof(Trunk_RVA); } pImportDirectory++; } /*列印匯出表*/ puts("\n=================================Export Table===========================\n"); DWORD Export_table_offset = RvaToRwa(pNtHeader, (DWORD)pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pbFile + Export_table_offset); DWORD EXport_table_offset_Name = (DWORD)pbFile + RvaToRwa(pNtHeader, pExportDirectory->Name); DWORD * pNameOfAddress =(DWORD *)((DWORD)pbFile + RvaToRwa(pNtHeader, pExportDirectory->AddressOfNames)); DWORD * pFunctionOfAdress = (DWORD *)((DWORD)pbFile + RvaToRwa(pNtHeader, pExportDirectory->AddressOfFunctions)); WORD * pNameOrdinalOfAddress = (WORD *)((DWORD)pbFile + RvaToRwa(pNtHeader, pExportDirectory->AddressOfNameOrdinals)); printf("Name:%s\n", EXport_table_offset_Name); printf("NameOfAddress:%08X\n", RvaToRwa(pNtHeader, pExportDirectory->AddressOfNames)); printf("FunctionOfAdress:%08X\n", RvaToRwa(pNtHeader, pExportDirectory->AddressOfFunctions)); printf("NameOrdinalOfAddress:%08X\n", RvaToRwa(pNtHeader, pExportDirectory->AddressOfNameOrdinals)); if (pExportDirectory->NumberOfFunctions == 0) { puts("!!!!!!!!!!!!!!!!!NO EXPORT!!!!!!!!!!!!!!!!!!!!!"); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } if (hMapping != NULL) { CloseHandle(hMapping); } if (pbFile != NULL) { UnmapViewOfFile(pbFile); } } printf("NumberOfNames:%d\n", pExportDirectory->NumberOfNames); printf("NumberOfFunctions:%d\n", pExportDirectory->NumberOfFunctions); puts("\n---------------------------------NAME EXPORT---------------------------------\n"); int NumberOfFounctions = (int)pExportDirectory->NumberOfFunctions; int * pIsFound = (int*)malloc(sizeof(int)*NumberOfFounctions); int k; for (k = 0; k < pExportDirectory->NumberOfFunctions; k++) { pIsFound[k] = 0; } printf("ExportNum\tName\t\t\tRva\n"); for (int i = 0; i < pExportDirectory->NumberOfNames; i++) { DWORD FunctionAddress = pFunctionOfAdress[pNameOrdinalOfAddress[i]]; DWORD FunName = (DWORD)pbFile + RvaToRwa(pNtHeader, pNameOfAddress[i]); pIsFound[pNameOrdinalOfAddress[i]] = 1; printf("%d\t\t%-10s\t\t%04X\t\t\n", pExportDirectory->Base + pNameOrdinalOfAddress[i], FunName, FunctionAddress); } if (pExportDirectory->NumberOfFunctions != pExportDirectory->NumberOfNames) { puts("\n--------------NUMBER EXPORT------------------\n"); printf("ExportNum\tName\t\t\tRva\n"); for (int m = 0; m < pExportDirectory->NumberOfFunctions; m++) { if (pIsFound[m] != 1) { DWORD FunctionAdress = pFunctionOfAdress[m]; printf("%d\t\t——%-10s\t\t%04X\t\t\n", pExportDirectory->Base + m, FunctionAdress); } } } else { printf("\nNO NUMBER EXPORT\n"); } free(pIsFound); /*列印重定位表*/ typedef struct _OFFSET_TYPE { WORD offset : 12; WORD type : 4; }OFFSET_TYPE,*POFFSET_TYPE; puts("\n=================================Base Relocation Table===========================\n"); DWORD RelocRva = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; if (!RelocRva) { printf("NOT FOUND Base Relocation Table"); return 0; } PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pbFile + RvaToRwa(pNtHeader, RelocRva)); while (pReloc->SizeOfBlock) { printf("\n--------------------------------------------------\n"); DWORD Count = (pReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); POFFSET_TYPE pOffset = (POFFSET_TYPE)(pReloc + 1); for (int i = 0; i < Count; ++i) { if (pOffset[i].type == 3) { DWORD RelocDataRva = pReloc->VirtualAddress + pOffset->offset; DWORD RelocDataFoa = (DWORD)((DWORD)pbFile + RvaToRwa(pNtHeader, RelocDataRva)); DWORD RealDataVA = *(DWORD*)RelocDataFoa; DWORD RealDataRva = RealDataVA - pNtHeader->OptionalHeader.ImageBase; DWORD RealDataFoa = (DWORD)(RvaToRwa(pNtHeader, RealDataRva) + (DWORD)pbFile); printf("需要重定位的第%d個數據 RVA:%0X FOA:%0X 改成:[%0X]\n", i + 1, RelocDataRva, RelocDataFoa, RealDataFoa); pOffset++; } } pReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pReloc + pReloc->SizeOfBlock); } if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } if (hMapping != NULL) { CloseHandle(hMapping); } if (pbFile != NULL) { UnmapViewOfFile(pbFile); } getchar(); return 0; } DWORD RvaToRwa(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva) { PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader); for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++) { //printf("%0x", pSectionHeader[i].VirtualAddress); DWORD SectionBeginRva = pSectionHeader[i].VirtualAddress; DWORD SectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData; //printf("%0x,%0x", SectionBeginRva, SectionEndRva); if (Rva >= SectionBeginRva && Rva <= SectionEndRva) { DWORD Temp = Rva - SectionBeginRva; DWORD Rwa = Temp + pSectionHeader[i].PointerToRawData; return Rwa; } } } /* DWORD RvaToName(PIMAGE_NT_HEADERS pNtHeader, DWORD Rva) { PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pNtHeader); for (int i = 0; i < pNtHeader->FileHeader.NumberOfSections; i++) { //printf("%0x", pSectionHeader[i].VirtualAddress); DWORD SectionBeginRva = pSectionHeader[i].VirtualAddress; DWORD SectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData; //printf("%0x,%0x", SectionBeginRva, SectionEndRva); if (Rva >= SectionBeginRva && Rva <= SectionEndRva) { //DWORD Temp = Rva - SectionBeginRva; //DWORD Rwa = Temp + pSectionHeader[i].PointerToRawData; return pSectionHeader[i].Name; } } } */ /* void HextoChar(char strHex[8]) { //char strHex[8]; char ch[8]; char str[2]; int i = 0, temp = 0, x = 0, str_num = 0, y; //long long answer = 0; for (i = 0; i<8 && strHex[i] != '\0'; i++) { if (i % 2 == 0) { switch (strHex[i]){ case 'A': temp = 10; break; case 'B': temp = 11; break; case 'C': temp = 12; break; case 'D': temp = 13; break; case 'E': temp = 14; break; case 'F': temp = 15; break; default: temp = strHex[i] - '0'; break; } ch[i] = (temp*pow(16, 1)); //printf("%d",ch[i]); } else { switch (strHex[i]) { case 'A': temp = 10; break; case 'B': temp = 11; break; case 'C': temp = 12; break; case 'D': temp = 13; break; case 'E': temp = 14; break; case 'F': temp = 15; break; default: temp = strHex[i] - '0'; break; } ch[i] = temp; //printf("%d",ch[i]); } } for (x = 0; x<8 && ch[x] != '\0'; x++, str_num++) { if (x % 2 == 0) { char temp_num = ch[x] + ch[x + 1]; //printf("%c",temp_num); str[str_num] = temp_num; //str_num++; //printf("%d",str[str_num]); } else{ continue; } } //printf("%d",str_num); for (y = 3; y>0; y--){ if (str[y - 1] != '\0'){ printf("%c", str[y - 1]); } else{ continue; } } } */