Básicamente, lo que intento hacer es encontrar la última sección del archivo PE. He leído la especificación PE con mucha atención, pero no puedo descubrir dónde falla mi código.
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
es una matriz de bytes que contiene ejecutable cargado, y pish
es un puntero a la última sección. Por alguna razón, parece que el número de secciones supera las 20 000.
Algunas ideas ? Gracias por adelantado

jowo
Hay un problema que veo de improviso: e_lfanew es el desplazamiento del IMAGE_NT_HEADERS
estructura en bytes. Está agregando este número de bytes a un IMAGE_DOS_HEADER
puntero, por lo que se está moviendo hacia adelante sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew
bytes
Versión fija:
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));
La mejor manera de depurar problemas como este es acceder al código con su depurador y ver los datos PE usted mismo en la memoria. Puede abrir el editor hexadecimal de Visual Studio, por ejemplo, y ver todos los datos de bytes y qué valores está leyendo en realidad.
Aquí hay información sobre cómo ver la memoria del programa en VS 2010:
http://msdn.microsoft.com/en-us/library/s3aw423e.aspx
Varias direcciones de sección y datos también se pueden obtener de la siguiente manera:
#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;
}
Simplemente lo haces de la manera incorrecta. Escribí un código para ti, espero que te ayude. Puede mostrar los datos de la última sección de un archivo PE.
#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;
}
En resumen, no sabe dónde están los datos hasta que los analiza de acuerdo con el encabezado del archivo.
puntero de secciones:
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); // definición en winnt.h
o
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((BYTE*)pioh + pifh->SizeOfOptionalHeader);
el puntero de la última sección es:
PIMAGE_SECTION_HEADER pilsh = &pish[pifh->NumberOfSections-1]
“No puedo descubrir dónde falla mi código”. – ¿Cómo falla?
– Trigo Mitch
9 de enero de 2012 a las 0:40
Como dije, el número de secciones supera los 20k. Por lo tanto, al desreferenciar a miembros de
pish
el programa falla.– Kijan
9 de enero de 2012 a las 0:44