I'm have a memory buffer which contains a valid exe file image and I want to extract some resources from it.
For that I'm using the FindResource
function, but the function expects a HMODULE and crashes when supplied a memory buffer with the exe.
Is there a way to make it work with a memory buffer instead of writing the exe to a tempomary file, loading it using LoadLibrary
and then doing the work needed?
I'm have a memory buffer which contains a valid file image
in which form ? i guess than in raw (as on disk). but you need 'mapped as image' memory for use FindResource. not hard map you raw image by self ( if you want only access resource, but not execute it from memory) example of code:
PVOID MapImage(PIMAGE_DOS_HEADER pvRawData, ULONG cbRawData)
{
if (cbRawData < sizeof(IMAGE_DOS_HEADER))
{
return 0;
}
if (pvRawData->e_magic != IMAGE_DOS_SIGNATURE)
{
return 0;
}
ULONG e_lfanew = pvRawData->e_lfanew, s = e_lfanew + sizeof(IMAGE_NT_HEADERS);
if (e_lfanew >= s || s > cbRawData)
{
return 0;
}
PIMAGE_NT_HEADERS pinth = (PIMAGE_NT_HEADERS)RtlOffsetToPointer(pvRawData, e_lfanew);
if (pinth->Signature != IMAGE_NT_SIGNATURE)
{
return 0;
}
ULONG SizeOfImage = pinth->OptionalHeader.SizeOfImage, SizeOfHeaders = pinth->OptionalHeader.SizeOfHeaders;
s = e_lfanew + SizeOfHeaders;
if (SizeOfHeaders > SizeOfImage || SizeOfHeaders >= s || s > cbRawData)
{
return 0;
}
s = FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pinth->FileHeader.SizeOfOptionalHeader;
if (s > SizeOfHeaders)
{
return 0;
}
ULONG NumberOfSections = pinth->FileHeader.NumberOfSections;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)RtlOffsetToPointer(pinth, s);
ULONG Size;
if (NumberOfSections)
{
if (e_lfanew + s + NumberOfSections * sizeof(IMAGE_SECTION_HEADER) > SizeOfHeaders)
{
return 0;
}
do
{
if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData))
{
union {
ULONG VirtualAddress, PointerToRawData;
};
VirtualAddress = pish->VirtualAddress, s = VirtualAddress + Size;
if (VirtualAddress > s || s > SizeOfImage)
{
return 0;
}
PointerToRawData = pish->PointerToRawData, s = PointerToRawData + Size;
if (PointerToRawData > s || s > cbRawData)
{
return 0;
}
}
} while (pish++, --NumberOfSections);
}
PVOID ImageBase = VirtualAlloc(0, SizeOfImage, MEM_COMMIT, PAGE_READWRITE);
if (!ImageBase)
{
return 0;
}
memcpy(ImageBase, pvRawData, SizeOfHeaders);
if (NumberOfSections = pinth->FileHeader.NumberOfSections)
{
do
{
--pish;
if (Size = min(pish->Misc.VirtualSize, pish->SizeOfRawData))
{
memcpy(RtlOffsetToPointer(ImageBase, pish->VirtualAddress),
RtlOffsetToPointer(pvRawData, pish->PointerToRawData), Size);
}
} while (--NumberOfSections);
}
return ImageBase;
}
void Test(PVOID pvRawData, ULONG cbRawData, PCWSTR lpType, PCWSTR lpName)
{
if (HMODULE ImageBase = (HMODULE)MapImage((PIMAGE_DOS_HEADER)pvRawData, cbRawData))
{
if (HRSRC hResInfo = FindResource(ImageBase, lpName, lpType))
{
if (HGLOBAL hg = LoadResource(ImageBase, hResInfo))
{
__nop();
}
}
VirtualFree(ImageBase, 0, MEM_RELEASE);
}
}
MapImage containing check for valid data sizes. however if you sure that (pvRawData, cbRawData) is 100% correct - you can skip this checks and simplify code
// i EDIT Test
function based on @IInspectable comment - remove __try/__except - it not needed here