Linux hook系统调用使你文件无法删除

news2024/11/27 8:40:55

文章目录

  • 前言
  • 一、什么是hook技术
  • 二、Linux hook种类
  • 三、系统调用表hook
    • 3.1 查看删除文件用到系统调用
    • 3.2 获取系统调用函数
    • 3.3 编写hook函数
    • 3.4 替换hook函数
    • 3.5 测试
  • 参考资料

前言

hook技术在Linux系统安全领域有着广泛的应用,例如通过hook技术可以劫持删除文件的系统调用,从而使用户无法删除特定文件,也可以实现对系统网络,文件,进程等的监控。

一、什么是hook技术

hook技术即钩子函数,钩子的本质是一段用以处理系统消息的程序,。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息(如屏幕取词,监视日志,截获键盘/鼠标输入等),也可以不作处理而继续传递该消息,还可以强制结束消息的传递。也即这项技术就是提供了一个入口,能够针对不同的消息或者API在执行前,先执行你的操作,你的操作也称为[钩子函数]

二、Linux hook种类

三、系统调用表hook

相信大家对某些无法删除的流氓软件都有深刻的印象,下面我们通过一个系统调用表hook来实现该功能。
试验环境:centos,x86,3.10+内核

3.1 查看删除文件用到系统调用

使用strace跟踪文件删除系统调用

strace -o 1.txt rm test

查看输出结果

cat 1.txt

execve("/usr/bin/rm", ["rm", "test"], 0x7ffc8101c548 /* 24 vars */) = 0
brk(NULL)                               = 0xa0f000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ae12a4000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=87988, ...}) = 0
mmap(NULL, 87988, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0ae128e000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`&\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2156592, ...}) = 0
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0ae0cb6000
mprotect(0x7f0ae0e7a000, 2093056, PROT_NONE) = 0
mmap(0x7f0ae1079000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f0ae1079000
mmap(0x7f0ae107f000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0ae107f000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ae128d000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0ae128b000
arch_prctl(ARCH_SET_FS, 0x7f0ae128b740) = 0
access("/etc/sysconfig/strcasecmp-nonascii", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/sysconfig/strcasecmp-nonascii", F_OK) = -1 ENOENT (No such file or directory)
mprotect(0x7f0ae1079000, 16384, PROT_READ) = 0
mprotect(0x60d000, 4096, PROT_READ)     = 0
mprotect(0x7f0ae12a5000, 4096, PROT_READ) = 0
munmap(0x7f0ae128e000, 87988)           = 0
brk(NULL)                               = 0xa0f000
brk(0xa30000)                           = 0xa30000
brk(NULL)                               = 0xa30000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106172832, ...}) = 0
mmap(NULL, 106172832, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0ada774000
close(3)                                = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "test", {st_mode=S_IFREG|0644, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 0
unlinkat(AT_FDCWD, "test", 0)           = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

从上述内容中我们不难看出用户使用rm命令删除文件时,最终是调用了unlinkat实现的删除操作。

3.2 获取系统调用函数

打开内核源码在线阅读网站,搜索sys_unlinkat(系统调用函数一般是sys_*的格式,在搜索时需要添加前缀)

include/linux/syscalls.h文件中找到函数的定义(主要是看一下参数列表)。

在这里插入图片描述

下面我们在系统调用表中找到这个函数的地址,获取它的函数指针。

unsigned long (*orig_unlinkat)(int dfd, const char __user * pathname, int flag);

unsigned long *sys_call_table = NULL;
sys_call_table = (unsigned long *)kallsyms_lookup_name("sys_call_table");
if(sys_call_table == NULL) {
	printk("%s: can not find sys_call_table address\n", __func__);
	return -1;
}
printk("%s: sys_call_addr = 0x%p\n", __func__, sys_call_table);
orig_unlinkat = sys_call_table[__NR_unlinkat];
printk("%s: _NR_unlinkat = 0x%p\n", __func__, orig_unlinkat);

3.3 编写hook函数

这里我们定义一个hook函数,当文件名称等于"test"返回错误,否则调用unlinkat函数。
这里有2点需要注意:

  • hook函数参数列表必须和原函数完全一致;
  • 在内核空间中无法直接访问用户空间地址的数据,如果要在hook函数中读取参数的值,需要借助copy_from_user先将数据拷贝到内核空间;
asmlinkage long hook_unlinkat(int dfd, const char __user * pathname, int flag)
{
    char *filename;
    long ret;

    // Allocate memory to store the filename
    filename = (char *)kmalloc(PATH_MAX, GFP_KERNEL);
    if (!filename)
        return -ENOMEM;

    // Copy the pathname from userspace to kernelspace
    if (copy_from_user(filename, pathname, PATH_MAX)) {
        kfree(filename);
        return -EFAULT;
    }

    // Check if the filename is the one we want to block
    if (strcmp(filename, TARGET_FILENAME) == 0) {
        printk(KERN_INFO "Attempt to delete %s blocked\n", TARGET_FILENAME);
        kfree(filename);
        return -EPERM; // Permission denied
    }

    // Call the original unlink syscall
    ret = orig_unlinkat(dfd, pathname, flag);

    kfree(filename);

    return ret;
}

3.4 替换hook函数

这里只需要将系统调用表中__NR_unlinkat表项存储的地址替换为我们自己定义的hook函数地址即可。
替换后在用户在使用unlinkat系统调用时会走到我们的hook函数中,经过hook函数处理之后才原来的系统调用函数。
需要注意的是,系统调用表位于内核代码段,在修改系统调用表之前需要先将页表属性修改为可写。

/* make the page writable */
int make_rw(unsigned long address)
{
    unsigned int level;
    pte_t *pte = lookup_address(address, &level); //查找虚拟地址所在的页表地址
    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;
}

make_rw((unsigned long)sys_call_table); //修改页属性
sys_call_table[__NR_unlinkat] = (unsigned long *)hook_unlinkat; //设置新的系统调用地址
make_ro((unsigned long)sys_call_table);

3.5 测试

加载编译好的内核模块,测试删除test文件
在这里插入图片描述
可以看到在加载了我们编译的模块之后,已经无法删除test文件,这里只是一个示例,通过修改hook函数我们可以实现更多的功能。

参考资料

  1. hook原理介绍与简单实例
  2. Linux hook 机制
  3. Hooking linux内核函数(一):寻找完美解决方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1530606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Regex正则表达式 --java学习笔记

正则表达式 由一些特定字符组成,代表的是一个规则作用一:校验数据格式是否合法作用二:在一段文本中查找满足要求的内容 String提供了一个匹配正则表达式的方法 public boolean matches(String regex(正则表达式&…

高校|政务|医院|集团等网站站群建设要怎么做

网站站群集约化系统,建立统一部署、统一标准、统一规范、统一管理、统一安全体系、支持移动终端访问的“门户网站群”,建设以高校/集团/医院/门户网站为主站,以部门、院系、子公司及其应用为基础支撑的若干子站,形成若干主站子站以…

python3入门机器学习,知识点全面总结与代码实操示例

目录 写在前面的话 一、机器学习的基本任务与方法分类 机器学习的概念和定义 基本任务 二分类任务(Binary Classification): 多分类任务(Multi-class Classification): 多标签分类任务(Mu…

第二证券股市指南:如何看懂股票的量价关系?

股票成交量是指生意日当天个股成交的股数,股票成交量越大,说明当天股票生意比较生动,商场上的流动资金增加,股票后期上涨的或许性加大。成交量越小,说明个股当天生意比较低迷,缺少出资者的注重。所以一般情…

室友打团太吵?一条命令断掉它的WiFi

「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:更多干货,请关注专栏《网络安全自学教程》 ARP欺骗原理 1、arpspoof实现ARP欺骗1.1、主机探测1.2、欺骗…

【WEB3安全基建项目Secwarex】空投指南

GoPlusSecurity是WEB3安全基建项目,3月8日完成400万美元的私募融资,目前总融资已经高达1500万美元,其中包括Binance Labs、Huobi Incubator、Kucoin Ventures、Avalanche等知名机构参投。 1、打开网址:secwarex.io,点…

Gin框架 源码解析

https://zhuanlan.zhihu.com/p/136253346 https://www.cnblogs.com/randysun/category/2071204.html 这个博客里其他go的内容也讲的很好 启动 因为 gin 的安装教程已经到处都有了,所以这里省略如何安装, 建议直接去 github 官方地址的 README 中浏览安装…

QT 驾校系统界面布局编写

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);this->resize(ui->label_img->width(),ui->label_img->height());//图片自适应窗口大小ui->label_img->setScaledContents(true);//图片置…

sora笔记(三):diffusion transformer模型的发展历程

:::info 💡 在sora笔记(一):sora前世今生与技术梗概 一文中介绍了目前未开源的sora模型可能涉及到的技术点,包括介绍了Vision Transformer,作为transformer正式用于图像的一种范式,为本文中将提…

慧海科创再探潮间带|全面调研推动梭子蟹产业进步

浙江的海岸线延绵,孕育了丰富的海洋生物多样性。在这样的背景下,慧海科创团队沿着宁波至舟山的潮间带开展了全面的调研活动。2024年3月15日,浙江海洋大学、宁波大学、上海理工大学的梭子蟹智能捆扎实践团队,深入海岸一线,与当地养殖户交流产业发展中的痛点难点,共同探讨梭子蟹产…

Java 多线程线程池分析

[1]前言 关于Java多线程的知识,看了很多博客书籍,对理论还是比较了解的。但是,最近写一个很简单的使用线程池对列表中任务进行处理,然后返回结果列表的功能,发现理论和实际操作还是有相当大的差距。 首先贴出一个很简…

适用于 Windows 2024 的 7 个最佳免费分区恢复软件分享

无法确定 2024 年 Windows 上最好的免费分区恢复软件是什么?那么,我们可以提供帮助!我们测试了目前市场上可用的几种硬盘分区恢复软件 - 包括免费和付费版本。您现在所需要的只是 - 只需浏览列表并选择适合您要求的一项即可。继续阅读&#x…

ARM Cortex-R82处理器在压缩SSD场景的应用

ScaleFlux公司宣布在其下一代企业级SSD控制器产品线中采用Arm公司的Cortex-R82处理器。这一决策旨在应对企业环境中对高带宽存储解决方案日益增长的需求,并通过提升数据传输速度和效率来满足市场期待。 Arm Cortex-R82处理器是Arm公司迄今为止性能最强的实时处理器…

107 在携带请求体的情况下, hutool 将 get 请求转换为了 post 请求

前言 本问题主要是来自于同事 情况大致如下, 同样的代码 一个是测试用例, 一个是生产环境的应用, 访问同一个第三方服务, 参数什么的完全一致 但是 出现的问题就是 测试用例能够拿到正确的对方的响应, 但是 生产环境的应用 却是拿到的对方的报错 然后 我开始以为是 是否…

通过rmi实现远程rpc(可以认为java自带Dubbo RPC)

背景: 发现公司几个运行10年的游戏,用的竟然是rmi,而我只听说过dubbo 和 基于netty的rpc,于是就补充了下rmi。 其次,是最近对于跨服的思考,如何避免回调也需要用同步写法,rmi比较适合。 1)api…

算法笔记p251队列循环队列

目录 队列循环队列循环队列的定义初始化判空判满入队出队获取队列内元素的个数取队首元素取队尾元素 队列 队列是一种先进先出的数据结构,总是从队尾加入元素,从队首移除元素,满足先进先出的原则。队列的常用操作包括获取队列内元素的个数&a…

2023年蓝桥杯模拟省赛——列名

目录 题目链接:2.列名 - 蓝桥云课 (lanqiao.cn) 思路 高级思路:进制转换 难点一 难点二 难点三 总结 题目链接:2.列名 - 蓝桥云课 (lanqiao.cn) 思路 先来看我的暴力的思路吧 主要有以下步骤: 初始化一个长度为3的数组res用…

图像分割之k-means聚类分割

文章目录 k-means聚类原理k-means基本思路聚类效果评估k-means聚类算法流程MATLAB实现测试结果参考文献 k-means聚类原理 k-means聚类是一种无监督学习的聚类算法,它的目的是将数据集中的样本划分成若干个类别,使得同一类别内的样本相似度高&#xff0c…

Java:类和对象

目录 1.面对对象的初步认识1.1 什么是面向对象?(Java当中一切皆为对象)1.2 面对对象与面对过程 2.类的定义和使用2.1简单认识类2.2 类的定义格式 3.类的实例化3.1 什么是实例化3.2类和对象的说明 4.this引用4.1为什么要使用this引用4.2 什么是…

集合系列(十) -Set接口详解

一、摘要 关于 Set 接口,在实际开发中,其实很少用到,但是如果你出去面试,它可能依然是一个绕不开的话题。 言归正传,废话咱们也不多说了,相信使用过 Set 集合类的朋友都知道,Set集合的特点主要有…