DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName) { BYTE* pbResBase; FILE* pF = NULL; DWORD ret = 0; DWORD dwResDirRVA; DWORD dwResDirSize; unsigned ulNumResNodes=0; DynamicArray<ResourceNode*> g_prResNodePtr; if (g_pPELoader->IsPE32()) { IMAGE_OPTIONAL_HEADER32 *pOptHeader = &(g_pPELoader->ntHeaders32()->OptionalHeader); dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); } else { IMAGE_OPTIONAL_HEADER64 *pOptHeader = &(g_pPELoader->ntHeaders64()->OptionalHeader); dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); } if(dwResDirRVA && dwResDirSize) { if(g_pPELoader->getVAforRVA(dwResDirRVA, (void **) &pbResBase)) { // First, pull out all resource nodes (tree leaves), see ResourceNode struct PIMAGE_RESOURCE_DIRECTORY pirdType = (PIMAGE_RESOURCE_DIRECTORY)pbResBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeType = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbResBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwTypeID; unsigned short i = 0,N = pirdType->NumberOfNamedEntries+pirdType->NumberOfIdEntries; PAL_CPP_TRY { for(i=0; i < N; i++, pirdeType++) { dwTypeID = VAL32(IMAGE_RDE_NAME(pirdeType)); if(IMAGE_RDE_OFFSET_FIELD(pirdeType, DataIsDirectory)) { BYTE* pbNameBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeType, OffsetToDirectory)); PIMAGE_RESOURCE_DIRECTORY pirdName = (PIMAGE_RESOURCE_DIRECTORY)pbNameBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeName = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbNameBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwNameID; unsigned short i,N = VAL16(pirdName->NumberOfNamedEntries)+VAL16(pirdName->NumberOfIdEntries); for(i=0; i < N; i++, pirdeName++) { dwNameID = VAL32(IMAGE_RDE_NAME(pirdeName)); if(IMAGE_RDE_OFFSET_FIELD(pirdeName, DataIsDirectory)) { BYTE* pbLangBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeName, OffsetToDirectory)); PIMAGE_RESOURCE_DIRECTORY pirdLang = (PIMAGE_RESOURCE_DIRECTORY)pbLangBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeLang = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbLangBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwLangID; unsigned short i,N = VAL16(pirdLang->NumberOfNamedEntries)+VAL16(pirdLang->NumberOfIdEntries); for(i=0; i < N; i++, pirdeLang++) { dwLangID = VAL32(IMAGE_RDE_NAME(pirdeLang)); if(IMAGE_RDE_OFFSET_FIELD(pirdeLang, DataIsDirectory)) { _ASSERTE(!"Resource hierarchy exceeds three levels"); } else { g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,dwLangID, VAL32(IMAGE_RDE_OFFSET(pirdeLang)),pbResBase); } } } else { g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,0,VAL32(IMAGE_RDE_OFFSET(pirdeName)),pbResBase); } } } else { g_prResNodePtr[ulNumResNodes++] = new ResourceNode(dwTypeID,0,0,VAL32(IMAGE_RDE_OFFSET(pirdeType)),pbResBase); } } } PAL_CPP_CATCH_ALL { ret= 0xDFFFFFFF; ulNumResNodes = 0; } PAL_CPP_ENDTRY // OK, all tree leaves are in ResourceNode structs, and ulNumResNodes ptrs are in g_prResNodePtr if(ulNumResNodes) { ret = 1; #ifdef RES_FILE_DUMP_ENABLED _wfopen_s(&pF,wzFileName,L"wb"); if(pF) { // Dump them to pF // Write dummy header ResourceHeader *pRH = new ResourceHeader(); fwrite(pRH,sizeof(ResourceHeader),1,pF); SDELETE(pRH); // For each resource write header and data PAL_CPP_TRY { for(i=0; i < ulNumResNodes; i++) { /* sprintf_s(szString,SZSTRING_SIZE,"// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d", i+1, g_prResNodePtr[i]->ResHdr.dwTypeID, g_prResNodePtr[i]->ResHdr.dwNameID, g_prResNodePtr[i]->ResHdr.wLangID, VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData), VAL32(g_prResNodePtr[i]->DataEntry.Size)); printLine(NULL,szString); */ g_prResNodePtr[i]->Save(pF); SDELETE(g_prResNodePtr[i]); } } PAL_CPP_CATCH_ALL { ret= 0xDFFFFFFF; } PAL_CPP_ENDTRY fclose(pF); }// end if file opened else ret = 0xEFFFFFFF; #else // Dump to text, using wzFileName as GUICookie //char szString[4096]; void* GUICookie = (void*)wzFileName; BYTE* pbData; printLine(GUICookie,""); sprintf(szString,"// ========== Win32 Resource Entries (%d) ========",ulNumResNodes); for(i=0; i < ulNumResNodes; i++) { printLine(GUICookie,""); sprintf(szString,"// Res.# %d Type=0x%X Name=0x%X Lang=0x%X DataOffset=0x%X DataLength=%d", i+1, g_prResNodePtr[i]->ResHdr.dwTypeID, g_prResNodePtr[i]->ResHdr.dwNameID, g_prResNodePtr[i]->ResHdr.wLangID, VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData), VAL32(g_prResNodePtr[i]->DataEntry.Size)); printLine(GUICookie,szString); if(g_pPELoader->getVAforRVA(VAL32(g_prResNodePtr[i]->DataEntry.OffsetToData), (void **) &pbData)) { strcat(g_szAsmCodeIndent,"// "); strcpy(szString,g_szAsmCodeIndent); DumpByteArray(szString,pbData,VAL32(g_prResNodePtr[i]->DataEntry.Size),GUICookie); printLine(GUICookie,szString); g_szAsmCodeIndent[strlen(g_szAsmCodeIndent)-4] = 0; } SDELETE(g_prResNodePtr[i]); } ret = 1; #endif } // end if there are nodes }// end if got ptr to resource
DWORD DumpResourceToFile(WCHAR* wzFileName) { BYTE* pbResBase; FILE* pF = NULL; DWORD ret = 0; DWORD dwResDirRVA; DWORD dwResDirSize; if (g_pPELoader->IsPE32()) { IMAGE_OPTIONAL_HEADER32 *pOptHeader = &(g_pPELoader->ntHeaders32()->OptionalHeader); dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); } else { IMAGE_OPTIONAL_HEADER64 *pOptHeader = &(g_pPELoader->ntHeaders64()->OptionalHeader); dwResDirRVA = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); dwResDirSize = VAL32(pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size); } if(dwResDirRVA && dwResDirSize) { ULONG L = (ULONG)wcslen(wzFileName)*3+3; char* szFileNameANSI = new char[L]; memset(szFileNameANSI,0,L); WszWideCharToMultiByte(CP_ACP,0,wzFileName,-1,szFileNameANSI,L,NULL,NULL); pF = fopen(szFileNameANSI,"wb"); delete [] szFileNameANSI; if(pF) { if(g_pPELoader->getVAforRVA(dwResDirRVA, (void **) &pbResBase)) { // First, pull out all resource nodes (tree leaves), see ResourceNode struct PIMAGE_RESOURCE_DIRECTORY pirdType = (PIMAGE_RESOURCE_DIRECTORY)pbResBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeType = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbResBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwTypeID; unsigned short i,N = VAL16(pirdType->NumberOfNamedEntries)+VAL16(pirdType->NumberOfIdEntries); for(i=0; i < N; i++, pirdeType++) { dwTypeID = VAL32(IMAGE_RDE_NAME(pirdeType)); if(IMAGE_RDE_OFFSET_FIELD(pirdeType, DataIsDirectory)) { BYTE* pbNameBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeType, OffsetToDirectory)); PIMAGE_RESOURCE_DIRECTORY pirdName = (PIMAGE_RESOURCE_DIRECTORY)pbNameBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeName = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbNameBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwNameID; unsigned short i,N = VAL16(pirdName->NumberOfNamedEntries)+VAL16(pirdName->NumberOfIdEntries); for(i=0; i < N; i++, pirdeName++) { dwNameID = VAL32(IMAGE_RDE_NAME(pirdeName)); if(IMAGE_RDE_OFFSET_FIELD(pirdeName, DataIsDirectory)) { BYTE* pbLangBase = pbResBase + VAL32(IMAGE_RDE_OFFSET_FIELD(pirdeName, OffsetToDirectory)); PIMAGE_RESOURCE_DIRECTORY pirdLang = (PIMAGE_RESOURCE_DIRECTORY)pbLangBase; PIMAGE_RESOURCE_DIRECTORY_ENTRY pirdeLang = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pbLangBase+sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD dwLangID; unsigned short i,N = VAL32(pirdLang->NumberOfNamedEntries)+VAL16(pirdLang->NumberOfIdEntries); for(i=0; i < N; i++, pirdeLang++) { dwLangID = IMAGE_RDE_NAME(pirdeLang); if(IMAGE_RDE_OFFSET_FIELD(pirdeLang, DataIsDirectory)) { _ASSERTE(!"Resource hierarchy exceeds three levels"); } else { if (g_prResNodePtr == NULL) { g_prResNodePtr = new DynamicArray<ResourceNode*>; } (*g_prResNodePtr)[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,dwLangID,pbResBase + VAL32(IMAGE_RDE_OFFSET(pirdeLang))); } } } else { if (g_prResNodePtr == NULL) { g_prResNodePtr = new DynamicArray<ResourceNode*>; } (*g_prResNodePtr)[ulNumResNodes++] = new ResourceNode(dwTypeID,dwNameID,0,pbResBase + VAL32(IMAGE_RDE_OFFSET(pirdeName))); } } } else { if (g_prResNodePtr == NULL) { g_prResNodePtr = new DynamicArray<ResourceNode*>; } (*g_prResNodePtr)[ulNumResNodes++] = new ResourceNode(dwTypeID,0,0,pbResBase + VAL32(IMAGE_RDE_OFFSET(pirdeType))); } } // OK, all tree leaves are in ResourceNode structs, and ulNumResNodes ptrs are in g_prResNodePtr // Dump them to pF if(ulNumResNodes) { BYTE* pbData; // Write dummy header ResourceHeader *pRH = new ResourceHeader(); fwrite(pRH,sizeof(ResourceHeader),1,pF); delete pRH; DWORD dwFiller; BYTE bNil[3] = {0,0,0}; // For each resource write header and data for(i=0; i < ulNumResNodes; i++) { if(g_pPELoader->getVAforRVA(VAL32((*g_prResNodePtr)[i]->DataEntry.OffsetToData), (void **) &pbData)) { fwrite(&((*g_prResNodePtr)[i]->ResHdr),sizeof(ResourceHeader),1,pF); fwrite(pbData,VAL32((*g_prResNodePtr)[i]->DataEntry.Size),1,pF); dwFiller = VAL32((*g_prResNodePtr)[i]->DataEntry.Size) & 3; if(dwFiller) { dwFiller = 4 - dwFiller; fwrite(bNil,dwFiller,1,pF); } } delete (*g_prResNodePtr)[i]; } } if (g_prResNodePtr) { delete g_prResNodePtr; g_prResNodePtr = NULL; } ulNumResNodes = 0; ret = 1; }// end if got ptr to resource else ret = 0xFFFFFFFF; if(pF) fclose(pF); }// end if file opened else ret = 0xEFFFFFFF; } // end if there is resource else ret = 0; return ret; }