system call hooking 系统调用增加或劫持
1. 引言:这篇文章提供了一种增加自定义系统调用或劫持原有的系统调用的实现方法,只针对 linux 系统。主要思路是获取系统调用表 sys_call_table 地址,然后用新函数地址覆盖系统调用表某个元素的值,最终代码可以以modules的模式使用,也可以直接编译进内核使用。
2. 获取系统调用表基地址的方法: cat System.map | grep "sys_call_table"
3. 获取了系统调用表基地址后,如果直接修改这个表,会报错unable to handle kernel paging request at XX,这里引出本文主要要说清楚的一个问题:系统调用表的保护机制,或者更广泛而言,内核页表的保护机制。x86体系架构的页级保护参考 页级保护措施 ,概括而言,一个页面的保护,是由3个地方决定的:pte的U/S域、pte的R/W域、RC0寄存器的WP位; U/S 域指定该页面是属于user访问权限(ring3)还是supervisor(ring0,1,2);R/W域指定页面是read-only还是read-write; RC0.WP 主要是限制supervisor状态的CPU写R/W=read-only 的页面:
1、read-only类型 page
★ PDE/PTE 的 W/R标志被清 0,此时属于 read-only类型 page
★ processor 在 user模式下,只能 read
★ processor 在 supervisor模式下,且 CR0.WP为 0时,可以 read-write
2、read-write类型 page
★ PDE/PTE 的 W/R标志被置 1,此时属于 read-write类型 page
★ processor 在 user模式下,可以对 user模式的 page进行 read-write
★ processor 在 supervisor模式下,可以对supervisor/user模式的 page进行 read-write
U/Sbit的设置好理解:由于我们不想用户空间的代码随意访问(读或写)内核空间的代码或数据,所以内核空间的东西所在页面的属性都是 U/S=supervisor,这样CPU在用户态时将无法访问(如果访问就是段错误)。R/Wbit的设置也好理解,对于一个page,有很多场景要求其是 read-only的;上面比较难理解的是RC0.WP 的设置。其实,该bit真正的作用是实现内核copy-on-write机制,参考what's the purpose of x86 cr0 wp bit?
对于本文的目的来说,系统调用表的属性,U/S必须等于 supervisor ,R/W默认是 read-only, RC0.WP 默认是1,即处于supervisor的CPU无法写 Read-only的页面,这样就导致了我们获取了sys_call_table的地址后,如果直接对其中某个地址赋值,会导致kernel panic。 解决这个问题主要是两种方式: 要不就是在赋值之前,先修改RC0.WP为0;要不就是在赋值之前,修改页面属性为 read-write.
4 下面是代码
char * hack_mkdir(const char * path)(//这里我们增加的系统调用
{
printk(KERN_INFO "this is in hack_mkdir\n");
} //// for 64bit
static u64 clear_cr0(void) //将 cr0.mp 置0,同时要保存原来的 cr0 的值
{
u64 cr0 = ;
u64 ret; asm volatile ("movq %%cr0, %0"
: "=a"(cr0)
);
ret = cr0; //clear the 20 bit of CR0, a.k.a WP bit
cr0 &= ~0x10000LL; asm volatile ("movq %0, %%cr0"
:
: "a"(cr0)
);
return ret;
} static void setback_cr0( u64 val ) //将保存的cr0值赋回去
{
asm volatile ("movq %0, %%cr0"
:
: "a"(val)
); }
*/
// for xen system
static void set_addr_rw(void** addr) {//将页面R/W属性改为 read-write unsigned int level;
pte_t *pte = lookup_address((unsigned long)addr, &level); if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW; } static void set_addr_ro(void** addr) {//将页面R/W属性改为 read-only unsigned int level;
pte_t *pte = lookup_address((unsigned long)addr, &level); pte->pte = pte->pte &~_PAGE_RW; } static int __init begin(void)
{
orig_mkdir = call_table[300]; // 这里我们增加第 300 号系统调用,并将原有的地址保存
printk(KERN_INFO "call_table[__NR_hello] = %p\n", call_table[__NR_hello]);
//u64 cr0;
//cr0 = clear_cr0();
set_addr_rw(call_table);
call_table[__NR_hello] = hack_mkdir; //?..
//setback_cr0(cr0);
set_addr_ro(call_table);
printk(KERN_INFO "call_table[__NR_hello] = %p\n", call_table[__NR_hello]); return ;
} static void __exit end(void)
{
//u64 cr0;
//cr0 = clear_cr0();
set_addr_rw(call_table);
call_table[__NR_hello] = orig_mkdir;//setback_cr0(cr0);
set_addr_ro(call_table);
} module_init(begin);
module_exit(end);
上面两种解决方案有什么区别呢?在我们的实验当中,系统是跑在xen hypervisor层之上的,即整个kernel的内存都是被xen虚拟化之后的内存,而xen hypervisor对 CR0 寄存器的虚拟页面有做控制(注意,这时候 cr0 不再是物理的寄存器,而是一个页面),导致如果调用clear_cr0 函数,虚拟机会panic。 这时候采用 set_addr_rw 的方案就可以。这里提到了xen虚拟机里设置cr0寄存器发生的问题
system call hooking 系统调用增加或劫持的更多相关文章
- Win7系统system进程句柄数一直增加解决方案
公司内部最近有个服务端的同事电脑句柄数一开机就一直增加 一台Windows7x64系统16G 其实物理内存使用情况在开机后并没有太大的变化,但虚拟内存占用明显在不停的增加. 我通过“任务管理器”一直也 ...
- Linux System Calls Hooking Method Summary
http://www.cnblogs.com/LittleHann/p/3854977.html http://www.cnblogs.com/cozy/articles/3175615.html h ...
- Hooking Android System Calls for Pleasure and Benefit
The Android kernel is a powerful ally to the reverse engineer. While regular Android apps are hopele ...
- Windows API Hooking in Python
catalogue . 相关基础知识 . Deviare API Hook Overview . 使用ctypes调用Windows API . pydbg . winappdbg . dll inj ...
- 《Linux内核分析》第五周笔记 扒开系统调用的三层皮(下)
扒开系统调用的三层皮(下) 一.给menuOS增加time和time-asm 通过内核调试系统调用.将上次做的实验加入到menusOS,变成menusOS里面的两个命令. 1 int Getpid(i ...
- system函数遇到的问题
这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以 ...
- 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call. 系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变 ...
- Java数组,去掉重复值、增加、删除数组元素
import java.util.List; import java.util.ArrayList; import java.util.Set; import java.util.HashSet; p ...
- Linux内核-系统调用
Linux内核-系统调用 1.与内核通信 #系统调用在用户空间进程和硬件设备之间添加了一个中间层 作用:1.为用户空间提供了一种硬件的抽象接口 2.系统调用保证了系统的稳定和安全 3.出于每一个进程都 ...
随机推荐
- Android 程序中获取一个反向 Shell
代码如下: String command = "ls -al /"; Process process = Runtime.getRuntime().exec(command); 之 ...
- Android面试收集录9 IntentService详解
一. 定义 IntentService是Android里面的一个封装类,继承自四大组件之一的Service. 二.作用 处理异步请求,实现多线程 三. 工作流程 注意:若启动IntentService ...
- Hyper-V中的Linux无法配置网络地址的解决办法
一周碰到2次在Hyper-V 2012中安装了Linux,也安装了IC 3.4.但是却无法配置IP地址的问题.因此造成很多不便,因此找机会把这个原因和解决办法进行了尝试. 这过程中感谢同事的提示,让我 ...
- 关于IOS下日期格式分隔符 - 、 /的问题
之前我们项目有一个低价日历,服务端下发的时间格式为: "2014-07-21 09:45:12" 然后一直出不了数据,后来发现. IOS下无论chrome.safari还是Uc如 ...
- 《Cracking the Coding Interview》——第2章:链表——题目2
2014-03-18 02:24 题目:给定一个单链表,找出倒数第K个节点. 解法:让一个指针先走K步,然后俩指针一起走到尽头.当然也可以先走到尽头数出链表的长度,然后第二次少走K步.其实耗费的工夫是 ...
- Windows Phone 8.1 学习之路
前几天看一哥们写的“Android学习之路”一文很不错,遂也写一篇Windows Phone的学习之路. 开发环境 台式机 不管是台式机还是笔记本,建议配置在I5+8G以上,I3+4G的话就别考虑用模 ...
- HTML简易学习笔记
文字版地址 https://github.com/songzhenhua/github/blob/master/HTML简易学习笔记.txt
- springboot整合jersey
https://blog.csdn.net/xiongpei00/article/details/76576420
- 【转载】法线贴图Nomal mapping 原理
法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,贴在低端模型的法线贴图通道上,使之拥有法线贴图的渲染效果,却可以大大降低渲染时需要的面数和计算内容,从而达到 ...
- 孤荷凌寒自学python第十八天python变量的作用范围
孤荷凌寒自学python第十八天python函数的形参与变量的范围 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.在python的函数中各种不同的形式参数在定义的先后顺序上有规定: 必须 ...