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.
Código: Seleccionar todo
/**************************************************
* Resource Dumper.
* Programado por Iván Portilla.
* 31 de mayo de 2012
* http://www.h-sec.org & http://www.elhacker.net
**************************************************/
#include <stdio.h>
#include <windows.h>
#define MediumSize 0x20
#define BasicSize 0x10
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 Id);
PCHAR ResourceType(DWORD ResType);
PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String);
int main()
{
/*RESOURCE_DUMP("C:\\xd.exe", "PE_LOADED", "C:\\Test\\");*/
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");
printf("###############################################\n\n");
GetResources(Mapped, Resource, DumpPath,(PIMAGE_SECTION_HEADER)&Mapped[IDH->e_lfanew + 24 + INH->FileHeader.SizeOfOptionalHeader], INH->FileHeader.NumberOfSections);
printf("###############################################\n\n");
printf("Resources Dumped (:");
}
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;
PCHAR STR_ID = (PCHAR)GlobalAlloc(GPTR, BasicSize);
PCHAR STR_ID2 = (PCHAR)GlobalAlloc(GPTR, BasicSize);
PCHAR STR_ID3 = (PCHAR)GlobalAlloc(GPTR, BasicSize);
PCHAR STR_ID4 = (PCHAR)GlobalAlloc(GPTR, MediumSize);
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 Number Of Entries: %x \n", NumberOfEntries);
while(NumberOfEntries > 0)
{
if (IRDRE->DataIsDirectory == 1)
{
SecureZeroMemory(STR_ID3, BasicSize);
if (IRDRE->NameIsString == 0)
{
printf(" Type: %s\n", ResourceType(IRDRE->Id));
strncpy(STR_ID3, ResourceType(IRDRE->Id), strlen(ResourceType(IRDRE->Id)) );
lstrcatA(STR_ID3, "_");
}
else
{
IRDS = (PIMAGE_RESOURCE_DIR_STRING_U) (IRDRE->NameOffset + (int)IRD);
printf(" Type: %s\n", UNICODE_TO_STRING(IRDS));
strncpy(STR_ID3, UNICODE_TO_STRING(IRDS), strlen(UNICODE_TO_STRING(IRDS)) );
lstrcatA(STR_ID3, "_");
}
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(" 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 SSub Entries: %x \n", NumberOfSSubEntries);
while(NumberOfSSubEntries > 0)
{
IRDTE = (PIMAGE_RESOURCE_DATA_ENTRY) ((int)IRD +SSUBIRDRE->OffsetToData);
printf(" RVA:%x Size:%x \n", IRDTE->OffsetToData, IRDTE->Size);
SecureZeroMemory(STR_ID, BasicSize);
SecureZeroMemory(STR_ID2, BasicSize);
SecureZeroMemory(STR_ID4, MediumSize);
lstrcatA(STR_ID4, STR_ID3);
itoa(SUBIRDRE->Id, STR_ID, 10);
lstrcatA(STR_ID, "_");
itoa(SSUBIRDRE->Id, STR_ID2, 10);
lstrcatA(STR_ID4, STR_ID);
lstrcatA(STR_ID4, STR_ID2);
RESOURCE_TO_FILE(Path, (PBYTE)((int)MappedFile + RVA_TO_OFFSET(IRDTE->OffsetToData, ish, NumberOfSections)), IRDTE->Size, STR_ID4);
NumberOfSSubEntries = NumberOfSSubEntries - 1;
SSUBIRDRE++;
}
}
NumberOfSubEntries = NumberOfSubEntries - 1;
SUBIRDRE++;
}
}
NumberOfEntries = NumberOfEntries - 1;
IRDRE++;
}
GlobalFree(STR_ID);
GlobalFree(STR_ID2);
}
int RVA_TO_OFFSET(int RVA, PIMAGE_SECTION_HEADER ish, int NumberOfSections)
{
int i, n = 0, Offset = 0;
for (i = 0; i < NumberOfSections; i++)
{
n = (ish[i].VirtualAddress + ish[i].SizeOfRawData)-RVA;
if (n > 0)
{
Offset =((RVA - ish[i].VirtualAddress) + ish[i].PointerToRawData);
break;
}
}
return Offset;
}
PCHAR UNICODE_TO_STRING(PIMAGE_RESOURCE_DIR_STRING_U String)
{
PCHAR NewString;
DWORD i;
NewString = (PCHAR) GlobalAlloc(GPTR, String->Length + 1);
for (i = 0; i < String->Length; i++)
{
NewString[i] = String->NameString[i];
}
return NewString;
}
int RESOURCE_TO_FILE(PCHAR Path, PBYTE ResourceRVA, DWORD Size, PCHAR Id)
{
PCHAR lFile = (PCHAR)GlobalAlloc(GPTR, strlen(Path) + MediumSize);
PCHAR Buffer = (PCHAR)GlobalAlloc(GPTR, Size);
HANDLE sFile;
DWORD Bytes = 0;
CopyMemory(Buffer, ResourceRVA, Size);
strncpy(lFile, Path, strlen(Path));
if ((Path[strlen(Path)-2] == 92) & (Path[strlen(Path)-1] == 92))
strncpy(&lFile[strlen(Path)], Id, strlen(Id));
else
{
lFile[strlen(Path)+1] = 92;
lFile[strlen(Path)] = 92;
strncpy(&lFile[strlen(Path)+2], Id, strlen(Id));
}
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);
GlobalFree(Buffer);
}
else
return -1;
return 0;
}
PCHAR ResourceType(DWORD ResType)
{
PCHAR Res = (PCHAR)GlobalAlloc(GPTR, BasicSize);
switch(ResType)
{
case 1:
lstrcpyA(Res, "RT_CURSOR");
break;
case 2:
lstrcpyA(Res, "RT_BITMAP");
break;
case 3:
lstrcpyA(Res, "RT_ICON");
break;
case 4:
lstrcpyA(Res, "RT_MENU");
break;
case 5:
lstrcpyA(Res, "RT_DIALOG");
break;
case 6:
lstrcpyA(Res, "RT_STRING");
break;
case 7:
lstrcpyA(Res, "RT_FONTDIR");
break;
case 8:
lstrcpyA(Res, "RT_FONT");
break;
case 9:
lstrcpyA(Res, "RT_ACCELERATOR");
break;
case 10:
lstrcpyA(Res, "RT_RCDATA");
break;
case 11:
lstrcpyA(Res, "RT_MESSAGETABLE");
break;
case 12:
lstrcpyA(Res, "RT_GROUP_CURSOR");
break;
case 14:
lstrcpyA(Res, "RT_FONTDIR");
break;
case 16:
lstrcpyA(Res, "RT_VERSION");
break;
case 17:
lstrcpyA(Res, "RT_DLGINCLUDE");
break;
case 19:
lstrcpyA(Res, "RT_PLUGPLAY");
break;
case 20:
lstrcpyA(Res, "RT_VXD");
break;
case 21:
lstrcpyA(Res, "RT_ANICURSOR");
break;
case 22:
lstrcpyA(Res, "RT_ANIICON");
break;
case 23:
lstrcpyA(Res, "RT_HTML");
break;
case 24:
lstrcpyA(Res, "RT_MANIFEST");
break;
default:
lstrcpyA(Res, "UNKNOWN");
break;
}
return Res;
}