NT/2000下不用驱动的Ring0代码实现

2008-02-23 05:36:38来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

大家知道,Windows NT/2000为实现其可靠性,严格将系统划分为内核模式和用户模式,在i386系统中分别对应CPU的Ring0和Ring3级别。Ring0下,能够执行特权级指令,对任何I/O设备都有访问权等等。要实现从用户态进入核心态,即从Ring 3进入Ring 0必须借助CPU的某种门机制,如中断门、调用门等。而Windows NT/2000提供用户态执行系统服务(Ring 0例程)的此类机制即System Service的int 2eh中断服务等,严格的参数检查,只能严格的执行Windows NT/2000提供的服务,而假如想执行用户提供的Ring 0代码(指运行在Ring 0权限的代码),常规方法似乎只有编写设备驱动程式。本文将介绍一种在用户态不借助任何驱动程式执行Ring0代码的方法。

Windows NT/2000将设备驱动程式调入内核区域(常见的位于地址0x80000000上),由DPL为0的GDT项8,即cs为8时实现Ring 0权限。本文通过在系统中构造一个指向我们的代码的调用门(CallGate),实现Ring0代码。基于这个思路,为实现这个目的主要是构造自己的CallGate。CallGate由系统中叫Global Descriptor Table(GDT)的全局表指定。GDT地址可由i386指令sgdt获得(sgdt不是特权级指令,普通Ring 3程式均可执行)。GDT地址在Windows NT/2000保存于KPCR(Processor Control Region)结构中(见《再谈Windows NT/2000环境转换》)。GDT中的CallGate是如下的格式:

typedef struct
{
unsigned short offset_0_15;
unsigned short selector;

unsigned char param_count : 4;
unsigned char some_bits : 4;

unsigned char type : 4;
unsigned char app_system : 1;
unsigned char dpl : 2;
unsigned char present : 1;

unsigned short offset_16_31;
} CALLGATE_DESCRIPTOR;

GDT位于内核区域,一般用户态的程式是不可能对这段内存区域有直接的访问权。幸运的是Windows NT/2000提供了一个叫PhysicalMemory的Section内核对象位于\Device的路径下。顾名思义,通过这个Section对象能够对物理内存进行操作。用objdir.exe对这个对象分析如下:

C:\NTDDK\bin>objdir /D \Device

PhysicalMemory
Section
DACL -
Ace[ 0] - Grant - 0xf001f - NT AUTHORITY\SYSTEM
Inherit:
Access: 0x001F and ( D RCtl WOwn WDacl )

Ace[ 1] - Grant - 0x2000d - BUILTIN\Administrators
Inherit:
Access: 0x000D and ( RCtl )

从dump出的这个对象DACL的Ace能够看出默认情况下只有SYSTEM用户才有对这个对象的读写权限,即对物理内存有读写能力,而Administrator只有读权限,普通用户根本就没有权限。但是假如我们有Administrator权限就能够通过GetSecurityInfo、SetEntriesInAcl和SetSecurityInfo这些API来修改这个对象的ACE。这也是我提供的代码需要Administrator的原因。实现的代码如下:

VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection)
{

PACL pDacl=NULL;
PACL pNewDacl=NULL;
PSECURITY_DESCRIPTOR pSD=NULL;
DWORD dwRes;
EXPLICIT_ACCESS ea;

if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,
NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS)
{
printf( "GetSecurityInfo Error %u\n", dwRes );
goto CleanUp;
}

ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = SECTION_MAP_WRITE;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance= NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = "CURRENT_USER";


if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS)
{
printf( "SetEntriesInAcl %u\n", dwRes );
goto CleanUp;
}

if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,
NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS)
{
printf("SetSecurityInfo %u\n",dwRes);
goto CleanUp;
}

CleanUp:

if(pSD)
LocalFree(pSD);
if(pNewDacl)
LocalFree(pSD);
}

这段代码对给定HANDLE的对象增加了如下的ACE:

PhysicalMemory
Section
DACL -
Ace[ 0] - Grant - 0x2 - WEBCRAZY\Administrator
Inherit:
Access: 0x0002 //SECTION_MAP_WRITE

这样我们在有Administrator权限的条件下就有了对物理内存的读写能力。但若要修改GDT表实现Ring 0代码。我们将面临着另一个难题,因为sgdt指令获得的GDT地址是虚拟地址(线性地址),我们只有知道GDT表的物理地址后才能通过\Device\PhysicalMemory对象修改GDT表,这就牵涉到了线性地址转化成物理地址的问题。我们先来看一看Windows NT/2000是如何实现这个的:

kd> u nt!MmGetPhysicalAddress l 30
ntoskrnl!MmGetPhysicalAddress:
801374e0 56 push esi
801374e1 8b742408 mov esi,[esp 0x8]
801374e5 33d2 xor edx,edx
801374e7 81fe00000080 cmp esi,0x80000000
801374ed 722c jb ntoskrnl!MmGetPhysicalAddress 0x2b (8013751b)
801374ef 81fe000000a0 cmp esi,0xa0000000
801374f5 7324 jnb ntoskrnl!MmGetPhysicalAddress 0x2b (8013751b)
801374f7 39153ce71780 cmp [ntoskrnl!MmKseg2Frame (8017e73c)],edx
801374fd 741c jz ntoskrnl!MmGetPhysicalAddress 0x2b (8013751b)
801374ff 8bc6 mov eax,esi
80137501 c1e80c shr eax,0xc
80137504 25ffff0100 and eax,0x1ffff
80137509 6a0c push 0xc
8013750b 59 pop ecx
8013750c e8d3a7fcff call ntoskrnl!_allshl (80101ce4)
80137511 81e6ff0f0000 and esi,0xfff
80137517 03c6 add eax,esi
80137519 eb17 jmp ntoskrnl!MmGetPhysicalAddress 0x57 (80137532)
8013751b 8bc6 mov eax,esi
8013751d c1e80a shr eax,0xa
80137520 25fcff3f00 and eax,0x3ffffc
80137525 2d00000040 sub eax,0x40000000
8013752a 8b00 mov eax,[eax]
8013752c a801 test al,0x1
8013752e 7506 jnz ntoskrnl!MmGetPhysicalAddress 0x44 (80137536)

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: DriverStudio工具包介绍

下一篇: 用PcommPro研发串行通信程式