hasherezade / libpeconv

A library to load, manipulate, dump PE files. See also: https://github.com/hasherezade/libpeconv_tpl
https://hasherezade.github.io/libpeconv
BSD 2-Clause "Simplified" License
1.07k stars 176 forks source link

Start windows 7 notepad.exe fail #44

Closed wch1618 closed 1 year ago

wch1618 commented 2 years ago

Here is code,

    size_t v_size = 0;
    LPCTSTR pe_path = "C:\\windows\\notepad.exe";
    BYTE* my_pe = peconv::load_pe_executable(pe_path, v_size);

    if (!my_pe) {
        return -1;
    }

    peconv::set_main_module_in_peb((HMODULE)my_pe);

    peconv::run_tls_callbacks(my_pe, v_size);

    DWORD ep_rva = peconv::get_entry_point_rva(my_pe);
    if (!ep_rva) {
        return -2;
    }
    ULONG_PTR ep_va = ep_rva + (ULONG_PTR) my_pe;

    int (*new_main)() = (int(*)())ep_va;

    return new_main();

Thanks

hasherezade commented 1 year ago

Hi @wch1618 ! sorry for the late response, I am nowadays very busy.

So, there are two main problems with notepad.exe: First of all, it uses Delayload Imports in additional to the casual imports, but this can be resolved easily with libPeConv, just add this fragment after the PE loading:

// load delayed imports (if present):
const ULONGLONG loadBase = (ULONGLONG)g_Payload;
peconv::load_delayed_imports(g_Payload, loadBase);

But there is a second thing, a bit more problematic - notepad it sensitive to the path it is loaded from. Even if you copy the original notepad.exe on the Desktop, it won't run. You may ask, where does it come from? There is a function LoadAcceleratorsW called (for the version that I analyzed, on Windows 10 64 bit, they are at RVA0x13807 and 0x13824) in the Notepad, which basically loads some GUI properties (including the menu), but if the application name is different than expected, the proper accelerator table cannot be found, so the Notepad exits.

load_acc

It happens because those acceletators are loaded from the MUI file, not from the notepad.exe itself.

mui_file

accelerators

And for the MUI file to be loaded, the path must match the expected one.

What are the workarounds for this? The simplest is to hook those functions / patch the checks, and make the notepad load even without the menu. I guess the proper, solid solution would be to load the appropriate MUI, and set it into AlternateResourceModules, so that the function LdrpGetFromMUIMemCache that is called underneath can reference it. Or, maybe hooking LdrFindResource_U. I will experiment with it a bit more when I get some time.

I managed to run notepad with the help of this loader:

wch1618 commented 1 year ago

Thank you very much.