加载PE标头

基本上,我想要做的是找到PE文件的最后一部分。 我非常认真地阅读了PE规范,但我无法发现我的代码失败的地方。

PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer; PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)(pidh + pidh->e_lfanew); PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader; PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)(pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER)); 

buffer是包含加载的可执行文件的字节数组, pish是指向最后一部分的指针。 由于某种原因,似乎部门的数量超过20 000。

有任何想法吗 ? 提前致谢

我看到一个问题:e_lfanew是IMAGE_NT_HEADERS结构的偏移量,以字节为单位 。 您正在将此字节数添加到IMAGE_DOS_HEADER指针,因此您sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew字节向前移动。

固定版本:

 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer; PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE*)pidh + pidh->e_lfanew); PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader; PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader; PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((BYTE*)pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER)); 

调试此类问题的最佳方法是使用调试器进入代码并在内存中查看PE数据。 例如,您可以打开Visual Studiohex编辑器,查看所有字节数据以及实际读取的值。

以下是有关在VS 2010中查看程序内存的一些信息: http : //msdn.microsoft.com/en-us/library/s3aw423e.aspx

你只是以错误的方式去做。 我为你写了一些代码,希望它有所帮助。它可以显示PE文件最后一部分的数据。

 #include  #include  #include  void ShowHexData(BYTE *ptr,DWORD len) { int index = 0; int i = 0; const int width = 16; while(index + width < len) { int i; for(i = 0; i < width; ++i) { printf(" %02X",ptr[index + i]); } printf(" \t"); for(i = 0; i < width; ++i) { if(ptr[index + i] >= 0x20 && ptr[index + i] <= 0x7F) { putchar(ptr[index + i]); }else{ putchar('.'); } } index += width; putchar('\n'); } for(i = 0; index + i < len; ++ i) { printf(" %02X",ptr[index + i]); } while(i < width) { printf(" "); i += 1; } printf(" \t"); for(i = 0; index + i < len; ++ i) { if(ptr[index + i] >= 0x20 && ptr[index + i] <= 0x7F) { putchar(ptr[index + i]); }else{ putchar('.'); } } putchar('\n'); } int main(int argc, char *argv[]) { if(argc != 2) { printf("Usage : %s filename\n",argv[0]); return -1; }else{ FILE *fp = fopen(argv[1],"rb"); IMAGE_DOS_HEADER DosHeader = {0}; IMAGE_FILE_HEADER FileHeader = {0}; IMAGE_SECTION_HEADER SectionHeader = {0}; DWORD Signature = 0; DWORD RawPointerToPeHeader = 0, SizeOfFile = 0; DWORD SectionCount = 0; DWORD ByteCount = 0; BYTE *pData = NULL; if(!fp) { perror(""); return -1; } fseek(fp,0,SEEK_END); SizeOfFile = ftell(fp); if(SizeOfFile < sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS)) goto not_pe_file; fseek(fp,0,SEEK_SET); fread(&DosHeader,1,sizeof DosHeader,fp); if(DosHeader.e_magic != 'M' + 'Z' * 256) goto not_pe_file; RawPointerToPeHeader = DosHeader.e_lfanew; if(SizeOfFile <= RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS)) goto not_pe_file; fseek(fp,RawPointerToPeHeader,SEEK_SET); fread(&Signature,1,sizeof(DWORD),fp); if(Signature != 'P' + 'E' * 256) goto not_pe_file; fread(&FileHeader,1,sizeof FileHeader,fp); if(FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) goto not_pe_file; SectionCount = FileHeader.NumberOfSections; if(SectionCount == 0) { printf("No section for this file.\n"); fclose(fp); return -1; } if(SizeOfFile <= RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS) + SectionCount * sizeof(IMAGE_SECTION_HEADER)) goto not_pe_file; fseek(fp, RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS) + (SectionCount - 1) * sizeof(IMAGE_SECTION_HEADER), SEEK_SET); fread(&SectionHeader,1,sizeof SectionHeader,fp); ByteCount = SectionHeader.Misc.VirtualSize < SectionHeader.PointerToRawData ? SectionHeader.Misc.VirtualSize : SectionHeader.PointerToRawData; if(ByteCount == 0) { printf("No data to read for target section.\n"); fclose(fp); return -1; }else if(ByteCount + SectionHeader.PointerToRawData > SizeOfFile) { printf("Bad section data.\n"); fclose(fp); return -1; } fseek(fp,SectionHeader.PointerToRawData,SEEK_SET); pData = (BYTE*)malloc(ByteCount); fread(pData,1,ByteCount,fp); ShowHexData(pData,ByteCount); free(pData); fclose(fp); return 0; not_pe_file: printf("Not a PE file.\n"); fclose(fp); return -1; } return 0; } 

简而言之,在根据文件头分析数据之前,您不知道数据的位置。

各种部分地址和数据也可以通过以下方式获得:

 #include #include int main() { LPCSTR fileName="inputFile.exe"; HANDLE hFile; HANDLE hFileMapping; LPVOID lpFileBase; PIMAGE_DOS_HEADER dosHeader; PIMAGE_NT_HEADERS peHeader; PIMAGE_SECTION_HEADER sectionHeader; hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hFile==INVALID_HANDLE_VALUE) { std::cout<<"\n CreateFile failed \n"; return 1; } hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL); if(hFileMapping==0) { std::cout<<"\n CreateFileMapping failed \n"; CloseHandle(hFile); return 1; } lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0); if(lpFileBase==0) { std::cout<<"\n MapViewOfFile failed \n"; CloseHandle(hFileMapping); CloseHandle(hFile); return 1; } dosHeader = (PIMAGE_DOS_HEADER) lpFileBase; if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE) { std::cout<<"\n DOS Signature (MZ) Matched \n"; peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew); if(peHeader->Signature==IMAGE_NT_SIGNATURE) { std::cout<<"\n PE Signature (PE) Matched \n"; sectionHeader = IMAGE_FIRST_SECTION(peHeader); UINT nSectionCount = peHeader->FileHeader.NumberOfSections; //No of Sections std::cout<<"\n No of Sections : "<Name<<" \n"; //address can be obtained as (PBYTE)lpFileBase+sectionHeader->PointerToRawData std::cout<<"\n Size of section data : "<Misc.VirtualSize<<" \n"; std::cout<<"\n-----------------------------------------------\n"; } //Now sectionHeader will have pointer to last section //if you add sectionHeader++ in for loop instead of ++sectionHeader it will point to memory after last section } else { return 1; } } else { return 1; } return 0; }