分享
 
 
 

任意用户模式下执行Ring代码

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

众所周知在非 Admin 用户模式下,是不允许加载驱动执行 RING 0 代码的。

本文提供了一种方法,通过修改系统 GDT,IDT 来添加自己的 CALLGATE 和

INTGATE 这样便在系统中设置了一个后门。我们就可以利用这个后门

在任意用户模式下执行 ring 0 代码了。为了保证我们添加的 CALLGATE 和 INT

GATE 永久性。可以在第一次安装时利用 SERVICE API 或 INF 文件设置成随

系统启动。不过此方法也有个缺陷,就是在第一次安装 CALLGATE 或 INTGATE

时仍然需要 ADMIN 权限。下面分别给出了添加 CALLGATE 与 INTGATE 的具体

代码。

一、通过添加调用门实现

为了可以让任意用户来调用我们的 CALLGATE 需要解决一个小问题。因为

需要知道 CALLGATE 的 SELECTOR 后才可以调用。而在 RING 3 下除了能

得到 GDT 的 BASE ADDRESS 和 LIMIT 外是无法访问 GDT 内容的。我本想

在 RING 0 把 SELECTOR 保存到文件里。在 RING 3 下读取出来再调用。

后经过跟 wowocock 探讨。他提出的思路是在 RING 0 下通过

ZwQuerySystemInformation 得到 NTDLL.DLL 的 MODULE BASE 然后根据

PE HEADER 中的空闲处存放 SELECTOR。这样在 RING 3 的任意用户模式下

就很容易得到了。在这里要特别感谢 wowocock。下面的代码为了演示

方便,用了在我机器上 GDT 中第一个空闲描述符的 SELECTOR 。

驱动程序:

/*****************************************************************

文件名 : WssAddCallGate.c

描述 : 添加调用门

作者 : sinister

最后修改日期 : 2002-11-02

*****************************************************************/

#include "ntddk.h"

#include "string.h"

#ifndef DWORD

#define DWORD unsigned int

#endif

#ifndef WORD

#define WORD unsigned short

#endif

#define LOWORD(l) ((unsigned short)(unsigned int)(l))

#define HIWORD(l) ((unsigned short)((((unsigned int)(l)) >> 16) & 0xFFFF))

typedef unsigned long ULONG;

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);

#pragma pack(push,1)

typedef struct tagGDTR{

WORD wLimit;

DWORD *dwBase;

}GDTR, *PGDTR;

typedef struct tagGDT_DESCRIPTOR{

unsigned limit : 16;

unsigned baselo : 16;

unsigned basemid : 8;

unsigned type : 4;

unsigned system : 1;

unsigned dpl : 2;

unsigned present : 1;

unsigned limithi : 4;

unsigned available : 1;

unsigned zero : 1;

unsigned size : 1;

unsigned granularity : 1;

unsigned basehi : 8;

}GDT_DESCRIPTOR, *PGDT_DESCRIPTOR;

typedef struct tagCALLGATE_DESCRIPTOR{

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, *PCALLGATE_DESCRIPTOR;

#pragma pack(pop)

void __declspec(naked) Ring0Call()

{

PHYSICAL_ADDRESS PhyAdd;

__asm {

pushad

pushfd

cli

}

DbgPrint("WSS - My CallGate \n");

//

// 这里可以添加你想要执行的 ring 0 代码。

//

__asm {

popfd

popad

retf

}

}

VOID AddCallGate( ULONG FuncAddr )

{

GDTR gdtr;

PGDT_DESCRIPTOR gdt;

PCALLGATE_DESCRIPTOR callgate;

WORD wGDTIndex = 1;

__asm {

sgdt gdtr // 得到 GDT 基地址与界限

}

gdt = (PGDT_DESCRIPTOR) ( gdtr.dwBase + 8 ); // 跳过空选择子

while ( wGDTIndex < ( gdtr.wLimit / 8 ) )

{

if ( gdt->present == 0 ) //从 GDT 中找到空描述符

{

callgate = (PCALLGATE_DESCRIPTOR)gdt;

callgate->offset_0_15 = LOWORD(FuncAddr);

callgate->selector = 8; // 内核段选择子

callgate->param_count = 0; // 参数复制数量

callgate->some_bits = 0;

callgate->type = 0xC; // 386调用门

callgate->app_system = 0; // 系统描述符

callgate->dpl = 3; // RING 3 可调用

callgate->present = 1; // 设置存在位

callgate->offset_16_31 = HIWORD(FuncAddr);

DbgPrint("Add CallGate\n");

return;

}

gdt ++;

wGDTIndex ++;

}

}

// 驱动入口

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )

{

UNICODE_STRING nameString, linkString;

PDEVICE_OBJECT deviceObject;

NTSTATUS status;

HANDLE hHandle;

int i;

//卸载驱动

DriverObject->DriverUnload = DriverUnload;

//建立设备

RtlInitUnicodeString( &nameString, L"\\Device\\WssAddCallGate" );

status = IoCreateDevice( DriverObject,

0,

&nameString,

FILE_DEVICE_UNKNOWN,

0,

TRUE,

&deviceObject

);

if (!NT_SUCCESS( status ))

return status;

RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssAddCallGate" );

status = IoCreateSymbolicLink (&linkString, &nameString);

if (!NT_SUCCESS( status ))

{

IoDeleteDevice (DriverObject->DeviceObject);

return status;

}

AddCallGate((ULONG)Ring0Call);

for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {

DriverObject->MajorFunction[i] = MydrvDispatch;

}

DriverObject->DriverUnload = DriverUnload;

return STATUS_SUCCESS;

}

//处理设备对象操作

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

{

Irp->IoStatus.Status = STATUS_SUCCESS;

Irp->IoStatus.Information = 0L;

IoCompleteRequest( Irp, 0 );

return Irp->IoStatus.Status;

}

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)

{

UNICODE_STRING nameString;

RtlInitUnicodeString( &nameString, L"\\DosDevices\\WssAddCallGate" );

IoDeleteSymbolicLink(&nameString);

IoDeleteDevice(pDriverObject->DeviceObject);

return;

}

应用程序:

#include <windows.h>

#include <stdio.h>

void main()

{

WORD farcall[3];

farcall[0] = 0x0;

farcall[1] = 0x0;

farcall[2] = 0x4b; //在我机器上,添加 CALLGATE 的选择子为 4BH

_asm call fword ptr [farcall]

}

二、通过添加中断门实现

添加中断门没有什么需要解决的问题。直接在 RING 3 利用 int x

即可切换。想想系统调用 INT 2E 就很容易理解了。

/*****************************************************************

文件名 : WssMyInt.c

描述 : 添加中断门

作者 : sinister

最后修改日期 : 2002-11-02

*****************************************************************/

#include "ntddk.h"

#pragma pack(1)

typedef struct tagIDTR {

short Limit;

unsigned int Base;

}IDTR, *PIDTR;

typedef struct tagIDTENTRY {

unsigned short OffsetLow;

unsigned short Selector;

unsigned char Reserved;

unsigned char Type:4;

unsigned char Always0:1;

unsigned char Dpl:2;

unsigned char Present:1;

unsigned short OffsetHigh;

} IDTENTRY, *PIDTENTRY;

#pragma pack()

#define MYINT 0x76

extern VOID _cdecl MyIntFunc();

CHAR IDTBuffer[6];

IDTENTRY OldIdt;

PIDTR idtr = (PIDTR)IDTBuffer;

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);

// 我们得中断处理函数

VOID _cdecl MyIntFunc()

{

PHYSICAL_ADDRESS PhyAdd;

unsigned int dwCallNum;

unsigned int dwVAddr;

_asm mov dwCallNum,eax

//

// 这里可以添加你想要执行的 ring 0 代码

//

switch ( dwCallNum )

{

case 0x01:

DbgPrint("MyIntGate eax = 0x01\n");

break;

case 0x02:

DbgPrint("MyIntGate eax = 0x02\n");

break;

default:break;

}

_asm iretd; //中断返回

}

NTSTATUS AddMyInt()

{

PIDTENTRY Idt;

//得到 IDTR 中得段界限与基地址

_asm sidt IDTBuffer

Idt = (PIDTENTRY)idtr->Base; //得到IDT表基地址

//保存原有得 IDT

RtlCopyMemory(&OldIdt, &Idt[MYINT], sizeof(OldIdt));

//禁止中断

_asm cli

//设置 IDT 表各项添加我们得中断

Idt[MYINT].OffsetLow = (unsigned short)MyIntFunc; //取中断处理函数低16位

Idt[MYINT].Selector = 8; //设置内核段选择子

Idt[MYINT].Reserved = 0; //系统保留

Idt[MYINT].Type = 0xE; //设置0xE表示是中断门

Idt[MYINT].Always0 = 0; //系统保留必须为0

Idt[MYINT].Dpl = 3; //描述符权限,设置为允许 RING 3 进程调用

Idt[MYINT].Present = 1; //存在位设置为1表示有效

Idt[MYINT].OffsetHigh = (unsigned short)((unsigned int)MyIntFunc>>16); //取中断处理函数高16位

//开中断

_asm sti

return STATUS_SUCCESS;

}

//删除中断

void RemoveMyInt()

{

PIDTENTRY Idt;

Idt = (PIDTENTRY)idtr->Base;

_asm cli

//恢复 IDT

RtlCopyMemory(&Idt[MYINT], &OldIdt, sizeof(OldIdt));

_asm sti

}

// 驱动入口

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )

{

UNICODE_STRING nameString, linkString;

//UNICODE_STRING deviceString;

PDEVICE_OBJECT deviceObject;

NTSTATUS status;

WCHAR wBuffer[200];

nameString.Buffer = wBuffer;

nameString.MaximumLength = 200;

//卸载驱动

DriverObject->DriverUnload = DriverUnload;

//建立设备

RtlInitUnicodeString( &nameString, L"\\Device\\WSSINT" );

status = IoCreateDevice( DriverObject,

0,

&nameString,

FILE_DEVICE_UNKNOWN,

0,

TRUE,

&deviceObject

);

if (!NT_SUCCESS( status ))

return status;

RtlInitUnicodeString( &linkString, L"\\??\\WSSINT" );

//使WIN32应用程序可见

status = IoCreateSymbolicLink (&linkString, &nameString);

if (!NT_SUCCESS( status ))

{

IoDeleteDevice (DriverObject->DeviceObject);

return status;

}

AddMyInt();

DriverObject->MajorFunction[IRP_MJ_CREATE] = MydrvDispatch;

DriverObject->MajorFunction[IRP_MJ_CLOSE] = MydrvDispatch;

return STATUS_SUCCESS;

}

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

{

NTSTATUS status;

UNREFERENCED_PARAMETER( DeviceObject );

Irp->IoStatus.Status = STATUS_SUCCESS;

Irp->IoStatus.Information = 0L;

status = STATUS_SUCCESS;

IoCompleteRequest( Irp, 0 );

return status;

}

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)

{

UNICODE_STRING nameString;

UNICODE_STRING deviceString,driveString;

NTSTATUS ntStatus;

RemoveMyInt();

//删除WIN32可见

IoDeleteSymbolicLink(&nameString);

//删除设备

IoDeleteDevice(pDriverObject->DeviceObject);

return;

}

//代码转自安全焦点

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有