当前位置: 代码迷 >> 汇编语言 >> [原创]浅谈NT下Ring3无驱进入Ring0的方法,该如何处理
  详细解决方案

[原创]浅谈NT下Ring3无驱进入Ring0的方法,该如何处理

热度:6935   发布时间:2013-02-26 00:00:00.0
[原创]浅谈NT下Ring3无驱进入Ring0的方法
[原创]浅谈NT下Ring3无驱进入Ring0的方法
关键字:NT,Ring0,无驱

(测试环境:Windows   2000   SP4,Windows   XP   SP2.
Windows   2003   未测试)

在NT下无驱进入Ring0是一个老生常谈的方法了,网上也有一些C代码
的例子,我之所以用汇编重写是因为上次在

[原创/探讨]Windows   核心编程研究系列之一(改变进程   PTE)

的帖子中自己没有实验成功(其实已经成功了,只是自己太马虎,
竟然还不知道   -_-b),顺面聊聊PM(保护模式)中的调用门的使用情况。
鉴于这些都是可以作为基本功来了解的知识点,所以对此已经熟悉的朋友
就可以略过不看了,当然由于本人水平有限,各位前来“挑挑刺”也是非
常欢迎的,呵呵。

        下面言归正传,我们知道在NT中进入Ring0的一般方法是通过
驱动,我的Windows   核心编程研究系列   文章前两篇都使用了
这个方法进入Ring0   完成特定功能。现在我们还可以通过在Ring3
下直接写物理内存的方法来进入Ring0,其主要步骤是:


0 以写权限打开物理内存对象;
1 取得   系统   GDT   地址,并转换成物理地址;
2 构造一个调用门;
3 寻找   GDT   中空闲的位置,将   CallGate   植入;
4 Call植入的调用门。


前面已打通主要关节,现在进一步看看细节问题:

      [零] 默认只有   System   用户有写物理内存的权限  
              administrators   组的用户 只有读的权限,但
              是通过修改用户安全对象中的DACL   可以增加写的权限:

_SetPhyMemDACLs proc uses   ebx   edi   esi   \
_hPhymem:HANDLE,\
_ptusrname:dword
local @dwret:dword
local @htoken:HANDLE
local @hprocess:HANDLE
local @个
local @OldDACLs:PACL
local @SecurityDescriptor:PSECURITY_DESCRIPTOR
local @Access:EXPLICIT_ACCESS

mov @dwret,FALSE

invoke RtlZeroMemory,addr   @NewDACLs,sizeof   @NewDACLs
invoke RtlZeroMemory,addr   @SecurityDescriptor,\
sizeof @SecurityDescriptor

invoke GetSecurityInfo,_hPhymem,SE_KERNEL_OBJECT,\
DACL_SECURITY_INFORMATION,NULL,NULL,\
addr   @OldDACLs,NULL,\
addr   @SecurityDescriptor

.if eax   !=   ERROR_SUCCESS
jmp SAFE_RET
.endif

invoke RtlZeroMemory,addr   @Access,sizeof   @Access

mov @Access.grfAccessPermissions,SECTION_ALL_ACCESS
mov @Access.grfAccessMode,GRANT_ACCESS
mov @Access.grfInheritance,NO_INHERITANCE
mov @Access.stTRUSTEE.MultipleTrusteeOperation,\
NO_MULTIPLE_TRUSTEE
mov @Access.stTRUSTEE.TrusteeForm,TRUSTEE_IS_NAME
mov @Access.stTRUSTEE.TrusteeType,TRUSTEE_IS_USER
push _ptusrname
pop @Access.stTRUSTEE.ptstrName

invoke GetCurrentProcess
mov @hprocess,eax
invoke OpenProcessToken,@hprocess,TOKEN_ALL_ACCESS,\
addr   @htoken

invoke SetEntriesInAcl,1,addr   @Access,\
@OldDACLs,addr   @NewDACLs

.if eax   !=   ERROR_SUCCESS
jmp SAFE_RET
.endif

invoke SetSecurityInfo,_hPhymem,SE_KERNEL_OBJECT,\
DACL_SECURITY_INFORMATION,NULL,NULL,\
@NewDACLs,NULL

.if eax   !=   ERROR_SUCCESS
jmp SAFE_RET
.endif

mov @dwret,TRUE

SAFE_RET:

.if @NewDACLs   !=   NULL
invoke LocalFree,@NewDACLs
mov @NewDACLs,NULL
.endif

.if @SecurityDescriptor   !=   NULL
invoke LocalFree,@SecurityDescriptor
mov @SecurityDescriptor,NULL
.endif

mov eax,@dwret
ret

_SetPhyMemDACLs endp

[一]   可以在Ring3下使用SGDT指令取得系统GDT表的虚拟地址,
这条指令没有被Intel设计成特权0级的指令。据我的
观察,在   Windows   2000   SP4   中   GDT   表的基址都是相同的,
而且在   虚拟机VMware   5.5   虚拟的   Windows   2000   SP4中
执行   SGDT   指令后返回的是错误的结果,在虚拟的   Windows   XP  
中也有同样情况,可能是虚拟机的问题,大家如果有条件可以试一下: