Introduction
This article explains how to get interrupt vector information in a Windows system. Before reading this article, you will need to familiarise yourself with: INTERRUPT, IDT, IVT and IRQ. This article will not explain these subjects. I recommend that you search the web for more information if you are not familiar with them, as I have written this article under the assumption that you are.
IDT in Windows
IDT stands for Interrupt Descriptor Table. Such tables contain Interrupt information of the i386 Processor in Protected Mode, not Real Mode. These tables consist of 8 bytes and there is a lot of information about the Table that you can easily find out. IDT is an essential component of the Operating System's kernel. When the Operating System transitions from Real Mode to Protected Mode, OSs make an IDT. IDTs are able to change because Windows supports the Plug and Play feature.
IDTs have an opportunity to remap by system. IOAPICs have something to do with this remapping operation. See the DataSheet of 82093AA I/O Advanced Programmable Interrupt Controller for more information. IOAPIC makes IRQ and remaps IRQ to IDT. You can see current the remapping status of IRQ and IDT by typing !ioapic
in Windbg. This is the result of !ioapic
:
kd> !ioapic
IoApic @ FEC00000 ID:1 (11) Arb:1000000
Inti00.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti01.: 00000993 Vec:93 LowestDl Lg:01000000 edg high
Inti02.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti03.: 000009b2 Vec:B2 LowestDl Lg:01000000 edg high
Inti04.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti05.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti06.: 000109b3 Vec:B3 LowestDl Lg:01000000 edg high masked
Inti07.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti08.: 000008d1 Vec:D1 FixedDel Lg:01000000 edg high
Inti09.: 0000e9b1 Vec:B1 LowestDl Lg:01000000 lvl low rirr
Inti0A.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti0B.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti0C.: 000009a3 Vec:A3 LowestDl Lg:01000000 edg high
Inti0D.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti0E.: 00000962 Vec:62 LowestDl Lg:01000000 edg high
Inti0F.: 00000982 Vec:82 LowestDl Lg:01000000 edg high
Inti10.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti11.: 0000a983 Vec:83 LowestDl Lg:01000000 lvl low
Inti12.: 0000a963 Vec:63 LowestDl Lg:01000000 lvl low
Inti13.: 0000a973 Vec:73 LowestDl Lg:01000000 lvl low
Inti14.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti15.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti16.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
Inti17.: 000100ff Vec:FF FixedDel PhysDest:00 edg high masked
How to resolve an IDT vector
There are many methods to resolve IDT vectors.
- Use APIC
- Scan kernel memory
- Use the kernel API function
Using APIC
If you want to know more about the "Use APIC" method, see the APIC document. Intel recommends mapping IOAPIC to 0xFEC00000. Surely it can replace to another address, but Windows doesn't. In the following results, we can appreciate that Windows follows the IOAPIC document's recommendation.
kd> !ioapic
IoApic @ FEC00000 ID:1 (11) Arb:1000000
Now the memory (0xFEC00000) contains IDT vector information. These methods are fully explained in the CodeProject article found here.
Scanning kernel memory
Next, we can scan kernel memory space. This is a traditional and hazardous method. It is described in the eEye Security White Paper, which was published in 2005. This method's main premise is that hal.dll's memory space contains IDT and IRQ information and that we can obtain this address by scanning the memory space. This method's implementation is very small, so we can use it in stark a environment.
mov esi, dword ptr ds:[0ffdff038h] ; Get base address of IDT
lodsd
cdq
lodsd ; Get pointer into NTOSKRNL
@base_loop:
dec eax
cmp dword ptr [eax], 00905a4dh ; Check for MZ signature
jnz @base_loop
jecxz @hal_base ; NTOSKRNL base is in EAX
xchg edx, eax
mov eax, [edx+590h] ;Get a pointer to a HAL function
xor ecx, ecx
jmp @base_loop ;Find HAL base address
@hal_base:
mov edi, eax ;HAL base in EDI
mov ebp, edx ;NTOSKRNL base in EBP
cld
mov eax, 41413d00h ;Signature bytes "=AA\0"
xor ecx, ecx
dec cx
shr ecx, 4
repnz scasd ;Get offset to table
or ecx, ecx
jz @no_table
lea edi, [edi+01ch] ;Get pointer to Vector table
This code:
- Gets
ntoskrnl
's base address - Moves to the
hal
functions's area - Finds until
=AA\0
, which means IRQ0
's information =AA\0
is 0x41413d00h
Using kernel API
These two methods are not reliable. They appear to be an effective way to control APIC, but Windows can change these addresses to indirect addresses. So, it's not a very effective way to do things. The second method of finding memory isn't a good method by itself. Also, =AA\0
is too specific to use in all environments. We can solve these problems with HalGetInterruptVector
, which is the kernel API. This function is declared in ntddk.h.
NTHALAPI
ULONG
HalSetBusData(
IN BUS_DATA_TYPE BusDataType,
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Length
);
BUS_DATA_TYPE
is declared in ntddk.h.
typedef enum _BUS_DATA_TYPE {
ConfigurationSpaceUndefined = -1,
Cmos,
EisaConfiguration,
Pos,
CbusConfiguration,
PCIConfiguration,
VMEConfiguration,
NuBusConfiguration,
PCMCIAConfiguration,
MPIConfiguration,
MPSAConfiguration,
PNPISAConfiguration,
SgiInternalConfiguration,
MaximumBusDataType
} BUS_DATA_TYPE, *PBUS_DATA_TYPE;
You can call a function such as:
KIRQL sIrql;
KAFFINITY sAffinity;
ULONG uVector;
ULONG uInterruptNumber = 1;
uVector =
HalGetInterruptVector(EisaConfiguration,
0, uInterruptNumber, uInterruptNumber, &sIrql, &sAffinity);
uVector = uVector & 0xFF;
This function is described in MSDN. When you pass the IRQ number to BusInterruptLevel
and BusInterruptVector
, the function returns the index of the IDT vector. This returned value is bigger by 0x100 than original value. We must odds 0x100 or mask with 0xFF.
History
- 18 July, 2007 -- Original version posted
I started to write software since 1999 and have developed various products including security solutions and system utilities.
Microsoft Visual C++ MVP
Assistant Professor at the University of Virginia
Website: http://yongkwon.info