Skip to content

Import table with no relaction blocks are seen as "status": -1 #30

@terrybr

Description

@terrybr

Hello hasherezade,

I believe there's a bug in libpeconv where a malware that doesn't have any relocation blocks returns the status: -1 in pe-sieve (with /jlvl 2) and thus is not processed.

I found that the specific malware I tested with doesn't have any relocation blocks (using your great PE-Bear tool):

image

It's happening in this function: peconv::process_relocation_table which I see you already addressed the issue when relocation blocks are null in this fix #22 .

A friend of mine (Ron, who found the memory leak in pe-sieve) came up with a potential fix which I tested and works. Basically the function has to return true in the case there's nothing to relocate. We added bool NoBlocks = true which is set to false if there are valid blocks and is used for the return value condition.

bool peconv::process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback)
{
    IMAGE_DATA_DIRECTORY* relocDir = peconv::get_directory_entry((const BYTE*)modulePtr, IMAGE_DIRECTORY_ENTRY_BASERELOC);
    if (relocDir == NULL) {
#ifdef _DEBUG
        std::cout << "[!] WARNING: no relocation table found!\n";
#endif
        return false;
    }
    if (!validate_ptr(modulePtr, moduleSize, relocDir, sizeof(IMAGE_DATA_DIRECTORY))) {
        std::cerr << "[!] Invalid relocDir pointer\n";
        return false;
    }
    DWORD maxSize = relocDir->Size;
    DWORD relocAddr = relocDir->VirtualAddress;
    bool is64b = is64bit((BYTE*)modulePtr);

    IMAGE_BASE_RELOCATION* reloc = NULL;

    DWORD parsedSize = 0;
    DWORD validBlocks = 0;
    bool NoBlocks = true;

    while (parsedSize < maxSize) {
        reloc = (IMAGE_BASE_RELOCATION*)(relocAddr + parsedSize + (ULONG_PTR)modulePtr);
        if (!validate_ptr(modulePtr, moduleSize, reloc, sizeof(IMAGE_BASE_RELOCATION))) {
#ifdef _DEBUG
            std::cerr << "[-] Invalid address of relocations\n";
#endif
            return false;
        }
        if (reloc->SizeOfBlock == 0) {
            break;
        }
        size_t entriesNum = (reloc->SizeOfBlock - 2 * sizeof(DWORD)) / sizeof(WORD);
        DWORD page = reloc->VirtualAddress;

        BASE_RELOCATION_ENTRY* block = (BASE_RELOCATION_ENTRY*)((ULONG_PTR)reloc + sizeof(DWORD) + sizeof(DWORD));
        if (!validate_ptr(modulePtr, moduleSize, block, sizeof(BASE_RELOCATION_ENTRY))) {
            std::cerr << "[-] Invalid address of relocations block\n";
            return false;
        }
        if (!is_empty_reloc_block(block, entriesNum, page, modulePtr, moduleSize)) {
            if (process_reloc_block(block, entriesNum, page, modulePtr, moduleSize, is64b, callback)) {
                validBlocks++;
                NoBlocks = false;
            }
            else {
                // the block was malformed
                return false;
            }
        }
        parsedSize += reloc->SizeOfBlock;
    }
    return (NoBlocks || validBlocks != 0);

Thank you, and keep up the fantastic work!

Terry

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions