Question

void
CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
{
    int i, size;
    unsigned char *codeBase = module->codeBase;
    unsigned char *dest;
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
    for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++) {
        if (section->SizeOfRawData == 0) {
            // section doesn't contain data in the dll itself, but may define
            // uninitialized data
            size = old_headers->OptionalHeader.SectionAlignment;
            if (size > 0) {
                dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
                    size,
                    MEM_COMMIT,
                    PAGE_READWRITE);

                section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
                memset(dest, 0, size);
            }

            // section is empty
            continue;
        }

        // commit memory block and copy data from dll
        dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,
                            section->SizeOfRawData,
                            MEM_COMMIT,
                            PAGE_READWRITE);
        memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);
        section->Misc.PhysicalAddress = (DWORD) (POINTER_TYPE) dest;
    }
}

I want to load a dll file from memory.And the code above was found in http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory.

I also found author says that: "Sections without data in the file (like data sections for the used variables) have a SizeOfRawData of 0, so you can use the SizeOfInitializedData or SizeOfUninitializedData of the OptionalHeader. Which one must get choosen depending on the bit flags IMAGE_SCN_CNT_INITIALIZED_DATA and IMAGE_SCN_CNT_UNINITIALIZED_DATA that may be set in the section`s characteristics."

But i can't understand when SizeOfRawData is zero,why the size of memory committed is SectionAlignment, neither SizeOfInitializedData nor SizeOfUninitializedData.

Was it helpful?

Solution

According to the Microsoft PE and COFF Specification SizeOfRawData is zero when:

When a section contains only uninitialized data, this field (SizeOfRawData) should be zero.

(As a side note this is also true if the section only contains initialized data which is initialized to 0.)

SizeOfInitializedData or SizeOfUninitializedData can't be used on a per section basis as these fields are the sum of all initialized and uninitialized sections if there is more than one of this type of section (quoting the spec):

SizeOfInitializedData : The size of the initialized data section, or the sum of all such sections if there are multiple data sections.

SizeOfUninitializedData : The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections.

Thus, if you have more than one initialized or uninitialized section, you would end up allocating to much for a single section if you use (respectively) SizeOfInitializedData or SizeOfUninitializedData fields.

It can't be SectionAlignment (which is usually set to the system allocation granularity) because you would also end up allocating not enough room for your section if the size of the xection is bigger than the allocation granularity (which is usually 4Kibi, or 4096 bytes).

SectionAlignment: The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to FileAlignment. The default is the page size for the architecture.

As an example, suppose you have 2 Uninitialized data sections (SizeOfRawData = 0 for each section) of 8192 bytes each. If you allocate:

  • SizeOfUninitializedData : you'd end up allocating 8192 * 2 bytes for each sections which is too much.

  • SectionAlignment: you'd end up allocating 4096 (0x1000) bytes for each sections which is not enough.

IMO, the only fields that is relevant in your case is IMAGE_SECTION_HEADER.VirtualSize:

VirtualSize: The total size of the section when loaded into memory. If this value is greater than SizeOfRawData, the section is zero‐padded. This field is valid only for executable images and should be set to zero for object files.

Note that the VirtualSize field is not rounded (it is the exact number of bytes required in memory without taking into account the page granularity).

Thus, in the case you have a section with SizeOfRawData = 0, you should:

  • Take the VirtualSize field of this section
  • Allocate the resulting size with VirtualAlloc()

You don't have to round up the VirtualSize because VirtualAlloc() will take care of allocating to the next multiple of the page size granularity (as given by GetSystemInfo and the SYSTEM_INFO.dwPageSize field).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top