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.
Código
/************************************************** * 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");; 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 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) { GetResources(Mapped, Resource, DumpPath,(PIMAGE_SECTION_HEADER)&Mapped[IDH->e_lfanew + 24 + INH->FileHeader.SizeOfOptionalHeader], INH->FileHeader.NumberOfSections); } else } } 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)); while(NumberOfEntries > 0) { if (IRDRE->DataIsDirectory == 1) { SecureZeroMemory(STR_ID3, STATIC_SIZE); if (IRDRE->NameIsString == 0) { RES_TYPE = RESOURCES[(IRDRE->Id)-1]; 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); 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)); while(NumberOfSubEntries > 0) { if(SUBIRDRE->DataIsDirectory == 1) { SSUBIRD = (PIMAGE_RESOURCE_DIRECTORY) ((int)IRD + SUBIRDRE->OffsetToDirectory); NumberOfSSubEntries = SSUBIRD->NumberOfNamedEntries + SSUBIRD->NumberOfIdEntries; SSUBIRDRE = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((int)SSUBIRD + sizeof(IMAGE_RESOURCE_DIRECTORY)); while(NumberOfSSubEntries > 0) { IRDTE = (PIMAGE_RESOURCE_DATA_ENTRY) ((int)IRD +SSUBIRDRE->OffsetToData); 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++; } } 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; }