Log in

View Full Version : Softice detection in general...(and hiding)


Snatch
January 9th, 2002, 17:20
I have a simple question for the brains out there. It seems as if the only good ways to detect softice apart from doing silly things like looking for the files or using the registry which dont tell whether it is loaded or not and is a very bad technique and not too hard to defend against I reckon. But aside from those all the tricks seem to use VXDCall ?, Int ?, or a handful of API calls. Now am I missing something or could I put a global wide hook on all of these calls and then return what I like. A program that has a list of trapped calls such as Int 21h, Int 41h, Int 48h, Int 3h, the VXDCalls and API's, and then the program would let you choose the return values based on the input values and not call the actual routine. Wouldnt that set anti softice tricks behind permanently. I admit I am a newbie in this field so maybe I am missing something fundamental but it would seem that a program of this sort would be the universal Softice hider.

Snatch

Kayaker
January 10th, 2002, 21:21
Hi Snatch,

Seems reasonable, though I'm just getting into this myself. From the testing Clandestiny and I have been doing lately there seems to be little problem in hooking the IDT and installing your own error handler, even with Icedump /PROTECT loaded. INT 1 hooking while debugging in Softice using INT 1 as a breakpoint is problematic ;-) , but the rest are OK.

The question probably is, do you chain to the original interrupt handler or not, and how do you determine from whence the interrupt came? In our code the interrupt is going to be generated by ourselves after hooking the IDT.

While in our handling routine (which will take msecs to seconds in time to complete) there *may* be an interrupt generated from outside. We can easily detect our *own* interrupt by scanning for the bytes we inserted. If there happened to be another of the same interrupt called we would have to handle it if it warranted handling by the system. Either we let our own app crash (try for a clean exit), or we let the system handle it, necessitating chaining, and hope it returns gracefully to our code. Depends if it was chained back to us I would assume. This Reentrancy problem is a real issue.


In your case, from the way you put it, you want to protect Softice for example, so I assume you would want to *know* if the interrupt(s), VXDCalls, etc. that you hook are being generated from a potentially bad app that is trying itself to detect SI. Or, you hook them explicitly and don't allow any of the interrupts to be handled by other than yourself. If you write in a vxd you will have priority over Ring3 apps, so if you test the registers for whatever signature bytes might be used (ax/bx, "FG-JM", BCHK...) you should protect from the standard techniques.

But, what if the SI detection is from a VXD call such as VMMCall Get_DDB? The vxd could have overwritten the IDT itself, kicking you down the line on having priority over the interrupts n'est pas? Who's on first, No he's on second, What's on third? How do you protect the IDT from a vxd? Do you always RE-hook the interrupt once again? RE-RE-hook perhaps? Icedump protects the IDT, but only from Ring3 apps.

Interesting thought about the program letting you choose what you want to do. Once you're out of vxd code though you're at the mercy of the system unless you can suspend the thread of the app that caused the interrupt I would think, or whatever thread that led to you. I haven't checked, but will a BSOD accept more than a single keystroke as input? Something a little more advanced would be to access Softice itself to help and use it for I/O, however Icedump does it. Or register a dot command such as Softice EXtension (SEX) does to communicate with Softice.

I did see a protector (or would that be deprotector, I really can't differentiate any more, they both fight on the same battleground it seems) which handled a lot of the common Softice detection routines, no not Frogsice or Icedump, I know I have it on my hd somewhere but my filing system still kinda sucks

BTW, why the hell does Adobe Acrobat try to access the LDT? (Try a .pdf file with Icedump /PROTECT on

Cheers,
Kayaker

Snatch
January 11th, 2002, 11:48
Very interesting problem. You have to hook the hook routine. So when an application tries to hook it you can pretend to let it hook the table when in truth it hasnt. Something like that. To make sure the application can never hook anything ahead of you. Or if they do you have the hook routine hooked so you rehook in front of their app as you were saying. None of this sounds easy simple or even documented. But in theory something good should be possible . Figuring out if it is the app or something legal is a problem too. Maybe you could use the process handle to determine. And why the hell does acrobat use the LDT? I know for a fact that Acrobat's docbox.api wont load with softice present and will without it. Are they trying to hide something? Wouldnt surprise me after they got so angry when Dmitry Skylarov talked about their silly weak ebook encryption scheme.

Snatch

Kayaker
January 11th, 2002, 23:13
Just a little banter about an interesting topic...

There's actually a series of Window functions already set up to handle interrupts that you could use, including Hook_V86_Int_Chain.

mov eax, Interrupt ; number of interrupt to hook
mov esi, OFFSET32 HookProc ; points to hook procedure
VMMCall Hook_V86_Int_Chain

jc not_installed ; carry flag set if procedure not installed

"Installs a hook procedure that the system calls whenever the specified interrupt occurs.
Any number of virtual devices can install a hook procedure for a given interrupt. The system always calls the last hook procedure first. A hook procedure either services the interrupt or directs the system to pass the interrupt to the next hook procedure. If no hook procedure services the interrupt, the system reflects the interrupt to the virtual machine.

This service is recommended instead of hooking the V86 interrupt vector directly. "

------------------------

I think the last line is the key. If an application was trying to access the IDT for, shall we say 'aboveboard' reasons, the programmer might choose to use the Windows functions to do it. All flags and registers are saved for you in a Client_Reg_Struc structure, nice safe programming, guaranteed from MS itself

If a 'protector', or vilest of all, a virus, were trying to install its own hook procedure it might try to hide that fact by doing it directly with sidt. If it was trying to detect Softice it would likely do it by

Hook IDT -> Detect Softice by chosen method -> UnHook IDT
or
Hook IDT -> Detect Softice by chosen method -> Leave Hook installed


If a 'deprotector' were trying to circumvent that it would need to get in after the app hooked the IDT but before SI was detected. This could be a matter of a few lines of code. The only thing I can think of is use a loader and wait until the app loads its vxd. Somehow you need a way to detect when the IDT has been changed. Immediately rehook the IDT and intercept the interrupt yourself.

Or you detect when the app dynamically loads a vxd with CreateFileA. I think it could change the IDT in its loading call (DIOC_Open) even before CreateFileA returns anyway, but you *might* be able to install over that or handle return values from DeviceIoControl before it shuts itself down (or whatever it's going to do). If it craps out on you in a BSOD without using DeviceIoControl you're probably screwed anyway. But then this would be extreme and is no way for an app to handle the fact that SI is loaded.

I see scenarios where you might be able to handle it in an 'application specific' form, but only the guru gods know if there's a more global method ;p

Kayaker

Snatch
January 11th, 2002, 23:57
This is definetly an interesting topic. It drives straight into the topic of emulation. If you had an emulator doing everything then it would be a walk in the park to find the interupt or hook calls. Or native assembly sidt. Of course it would be slow but if its just a tool for debugging than that is a small cost. Emulation sounds like a great unpacking technique. Instruction by instruction. You have complete control of the target before anything is done. Just have to keep updating it for different targets doing different things. A thought. Lots of work required but the payoff would be the ultimate softice hiding tool.

Snatch

tony b.
January 12th, 2002, 23:30
About Adobe's Softice detection - from what i have seen,
this is caused by the Intertrust docbox plug-in. It does
only the standard CreateFile() trick, so its easy to
bypass. You can also just delete the Intertrust docbox
plug-in from the Adobe plug-ins dir, as i did, since its
not really useful for anything (well i haven't seen any
docbox protected stuff anywhere)

regards,

tony (btw, the above is on NT -- dunno what they might
do for 9x)

Clandestiny
January 14th, 2002, 19:54
Quote:
Originally posted by Kayaker

If a 'deprotector' were trying to circumvent that it would need to get in after the app hooked the IDT but before SI was detected. This could be a matter of a few lines of code. The only thing I can think of is use a loader and wait until the app loads its vxd. Somehow you need a way to detect when the IDT has been changed. Immediately rehook the IDT and intercept the interrupt yourself.


Hi guys,

Interesting question. How exactly do you detect when the IDT has been changed? To me its seems related to the question of 'how do you detect read / write access on a memory range ?'... If you could detect a write access on the memory range for the IDT, you could theoretically rehook the interrupt the IDT at the changed address before any nasty anti-SI tricks had a chance to be performed. I know there are at least 2 ways to detect memory reads and writes...

1) Detecting write access across a *range* of memory can be accomplished by marking the corresponding page table entrys as 'not present' for those addresses. When an access on one of those addresses occurs, a page fault is generated and hooked to determine if the faulting address lies in a specific range.

The VMM reference touches on this issue a bit in its discussion of virtual memory:

-----------------------------Excerpted from the VMM Reference------------------------------
"The 32-bit linear address space used by the Intel 80386 and later microprocessors is divided into 4 kilobyte units called pages. Each page can be assigned specific permissions, and can be mapped to any 4K section of physical memory. The base physical address of a page is its page frame address. A page can also be marked not present, in which case it does not map to any physical memory.
Page mapping is possible because of page translation, the mechanism by which the CPU translates linear addresses to physical addresses. A linear address can be viewed as a combination of two values: a 20-bit page number, and a 12-bit offset (4K = 2^12 bytes). The CPU uses the page number to locate a page descriptor, which contains a page frame address and other information. Adding the offset to the page frame address yields a physical address.

A page that is marked not present does not map to any physical address. Attempting to access such a page triggers a page fault. Typically, a page is marked not present if has been temporarily swapped out to disk or if no physical storage has been allocated for the page. In addition, virtual devices may mark a hooked page as not present in order to trigger a page fault every time the page is accessed. The system does something similar for instanced pages."
------------------------------------------------------------------------------------------------
SoftICE actually employs this method to implement the range breakpoint (bprw) command and this is discussed in +Spath's SoftICE internals essay.

We can speculate some obvious drawbacks to trying to use this method for detecting access on the IDT. First, there is no way to distinguish between memory reads (which would occur all the time as the processor goes to look up the handlers for various system interrupts) and memory writes (which would occur mostly only when a specific application hooked a vector in the IDT). Most likely chaos would ensue at any attempt to implement such a scheme, but even if it didn't, the performance hit would probably be formidable.

2) The second method of detecting memory access relies upon using the internal debug registers. The debug registers have the added benefit of being able to detect the *type* of access (read or write). They are also used by SoftICE to implement the bpm commands. One might be able to use the debug registers to watch access and prevent hooking of a couple of the key IDT interrupt vectors used in SI detection. The drawback here is that there are only 4 debug registers. And of course, there's the possiblity that there might be some conflict w/ SI over the control of the debug registers. I really don't know. Its an interesting topic and I'm just speculating here.

As for how to tell if the access was performed by something legit?... I don't even want to venture specluation on that difficult issue

Cheers,
Clandestiny

Kayaker
January 15th, 2002, 01:23
Quote:
Originally posted by Clandestiny

Interesting question. How exactly do you detect when the IDT has been changed? To me its seems related to the question of 'how do you detect read / write access on a memory range ?'... If you could detect a write access on the memory range for the IDT, you could theoretically rehook the interrupt the IDT at the changed address before any nasty anti-SI tricks had a chance to be performed.


Hiya,

Now we're getting into the meaty stuff...

Your question is a good one that strikes into the heart of the matter. If we assume an app will use Ring3 to hook the IDT (of course we all know what happens when we ass-U-me don't we? , then if you are in Ring 0 you should be able to detect that. How is unclear, but there is code available that does just that, even if it's shrouded in some mystery.

My thought was more on a Ring0 - Ring0 equal footing basis. If the app was using a Win9x vxd, NT kmd or sys file could a change to any critical system area be detected? Is it possible to protect certain areas of memory against any kind of read/write such that a fault could be redirected to your own exception handler?

Again, +Spath's document is always illuminating.

------------------------------------------------
"BPR is SoftICE's breakpoint on memory range, which can detect read
and write accesses to a (hardcoded) maximum range of 400000h bytes.
This is done by marking the corresponding page (or pages, up to 1024)
as non present : when an access to a non present 4k page is made, a
page fault occur, SoftICE's page fault handler is called and checks
if the faulting address is in the required range.

It should be noted that since the non-present bit of the PTE is used,
this can detect accesses from any privilege level, yet SoftICE will
only trigger for accesses from ring3. This means that for some reason
SoftICE page fault handler filters accesses from ring0 (and therefore
limits this breakpoint's capabilities).
-----------------------------------------------

It seems that Softice itself detects access to a protected page from Ring0, but only reacts to Ring3 attempts to read/write to that page. Detecting Read and Write are apparently 2 different schemes, I don't know how 'eXecute' in the BPM <address> R W RW X scheme is handled differently. From what I can gather Softice uses INT 0Eh for its BPR page fault detection. This is the Hard Drive Interrupt?

The VMM Reference says in the above post that each page can be assigned specific permissions. Question is, how do you assign a permission to a page? This might be a valid way to detect an access to the page containing the IDT or the other descriptor tables. I've also heard about "touching or pre-touching" a page in memory to force it present, anybody know about this?


One interesting thing is when Softice has hooked it's 16 interrupt vectors in the system IDT it makes a backup copy of the original IDT that it "presents" to you when you type 'IDT', giving you false handler address information.

-----------------------------------------------------------
The 'IDT' command does not reveal this [hooking the interrupts], but instead shows these interrupt
descriptors pointing to their original locations (usually VMM). This is
because SoftICE saved the original IDT before setting its hooks, and when
the user types the command, it reloads IDTR to use the saved IDT, executes
a "real" 'IDT' command, and restores IDTR to the system IDT. Thanks to
this nice implementation, one can quite easily patch his winice.exe to
always see the real IDT.
-------------------------------------------------------------


On another note, using Softice's tricks itself to protect Softice:

--------------------------------------------------------------
Since SoftICE is registered as driver, winice.exe will receive all
VxD system messages (SoftICE only handles SYS_CRITICAL_INIT, DEVICE_INIT,
INIT_COMPLETE, SYS_CRITICAL_EXIT, W32_DEVICEIOCONTROL, SET_DEVICE_FOCUS,
DESTROY_VM).
--------------------------------------------------------------

I find the idea of hooking the W32_DEVICEIOCONTROL message interesting as a way of detecting communication between an app and its vxd, and vice versa. From the Windows 98 DDK:

--------------------------------
W32_DEVICEIOCONTROL

mov ebx, VMHandle
mov eax, W32_DEVICEIOCONTROL
mov esi, OFFSET32 dioparams
VMMCall System_Control

Passes a control code and related information to a virtual device driver. This message is sent to a VxD when an application specifies the name of a VxD in the CreateFile function and when an application specifies the device handle of the VxD in a call to the DeviceIoControl or CloseHandle function.
---------------------------------

From the sounds of this if you could detect this message being sent you could tell when an app is loading and talking to its vxd.


BTW, the program with source code I mentioned that hides SoftIce from detection by other programs, is called IceGhost and was written primarily by yAtEs. If I'm not mistaken you can get it in the ID-Rip archive. Would make a good project to duplicate and enhance ;-)

Kayaker