 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5
| Analysis of Backstealth technology There has been discussion here about the "Backstealth" trojan, but I'm not sure if there has been much talk about exactly how it works. I've been disassembling it and have a pretty good idea how it operates. This is my analysis of it so far. Note that I'm not really strong on the Win32 calls involved here so am doing a certain amount of hand-waving in my explanations. But I have a pretty good idea how it's working.
This proof-of-concept comes in two parts: backstealth.exe and backdll.dll.
Backstealth.exe contains the new idea here: it searches for the personal firewall process and infects it with a bit of code at runtime. Then this bit of code is actually executed in the firewall's address space, and it is able to talk to the internet without notice.
Backdll.dll is the code that ultimately gets run in the firewall's address space, and the one provided is just sample code: it fetches a file. Within certain parameters, this code could in practice do nearly anything.
The infected code doesn't seem to interact with the firewall itself, so it's not like it's taking firewall-specific countermeasures: it simply relies on the fact that the firewall trusts itself.
How Backstealth seems to work
This discussion is at the C programming level talking to the Win32 API - "regular users" don't see any of these functions.
First, backstealth uses FindWindow() to search by name for the signature window of each firewall. The windows and their names- Sygate Personal Firewall Pro (with class #32770)
- McAfee_FwClientClass (with class McAfee_FwClientClass
- TinyPersonalFirewallMainWindow (with class #32770)
- no window name, but with class Symantec NAMApp Class
- KerioPersonalFirewallMainWindow (with class #32770)
I don't know whether these are actually visible windows or not, but I'm pretty sure it doesn't matter. The name of the firewall .EXE doesn't matter at all - renaming won't help.
Each of the firewalls is searched in order, but only the last one found is chosen for infection.
If the firewall's window handle is found, GetWindowThreadProcessId() is called to get a handle to the firewall process itself. This handle will gives access to all the manipulations that follow.
The program uses AdjustTokenPrivileges() to give itself permission to "do stuff" to the other process. This probably won't work for non-admin users, and I've not looked at it in that much detail. If this step fails, the injection can't happen.
It then calls VirtualAllocEx() to allocate a chunk of memory in the firewall process itself (yes, remotely), and I believe that the remote process can't detect this. The returned address is valid only in the remote process, but we can write to it from here.
Then it uses WriteProcessMemory() to remotely poke in some data to this newly-allocated space. This data includes a small bit of code. Again, it's a pretty safe bet that the remote process cannot detect that this new chunk of memory that it doesn't know about is starting to be filled in with Bad Stuff.
Then, CreateRemoteThread() is called to launch a new thread that uses the newly-allocated memory as the code base. Now the remote process - the firewall - has a new thread running that it doesn't know anything about. And since the firewall generally trusts itself, that thread's network access is unnoticed.
But Gwion had the bright idea to tell Kerio to watch itself, and it was able to catch this outbound access.
Impact
This technique rests squarely on the ability of the injection .EXE to run on the user's machine, and good computing practices should protect you. It's likely that there are those who rely on their firewall to catch the bad stuff do they can work without thinking, and they are the ones at risk.
How the firewall vendors will address this is unclear: protecting the user from himself is not always such an easy job.
Edit - minor technical updates
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net [text was edited by author 2002-05-02 13:32:59] |
|
 YinYangCelestial Phenomenon join:2002-04-24 Kissimmee, FL | Great info on this! I'm also going to be adding Gwion's rule to block this. -- Everything is a differentiation of One Infinity. |
|
 | reply to Steve So, backstealth technology relies on the fact that your firewall trusts its own process and memory space -- interesting. |
|
 gwionwild colonial boyPremium,ExMod 2001-08 join:2000-12-28 Pittsburgh, PA kudos:1 | reply to Steve Steve, you're priceless. Thanks. Very much appreciated. |
|
 jvmorrisI Am The Man Who Was Not There.Premium,MVM join:2001-04-03 Reston, VA | reply to Steve Steve,
Nice piece of work! Knew you couldn't resist! 
For those like myself who aren't going to play with this baby, -- How big is BackStealth.exe? -- How bit is BackStealth.dll?
Just for general sizing information.
Understand your comment on BackStealth.dll. Like CRv1, I suppose we ought to be damn glad that it doesn't do anything more than it current does.
Re FindWindow(), now are you saying you KNOW it only searches for these signature windows or are you assuming that? If the former, then that would answer one of my questions as to whether it even tries to run with ZA/ZAP.
Re AdjustTokenPriviileges(), effectively Win 9X/ME users would consequently have no protection against this call (assuming it works on those OSs). Win NT/2K/XP users would have at least some protection running with a non-Admin account? (Which would be consistent with some recent posts by gwion in the Tiny-Kerio Program.)
As always, much thanks. (Warming up for the summer season, are you? ) -- Regards, Joseph V. Morris |
|
|
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5
| -- How big is BackStealth.exe? 58,368 bytes -- How big is BackDLL.dll? 55,808 bytes quote: Re FindWindow(), now are you saying you KNOW it only searches for these signature windows or are you assuming that?
I'm looking at the disassembled code, not strings in the binary: this is all it looks for. But in general, it's not in concept looking for "firewall processes" as it is "processes known to be trusted". My guess is that it could inject itself into IE with the same ease - most of the time IE is trusted as well, and this hidden worker thread would not likely go through all the security setup imposed by the browser. quote: Re AdjustTokenPriviileges(), effectively Win 9X/ME users would consequently have no protection against this call (assuming it works on those OSs)
This is true in any case. On an operating system with no real hardware protection of memory (as you have on the Win 9x/ME), there is next to nothing you can do to keep really mal-intentioned code from behaving badly. It may be a lot of work, but once bad code gets the CPU, you're finished.
Edit: - typos
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net [text was edited by author 2002-05-02 14:44:07] |
|
 | reply to Steve Just a data point Backstealth doesn't make a connection on win98 although it identifies correctly the target fw(s) lack of debug privileges 
Cudni |
|
 gwionwild colonial boyPremium,ExMod 2001-08 join:2000-12-28 Pittsburgh, PA kudos:1
| reply to Steve Well, trying to run this as "user" in my NT setup kills it instantly... just plain dies the minute I press the go button. I saw a few log entries "denied" referring to it... and some attempted accesses contemporaneous with the test that are unusual ... some service controller and token stuff, but I'm not looking at it, right now, so that's my best comment, for now.
Haven't had a chance to review them all... but something in that configuration is murder on this exploit. I wish I could put my finger on what it is...
Probably immaterial, though, since most win users are reticent about running as admin full time, anyhow... defeating any real advantage that NT family security provides pretty much entirely. Which was why I took it to a junker and ran it as admin to start off, figuring that would be the way 80% of users will be running... and, of course, that 9x users have no choice at all in the matter ... -- Forget and forgive. This is not difficult, when properly understood. It means you are to forget inconvenient duties, and forgive yourself for forgetting. In time, by rigid practice and stern determination, it comes easy. - Mark Twain [text was edited by author 2002-05-02 14:48:10] |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | reply to Steve A bit more study reveals how this works.
The injecting program (backstealth.exe) creates a small memory buffer that contains data that will be needed by the remote thread: this includes the addresses of three key functions in the KERNEL32 DLL (GetProcAddr(), LoadLibrary(), FreeLibrary()), along with the full pathname of the backdll.dll to load and the name of the entry point function (themain).
These bits of data are all copied to the start of the memory allocated by VirtualAllocEx(), and the injection subroutine is copied to follow it. This is a fairly small amount of memory in total, perhaps 1 kbyte.
Once the memory has been crafted, the remote thread is executed at the start of the copied injection subroutine. This gets things going over in the remote process.
The concept of "starting a remote thread" is foreign to UNIX folks, where processes are much more inviolable than they are under Win32. This is not really a bug in Win32 at all - it's a feature, but it should be protected by the permission structure.
This injection subroutine is really simple: a classic trampoline function. It simply loads the requested DLL, finds the entry point, and calls it - it has no idea what the loaded DLL does, nor does it care. All the "real" work is done by the secondary DLL (backdll).
... and the SetProcessToken() business is used to grant the current process the seDebugPrivilege right. "Privileges" are the ability to do a thing, as opposed to "Access Permissions" which are the ability to access an object. "Debug another process" is a privilege. "Read a file" is a permission.
I believe that this whole technology won't work on 95/98/Me, but it's not due to the lack of the debug privilege. The key function is CreateRemoteThread, which is not supported under these operating systems.
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | reply to gwion said by gwion: Well, trying to run this as "user" in my NT setup kills it instantly...
Most likely the process is not able to acquire the seDebugPrivilege right. Run the program in a cmd window and there should be debugging information to the console.
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|
 SentinelPremium join:2001-02-07 Florida kudos:1 | reply to Steve said by Steve: snip... I believe that this whole technology won't work on 95/98/Me, but it's not due to the lack of the debug privilege. The key function is CreateRemoteThread, which is not supported under these operating systems.
This thread is way to far over my head but I am trying to read it anyway in hopes of someday getting smarter but... I did catch this quote and I saw something that interested me. Are you saying that this whole thing is a non-issue on Win9x based systems because of their inability to do something that is possible on NT based systems? Or am I reading that wrong? -- AL |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | said by Al Otero: Are you saying that this whole thing is a non-issue on Win9x based systems because of their inability to do something that is possible on NT based systems?
I think that's a good way to put it: the program backstealth simply relies on the ability to create a remote thread, and if it can't, it will fail. That just means that 9x is immune to this exploit.
But because it's a much more "open" memory architecture (aka, "unprotected"), it seems to me that with some effort somebody could accomplish more or less the same thing by doing this "the hard way". It might be too hard tobe worth the bother, but I'm pretty sure that in this battle, the bad guys will ultimately get the upper hand on the 9x/ME front.
... but I could be wrong on all of this - it's been a hasty analysis.
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | ... and I'd like to take this chance to sing a happy song about the fantastic disassembler I use, "IDA Pro" from DataRescue. The last time I jumped into disassembling something (Code Red II), I was using an utter piece of crap that made life lousy. I was determined not to go through that again, so I looked in to IDA Pro.
What a fantastic piece of software. It's an interactive disassembler that runs under Windows, and it's simply spectacular in its ability to turn "bytes" back into "programs". They have modules to disassemble nearly anything, and they recognize most of the popular C runtime libraries so that "unknown_sub_1235" is actually recognized as "printf". It's just stunningly good.
Highest possible recommendation for this work of art.
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|
 R2R NotPremium,MVM join:2000-09-18 Long Beach, CA kudos:1 | reply to Steve Steve - is ZoneAlarm immune to this vulnerability -- or just immune to this demonstration of the vulnerability? I noticed that by your report backstealth.exe does NOT go looking for ZA -- so it was NEVER intended to test ZA. |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | said by R2: is ZoneAlarm immune to this vulnerability -- or just immune to this demonstration of the vulnerability?
All I know is that the program doesn't check for it, and I thought I remember reading somewhere that the technique doesn't work for ZA (I can't find that reference now).
I don't run any of the personal firewalls so I can't test it out, nor do I know how a piece of software would defend itself this in the general case.
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|
 R2R NotPremium,MVM join:2000-09-18 Long Beach, CA kudos:1 | One source of the reference was ZoneLabs, but I would like to have a third-party source verify this...
Clearly, testing "backstealth" on a system using ZoneAlarm is not going to be a useful endeavor. Thanks. |
|
 jvmorrisI Am The Man Who Was Not There.Premium,MVM join:2001-04-03 Reston, VA | reply to Steve Steve,
If we've been reading the same comments, we've been seeing a bit of inductive reasoning. To wit:
Statements that Zone Alarm is not affected by BackStealth, which is then used to conclude that Zone Alarm is invulnerable to BackStealth.
All of which, of course, would be true by definition.
However, it continues to beg the question as to whether Zone Alarm can be exploited based on this vulnerability demonstrated by BackStealth.
I don't know one way or the other and I won't pretend that I do. What I would like to see is a definitive statement (one way or the other) as to whether ZA/ZAP (by version) on a particular OS is or is not vulnerable to the fundamental vulnerability upon which the BackStealth vulnerability demonstrator is based. I've been waiting for about 48 hours now, but still haven't seen any such definitive statement (again, one way or the other). -- Regards, Joseph V. Morris |
|
 R2R NotPremium,MVM join:2000-09-18 Long Beach, CA kudos:1 | I agree completely.
Which begs the next question -- did the creator of backstealth purposefully not attempt test ZA??
Again, I also have no bloody idea, but I am interested only from a security standpoint. If ZA is vulnerable, but the vulnerability is not tested, Zonelabs will have no 'pressure' to 'fix' ZoneAlarm...
I would relish a definitive answer. |
|
 gwionwild colonial boyPremium,ExMod 2001-08 join:2000-12-28 Pittsburgh, PA kudos:1
| reply to Steve "Can't open process. 5. ERROR"

That was the termination message that appears in the console...
... edit: and consider, too, that the implicit rules issue this has uncovered (again) is another vulnerability altogether. What good purpose do open-ended allow rules serve for the user? I make a practice of preaching to people, look, if you want to run a PC firewall, then do it right and restrict remote endpoints as much as possible... and here, we see the manufacturers putting unloggable, un-overridable implicit rules, and compounding the issues by making the remote endpoint "any remote host, port 80!" Why do I bother? Hell, that's unbelievable. They mean to tell me my firewall can connect to "porn_n_warez.com" as easily as update.kerio.com ? That's a serious problem. What purpose does a non-closable, non-loggable implicit rule serve to begin with? And even if there's an explanation, why... why on earth... make the rule endpoint "ANY" remote host??? [text was edited by author 2002-05-02 17:41:08] |
|
 SteveI know your IP addressConsultant join:2001-03-10 Yorba Linda, CA kudos:5 | said by gwion: "Can't open process. 5. ERROR"
"5" is a Win32 error code code:
C> net helpmsg 5
Access is denied.
No permission to open the process because it clearly couldn't get the debug privilege. It probably also printed the message Failed enabling Debug privilege. Proceeding anyway, right?
Steve -- Stephen J. Friedl Security Consultant Tustin, California USA »www.unixwiz.net |
|