话说linux的内核空间不能访问用户空间,这是真的吗?前面说过很多次,没有什么是绝对不能的,一定要区分清楚什么是不允许什么是不可能,用户空间不能访问内核空间是硬件规定和实现的,但是反过来,内核空间不能访问用户空间却只是linux的一种约定,一种规定或者多多少少有点设计上的约定,内核空间拥有至高无上的权力为何要限制它呢?其实不是限制而是这样规定使得实现起来更加方便和有条理,仔细想想,内核空间被所有的进程共享,你让内核访问用户空间, 那么访问谁的用户空间呢?所以要想实现内核访问用户空间,必须在访问时指明访问哪个进程的用户空间,而且还会涉及缺页处理的问题,毕竟内核访问的用户空间对应的进程可能不是当前进程,之后的复杂性就不用多说了吧。另外的原因就是设计上的规定了,设计上有个“流”的概念,要想使设计灵活,模块化,或者说低耦 合,那就得使对应的流单向化,就是所谓的单向依赖,tcp/ip模型和osi模型就是这么设计的,上层使用下层的服务,下层绝对不依赖上层,就是不会“调 用”上层,在操作系统的设计中当然也是这样,内核为用户空间服务并且不依赖用户空间,就是不调用用户空间。
事实上就真的不能调用用户空间吗?肯定不是的,就像内核不允许在中断中睡眠,但是你真的在中断处理函数里面调用了个schedule并不会使得内核马上崩 溃,只是内核后面的行为变得不能保证了。我们还是用内核模块来实现一个内核访问用户空间的例子,访问用户空间的数据在《char *和char数组的区别(深拷贝和浅拷贝的观点)以及内核访问用户空间》里面已经说过了,现在要谈的的是内核调用用户空间的函数,这个理解起来要明白两个 东西,一个是程序的text段,一个程序的栈,一个函
数的执行关联到了text段和栈,所谓text段其实也是一种数据,内核调用用户空间的函数实际上就是访问了用户空间的数据,内核从用户空间的text段取到被调函数的指令,这就访问了用户空间数据,然后执行的场所呢?当然是栈了,有函数调用就需要栈,可是这个栈不是那个栈,内核调用用户空间的函数时所用的栈是内核栈,其实也是当前进程的当前栈。这就是说,一个函数执行要弄明白两点,一是到哪里 取指令(一般为text段,当然在缓冲区溢出攻击中可能是栈),二是在哪里执行(一般是
栈)。因此内核调用用户空间的函数就是到用户空间的text段取指令,在内核栈执行,如此而已,还有一个问题,就是如何得到用户空间的函数地址,当然可以通过特征扫,也可以硬赋值,我这里为了简单采用了后者,先看看用户空间程序:
void userfunc( int i )
{
pringf("value:%d/n",i);
}
int main()
{
void *mod;
unsigned int sz;
int ret;
mod = readfile("test.ko", &sz);//将模块读到mod中,此函数略
ret = init_module(module, size, "");//用系统调用加载模块
free(mod);
return 0;
}
编译为testcall应用程序,通过objdump我们查到userfunc的地址是0X80486B4,然后开始写内核模块(只保留主要代码,其余略):
static __init int test_init(void)
{
int (*p)(int i);
p = 0x80486b4;
(*p)(12);
return 0;
}
编 译此模块为test.ko(若有不明请参阅《linux内核相关的两个问题》)。然后将test.ko复制到前面应用程序testcall相同的目录,执 行testcall,猜猜得到了什么?如果说内核不能调用用户函数的话,系统应该panic,如果真的能调用的话,应该打印出value:12,可惜,内 核既没有panic也没有打印value:12,而是打印出了value:-795975574,看来还是调用了用户空间的函数,只是参数传递有问题,还是那句话:汇编代码永远都不会欺骗你。这其实有点哲学意义,越高层越不能相信,最低层的往往最可信,这就是“微服私访”的意义,宁信老百姓,不信当官的。 我们还是用objdump看看userfunc吧:
80486B4 <userfunc>: <br> push %ebp <br> mov %esp,%ebp <br> ... <br> pushl $0x8(%ebp) <br> call printf <br>然后再用objdump看看test.ko里面是怎么设置参数的: <br>00000000 <init_module>: <br>... <br> mov $0x80486b4,%edx <br> mov $0xc,%eax <br> call *%edx <br>... <br>看 到了吧,直接用寄存器eax传递参数,如果你不了解编译器还可以设置参数传递的方式,那么为了得到正确结果有两种方式,一个直接用汇编写userfunc 函数,而是保留c语言的userfunc,但是在内部想办法得到eax的值,如果你根本不会汇编(或者内嵌汇编),那么得到eax的唯一方式就是利用函数的返回值,就是再加一个函数: <br>int help() <br>{ <br> return; <br>} <br>然后更改userfunc: <br>void userfunc( int i ) <br>{ <br> i = help(); <br> pringf("value:%d/n",i); <br>} <br>help 函数什么也没有做,只是返回,用objdump确保它内部没有触及eax的话,这次打印的一定是value:12,因为help函数直接返回了一个值,该 值在eax中,但是help什么也没有做,因此它就直接将eax返回了,试试看,果然结果正确(估计再高版本的编译器会认为help的写法不对,但最起码 在我的gcc上它是正确的,想搞攻击的朋友一定不能放过任何蛛丝马迹)。但是这毕竟不是权宜之计,如果传递第二个,第三个...参数的话这种方法就不奏效 了,当然直接用汇编写函数什么时候都奏效。那该怎么办呢?想想gcc的特性,它专门提供了设置参数传递方式的接口,比如用寄存器传,用堆栈传等等,在利用 这些特性之前先想明白为何内核用寄存器传参,实际上内核栈是很宝贵的,linux中只有4k不到,不像用户空间从3g的边界向下扩展,如果内核栈中塞满了 参数信息,很容易就会栈溢出,另外一个原因就是速度,内核绝对不想让进程在内核态时间过久,要知道push和pop是操作内存的,是相当耗时的操作,为了 速度也要尽量用寄存器传参。 <br>明白了一切后修改的方式有两种,一种是该内核模块,另一种是该用户函数,先看看改内核模块吧,其实很简单,就是将 <br>int (*p)(int i); <br>改为: <br>int __attribute__((regparm(0))) (*p)(int i); <br>__attribute__((regparm(0))) 告诉编译器不要用寄存器传递参数而是用堆栈,其实内核专门提供了一个宏asmlinkage来标志这个特性,如此改变后,结果就正确了;另外改用户函数的 方式与此类似,就是告诉编译器用寄存器传递参数而不是用堆栈,具体改法就是内核模块不变在用户函数前加上 __attribute__((regparm(n))),n为使用寄存器的个数,不同平台规定不同,比如i386上n为3表示可以用eax,edx 和ecx传递参数,这样结果也是正确的。 <br>经过上述对linux的蹂躏可以明白内核真的就是权力很大,完全可以调用用户的函数,但是调用之前必须自己心里清楚当前进程是谁以及那个函数确实存在</init_module></userfunc>
分享到:
相关推荐
忽必烈蹂躏上津.pdf
iPad Air蹂躏测试.docx
资源名称:轻轻松松践踏易语言实战广域网聊天工具开发 资源目录:第一课:认识易语言第二课:瞬间掌握易语言核心编程技巧第三课:提高编码效率第四课:对文本的处理掌握第五课:对文本处理的核心知识掌握第六课-第...
某市城市绿地绿化施工组织设计.doc
从简到难,详细介绍。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
电脑超级技巧3000招,电脑常识!(看完之后你已成为高手)
介绍unity项目如何在AS中Facebook SDK,接入TalkingData和调用安卓的原生震动
H264规范文档,英文。需要学习H264的来下载吧
例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典例子经典
Effective Java (异常处理),需要的朋友可以参考一下
里面封装了各种常用日期格式,肯定能满足你对日期的蹂躏
代码可直接另存为一个文件,如vcode.asp,然后通过图片的方式调用改文件,如,然后...程序就是“5+6=”这样的随机数字相加的形式生成在bmp图片里了,它们的和需要你计算后填入,以达到验证的功能,防止机器蹂躏你的网站
东南大学硬件实验课程设计报告,非常完整,供广大被硬件实验蹂躏的同学们作参考
整理发布的XX集团有限公司管理咨询项目——项目建议书以实现多、快、好、省为目标,欢迎大家下...该文档为XX集团有限公司管理咨询项目——项目建议书,是一份很不错的参考资料,具有较高参考价值,感兴趣的可以下载...
打开一路next就安装好了,再注册一下就可以尽情的蹂躏啦~ (登录后会自动同步你的数据,所有不要吝啬,注册是值得的) 作者:Cindy_Long 链接:https://www.jianshu.com/p/46d44c09d94c 来源:简书 著作权归作者...
主要介绍了个人对c# 面向对象的理解,算是一个入门篇吧,给需要的小伙伴参考下,抛砖引玉。
酷安网点评 · · ·就像在电脑上增加虚拟内存一样,将硬盘的空间虚拟成内存来使用,机器爽了,硬盘就累了,不过相对于蹂躏几千块钱的的机器,大家应该都更倾向于蹂躏几十块钱的SD卡吧,对于内存不够用的机器很有用...
但是技术还是要提高,分享依旧要继续。顺应一句话,你收或者不收,我都在这里。只增不减,不悲不喜。 ok,废话免谈。在之前的文章中曾经写到过一篇“三角形变形记之纯css实现的分布导航条效果”,其中用到了边框...
能让显示卡跑出任何游戏都达不到的高温,对显卡的蹂躏程度越来越“变态”,而且还带有屏蔽显卡的功耗保护功能,所以理论上只要通过了FurMark考验过的显示卡,运行任何游戏都不会出现稳定性问题,可谓是名副其实的...
HTML5及CSS3常见考题汇总,如果你独自完成到这里,只要完成80%,你的HTML5,CSS3原生基础已经相当扎实,你也被大象蹂躏,磨炼成了优秀的人。