注意返回时得使用iretd。
通过sidt取得idtr,找到里面的基址和limit。遍历所有的表项,找到一个p位没有置位的,添加一个调用门。和使用call gate没什么大差别。
看了下,我机器里的第一个空白项是0x20,就懒得写和ring3通信的东西了。
ring3:
#include <stdio.h>
int main()
{
__asm int 0x20
return 1;
}
ring0:
#include <ntddk.h>
#pragma pack(1)
typedef struct _IDTR
{
USHORT limit;
ULONG base;
}IDTR, *PIDTR;
typedef struct _IDT_ENTRY
{
USHORT OffsetLow;
USHORT selector;
UCHAR reserved;
UCHAR type :4;
UCHAR always0 :1;
UCHAR dpl :2;
UCHAR present :1;
USHORT OffsetHigh;
}IDT_ENTRY, *PIDT_ENTRY;
#pragma pack()
ULONG IdtIndex = 0;
IDT_ENTRY IdtEntry = {0};
PIDT_ENTRY OrigIdtEntry = NULL;
ULONG SetInterruptGate(PVOID MyFuncAddr);
MyFunc();
VOID ring0func();
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
IdtIndex = SetInterruptGate(MyFunc);
pDriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
ULONG SetInterruptGate(PVOID MyFuncAddr)
{
IDTR idtr = {0};
ULONG i = 0;
PIDT_ENTRY pIdtEntry = NULL;
__asm sidt idtr
for(i = 0;i < idtr.limit;i++)
{
pIdtEntry = (PIDT_ENTRY)(idtr.base + i * 8);
if(!pIdtEntry->present)
{
OrigIdtEntry = pIdtEntry;
IdtEntry.OffsetLow = pIdtEntry->OffsetLow;
IdtEntry.OffsetHigh = pIdtEntry->OffsetHigh;
IdtEntry.selector = pIdtEntry->selector;
IdtEntry.reserved = pIdtEntry->reserved;
IdtEntry.type = pIdtEntry->type;
IdtEntry.always0 = pIdtEntry->always0;
IdtEntry.dpl = pIdtEntry->dpl;
IdtEntry.present = pIdtEntry->present;
pIdtEntry->OffsetLow = (USHORT)MyFuncAddr;
pIdtEntry->OffsetHigh = (USHORT)((ULONG)MyFuncAddr >> 16);
pIdtEntry->selector = 0x8;
pIdtEntry->reserved = 0;
pIdtEntry->type = 0xE;
pIdtEntry->always0 = 0;
pIdtEntry->dpl = 3;
pIdtEntry->present = 1;
break;
}
}
return i;
}
__declspec(naked) MyFunc()
{
__asm
{
pushad
call ring0func
popad
iretd
}
}
VOID ring0func()
{
DbgPrint("interrupt gate");
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
OrigIdtEntry->OffsetLow = IdtEntry.OffsetLow;
OrigIdtEntry->OffsetHigh = IdtEntry.OffsetHigh;
OrigIdtEntry->selector = IdtEntry.selector;
OrigIdtEntry->reserved = IdtEntry.reserved;
OrigIdtEntry->type = IdtEntry.type;
OrigIdtEntry->always0 = IdtEntry.always0;
OrigIdtEntry->dpl = IdtEntry.dpl;
OrigIdtEntry->present = IdtEntry.present;
}