1 /* @(#) $Id: check_rc_pids.c,v 1.29 2009/06/24 18:53:07 dcid Exp $ */
3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 3) as published by the FSF - Free Software
14 #include "rootcheck.h"
20 /** int proc_read(int pid)
21 * If /proc is mounted, check to see if the pid is present
23 int proc_read(int pid)
25 char dir[OS_SIZE_1024 +1];
30 snprintf(dir, OS_SIZE_1024, "%d", pid);
31 if(isfile_ondir(dir, "/proc"))
39 /** int proc_chdir(int pid)
40 * If /proc is mounted, check to see if the pid is present
42 int proc_chdir(int pid)
45 char curr_dir[OS_SIZE_1024 + 1];
46 char dir[OS_SIZE_1024 + 1];
51 if(!getcwd(curr_dir, OS_SIZE_1024))
56 if(chdir("/proc") == -1)
59 snprintf(dir, OS_SIZE_1024, "/proc/%d", pid);
65 /* Returning to the previous directory */
72 /** int proc_stat(int pid)
73 * If /proc is mounted, check to see if the pid is present there.
75 int proc_stat(int pid)
77 char proc_dir[OS_SIZE_1024 + 1];
82 snprintf(proc_dir, OS_SIZE_1024, "%s/%d", "/proc", pid);
93 /** void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
94 * Check all the available PIDs for hidden stuff.
96 void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
112 char command[OS_SIZE_1024 +1];
118 if((i <= 0)||(i > max_pid))
136 if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
142 if(!((getsid(i) == -1)&&(errno == ESRCH)))
148 if(!((getpgid(i) == -1)&&(errno == ESRCH)))
155 _proc_stat = proc_stat(i);
158 _proc_read = proc_read(i);
161 _proc_chdir = proc_chdir(i);
164 /* IF PID does not exist, keep going */
165 if(!_kill0 && !_gsid0 && !_gpid0 &&
166 !_proc_stat && !_proc_read && !_proc_chdir)
171 /* We do not need to look at our own pid */
177 /* Checking the number of errors */
180 char op_msg[OS_SIZE_1024 +1];
181 snprintf(op_msg,OS_SIZE_1024,"Excessive number of hidden processes"
182 ". It maybe a false-positive or "
183 "something really bad is going on.");
184 notify_rk(ALERT_SYSTEM_CRIT, op_msg);
189 /* checking if process appears on ps */
192 snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1",
196 /* Found PID on ps */
198 if(system(command) == 0)
202 /* If we are being run by the ossec hids, sleep here (no rush) */
207 /* Everyone returned ok */
208 if(_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read)
215 /* If our kill or getsid system call, got the
216 * PID , but ps didn't, we need to find if it was a problem
217 * with a PID being deleted (not used anymore)
220 if(!((getsid(i) == -1)&&(errno == ESRCH)))
225 if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
230 if(!((getpgid(i) == -1)&&(errno == ESRCH)))
236 _proc_stat = proc_stat(i);
238 _proc_read = proc_read(i);
240 _proc_chdir = proc_chdir(i);
242 /* If it matches, process was terminated */
243 if(!_gsid1 &&!_kill1 &&!_gpid1 &&!_proc_stat &&
244 !_proc_read &&!_proc_chdir)
251 /* Ignoring AIX wait and sched programs. */
252 if((_gsid0 == _gsid1) &&
253 (_kill0 == _kill1) &&
254 (_gpid0 == _gpid1) &&
259 /* The wait and sched programs do not respond to kill 0.
260 * So, if everything else finds it, including ps, getpid, getsid,
262 * kill, we can safely ignore on AIX.
263 * A malicious program would specially try to hide from ps..
270 if((_gsid0 == _gsid1)&&
274 /* If kill found, but getsid and getpgid didnt', it may
275 * be a defunct process -- ignore.
277 if(!((_kill0 == 1)&&(_gsid0 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
279 char op_msg[OS_SIZE_1024 +1];
281 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
282 "kill (%d) or getsid (%d). Possible kernel-level"
283 " rootkit.", (int)i, _kill0, _gsid0);
285 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
289 else if((_kill1 != _gsid1)||
293 /* See defunct process comment above. */
294 if(!((_kill1 == 1)&&(_gsid1 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
296 char op_msg[OS_SIZE_1024 +1];
297 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
298 "kill (%d), getsid (%d) or getpgid. Possible "
299 "kernel-level rootkit.", (int)i, _kill1, _gsid1);
301 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
305 else if((_proc_read != _proc_stat)||
306 (_proc_read != _proc_chdir)||
307 (_proc_stat != _kill1))
309 /* checking if the pid is a thread (not showing on proc */
310 if(!noproc && !check_rc_readproc((int)i))
312 char op_msg[OS_SIZE_1024 +1];
313 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
314 "/proc. Possible kernel level rootkit.", (int)i);
315 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
319 else if(_gsid1 && _kill1 && !_ps0)
321 /* checking if the pid is a thread (not showing on ps */
322 if(!check_rc_readproc((int)i))
324 char op_msg[OS_SIZE_1024 +1];
325 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
326 "ps. Possible trojaned version installed.",
329 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
337 /* check_rc_sys: v0.1
338 * Scan the whole filesystem looking for possible issues
345 char ps[OS_SIZE_1024 +1];
347 char proc_0[] = "/proc";
348 char proc_1[] = "/proc/1";
350 pid_t max_pid = MAX_PID;
354 /* Checking where ps is */
355 memset(ps, '\0', OS_SIZE_1024 +1);
356 strncpy(ps, "/bin/ps", OS_SIZE_1024);
359 strncpy(ps, "/usr/bin/ps", OS_SIZE_1024);
365 /* Proc is mounted */
366 if(is_file(proc_0) && is_file(proc_1))
371 loop_all_pids(ps, max_pid, &_errors, &_total);
375 char op_msg[OS_SIZE_1024 +1];
376 snprintf(op_msg, OS_SIZE_1024, "No hidden process by Kernel-level "
377 "rootkits.\n %s is not trojaned. "
378 "Analyzed %d processes.", ps, _total);
379 notify_rk(ALERT_OK, op_msg);