[C]Resource Dumper.

Iniciado por The Swash, 31 Mayo 2012, 21:48 PM

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

The Swash



Hola,

Hoy les vengo a traer una aplicación que programé y lo que en realidad hace es extraer todos los recursos de un ejecutable. Más que por su utilidad seguro pueden entender como funciona el directorio de recursos de un archivo ejecutable.
No utilizo ninguna función API de recursos proporcionada por Windows, todo está hecho a mano.

Un saludo,
Iván Portilla.

Actualizado 22 de junio de 2012, ahora soporta parámetros en su función principal y tiene corregidos errores de manejo de memoria y está mucho más optimizado.

/**************************************************
* Resource Dumper v0.1 .
* Programado por Iván Portilla.
* Actualizado 22 de junio de 2012
* http://www.h-sec.org & http://www.elhacker.net
**************************************************/

#include <stdio.h>
#include <windows.h>
#include <Strsafe.h>
#define STATIC_SIZE 0x20

void GetResources(PBYTE MappedFile, DWORD ResourceRVA, PCHAR Path, PIMAGE_SECTION_HEADER ish, DWORD NumberOfSections);
int RVA_TO_OFFSET(int RVA, PIMAGE_SECTION_HEADER ish, int NumberOfSections);
int RESOURCE_DUMP(PCHAR lFile, PCHAR MappedName, PCHAR DumpPath);
int RESOURCE_TO_FILE(PCHAR Path, PBYTE ResourceRVA, DWORD Size);
PCHAR ResourceType(DWORD ResType);
PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String);

typedef BOOL (WINAPI * _PathIsDirectory)(PCHAR Directory);
typedef BOOL (WINAPI * _PathFileExists)(PCHAR Directory);

char STR_ID[STATIC_SIZE];
char STR_ID2[STATIC_SIZE];
char STR_ID3[STATIC_SIZE];
char STR_ID4[STATIC_SIZE];
char * RESOURCES[25] = {"RT_CURSOR","RT_BITMAP","RT_ICON","RT_MENU","RT_DIALOG",
                        "RT_STRING","RT_FONTDIR","RT_FONT","RT_ACCELERATOR","RT_RCDATA",
                        "RT_MESSAGETABLE","RT_GROUP_CURSOR","","GROUP_ICON","","RT_VERSION",
                        "RT_DLGINCLUDE","","RT_PLUGPLAY","RT_VXD","RT_ANICURSOR","RT_ANIICON",
                        "RT_HTML","RT_MANIFEST","UNKNOWN"};

int main(int argc, char * argv[])
{
    _PathIsDirectory PathIsDirectoryA = (_PathIsDirectory)GetProcAddress(LoadLibraryA("Shlwapi.dll"), "PathIsDirectoryA");
    _PathFileExists PathFileExistsA = (_PathFileExists)GetProcAddress(LoadLibraryA("Shlwapi.dll"), "PathFileExistsA");;

    printf("####  ####\n");
    printf("#  #  #   #\n");
    printf("# #   #    #\n");
    printf("##    #    #\n");
    printf("# #   #   #\n");
    printf("#  #  ####\n\n");
    printf("Resource Dumper Base Model v0.1\n\n");

    if ((PathFileExistsA != NULL) && (PathIsDirectoryA != NULL))
    {
        if (argc == 4)
        {
            if ((PathFileExistsA(argv[1]) == 1) && (PathIsDirectoryA(argv[3])) && (argv[2] != NULL))
            {
                RESOURCE_DUMP(argv[1], argv[2], argv[3]);
            }
            else
                printf("Check your parameters [File path, File Mapped Name, Path To Save Resources] (ALL STRINGS)");
        }
        else
            printf("This software should be execute with params [File path, File Mapped Name, Path To Save Resources] (ALL STRINGS)");
    }
    else
        printf("Fail to load API functions of shlwapi.dll.");
    getchar();
    return 0;
}

int RESOURCE_DUMP(PCHAR iFile, PCHAR MappedName, PCHAR DumpPath)
{
    HANDLE lFile, lMap;
    PBYTE Mapped;
    PIMAGE_DOS_HEADER IDH;
    PIMAGE_NT_HEADERS INH;
    DWORD Resource;

    lFile = CreateFileA(iFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,0,0);
    if (lFile != INVALID_HANDLE_VALUE)
    {
        lMap = CreateFileMappingA(lFile, NULL, PAGE_READONLY, 0, 0, MappedName);
        Mapped = (PBYTE)MapViewOfFile(lMap, FILE_MAP_READ, 0, 0, 0);
        IDH = (PIMAGE_DOS_HEADER)Mapped;
        if (IDH->e_magic == IMAGE_DOS_SIGNATURE)
        {
            INH = (PIMAGE_NT_HEADERS)&Mapped[IDH->e_lfanew];
            if(INH->Signature == IMAGE_NT_SIGNATURE)
            {
                Resource = INH->OptionalHeader.DataDirectory[2].VirtualAddress;
                if (Resource > 0)
                {
                    printf("Getting resources..\n");
                    GetResources(Mapped, Resource, DumpPath,(PIMAGE_SECTION_HEADER)&Mapped[IDH->e_lfanew + 24 + INH->FileHeader.SizeOfOptionalHeader], INH->FileHeader.NumberOfSections);
                }
                else
                    printf("Resource directory not present\n");
            }

        }
        UnmapViewOfFile(Mapped);
        CloseHandle(lMap);
        CloseHandle(lFile);

    }
    else
    {
        return -1;
    }

    return 0;
}

void GetResources(PBYTE MappedFile, DWORD ResourceRVA, PCHAR Path, PIMAGE_SECTION_HEADER ish, DWORD NumberOfSections)
{
    PIMAGE_RESOURCE_DIRECTORY IRD, SUBIRD, SSUBIRD;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY IRDRE, SUBIRDRE, SSUBIRDRE;
    PIMAGE_RESOURCE_DATA_ENTRY IRDTE;
    PIMAGE_RESOURCE_DIR_STRING_U IRDS;
    DWORD NumberOfEntries, NumberOfSubEntries, NumberOfSSubEntries, Counter = 0, Tick = 0, lBytes = 0;
    PCHAR UNICODE_STR_PARSED = NULL;
    PCHAR RES_TYPE = NULL;

    Tick = GetTickCount();
    IRD = (PIMAGE_RESOURCE_DIRECTORY) &MappedFile[RVA_TO_OFFSET(ResourceRVA, ish, NumberOfSections)];
    NumberOfEntries = (IRD->NumberOfNamedEntries + IRD->NumberOfIdEntries);
    IRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)IRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
    printf("[Root resource directory entries: %X]\n\n", NumberOfEntries);
    while(NumberOfEntries > 0)
    {
        if (IRDRE->DataIsDirectory == 1)
        {
            SecureZeroMemory(STR_ID3, STATIC_SIZE);
            if (IRDRE->NameIsString == 0)
            {
                RES_TYPE = RESOURCES[(IRDRE->Id)-1];
                printf("  [Resource type: %s]\n", RES_TYPE);
                StringCchCopyA(STR_ID3, STATIC_SIZE, RES_TYPE);
                StringCchCatA(STR_ID3, STATIC_SIZE, "_");
            }
            else
            {
                IRDS = (PIMAGE_RESOURCE_DIR_STRING_U) (IRDRE->NameOffset + (int)IRD);
                UNICODE_STR_PARSED = UNICODE_TO_STRING(IRDS);
                printf("  [Resource type: %s]\n", UNICODE_STR_PARSED);
                StringCchCopyA(STR_ID3, STATIC_SIZE, UNICODE_TO_STRING(IRDS));
                StringCchCatA(STR_ID3, STATIC_SIZE, "_");
                GlobalFree(UNICODE_STR_PARSED);
            }
            SUBIRD = (PIMAGE_RESOURCE_DIRECTORY) ((int)IRD + IRDRE->OffsetToDirectory);
            NumberOfSubEntries = SUBIRD->NumberOfNamedEntries + SUBIRD->NumberOfIdEntries;
            SUBIRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)SUBIRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
            printf("    [Number of sub entries: %x]\n", NumberOfSubEntries);
            while(NumberOfSubEntries > 0)
            {
                if(SUBIRDRE->DataIsDirectory == 1)
                {
                    printf("      [Resource Id: %i]\n", SUBIRDRE->Id);
                    SSUBIRD = (PIMAGE_RESOURCE_DIRECTORY) ((int)IRD + SUBIRDRE->OffsetToDirectory);
                    NumberOfSSubEntries = SSUBIRD->NumberOfNamedEntries + SSUBIRD->NumberOfIdEntries;
                    SSUBIRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)SSUBIRD + sizeof(IMAGE_RESOURCE_DIRECTORY));
                    printf("      [Number of re-sub entries: %x]\n", NumberOfSSubEntries);
                    while(NumberOfSSubEntries > 0)
                    {
                        IRDTE = (PIMAGE_RESOURCE_DATA_ENTRY) ((int)IRD +SSUBIRDRE->OffsetToData);
                        printf("        [RVA: 0x%X Size: 0x%X]\n", IRDTE->OffsetToData, IRDTE->Size);

                        SecureZeroMemory(STR_ID, STATIC_SIZE);
                        SecureZeroMemory(STR_ID2, STATIC_SIZE);
                        SecureZeroMemory(STR_ID4, STATIC_SIZE);

                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID3);
                        _itoa(SUBIRDRE->Id, STR_ID, 10);
                        StringCchCatA(STR_ID, STATIC_SIZE, "_");
                        _itoa(SSUBIRDRE->Id, STR_ID2, 10);
                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID);
                        StringCchCatA(STR_ID4, STATIC_SIZE, STR_ID2);
                        RESOURCE_TO_FILE(Path, (PBYTE)((int)MappedFile + RVA_TO_OFFSET(IRDTE->OffsetToData, ish, NumberOfSections)), IRDTE->Size);
                        NumberOfSSubEntries = NumberOfSSubEntries - 1;
                        SSUBIRDRE++;
                        Counter++;
                        lBytes += IRDTE->Size;
                    }
                }
                NumberOfSubEntries = NumberOfSubEntries - 1;
                SUBIRDRE++;
            }
        }
        NumberOfEntries = NumberOfEntries - 1;
        IRDRE++;
    }
    printf("\nResources dumped: 0x%X.", Counter);
    printf("\nTime of dumped: %i miliseconds.", (GetTickCount()-Tick));
    printf("\nBytes dumped: 0x%X.", lBytes);
}

int RVA_TO_OFFSET(int RVA, PIMAGE_SECTION_HEADER ISH, int NumberOfSections)
{
    int i, Offset = 0;
    if (ISH != NULL)
    {
        for (i = 0; i < NumberOfSections; i++)
        {
            if ((RVA >= (int)ISH[i].VirtualAddress) && (RVA <= (int)(ISH[i].VirtualAddress + ISH[i].Misc.VirtualSize)))
            {
                    Offset = (RVA - ISH[i].VirtualAddress) + ISH[i].PointerToRawData;
            }
        }
    }
    else
        Offset = 0;

    return Offset;
}

PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String)
{
    PCHAR nStr = (PCHAR) GlobalAlloc(GPTR, String->Length + 1);;
    WideCharToMultiByte(CP_ACP, 0, String->NameString, String->Length * 2, nStr, String->Length, NULL, NULL);
    return nStr;
}

int RESOURCE_TO_FILE(PCHAR Path, PBYTE ResourceRVA, DWORD Size)
{
    PCHAR lFile = (PCHAR)GlobalAlloc(GPTR, lstrlenA(Path) + STATIC_SIZE);
    PCHAR Buffer = (PCHAR)GlobalAlloc(GPTR, Size);
    HANDLE sFile;
    DWORD Bytes = 0, Rest;

    CopyMemory(Buffer, ResourceRVA, Size);
    StringCchCopyA(lFile, lstrlenA(Path) + STATIC_SIZE, Path);
    if ((Path[lstrlenA(Path)-2] == 92) & (Path[lstrlenA(Path)-1] == 92))
        StringCchCopyA(&lFile[lstrlenA(Path)], lstrlenA(Path) + STATIC_SIZE, STR_ID4);
    else
    {
        lFile[lstrlenA(Path)+1] = 92;
        lFile[lstrlenA(Path)] = 92;
        StringCchCopyA(&lFile[lstrlenA(Path)+2], lstrlenA(Path) + STATIC_SIZE, STR_ID4);
    }
    sFile = CreateFileA(lFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
    if (sFile != INVALID_HANDLE_VALUE)
    {
        WriteFile(sFile, Buffer, Size, &Bytes, NULL);
        CloseHandle(sFile);
        Rest = 0;
    }
    else
        Rest = -1;

    GlobalFree(Buffer);
    GlobalFree(lFile);
    return Rest;
}

Иōҳ

Gracias por compartir :D

Saludos,
Nox.
Eres adicto a la Ing. Inversa? -> www.noxsoft.net

x64core

gracias The Swash :) yo voy a leer de otro momento y os cuento  :)

0xDani

Y por que se incluye windows.h?
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

The Swash

Hola,

@daniyo, se incluye <windows.h> porque este tienes declaradas las estructuras de recursos que empleamos y el API que necesitamos para trabajar con ficheros mapeados en memoria. No te confundas, dije claramente "No utilizo API de recursos".

Un saludo,
Iván Portilla.

0xDani

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

karmany

Muy buen trabajo y gracias por compartir.
¡Te has metido de lleno a estudiar el PE header! Excelente.

Dryken

Wow!! Menudo trabajo para hacer esto, te habrá llevado mucho tiempo compañero.

Luego lo compilo a ver que tal va, aunque de primera tiene muy buena pinta  ;)
Lo intentas y fracasas, lo intentas y fracasas pero fracasas realmente cuando dejas de intentarlo.

Calc Don v0.7 - C
http://foro.elhacker.net/programacion_cc/source_calculadora_calc_don_10-t366489.0.html

Hundir la flota v0.3 - C#
http://foro.elhacker.net/net/source_c_juego_hundir_la_flota_v01-t377794.0.html