1 /* @(#) $Id: ./src/rootcheck/check_rc_pids.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
15 #include "rootcheck.h"
21 /** int proc_read(int pid)
22 * If /proc is mounted, check to see if the pid is present
24 int proc_read(int pid)
26 char dir[OS_SIZE_1024 +1];
31 snprintf(dir, OS_SIZE_1024, "%d", pid);
32 if(isfile_ondir(dir, "/proc"))
40 /** int proc_chdir(int pid)
41 * If /proc is mounted, check to see if the pid is present
43 int proc_chdir(int pid)
46 char curr_dir[OS_SIZE_1024 + 1];
47 char dir[OS_SIZE_1024 + 1];
52 if(!getcwd(curr_dir, OS_SIZE_1024))
57 if(chdir("/proc") == -1)
60 snprintf(dir, OS_SIZE_1024, "/proc/%d", pid);
66 /* Returning to the previous directory */
73 /** int proc_stat(int pid)
74 * If /proc is mounted, check to see if the pid is present there.
76 int proc_stat(int pid)
78 char proc_dir[OS_SIZE_1024 + 1];
83 snprintf(proc_dir, OS_SIZE_1024, "%s/%d", "/proc", pid);
94 /** void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
95 * Check all the available PIDs for hidden stuff.
97 void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
113 char command[OS_SIZE_1024 +1];
119 if((i <= 0)||(i > max_pid))
137 if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
143 if(!((getsid(i) == -1)&&(errno == ESRCH)))
149 if(!((getpgid(i) == -1)&&(errno == ESRCH)))
156 _proc_stat = proc_stat(i);
159 _proc_read = proc_read(i);
162 _proc_chdir = proc_chdir(i);
165 /* IF PID does not exist, keep going */
166 if(!_kill0 && !_gsid0 && !_gpid0 &&
167 !_proc_stat && !_proc_read && !_proc_chdir)
172 /* We do not need to look at our own pid */
178 /* Checking the number of errors */
181 char op_msg[OS_SIZE_1024 +1];
182 snprintf(op_msg,OS_SIZE_1024,"Excessive number of hidden processes"
183 ". It maybe a false-positive or "
184 "something really bad is going on.");
185 notify_rk(ALERT_SYSTEM_CRIT, op_msg);
190 /* checking if process appears on ps */
193 snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1",
197 /* Found PID on ps */
199 if(system(command) == 0)
203 /* If we are being run by the ossec hids, sleep here (no rush) */
208 /* Everyone returned ok */
209 if(_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read)
216 /* If our kill or getsid system call, got the
217 * PID , but ps didn't, we need to find if it was a problem
218 * with a PID being deleted (not used anymore)
221 if(!((getsid(i) == -1)&&(errno == ESRCH)))
226 if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
231 if(!((getpgid(i) == -1)&&(errno == ESRCH)))
237 _proc_stat = proc_stat(i);
239 _proc_read = proc_read(i);
241 _proc_chdir = proc_chdir(i);
243 /* If it matches, process was terminated */
244 if(!_gsid1 &&!_kill1 &&!_gpid1 &&!_proc_stat &&
245 !_proc_read &&!_proc_chdir)
252 /* Ignoring AIX wait and sched programs. */
253 if((_gsid0 == _gsid1) &&
254 (_kill0 == _kill1) &&
255 (_gpid0 == _gpid1) &&
260 /* The wait and sched programs do not respond to kill 0.
261 * So, if everything else finds it, including ps, getpid, getsid,
263 * kill, we can safely ignore on AIX.
264 * A malicious program would specially try to hide from ps..
271 if((_gsid0 == _gsid1)&&
275 /* If kill found, but getsid and getpgid didnt', it may
276 * be a defunct process -- ignore.
278 if(!((_kill0 == 1)&&(_gsid0 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
280 char op_msg[OS_SIZE_1024 +1];
282 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
283 "kill (%d) or getsid (%d). Possible kernel-level"
284 " rootkit.", (int)i, _kill0, _gsid0);
286 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
290 else if((_kill1 != _gsid1)||
294 /* See defunct process comment above. */
295 if(!((_kill1 == 1)&&(_gsid1 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
297 char op_msg[OS_SIZE_1024 +1];
298 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
299 "kill (%d), getsid (%d) or getpgid. Possible "
300 "kernel-level rootkit.", (int)i, _kill1, _gsid1);
302 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
306 else if((_proc_read != _proc_stat)||
307 (_proc_read != _proc_chdir)||
308 (_proc_stat != _kill1))
310 /* checking if the pid is a thread (not showing on proc */
311 if(!noproc && !check_rc_readproc((int)i))
313 char op_msg[OS_SIZE_1024 +1];
314 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
315 "/proc. Possible kernel level rootkit.", (int)i);
316 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
320 else if(_gsid1 && _kill1 && !_ps0)
322 /* checking if the pid is a thread (not showing on ps */
323 if(!check_rc_readproc((int)i))
325 char op_msg[OS_SIZE_1024 +1];
326 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
327 "ps. Possible trojaned version installed.",
330 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
338 /* check_rc_sys: v0.1
339 * Scan the whole filesystem looking for possible issues
346 char ps[OS_SIZE_1024 +1];
348 char proc_0[] = "/proc";
349 char proc_1[] = "/proc/1";
351 pid_t max_pid = MAX_PID;
355 /* Checking where ps is */
356 memset(ps, '\0', OS_SIZE_1024 +1);
357 strncpy(ps, "/bin/ps", OS_SIZE_1024);
360 strncpy(ps, "/usr/bin/ps", OS_SIZE_1024);
366 /* Proc is mounted */
367 if(is_file(proc_0) && is_file(proc_1))
372 loop_all_pids(ps, max_pid, &_errors, &_total);
376 char op_msg[OS_SIZE_1024 +1];
377 snprintf(op_msg, OS_SIZE_1024, "No hidden process by Kernel-level "
378 "rootkits.\n %s is not trojaned. "
379 "Analyzed %d processes.", ps, _total);
380 notify_rk(ALERT_OK, op_msg);