News for hackers. Stuff that matters.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @09:59AM (#37496850)
The author says the binary looks like malware because it self-deletes, sleeps and touches this uninstaller thing. But the script he proposes, which would be triggered by this same thing, does the same. I am ignoring the injection thing since he guesses at it (likely correct) and also because, lots of things inject into processes without being malware. (monitoring stuff like AV etc.) Additionally, binaries which terminate with a run some script via a scripthost... this could just as well be some malware? (stage1 malware downloads script, runs it via scripthost?)

my question(s): How is the proposed solution better than the original thing? Isn't this a case of using bad heuristics to determine maliciousness?

In the end, he goes a bit further, and sees its non-malicious. So, with a more elaborate rule or heuristic, wouldn't it be clear its not malicious?

Re:Any sufficiently advanced uninstaller is indistinguishabl... by ghostpepper on Wednesday September 13, 2023 @10:36AM (#37497327)
Once you move past comparing hashes against known malware (by definition useless against novel malware), and the slightly more complex matching of specific binary strings, detecting malware with "shitty heuristics" is basically all we've got.

Companies that buy AV/EDR products expect them to detect unwanted behaviour while allowing any sort of weird, hacky, abuses of the system that they rely upon for their business.

It's never been entirely clear to me why windows provides such a rich interface for one process to inject and start executing code in the address space of another but IMHO I want to know when this is happening even when it's done by a "legitimate" uninstaller.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @10:47AM (#37497460)
The first point is true i admit. There are very complex and good ways to identify stuff but those perform so bad they cannot be used in practice.

AV/EDR products do try to prevent a lot of stuff. They can 'generically' block things like injection etc. by 'hooking all the things' and injecting into everything (yes, yuck :D and still kind of heuristic based i admit!) to make certain sections read only or remove executable mappings etc. (got/plt/stack/...)

Linux or more specifically ELF files also have an easy vector to allow injection by having a dynamic table entry for debugging purposes which can be trivially overwritten for example. "ibc.so" :(). I'm not sure anyone uses that entry validly... especially since there's better/less awkward debugging interfaces than injecting a debugger DLL into something :') at least in x86/64 Linux land. (ELFShell sure was fun tho!)

Re:Any sufficiently advanced uninstaller is indistinguishabl... by monocasa on Wednesday September 13, 2023 @11:30AM (#37498119)
If you're talking about LD_PRELOAD, I used it for an integration test suite of low level system components.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @01:58PM (#37587474)
im not sure how the implementation of ld preload works, but this is a linker directive if i am correct. the thing i am on about is the DT_DEBUG dynamic table entry. its an entry meant to allow a debugging dll to be loaded. you can overwrite it and point it to a malicious dll (with a bit of difficulties) to get injection going. its then hardcoded into tue binary by your modification. admittedly maybe ld preload is easier if thats allowed on a system
Re:Any sufficiently advanced uninstaller is indistinguishabl... by pests on Thursday September 28, 2023 @03:08AM (#37686335)
LD_PRELOAD is handled entirely by ld.so and includeed inside your ELF by the linker. It not only handles that but also all dynamic linking inside your program.

By writing a custom linker you can easily incercept all dynamic linking done at runtime and provide whatever you want to the program.

gcc -Wl,-dynamic-linker,/path/to/my/linker myprogram.c -o myprogram

Re:Any sufficiently advanced uninstaller is indistinguishabl... by PcChip on Wednesday September 13, 2023 @10:06AM (#37496944)
>How is the proposed solution better than the original thing?

I'm only assuming here, but maybe because it won't crash explorer and it's just a few lines of self-documenting code?

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @10:34AM (#37497303)
Haha, well fair enough the crash is bad indeed, good point! This isn't intended behavior though and presumably, it doesn't crash on in cases of this technique being implemented in uninstallers. (a bit of a guess i admit!)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by ChrisSD on Wednesday September 13, 2023 @11:08AM (#37497781)
The fact it injects into another process means they can't know if it'll crash or not. You're just one Explorer update away from things changing enough for the hack to crash it.

I guess they could do this more robustly. I.e pause the entire explorer process, save all its state, remotely allocate new memory to inject their code, remotely create a new thread, run only that thread using the injected code, restore all the process' state and finally start it running where it left off. A script would be easier though.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by xp84 on Wednesday September 13, 2023 @01:24PM (#37499175)
Agree completely.

I would have assumed (naively?) that they could just copy their uninstaller into a temp folder and run it from there, and just rely on the OS to nuke it in due time, but as a consumer I appreciate the thoroughness of an uninstaller that leaves no trace.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @02:01PM (#37587521)
honestly your idea about the tmp dir i think is better than the no trace option. especially given the hacky nature of self deleting stuff. if you have so many uninstallers around that the disk fills up the tmp.dir cleaning would fix it, which is a common first thing to clean when cleaning the filesystem. i like your idea :)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by nneonneo on Wednesday September 13, 2023 @02:15PM (#37499789)
The problem isn’t that the injected thread is racing explorer - indeed, pausing the entirety of explorer to run your uninstaller would probably be strictly more dangerous than what they’re doing - the problem is that the injected thread is using function pointers that do not exist in explorer.exe. Most likely, the reason is that the uninstaller itself has been “detoured” by yet another program to patch calls to certain functions, and it’s copying the detoured addresses instead of the addresses to the real functions.

Both detouring and remote thread injection are supported on Windows, but fall into the category of gray-hat techniques; there are some legitimate uses but quite a lot of illegitimate uses, and using these techniques correctly (without crashing anything!) can be a real challenge.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by Arainach on Wednesday September 13, 2023 @03:53PM (#37500927)
You find the instructions to sweep your floor cumbersome so you reprogram your neighbor's Roomba to come clean your floor. Sure, it may well go back to their house and no harm done, but it's hacky, socially unacceptable, and no matter how hard your broom is to use it's not OK.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by S3rM5Y5 on Thursday September 14, 2023 @08:35PM (#37516687)
The technique could have been made a little more robust by calling GetProcAddress to get the function pointers in Explorer's context, assuming GetProcAddress wasn't itself detoured.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by kazinator on Wednesday September 13, 2023 @10:14AM (#37497053)
The .js script isn't injecting code into another program in order to deletee itself; it is deleeting itself directly.

It can do that because, I'm guessing, the file isn't open; the run-time isn't executing instructions from that file. The file was read, the content compiled into memory, and closed.

The script is deleting its source code, not itself. What actually deletes the script itself is the garbage collector in the run-time. Once the fso.Deletefile call and the for loop are executed, they are no longer reachable and so they are garbage. If there is a way for the "var fso" and "var path" variables to go out of scope, they become garbage also.

A binary executable is mapped into memory while the process is running it. In Windows, an open file cannot be deleted.

But, even on Windows, a prog.exe could delete the prog.c source code it was compiled from, right? Same thing, sort of.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by masfuerte on Wednesday September 13, 2023 @10:34AM (#37497302)
Being pedantic, you can delete open files on Windows if you open them with FILE_SHARE_DELETE.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @10:47AM (#37497462)
The script doesn't inject. But a lot of malware downloads a script and runs it, so you'd hit another rule.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by kazinator on Wednesday September 13, 2023 @12:57PM (#37498894)
The way I understand it, the uninstaller program that wants to delete itself doesn't have to download the script from anywhere; it generates the script out to a file.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @01:51PM (#37587361)
this is true, a good heuristic would see the difference perhaps. but malicious scripts can also be generated rather than downloaded (or more commonly decrypted from some seemonly random data) so it can be hard to tell, especially given threat actors having access to security products easily while the opposite is not always true.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by dmazzoni on Wednesday September 13, 2023 @01:27PM (#37499215)
Is the behavior that a running .js script is fully loaded into memory and the file doesn't need to exist documented, supported behavior?

What if, hypothetically, the system was suspended in the middle of script execution, and the resume function was designed to reload the script from disk?

It just feels like a different hack to me.

Also - trying 20 times and pausing 500 ms seems wasteful. What are the chances that it's going to succeed a subsequent try if it fails the first try? Why not catch the error message and only retry for errors that have a plausible chance of succeeding if you retry?

Re:Any sufficiently advanced uninstaller is indistinguishabl... by omnicognate on Wednesday September 13, 2023 @02:16PM (#37499796)
[delayed]
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @01:54PM (#37587413)
even though i admot this guy is genious level, its not really good to rely on one persons judgement for anything. thats a bad practice in general. zerotrust and all :)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by chrchang523 on Wednesday September 13, 2023 @02:27PM (#37499894)
Agree, I'm shocked at how ugly the recommended alternative is. This does not make MS look good.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by Arainach on Wednesday September 13, 2023 @03:51PM (#37500911)
There are plenty of other solutions; that was merely one straightforward option that could be shown in a few lines of code and which doesn't require *injecting code into a binary you don't own*.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by chrchang523 on Wednesday September 13, 2023 @04:12PM (#37501141)
Sure, but there isn't even an offhand remark about how hacky this kind of polling is. It's presented as if it's a completely normal way to do things in reliable software.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by kazinator on Wednesday September 13, 2023 @05:07PM (#37501739)
No worse than the 10 minute delay rule in DllCanUnloadNow.

DllCanUnloadNow returns an indication that a DLL can be unloaded. A DLL cannot be unloaded if any threads are executing the code. But a DLL can only change to the unloadable state by executing some code, and that code has to return after it has set the indication. Only after it returns is the DLL is actually unloadable! So a delay is needed for that thread to vacate the DLL.

https://groups.google.com/g/microsoft.public.vc.atl/c/AQvHCW... [2001]

Re:Any sufficiently advanced uninstaller is indistinguishabl... by kazinator on Wednesday September 13, 2023 @06:56PM (#37502759)
So in the present example from Raymond Chen you need the loop for a similar reason.

The binary .exe program which the script is trying to delete is the one which created the script and launched it. So that means the .exe is still running at that point and cannot yet be deleted. Lauching the script indicates "I'm about to die", not "I'm already dead". The script cannot delete the .exe until the .exe terminates. Without some event to indicate that, you poll.

The script knows it can delete itself, so it tries that only once.

If a handle could be attached to the process, then the script could do a WaitForSingleObject on it; that would be the prim and proper way.

It doesn't seem worth doing; the chances are low that the process cannot terminate within 20 seconds of launching the reaper script.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @01:55PM (#37587433)
i am not shocked, but its hacky like comments suggested. ultimately done because the lack of a better alternative. id still follow chens advice even though its hacky.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by Arainach on Wednesday September 13, 2023 @03:48PM (#37500888)
There is never a good reason to inject code into another process - particularly a system process. At the point at which you believe this is necessary you are several layers of hackiness deep and should go find a beverage and think over what your actual goal is.

As a metaphor: you find the instructions to sweep your floor cumbersome so you reprogram your neighbor's Roomba to come clean your floor. Sure, it may well go back to their house and no harm done, but it's hacky, socially unacceptable, and no matter how hard your broom is to use it's not OK.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @01:54PM (#37587395)
security products have valid reasons, though maybe not _good_. forcing plt and got entries to be bound rather than lazy loaded, forcing certain segments to be read only and hooking a bunch of stuff is neccesary for them, and that can only be done by suspending processes at startup and then injecting and modifying them. its a bandaid to a bad system hence its a valid but maybe not good reason (better to prevent than this cure of theirs..)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by slaymaker1907 on Wednesday September 13, 2023 @03:48PM (#37500890)
Even if it doesn't, I think you could do something similar by just spawning a shell (command prompt) that executes a small script trying to delete the file. You just have to take care to make sure the process is detached from the original one and then let the spawning process terminate to release the lock on the executable. PowerShell could also work, but I know it is pretty restricted in a lot of environments. These completely avoid any intermediate file.

I think the retry is necessary because if you launch "wscript cleanup.js" from the process that wants to be cleaned up, you then need to wait for the spawning process to finish executing. I agree if it fails after 20 times, you should probably spawn an alert or something letting the user know that uninstall failed. There are also so many random processes that might take a reference on the file like antivirus in Windows so just spamming retry will help wait that stuff out (this problem does not exist on Linux since Linux generally just does garbage collection which has the downside of not keeping specific paths around, just file inodes).

Re:Any sufficiently advanced uninstaller is indistinguishabl... by thombat on Wednesday September 13, 2023 @10:26AM (#37497200)
It's more about how it does it: injecting executable code directly into the stack so that some other code unwittingly transfers control to it. Stack-smashing is a lot more malware-ISH than a few lines of shell script.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @10:40AM (#37497378)
They inject something into Explorer. I would assume that to be some DLL that is injected?

---- Neither code injection nor detouring is officially supported. I can’t tell who did the detouring. Maybe somebody added a detour to the uninstaller, unaware that the uninstaller is going to inject a call to the detour into Explorer. Or maybe the detour was injected by anti-malware software. Or maybe the detour was injected by Windows’ own application compatibility layer. Whatever the reason, the result was a crash in Explorer. ----

I'd think the anti-malware guess here would be correct, and that (DLL) injection was stopped, and thus some crash happened. Thanks for your reply.

The DLL would execute something from its stack so it can be somewhat dynamic (perhaps some path or something is generated before the injection or so - really little to go on here...) and not need to make a heap allocation within Explorer.exe. (this is perhaps a bit too much to assume idk.)

Thanks for your insights!

Re:Any sufficiently advanced uninstaller is indistinguishabl... by darkclouds on Wednesday September 13, 2023 @01:14PM (#37499074)
>I can’t tell who did the detouring

I was thinking hmm and so it continues that game of whack a mole.

If a new OS could be designed from scratch, there must be a way to prevent this sort of stuff.

Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 20, 2023 @02:02PM (#37587549)
i am making an os from scratch. but admittedly, i am so far from this stuff i will never ever have anything even closely related to such a problem hah. its so much work :'( (fun tho!)
Re:Any sufficiently advanced uninstaller is indistinguishabl... by oefrha on Wednesday September 13, 2023 @10:10AM (#37496996)
Maybe it’s less likely to be flagged or interfered with by antivirus? Antivirus uses all kinds of shitty heuristics, seeing that my Go executables built with -ldflags="-H windowsgui" are flagged as malware by Windows Defender and co. all the time. It’s maddening.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by sim7c00 on Wednesday September 13, 2023 @10:48AM (#37497473)
that's fair enough. perhaps they can more easily in AV land make some kind of signature that whitelists this self-deletion javascript method because the script is more readable. though i'd expect a good AV to be at least worried if some executable on my system runs a script file via a scripthost.
Re:Any sufficiently advanced uninstaller is indistinguishabl... by some_random on Wednesday September 13, 2023 @10:57AM (#37497601)
Cybersecurity is pretty much all bad heuristics with the belief that if you use enough of them they average out to an ok determination of maliciousness. It works alright, sometimes.