5 ms·
Running code within another process's address space
- R0b0t1 6y agoThe existence of CreateRemoteThread[1] may amuse readers. In addition to the obvious nefarious uses, it does end up being quite useful. [1]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread https://docs.microsoft.com/en-us/windows/win32/api/processth...
- Namidairo 6y agoOne of the many dll injection methods possible in Windows, if I recall correctly. Although I do usually just end up hijacking a dll already used by the program when I want to sneak my own code within a process that I don't have the source for, for the sake of future usability. (When patching the executable on-disk isn't desirable, and you don't want to go insane running an injector each time you start the process.)
- huhtenberg 6y agoNot always effective as it's trivial to protect against if the program bothers to do so.
- staticassertion 6y agoWhat is trivial to protect against and how? I'm not aware of a general way to prevent an attacker within your user from accessing your process's memory, on any OS, except for a few newer capabilities on Windows, which are also bypassable.
- kevingadd 6y agoSome software (mostly games) attempts to hook things like CreateRemoteThread or abort when they get the dll load/thread start events, but you can always patch those detection hooks to not run before you start your thread
- nathanlied 6y agoEnds up being a cat-and-mouse game, but the power dynamics are even more unbalanced towards the red team: not only do they have control of the hardware, they also control your executable. It's also why "anti-cheat drivers" have never gone away, they allow a greater level of control over what's done to your protected processes. I'm not sure I am okay with that - there's only so much I'm willing to put up with to play some game - but I do understand why developers/producers would want such draconian solutions. In some game genres, cheating is rampant.
- huhtenberg 6y agoAs per GP comment's context - it's trivial to detect system DLLs replacement, which is a common way to inject code without the use of trainers, loaders or exe patching.
- staticassertion 6y agoOh cool, yeah I wasn't sure if they were talking specifically about DLL hijacking or about injection in general.
- deleted 6y ago[deleted]
- saagarjha 6y agoProtecting against remote code injection is not just nontrivial, it's fundamentally impossible in general if the injector is more privileged than you.
- Const-me 6y ago> end up hijacking a dll already used by the program That’s hard to do for an OS component, due to the anti-viral measures in the OS. Modern windows freaks out when you replace DLLs in c:/Windows/System32 directory. Last time I used CreateRemoteThread was when a client wanted Windows 7 equivalent of Desktop Duplication API (introduced in Windows 8). I injected my DLL into the desktop compositor (dwm.exe process), hooked IDXGISwapChain.Present and IDXGISwapChain.ResizeBuffers methods, and wrote some C++ to copy desktop image into another ID3D10Texture2D in VRAM, and share the copy with the video capturing process.
- eps 6y agoUsually, you don't need to replace a system dll at all. You can just drop an alter ego in exe's own directory or even in a launch directory. Default search order in Windows is such that it'll pick up from the latter two first and check PATH second. Once the process is up and running it has the control over this (with LoadLibraryEx and SetDefaultDllDirectories) and it's also possible to tighten search logic at the OS level (with a registry patch), but if the machine is under attacker's control, the only option is to validate loaded module list from within the app.
- Const-me 6y agodwm.exe is in the same directory, c:/Windows/System32. The process is launched by Windows automatically, immediately after login. The desktop capture app I was working on is launched way later than that, by user.
- eps 6y agoAh, right. Missed the part it was dwm.exe
- garaetjjte 6y agoThough some core system DLLs are specified in KnownDLLs registry key, and thus not loaded from application directory.
- deleted 6y ago
- TravHatesMe 6y agoShameless plug for a .NET library I wrote to help interop between compiled x86 binary and .NET: https://github.com/blurt/X86.Interop https://github.com/blurt/X86.Interop Guide to inject your .NET dlls into a native process: https://www.codeproject.com/Articles/607352/Injecting-NET-Assemblies-Into-Unmanaged-Processes https://www.codeproject.com/Articles/607352/Injecting-NET-As...
- warkdarrior 6y agoAvailable on Windows since 2003. Linux is finally catching up!
- dblohm7 6y agoIt’s been available long before that, it’s just that MSDN compatibility listing often drop EOL’d versions off the list.
- nyellin 6y agoAn interesting and non-obvious usecase: debugging python code. Standard debuggers use ptrace to implement breakpoints by replacing instructions in debugged process with the assembly code INT3 (or equivalents). This makes the cpu trap when it reaches that instruction which transfers control to the kernel who pauses the process and notifies the debugger. This approach doesn't work for Python because there are no native assembly instructions for the Python code - only for the C interpreter. Most Python debuggers attach to already running processes by injecting a few lines of native code (ptrace on Linux, CreateRemoteThread on Windows) which then bootstraps a new Python thread that actually implements the debugger. (As the linked article mentions, on Linux you can inject code using ptrace today but it isn't the most convenient.) This is also the trick that tools like pyrasite take to inject python code into running processes. On that note, if anyone wants to easily debug/profile code running on kubernetes clusters with no prior setup, I'm looking for beta testers for an open source framework my cofounder and I are developing. It enables general application maintenance on kubernetes and not just debugging/profiling, but that's the part we need testers for right now [1]: https://en.m.wikipedia.org/wiki/INT_(x86_instruction) https://en.m.wikipedia.org/wiki/INT_(x86_instruction)
- aidos 6y agoThanks for that rundown. Super interesting.
- phaedrus 6y agoI implemented a debugger for an interpreted language (not Python, but similar design problem). I added a C "API" to the interpreter that was designed to be easily callable via GDB. IIRC it consisted of just three functions: "break on script line", "catch break here", and "why did I break?" My "debugger" was a shim or wrapper around GDB. For debugging C/C++ code, it just piped standard in/out with GDB. However if it recognized a "set breakpoint" that was actually for a line of script code, it would intercept it. Instead of telling GDB to set a breakpoint there, it would do two things: It would use GDB to manually call a function in the target program instructing the interpreter to watch for that script line ("set script breakpoint"). Then it would set a normal (native) breakpoint, but in the special function the interpreter would call from its main loop ("catch break here"). Conversely while relaying output from GDB back to the IDE, if it saw it hit a breakpoint in the "catch break here" function, it wouldn't report that. Instead the shim would use GDB to call the "why did I break" function and report the result of that back to the IDE. It was like magic getting to see the IDE bring up the correct script file and line as if the debugger hit it! Other extensions like single stepping are obvious from these primitives.
- saagarjha 6y agoFor Mac users, thread_create: https://developer.apple.com/documentation/kernel/1538152-thread_create https://developer.apple.com/documentation/kernel/1538152-thr...
- o_p 6y agoBut the nefarious potential its so obvious that no one with that intention would do DLL injection that way when there are other thousand of ways to get in
- skywal_l 6y agoCould this be used to write dynamic analysers more easily? Like valgrind but without the need to decompile/modify/recompile the analyzed process.
- the8472 6y agoCould this also be used as a different way to prepare processes in the fork/exec dance? To do a post-exec setup instead of a pre-exec one.
- catern 6y agoThat's one of the things I use this kind of primitive for in https://github.com/catern/rsyscall https://github.com/catern/rsyscall
- andy_threos_io 6y agoIn our operating system (threos [1] ) this is the way the loader works (page fault exception handling code is from the loader task, mapped and running in the owner context) Also if you have permission, you can call CreateThread [2] system call and start a thread in other task. (Normally you don't have permission.) [1]: https://threos.io/ https://threos.io/ [2]: https://threos.io/docs/threos/html/syscall.html#syscall_CreateThread https://threos.io/docs/threos/html/syscall.html#syscall_Crea... Handle CreateThread(Handle task, PFN_THREADENTRY start, void* data, uintptr_t type, void* sp);
- cryptonector 6y agoSolaris has had a notion called an "agent thread" for a long time. Basically a debugger can attach to a process and start an "agent thread" in the victim process to run text that is sent to the agent thread to run. This has been used for all sorts of magical features like redirecting a running process' standard I/O handles. This is sufficiently hard to use that it was roundly hated. What you really want is a whole, parallel linker-loader environment in the agent thread so you could say "load this shared object and call this function in it with these arguments".