Log in

View Full Version : Ring 0 anti-debugger code in Daemon Tools?


dELTA
June 18th, 2006, 13:07
I was unpleasantly surprised when I just downloaded the latest Daemon Tools version from the official website.

First of all, the software now contains (opt-out) spyware. Secondly, and most important in this context, the following message is shown during install:

Quote:
This program will install SCSI Pass Through Direct (SPTD) layer on your computer.
WARNING - SPTD is not compatible with kernel mode debuggers (SoftICE, WinDBG etc.)!
Please cancel setup if you plan to use kernel debugger on this machine.


So, this software makes the machine unusable for any kernel debuggers, not so nice, and very intrusive...

Is there any valid reason for this, or is it just a very intrusive anti-debugger protection inside their driver?

Has anyone looked into this any further, or know anything more about it in general?

CrackZ
June 18th, 2006, 13:54
Heya dELTA,

Had the same nasty surprise myself, I'm not even a big Daemon Tools fan either (just needed it for burning a particular ISO format).

My problem was further compounded by the fact I was tracing a rather evil protection system as well, took me a time to realise the culprit was actually Daemon Tools.

There doesn't seem to me to be any good reason for this detection other than to stop people from delving inside the code. I have the installer still on this box, planning to investigate it at some point.

Regards

CrackZ.

dELTA
June 18th, 2006, 14:32
Thanks for the info CrackZ, indeed interesting to hear that it was not an "empty threat" from their side. If you'd like to share some more details about exactly how Daemon Tools interferes with the kernel mode debugging/debuggers on a machine, I'm sure there are more people here than me who would be interested to hear about it.

If nothing else, more exactly what kind of damage/problems does it cause? Will a simple uninstall of Daemon Tools restore the situation to normal?

0xf001
June 18th, 2006, 17:27
heya,

I remember this thread - related to the kernel debugger incompatibilities:

http://www.woodmann.com/forum/showthread.php?t=7894&highlight=SPTD

regards, 0xf001

doug
June 18th, 2006, 21:38
It's always impressive to see old time crackers that think that they can make the uncrackable protection. I'm not sure if it's the ego or simply that they are naive, the end result is the same - the protection never stays uncracked for too long. In the case of dtools, I think they are trying to avoid copy-protection ppl from spying on their tool to see how it works and then blacklist it. An honest, but futile attempt at preventing it.

Basically, it is in line with every other piece of software that tries to block debuggers, where as even in cases where you use the debugger for non-RCE purposes, you still get annoyed by that program that's supposed to be idle but crashes your PC as soon as a debugger starts.

This is an annoyance that you'll have to live with. You could always roll back to the 3.x version (which also use the 'incompatible' scsi pass through btw), which worked perfectly fine with every debugger out there.

Aimless
June 18th, 2006, 23:58
Personally, I always thought Deamon tools to be crap. Just the small footprint is the advantage.

Alcohol is better. And there are many full versions "out there". Just my 2 cents.

Have Phun

LLXX
June 19th, 2006, 04:24
I've encountered a *lot* of soft that contains anti-debug. However, I always have a debugger ready (SoftICE). What to do? Hide the 'ice, and use it to kill the antidebug from whatever soft has it. No more problem

dELTA
June 19th, 2006, 04:39
Thanks a lot for the reference to that old thread 0xf001! I guess the reason I didn't remember it was because it got so massively off-topic so quick... I've updated the personal search index in my head with it now anyway.

omega_red
July 5th, 2006, 19:55
I'm using d-tools at work for some automated tasks involving ISO images. Some time ago, out of curiosity I've run ntcrash utility from sysinternals - it basically tries all system calls with some random data in order to find insecure drivers. To my surprise, I got a BSOD. After reboot, I went to event log and found that "sptd.sys" driver was responsible for it. Too bad I didn't investigate it further, just thought it's some buggy system stuff.

Some time passed. One day I rebooted my machine after automatic windows update (or maybe it was after installing some new d-tools version, can't remember). Woops - surprise, BSOD at boot. WTF, I thought? Booted to safe mode - all works fine. After some poking and sniffing, I uninstalled d-tools, and voila - system boots without problems. Right, something was *seriously* wrong here. I uninstalled d-tools for good, but again, didn't investigate the issue further.

Meanwhile, at my home system, I started to experience weird performance loss issues in some games. Again, after some tries and errors, I got rid of d-tools and the problems disappeared.

Some more time passed. I've written a tool that lists all kernel system calls and modules responsible for their service. It seemed to work fine, I got a nice list from fresh windows install. Then I run it on some other machine. WTF? Some syscalls were <unknown> (dbghelp couldn't find symbols for them), located in... surprise, sptd.sys! Riiight. Let's compare list from "clean" OS and "hooked" one. Result? All registry calls were hooked.

And finally, a few days ago I went to d-tools site. Oh, a new version!
Quote:
we updated latest DaemonTools (V4.0.3) with latest available SPTD-Driver (V1.25)!

The new SPTD fixes several critical issues, a problem with McAfee-Virus-Scan and VistaBeta2-Problems!
The X64-Version also fixes the latest issues between SPTD introduced by Microsoft-patch KB 914784

Interesting... What's that hotfix?
Quote:
Microsoft Security Advisory: Update to improve kernel patch protection

It seems like it's only for x64 systems - my home system is xp x64. Neat.
I went to d-tools download section.
Quote:
this is the standalone-package of the SPTD-driver. To remove the SPTD-driver, simple download it and via command-console, execute it "sptdinst_x86.exe remove" and SPTD will remove itself from your windows installation. If you want to add it, execute in command console "sptdinst_x86.exe add". SPTD is also used (besides DaemonTools) in some proprietary security, antivirus and monitoring applications which are not disclosed to wide public.

Sounds nice?
http://www.sysinternals.com/blog/2006/02/using-rootkits-to-defeat-digital.html
http://www.duplexsecure.com/faq/
Quote:
Q: I see that my software application is using SCSI Pass Through Direct (SPTD) layer. What is it for? Can my software application work without it?

A: SPTD is a new method of access to storage devices that was developed by Duplex Secure Ltd.

Basically SPTD is similar to other access layers used by other programs (eg. ASPI from Adaptec, or standard SPTI from Microsoft) who provide access to storage devices but it has a lot more features that make this interface unique.

The key feature of SPTD is its ability to provide direct control of devices without risk of compromising it by some malicious 3rd party filter drivers or other "rootkit" applications that are common today - this is the main goal of SPTD development for organizations and applications where it currently used.

Any more questions?

dELTA
July 7th, 2006, 04:33
Nice info omega_red (and everyone else too), thanks!

DillerInc
September 11th, 2006, 15:36
By Alcohol sptd.sys was introduced just after version 1.9.5.3105(that is one of the reasons that version was the last for Win98).

From www.duplexsecure.com/faq
Quote:
SPTD (similar to other access layers) is by default not removed from your system after uninstallation of software application which used SPTD, in order not to disrupt other applications that may use it! This also allows user to avoid reboots in most cases for new installations if same SPTD version is already present on his system.


...I really doubt,that some other applications on my machine will use this Ring0-driver.
Sad, but now it is either to have two operating systems(one for Kernel-mode debugger and the other for Alcohol) or merely stop this SPTD-device via Device Manager,which is a bit annoying.

So I think the question remains open -- is it somehow possible to hide SoftIce from sptd.sys and let both of these devices work together??
If it possible, than how it would look like -- a patched sptd.sys or a plugin/utility for SoftIce that would hide him??

Kayaker
September 11th, 2006, 16:32
Hi

Probably the first thing to try is the IceExt PROTECT option to see if it fools the sptd driver. If not, then at least you've eliminated several of the usual Sice detection methods and can dig further from there.

If I understand correctly, sptd.sys hooks some syscalls? Just for fun it would be interesting to run KprocCheck or Raide or some other rootkit detector to see what is being hooked.

Kayaker

omega_red
September 12th, 2006, 03:43
I cannot even install DT nor Alcohol now, SPTD just won't install on fully patched XP SP2. Which is only good. :P

DillerInc
September 12th, 2006, 15:00
Kayaker
IceExt is unable to hide the debugger, because SoftIce doesn't even manage to start(manually), if the active sptd.sys is present.
Quote:
If I understand correctly, sptd.sys hooks some syscalls?

...or maybe it uses some significant debug resources just like StarForce does??For example,SF uses INT1, INT3 and DRx for his own purposes leaving SoftIce no chance to set breakpoints...

omega_red
Maybe some conflict with antivirus software??

Kayaker
September 12th, 2006, 23:04
Quote:
[Originally Posted by DillerInc]IceExt is unable to hide the debugger, because SoftIce doesn't even manage to start(manually), if the active sptd.sys is present.


Oh I see. Well isn't that a piss-off?

I've been trying to think of ways to get information on how the sptd driver affects Softice and WinDbg. They *say* SPTD is not "compatible" with kernel debuggers. Again the questions are:

1. is this just a ruse and it's doing deliberate anti-debugger tricks?
2. is it 'deliberate' bad programming and the driver is doing things like not chaining to hooked interrupts and such, which all legitimate drivers should do?
3. is there truly an incompatibility and sptd cannot *honestly* coexist with a kernel debugger?

The true answer may be a combination of the above.


I'd be interested in knowing the *order* in which driver events take place in order to figure out where sptd.sys may be acting. I don't have the driver to reverse, so please bear with me..

Sptd.sys is loaded at boot time and from the sounds of it remains stuck like a bad leech even after the application is uninstalled.

I read somewhere that sptd.sys can be prevented from loading by booting in safe mode and reacting to the message "Press ESC to cancel loading SPTD.sys". We also know that Softice can be prevented from loading by acting on a similar message at boot time (and not only in safe mode).

I'd like to know if the portion of Softice which loads at boot time (Osidata.sys and Cpthook.sys) is loaded *before* sptd.sys and loads successfully. The Sice drivers DO load very early, I have a utility which displays the list of loaded drivers in the order they load (a result of querying ZwQuerySystemInformation / SystemModuleInformation), and they load number 9 and 10 out of more than 100 boot-loading drivers. Chances are that sptd.sys is loaded after Sice, but if interested, my utility is here: http://woodmann.net/forum/attachment.php?attachmentid=904&d=1077340907 (QuerySysInfo.zip)


Let's say that part is OK. If sptd.sys is now active then it's probably pretty easy to prevent Softice from loading manually (the ntice.sys part) with any number of simple detection methods. And similarly with KWinDbg. The only recourse would be to patch sptd.sys.

What happens if Softice is fully loaded at boot time, does sptd refuse to operate?


The last idea I had was to see how *far* ntice.sys gets to loading manually before sptd.sys detects and interferes with that. I thought of using PoolTag for that. PoolTag is part of the DDK or Windows Resource Kit or offered at OSR, should be simple to find. It will log all "tags" used with ExAllocatePoolWithTag.

Softice uses the tag "SIce" and this is recorded by PoolTag when you start ntice.sys manually. If used on a clean system, PoolTag will log for example, 48 non-paged Allocs with 7 Frees, for a net of 41 active memory pools tagged with the string "SIce". This simply indicates that Softice is running normally.

I was wondering if sptd.sys was active and you tried starting Softice, PoolTag *might* show a different result that might be useful. If for example, NO Allocs were recorded then it would indicate sptd.sys doesn't even allow ntice.sys to load it's INIT section (where ExAllocatePoolWithTag is called several times). This might suggest sptd is monitoring driver loading somehow and preventing ntice from running. If however PoolTag records most of the normal Allocs by ntice.sys, then maybe it's corrupting its operation in other ways.

Those are just examples. I'm simply trying to use PoolTag as a "probe" to figure out what's going on since we have little else to go on at this point.

I did a bit of searching but found nothing, has no one done a detailed static reversing at least of SPTD.sys?

Cheers,
Kayaker

LLXX
September 13th, 2006, 02:14
Quote:
[Originally Posted by Kayaker]I did a bit of searching but found nothing, has no one done a detailed static reversing at least of SPTD.sys?
This was my first thought, just open it in IDA and take a look.

I haven't the file either, so I can't make any statements regarding it, but static analysis is sometimes still the best way to understand hostile code.

omega_red
September 13th, 2006, 03:23
Quote:
[Originally Posted by DillerInc]omega_red
Maybe some conflict with antivirus software??

No, it's a clean xp 32-bit.
I've had this problem with my 64-bit system at home, but that was related to some 64-bit specifix hotfix affecting Windows kernel protection (at least that's what I found with google - KB914784). However, I've found no online sources mentioning that it's an issue on 32-bit xp too, and this specific KB is not installed on 32bit system. Interestingly, I have the same DT version (4.03) working on other 32-bit machine with xp, fully patched too..

As for hooked syscalls, the list is as follows:
0029: NtCreateKey
0047: NtEnumerateKey
0049: NtEnumerateValueKey
0077: NtOpenKey
00a0: NtQueryKey
00b1: NtQueryValueKey
00f7: NtSetValueKey

DillerInc
September 13th, 2006, 08:12
Quote:
[Originally Posted by LLXX]I haven't the file either, so I can't make any statements regarding it

I attached the latest version of sptd.sys -- 1.25.0.0
I'm not very familiar with the kernel-mode stuff,so I can't get the point of all these ntoskrnl functions...but IDA shows some interesting strings like:

Code:
.data:00078808 00000053 C Debug TEST trigger in DPC: overflow by %I64d ms!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n

DillerInc
September 14th, 2006, 13:29
From Alcohol Customer forum:
Quote:

- Why don't you want SPTD? Did you have any related problems?
- Yes, it won't live with my Logitech Quickcam Pro 5000 drivers. The machine stalls on boot after the Windows logo screen.

LLXX
September 15th, 2006, 13:48
Quote:
[Originally Posted by DillerInc]I attached the latest version of sptd.sys -- 1.25.0.0
I'm not very familiar with the kernel-mode stuff,so I can't get the point of all these ntoskrnl functions...but IDA shows some interesting strings like:

Code:
.data:00078808 00000053 C Debug TEST trigger in DPC: overflow by %I64d ms!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n
It also looks like it's been encrypted/packed... I'm not familiar with NT kernel architecture either, so that's all I can see...

Kayaker
September 15th, 2006, 14:49
I'll post more on this later. I found that there is an easy way to get Softice to load with sptd.sys active - simply change the ServiceGroupOrder so that cpthook.sys and osidata.sys load before sptd.sys.


SPTD sets itself up as a Boot Bus Extender driver, the same as Softice. Within that group there is a ServiceGroupOrder which specifies which driver loads first, based on the Tag value set for the driver.

See here for more
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q115486

SPTD sets itself up to load as the *first* Boot Bus Extender driver, so it gets the chance to grab all the resources. It is a simple matter to change this order so Softice gets its shot at what it wants to hook etc. before sptd.

I don't have an application which uses SPTD, only the installed driver itself, so I can't tell if doing this interferes with its actual operation. Doesn't matter, this is for debugging purposes anyway.

Now that Softice can "see" SPTD successfully installed you can issue commands such as
DRIVER sptd - see IRPs used etc.
MAP32 sptd - use addresses to disassemble the various sections, if indeed there are encrypted sections, they should be decrypted by now depending on the exact implementation

If SPTD is actually running normally then you may be able to set breakpoints on the IRP functions in order to see how the application is communicating with it...
etc.

Kayaker

DillerInc
September 15th, 2006, 16:46
Quote:
simply change the ServiceGroupOrder so that cpthook.sys and osidata.sys load before sptd.sys

...which way SoftIce needs to be loaded in that case -- manuelly or at system boot??
Quote:
I'll post more on this later

...it would be very kind of you

Kayaker
September 15th, 2006, 17:21
Quote:
[Originally Posted by DillerInc]...which way SoftIce needs to be loaded in that case -- manuelly or at system boot??


Normal manual start of Softice. The two drivers cpthook and osidata are both loaded at boot time anyway and are for the important hooking. The "manual" starting mode just executes ntice.sys when you decide.

You will probably need to boot once in Safe Mode and prevent SPTD from loading. Then you can change the registry entry. Then reboot normally. Softice should be able to start after this. If you change the registry while SPTD is still active it seems to change it back on shutdown. It may be checked on every shutdown, I've haven't had time to test that yet.

Code:

Original:
The first 06 dword indicates the number of entries, the second 06 is the
"Tag" value for SPTD, then follows Tags for other drivers including
the two drivers of Softice.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList]

"Boot Bus Extender"=hex:06,00,00,00,06,00,00,00,01,00,00,00,02,00,00,00,03,00,\
00,00,04,00,00,00,05,00,00,00

Change order to this, sptd will be loaded last:

"Boot Bus Extender"=hex:06,00,00,00,01,00,00,00,02,00,00,00,03,00,00,00,04,00,\
00,00,05,00,00,00,06,00,00,00


Kayaker

Kayaker
September 16th, 2006, 01:44
Here's a bit more on debugging the unbuggable..

If interested, you can run spdt.sys as a regular SERVICE_DEMAND_START driver and trace into the INIT routine to check out what certainly appears to be a decryption of sorts. Ultimately I don't know if there is specific anti-debugging code or whether the incompatibility with kernel mode debuggers is a result of not being able to share resources. Trying to run SPTD under the conditions I gave above (by making sure Softice loads first) might be the best way to tell.

As for tracing the INIT, or normal DriverEntry routine, all you need to do is set a breakpoint on the indirect call within the ntoskrnl IopLoadDriver routine which directly calls DriverEntry for all SERVICE_DEMAND_START drivers. Other driver types may use different routines, SERVICE_BOOT_START runs from ntldr I believe.

The easiest way to find the correct address to break on is to set a breakpoint in your own DriverEntry routine and trace back to ntoskrnl code. In XPsp2 this is at 805A69D0. If you can't do this you can probably find it with the help of IDA and a byte/offset search in Softice.

The specific call is this one, you should have the PDB symbols loaded to find IopLoadDriver:

Code:

PAGE:004CF9C9 loc_4CF9C9: ; CODE XREF: IopLoadDriver(x,x,x,x)+3AD
PAGE:004CF9C9 push [ebp+P]
PAGE:004CF9CF push edi
PAGE:004CF9D0 FF 57 2C call dword ptr [edi+2Ch] breakpoint here


For SPTD, make sure it is *completely* uninstalled first as a boot loading driver. The driver install package comes with an uninstall routine ("remove". First however make a copy of sptd.sys and its associated driver sptd2461.sys (the numbers 2461 may be different for you (7805?). Once you've got a "clean" system again, copy the 2 sptd drivers back to /windows/system32/drivers. I used a clean VMWare image for this.

Now you're ready to start up SPTD as a traceable SERVICE_DEMAND_START driver. I use Driver Monitor from the DriverStudio Tools directory. Open sptd.sys in Driver Monitor, a new registry entry will be made under
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Sptd]

Now set a breakpoint on the Call [edi+2Ch] above, press Go in Driver Monitor, and just step into what is a normal DriverEntry routine when it breaks. Welcome to driver tracing..


I'm not going to pursue this further unless someone finds something interesting out of all this, it's all pretty ugly in there.

Cheers,
Kayaker

dELTA
September 18th, 2006, 15:25
Hehe, as always, you da ring 0 man Kayaker.

Quote:
I don't have an application which uses SPTD, only the installed driver itself, so I can't tell if doing this interferes with its actual operation.
Daemon Tools, which is one of the applications using this driver, is free, small, and works perfect inside a VMware machine, so if you want to try if your simple method works all the way it should be quite easy to just download, install and see, just so you know.

DillerInc
September 18th, 2006, 17:41
Kayaker
So,it seems a bit strange on my Win2k SP4 machine.
When I had SoftIce installed, this GroupOrderList registry key looked that way:
Quote:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList]
"Boot Bus Extender"=hex:07,00,00,00,09,00,00,00,08,00,00,00,01,00,00,00,04,00,\
00,00,05,00,00,00,54,72,75,73,00,3e,00,3e

If I have correctly understood, there are seven entries out there.
OsiData should have a "Tag" value -- 2
CptHook should have a "Tag" value -- 3
But as we can see there are no such values.Though SoftIce started perfectly.

After that I istalled Alcohol with that latest sptd.sys, and the registry value changed to this:
Quote:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList]
"Boot Bus Extender"=hex:07,00,00,00,08,00,00,00,09,00,00,00,01,00,00,00,04,00,\
00,00,05,00,00,00,54,72,75,73,00,3e,00,3e

SoftIce began to fail at start.
I booted into Safe Mode,cancelled by the way the load of sptd.sys and changed the value "Boot Bus Extender" to a former state.It did not help -- SoftIce continued to fail at start with "Error code 31".
Any suggestions??

Kayaker
September 18th, 2006, 22:26
Shure dELTA, take advantage of my debilitating reversing addiction and throw me another teaser why don't you?
Those Reverser's Anonymous meetings just aren't helping...

OK, I installed DT and set it up to mount an iso image of an old Win3.1 era game which required the CD be present. DT worked great! (though the game sure sucks)

Then I forced SPTD to load *after* the Softice boot drivers as I outlined above:

- boot once in Safe Mode and prevent SPTD from loading (press ESC at prompt)
- change the GroupOrderList so that the SPTD.sys driver Tag (#6 on my system) is listed last (see above)
- reboot normally
- Softice can now be activated manually

Unfortunately, this didn't work quite as hoped because when DT tried to start it detected Softice was active (even though not started manually yet) and gave a MsgBox error.

OK, partial setback, but wait a minute, what wrong here?

DT usermode application normally starts from
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
but can now be started manually..

DT application can be loaded with Softice Loader32 and traced like a normal application..
Breakpoints stick and app can be restarted over and over again with same bp's active..
DT application can be loaded with OllyDbg..
Interesting decryption algorithm can be traced (looks very similar to the one present in sptd.sys btw)..
MessageBoxW which gives the error can be found..

Oops, I guess we weren't meant to be able to do this..

The Softice/kernel debugger detection must be in the decrypted code somewhere but would require some determined reversing..

No guarantees that bypassing the debugger detection would allow DT to operate normally..

This information is for malware reversing purposes only..

Kayaker

DillerInc
September 19th, 2006, 07:53
Kayaker
Well, on my WinXP SP2 machine it went just as you discribed above.That's good!
Now SoftIce is able to start succesfully, BUT there is no virtual drive by Alcohol anymore, because sptd.sys merely did not boot.If we now try to run Alcohol, it loads but also shows a MessageBoxA telling us, that an error occured while loading Alcohol drivers.
It's true that we can debug the usermode application alcohol.exe(it is packed with UPX), but would it help us, if sptd.sys is not present anyway...or??

Kayaker
September 19th, 2006, 12:45
Hi DillerInc

The SPTD drivers should boot up anyway if everything went well. It's the system, not the application, which is loading the drivers, so as long as the registry settings are OK there shouldn't be anything preventing them from loading at boot time. All we've done is modify their load order.

In my case anyway I can see that the drivers are loaded with the Softice commands:

DRIVER sptd*
or
MOD sptd*

The MOD command will also show the sptdxxxx.sys driver which is loaded as an export module for the main sptd.sys driver.


You should also be able to confirm sptd is loaded and active (irrespective of whether or not DT/Alcohol is running) with something like OSR's IrpTracker. It will easily show what IRP's are being issued through SPTD, even while quietly humming in the background without an application using it. If DT issues a DeviceIoControl call, IrpTracker picks that up as well.


It's quite possible that even though the (load-order modified) drivers appear to be loaded, they haven't been successfully initialized in terms of what needs to be hooked, etc. It's still an open question as to why these drivers can't coexist with Softice. However I think that the user application should still behave somewhat "normally" in general terms.

Kayaker

DillerInc
September 19th, 2006, 13:34
Kayaker
Once again you are right -- sptd.sys does boot.
We can investigate it also using the feature "Enable Boot Logging" during advanced windows startup.Then we can see this:
Quote:
[Originally Posted by Ntbtlog.txt]
Service Pack 2 9 19 2006 21:05:43.500
Loaded driver \WINDOWS\system32\ntoskrnl.exe
Loaded driver \WINDOWS\system32\hal.dll
Loaded driver \WINDOWS\system32\KDCOM.DLL
Loaded driver \WINDOWS\system32\BOOTVID.dll
Loaded driver bootcfg.sys
Loaded driver ACPI.sys
Loaded driver \WINDOWS\System32\DRIVERS\WMILIB.SYS
Loaded driver pci.sys
Loaded driver OsiData.sys
Loaded driver cpthook.sys

Loaded driver isapnp.sys
Loaded driver sptd.sys
Loaded driver \WINDOWS\System32\Drivers\SPTD7805.SYS
...

Now, I'm planning to dump this driver using IceExt...

Kayaker
September 19th, 2006, 21:12
Just thought I'd mention that both DT and the sptd driver (INIT section) show a very strong indication of running a Virtual Machine. I don't know that they are identical VM's but both are structured very similarly. Both are condusive to IDA analysis as well as live tracing.

I figured there'd be at least a few people interested in exploring that further..

Kayaker

Maximus
September 27th, 2006, 06:29
uhm... interesting

from a very random and quick look, the dispatcher seems:
.text:0003363E push ds: off_33D0A[eax*4]

It looks like Code Virtualizer, looking the obfuscation kind.

edit----
had now the time to do few clicks more, and I found other CV patterns -it is, IMHO.
(i.e. code that goes to .text:00031803 and follows it)

Kayaker
September 27th, 2006, 18:27
That's interesting Maximus. I didn't know the product existed, it looks pretty impressive (ouch - Oreans).

I've made a few more attempts at trying to figure out how/why the sptd driver is not 'compatible' with Softice. It's now apparent the DriverEntry routine at least is wrapped in CV. I haven't done any testing to see if CV alone detects the presence of a kernel debugger, but it's apparent that one way or another sptd "reacts" to the presence of a KD and modifies it's behaviour.

One of the things I noticed is that sptd uses PsSetLoadImageNotifyRoutine to detect when certain modules are loaded, notably ntdll and winlogon.exe. Under the 'modified' conditions I gave above of loading sptd *after* Sice you can trace this routine for debugging purposes.
(Sidenote: Actually there is a jump table used and some addresses point to 'false' routines (i.e. a RET instead of the correct LoadImageNotifyRoutine callback), but the jump table can be 'corrected' to point to the proper (virgin) addresses).

Anyway, under "goodboy" conditions, there exists a LoadImageNotifyRoutine Callback, all is rosy in the world of the app. Under "badboy" conditions, say you boot VMWare with WinDbg kernel debugger active, then this Callback is never created!

So, not surprisingly, debugger detection leads to modified behaviour. Since this modified behaviour can be subtle or dramatic (i.e. no NotifyRoutine callback), and all occurs during boot loading, it would be just about impossible to "fix" the program after the fact.


I'll explain how I determined this business with the LoadImageNotifyRoutine Callback since it's not something normally easily detected, especially without a kernel debugger.

The PsSetLoadImageNotifyRoutine routine registers a driver-supplied callback that is subsequently notified whenever an image is loaded for execution. There exists a table of callbacks (maximum of 8), which are located at an unexported variable address in ntoskrnl, _PspLoadImageNotifyRoutine. Another variable holds the number of callbacks, _PspLoadImageNotifyRoutineCount. The callbacks themselves, if present, are executed through PsCallImageNotifyRoutines during process initialization, also at other times such as if ZwMapViewOfSection is used. A callback will be called for any usermode module or for a driver module not loaded from a system process.

To determine if a _PspLoadImageNotifyRoutine callback table existed, under the conditions of not having a kernel debugger handy, I used two utilities. One is LiveKD. The other is a simple full-text kernel mode disassembler I wrote quite some time ago. This allowed me to disassemble a known exported function in order to find the address for the unexported _PspLoadImageNotifyRoutine callback table variable. Then I used LiveKD to view that address, confirming whether there was an active callback or not.


First step was to understand what to look for in IDA with symbols loaded:
Code:

PAGE:005554F7 _PsSetLoadImageNotifyRoutine@4 proc near
PAGE:005554F7 mov edi, edi
...
PAGE:00555517 mov esi, offset _PspLoadImageNotifyRoutine


The second step was to "live" disassemble this routine by name
and find the address of the callback table:
Code:

>kdasm df PsSetLoadImageNotifyRoutine

1 8062C4F7 8bff mov edi,edi
...
16 8062C517 be000d5680 mov esi,80560d00 // _PspLoadImageNotifyRoutine


The third step was to display the _PspLoadImageNotifyRoutine address with LiveKD.
The address is actually at _PspLoadImageNotifyRoutineCount, which is just before
the callback table itself (8 dwords):
Code:

kd> dd 80560ce8

80560ce8 00000001 00000000 00000000 00000000
80560cf8 00000000 00000000 e139204f 00000000
80560d08 00000000 00000000 00000000 00000000
80560d18 00000000 00000000


The "address" e139204f is not actually a direct address of the SPTD NotifyRoutine callback, but can be easily calculated from it. (In Win2K it would be a true address, but this changed slightly in XP and above).


Now if you were to do the exact same thing with the WinDbg kernel debugger active, you would find that the SPTD driver never creates the above callback routine and the table would be empty. Bye bye normal operation..


Anyway, hope that's a somewhat interesting tidbit, though it doesn't really accomplish a hell of a lot. If interested, the kernel mode disassembler I wrote is attached, I released it a couple of years ago at rootkit.com. It's based on the NASM disassembler, for years I've used that source code compiled into a usermode dll for disassembly projects, this time I compiled it into a kernel mode dll to give full-text kernel disassembly as well. It will disassemble by address or ntoskrnl function name. Full VC++ source and explanations included.


Thanks again for the heads up on the VM!

Cheers,
Kayaker

Maximus
September 27th, 2006, 19:10
Quote:
[Originally Posted by Kayaker]PsSetLoadImageNotifyRoutine


..even if I desinstalled DDK, I know it I used it to 'fix' the Soviet protector (look at CodeProject) behaviour, that was using a bit... messy solution (checked sections load with hooks, not elegant IMHO, even if effective).
PS* is the only truly viable way for intercepting the launch of an application, and gives you ALL the information you need for performing a r3 hook by debugger (why all this? can be... useful...)
It costed me a week of research or so, and it is even decently documented in DDK -bah! Sometime I am really really dumb

nice way to locate the callback lists...
..again, let me double Delta's assertion -you da r0 man

...also, I looked on virtual earth and sky a r0 disassembler for months, for another project I were discussing with my retired friend (sigh!) HAVOK- THANKS!

When my WinXP (or Ware) will stand the DDK and debuggers again, I will hopefully make good use of it

About CV...

heh, An article on it was planned to be the my 2nd one, I even started to do a comparative analysis of CV machines, but I got request of both simpler and harder things on VMs... Also, I were discussing of this with a TheMida expert, OHPen, but we 'lost' for awhile -RL ...

Hopefully I'll discuss with him again about my idea on a CV article

This target sounds pretty interesting, so I guess I will give a better look to it... might be a good target for a comparative article for attack methods of Oreans VMs.

Maximus

Kayaker
September 28th, 2006, 15:24
That would be an interesting paper Maximus. I still can't solve VM's but thanks to your earlier explanations I can at least recognize them!

DillerInc
September 28th, 2006, 16:06
Kayaker
Maximus

I'm quite impressed.Hope that your efforts would have a positive result

blabberer
September 30th, 2006, 14:42
nice disassembler there kayaker , could come in usefull when working with floppies dont need windbg installed isnt it ?
btw it escapes on the first ret that it locates linearly isnt it ?
or does it do control flow ?

i mean is df == uf in windbg ?

but i could just hint a solution for you if you want information with symbols
if you are on xp where lkd is enabled by default in windbg you can use kd like this from command prompt

you can pipe it to notepad for future referance


Code:


C:\Program Files\Debugging Tools for Windows>kd -kl -c "uf ntDeviceIoControlFile
; q"
====================
snipped the version bs crap
====================
lkd> kd: Reading initial command 'uf ntDeviceIoControlFile; q'
nt!NtDeviceIoControlFile:
8057fbd0 8bff mov edi,edi
8057fbd2 55 push ebp
8057fbd3 8bec mov ebp,esp
8057fbd5 6a01 push 1
8057fbd7 ff752c push dword ptr [ebp+2Ch]
8057fbda ff7528 push dword ptr [ebp+28h]
8057fbdd ff7524 push dword ptr [ebp+24h]
8057fbe0 ff7520 push dword ptr [ebp+20h]
8057fbe3 ff751c push dword ptr [ebp+1Ch]
8057fbe6 ff7518 push dword ptr [ebp+18h]
8057fbe9 ff7514 push dword ptr [ebp+14h]
8057fbec ff7510 push dword ptr [ebp+10h]
8057fbef ff750c push dword ptr [ebp+0Ch]
8057fbf2 ff7508 push dword ptr [ebp+8]
8057fbf5 e8dddbffff call nt!IopXxxControlFile (8057d7d7)
8057fbfa 5d pop ebp
8057fbfb c22800 ret 28h
quit:

C:\Program Files\Debugging Tools for Windows>



or your real life example in one go

Code:

lkd> kd: Reading initial command 'uf PsSetLoadImageNotifyRoutine; dd 80560ce8 ; q'
nt!PsSetLoadImageNotifyRoutine:
8062c4f7 8bff mov edi,edi
8062c4f9 55 push ebp
8062c4fa 8bec mov ebp,esp
8062c4fc 53 push ebx
8062c4fd 57 push edi
8062c4fe 33ff xor edi,edi
8062c500 57 push edi
8062c501 ff7508 push dword ptr [ebp+8]
8062c504 e833790100 call nt!ExAllocateCallBack (80643e3c)
8062c509 8bd8 mov ebx,eax
8062c50b 3bdf cmp ebx,edi
8062c50d 7507 jne nt!PsSetLoadImageNotifyRoutine+0x1f (8062c516)

nt!PsSetLoadImageNotifyRoutine+0x18:
8062c50f b89a0000c0 mov eax,0C000009Ah
8062c514 eb2a jmp nt!PsSetLoadImageNotifyRoutine+0x49 (8062c540)

nt!PsSetLoadImageNotifyRoutine+0x1f:
8062c516 56 push esi
8062c517 be000d5680 mov esi,offset nt!PspLoadImageNotifyRoutine (80560d00)

nt!PsSetLoadImageNotifyRoutine+0x25:
8062c51c 6a00 push 0
8062c51e 53 push ebx
8062c51f 56 push esi
8062c520 e84e790100 call nt!ExCompareExchangeCallBack (80643e73)
8062c525 84c0 test al,al
8062c527 751d jne nt!PsSetLoadImageNotifyRoutine+0x4f (8062c546)

nt!PsSetLoadImageNotifyRoutine+0x32:
8062c529 83c704 add edi,4
8062c52c 83c604 add esi,4
8062c52f 83ff20 cmp edi,20h
8062c532 72e8 jb nt!PsSetLoadImageNotifyRoutine+0x25 (8062c51c)

nt!PsSetLoadImageNotifyRoutine+0x3d:
8062c534 53 push ebx
8062c535 e89134f4ff call nt!RtlpSysVolFree (8056f9cb)
8062c53a b89a0000c0 mov eax,0C000009Ah

nt!PsSetLoadImageNotifyRoutine+0x48:
8062c53f 5e pop esi

nt!PsSetLoadImageNotifyRoutine+0x49:
8062c540 5f pop edi
8062c541 5b pop ebx
8062c542 5d pop ebp
8062c543 c20400 ret 4

nt!PsSetLoadImageNotifyRoutine+0x4f:
8062c546 b801000000 mov eax,1
8062c54b b9e80c5680 mov ecx,offset nt!PspLoadImageNotifyRoutineCount (80560ce8)
8062c550 0fc101 xadd dword ptr [ecx],eax
8062c553 c60534cf688001 mov byte ptr [nt!PsImageNotifyEnabled (8068cf34)],1
8062c55a 33c0 xor eax,eax
8062c55c ebe1 jmp nt!PsSetLoadImageNotifyRoutine+0x48 (8062c53f)
80560ce8 00000001 00000000 00000000 00000000
80560cf8 00000000 00000000 e15d32bf 00000000
80560d08 00000000 00000000 00000000 00000000
80560d18 00000000 00000000 e15d15c7 00000000
80560d28 00000000 00000000 00000000 00000000
80560d38 00000000 00000000 00000001 00000000
80560d48 00000000 00000000 00000000 00000000
80560d58 00000000 00000000 e15d2d5f 00000000
quit:

Kayaker
September 30th, 2006, 23:24
Thanks blabberer. Yeah it could certainly be developed further. The only control flow it does at the moment is to follow any FAR JMP (opcode 0xEA) diversions it finds in order to trace inline hooks of that type. And yes it stops disassembly when it finds a RET/RETN/RETF/IRET.

It would make sense to disassemble in the manner you showed. I guess what you'd have to do is to first find the RET, then go back and disassemble the full function, following each of the jumps which go to an address past the RET, or before the function start. Then position each of the function chunks in a logical order for output. Output can be piped to a text file in the normal console manner using "> output.txt".

As for symbols, I never did get around to that but if I did I was thinking of using the relevant ntoskrnl or hal pdb file. "Function" recognition here is based on MmGetSystemRoutineAddress, which works only for ntoskrnl or hal functions.

I don't know yet exactly how to work with symbol files and how best to use their information for updating a raw disassembly of this sort, but there seems to be good information in Sven Schriebers Undocumented Windows 2000 Secrets on the pdb format. There is also a PdbDump utility which could help (sourceforge), plus whatever can be gleaned from studying Windbg/Kd.


I wouldn't mind seeing it developed further as a fully functional r0 disassembler, I haven't had time or inclination myself. The ring3 version I use, based on the same source code/disassembly module and part of a dll injection package, has a GUI interface and allows right clicking on call and jump addresses to further disassemble them in another window, also to display memory addresses and other stuff, and will disassemble linearly past RET's. The same thing could be done for a ring 0 version, gui instead of console output would make it more user friendly. And still all fit on a floppy!

I thought about using it in an Olly plugin, but I'm not sure if that would be of much use. It could be mated with a utility which gets driver information such as IRP entry points and could allow disassembly of drivers (well it can now if you know the address). And of course the disasm source can be compiled directly into a driver, I only put in into a separate kernel module to keep any projects I use it in "clean" from all the disasm source code.

Kayaker

Kayaker
October 17th, 2006, 02:41
Hello again,

If you've been following this thread so far you know that the SPTD driver is "incompatible" with Softice. If you try to load Softice you get the very uninformative error message:
The NTice service failed to start due to the following error:
A device attached to the system is not functioning.


I was curious to know *why* it wasn't loading, and to what extent this "incompatibility" was an honest conflict with the two drivers and how much was deliberate anti-debugging for all the usual reasons. I can answer the first part, the second part might still be open to speculation.

Please bear with me if this is long-winded and I hold the answer till the end. I'm hoping the sequence of reversing steps taken and the code presented will be informative in a more generic way.


Recall what I said about how a driver is loaded through ntoskrnl!IopLoadDriver and the sequence:

Code:

push dword ptr [ebp-0x0090] // PUNICODE_STRING RegistryPath
push edi // PDRIVER_OBJECT pDriverObject
call [edi+0x2C] // DriverEntry


Prior to this the loading driver is mapped to memory via MmLoadSystemImage. Within the MiMapViewOfImageSection subfunction it checks the PsImageNotifyEnabled variable to see if any LoadImageNotifyRoutine callbacks have been registered with the system, if so it calls them in turn (to a maximum of 8). After MmLoadSystemImage is called the loading continues, a DRIVER_OBJECT is initialized and the driver is eventually loaded.

A PspLoadImageNotifyRoutine callback allows a covert process to monitor, or indeed subvert, the loading module. An elegant rootkit technique actually. As I mentioned, SPTD registers a PspLoadImageNotifyRoutine callback...



OK, back to attempting to load NTICE with SPTD active. Note that the boot drivers of Softice such as CptHook have already been normally loaded (though out of order because of SPTD), and it is within CptHook that the IDT entries are hooked and where the new hook functions for Int1 (single step), Int3 (breakpoint), Int0E (page fault), etc. reside. These are always active whether or not the user interface NTICE is loaded, including when SPTD is loaded.

I'll briefly explain what didn't work as well as what did. So what I first did was to register my own PspLoadImageNotifyRoutine callback just to confirm that NTICE was in the process of being loaded and the code had gotten that far. You can check the definition for the function and see that obtaining the name and base address of the loading module is straightforward.

Fine so far, what about within the NTICE DriverEntry (INIT) routine itself, how far along was that code executing? I mentioned about using PoolTag to probe if any ExAllocatePoolWithTag calls were being made. Turns out they weren't.

OK, taking a closer look at the NTICE code you can see that it's nicely laid out with a number of error checks. If an error occurs during initialization it logs that to the system Event Log with IoWriteErrorLogEntry. The various error messages are given in the resource string message table you can see using i.e. ResHack. One of the first things NTICE does is to communicate with CptHook via driver IOCTL calls. If this step fails it records one of these error event messages. What I did was to hard patch (jnz nop) the ntice.sys file to force an Event to be logged - it wasn't!

Wtf? It looked like even the first few instructions of the NTICE DriverEntry weren't being executed. What the heck was going on?

Time to take the bull by the horns and get down 'n dirty to see what was happening..

Kayaker
October 17th, 2006, 02:43
What I decided to do then was to create a detour of the ntoskrnl driver loading code itself so I could disassemble things and monitor exactly what was going on. Here is the code I used for setting and removing the inline patch:

Code:

Data declarations:

// Our Device Extension
typedef struct _DEVICE_EXTENSION {
ULONG PatchAddress;
UCHAR OriginalPatchBytes[10];
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

#pragma data_seg(".data"

PDEVICE_EXTENSION pDevExt;

ULONG DriverEntry_returnvalue; // value normally returned from DriverEntry
ULONG ReturnAddress_DriverEntryDetour; // return address from our Detour

// save original DriverEntry variables when we enter our Detour
PUNICODE_STRING pusRegistryPath_original;
PDRIVER_OBJECT pDriverObject_original;
ULONG DriverEntry_original;

const WCHAR DriverName_Ntice[] = L"\\Driver\\NTice";


Code:

The relevant IOCTL calls, as part of a normal DeviceControl function:

//################################################################

case IOCTL_SETHOOK: // hook

/* BYTES WE PATCH
ntoskrnl!IopLoadDriver for WinXPsp2
805A69C9 FF B5 70 FF FF FF push dword ptr [ebp-0x0090] // PUNICODE_STRING RegistryPath
805A69CF 57 push edi // PDRIVER_OBJECT pDriverObject
805A69D0 FF 57 2C call [edi+0x2C] // DriverEntry
*/

__try {

UnProtectKernelMemory(); // remove write protection

pDevExt->PatchAddress = 0x805A69C9;

// Calculate return address
ReturnAddress_DriverEntryDetour = pDevExt->PatchAddress + sizeof pDevExt->OriginalPatchBytes;

// Save original bytes
memcpy( pDevExt->OriginalPatchBytes,
(UCHAR*) (ULONG*)pDevExt->PatchAddress,
sizeof pDevExt->OriginalPatchBytes);

////////////////////////////////////////////////////////////////

// we want to encode a FAR jump in the form
// jmp FAR 0x0008:0xAAAAAAAA

UCHAR FarJumpOpcode = 0xEA;
ULONG NewHook;
USHORT FarJumpSegment = 0x0008;
UCHAR FarJumpNop = 0x90;

NewHook = (ULONG)&DriverEntryDetour; // address of our naked function detour

// encode FAR JUMP opcode (1 byte)
memcpy( (UCHAR*) (ULONG*)pDevExt->PatchAddress,
&FarJumpOpcode,
sizeof FarJumpOpcode);

// encode new detour address (4 bytes)
memcpy( (UCHAR*) (ULONG*)pDevExt->PatchAddress + 1,
&NewHook,
4);

// encode segment (2 bytes)
memcpy( (UCHAR*) (ULONG*)pDevExt->PatchAddress + 5,
&FarJumpSegment,
sizeof FarJumpSegment);

// encode at least one NOP opcode (fill remaining overwritten bytes)
for (int i=7; i < sizeof pDevExt->OriginalPatchBytes; i++)
{
memcpy( (UCHAR*) (ULONG*)pDevExt->PatchAddress + i,
&FarJumpNop,
sizeof FarJumpNop);
}

////////////////////////////////////////////////////////////////

ProtectKernelMemory(); // restore write protection


//=============================================================

} __except (EXCEPTION_EXECUTE_HANDLER) {

DbgPrint ("HOOK: ERROR ExceptionCode: %x\n", GetExceptionCode() );

} // end __try{


/****************************************************************/

//===========================================================
// Complete the IRP
//===========================================================

IoStatus->Information = 1;
IoStatus->Status = STATUS_SUCCESS;

//===========================================================

break;

//################################################################

//################################################################

case IOCTL_REMOVEHOOK: // unhook

/****************************************************************/

__try {

UnProtectKernelMemory();

// Restore bytes

memcpy( (UCHAR*) (ULONG*)pDevExt->PatchAddress,
pDevExt->OriginalPatchBytes,
sizeof pDevExt->OriginalPatchBytes);

ProtectKernelMemory();

//=============================================================

} __except (EXCEPTION_EXECUTE_HANDLER) {

DbgPrint ("HOOK: ERROR ExceptionCode: %x\n", GetExceptionCode() );

} // end __try{

/****************************************************************/

//===========================================================
// Complete the IRP
//===========================================================

IoStatus->Information = 1;
IoStatus->Status = STATUS_SUCCESS;

//===========================================================

break;

//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

/***********************************************************
UnProtectKernelMemory
Allows writing to memory pages marked as read-only
by disabling the write protect (WP) bit of CR0
************************************************************/
VOID UnProtectKernelMemory()
{
__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}
}
/***********************************************************/

/***********************************************************
ProtectKernelMemory
Reenables write protection of read-only memory pages
************************************************************/
VOID ProtectKernelMemory()
{
__asm
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}
}
/***********************************************************/


Here is our *basic* Detour function which does nothing except execute the overwritten instructions and return. Note that it is a 'naked' function for simplicity, there is no stack so any variables used must be global in nature.

Code:

__declspec(naked) DriverEntryDetour(){

///////////////////////////////////////////////

// Save the original DriverEntry parameters
// DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)

_asm{
push dword ptr [ebp-0x0090]
pop pusRegistryPath_original

mov pDriverObject_original, edi

push dword ptr [edi+0x2C]
pop DriverEntry_original
}

///////////////////////////////////////////////

__asm
{
// Execute overwritten instructions
push dword ptr [ebp-0x0090]
push edi
call [edi+0x2C]
}

_asm{
mov DriverEntry_returnvalue, eax
}

///////////////////////////////////////////////

///////////////////////////////////////////////

_asm{
mov eax, DriverEntry_returnvalue
}

__asm{
push ReturnAddress_DriverEntryDetour
ret
}
}


continued..

Kayaker
October 17th, 2006, 02:47
What I did next was to modify the Detour to use the SysDasm full-text disassembler I introduced earlier to output the NTICE DriverEntry code as it existed just BEFORE it was called, and just AFTER it was called. I incorporated the disassembler code directly into the project instead of as a separate kernel driver module, I won't post the entire code but if anyone wants to see how to use it and produce nice DbgPrint output from it let me know.

In order to understand the following code flow I'll explain now that SPTD overwrites the start of the NTICE DriverEntry with a detour of its own. It returns not to NTICE code but back to the normal return address in ntoskrnl!IopLoadDriver. In actual fact, it's returning to our own Detour, so we still have control over the code flow. Conveniently, SPTD restores the bytes it overwrites in NTICE, so what we can do is to simply call the NTICE DriverEntry again, for *real* this time. This effectively loads Softice, which SPTD tried so hard to prevent in the first place.

Code:

__declspec(naked) DriverEntryDetour()
{
///////////////////////////////////////////////

// Save the original DriverEntry parameters
// DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)

_asm{
push dword ptr [ebp-0x0090]
pop pusRegistryPath_original

mov pDriverObject_original, edi

push dword ptr [edi+0x2C]
pop DriverEntry_original
}

///////////////////////////////////////////////

// save context
_asm pushad
_asm pushf

// If NTICE is being loaded..

if(!_wcsnicmp(pDriverObject_original->DriverName.Buffer,
DriverName_Ntice,
pDriverObject_original->DriverName.Length/sizeof(WCHAR)))
{
// Output disassembly

DbgPrint("NTICE DriverEntry is overwritten with SPTD detour \n";

DisasmAddress = (ULONG) pDriverObject_original->DriverInit;
NumInstructions = 5;

OutputDisasm(DisasmAddress, NumInstructions);

} // end if NTICE

// restore context
_asm popf
_asm popad

///////////////////////////////////////////////

__asm
{
// Execute overwritten instructions
push dword ptr [ebp-0x0090]
push edi
call [edi+0x2C] // DriverEntry
}

_asm{
mov DriverEntry_returnvalue, eax
}


// If NTICE is being loaded, call it for real after SPTD
// subverted its original loading

if(!_wcsnicmp(pDriverObject_original->DriverName.Buffer,
DriverName_Ntice,
pDriverObject_original->DriverName.Length/sizeof(WCHAR)))
{

///////////////////////////////////////////////

// Output disassembly

DbgPrint("NTICE DriverEntry has been restored \n";

DisasmAddress = (ULONG) pDriverObject_original->DriverInit;
NumInstructions = 5;

OutputDisasm(DisasmAddress, NumInstructions);

///////////////////////////////////////////////

__asm
{
// Execute DriverEntry again

push pusRegistryPath_original
push pDriverObject_original
call [DriverEntry_original]
}

_asm{
mov DriverEntry_returnvalue, eax
}
} // end if NTICE

///////////////////////////////////////////////

_asm{
mov eax, DriverEntry_returnvalue
}

__asm{
push ReturnAddress_DriverEntryDetour
ret
}
}


If you followed all that, here is the DbgPrint output from my disassembler and captured with DbgView. You can clearly see the SPTD detour.

Code:

NTICE DriverEntry is overwritten with SPTD detour
# Address Length Opcode Disassembly
*******************************************************
1 F7AAE8C6 5 E99D8F1008 jmp ffbb7868
2 F7AAE8CB 6 008B84249805 add [ebx+5982484],cl
3 F7AAE8D1 2 0000 add [eax],al
4 F7AAE8D3 1 57 push edi
5 F7AAE8D4 2 33FF xor edi,edi
*******************************************************

NTICE DriverEntry has been restored
# Address Length Opcode Disassembly
*******************************************************
1 F7AAE8C6 6 81EC90050000 sub esp,590
2 F7AAE8CC 7 8B842498050000 mov eax,[esp+598]
3 F7AAE8D3 1 57 push edi
4 F7AAE8D4 2 33FF xor edi,edi
5 F7AAE8D6 4 897C2404 mov [esp+4],edi
*******************************************************


holy crap, there's more?..

Kayaker
October 17th, 2006, 02:52
If we examine the SPTD detour address itself we see this interesting snippet:

Code:

FFBB7868 B88877BBFF mov eax, FFBB7788
FFBB786D 870424 xchg eax, [esp] // store return address (to ntoskrnl!IopLoadDriver)
FFBB7870 50 push eax // push return address
FFBB7871 68C6FCDCF9 push F9DCFCC6 // push further Detour code
FFBB7876 C3 ret // execute more Detour code


I'm not going to get into the rest of the SPTD Detour code, partly because I'm not intending to expose it and mostly because I just don't understand it all. You can examine it with full ntoskrnl symbol support however because Softice is now functional. What it does just before returning to ntoskrnl code is, as I mentioned, restore the overwritten NTICE bytes, but it also passes 0xC0000001 as a return value. The detour itself and the STATUS_UNSUCCESSFUL return value is the whole reason why Softice does not load and gives the mundane error message.

Other things.. I'm assuming SPTD overwrites the NTICE code during its LoadImageNotify callback, can't be anywhere else, but I haven't confirmed it.

.. If you simple *prevent* the SPTD detour from executing and instead restore the NTICE bytes yourself then call the corrected DriverEntry.. Softice will load and function but will be unstable and crash eventually. One of the first things the SPTD detour code does is to call IoFreeMdl on a previously allocated MDL. I am presuming this MDL may have been allocated in the LoadImageNotify callback for some reason. This seems to indicate that the two code sections are interdependant.

This does raise questions as to *what* is SPTD doing? If the idea is to simply not allow NTICE to load then the detour doesn't have to do anything except divert and return. Instead it handles MDL's, tests the Irql, flushes the instruction cache, and many other things I haven't figured out.


Finally, one last, and major caveat! While Softice does seem to work now, I can breakpoint and trace relatively normally. Daemon Tools still works as well, I can map an iso drive and play a game which would normally requried a CD, etc. I did have some problems with Softice. For one, as soon as Softice was enabled I lost keyboard support in Windows (though it still worked in Softice itself). I have only run this under VMWare in XP and Win2K and have occasionally had similar problems when mucking too deeply in Softice anyway. I have not tried this on my "real" system so the problem might or might not show up there. Also, breakpoints in SPTD code itself (for example the LoadImageNotifyRoutine) seem to cause an immediate crash, deliberate or inadvertent I do not know.

The bottom line is that my "solution" is probably not stable, is unlikely that it can be used for tracing SPTD code itself, and basically I wouldn't recommend it except for those adventurous souls who like to play around with this kind of stuff.. /end caveat


One thing that did cross my mind.. the people who wrote this are very clever and have my full respect. I don't want to expose their work or make it easier for other "parties" to undermine their efforts. I do however feel it's important to be able to ascertain the extent of any kind of rootkit code, which I categorize this as, to be able to determine its intent, the DMCA notwithstanding. I was wondering though, back to *why* the detour code is so complex, I know you don't *need* a kernel debugger to write driver code, but how did these guys debug their code? I'm curious if, somewhere deep in the LoadImageNotify and Softice detour code, there exists a backdoor "switch" which allowed for debugging of the code during development? This is just a fanciful idea and probably not the case.

Cheers,
Kayaker

dELTA
October 17th, 2006, 07:54
As always, you are the almighty ring 0 wizard Kayaker, and it's a joy to read about your excavations every time.

About the little "master switch" idea at the end, my experience tells me that these things are normally implemented using compiler directives, not using runtime checks. So yes, I think they do indeed have such a master switch, but rather in the form of a compiler directive that enables/disables/replaces code in one or (more likely) several places before compilation, rather than a runtime flag check.

But still, if just pinpointed (which is often 95% of the work in a reversing project of course), most protections like this one can be completely neutralized with just a few carefully crafted patches in the right places.

And like you say, protecting your own code is one thing, but rootkitting the operating system and disabling other programs is another, which makes it quite legit to try to "fix these side effects" I think. I'll be looking forward to any other findings regarding this subject anyway.

Maximus
October 17th, 2006, 09:08
I totally agree.
Such feature must be disabled, and it should really be analized for discovering *why* they don't want sice on. Indeed, Syser loads fine

LLXX
October 17th, 2006, 23:23
Quote:
[Originally Posted by Kayaker]I know you don't *need* a kernel debugger to write driver code, but how did these guys debug their code?
They may have a hardware-based debugger, aka ICE (not soft ). You can debug almost anything with those. Even software-based debuggers like SoftICE; and see "anti-debug" in action. The thing is, they're prohibitively expensive.

JMI
October 18th, 2006, 02:26
And for those whose searching skills may not be up to par:

The in-circuit emulator (ICE) remains the most powerful debugging tool available. Nothing else approaches an ICE’s wide range of troubleshooting resources; no other tool so completely addresses problems stemming from hardware/software interaction. The emulator’s birth was almost coincident with the start of the microprocessor age, since micros live deeply buried in applications that simply don’t resemble computers.

http://www.embedded.com/1999/9910/9910sr.htm

Regards,

blabberer
October 18th, 2006, 04:45
talking of hardice "au contraire" softice yep may be something like american arium products were used to debug them

hi kayaker,

though a lot of things you posted doesnt register in my mind yet

i grasp that the sptd.sys patches sice's entrypoint and prohibits
it from loading and thats the most probable cause of sice being not able to load

well so i have a question i assume you might have tested this with windbg kernel debugger too with two machine setup

in the target the only requirement is to add the /debug switch to boot .ini
for activating the kerneldebugger

so i think (there cannot be a generic driver or whatever that could be patched in its entry point (yeah i may be wrong may be some kd.sys exist and may be its being loaded if there is a /debug switch i dont know it just occured to me that a legacy old win2k cd with no service packs loaded into a vm and not updated but just install this app that uses this sptd.sys might not anticipate changes that would be there in the latest versions of kd
or does it check if the debug switch exist and prevent from loading itself so that the child usermode programs dont work probably its later maybe )

so why does this sptd.sys hate kd too (does it hate kd ?)
yeah it might be checking some apis like isKDebuggerEnabled()
but that could be handled i suppose if you really break while this sptd.sys is
doing its stuff

you can break into a kd while only one process is active that is the system process i believe and when the minimalist of minimal drivers has loaded

any explanation in this regard would be enlightning


and thanks for writing such excellent articles in a four part series its
absolutely fantastic reading articles of this calibre motivates one to
really dig deep deeper and deepest

regards

Kayaker
October 18th, 2006, 16:29
I *KNEW* you'd be the one asking about WinDbg blabberer, I just knew it!

Yep that was a good guess, if you boot with the /DEBUG switch, SPTD never loads at all and you can use Softice or WinDbg to your hearts content. In fact this a great way to set up a dual-boot option to allow you to use one or the other (SPTD or debugger). Kinda surprised they might not have mentioned this option to users who DO want to use a kernel debugger for valid reasons other than reversing SPTD or its apps

So yeah, SPTD probably checks the exported variables KdDebuggerNotPresent or KdDebuggerEnabled early during its initialization, but this is most likely hidden within the Virtual Machine code it uses.

Far be it from me to suggest a way to circumvent this , but what IF..

..you create a boot loading driver which loads just *before* SPTD and disables the KdDebuggerEnabled flag. You might be able to do this by modifying the ServiceGroupOrder as we discussed earlier.
..you "later" reenable the KdDebuggerEnabled flag so things operate correctly.
.. if "later" (post boot) is too "late", maybe create a second driver but which loads immediately *after* SPTD and reenables the flag. Boot loading then continues normally.

This isn't to say there might not be other checks for /DEBUG, but if it's a simple test of that flag during SPTD initialization this idea should effectively "blind" it.

K.

blabberer
October 19th, 2006, 04:55
Quote:

I *KNEW* you'd be the one asking about WinDbg blabberer, I just knew it!




premonitions,some kind of esp (not the damn register in x86 cpus) or telepathy what makes you know it


anyway thanks for confirming my dumb guess
so if it didnt load sptd then the child dont work so windbg works and
i am happy (i was looking at the site there is a sptdinst avialble for download) is it enough to download only that if i want to play with sptd ? or should i get that whole bunch of thingies including the toolbars and stuff that it asks)
any way it looks like its a slim package no gigabytes of bloat to downlaod
so possibly i may give it a spin if only to see and understand )

ok so if it commits suicide since it cant assasinate (damn suicide bomber)
how about getting it to a lab and injecting it with truth serums like
trying to load it after you start with (load image whatever )(just like your sysdasm loads) and have some breakpoints ready in kd in system code
and simply bruting (no brain just brawn)through the code step by step (yep if it is a vm it might be tough but ) and having damn breaks all over it has to end up in system some where (once it spits one little secret password forensics can take over the rest of the jigsaw)

with kd on
and doing a bm nt!A* bm nt!B* bm nt!C* bm nt!D* .....,bm nt!Z*
bm hal!A* to bm hal!Z*

and have a logopen so that you could simply g g g and if it crashed
you could simply look at the log and stop one stepabove

yeah it sounds simple i guess the authours of this thing would have
sure thought about this if they wrote such master pieces damning
every piece of debugger and would have put in place some kind of
checks to prevent this

but like the sages of the yore used to say if it runs it cant hide
it can hide from someone for somedays but it cant hide from everyone
everyday

yep its time to get the four-f's kit and masm32 dusted out

Kayaker
October 19th, 2006, 11:07
Quote:
premonitions,some kind of esp (not the damn register in x86 cpus) or telepathy what makes you know it

Noooo.., [ESP+00h] had nothing to do with it. It has more to do with your apparent mastery of the usage and syntax of all the cryptic WinDbg commands (I've seen the output you've sent me). This "tool wizardry" is only rivaled by that you show with Olly

Quote:
is it enough to download only that if i want to play with sptd?

The driver install is enough for analysis purposes. The rest is no big deal, the usermode toolbar ad-thingy is a secondary optional install which you can completely disable from the registry Autorun.

Quote:
how about getting it to a lab..

Yup

Regards

blabberer
October 22nd, 2006, 11:46
hi kayaker,

i was reviewing this thread from start

i see you mentioning an indirect call that calls Driverentry()

this call called only by which class of drivers only those that are started via SERVICE_DEMAND_START ?

does it apply to your bootbus extender and boot phase drivers too

anyway it looks like boot phase drivers arent being called via this call
and also the loadasimage or linkasdll sysdasm.sys or neither four-fs



here is the output of windbg
Code:

kd> .reboot
Shutdown occurred...unloading all symbol tables.
Waiting to reconnect...
Connected to Windows 2000 2195 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.
Symbol search path is: srv*c:\debugsymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows 2000 Kernel Version 2195 UP Free x86 compatible
Kernel base = 0x80400000 PsLoadedModuleList = 0x8046e1b8
System Uptime: not available
Break instruction exception - code 80000003 (first chance)
nt!DbgBreakPoint: <--- break by /break switch in boot.ini

8045647c cc int 3
kd> bl
0 d 8045647c 0001 (0001) nt!DbgBreakPoint

kd> bp nt!NtLoadDriver
kd> bp 8049a037 ".printf \"%y\\n\", poi(eax+2c);g"
kd> bl
0 d 8045647c 0001 (0001) nt!DbgBreakPoint
1 e 8052dc72 0001 (0001) nt!NtLoadDriver
2 e 8049a037 0001 (0001) nt!IopLoadDriver+0x66f ".printf \"%y\n\", poi(eax+2c);g"

kd> g
*** ERROR: Module load completed but symbols could not be loaded for vpc-8042.sys
vpc_8042+0xd1f2 (feaca1f2)
kbdclass!DriverEntry (f96abe64)
mouclass!DriverEntry (f96bb4e4)
serial!DriverEntry (f945a380)
serenum!DriverEntry (f987ab00)
fdc!DriverEntry (f96d4f30)
parport!DriverEntry (f96e04a2)
gameenum!DriverEntry (f9881ba0)
ctlsb16!DriverEntry (feaaff00)
cdrom!DriverEntry (f96fdbc0)
*** ERROR: Module load completed but symbols could not be loaded for vpc-s3.sys
vpc_s3+0x73ca (fea4a3ca)
dc21x4!DriverEntry (f947ece0)
audstub!DriverEntry (f9a3f500)
rasl2tp!DriverEntry (f948b780)
ndistapi!DriverEntry (f9891762)
ndiswan!DriverEntry (fea3fae0)
raspptp!DriverEntry (f949a920)
ptilink!DriverEntry (f97282e0)
raspti!DriverEntry (f973b240)
parallel!DriverEntry (f94a2bbe)
swenum!DriverEntry (f9a426c0)
update!DriverEntry (fea2a660)
flpydisk!DriverEntry (f9753b80)
Breakpoint 1 hit
nt!NtLoadDriver:
8052dc72 55 push ebp
kd> g
NDProxy!DriverEntry (f94d8720)
Breakpoint 1 hit
nt!NtLoadDriver:
8052dc72 55 push ebp
kd> g
Sfloppy!DriverEntry (f98bdc80)
Fips device driver loaded successfully
Fips driver locked into memory
Fips driver unlocked from memory
giveio: Entering DriverEntry <--- four-fs datetime dbgprint
giveio: Leaving DriverEntry

Breakpoint 1 hit
nt!NtLoadDriver:
8052dc72 55 push ebp
kd> g
*** ERROR: Module load completed but symbols could not be loaded for SysDasm_LinkAsDLL.sys
SysDasm_LinkAsDLL+0x940 (f9af3940)
Invalid Address <--- i passed kdasm da 701000
Invalid Address
Invalid Address


Kayaker
October 22nd, 2006, 14:38
Hi blabberer,

Cool results. Undoubtedly the different driver types and load methods use different code from the standard SERVICE_DEMAND_START startup. My assumption was that C:\NTLDR handled much of the early boot loading. Within NTLDR is the embedded file osloader.exe, within that you can see string references to bits of driver loading info, including the ScsiPort* imports that SPTD.sys and its associated driver SPTD***.sys use. Someone over at RET did some NTLDR reversing of interest:
http://www.reteam.org/board/?showtopic=351

I took a look at the boot sequence as recorded by Boot Log XP (Greatis). It shows the 'Boot Bus Extender' drivers such as sptd and cpthook, also 'PnP Filter' drivers such as agp440 or 'Base' drivers such as KSecDD, all loading as the first group. I presume these are all loaded by the NTLDR process.

Next it shows the drivers which are loaded at boot as the second group, by the SYSTEM process, such as i8402prt, kbdclass, mouclass, etc.

What's interesting is that if you output the results to a text file it indicates that the first group of drivers (loaded via NTLDR) are loaded under the ProcessId = -1. The second group of drivers are loaded by the SYSTEM process, with a ProcessId = 4 (as normal).

I was just thinking in terms of WinDbg whether you can use this ProcessId value, or some other way, to make WinDbg *stop* execution on boot loading while the NTLDR (osloader.exe) or SYSTEM process is executing. If your intent is to break while SPTD is loading you need *some* way to get WinDbg to stop OS loading at a very early stage. Not sure how you could do this but it would be interesting to be able to step through OS loading from the very start.

Kayaker

autarky
October 23rd, 2006, 02:36
The earliest possible breakpoint that can be set with WinDbg is if you use the /BREAK switch (along with the ususal stuff) in boot.ini. This causes the kernel to break at HAL initialisation. I don't think you can break earlier with WinDbg as the target machine hasn't initialised enough for the debugger to be usable. The only way to break before this would be to use a hardware solution.

According to Windows Internals, boot drivers are loaded by NTLDR, but their DriverEntrys are not called until much later, just before the system-start service drivers are started. I have used WinDbg to step through the driver loading code on XP when I was playing about with some rootkits. I can't remember exactly what happened as it was maybe 6 months or more ago. However, the signature for the code that calls DriverEntry from IopLoadDriver is '57 ff 57 2c 3b c3' on all XP versions I've looked at:

Code:

push edi
call [edi + 2c]
cmp eax, ebx

blabberer
October 23rd, 2006, 05:31
yes auturky /break switch is the most earliest break thats possible in normal way of things but reversers dont work normally if you screw up on /break
stepping inside while cli sti disable interrupts are effective and it is highly possible its a royal pain in the uhmmm to step through many of the codes
as many of them call irets and stuff that

(its completely spaghetti code if you ask a c application programmer interspersed with gotos (unconditional jumps to hell ) yeah goto is of tremendous use when you are coding pretty lowlevel )

effectively cant be single stepped
(single stepping on irets mostly causes stack to filled with gibberish and the return pointing to iret again and again till possibly stack overflows )
i think stack gets filled with cs,eip,and possibly efl and the retn address which points to itself


you end up with HAL_INITIALISATION FAILED bugcheck (bugcheckcode ox5c)

after that comes commandline switch -d which breaks on symbol loading of the first kernel module usually ntoskrnl.exe the next is hal.dll and the then starts bootvid.dll and other blah blah drivers
and then comes -b commandline switch which breaks after kernel is initialised

and btw are you sure IopLoadDriver is called ?? probably may be called with disabled interrupts because after success of HAL_INITIALISATION
you can see HalExecutiveInitialize calling RestoreInterrupts()

anyway ill check if it is being called i highly doubt windbg will break while it is in HalExecutiveInit stage

autarky
October 23rd, 2006, 07:04
You're right, IopLoadDriver isn't called during HAL initialisation, or anything like that. I've just used it to break on driver loading. However, I can't remember if the code I mentioned above was called by the kernel when it calls the DriverEntrys of drivers loaded (but not initialized) by the NTLDR. I know it's called by IopInitializeSystemDrivers. I've got Daemon Tools on the machine I normally debug, so I can check in about 5 hours time when I get back from work. Maybe MiBuildImportsForBootDrivers is worth a look, or MiReloadBootLoadedDrivers (called from MiInitMachineDependent) and IopInitializeBootDrivers (called from IoInitSystem). Not much/any documentation on any of these.

Also, I've never tried stepping through the HAL, just used it as a useful stopping point to set further breakpoints. From what you've said, I don't think I'll ever try it either.

blabberer
October 24th, 2006, 13:59
hi kayaker ,

thanks for the information i was looking around for information on the

f8 debugging mode (advanced options in boot menu)to see if it in any way helps in breaking pretty early

though i couldnt land any pertinent information on how to break

i found some sites which do have a lot of information of the process itself
if these guys do know all these then there should be some ways not everyone runs with hardware ices so some software debugging methods should exist ill post back if i find anything more

in the meanwhile

this link is what i am referring

http://onyx.yonsei.ac.kr/courses/management/down/Chap4-StartupandShutdownbootprocess.ppt

just explore the root it looks like its holding a goldmine of information

blabberer
October 25th, 2006, 13:44
reviewing the ppt again today with little help of kd
all the percentages it speaks of is after the splash screen is shown
and not before the splash screen is hsown

i was jumping to conclusions thinking that the ppt is talking about the
progress bar in txt mode

well all that the ppt says could be confirmed with kd

anyway here is some edited paste on driver entries from kd after all it is debuggable may be one needs some patience to get the vm or whatever obfuscation straightened out and thats what is needed to find out if it is a true incompatibility or intentional antidebug

Code:


kd> g
nt!RawInitialize (8056308e)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
*** ERROR: Module load completed but symbols could not be loaded for sptd.sys
sptd+******* (********)
Error code: (NTSTATUS) 0xc000009a - Insufficient system resources exist to complete the API.
ACPI!DriverEntry (febdc14b)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
pci!DriverEntry (f940bca8)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
isapnp!DriverEntry (f9419b62)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
intelide!DriverEntry (f99002c0)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
MountMgr!DriverEntry (f968e100)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
ftdisk!DriverEntry (febb42f8)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
Diskperf!DriverEntry (f99033a0)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
dmload!DriverEntry (f99044fa)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
dmio!DriverEntry (feb7b816)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
PartMgr!DriverEntry (f98161a0)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
atapi!DriverEntry (feb75bfa)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
disk!DriverEntry (f9695b40)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
Fastfat!DriverEntry (feb5e8e6)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
KSecDD!Sel <PERF> (KSecDD+0x1031e) (feb3e31e)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
NDIS!DriverEntry (feb2ab7e)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0
Mup!DriverEntry (feaf3de4)
Error code: (NTSTATUS) 0 - STATUS_WAIT_0


have phun

evlncrn8
October 25th, 2006, 17:47
for sure its intentional... they want to stop people from recreating their product (and/or the protection people from finding methods to blacklist their code easily... and seeing as its pretty much blacklisted by most prots (you need to use 3rd party tools to 'hide' alcohol or daemon) already, its kinda futile)..

autarky
October 29th, 2006, 09:30
I spent all week down the pub, and have only got round to going through the driver loading now. So, a quick overview for the interested:

Boot drivers are loaded by NTLDR somewhere low down in physical memory. Once paging and protected mode is turned on (I'm not sure which order this happens in, but Windows Internals will say), these boot drivers (including ntoskrnl) will all be in the low area of kernel memory, typically 0x800XXXXX. This is done to avoid a circular dependency whereby ntoskrnl would have to use a file system driver to load itself - directly talking to the hardware being left to the HAL and NTLDR.

However, these drivers cannot be run by NTLDR, as the NT subsystem isn't up and running yet. So, once execution is handed over to ntoskrnl, all boot drivers are relocated and initialised during Phase1Initialisation. The IO manager initialises itself, and in so doing calls MiReloadBootLoadedDrivers which copies all the boot drivers up to the other end of kernel memory where drivers typically live (0xFXXXXXXX). Having done this, the drivers' are all initialised by calling IopInitializeBootDrivers, which in turn calls IopInitializeBuiltinDriver, which calls the DriverEntry directly for each driver. The code signature on XP SP2, single processor is FF 53 2C 8B F0 (I haven't checked any others):

Code:

call [ebx + 2c]
mov esi, eax


Not that you need to find and BP that code - a one shot on MiReloadBootLoadedDrivers, then a BP on the call in that function to LdrRelocateImage will suffice. This will be called for every boot driver to do the relocation table fixups. Recognising sptd is not difficult, so just hit 'g' until it's its turn - I just dereferenced what was on the top of the stack each time a BP was hit. And, seeing as the new base address is on the top of the stack, we can just use that to put a BP on the EP, and then hit 'g'.

I may have a look later today to see where the code that's returning that error is. 'tc' might do the trick. I'm not very experienced with WinDbg.

autarky
October 30th, 2006, 09:38
This isn't directly related to the above post. Anyway, the code is encrypted, and the VM is used to decrypt the encrypted code section and original DriverEntry. It may well do other stuff as well, I haven't stepped all the way through it as I haven't the patience. It does use the debug registers for stuff. I don't know what is returning the 'insufficient resources' error, but it's not one of the usual suspects (such as ExAllocatePoolWithTag). Underneath, it's a plain old driver written in C.

It's possible to dump the image, though it will be missing the INIT section. It can be dumped - livekd works (try .writemem), and I've been working on something to dump kernel modules from user mode. There is section based obfuscation (due to the slightly different way kernel modules are loaded), so the dumped file needs some reconstruction. I should have a decent reconstruction this evening, minus original DriverEntry. The section based obfuscation is worth paying attention to if you're interested - I haven't seen it before.

It doesn't look rootkit-esque at the moment, I'll be able to get a better idea later. To be honest, I was and still am more interested in the armour. KM armour isn't that well explored (at least not publicly) under NT to my knowledge. You can do some pretty cool stuff.

blabberer
October 30th, 2006, 11:53
I am not much aware of the intricacies of discardable pages but i think you shouldn't loose any thing if you dump at right moment

Code:


.data:FEC52FFF
INIT:FEC53000 ; ---------------------------------------------------------------------------
INIT:FEC53000 ; Section 5. (virtual address 00060000)
INIT:FEC53000 ; Virtual size : 0001E000 ( 122880.)
INIT:FEC53000 ; Section size in file : 0001E000 ( 122880.)
INIT:FEC53000 ; Offset to raw data for section: 00060000
INIT:FEC53000 ; Flags E2000020: Text Discardable Executable Readable Writable
INIT:FEC53000 ; Alignment : 16 bytes ?
INIT:FEC53000 ; ---------------------------------------------------------------------------
INIT:FEC53000
INIT:FEC53000 ; Segment type: Pure code
INIT:FEC53000 INIT segment para public 'CODE' use32
INIT:FEC53000 assume cs:INIT
INIT:FEC53000 ;org 0FEC53000h
INIT:FEC53000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
INIT:FEC53000 push 8A780h
INIT:FEC53005 jmp loc_FEC18578


i am not aware if this is original driver entry or not

Code:

start ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
start
start ; Attributes: bp-based frame
start
start public start
start start proc near
start
start arg_0 = dword ptr 8
start arg_4 = dword ptr 0Ch
start
start push ebp
start+1 mov ebp, esp
start+3 call sub_FEC6B010
start+8 test eax, eax
start+A jnz short loc_FEC6F0E5
start+C and [ebp+arg_0], eax
start+F
start+F loc_FEC6F0E5: ; CODE XREF: start+Aj
start+F cmp [ebp+arg_0], 0
start+13 jz short loc_FEC6F12A
start+15 cmp [ebp+arg_4], 0
start+19 jz short loc_FEC6F12A
start+1B push esi
start+1C call sub_FEC6D296
start+21 mov eax, dword_FEC4F320
start+26 cmp eax, 100h
start+2B jnz short loc_FEC6F112
start+2D push [ebp+arg_4]
start+30 push [ebp+arg_0]
start+33 call sub_FEC6DEFE
start+38 mov esi, eax
start+3A jmp short loc_FEC6F117
start+3C ; ---------------------------------------------------------------------------
start+3C
start+3C loc_FEC6F112: ; CODE XREF: start+2Bj
start+3C mov esi, 0C000009Ah
start+41
start+41 loc_FEC6F117: ; CODE XREF: start+3Aj
start+41 test esi, esi
start+43 jge short loc_FEC6F125
start+45 call sub_FEC6D0CE
start+4A call sub_FEC6D2CA
start+4F
start+4F loc_FEC6F125: ; CODE XREF: start+43j
start+4F mov eax, esi
start+51 pop esi
start+52 jmp short loc_FEC6F12F
start+54 ; ---------------------------------------------------------------------------
start+54
start+54 loc_FEC6F12A: ; CODE XREF: start+13j
start+54 ; start+19j
start+54 mov eax, 0C0000183h
start+59
start+59 loc_FEC6F12F: ; CODE XREF: start+52j
start+59 pop ebp
start+5A retn 8
start+5A start endp
start+5A
start+5A ; ---------------------------------------------------------------------------

autarky
October 30th, 2006, 12:42
Ok, yeah, that's the original DriverEntry . But seeing as it looks like a standard C driver, I was interested in the 'original' DE, ie the one before it was protected with whatever it is - the one that creates any devices, access parameters in the registry, and typically does the hooking in a kernel mode rootkit.

And if you try and dump the module during runtime, then livekd (or whatever) will error when it gets to the INIT section, as it has been discarded. I'm not sure when the IO manager gets rid of it, but probably fairly soon after the DriverEntry returns success. Certainly by the time I've booted up and started liveked. Though, I suppose it might work if you just renamed the section to something else, and fix the xsum in the PE header. I'll check later.

upb
November 20th, 2006, 06:15
hi, i dont think its actually the name that triggers the discarding but section flags.

autarky
November 20th, 2006, 08:28
Yeah, I just checked that, and that's correct as far as I can tell. Though the kernel does check specifically for sections with names starting INIT, PAGE, and EDAT. Though what it does in those cases, I don't know. I've been too busy with other kernel mode and native stuff to get a properly analyzable dump; I might have another go in the next couple of weeks, depending on how things pan out.