man
man

Reputation: 155

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?

Upvotes: 2

Views: 474

Answers (2)

RbMm
RbMm

Reputation: 33754

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

Upvotes: 3

David Heffernan
David Heffernan

Reputation: 613232

Your options:

  1. Save to temporary file and load with LoadLibraryEx.
  2. Parse the PE file and locate the resource yourself.
  3. Replicate the necessary actions to load the module from memory in the manner of one of the various memory module libraries.

Upvotes: 0

Related Questions