Linux hook系统调用read

前面的文章有聊到怎么拿到linux sys_call_table,高版本和低版本内核都有对应的方式,那么这篇文章讲怎么去hook Linux 系统调用,建议在虚拟机中尝试,此篇文章内核如下所示:

curtis@curtis-virtual-machine:~/Desktop/test$ uname -a
Linux curtis-virtual-machine 4.2.0-42-generic #49~14.04.1-Ubuntu SMP Wed Jun 29 20:22:11 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

代码:hook_read.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <asm/paravirt.h>

unsigned long **sys_call_table;
unsigned long original_cr0;

asmlinkage long (*ref_sys_read)(unsigned int fd, char __user *buf, size_t count);
asmlinkage long new_sys_read(unsigned int fd, char __user *buf, size_t count)
{
	/*do everything what you want*/
	printk("sys_read has benn hook!\n");
	return ref_sys_read(fd, buf, count);
}

//set a page writeable
int make_rw(unsigned long address)
{
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    pte->pte |= _PAGE_RW;
    return 0;
}
 
//set a page read only
int make_ro(unsigned long address)
{ 
    unsigned int level;
    pte_t *pte = lookup_address(address, &level);
    pte->pte = pte->pte & ~_PAGE_RW;
    return 0;
}


//Consider race condition on SMP systems.
void
disable_wp(void)
{
    unsigned long cr0;

    preempt_disable();
    cr0 = read_cr0();
    clear_bit(X86_CR0_WP_BIT, &cr0);
    write_cr0(cr0);
    preempt_enable();

    return;
}

//Consider race condition on SMP systems.
void
enable_wp(void)
{
    unsigned long cr0;

    preempt_disable();
    cr0 = read_cr0();
    set_bit(X86_CR0_WP_BIT, &cr0);
    write_cr0(cr0);
    preempt_enable();

    return;
}

//find sys_call_table address
static unsigned long **acquire_sys_call_table(void)
{
    unsigned long int offset = (unsigned long int) sys_close;
    unsigned long **sct;
    
    printk(KERN_INFO "finding syscall table from: %p\n", (void*)offset);

    while (offset < ULLONG_MAX)
    {
    	sct = (unsigned long **)offset;

    	if (sct[__NR_close] == (unsigned long *)sys_close)
        {
            printk(KERN_INFO "sys call table found: %p\n", (void*)sct);
    		return sct;
        }
    	offset += sizeof(void *);
    }

    return NULL;
}


static int __init read_hook_start(void) 
{
	if(!(sys_call_table = acquire_sys_call_table()))
		return -1;
	printk("sysc_call_table address:%p\n",(void *)sys_call_table);	
//	original_cr0 = read_cr0();
	printk("cr0 value is:0x%ld\n",read_cr0());
//	disable_wp();
//	write_cr0(original_cr0 & ~0x000100000);
	make_rw((long unsigned int)sys_call_table);
	ref_sys_read = (void *)sys_call_table[__NR_read];
	printk("sys_open address is :%p\n",ref_sys_read);
	sys_call_table[__NR_read] = (unsigned long *)new_sys_read;
	printk("Nes sys_open address is :%p\n",(void*)sys_call_table[__NR_read]);
	make_ro((long unsigned int)sys_call_table);
//	write_cr0(original_cr0);
//	enable_wp();
	
	return 0;
}

static void __exit read_hook_end(void) 
{
	if(!sys_call_table) {
		return;
	}

//	disable_wp();	
//	write_cr0(original_cr0 & ~0x00010000);
	make_rw((long unsigned int)sys_call_table);
	sys_call_table[__NR_read] = (unsigned long *)ref_sys_read;
	make_ro((long unsigned int)sys_call_table);
//	write_cr0(original_cr0);
//	enable_wp();
	
	printk("Bye bye test!\n");
}

module_init(read_hook_start);
module_exit(read_hook_end);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Curtis li");

Makefile:

obj-m :=hook_read.o
KERNEL := /lib/modules/$(shell uname -r)/build
 
all:
	make -C $(KERNEL) M=$(shell pwd) modules
install:
	make -C $(KERNEL) M=$(shell pwd) modules_install
	depmod -A
clean:
	make -C $(KERNEL) M=$(shell pwd) clean

简要代码分析:
初始化函数通过以sys_close为基址遍历内存找到sys_call_table地址,拿到地址后,需要解决的是内核内存写保护的问题,代码中分别给到三种方法来关闭内存的写保护,实际上是两种,一种是改pte参数,一种是修改cr0寄存器的值(两种方法实现),先要定义好open的原始函数和open_hook函数,在open_hook函数中可以做自己想做的事情,但是一定要记得返回到原始open函数入口地址。
效果展示:

[  584.867416] sys_read has benn hook!
[  584.867416] sys_read has benn hook!
[  584.867417] sys_read has benn hook!
[  584.867418] sys_read has benn hook!
[  584.867418] sys_read has benn hook!
[  584.868939] sys_read has benn hook!
[  584.868951] sys_read has benn hook!
[  584.869104] sys_read has benn hook!
[  584.869259] sys_read has benn hook!
[  584.869261] sys_read has benn hook!
[  584.869277] sys_read has benn hook!
[  584.869279] sys_read has benn hook!
[  584.869288] sys_read has benn hook!
[  584.869289] sys_read has benn hook!
[  584.869294] Bye bye test!

open函数被成功Hook住,此文章介绍的是低内核版本的open_hook,高版本获取sys_call_table的值方式不一样,可以参考之前文章!!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Linux Hook 系统调用是指在 Linux 操作系统中,通过修改系统调用表来拦截和修改系统调用的行为。这种技术可以用于实现各种功能,如监控系统调用、实现安全策略、实现虚拟化等。Hook 系统调用的实现方式有多种,如使用内核模块、使用 LD_PRELOAD 环境变量、使用 ptrace 等。但是,Hook 系统调用也可能会带来一些安全风险,因此需要谨慎使用。 ### 回答2: Linux系统中的hook是一种通过修改系统内核来实现对系统或应用程序行为的改变的技术手段。hook技术的实现方式有很多种,比如LD_PRELOAD,在程序运行前拦截系统调用,重定向到用户编写的函数中,实现对系统调用进行Hook;也可以修改内核源代码,在内核中添加对指定系统调用Hook函数,并重新编译部署内核。 在Linux系统中,Hook技术被广泛运用于安全防护、性能优化、监控记录等领域。安全防护方面,通过Hook技术可以拦截进程的系统调用,实现对安全攻击的检测和防范;在性能优化方面,Hook技术可以记录系统资源使用情况,进行优化分析;在监控记录方面,Hook技术可以通过修改系统调用返回值,实现对应用程序的状态监控和记录等功能。 Hook技术的实现需要一定的计算机专业知识和技能,同时也需要了解目标系统的内部运行机制和系统调用的使用方法。在使用时需要注意,Hook技术对系统稳定性和性能会产生影响,需要谨慎使用和调试。同时,在使用Hook技术时需要考虑到实现方式的兼容性、对日后维护的影响等问题,从而保证Hook技术的稳健性和长期有效性。 综上所述,在Linux系统中,Hook技术是一种应用广泛、有效性高的技术手段,可以实现对系统和应用程序行为的灵活定制和改变,通过对系统调用的拦截和修改,实现安全防护、性能优化、监控记录等多种功能。不过,在使用时需要注意风险和影响,选择合适的实现方式,从而确保Hook技术的有效性和稳健性。 ### 回答3: Linux 系统调用是操作系统的一个重要组成部分,它提供了应用程序与操作系统之间通信的桥梁,使得应用程序可以利用操作系统的功能进行各种操作。然而,在某些情况下,用户可能需要修改某些系统调用的行为或者监控它们的使用情况,这就需要使用 Linux hook 系统调用Linux hook 系统调用,也称为系统调用钩子,是一种在系统调用进行时拦截和修改系统调用的技术。其主要作用是通过程序实现拦截和修改系统调用的行为,以达到特定的目的。比如,通过修改文件访问系统调用的行为,可以对文件进行加密、解密和防止恶意软件操作等。 Linux hook 系统调用的实现方式有很多种,其中最常见的方式就是使用内核模块实现。内核模块是一种动态加载到内核中的代码,可以通过内核提供的对模块的管理函数进行加载、卸载和修改等操作。利用内核模块,可以实现对指定系统调用的拦截与修改,具体实现方法是通过在模块中添加指定系统调用的替代函数来实现。 除此之外,还可以使用 LD_PRELOAD 环境变量或者 ptrace 系统调用来实现 Linux hook 系统调用。其中,LD_PRELOAD 环境变量是一种可以动态加载库文件的方法,通过在 LD_PRELOAD 中指定某个库文件,可以在程序运行时优先加载该库文件,从而实现对系统调用的拦截;而 ptrace 系统调用则是一种常用的系统调用监控方法,可以用来检测系统调用调用次数、参数和返回结果等信息。 总体来说,Linux hook 系统调用是一种非常实用的技术,可以用来实现各种监控和安全保障功能。但是,在使用时需要注意保证系统的稳定性和安全性,避免出现非预期的系统崩溃或安全漏洞。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值