注意返回时得使用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;}