/*
[Get size of file to base of PE]
- Programmer: The Swash
- Dedicated: Zero, Thor Psymera, Steve10120
*/
#include <windows.h>
#include <stdio.h>
#define RB "rb"
int PEFileSize(char * fPath);
int main(void)
{
printf("File size: %i", PEFileSize("C:\\test.exe"));
getchar();
}
int PEFileSize(char * fPath)
{
IMAGE_DOS_HEADER IDH;
IMAGE_NT_HEADERS INH;
IMAGE_SECTION_HEADER ISH;
FILE * lpFile;
int sTemp = 0, i;
lpFile = fopen(fPath,RB);
if (lpFile != NULL)
{
fseek(lpFile, 0, SEEK_SET); // Seek to begin of file
fread(&IDH, sizeof(IDH), 1, lpFile); // Read 64 bytes to IDH struct
if (IDH.e_magic == IMAGE_DOS_SIGNATURE) // If IDH.e_magic = (MZ)
{
fseek(lpFile, IDH.e_lfanew, SEEK_SET); // Seek in file in begin of NT Headers (PE)
fread(&INH, sizeof(INH), 1, lpFile); // Read in structure 248 bytes
if (INH.Signature == IMAGE_NT_SIGNATURE) // If INH.Signature = (PE)
{
for (i = 0; i < INH.FileHeader.NumberOfSections; i++) // go for all sections
{
fseek(lpFile, IDH.e_lfanew + sizeof(INH) + sizeof(ISH)*i, SEEK_SET); // Seek in actual section
fread(&ISH, sizeof(ISH), 1, lpFile); // Read section
sTemp += ISH.SizeOfRawData; // Save sizeofrawdata of section
}
sTemp += INH.OptionalHeader.SizeOfHeaders;
fclose(lpFile);
return sTemp;
}
}
else
{
return -1;
}
}
else
{
return -1;
}
}
Que tál mis amigos, bueno estudiando el formato PE digamos que se me paso esta idea por la cabeza y no era tan dificil, lo que hace el código es obtener el tamaño original del archivo generado por el tamaño de las secciones del ejecutable + su cabecera.
Espero les sea de utilidad!
Muy buena la función The Swash, aquí tienes la versión en Delphi:
http://foro.elhacker.net/programacion_general/delphi_pefilesize_function-t317791.0.html
Saludos.
.
Viendo el codigo de The Swash re-arme el codigo de una forma mas limpia y evitando errores a toda costa, inclusive ante los archivos incompletos mas que nada, o que los imiten de alguna manera, pero no al 100%.
unsigned long long GetPeSize(const char *fPath)
/** Retorna el Byte donde termina TODOS los bytes de un Ejecutable en formato PE **/
{ /* By BlackZerox ( http://Infrangelux.sytes.net/ ) */
IMAGE_DOS_HEADER v_idh;
IMAGE_NT_HEADERS v_inh;
IMAGE_SECTION_HEADER v_ish;
FILE *v_pFile;
unsigned long long v_ullTemp = 0;
if ( (v_pFile = fopen(fPath,"r")) != NULL)
{
fseek(v_pFile, 0, SEEK_SET);
if ( fread(&v_idh, 1, sizeof(IMAGE_DOS_HEADER) , v_pFile) == sizeof(IMAGE_DOS_HEADER ))/* ¿leimos lo desedo? [se evitan errores estupidos]*/
if (v_idh.e_magic == IMAGE_DOS_SIGNATURE)/* ¿Es PEFormat? */
if ( fseek(v_pFile, v_idh.e_lfanew, SEEK_SET) == 0 )/* [se evitan errores estupidos] */
if ( fread(&v_inh, 1 , sizeof(IMAGE_NT_HEADERS), v_pFile) == sizeof(IMAGE_NT_HEADERS) )/* ¿leimos lo desedo? [se evitan errores estupidos] */
if (v_inh.Signature == IMAGE_NT_SIGNATURE)/* ¿Es PEFormat? */
if ( v_inh.FileHeader.NumberOfSections > 0 )/* [se evitan errores estupidos] */
v_ullTemp = v_idh.e_lfanew + sizeof(IMAGE_NT_HEADERS) + ((v_inh.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER));
if ( fseek(v_pFile, v_ullTemp , SEEK_SET) == 0 )/* [se evitan errores estupidos] */
if ( sizeof(IMAGE_SECTION_HEADER) == fread(&v_ish, 1 , sizeof(IMAGE_SECTION_HEADER) , v_pFile))/* ¿leimos lo desedo? [se evitan errores estupidos] */
v_ullTemp = v_ish.SizeOfRawData + v_ish.PointerToRawData;
fclose(v_pFile);
}
return v_ullTemp;
}
O para quien no entienda aqui esta otro ( Es como a mi me gusta mas, aun que el de arriba esta mas limpio )
unsigned long long GetPeSize(const char *fPath)
/** Retorna el Byte donde termina TODOS los bytes de un Ejecutable en formato PE **/
{ /* By BlackZerox ( http://Infrangelux.sytes.net/ ) */
IMAGE_DOS_HEADER v_idh;
IMAGE_NT_HEADERS v_inh;
IMAGE_SECTION_HEADER v_ish;
FILE *v_pFile;
unsigned long long v_ullTemp = 0;
if ( (v_pFile = fopen(fPath,"r")) != NULL)
{
fseek(v_pFile, 0, SEEK_SET);
if ( fread(&v_idh, 1, sizeof(IMAGE_DOS_HEADER) , v_pFile) == sizeof(IMAGE_DOS_HEADER ))
{/* ¿leimos lo desedo? [se evitan errores estupidos]*/
if (v_idh.e_magic == IMAGE_DOS_SIGNATURE)
{/* ¿Es PEFormat? */
if ( fseek(v_pFile, v_idh.e_lfanew, SEEK_SET) == 0 )
{/* [se evitan errores estupidos] */
if ( fread(&v_inh, 1 , sizeof(IMAGE_NT_HEADERS), v_pFile) == sizeof(IMAGE_NT_HEADERS) )
{/* ¿leimos lo desedo? [se evitan errores estupidos] */
if (v_inh.Signature == IMAGE_NT_SIGNATURE)
{/* ¿Es PEFormat? */
if ( v_inh.FileHeader.NumberOfSections > 0 )
{/* [se evitan errores estupidos] */
v_ullTemp = v_idh.e_lfanew + sizeof(IMAGE_NT_HEADERS) + ((v_inh.FileHeader.NumberOfSections-1)*sizeof(IMAGE_SECTION_HEADER));
if ( fseek(v_pFile, v_ullTemp , SEEK_SET) == 0 )
{/* [se evitan errores estupidos] */
if ( sizeof(IMAGE_SECTION_HEADER) == fread(&v_ish, 1 , sizeof(IMAGE_SECTION_HEADER) , v_pFile))
{/* ¿leimos lo desedo? [se evitan errores estupidos] */
v_ullTemp = v_ish.SizeOfRawData + v_ish.PointerToRawData;
}
}
}
}
}
}
}
}
fclose(v_pFile);
}
return v_ullTemp;
}
P.D.: The Swash estas usando mal fread() no?...
Temibles lunas!¡.
.
Ambos tenéis un error que también está en todos mis códigos y que me corrigieron en un foro. No es buena idea usar sizeof(IMAGE_NT_HEADERS) para llegar a la tabla de secciones, pues el tamaño de INH no es fijo, depende del tamaño de IMAGE_OPTIONAL_HEADER y a su vez éste depende del número de directorios. También es cierto que en el 99,99% de los ejecutables el tamaño será igual al de la estructura definida en <windows.h>, pero no tiene por qué :P.
Saludos
Muchas gracias por la información [Zero].