[C] PEFileSize function

Iniciado por The Swash, 25 Enero 2011, 05:58 AM

0 Miembros y 1 Visitante están viendo este tema.

The Swash

/*
   [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!

Khronos14


BlackZeroX

#2
.
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!¡.
.
The Dark Shadow is my passion.

[Zero]

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

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

The Swash

Muchas gracias por la información [Zero].