[fw]拦截系统调用
今天在ubuntu中玩了下“拦截系统调用”,记录下自己对整个实现的理解。
原理
在linux kernel中,系统调用都放在一个叫做“sys_call_table”的分配表里面,在进入一个系统调用的最后一步,会调用与eax中包含的系统调用号对应的特定服务例程:
- call *sys_call_table(,%eax,4)
因为分派表中的每个表项占4个字节,因此首先把系统调用号乘以4,再加上sys_call_table分配表的起始地址,然后从从这个地址单元获取指向服务例程的指针,内核就找到了要调用的服务例程。我们只要修改对应的分配表项,即可实现系统调用的拦截。
获取sys_call_table的地址
网上介绍了很多种方法得到sys_call_table的地址,我使用了相对简单的一种方法——从内核导出的符号表中获取。
图中,十六进制数c15b3000即为sys_call_table的地址。同时,我们也得到了一个重要的信息,该符号对应的内存区域是只读的!
清除写保护
因为sys_call_table分配表的内存属性为只读,因此,我们要先清除对应地址的写保护。暂时使用了两种方法实现该目的:
第一种方法,修改cr0读写保护位:
- /* 清除写保护 */
- unsigned int clear_and_return_cr0(void)
- {
- unsigned int cr0 = 0;
- unsigned int ret;
- asm volatile ("movl %%cr0, %%eax"
- : "=a"(cr0)
- );
- ret = cr0;
- /* clear the 16 bit of CR0, a.k.a WP bit */
- cr0 &= 0xfffeffff;
- asm volatile ("movl %%eax, %%cr0"
- :
- : "a"(cr0)
- );
- return ret;
- }
- /* 设置cr0,--本程序用来恢复写保护 */
- void setback_cr0(unsigned int val)
- {
- asm volatile ("movl %%eax, %%cr0"
- :
- : "a"(val)
- );
- }
第二种方法,设置虚拟地址对应页表项的读写属性:
- /* make the page writable */
- int make_rw(unsigned long address)
- {
- unsigned int level;
- pte_t *pte = lookup_address(address, &level);
- if (pte->pte & ~_PAGE_RW)
- pte->pte |= _PAGE_RW;
- return 0;
- }
- /* make the page write protected */
- int make_ro(unsigned long address)
- {
- unsigned int level;
- pte_t *pte = lookup_address(address, &level);
- pte->pte &= ~_PAGE_RW;
- return 0;
- }
附:完整代码
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/sched.h>
- #include <linux/init.h>
- #include <linux/fs.h>
- #include <linux/file.h>
- #include <linux/fs_struct.h>
- #include <linux/fdtable.h>
- #include <linux/string.h>
- #include <linux/mm.h>
- #include <linux/syscalls.h>
- #include <linux/list.h>
- #include <linux/jiffies.h>
- #include <linux/cdev.h>
- #include <asm/unistd.h>
- #include <asm/uaccess.h>
- #include <linux/path.h>
- #include <linux/time.h>
- #include <linux/stat.h>
- #include <net/sock.h>
- #include <net/inet_sock.h>
- #include <asm/cpufeature.h>
- /* grep sys_call_table /boot/System.map-`uname -r` */
- unsigned long **sys_call_table = (unsigned long **)0xc15b3000;
- unsigned long *orig_mkdir = NULL;
- /* make the page writable */
- int make_rw(unsigned long address)
- {
- unsigned int level;
- pte_t *pte = lookup_address(address, &level);
- if (pte->pte & ~_PAGE_RW)
- pte->pte |= _PAGE_RW;
- return 0;
- }
- /* make the page write protected */
- int make_ro(unsigned long address)
- {
- unsigned int level;
- pte_t *pte = lookup_address(address, &level);
- pte->pte &= ~_PAGE_RW;
- return 0;
- }
- asmlinkage long hacked_mkdir(const char __user *pathname, int mode)
- {
- printk("mkdir pathname: %s\n", pathname);
- printk(KERN_ALERT "mkdir do nothing!\n");
- return 0; /*everything is ok, but he new systemcall does nothing*/
- }
- static int syscall_init_module(void)
- {
- printk(KERN_ALERT "sys_call_table: 0x%lx\n", sys_call_table);
- orig_mkdir = (unsigned long *)(sys_call_table[__NR_mkdir]);
- printk(KERN_ALERT "orig_mkdir: 0x%lx\n", orig_mkdir);
- make_rw((unsigned long)sys_call_table);
- sys_call_table[__NR_mkdir] = (unsigned long *)hacked_mkdir;
- make_ro((unsigned long)sys_call_table);
- return 0;
- }
- static void syscall_cleanup_module(void)
- {
- printk(KERN_ALERT "Module syscall unloaded.\n");
- make_rw((unsigned long)sys_call_table);
- sys_call_table[__NR_mkdir] = (unsigned long *)orig_mkdir; /*set mkdir syscall to the origal one*/
- make_ro((unsigned long)sys_call_table);
- }
- module_init(syscall_init_module);
- module_exit(syscall_cleanup_module);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("hack syscall");
参考:
1、《深入理解linux内核(第三版)》
2、Hijack Linux System Calls: Part III. System Call Table
[fw]拦截系统调用的更多相关文章
- xenomai内核解析之双核系统调用(一)
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 xenomai 内核系统调用 一.32位Lin ...
- Hook android系统调用研究(一)
本文的博客链接:http://blog.csdn.net/qq1084283172/article/details/55657300 一.Android内核源码的编译环境 系统环境:Ubuntu 14 ...
- hook Android系统调用的乐趣和好处
翻译:myswsun 0x00 前言 Android的内核是逆向工程师的好伙伴.虽然常规的Android应用被限制和沙盒化,逆向工程师可以按自己希望自定义和改变操作系统和内核中行为.这给了你不可多得的 ...
- Linux Rootkit Sample && Rootkit Defenser Analysis
目录 . 引言 . LRK5 Rootkit . knark Rootkit . Suckit(super user control kit) . adore-ng . WNPS . Sample R ...
- linux ptrace I
这几天通过<游戏安全--手游安全技术入门这本书>了解到linux系统中ptrace()这个函数可以实现外挂功能,于是在ubuntu 16.04 x86_64系统上对这个函数进行了学习. 参 ...
- [译] 玩转ptrace (一)
[本文翻译自这里: http://www.linuxjournal.com/article/6100?page=0,0,作者:Pradeep Padaia] 你是否曾经想过怎样才能拦截系统调用?你是否 ...
- 玩转ptrace (一)
转自http://www.cnblogs.com/catch/p/3476280.html [本文翻译自这里: http://www.linuxjournal.com/article/6100?pag ...
- python-Flask模版注入攻击SSTI(python沙盒逃逸)
一篇以python Flask 模版渲染为例子的SSTI注入教学~ 0x01 Flask使用和渲染 这里简化了flask使用和渲染的教程 只把在安全中我们需要关注的部分写出来 来一段最简单的FLASK ...
- linux ptrace I【转】
转自:https://www.cnblogs.com/mmmmar/p/6040325.html 这几天通过<游戏安全——手游安全技术入门这本书>了解到linux系统中ptrace()这个 ...
随机推荐
- 详解webpack4打包--新手入门(填坑)
注意,这个dev和build好像在哪儿见过??对了, 刚刚才在package.json里配置的“scripts”这一项的值就有“dev”和“build”.对,一点都不错,就是这2个值,这2个值代表的是 ...
- nginx中break和last的区别
一.环境准备 资源文件创建 mkdir -p /opt/tmp/wqy/test/aaa mkdir -p /opt/tmp/wqy/test/bbb echo "aaa" > ...
- windows下数字以2进制打印
#include <cstdlib> _itoa(num, buf, 2); 打印buf既是二进制
- 【LeetCode】二叉查找树 binary search tree(共14题)
链接:https://leetcode.com/tag/binary-search-tree/ [220]Contains Duplicate III (2019年4月20日) (好题) Given ...
- git clone的低级错误
犯了一个低级错误: server ip: 192.168.40.41 有一个git账户 所有的git仓库都在/home/git仓库下 比如/home/git/u-boot-2018.07-fmxx.g ...
- ThreadPoolExecutor线程池原理
参考: https://www.cnblogs.com/liuzhihu/p/8177371.html
- luogu4061 大吉大利,晚上吃鸡!
链接 最短路径\(dag\),一道好题. 题目大意:求一张图中满足下列要求的点对\((i,j)\)数量: 所有最短路径必定会经过 \(i\) 点和 \(j\) 点中的任意一点. 不存在一条最短路同时经 ...
- 转Serial,Parallel,CMS,G1四大GC收集器特点小结
转 https://blog.csdn.net/u013812939/article/details/48782343 1.Serial收集器 一个单线程的收集器,在进行垃圾收集时候,必须暂停其他所有 ...
- DataFrame.loc的区间
df.loc[dates[0:1],'E']和df.loc[dates[0]:dates[1],'E']不同. 前者不包含dates[1],后者是包含dates[1]的. 根据Python3中实际代码 ...
- centos上部署flask项目之环境配置-MySQL的安装
1.添加mysql 的yum源 wget 'https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm' rpm ...