Search code examples
c++winapiembedded-resource

Using FindResource with a memory buffer


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?


Solution

  • 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