fancycode/memorymodule

repository·master·Indexed 25 days ago

https://github.com/fancycode/memorymodule

A C library and tutorial for loading Windows DLLs directly from memory buffers, bypassing the need for files on disk and the limitations of standard LoadLibrary APIs. It provides an interface mimicking standard Windows loading functions, including MemoryLoadLibrary, MemoryGetProcAddress, and MemoryFreeLibrary, while handling PE format structures, base relocation, and memory allocation via VirtualAlloc.

Tokens
1.7K
Snippets
4
Records
11
Agent score
35%

What's inside memorymodule

  1. Overview of MemoryModule

    master
    MemoryModule is a library designed to load Windows DLLs directly from memory, bypassing the requirement for the DLL to exist as a file on the filesystem. This is useful for scenarios where you want to avoid distributing multiple files or wish to make reverse engineering (disassembling) more difficult by not leaving traces of the DLL on the disk.
  2. Understand the PE (Portable Executable) format structure

    master

    Windows binaries (.exe, .dll, .sys) use the PE format. To load a DLL from memory, you must understand its structure, which is defined in winnt.h. The format consists of:

    1. DOS Header/Stub: For backwards compatibility.
    2. PE Header: Contains IMAGE_NT_HEADERS, which includes:
      • IMAGE_FILE_HEADER: Describes the physical format (e.g., NumberOfSections, Characteristics).
      • IMAGE_OPTIONAL_HEADER: Describes the logical format (e.g., ImageBase, SizeOfImage, AddressOfEntryPoint, and the DataDirectory).
    3. Section Headers: A list of IMAGE_SECTION_HEADER structures describing the contents (code, data, etc.) and their locations.
    4. Sections: The actual data/code blocks.

    The DataDirectory within the OptionalHeader is critical for finding imports (Index 1), exports (Index 0), and the base relocation table (Index 5).

  3. Unload a library loaded with MemoryModule

    master

    To properly free a custom loaded library, you must follow these steps:

    1. Call the DLL entry point to notify the library that it is being detached (using DLL_PROCESS_DETACH).
    2. Free any external libraries that were used to resolve imports.
    3. Free the allocated memory used by the module.
  4. Use the MemoryModule API to load DLLs from memory

    master
    MemoryModule is a C library designed to load a DLL directly from a memory buffer. Its interface mimics the standard Windows library loading functions. Use MemoryLoadLibrary to load the module, MemoryGetProcAddress to retrieve function pointers, and MemoryFreeLibrary to unload it.
  5. Allocate memory for a DLL using VirtualAlloc

    master

    To load a DLL from memory, you must reserve a memory block using VirtualAlloc. The size of the block should be determined by PEHeader->OptionalHeader->SizeOfImage. It is best practice to attempt to reserve the memory at the address specified by ImageBase.

    memory = VirtualAlloc((LPVOID)(PEHeader->OptionalHeader.ImageBase),
        PEHeader->OptionalHeader.SizeOfImage,
        MEM_RESERVE,
        PAGE_READWRITE);

    If the reserved memory address differs from the ImageBase requested, you must perform Base relocation later.

    memory = VirtualAlloc((LPVOID)(PEHeader->OptionalHeader.ImageBase),
        PEHeader->OptionalHeader.SizeOfImage,
        MEM_RESERVE,
        PAGE_READWRITE);
  6. Reference the DataDirectory indices

    master

    The DataDirectory contains 16 entries defining the logical components of the library. Key indices for manual loading include:

    IndexDescription
    0Exported functions
    1Imported functions
    2Resources
    3Exception informations
    4Security informations
    5Base relocation table
    6Debug informations
    7Architecture specific data
    8Global pointer
    9Thread local storage
    10Load configuration
    11Bound imports
    12Import address table
    13Delay load imports
    14COM runtime descriptor

    To provide access to exported functions, the exports entry (0) is required. To load the DLL, the imports (1) and base relocation table (5) are necessary.

  7. Reference the IMAGE_NT_HEADERS32 structure

    master

    The IMAGE_NT_HEADERS32 structure is the core of the PE header, containing the file header and the optional header.

    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature;
        IMAGE_FILE_HEADER FileHeader;
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
    typedef struct _IMAGE_NT_HEADERS {
        DWORD Signature;
        IMAGE_FILE_HEADER FileHeader;
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
  8. Reference the IMAGE_OPTIONAL_HEADER32 structure

    master

    The IMAGE_OPTIONAL_HEADER32 contains logical information required for loading the library, such as memory requirements and entry points.

    typedef struct _IMAGE_OPTIONAL_HEADER {
        // Standard fields.
        WORD    Magic;
        BYTE    MajorLinkerVersion;
        BYTE    MinorLinkerVersion;
        DWORD   SizeOfCode;
        DWORD   SizeOfInitializedData;
        DWORD   SizeOfUninitializedData;
        DWORD   AddressOfEntryPoint;
        DWORD   BaseOfCode;
        DWORD   BaseOfData;
    
        // NT additional fields.
        DWORD   ImageBase;
        DWORD   SectionAlignment;
        DWORD   FileAlignment;
        WORD    MajorOperatingSystemVersion;
        WORD    MinorOperatingSystemVersion;
        WORD    MajorImageVersion;
        WORD    MinorImageVersion;
        WORD    MajorSubsystemVersion;
        WORD    MinorSubsystemVersion;
        DWORD   Win32VersionValue;
        DWORD   SizeOfImage;
        DWORD   SizeOfHeaders;
        DWORD   CheckSum;
        WORD    Subsystem;
        DWORD   DllCharacteristics;
        DWORD   SizeOfStackReserve;
        DWORD   SizeOfStackCommit;
        DWORD   SizeOfHeapReserve;
        DWORD   SizeOfHeapCommit;
        DWORD   LoaderFlags;
        DWORD   NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
    typedef struct _IMAGE_OPTIONAL_HEADER {
        //
        // Standard fields.
        //
        WORD    Magic;
        BYTE    MajorLinkerVersion;
        BYTE    MinorLinkerVersion;
        DWORD   SizeOfCode;
        DWORD   SizeOfInitializedData;
        DWORD   SizeOfUninitializedData;
        DWORD   AddressOfEntryPoint;
        DWORD   BaseOfCode;
        DWORD   BaseOfData;
    
        //
        // NT additional fields.
        //
        DWORD   ImageBase;
        DWORD   SectionAlignment;
        DWORD   FileAlignment;
        WORD    MajorOperatingSystemVersion;
        WORD    MinorOperatingSystemVersion;
        WORD    MajorImageVersion;
        WORD    MinorImageVersion;
        WORD    MajorSubsystemVersion;
        WORD    MinorSubsystemVersion;
        DWORD   Win32VersionValue;
        DWORD   SizeOfImage;
        DWORD   SizeOfHeaders;
        DWORD   CheckSum;
        WORD    Subsystem;
        DWORD   DllCharacteristics;
        DWORD   SizeOfStackReserve;
        DWORD   SizeOfStackCommit;
        DWORD   SizeOfHeapReserve;
        DWORD   SizeOfHeapCommit;
        DWORD   LoaderFlags;
        DWORD   NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;