Linux 函数调用劫持的方法总结(带图)

零、概述

  • Ring3中劫持

    1. 基于环境变量 LD_PRELOAD 的动态库劫持。
  • Ring0中劫持

    1. Kernel Inline Hook

    2. syscall table 修改

    3. 内核调试机制 Kprobe

一、Ring3 函数调用劫持

在 Linux 中,动态库加载的时候,会按照以下顺序进行搜索:

LD_PRELOAD > LD_LIBRARY_PATH > /etc/ld.so.cache > /lib > /usr/lib

方法原理:通过 LD_PERELOAD 定义在程序运行前优先加载的动态链接库为自己编写的动态库。

例子:劫持 gets() 函数

#include<stdio.h>
#include<dlfcn.h> //用于搜索原函数

/* 要求:函数的形式必须和原函数一样(返回类型,函数名,函数参数)*/
char* gets(char* str){
    
    /* 自定义的操作区域 */
    printf("hook gets! str: %s\n ",str);
    
    /* 调用原函数*/
    typeof(gets)  *func;//函数指针
    func=dlsym(RTLD_NEXT,"gets");//查找 gets 函数位置  dlsym:在打开的动态库里找一个函数
    return (*func)(str); //调用原函数执行
}

gcc hook.c -fPIC -shared -ldl -D_GNU_SOURCE -o hook.so 

设置 LD_PRELOAD 

通过设置环境变量的方法

  1. 临时设置 export LD_PRELOAD=$PWD/hook.so
  2. 永久设置
  • 修改 profile 文件 加入 export LD_PRELOAD=${YOUR PATH}/hook.so
  • 修改 .bashrc 文件 加入 export LD_PRELOAD=${YOUR PATH}/hook.so

编写一个测试程序 test.c 

#include <stdio.h>

int main(){
    char str[20]="\0";
    printf("请输入\n");
    gets(str);
    return 0;
}

函数调用劫持效果 

二、Ring0 系统调用劫持

2.1、Kernel Inline Hook

原理:一个系统调用会调用子函数的,这是通过段内偏移的方式完成的,我们可以通过设置这个偏移指向我们 Hook 的原函数

例子:劫持 sys_read 系统调用

2.2、sys_call_table 修改方法进行系统调用劫持

原理:将系统调用表中对应的服务例程修改为自己 Hook 函数的地址

例子:劫持 fork()

查找 syscall_table 位置的方法

  • 代码模拟出 call *sys_call_table(,%eax,4),然后查看机器码查找。
  • 通过 /boot/System.map-2.6.32-358.el6.i686 文件查找。
  • 通过 /proc/kallsyms 进行搜索。

2.3、内核调试机制 kprobe 进行系统调用劫持

(1)Kprobe介绍

轻量级内核调试机制

(2)Kprobe两种使用方法

模块加载

debugfs接口

(3)Kprobe三种探测手段

kprobe 基本的探测手段 基础 可以在函数内任意位置放置探测点

jprobe 探测在函数的入口,可以方便的获得函数参数,但是每个函数只能有一个探针

Kretprobe 探测在函数的返回值

例子:劫持 execve()


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>

int jsys_execve(const char __user *filename,
		const char __user *const __user *__argv,
		const char __user *const __user *__envp)
{
  	pr_info("jprobe: execve: %s\n", filename);

	/* Always end with a call to jprobe_return(). */
  	jprobe_return();
  	return 0;
}

static struct jprobe jprobe_execve = {
	.entry= jsys_execve,
	.kp = {
		.symbol_name	= "sys_execve",
	},
};

static int __init mymodule_init(void){
    int ret;

	/* 挂载 hook */
	ret = register_jprobe(&jprobe_execve);
	if (ret < 0) {
		pr_info("register_jprobe failed, returned %d\n", ret);
		return -1;
	}
	pr_info("Planted jprobe execve at %p, handler addr %p\n",
	       jprobe_execve.kp.addr, jprobe_execve.entry);
    
    return 0;
}

static void __exit mymodule_exit(void)
{
	unregister_jprobe(&jprobe_execve);
}


module_init(mymodule_init)
module_exit(mymodule_exit)
MODULE_LICENSE("GPL");

 

 

转载:Linux函数调用劫持的方法总结(带图)_HTmonster的博客-CSDN博客_linux系统调用劫持

(SAW:Game Over!)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值