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

文章目录

  • 前言
  • 一、什么是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内核函数(一):寻找完美解决方案

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

xilinx的高速接口构成原理和连接结构

本文来源: V3学院 尤老师的培训班笔记【高速收发器】xilinx高速收发器学习记录Xilinx-7Series-FPGA高速收发器使用学习—概述与参考时钟GT Transceiver的总体架构梳理 文章目录 一、概述:二、高速收发器结构:2.1 QUAD2.1.1 时钟2.1.2 CHANNEL…

pytest之fixture结合conftest.py文件使用+断言实战

pytest之fixture结合conftest.py文件使用 conftest.py--存放固件固件的优先级pytest执行流程pytest之断言实战pytest结合allure-pytest插件生成美观的报告 conftest.py–存放固件 在一个项目的测试中,大多数情况下会有多个类、模块、或者包要使用相同的测试夹具。这…

【Node.js】全局变量和全局 API

node 环境中没有 dom 和 bom ,此外 es 基本上都是可以正常使用的。 如果一定要使用 dom 和bom,可以借助第三方库 jsdom 帮助我们实现操作。npm i jsdom 实例: const fs require(node:fs) const {JSDOM} require(jsdom)const dom new JS…

命令执行漏洞

绕过技巧&#xff1a; cat 233.txt # 管道符号绕过 # 空格绕过 ${IFS} # %0a、%09 # 重定向绕过 < <> # 变量拼接绕过 kali:$ ac;bat;cfl;dag;$a$b $c$d # 单引号、双引号绕过 cat flag cat"" flag # 编码绕过 $(printf "\x63\x61\x74\x20\x2f\x…

前端学习之css 定位与浮动

定位 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>定位和浮动</title><style>*{/* 将模块紧紧贴着浏览器边框 */margin: 0;}.c{background-color: blueviolet;width: 100px;height: 1…

长安链团队论文入选国际顶会Usenix Security 2024

零知识证明是区块链扩容和隐私保护的关键前沿技术&#xff0c;其天然具备完备性、可靠性和零知识性的特点&#xff0c;是提升区块链交易吞吐量与可扩展性、在验证用户身份的同时保护用户数据隐私&#xff0c;实现复杂计算不可或缺的关键技术。基于零知识证明技术实现高兼容性、…

鸿蒙Harmony应用开发—ArkTS-像素单位

ArkUI为开发者提供4种像素单位&#xff0c;框架采用vp为基准数据单位。 说明&#xff1a; 本模块首批接口从API version 7开始支持&#xff0c;后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 名称描述px屏幕物理像素单位。vp屏幕密度相关像素&#xff0c;…

【机器学习】决策树学习下篇(详解)

引言 在当今数据驱动的时代&#xff0c;机器学习技术已成为解决复杂问题不可或缺的工具。其中&#xff0c;决策树学习作为一种基础且强大的算法&#xff0c;广泛应用于各种领域&#xff0c;包括但不限于金融风控、医疗诊断、客户关系管理等。决策树以其简单直观、易于理解和实…

Java八股文(秒杀)

Java八股文の秒杀 秒杀 秒杀 你对秒杀功能模块的理解是什么&#xff1f;你认为秒杀功能的关键点是什么&#xff1f; ○ 秒杀功能模块是指在一段时间内&#xff0c;将某个商品以非常优惠的价格或特殊活动进行销售&#xff0c;从而吸引大量用户抢购。其关键点是高并发的请求处理…

深层次理解拷贝构造函数

1.1 拷贝构造概念 在现实生活中&#xff0c;可能存在一个与你一样的自己&#xff0c;我们称其为双胞胎。 那在创建对象时&#xff0c;可否创建一个与已存在对象一某一样的新对象呢&#xff1f; 拷贝构造函数&#xff1a;只有单个形参&#xff0c;该形参是对本类类型对象的引…

提面 | 面试抽题

学习到更新日期面试抽题-1.2案例分析的思维本质2024-3-23 1提面抽屉论述问题的分类 1.1案例分析占总论 1.2案例分析的思维本质

权限提升-Windows权限提升篇溢出漏洞土豆家族通杀全系补丁对比EXP筛选

知识点 1、Web到Win-系统提权-土豆家族 2、Web到Win-系统提权-人工操作 章节点&#xff1a; 1、Web权限提升及转移 2、系统权限提升及转移 3、宿主权限提升及转移 4、域控权限提升及转移 基础点 0、为什么我们要学习权限提升转移技术&#xff1a; 简单来说就是达到目的过程…

IMU状态预积分的定义

IMU状态预积分的定义 IMU状态预积分的定义 在ESKF中&#xff0c;将两个GNSS观测之间的IMU数据进行积分&#xff0c;作为ESKF的预测过程。 这种做法把IMU数据看成某种一次性的使用方式&#xff1a;将它们积分到当前估计值上&#xff0c;然后用观测数据更新当时的估计值。 这种…

LeetCode每日一题——统计桌面上的不同数字

统计桌面上的不同数字OJ链接&#xff1a;2549. 统计桌面上的不同数字 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 思路&#xff1a; 这是一个很简单的数学问题&#xff1a; 当n 5时&#xff0c;因为n % 4 1&#xff0c;所以下一天4一定会被放上桌面 当n 4…

Python制作数据可视化大屏

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

springcloud+nacos服务注册与发现

快速开始 | Spring Cloud Alibaba 参考官方快速开始教程写的&#xff0c;主要注意引用的包是否正确。 这里是用的2022.0.0.0-RC2版本的springCloud&#xff0c;所以需要安装jdk21&#xff0c;参考上一个文章自行安装。 nacos-config实现配置中心功能-CSDN博客 将nacos-conf…

vue3对openlayers使用(加高德,天地图图层)

OpenLayers认识 WebGIS四大框架&#xff1a; Leaflet、OpenLayers、Mapbox、Cesium OpenLayers 是一个强大的开源 JavaScript 地图库&#xff0c;专注于提供可嵌入网页的交互式地图体验。作为一款地理信息系统&#xff08;GIS&#xff09;的前端开发工具&#xff0c;OpenLaye…

微软Microsoft Surface Go 2

1个小玩具 Microsoft Surface Go 2的评测结果出炉&#xff01;它是目前最好的中端Windows 二合一笔记本平板。 外形简洁小巧&#xff0c;工作娱乐两不误。 它有多个版本。 我们测试的是配备8GB Ram和128GB SSD的Pentium 4425Y处理器&#xff08;第8代&#xff09;的型号。 S…

OpenCV学习笔记(十一)——利用Sobel算子计算梯度

Sobel算子是基于一阶导数的离散差分算子&#xff0c;其中Sobel对于像素值的变化是十分敏感的&#xff0c;在进行边缘检测的时候&#xff0c;Sobel算子常用于对周围像素的重要性进行检测。 Sobel算子包括检验水平方向的算子和检测竖直方向的算子 计算机梯度值的操作如下&#x…

Dr4g0n

信息收集 # nmap -sn 192.168.56.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-04 08:52 CST Nmap scan report for 192.168.56.2 Host is up (0.00012s latency). MAC Address: 00:50:56:FE:B1:6F (VMware) Nmap scan report …