Searching for the IDT in memory dumps


Finding the IDT in a running system is trivial, but finding it in a memory dump is a bit harder. This time we will take a look at how it can be done in theory, and I will also provide you with a working tool.

Finding blocks likely to contain an IDT

When searching the memory dump we analyze one block of it at a time. A good block size could be for example 4096 bytes. In particular it should be a multiple of 8 bytes (the size of an IDT Gate Descriptor).

Looping through the block we look at each 8-byte entry one at a time, and determine if it matches a predefined set of requirements. First, it has to have the Present flag set. Second, bits 8-12 must be one of the patterns 00101, 00110, 01110, 00111, or 01111. These patterns are the only valid gate types. Third, if the entry looks like an Interrupt Gate or a Trap Gate, it has to have a non-zero Offset as well as zeroes in bits 5-7. Fourth, the Segment Selector has to be non-zero, but with a zero high byte (which is usually the case). We count all the matches in each block (MATCHES).

If we have a match we determine if the entry is a possible Task Gate. These are more problematic than the others since they have fewer defined fields, and thus raise more false positives. To counter that problem we use a simple check for repeating entries (TASKREPEAT). Any simple algorithm for counting repeating TSS Segment Selectors will probably do. Counting all of them is not necessary, all we have to do is keep track of the repeat count of one single TSS Segment Selector value as long as it is one that repeats. In practice there will usually not be more than one value repeating anyway.

Finally we have to keep track of the largest number of entries in a row which match the criteria (INAROW).

To single out the interesting blocks we check the values of MATCHES and INAROW. I have had good results with a MATCHES limit set to 25 and an INAROW limit set to 4 - that is, accept blocks with values at least that high.

Printing the IDT

Now we have a number of blocks which all could contain the IDT. We print those entries in each block which match the above set of requirements and have a TASKREPEAT no higher than 1. We also have to keep track of entries with the Present flag cleared when we number the entries in the printout. Otherwise the entry numbers will end up wrong if there are unused entries (which is the case at least in Windows XP).

The FindIDT tool

I have coded a small tool called FindIDT, which implements the above algorithm. In my tests it has worked really well on memory dumps from both Windows XP and Linux. Here is part of a sample output from a run against a memory dump from Windows XP:

IDT #1 follows:

00h / Interrupt Gate:
- DPL: 0
- Segment Selector: 8
- Offset: 804df350
01h / Interrupt Gate:
- DPL: 0
- Segment Selector: 8
- Offset: 804df4cb
02h / Task Gate:
- DPL: 0
- TSS Segment Selector: 58
03h / Interrupt Gate:
- DPL: 3
- Segment Selector: 8
- Offset: 804df89d


© Arne Vidstrom. All rights reserved.