Linux函数调用劫持方法
Posted 造夢先森
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux函数调用劫持方法相关的知识,希望对你有一定的参考价值。
- Ring3中劫持:
1,基于环境变量LD_PRELOAD的动态库劫持 - Ring0中劫持:
1,Kernel Inline Hook
2,syscall table修改
3,内核调试机制Kprobe
基于环境变量LD_PRELOAD的动态库劫持
在Linux中,动态库加载的时候,会按照以下顺序进行搜索:LD_PRELOAD >LD_LIBRARY_PATH >/etc/ld.so.cache>/lib>/usr/lib
方法原理:通过LD_PERELOAD设置编写自己的so库函数在原正常函数前执行
例子:劫持fputs()函数
整个调用过程如下:
编写自定义的动态链接库源码hook.c:
#include<stdio.h>
#include<dlfcn.h> //用于搜索原函数
/* 要求:函数的形式必须和原函数一样(返回类型,函数名,函数参数)*/
int fputs(const char*s, FILE *stream)
/* 自定义的操作区域 */
printf("hook puts! str: ");
/* 调用原函数*/
typeof(fputs) *func;//函数指针
func=dlsym(RTLD_NEXT,"fputs");//查找fputs函数位置 dlsym:在打开的动态库里找一个函数
return (*func)(s, stream); //调用原函数执行
编译成共享库:
gcc hook.c -fPIC -shared -ldl -D_GNU_SOURCE -o hook.so
- -fPIC: 编译器就输出位置无关目标码.适用于动态连接
- -shared: 生成共享目标文件
3.设置LD_PRELOAD
通过设置环境变量的方法
临时设置: export LD_PRELOAD=$YOUR PATH/hook.so
取消:unset LD_PRELOAD
永久设置:
修改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("input:");
fgets(str, 20, stdin);
printf("output:");
fputs(str, stdout);
return 0;
测试结果 :
# ./a.out
input:123
output:123
# export LD_PRELOAD=/root/hook.so
# ./a.out
input:123
output:hook puts! str: 123
内核调试机制kprobe进行系统调用劫持
- Kprobe介绍
轻量级内核调试机制 - Kprobe两种使用方法
模块加载
debugfs接口 - Kprobe三种探测手段
kprobe 基本的探测手段 基础 可以在函数内任意位置放置探测点
jprobe 探测在函数的入口,可以方便的获得函数参数,但是每个函数只能有一个探针
Kretprobe 探测在函数的返回值 - 例子:劫持execve()
hook.c:
#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");
Makefile:
KO_NAME:= # 传入生成的ko文件的名字
PWD=$(shell pwd) # Makefile文件所在目录
KDIR:=/lib/modules/$(shell uname -r)/build
obj-m:=$(KO_NAME).o
$(KO_NAME)module-objs:=$(KO_NAME).o # 此处.o文件的名字必须与源码的.c文件保持一致
MAKE:=make
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) EXTRA_CLFAGS+="" modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
编译ko:
make KO_NAME="hook"
参考:https://blog.csdn.net/weixin_38371073/article/details/106235404
以上是关于Linux函数调用劫持方法的主要内容,如果未能解决你的问题,请参考以下文章