frida-core icon indicating copy to clipboard operation
frida-core copied to clipboard

Add a stealthier injection technique for Frida on Windows

Open elvanderb opened this issue 7 years ago • 5 comments

For the moment, the code that injects Frida in Windows processes works by injecting a small shellcode that call LoadLibrary. This is not optimal for the following reasons:

  • the process may be sandboxed, via the Windows APIs but also via any other sandbox mechanism (browsers are the first example that comes in mind but many other process are now sandboxed).
  • frida try to mitigate this by setting special file writes that allow a low-integrity process to load the dll but this is not enough as some sandbox may only allow signed DLL / DLL in specific paths / no DLL at all.
  • the process may be protected by a device driver or ring 3 hooks which intercept and block all tentative to inject DLLs via classical mechanisms (anti-virus but also games (to block cheats) are protected by this kind of hooks)

There is two main techniques to load a DLL from memory:

  • entirely replace the windows loader (load in memory, fix relocations, load dependencies, fix the IAT etc.)
  • hook some APIs (NtCreateFile / NtMapViewOfSections etc.) to emulate the disk access and the mapping of the DLL in memory (which is normally done by the kernel) and call LoadLibrary.

The first option is not too hard to do but has one major drawback: replacing the Windows loader is not that easy, especially for the TLS vars and callbacks - mechanisms that are used by frida - and the dependency loading (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx ...). We may replace them by hooking RtlUserThreadStart for example but we may encounter chicken and egg problems...

The second option is quite elegant (it was used, for example, by Stuxnet) and solve all the Windows internal problems but it asks to hook functions in the targeted process, something that we cannot do without... injecting a DLL. Again, we have a chicken and egg problem.

A third option might be to use a mixed approach: we inject a simple DLL with the first approach to have a limited hooking framework and we inject Frida by using the second technique.

The question is: what should we do? I think that the first solution might be sufficient and it has the benefit of being stealthier, it can be done 100% from the remote process so no userland hooks should block us and it would require minor changes in the code (no additional projects).

What do you think?

elvanderb avatar May 14 '17 14:05 elvanderb

The first option also sounds like the best to me. Architecturally it should be like a Windows counterpart to gumdarwinmapper.h, and be consumed by frida-core like on i/macOS.

oleavr avatar May 14 '17 14:05 oleavr

OK. I'll continue to add some comments on this issue to document what I've done and what I plan to do.

TLS: Frida uses TLS callbacks to be noticed when a new thread is created. I'll see if we can do without those callbacks, if we can't we'll have to put some hooks as there is no other documented mechanism to do that. Frida also use some thread local variables. I didn't check yet but if they don't have initial value then we can get rid of them by using dynamically allocated TLS. If they have an initial non NULL value then we will have to initialize them at each new thread and we need TLS callbacks... I'll definitely have to code some multi-threaded tests and checks if it hasn't already be done.... I'm also afraid that the TLS are needed by the glib, which is a little bit more problematic...

DLLs: Frida only depends on system libraries so we don't have to deal with manifests etc. it should be easy to load it in memory an to populate the IAT.

elvanderb avatar May 15 '17 11:05 elvanderb

@elvanderb Any progresses with this? It's a feature that would be awesome to have, if you need it, I could give you some help, even if my skills are probably more limited than yours :P

CapitanShinChan avatar Aug 06 '18 21:08 CapitanShinChan

Hi, no, I didn't had time for this. I think the best way to deal with this would be to use the Stuxnet method as we wouldn't have to deal with TLS. The easiest way to do this would be by using inifinite jumps (\xEB\xFE) to "debug" the process and hook the APIs. I won't have time to work on this in the next few weeks but I may have some time in september.

elvanderb avatar Aug 07 '18 08:08 elvanderb

Hello. Any progress on this one?

fasetto avatar Aug 13 '22 09:08 fasetto