sysenter HOOK反OD调试

sysenter指令:

SYSENTER用来快速调用一个0层的系统过程。SYSENTER是SYSEXIT的同伴指令。该指令经过了优化,它可以使将由用户代码(运行在3层)向操作系统或执行程序(运行在0层)发起的系统调用发挥最大的性能。

 

在调用SYSENTER指令前,软件必须通过下面的MSR寄存器,指定0层的代码段和代码指针,0层的堆栈段和堆栈指针:

1.       IA32_SYSENTER_CS:一个32位值。低16位是0层的代码段的选择子。该值同时用来计算0层的堆栈的选择子。

2.       IA32_SYSENTER_EIP:包含一个32位的0层的代码指针,指向第一条指令。

3.       IA32_SYSENTER_ESP:包含一个32位的0层的堆栈指针。

 

MSR寄存器可以通过指令RDMSR/WRMSR来进行读写。寄存器地址如下表。这些地址值在以后的intel 64和IA32处理器中是固定不变的。

MSR

地址

IA32_SYSENTER_CS

174H

IA32_SYSENTER_ESP

175H

IA32_SYSENTER_EIP

176H

 

当执行SYSENTER,处理器会做下面的动作:

1.       从IA32_SYSENTER_CS从取出段选择子加载到CS中。

2.       从IA32_SYSENTER_EIP取出指令指针放到EIP中

3.       将IA32_SYSENTER_CS的值加上8,将其结果加载到SS中。

4.       从IA32_SYSENTER_ESP取出堆栈指针放到ESP寄存器中

5.       切换到0层。

6.       若EFLAGS中VM标志已被置,则清除VM标志。

7.       开始执行选择的系统过程。

 

处理器不保存返回地址和调用过程的其他状态信息。

 

SYSENTER指令总是转移到DPL为0的保护模式下的代码段。这条指令需要操作系统首先满足下面的条件:

1.       选择的系统代码段必须是一个平坦的、32位最大为4G的代码段。此段必须是可执行的、可读、已存取、非一致的。

2.       选择的系统堆栈段必须是一个平坦的、32位最大为4G的数据段。此段必须可读写、已存取、可向上扩展。

 

SYSENTER可在除实地址模式外所有其他模式下执行。

 

SYSENTER和SYSEXIT是同伴指令,但是它们并不像CALL/RET指令对。当执行SYSENTER时,处理器并不会为用户代码保存状态信息。而且无论是SYSENTER还是SYSEXIT都不能通过堆栈传递参数。

 

为了能通过SYSENTER/SYSEXIT指令,使控制在3层用户代码和0层操作系统代码之间相互转移,必须满足下面的条件:

1.       0层的代码段和0层堆栈段段以及3层的代码段和3层堆栈段在GDT中必须连续。这样就可以使处理器能从从SYSENTER_CS_MSR的值计算出其他的选择子的值了。

 

2.       .若要返回调用过程,由用户代码执行的快速系统调用“桩”(STUB)例程(通常在共享库或DLL中)必须保存返回地址以及处理器的状态信息;当要返回至用户代码时,操作系统或者由SYSENTER调用的执行程序必须使用这些保存的地址和状态信息。

 

SYSENTER和SYSEXIT指令是从Pentium II开始新加入到IA32位架构中来的。这两个指令在处理器上是否有效要看CPUID指令返回的EDX寄存器中SEP标记(SYSENTER/SYSEXIT存在标记)是否置上。操作系统若要检查SEP标记必须要同时检查处理器族(family)和型号(model),这样才能确保结果的准确性。例如:

 

IF (CPUID SEP bit is set)

IF (Family == 6) AND (Model < 3) AND (Stepping < 3)

THEN

Fast System Call NOT supported

FI;

ELSE Fast System Call is supported

FI

 

当CPUID指令在Penitum Pro(Model 1)上执行,虽然返回的SEP标志是置上的,但该处理器还是不支持SYSENTER/SYSEXIT指令的。

实现方法:

OD载入程序时会在目标地址写入0xCC(int 3)断点,只要我们HOOK掉WriteProcessMemory这个API即可防止OD下断点。

我这里是将任何程序使用WriteProcessMemory这个API来写CC断点都会拒绝。

先放一下图片

sysenter HOOK反OD调试_第1张图片

可以看到,OD载入这个程序时这个被载入的程序直接跑了起来,并没有被OD断下。

有的时候即使OD成功断下,但是设置断点的时候:

sysenter HOOK反OD调试_第2张图片

代码写的很烂,大神勿喷!

IDE:RadASM

编译器:MASM

操作系统:WINDOWS XP 32位

.686p
.model flat, stdcall
option casemap:none
include SysenterHook.inc
.data
	szHello		db	'Alg & Sec lab of China [254394017]',0
	szHello_	db	'By:yeeeee QQ:2308902347',0
	szErr		db	'OllyDbg'
.data?
	MSR_EIP		dd	?
	CallNumber	dd	?
.code

MyKiFastCallEntry proc
	mov CallNumber,eax
	xor CallNumber,115h
	.if CallNumber!=0
		jmp NEXT
	.else
		mov eax,dword ptr ds:[edx+16]
		mov eax,dword ptr ds:[eax]
		xor eax,0CCh
		.if eax==0
			pushad
			mov ebx,dword ptr ds:[edx+16]
			sub ebx,4
			mov dword ptr ds:[edx+12],ebx
			invoke DbgPrint,addr szErr
			popad
		.endif
		mov eax,115h
	.endif
NEXT:
	jmp MSR_EIP ;Jump to KiFastCallEntry
	ret
MyKiFastCallEntry endp
UnloadDriver proc pDriverObject:PDRIVER_OBJECT
	mov ecx,176h
	mov eax,MSR_EIP
	xor edx,edx
	wrmsr ;sysenter UnHook
	xor eax,eax
	ret
UnloadDriver endp
DriverEntry proc pDriverObject:PDRIVER_OBJECT,pusRegistryPath:PUNICODE_STRING
	invoke DbgPrint,addr szHello
	invoke DbgPrint,addr szHello_
	mov ecx,176h
	rdmsr ;Read the IA32_SYSENTER_EIP register
	mov MSR_EIP,eax ;Same the IA32_SYSENTER_EIP register
	jmp Entry
Entry:
	mov ecx,176h
	xor edx,edx
	mov eax,MyKiFastCallEntry
	wrmsr ;sysenter Hook
	xor eax,eax
	ret
DriverEntry endp
end DriverEntry

SysenterHook.inc代码:

include w2k\ntstatus.inc
include w2k\ntddk.inc
include w2k\ntoskrnl.inc 
includelib D:\aRadASM\masm32\lib\w2k\ntoskrnl.lib 




你可能感兴趣的:(系统底层,加密)