Earlier quoted context omitted.
Yes. That's pretty common, unfortunately.
I'd love to see Chrome and Firefox and IE working together to detect this kind of thing and put up a malware warning explaining how to uninstall it, and see how quickly it can be eliminated. Seriously, there is zero valid reason to ever inject code into another program, other than as a debugging tool on a system being debugged.
Please restore our registers when you’re done with them
81–90 of 142 posts
Re: Please restore our registers when you’re done with them
#82Earlier quoted context omitted.
It would just be slow for the caller to have to push and pop (say 30) registers in general that the specific callee (and transitive callees) may not even use. Most ABI specify some registers caller-saved, some registers callee-saved (retained unchanged from the perspective of the caller) and some registers scratch (not-saved). In the end it depends on the architecture and on typical workload which are the fastest--an…
You usually wouldn't need to push&pop all registers, just ones that you want to preserve across the call. Regardless, yeah, non-volatile aka callee-saved registers are extremely important for good performance of code that calls functions (esp. loops - without callee-saved registers, you'd have to store the loop counter & length on the stack!)
If someone is trying to use the same assembler routine on Windows as on Linux, it's likely to be wrong for one of them.
Re: Please restore our registers when you’re done with them
#83Earlier quoted context omitted.
Not worth checking for. The few people who write assembly code these days know what they are doing, and, bugs aside, the compiler knows what to do.
The old Russian proverb is "Trust but verify." I, for one, hate debugging asm. I do it a lot, and would prefer bugs be caught automatically, preferably soon after they are introduced.
It's not clear to me how to write such a tool as assembly code is the opposite of structured.
Re: Please restore our registers when you’re done with them
#84Earlier quoted context omitted.
My reading of it was that the bug was caused by XMM7 not being restored to its previous value. E.g. on Linux, functions should restore the values of ebx, esi, edi, ... once they're done with them. The article says (on Windows) that XMM7 needs to be restored too. If you can't trust one register being preserved (per the ABI), then you really can't trust the values of any registers.
Fair point, which is why I used the phrase "this particular example." In fact the compiler's lazy assumption about XMM7 was the key to determining that the ABI was being violated. It would have taken longer to figure this out if the compiler had been doing things my way, because then a failure of the callee to preserve XMM7 wouldn't have mattered.
Re: Please restore our registers when you’re done with them
#85Earlier quoted context omitted.
Yes. That's pretty common, unfortunately.
I'd love to see Chrome and Firefox and IE working together to detect this kind of thing and put up a malware warning explaining how to uninstall it, and see how quickly it can be eliminated. Seriously, there is zero valid reason to ever inject code into another program, other than as a debugging tool on a system being debugged.
It is potentially a bit fragile though - DLLs can load other DLLs, and it has happened before that in a new Windows version, Microsoft suddenly adds new implementation DLLs which get pulled in by the main system DLLs.
One approach might be to look at code-signing on all the DLLs, and ignore any unknown DLLs signed by Microsoft.
Would probably make sense to open a scary red warning at startup, telling users that their browser contains untrusted third party code, and stability/security cannot be guaranteed. Probably need to make sure there is no easy way to disable it, or else some IT will just disable it as part of installing DLL-injecting "security" software.
There are ways of doing hidden code injection, without the DLL coming up in the loaded DLLs list – https://reverseengineering.stackexchange.com/questions/2262/... – one option is for the loaded DLL to duplicate itself in memory, jump to the duplicate, then unload the original. Or, you can use VirtualAlloc2/WriteProcessMemory to load code into another process, and CreateRemoteThread to launch it.
I thought these "security" software vendors wouldn't be doing anything so fancy: but from the Chrome bug [0] it looks like some are:
> And I was able to confirm (in some of the dumps, we don't collect the right heap information in all dumps) that Trend Micro code (one region is a DLL that seems to be called ApiHookStub.x64.dll, another is not a direct DLL copy) which has been allocated on our process heap without going through the loader, presumably via something like ::VirtualProtectEx and ::WriteProcessMemory. This is a pattern I see used broadly in Edge crashes we root cause to third-party software.
However, that still can be detected – use VirtualQueryEx to iterate through process address space and find all executable memory regions – any not owned by a loaded DLL (or generated by JavaScript JIT/etc) are evidence of code injection, even if you don't know who the injector is.
[0] https://bugs.chromium.org/p/chromium/issues/detail?id=121838...
Re: Please restore our registers when you’re done with them
#86I think the real fix is to set all registers to a canary value at the start of int main(), and then when exiting check the canary value is still there. If anything has messed with any registers without permission, you crash and collect as much data as possible about any injected dll's. Then you correlate these to find the culprits, and for each you contact the authors of the DLL and figure out a way to block the inje…
Re: Please restore our registers when you’re done with them
#87Naïve question about ABIs: shouldn’t the caller be responsible for that? If I want a function to restore certain registers, wouldn’t it be simpler if I was the one that save them on my memory, call the function, and then override the registers with whatever values the function set? Otherwise it seems we’re just… asking for trouble, so to speak.
It's common to say "caller cleans up registers x, y, z, callee cleans up a, b, c".
So yes, the caller could do it or not do it, the choices are all possible to do both ways, but that wouldn't be the agreed upon ABI, it'd be something different.
Re: Please restore our registers when you’re done with them
#88Earlier quoted context omitted.
Yes. That's pretty common, unfortunately.
I'd love to see Chrome and Firefox and IE working together to detect this kind of thing and put up a malware warning explaining how to uninstall it, and see how quickly it can be eliminated. Seriously, there is zero valid reason to ever inject code into another program, other than as a debugging tool on a system being debugged.
Re: Please restore our registers when you’re done with them
#89Earlier quoted context omitted.
I'd love to see Chrome and Firefox and IE working together to detect this kind of thing and put up a malware warning explaining how to uninstall it, and see how quickly it can be eliminated. Seriously, there is zero valid reason to ever inject code into another program, other than as a debugging tool on a system being debugged.
On Windows, you can call "EnumProcessModules" to get all the DLLs loaded in the current process – and check those are what you expect. It is potentially a bit fragile though - DLLs can load other DLLs, and it has happened before that in a new Windows version, Microsoft suddenly adds new implementation DLLs which get pulled in by the main system DLLs. One approach might be to look at code-signing on all the DLLs, and…
And, as you say, code injection is possible without loading a DLL, and does seem to happen.
In this case I don't understand how the state leaked from the file-system filter driver to our process, as it seems to have done. It's a mystery.
I have plans to do the address space iteration you speak of in our crash reporter.
Re: Please restore our registers when you’re done with them
#90I used to take point for Mozilla's efforts dealing with third-party interference in our binaries. Browsers are ripe targets for this kind of shit. The stories we could tell...