[收藏] Ring0 Call Ring3

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
冰刃IceSword 1.22 简介 IceSword是一斩断黑手的利刃(所以取这土名,有点搞e,呵呵)。它适用于Windows 2000/XP/2003/Vista操作系统,用于查探系统中的幕后黑手(木马后门)并作出处理,当然使用它需要用户有一些操作系统的知识。 在对软件做讲解之前,首先说明第一注意事项 :此程序运行时不要激活内核调试器(如softice),否则系统可能即刻崩溃。另外使用前请保存好您的数据,以防万一未知的Bug带来损失。 IceSword目前只为使用32位的x86兼容CPU的系统设计,另外运行IceSword需要管理员权限。 如果您使用过老版本,请一定注意,使用新版本前要重新启动系统,不要交替使用二者。 IceSword内部功能是十分强大的。可能您也用过很多类似功能的软件,比如一些进程工具、端口工具,但是现在的系统级后门功能越来越强,一般都可轻而易举地隐藏进程、端口、注册表、文件信息,一般的工具根本无法发现这些“幕后黑手”。IceSword使用大量新颖的内核技术,使得这些后门躲无所躲。 如何退出IceSword:直接关闭,若你要防止进程被结束时,需要以命令行形式输入:IceSword.exe /c,此时需要Ctrl+Alt+D才能关闭(使用三键前先按一下任意键)。 如果最小化到托盘时托盘图标又消失了:此时可以使用Ctrl+Alt+S将IceSword主界面唤出。因为偷懒没有重绘图标,将就用吧^_^。 您无须为此软件付费,但如果您使用时发现了什么Bug,请mail to me:jfpan20000@sina.com ,十分感谢。 更新说明: 1.20:(1)恢复了插件功能,并提供一个文件注册表的小插件,详见FileReg.chm;(2)对核心部分作了些许改动,界面部分仅文件菜单有一点变化。 1.20(SubVer 111E3):添加对32位版本Vista(NtBuildNumber:6000)的支持。 1.22:(1)增加普通文件、ADS、注册表、模块的搜索功能;(2)隐藏签名项;(3)添加模块的HOOK扫描;(4)核心功能的加强。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

紫郢剑侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值