您的位置:首页 > 其它

【转】ring3 CPU指令级别--操作内核的一些系统级别工具

2012-10-07 21:22 561 查看
RING3

  什么是RING3?这得从CPU指令系统(用于控制CPU完成各种功能的命令)的特权级别说起。在CPU的所有指令中,有一些指令是非常危险的,如果错用,将导致整个系统崩溃。比如:清内存、设置时钟等。如果所有的程序都能使用这些指令,那么你的系统一天死机n回就不足为奇了。所以,CPU将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通的应用程序只能使用那些不会造成灾难的指令。形象地说,特权指令就是那些儿童不宜的东东,而非特权指令则是老少皆宜。

  Intel的CPU将特权级别分为4个级别:RING0,RING1,RING2,RING3。Windows只使用其中的两个级别RING0和RING3,RING0只给操作系统用,RING3谁都能用。如果普通应用程序企图执行RING0指令,则Windows会显示“非法指令”错误信息。因为有CPU的特权级别作保护。

内核级别相应工具,手动杀毒

如果您对window系统不甚熟悉,您还是不要使用本工具,即使要使用,也不要用本工具胡乱操作。

请注意,如果你不知道PROCESS,DRIVER,SSDT,HOOK,DLL INJECT,IAT HOOK,EAT HOOK,IRP HOOK 等等,请先百度,后使用!免费的不一定比收费的差!

XueTr0.29;这个最方便,支持WIN7,完全取代了冰刃(IceSword)

GMER;

KERNEL_DETECTIVE_V1.3.0;

RkU3.8.341.552;这个最强大

等等,很多。

有任何使用方面的问题都可以在下面跟帖说明!

※ 来源:·沁水青山BBS站

http://bbs.wust.edu.cn·[FROM:
58.19.34.*]

附件:XueTr0.29.zip(434242 字节)

附件:KERNEL_DETECTIVE_V1.3.0.ZIP(262827 字节)

附件:RkU3.8.341.552.rar(153249 字节)

附件:gmer.zip(280419 字节)

一些问题
如何实现在Ring3级具有Ring0级权限?

CPU特权级的切换 必须通过中断调用门来进行,必须通过汇编语言来实现。没有API能做到这点。因为通常操作系统对内核进行ring 0保护,任何应用程序不能进入ring 0操作。应用程序要使用内核功能(比如新建进程,新建线程等)的话,由系统调用先切换到ring 0,再紧接着切换回ring 3。ring 0对于应用程序来讲是透明的。

真想了解这种机制的话,可以看Linux的源代码http://www.oldlinux.org/

这个网站中有Linux 0.11版内核的完整介绍。看完了这个,你就对操作系统的5大功能基本实现有了大概的了解,至于保护模式中的ring0,ring3的概念以及切换方法也就明白了。

ring0级别调用ring3

Ring0 Call Ring3

因为最近决定把读本科时的古董机上的东西收拾一下,看到一些最初学习时的老代码,回忆往日的时光,还颇有一些感慨呢...以后有空就选一些贴贴,也不怕人笑了。今天第一帖,代码原是大二时为NT4系统写的,是原先实践x86体系写的,作用是在Driver中“调用”用户态的MessageBoxA做出显示。朋友都说:“你无聊不无聊,好多人写过这个题目了”,呵呵,我只是把以前的东西贴贴,尽量少提及别人说过的,可能初学者们会有收获呢。现在作了一点点修改,只在2000上测了测,还可以跑跑。

这就是一个Ring0 Call Ring3的问题。对于这个问题,在原先试验之前网上就有一些讨论了,有了一些替代方案,比如说User APC。

记得见过最早的是应该是Anatoly Vorobey在某新闻组的发言,查了查,他发帖是97年的时候,很古老了。最近www.rootkit.com贴出了一篇关于ring0创建进程 的文章用的就是这个方法,不过仅是其一个简单应用。

UserAPC的代码网上很多。就不贴了,使用很方便很简单,只是注意用时对Thread->ApcState.UserApcPending的处理。

如果我们把处理控制的直接转移作为“调用”的基本要求,那么

依赖于系统间接转移的APC机制就算不上“调用”。那么Ring3代码如何“调用”Ring0代码呢?方法是显然的,我们模拟这样一个场景:系统通过某种机制(比如中断或是改变特权的调用)由ring3进入了

ring0时候的现场(主要是栈现场)。于是我们模拟好后,直接通过返回指令达到直接控制转移的目的。当然,我们应当保存原始现场,以便用户台代码执行完毕后能顺利回到“调用”指令后的第一条指令执行(如同真正的call)。

实质上windows自己也在用这个方法来进行一些有必要的核心态向用户态的直接控制转移,即KeUserModeCallback。典型的例子就是wind32k中的使用,“防止消息钩子注入”里也简单提到。

当时2000还没出来,研究的比较多的是linux和9x的核,对于NT使用此回调的具体过程就不甚清楚,现在源码都漏了颇久了,初学者们看起来方便多了。下面我们自己不利用NT的代码,自己做一个类似的东西。

下面仅仅讨论直接“调用”的基本方法。ring0转向ring3之前首先要确保用户空间的合法性以及ring3代码与用户栈的合法性,这一点根据需求会有许多做法,为了简单起见,调用的时机选在ring3使用DeviceIoControl进入驱动例程时回调,回调的地址与用户栈均由应用程序传入,这样使预处理最小化。

驱动程序分派例程里只需写:

switch(IoControlCode)

{case IOCTL_CALL_RING3:

{addr = *PULONG(InputBuffer); //ring3函数地址

stack = *(PULONG(InputBuffer)+1);//ring3栈地址

cfunc();

return 0;

}}

其中cfunc函数即完成了向ring3的调用,其代码如下(很老的代码,很凌乱,加了点注释):

void __declspec(naked) cfunc()

{_asm pushad

_asm sidt buffer

IdtEntry = (PIdtEntry_t)Idtr->Base;

OldEntry = IdtEntry[HOOKINT]; //#define HOOKINT 0xF0

_asm lea eax,interrupt

_asm mov NewHandler,eax

/*接管中断0xF0,目的是让应用程序能通过使用int 0f0h

指令返回到核心态。

int 0f0h起的作用正是等同于ret

F0陷阱的处理函数恢复内核栈等至“调用”前的状态*/

_asm cli

IdtEntry[HOOKINT].Dpl = 3;

IdtEntry[HOOKINT].Type = 0xF;

IdtEntry[HOOKINT].Present = 1;

IdtEntry[HOOKINT].OffsetLow = (unsigned short)NewHandler;

IdtEntry[HOOKINT].OffsetHigh = \

(unsigned short)((unsigned int)NewHandler>>16);

_asm sti

_asm {

str word ptrpush eax

sgdt [esp-2]

pop eax

movzx ebx,word ptrand ebx,0fffffff8h

add eax,ebx

mov ebx,[eax]

and ebx,0ffff0000h

shr ebx,16

mov ecx,[eax+4]

and ecx,0ffh

shl ecx,16

or ebx,ecx

mov ecx,[eax+4]

and ecx,0ff000000h

or ebx,ecx

mov tss,ebx

mov cur,esp

}count=tss->esp0-cur;

/*上面代码获取当前内核栈的地址与需保存大小

下面代码保存栈内容*/

_asm{

mov ecx,count

mov edi,TMP

mov esi,cur

rep movsb

}/*模拟返回环境,不用多解释了

iretd我们把它类比于call*/

_asm{

mov eax,3bh

mov fs,ax

mov eax,23h

push eax

mov eax,stack

push eax

pushfd

mov eax,1bh

push eax

mov eax,addr

push eax

iretd

}/*int 0f0h后返回这里开始执行*/

interrupt:

_asm{

mov eax,30h

mov fs,ax

mov ecx,count

mov esi,TMP

mov edi,cur

rep movsb

mov esp,cur

}IdtEntry=(PIdtEntry_t)Idtr->Base;

_asm cli

IdtEntry[HOOKINT] = OldEntry;

_asm sti

_asm popad

_asm ret

}基本方法十分简单,具体使用需要的预处理就比较繁琐了。它可能并不实用,不过可以为一些朋友提供练手机会。被调用的用户代码就很简单了:

void __declspec(naked) FuncAddr()

{MessageBox(NULL, "OK","OK",MB_OK);

_asm int 0xF0 //ret

}...

{...

BOOL result;

ULONG param[2];

DWORD BytesReturned;

char *stack = (char*)malloc(0x10000);

param[0] = (DWORD)FuncAddr;

param[1] = (DWORD)(stack+0x10000);

result = DeviceIoControl(

hDevice,

IOCTL_CALL_RING3,

param,

8,

0,

0,

&BytesReturned,

0;

free(stack);

...

}ring0的驱动程序就这样“调用”了ring3的FuncAddr并显示出了对话框。

理解这些之后,有兴趣可以看看windows是如何利用这个手段的,它又复杂在哪点。最后说一句的是,因为我们的处理过于简单,如果你在ring3的函数里发生了异常,或是结束进程,那么效果是这个进程会成为清不掉的“僵尸”进程,可能一看“清不掉”,有的朋友又想到了可不可以利用来实现“进程不死术”,呵呵,会失望的。僵尸不同于不死,自己看看吧。

上面是PJF老大的帖子,下面是我根据他的做的例子,我发现通过MALLOC来分配的RING3堆栈在你FREE的时候会异常,可能堆栈的数据信息被破坏了,所以只能用静态数据区来代替下,大家也测试看看注意的是在输入缓冲区大小的时候应该>=8,因为我们把RING3的地址和堆栈都传入到RING0去执行了.

http://www.driverdevelop.com/forum/html_88451.html?1110610534http://www.driverdevelop.com/forum/upload/wowocock/2005-03-12_CallMsgRing0.rar

HOOK SSDT

NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )

{

DriverObject->DriverUnload = OnUnload;

Hook();

return STATUS_SUCCESS;

}

// 此处修改SSDT中的NtOpenProcess服务地址

VOID Hook()

{

ULONG Address;

// 0x7A为NtOpenProcess服务号

Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;

RealServiceAddress = *(ULONG*)Address;



RealNtOpenProcess = (NTOPENPROCESS)RealServiceAddress;

DbgPrint( "Address of Real NtOpenProcess: 0x%08X\n", RealServiceAddress );

DbgPrint(" Address of MyNtOpenProcess: 0x%08X\n", MyNtOpenProcess );

// 去掉内存保护 ,这个主要是跟内存分页有关的,出现BSOD

__asm

{

cli

mov eax, cr0

and eax, not 10000h

mov cr0, eax

}

// 修改SSDT中NtOpenProcess服务的地址

*((ULONG*)Address) = (ULONG)MyNtOpenProcess;



// 恢复内存保护

__asm

{

mov eax, cr0

or eax, 10000h

mov cr0, eax

sti

}

}





//这里是恢复

VOID Unhook()

{

ULONG Address;

Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;



//一样的去掉内存保护

__asm

{

cli

mov eax, cr0

and eax, not 10000h

mov cr0, eax

}



// 还原SSDT

*((ULONG*)Address) = (ULONG)RealServiceAddress;



__asm

{

mov eax, cr0

or eax, 10000h

mov cr0, eax

sti

}



DbgPrint("Unhook");

}

#c语言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: