利用SEH进入ring0
seh的一个应用是进入ring0,ring0有着更多的权利,你可以进行一些其他ring3级应用程序不能进行的操作,譬如改自己的代码段(在不修改段属性的前提下),改系统数据(病毒?)等等,在9X下进入ring0的方法很多,在NT下困难的多,SEH只是其中较简单的一种.打开调试器看看系统kernel的工作状态,在9X下cs一般是28h,ds,ss等通常是30h,因此只要我们的cs和ss等在异常处理程序中被赋予上述ring0选择子值,进入ring0就可以实现.可能我们需要执行较复杂的操作,在ring0下一般不能直接调用常用api,当然VxD,WDM等提供的系统服务是另外一种选择. 否则,这在用下述简单方法进入ring0后执行会产生错误,因此,我们在ring0下尽快完成需要完成的任务,然后迅速返回ring3.
在ring0下要完成如下任务:
1.取CR3的值,返回ring3显示.在ring3下不可以读取cr3的值.你可以打开kernel调试器看看例子程序取到的值是否正确.
2.修改代码段后面的jmp ****代码,这在通常情况下只会导致保护错误.而在ring0下是可以的,就像在前面例子中用she实现SMC的效果是一样的,最后显示几个MsgBox,证明我们曾经到达过ring0
这个例子是参考owl的那个nasm写的例子用masm改写,并增加ring0下SMC的代码部分以作演示.另外代码中iretd指令并不是简单实现跳转,而是实现从ring0切回ring3的功能,在变换代码特权级的同时,堆栈的也要变换到ring3.可能原例子ljtt前辈的中文注释容易引起初学者的误解.
别的不说,我发现进入ring0后修改代码段可以使trw的跟踪崩溃...hmmm,好消息?代码如下:
其中用的一些宏在Ex5中已经贴了,就不再重复.
;-----------------------------------------
;Ex6,演示利用seh进入ring0! by Hume,2002
;humewen@21cn.com
;hume.longcity.net
;-----------------------------------------
.586
.model flat, stdcall
option casemap :none ; case sensitive
include hd.h
include mac.h
;;--------------
ring0_xHandler proto C :DWORD,:DWORD,:DWORD,:DWORD
.data
szbuf db 100 dup (0)
count dd 0
;;-----------------------------------------
.CODE
_Start:
assume fs:nothing
push offset ring0_xHandler
push fs:[0]
mov fs:[0],esp
;--------------------
mov ecx,ds
test ecx,100b
jz NT_2K_XP ;NT/2K/XP has no LDT
pushfd
mov eax,esp
int 3
mov ebx,cr3 ;现在,正式宣布,进入ring0!
;呵呵这样简单就进入ring0了,至于进入
push ebx ;ring0有啥用,不要问我!
lea ebx,offset _modi ;SMC
mov byte ptr[ebx],75h ;修改jmp addinfo为jnz addinfo指令
pop ebx
push edx ;ss
push eax ;esp
push dword ptr[eax] ;eflags
push ecx ;cs
push offset ring3back ;eip
iretd ;这里是通过iretd 指令返回特权级3
ring3back:
popfd
invoke wsprintf,addr szbuf,ddd("It's in ring0,please see CR3==%08X",0dh,oah,"following display Modified info..."),ebx
invoke MessageBox,0,addr szbuf,ddd("Ring0! by Hume[AfO]"),40h
xor eax,eax
;add eax,2
.data
Nosmc db "Not modified area!",0
besmc db "haha,I am modified by self in ring0!",0
.code
mov ebx,offset Nosmc
mov eax,0
_modi:
jmp addinfo ;SMC后将这里改为jnz addinfo
mov ebx,offset besmc
mov eax,30h
addinfo:
invoke MessageBox,0,ebx,ddd("Rin0 SMC test"),eax
_exit:
;--------------------
pop fs:[0]
add esp,4
invoke ExitProcess,0
NT_2K_XP:
invoke MessageBox,0,ddd("The example not support NT/2K/Xp,only 9x!"),ddd("By hume"),20h
jmp _exit
;-----------------------------------------
ring0_xHandler PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
pushad
assume edi:ptr CONTEXT
assume esi:ptr EXCEPTION_RECORD
mov esi,pExcept
mov edi,pContext
test dword ptr[esi+4],1 ;Exception flags
jnz @f
test dword ptr[esi+4],6
jnz @f
cmp dword ptr[esi],80000003h ;break ponit flag
jnz @f
m2m [edi].regEcx,[edi].regCs ;保存3级代码段选择子
mov [edi].regCs,28h ;0级代码段选择子
m2m [edi].regEdx,[edi].regSs ;保存3级堆栈段选择子
mov [edi].regSs,30h ;0级堆栈选择子
mov dword ptr[esp+7*4],0
popad
ret
@@:
mov dword ptr[esp+7*4],1
popad
ret
ring0_xHandler ENDP
;-----------------------------------------
END _Start
由于在NT/2K/XP下这种进入ring0的方法不能使用,所以首先区别系统版本,如果是NT/2K/XP则拒绝执行, 原理是在NT/2K/XP下没有LDT,因此测试选择子是否指向LDT,这是一种简单的方法,但不推荐使用, 最好使用GetVersionEx...至于
mov dword ptr[esp+7*4],0
popad
是返回eax=1的实现}
文章来自http://www.cosye.com/