Log in

View Full Version : IVT format?


crUsAdEr
April 3rd, 2002, 23:20
Hi folks,

Can someone provide me some links discussing the Interrupt Vector Table structure (aka the format layout) and perhaps some reading about interrupt handling and setting etc... I am getting annoyed by all this anti tracing trick :<<... guess i have to pick it up anyway....

Thanx

Clandestiny
April 4th, 2002, 01:59
Quote:
Originally posted by binh81
Can someone provide me some links discussing the Interrupt Vector Table structure (aka the format layout) and perhaps some reading about interrupt handling and setting etc... I am getting annoyed by all this anti tracing trick :<<... guess i have to pick it up anyway....


Hiya,

I'll have a go at answering your question due to the fact, I've had the need to hook interrupts in the project I've been working on with Kayaker. With this said, I'm really a complete newbie on these topics so I'll appreciate it if anyone with a good grasp of systems level programming sees fit to patch up any holes in my current understanding of these matters.

There are actually 2 internal structures used by the processor for interrupt handling. The first is the Interrupt Vector Table (IVT) which is used in Real Mode. It consists of 4 byte entries containing far pointers to the interrupt handler procedures. The second table, called the Interrupt Descriptor Table, is used for handling interrupts in Protected Mode. In contrast the the IVT, the IDT consists of 8 byte descriptors which contain the segment and offset address of the interrupt service routine. Interestingly, the IDT is relocatable.

The ASM instructions for dealing with the IDT are the LIDT and SIDT commands. The SIDT (store interrupt descriptor table) command loads the size and location of the interrupt descriptor into an fword (6 byte) variable. If hooking an interrupt, you will use this command to get the base location of the interrupt descriptor table. The descriptors for each interrupt are indexed as offsets from this address.

For example, the INT 3 descriptor would be located at:
Base_IDT_Address (obtained from SIDT command) +[ 8 (size of each descriptor) * 3 (interrupt number)]

For the actual strucure of the descriptors, I'll refer you to an excellent doc which I'm attaching to this post... A picture really is worth a thousand words here

Similarly, one might use the LIDT (load interrupt descriptor table) to relocate the interrupt descriptor table or to change it's size. When I was reasearching this, I found it intriguing that one might actually enlarge the interrupt descriptor table to create their own "user defined" interrupts above and beyond the normal 256.

It is also important to note that ones interrupt service routine (ISR) needs to reside in non-pagable memory, in a locked code segment inside a VxD. Heh, hooking the IDT so it calls your handler is the easy part ...It's *inside* the ISR that the real fun begins... LOL, I've been finding this out the hard way recently. First, you have the issue of reentrancy. This can be partially solved by disabling interrupts around critical code sections using the cli instruction and by using dynamcially allocated variables. Beyond reentrancy, synchronization issues rear their ugly heads... For example, its impossible to do file I/O or memory allocation in the context of an interrupt handler. In such cases, it may be necessary to schedule an "event callback" to do this type of processing for you. In a real-time situation this synchronization is a *nightmare*. As far as I can tell, you're not guaranteed the VMM will even execute your event callbacks sequentially and the usage of synchronization structures like Sempahores and Mutexes appear to be questionable in context of an ISR. Indeed, the only safe functions to call are those labled as "asynchronous" in the documentation. Beyond these restrictions, it is desirable to keep your ISR as short and optomized as possilbe. Did I mention how much "fun" debugging an ISR with asynchronous callbacks can be Sorry, if I got of on a tangent here... Maybe this last stuff is not related to "cracking" per se, but I'm just discovering these "fun" synchronization problems so I thought I'd note them while they're fresh in my mind.

Anyway, here's part of my VxD's ISR routine which you can use as an example to see how an interrupt is hooked.

;================================Begin Hook_INT Proc==================================
BeginProc Hook_INT

;-------------------------------------------------------------------------
; Assume ebx contains the # of the interrupt you want to hook and edx
; contains a pointer to the new interrupt handler procedure you want to
; install.
;-------------------------------------------------------------------------
;INT 1

pushad ; save registers

;--------------------------------------------------
; SIDT stores the Interrupt Descriptor Table (IDT)
; Register into the specified operand
;--------------------------------------------------
sidt IDTR ; IDTR is variable to hold base address of IDT

;------------------------------------------------
; Get index into IDT for the int we want to hook
;------------------------------------------------
push edx ;save handler address
mov eax, 08h ; mov 08 multiplier in eax
mul dword ptr ebx ; mul with interrupt number in ebx
add eax, dword ptr [IDTR+2] ; add to base address of IDT + 2 bytes
; offset of INT x handler in eax

;------------------------------------------------
; Save the original INT handler
;------------------------------------------------
push ebx
mov ebx, Index
pop IntNumber[ebx] ; save interrupt # for lookup of handler later
mov cx,[eax+06h] ; get the low word part of the offset from the IDT
shl ecx,010h ; shift into high word position in register
mov cx,[eax] ; get the high word part of the offset from the IDT
push ecx
pop SaveOldInt[ebx] ; save old INT handler
add Index,4 ;increment index to point to next location in arrays

;-------------------------------------------------
; Replace original INT handler with our new one
;-------------------------------------------------
pop edx
cli ; ignore maskable external interrupts
mov [eax],dx ; modify the high word part of the offset
shr edx,010h ; shift into low word position in register
mov [eax+6],dx ; modify the low word part of the offset
sti ; resume responding to interrupts

clc
popad
mov eax, 1 ; if got here return TRUE
ret
EndProc Hook_INT
;==================================End Hook_INT Proc==================================

Hope this answers part of your question...

Cheers,
Clandestiny

PS. If you email me, I'll be happy to send you my "research" on the IDT, ISR's, reentrancy, and synchronization issues.

crUsAdEr
April 4th, 2002, 02:14
Thanx a lot Clandestiny,

This is far more than i expect... thanx a lot for the stuff.. it's great :>... slightly over my knowledge at teh moment, digesting the intel manual here andthere first... thanx for the pointer... shall do a bit of research myself before troublign u to spoonfeed me but i shall email u if i need further info...

Thanx a LOT!!!!!

evaluator
April 4th, 2002, 09:04
You shoud look at Y0DA's CreateINT!
Grab it from Y0DA's site.

(W98 only)

crUsAdEr
April 4th, 2002, 18:25
hi,

thanx for the input, shall look into y0da's code, thanx eval...

Just another question, how do i debug my implementation? cos when i trace the prog with sice, interrupt seems to be suspended.. guess basically this is how program tricks newbie who trace and trace and gets nowhere...

Like i have tried an int1 for div by 0, but the handler is not called,.. sice trace on :<....

Tried int6 by putting garbage opcode... sice goes on :<... or crashed???

Thanx... what must i do to trigger this when i am debugging it?

evaluator
April 4th, 2002, 18:38
If you will change INT1 you must not trace with
SICE! It is Debugger's default handler.
So I recomend you make tests on INT5

Clandestiny
April 5th, 2002, 01:03
Hiya binh81,

As evaluator says, you cannot hook the int 1 AND be able to trace it in SoftICE. The int 1 is the processor's "single step" exception fault. SoftICE hooks the int 1 itself to provide the functionality for tracing your code. If you hook this interrupt, you short-circuit your ability to trace your own code

Also,in my previous post, I think I neglected to mention the issue of chaining your ISR back to the previous handler. When you hook, you're replacing the default handler with your own... BUT what happens to the old handler??? At this point you have the choice to chain or not to chain. Basically, chaining involves calling the old handler either before or after execution of your own handler. Calling it before is termed "pre-execution" chaining and calling it afterward is termed "post-execution" chaining.

The post execution chaining technique is as simple as executing a
pushfd and far call. Remember, when the interrupt handler is called, 3 things are pushed on the stack...

1) the flags register
2) the code segment selector
3) the offset address

Similarly, the iretd instruction pops all three of these values off the stack. When chaining, you are in essence "emulating" an iretd instruction by manually pushing the flags and far calling the old interrupt handler.

It is not always necessary to chain... But its probably good programming practice. Consider... What if the VMM default handler (or even another driver) needs to execute some default code in response to that interrupt you just hooked... Well, if you don't chain, you've just short-circuited that functionality which may / may not result in a crash depending on how critical that code was that you bypassed.

BTW, the int 6 invalid opcode should work. It's what I've been using. I have inserted an int 1 into the ISR code and set "i1here on" in SoftICE for debugging. If your handler is doing anything much, you should also consider the problem of reentrancy. If your ISR isn't too long, disabling interrupts while your handler runs might solve the problem.

Cheers,
Clandestiny

crUsAdEr
April 5th, 2002, 12:49
Thanx Clandestiny,

Hee... it was my fault... my coding is crap :>... i hooked the wrong interrupt.... now that i re-read 386intel.txt i realise that i have been doing it all wrong :>... virtually messed up my IDT.. no wonder my system crashed :>... was swearing and cursing Clandestiny for sabotaging me by giving me the wrong info :>.. (just KIDDING)... thanx a lot... you are really helpful...

Yeah, it kinda works now... i am not coding anything at the moment, no where near that level of competency yet:<.. i just wanted to play with it and understand how all these anti tracing works by interrupt hooking...

Guess i have a rough idea now, but is there anyway i can trigger int1 in sice still? So that i can bypass anti tracing code?

Thanx,

Clandestiny
April 8th, 2002, 03:09
Quote:
Originally posted by binh81
Thanx Clandestiny,

Hee... it was my fault... my coding is crap :>... i hooked the wrong interrupt.... now that i re-read 386intel.txt i realise that i have been doing it all wrong :>... virtually messed up my IDT.. no wonder my

system crashed :>... was swearing and cursing Clandestiny for sabotaging me by giving me the wrong info :>.. (just KIDDING)... thanx a lot... you are really helpful...

Glad the info was helpful I'm really just now learning most of this myself for the project Kayaker and I have been working on... As they say, necessity is the mother of invention

Quote:

Guess i have a rough idea now, but is there anyway i can trigger int1 in sice still? So that i can bypass anti tracing code?

Hmm, this isn't really my area of expertise... At this point, I've played more with coding interrupt based stuff than cracking it, but I have read a couple of interesting articles and speculated a little bit. Here's one that poses some interesting possiblites...

http://www.humancapitall.com/arunkoshy/art_tunnel.htm

It talks about a technique called "recursive tunneling" This is a technique some virus scanners apparently use to trace chained ISRS and redirect the interrupt around the virus handler code back to the original system handler.

Here's the official definition:
“Tunneling collectively refers to the techniques, algorithms, and ways of tracing code attached to a particular interrupt, and then finding the original DOS/BIOS code. This in turn can be used to bypass all memory-resident programs including viruses, which have trapped the interrupt. Mostly it’s INT 21h and INT 13h which are modified.”

When I read this article, I wondered if these types of techniques could be also applied to protection / deprotection schemes... Say, for example a prog hooks one of SI's interrupts to do some nasties. Would it be possible to trace the interrupt handlers back to original segment of winice code similarily to the way the article speaks of locating the original DOS / BIOS code and then redirect the interrupt back to winice where it belongs?

Conversely, could a protection use this technique to short-circuit the interrupts SI hooks (ie. trace the ISR's back to the original default handlers and redirect the interrupts around SoftICE back to the original handlers)?

Anyway, this is all hypothetical here since I'm still pretty new to the interrupt stuff myself They're just a few interesting concepts and ideas I'd like to look into eventually.

Here's another thread from the mini project forum that might prove interesting to you. I guess it would blow the above mentioned tunneling technique out of the water though since the tunneling technique relies on the trap flag This anti-trace example involves the use of the undocumented int 1 opcode and a structured execption handler to catch tracing and redirect code to the bad-boy routine.

http://www.woodmann.net/forum/showthread.php?threadid=2634&perpage=15&pagenumber=2

Cheers
Clandestiny

crUsAdEr
April 8th, 2002, 11:41
Hi,

Thanx Clandestiny... Yeah i am aware of the thread you were talking about... great reading by ZaiRon and Kayaker...

I DID email the_analyst to ask him about how to trigger the int1 and bypass the anti-tracing, he did replied but i wasnt very clear what he meant :<...

Yeah, the recursive tunnelling articale is a great read, really easy to understand... i guess it is possible to do that if you can incorporate Tseph's tracer... and provided that the virus/programmer did chain the original interrupt handler...

but, just a thought... isnt the interrupt handler routine always fixed depending on the version of windows? I always assume that each OS version will have all this info at a fixed address.. so maybe the search for the original int handler routine is used so that it works on all version on Windoze??

And also, we might run into troubles if there are a few hooking... not quite sure how possible it is... but if a few service is hooking the same interrupt, chaining itself one after another then we might run into trouble doing this "recursive tunnelling"...

Just a few thoughts...

Off to read more... :>..

cheers,