如何在amd64中正确转储IDT条目?

时间:2016-11-25 22:10:41

标签: c windows x86 kernel

以下代码:

部首:

// InterruptDescriptorTable.h

#define MAX_IDT_ENTRIES 256

#define MAKELONG(a, b)  ((unsigned long) (((unsigned short)(a)) | ((unsigned long) ((unsigned) (b))) << 16 ))

/* SIDT returns IDT in following format */
#pragma pack(1)
typedef struct
{
    unsigned short IDTLimit;
    unsigned short LowIDTBase;
    unsigned short HighIDTBase;

} s_idt_info;
#pragma pack()

/* entry in IDT ( interrupt gate ) */
#pragma pack(1)
typedef struct
{
    unsigned short LowOffset;
    unsigned short selector;
    unsigned char unused_lo;
    unsigned char segment_type:4;
    unsigned char system_segment_flag:1;
    unsigned char DPL:2;                    // Descriptor Privilege Level
    unsigned char P:1;                      // Present
    unsigned short HighOffset;

} s_idt_entry;
#pragma pack()

主:

// driver.c
#include <ntddk.h>

#include "InterruptDescriptorTable.h"

const WCHAR deviceNameBuffer[] = L"\\Device\\MyDevice";

PDEVICE_OBJECT g_RootkitDevice; // pointer to device object

NTSTATUS
//STDCALL
_DriverDispatch(IN PDEVICE_OBJECT DeviceObject,
               IN PIRP Irp)
{
    return STATUS_SUCCESS;
}

VOID
//STDCALL
_DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    DbgPrint("DriverUnload() !\n");
    return;
}

NTSTATUS
_DriverEntry(IN PDRIVER_OBJECT DriverObject,
             IN PUNICODE_STRING RegistryPath)
{
    DbgPrint("DriverEntry() !\n");

    s_idt_info idt_info;        // returned by sidt
    s_idt_entry *idt_entries;   // obtained from idt_info
    unsigned int count;
    unsigned long addr;

    // load idt_info
    __asm ("sidt %0" : "=w" (idt_info));

    idt_entries = (s_idt_entry*) (long long)MAKELONG(idt_info.LowIDTBase, idt_info.HighIDTBase);

    for(count = 0; count < MAX_IDT_ENTRIES; ++count)
    {
        s_idt_entry *i = &idt_entries[count];

        addr = MAKELONG(i->LowOffset, i->HighOffset);

        DbgPrint("Interrupt %d, %lu", count, addr);
    }

    DriverObject->DriverUnload = _DriverUnload;

    return STATUS_SUCCESS;
}

使用Code :: Blocks中的MinGW-x64(GCC)编译为.sys文件。

当插入在VirtualBox上运行的Windows 7-64bit VM时,它会生成以下BSOD: enter image description here

我注意到只有在我尝试打印变量“addr”时才会发生这种情况。不知道为什么要确切或如何解决它。打印&#39;计数&#39;两次就好了。

以下代码用于加载/卸载驱动程序: http://pastebin.com/0Axy4WkZ

1 个答案:

答案 0 :(得分:4)

在64位模式下对IDT结构使用错误的定义。接下来是amd64的正确代码:

union KIDTENTRY64
{
    struct
    {
        USHORT OffsetLow;
        USHORT Selector;
        USHORT IstIndex:3;
        USHORT Reserved0:5;
        USHORT Type:5;
        USHORT Dpl:2;
        USHORT Present:1;
        USHORT OffsetMiddle;
        ULONG OffsetHigh;
        ULONG Reserved1;
    };
    UINT64 Alignment;
};

struct KDESCRIPTOR64
{
    USHORT Pad[3];
    USHORT Limit;
    PVOID Base;
};

void DumpIDT()
{
#ifdef _AMD64_

    KDESCRIPTOR64 descr; 
    __sidt(&descr.Limit);

    if (ULONG n = (descr.Limit + 1)/ sizeof(KIDTENTRY64))
    {
        int i = 0;
        KIDTENTRY64* pidte = (KIDTENTRY64*)descr.Base;

        do 
        {
            ULONG_PTR addr = ((ULONG_PTR)pidte->OffsetHigh << 32) + 
                ((ULONG_PTR)pidte->OffsetMiddle << 16) + pidte->OffsetLow;

            DbgPrint("Interrupt %u -> %p\n", i++, addr);

        } while (pidte++, --n);
    }
#endif  
}