Code injection like this is why we have historically been unable to enable stronger process mitigations for Chrome that might improve security and stability. It's a real pity :(
Didn't Microsoft do this in the old pre-Chromium Edge? It probably would've caused more of an outcry from users if anyone actually used the old Edge as their primary browser. Personally, I feel like this is the "wrong way" to enhance browser security. Should the browser, as important as it is, behave fundamentally differently than all other processes within an OS? What about other VIPs (Very Important Programs)? Who's to decide which apps are important enough? The right way, to me, would be for the Chrome/Chromium team (along with other browser vendors) to lobby and/or work with OS vendors such as MS, Apple, Canonical, etc. to come up with sensible OS mechanisms to limit dynamic code, with appropriate user control and override options. Sure, that's a bigger undertaking and "some users will be confused" as always. But it's not worth it to me to keep shrinking what part of my personal computer I can actually control just to gain a little bit more security and stability. I want to be the one to make the choices and strike a balance that's personally right for me. So for that reason, I hope this is one feature flag you will never enable by default.
Have to agree with you. You can find some good posts (blog posts? I forget) where an MS engineer explains why the desktop on Windows is as messy as it is. The gist of it was, they did actually try basically everything else and had various types of security, but anything but having the desktop as a single security boundary (at least as far as interaction was concerned) made everything too complicated and brittle.
For this reason I highly doubt wayland will really work as intended. We're going to end up with a middle shim layer that basically acts as X11 but doesn't look like it.
macOS has been moving this direction for a while. To inject code into an appropriately prepared process on that platform, you will need to generally want to run as root, have to attach to the process as a debugger, and then patch it. Plus there are APIs to suspend processes at creation and such.
If you need to hook methods in a remote process (and also inject payload), you may also consider the Detours library [1]. It has a straightforward API and its repository contains many interesting samples. One thing I was missing in the library was a function to inject code into a running process. So I wrote takedetour [2] which I use as a template for my other projects. Maybe you will find it useful as well.
Fun fact: in the #winprog irc channel on efnet in the 90s/early 00s, "how do I hook into another program's messages?" was the most common question asked by people new to the channel.
My preferred method was manipulating IAT table (Import Address Table) where the code injected into process is hooking CreateProcess and LoadLibrary (and similar) to further propagate injection into other processes/library spawned by current process(es) and using debug privileges to also inject into system processes (like login process on windows 2000, to survive logoff)
Anyway Microsoft Detours is the way to go, they actually modify the code of hooked function using trampolines, I don't think anything can be more efficient than that.
Lost? Past? The Windows world still runs on this stuff, and there are still plenty of people who know how it works and make money from knowing.
That said, MS have unintentionally (I think) done a pretty good job of scrubbing the internet clean of useful information about it by breaking all their links multiple times. I keep a personal copy of some things, such as Matt Pietrek's classic two-parter "An In-Depth Look into the Win32 Portable Executable File Format", lest they disappear completely while the technologies they describe continue to run the world.
Edit: MS only appear to have part 2 of that article in their archive, and it contains broken links (of course). Both parts can still be read at [1] and [2] and remain as relevant as they were the day they were written
Does anyone know about something similar on macOS? Environment variables like DYLD_INSERT_LIBRARIES or functions like mach_inject, dl_open and others are automatically disabled for processes protected by hardened runtime. I'm wondering if it's possible to inject to process only by exploiting the OS.
You will need to disable SIP (and library validation) to do this, because your code signature will not match the target process's, which is kind of what this is intended to prevent. This is also why you cannot attach a debugger to arbitrary processes when those protections are engaged. But once you turn that off, there's a lot you can do, here's one of my projects that might give you an idea of one way to do this: https://gist.github.com/a70d44951cb72f82efee3317d80ac07f
I think that disabling SIP can break some programs and it's hard to do for a normal user right? I'm curious how anti-malware software is doing this, because it's doing a lot of fancy stuff, maybe I should look into it by reverse engineering one of them. Thanks for the link I'll definitely check it out.
The hardest thing to wrap my head around in Windows is how perfectly normal and common to load new code into existing processes. There are well-known APIs to do it.
Non elevated process can't inject into elevated process. X user process can't inject into Y user process.
If user has access to process, they have very well access to modify by decompiling or reverse engineering it. Dynamic injection makes it much more seamless and less painful.
Here https://news.ycombinator.com/item?id=31092978 suggests its not possible to prevent code injection aka system or app hooks. Preventing system and app hooks is very possible and the MS api's gve you all you need to block them, people just need to come up with innovative ways to deploy them!
I don't think the comment by wfh is saying that it's not possible to prevent these hooks. In fact, wfh is saying the opposite, i.e. that they already have the mitigation in place, but cannot enable it because there are legitimate use cases for hooking/injection, and users who use programs that depend on these techniques would be (rightly) upset if Chrome unilaterally decided to block all such use cases. The comment is lamenting the fact that the author of the blog post is creating yet more such use cases and will make it even harder for Chrome to ever enable the feature to prevent code injection.
I don't have a question, but I wanted to let you know that you can enumerate processes and threads via NtQuerySystemInformation instead of CreateToolhelp32Snapshot, and it's much faster. The latter is slow only due to weird file section mapping behavior and not due to the actual query.
Thanks for the tip, I tried that. It might be a bit faster, but in my tests, it wasn't significant, and it still enumerates all system threads which means that it becomes slower the more threads your system has.
A truly fast and documented solution is using PssCaptureSnapshot, it can enumerate only threads of the target process. It uses NtGetNextThread under the hood. The downside: it's only available from Windows 8.1.
Using NtGetNextThread is not only fast and available from Windows Vista, it also allows avoiding race conditions - what happens if a new thread is created after the snapshot is created? A snapshot returns thread ids, what happens if one of the threads is destroyed? What happens if the thread id is reused (unlikely but possible)? I believe all the benefits I'm getting by using NtGetNextThread are worth using an undocumented function.
https://bugs.chromium.org/p/chromium/issues/detail?id=851565...
The flag we (still) can't enable by default is
--enable-features=BrowserDynamicCodeDisabled