Loading PE Headers
Solution 1:
There is one problem I see off hand: e_lfanew is the offset to the IMAGE_NT_HEADERS
structure in bytes. You are adding this number of bytes to a IMAGE_DOS_HEADER
pointer, so you are moving forward by sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew
bytes.
Fixed version:
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));
The best way to debug problems like this is to drop into the code with your debugger and view the PE data yourself in memory. You can open up the Visual Studio hex editor for example and see all of the byte data, and which values you are actually reading out.
Here's some information on viewing program memory in VS 2010: http://msdn.microsoft.com/en-us/library/s3aw423e.aspx
Solution 2:
Various section address and data can be obtained by below way also :
#include<windows.h>
#include<iostream>
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 : "<<nSectionCount<<" \n";
//sectionHeader contains pointer to first section
//sectionHeader++ will move to next section
for( UINT i=0; i<nSectionCount; ++i, ++sectionHeader )
{
std::cout<<"\n-----------------------------------------------\n";
std::cout<<"\n Section Name : "<<sectionHeader->Name<<" \n";
//address can be obtained as (PBYTE)lpFileBase+sectionHeader->PointerToRawData
std::cout<<"\n Size of section data : "<<sectionHeader->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;
}
Solution 3:
You just do it the wrong way. I wrote some code for you, hope it helps.It can show the data of the last section of a PE file.
#include <stdio.h>
#include <malloc.h>
#include <windows.h>
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;
}
In short, you do not know where the data is, until you analyze the data according to the file header.