分享
 
 
 

[收藏] Ring0 Call Ring3

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

pjf(jfpan20000@sina.com)

很久没写什么东西,一来文笔太烂,二来我不是一般的懒。这个东西一看题目也就知道又是一篇无聊的帖子,凑凑数先。

因为最近决定把读本科时的古董机上的东西收拾一下,看到一些最初学习时的老代码,回忆往日的时光,还颇有一些感慨呢...以后有空就选一些贴贴,也不怕人笑了。今天第一帖,代码原是大二时为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 ptr[tr]

push eax

sgdt [esp-2]

pop eax

movzx ebx,word ptr[tr]

and 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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有