Poisoning MUI files

In one of my older posts about persistence tricks I described a mechanism relying on a modification of MUI files. The idea was that if you could change a string inside a MUI file – a string so specific that is actually directly passed to one of the program executing functions (e.g. ShellExecute) during program run-time – you could achieve some sort of persistence. The idea is kinda OK, but the real world renders it completely useless. It’s just really hard to find programs that match the criteria…

There is one more interesting bit you can do with MUI files tho.

If you copy Notepad.exe and its associated En-Us\notepad.exe.mui file to a different directory, you now have an environment where you can launch a signed OS binary with its MUI file under your control. The MUI file is signed too, but this fact doesn’t seem to be checked during the program execution. So, we can play around with it.

My first test was a simple change to the way Notepad shows ‘working’ file name in its title. The original resource string:

  • %1 – Notepad

refers to a placeholder ‘%1’ (file name), followed by a hyphen, and then comes the ‘Notepad’ string. We are of course very familiar with this template being rendered into something like this:

When you open a file, or Save content of your Notepad window that ‘Untitled’ part in the title will be replaced by an actual file name.

Coming back to the resource strings – as mentioned earlier, the ‘%1’ refers to an argument that is replaced by a ‘working’ file name by program during its run-time. Could we add more arguments?

To test it, I changed that template string into:

  • %1 %2 %3 – Notepad

– assuming that program will fetch additional arguments from its stack while it renders the title of the main window. This indeed occurs and when I relaunched Notepad I immediately got this ‘corrupted’ title window:

A-ha. This is a good sign. We now know that can modify the MUI file and cause Notepad to misbehave.

This finding opens doors to a possible more systematic research on a controlled modification of MUI strings to force programs to behave erratically, or crash, at least. And who knows, maybe in some instances also to controlled code execution, or signed OS binary acting as a lolbin.

The latter is actually not that far from our reach. If you can find a signed program that fetches URL directly from MUI file and either opens it directly via an API, or places it on its UI so that it can be clicked you can easily swap that URL with a link to a local ‘badguy’ file (e.g. ‘file://c:/test/badguy.exe’). Launching the program, and/or clicking the link will ‘lolbinexecute’ the badguy.exe. The interaction is required, but the proxied execution via a signed OS binary is achieved.

A quick query over the default Windows install highlights some candidates (.exe.mui files with references to ‘http’ strings), but I couldn’t find any that would be easy to use as a demo. Oh well.. Maybe the technique is not that interesting after all ?

BUT

There is one more thing we can do with it. Since we know that we can insert anything we want into a MUI file, what about we smuggle in some payload into a memory space of a signed .exe? The signed .exe will have this payload embedded and present in memory immediately after launch. No need for WriteProcessMemory.

To test the idea I added an EICAR file to my test Notepad MUI file. After launching the .exe and searching for EICAR string in memory I was able to pinpoint it like this:

The memory seems to be PAGE_WRITECOPY protected so it may pose a problem, but at least the data is already there.

There may be other ideas here that I missed.

Returning the call – ‘moshi moshi’, the API way (a.k.a. API cold calling), Part 2

In my old post I described an idea of initializing registers with a predefined value using calls to APIs that return predictable values; such approach can help to develop novelty anti-* tricks, in particular targeting emulation of any sort & imho this is certainly worth an attention of anyone who tries to:

  • write code bypassing AV/EDR in a generic way
  • create obfuscators that may try to hide some logic of the program… outside of it…
  • reverse static analysis in a more generic way — reversers will need to take these into account to cover additional cases of opaque predicates

The idea of expanding on the old post was with me for a while and I finally decided to provide more examples of OS code that can be ‘repurposed’.

It took a long time, because it takes a lot of code browsing/searches. And I think I only touched the surface, because to be effective in this area one needs a proper database of OS code snippets that is searchable the same way as ROP gadgets databases.

So, there you go… if you are looking for an interesting reversing project: try to automate finding opaque predicates in as many libs as possible!

Browsing through the MSDN documentation and code of various OS libraries it’s quite easy to spot the functions that are no longer supported/deprecated or otherwise not maintained; they are a perfect target for abuse:

  • For example, looking at ‘Network DDE Reference‘ one can immediately recognize potential of old functions exported by Nddeapi.dll; they are returning NDDE_NOT_IMPLEMENTED (14) by default; there are exceptions of course – a couple of NetDDE APIs return 0, but this DLL can help to initialize registers to one of these two values w/o much effort
  • The good ol’ kernel32.dll is also full of surprises. The 16-bit legacy code is still there, even if in a dormant state. Calling a very old exported function UTRegister with wrong parameters can give you 1 in the eax, but if you provide 3 good arguments i.e.
UTRegister(0, "mem16.dll", 0, "GetMemory", &ptr, 0, 0)

You will get 0 in eax, plus a bonus – a pointer to a call back (a function in ptr variable). If you call this callback function, you will get 0x2000 in eax.

So, you can use this particular API to get 0, 1, or 0x2000 into eax.

  • Incorrect parameters passed to some very well-known functions can provide some unexpected results – we just need to make a deliberate mistake in our code 🙂
    For example, the good old LoadLibraryEx can help to initialize eax to 0x57 (ERROR_INVALID_PARAMETER) if you pass a nonzero value as a second argument when you call the function
  • LockResource is one of the best wrappers – it is doing nothing other than moving the first argument passed to the function to eax
  • I_CryptGetLruEntryIdentifier is similar, but the value will be increased by 8 (there are tones functions that are similar)
  • FreeResource does nothing and returns 0
  • If we need to initialize a DWORD value at some specific location (pointer), the msvcr120_clr0400 ! _vacopy API may come handy; it takes a pointer, and a value as its arguments and does the dirty job for us
  • Many GDI functions return 0 by default e.g. EngQueryEMFInfo, FixBrushOrgEx, GdiPlayJournal
  • Then there is always a trivial example of GetCurrentProcess that is always returning 0xFFFFFFFF
  • CloseProfileUserMapping, GdiSupportsFontChangeEvent, GdiEntry16, ImmReleaseContext, SetConsoleMaximumWindowSize always return 1; there is lots of APIs that behave this way
  • NtVdm64CreateProcessInternalW, VerifyConsoleIoHandle always return 0
  • Many unimplemented functions return 0x78 (ERROR_CALL_NOT_IMPLEMENTED) e.g. RegLoadMUIStringA
  • Many unimplemented functions return 0x32 (ERROR_NOT_SUPPORTED) e.g. SetEncryptedFileMetadata
  • ElfReportEventAndSourceW will give you 0xC0000002 (NT_STATUS_NOT_IMPLEMENTED)
  • SslChangeNotify will give you 0x80090029 (NTE_NOT_SUPPORTED )
  • MD5Init and similar functions can initialize some buffers with MD5 (or other hash functions’) initial values e.g. 0x67452301, 0x0EFCDAB89, 0x98BADCFE, 0x10325476; these could be used w/o using actual hash calculation code
  • Cleverly used encryption functions can give you a predictable set of values (e.g. initialize a buffer with a specific pattern, encrypt it, use some the data from the buffer as offsets to other data structures/callbacks)
  • FlushInstructionCache returns 1; I was curious about it and even asked on Twitter about it; It would seem x86 architecture doesn’t need it, but it’s good to call it for future compatibility; So, eax=1 it is
  • GetLargePageMinimum can give you a predictable value if you discard the lower bits of it e.g. 0x7FFExxxxh
  • Many DLLs with DllInstall, DllRegisterServer exports will return 0 when these APIs are called
  • SetLastError/GetLastError can transfer data via OS data buffers
  • Many msvbvm60 functions return 0x80010007 (RPC_E_SERVER_DIED)
  • msvcr* and msvcp* DLLs contain lots of functions that can help to transform data in a more or less unpredictable way
  • Some of the exported functions are so old school that they can be used to cause predictable exceptions e.g. reading/writing to I/O ports
  • COM return values can be predictable as well:
    • S_OK Operation successful 0x00000000
    • E_ABORT Operation aborted 0x80004004
    • E_ACCESSDENIED General access denied error 0x80070005
    • E_FAIL Unspecified failure 0x80004005
    • E_HANDLE Handle that is not valid 0x80070006
    • E_INVALIDARG One or more arguments are not valid 0x80070057
    • E_NOINTERFACE No such interface supported 0x80004002
    • E_NOTIMPL Not implemented 0x80004001
    • E_OUTOFMEMORY Failed to allocate necessary memory 0x8007000E
    • E_POINTER Pointer that is not valid 0x80004003
    • E_UNEXPECTED Unexpected failure 0x8000FFFF

And so on and so forth.

Many API functions can be called with incorrect parameters only to return a predictable error. Some of them are mentioned above, but these I looked for are primarily focused on returning error immediately (i.e. they are deprecated or legacy and are just a simple block of ‘mov eax, error_value/ret’ code); they are not the best choice.

It is much better to look for existing, popular, and working APIs, and call them with some unexpected error-prone arguments. Not necessarily fuzzing them, but fuzzing itself could be used to get some predictable results too.

Also…

Many DLLs that are created as traditional ‘utility’ DLLs export tones of mathematical, logical, worker, environmental, string functions that can be used to deliver (un)predictable code and data. Not a single sandbox or emulator handles them all, let alone scripts for IDA or Ghidra.

Finally, there are tones of other DLLs provided by 3rd party vendors, where the signed code offers all the primitives to deliver some value, string, or an opportunity to execute a more complex code block (e.g. adding stuff to Registry, writing files, hooking keyboard, mouse, etc.) that can be re-used.

Also…

Remember that there is always a way to instrument your own program.

Debugging functions, SEH, VEH, VirtualProtect, etc. can help to modify buffers as they are processed by the OS code or external DLL APIs. It’s hard to manipulate these buffers on a kernel level of course, but in the userland you can do lots of trickery this way. Causing predictable exceptions triggered inside the OS libs is a nice way to swap these buffers on the way to be processed (and outside of the actual program’s code). You can do the same for the return values.

You could even use a Trap Flag to fully trace through a certain API and only change the returned value at the very last moment…

I don’t know how many available ‘APIs are out there atm, but there is enough to make some interesting code decisions.