在从用户模式切换到内核模式的完整过程分析有讲到在用户态的代码执行了SYSENTER指令之后,处理器中的控制单元将寄存器MSR_IA32_SYSENTER_EIP的值装载到指令指针寄存器eip中。
从wrk中可以看到对它的初始化
VOID
KiLoadFastSyscallMachineSpecificRegisters(
IN PLONG Context
)
/*++
Routine Description:
Load MSRs used to support Fast Syscall/return. This routine is
run on all processors.
Arguments:
None.
Return Value:
None.
–*/
{
PKPRCB Prcb;
UNREFERENCED_PARAMETER (Context);
if (KiFastSystemCallIsIA32) {
Prcb = KeGetCurrentPrcb();
//
// Use Intel defined way of doing this.
//
WRMSR(MSR_SYSENTER_CS, KGDT_R0_CODE);
WRMSR(MSR_SYSENTER_EIP, (ULONGLONG)(ULONG)KiFastCallEntry);
WRMSR(MSR_SYSENTER_ESP, (ULONGLONG)(ULONG)Prcb->DpcStack);
}
}
所以寄存器MSR_IA32_SYSENTER_EIP的值决定了sysenter后执行的下一条指令,所以我们只要修改该寄存器的值即可!
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #include <ntddk.h> ULONG d_origKiFastCallEntry; void onUnload (IN PDRIVER_OBJECT DriverObject) { __asm{ mov ecx, 0x176 xor edx,edx mov eax, d_origKiFastCallEntry wrmsr } } ULONG i; __declspec(naked) MyKiFastCallEntry() { __asm{ mov i , eax jmp [d_origKiFastCallEntry] } } NTSTATUS DriverEntry (IN PDRIVER_OBJECT theDriverObject , IN PUNICODE_STRING theRegisteryPath) { theDriverObject->DriverUnload = onUnload; __asm{ mov ecx, 0x176 rdmsr mov d_origKiFastCallEntry,eax mov eax, MyKiFastCallEntry xor edx,edx wrmsr } return STATUS_SUCCESS; } |
编译加载后,我们再来看看MSR_IA32_SYSENTER_EIP的值:
kd> rdmsr 176
msr[176] = 00000000`905ae040
kd> u 905ae040
hooksysenter!MyKiFastCallEntry [d:\vs2012\hooksysenter\hooksysenter\hooksysenter.c @ 19]:
905ae040 a308005b90 mov dword ptr [hooksysenter!i (905b0008)],eax
905ae045 ff250c005b90 jmp dword ptr [hooksysenter!d_origKiFastCallEntry (905b000c)]
直接进入我自定义的方法中,然后jmp回原来的值。
kd> dd 905b000c l 1
905b000c 8285e300
kd> u 8285e300
nt!KiFastCallEntry:
8285e300 b923000000 mov ecx,23h
8285e305 6a30 push 30h
8285e307 0fa1 pop fs
8285e309 8ed9 mov ds,cx
8285e30b 8ec1 mov es,cx
8285e30d 648b0d40000000 mov ecx,dword ptr fs:[40h]
8285e314 8b6104 mov esp,dword ptr [ecx+4]
8285e317 6a23 push 23h