두 줄 코드는 프로세스가 top에 표시되는 것을 숨깁니다
두 줄의 코드는 무엇을 할 수 있습니까?프로세스가 top에 표시되는 것을 숨길 수 있지만, 프로세스가 top에 표시되는 것도 숨길 수 있습니다.만약 굳이 말대꾸를 해야 한다면,perf는 폭로할 수 있고,trace는 폭로할 수 있다.... 그것은 분명히 내가 말하고자 하는 점에 get이 없다.
CPU를 순환적으로 소모하는 프로그램을 작성합니다.
int main()
{
while (1) {}
}
그런 다음 그것을 실행하고 top:
top - 18:06:34 up 19:13, 4 users, load average: 0.22, 0.06, 0.06
Tasks: 90 total, 3 running, 87 sleeping, 0 stopped, 0 zombie
%Cpu(s): 99.5 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.5 si, 0.0 st
KiB Mem : 1016860 total, 69464 free, 482116 used, 465280 buff/cache
KiB Swap: 2097148 total, 2055368 free, 41780 used. 317840 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18351 root 20 0 4212 352 280 R 99.9 0.0 0:15.21 a.out
18345 root 20 0 161892 2160 1564 R 0.3 0.2 0:00.01 top
1 root 20 0 51684 1928 1192 S 0.0 0.2 0:07.87 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.53 ksoftirqd/0
a.out의 CPU 활용도에 유의하십시오.
그렇다면 어떻게 가장 간단한 방법으로 그것을 숨길까요?간단합니다.
#!/usr/bin/stap -g
global pid;
probe kernel.function("account_process_tick")
{
if (pid() == pid) {
@cast($p, "struct task_struct")->signal->prev_cputime->utime = 0x3fffffffffffffff;
@cast($p, "struct task_struct")->signal->prev_cputime->stime = 0x3fffffffffffffff;
exit();
}
}
probe begin
{
pid = $1
}
a.out의pid18351을 매개 변수로 실행하고 다시 top:
top - 18:11:33 up 19:18, 4 users, load average: 1.18, 0.76, 0.36
Tasks: 88 total, 3 running, 85 sleeping, 0 stopped, 0 zombie
%Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1016860 total, 286132 free, 283276 used, 447452 buff/cache
KiB Swap: 2097148 total, 2055280 free, 41868 used. 515244 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 51684 1924 1192 S 0.0 0.2 0:07.92 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.54 ksoftirqd/0
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
하하, 없어졌어!
그러나 토탈 usage는 아직 있지만 두 줄 코드가 할 수 있는 것도 그저 그렇다. 코드가 많으면 토탈 usage를 계속 숨길 수 있고 심지어perf 이벤트도 약탈할 수 있다.
내가 말하는 그 두 줄의 코드는 바로 다음과 같다.
@cast($p, "struct task_struct")->signal->prev_cputime->utime = 0x3fffffffffffffff;
@cast($p, "struct task_struct")->signal->prev_cputime->stime = 0x3fffffffffffffff;
왜 그랬을까?
모든 시계가 끊기면, 인터럽트 프로세서가 현재 프로세스의 상태를 판단하고, 이전 시계 주기를current의utime나stime에 기장합니다.
top 명령이 프로세스의 CPU 시간을 가져올 때 cputimeadjust:
static void cputime_adjust(struct task_cputime *curr,
struct cputime *prev,
cputime_t *ut, cputime_t *st)
{
cputime_t rtime, stime, utime;
/*
* Tick based cputime accounting depend on random scheduling
* timeslices of a task to be interrupted or not by the timer.
* Depending on these circumstances, the number of these interrupts
* may be over or under-optimistic, matching the real user and system
* cputime with a variable precision.
*
* Fix this by scaling these tick based values against the total
* runtime accounted by the CFS scheduler.
*/
rtime = nsecs_to_cputime(curr->sum_exec_runtime);
/*
* Update userspace visible utime/stime values only if actual execution
* time is bigger than already exported. Note that can happen, that we
* provided bigger values due to scaling inaccuracy on big numbers.
*/
if (prev->stime + prev->utime >= rtime)
goto out;
...
그 goto out에 주의하세요. 저는 주석을 보고 알았어요. 그래서 이 Trick은 이 조건을 이용했어요.모든 타임은 u64의 유형이고 단위는 나초이다. 즉, 1초에 흐르는 타임 영화는 1000100010001000개이다. 그러나 u64가 표시할 수 있는 숫자는 18446744073709551615이고 대체적으로 10000000000초의 양급이다. 약 317년이다.
즉, 300여 년이 지나야 u64가 돌아갈 수 있기 때문에 저는 prev의 stime와utime의 합을 충분하게 설정하면 OK입니다. 바로 위의 두 줄 코드입니다.
이런 수법은 단번에 잡혀서 놀 수밖에 없어요. 제가 앞에 쓴 Rootkit 수법은 깊이 연구할 수 있어요.
닭똥도 남기지 않고 손으로 때려 정제육구!
절강성 온주는 구두가 젖어서 비가 오면 물에 들어가도 살이 찌지 않는다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.