1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All right reserved.
3 *
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
7 * Foundation
8 */
9
10 #include "shared.h"
11 #include "rootcheck.h"
12
13
14 /* Report a problem */
notify_rk(int rk_type,const char * msg)15 int notify_rk(int rk_type, const char *msg)
16 {
17 /* Non-queue notification */
18 if (rootcheck.notify != QUEUE) {
19 if (rk_type == ALERT_OK) {
20 printf("[OK]: %s\n", msg);
21 } else if (rk_type == ALERT_SYSTEM_ERR) {
22 printf("[ERR]: %s\n", msg);
23 } else if (rk_type == ALERT_POLICY_VIOLATION) {
24 printf("[INFO]: %s\n", msg);
25 } else {
26 printf("[FAILED]: %s\n", msg);
27 }
28
29 printf("\n");
30 return (0);
31 }
32
33 /* No need to alert on that to the server */
34 if (rk_type <= ALERT_SYSTEM_ERR) {
35 return (0);
36 }
37
38 #ifdef OSSECHIDS
39 /* When running in context of OSSEC-HIDS, send problem to the rootcheck queue */
40 if (SendMSG(rootcheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) {
41 merror(QUEUE_SEND, ARGV0);
42
43 if ((rootcheck.queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
44 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
45 }
46
47 if (SendMSG(rootcheck.queue, msg, ROOTCHECK, ROOTCHECK_MQ) < 0) {
48 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
49 }
50 }
51 #endif
52
53 return (0);
54 }
55
56 /* Execute the rootkit checks */
run_rk_check()57 void run_rk_check()
58 {
59 time_t time1;
60 time_t time2;
61 FILE *fp;
62 OSList *plist;
63
64 #ifndef WIN32
65 /* On non-Windows, always start at / */
66 size_t i;
67 char basedir[] = "/";
68
69 /* Removing the last / from basedir */
70 i = strlen(basedir);
71 if (i > 0) {
72 if (basedir[i - 1] == '/') {
73 basedir[i - 1] = '\0';
74 }
75 }
76 #else
77 /* On Windows, always start at C:\ */
78 char basedir[] = "C:\\";
79
80 #endif
81
82 /* Set basedir */
83 if (rootcheck.basedir == NULL) {
84 rootcheck.basedir = basedir;
85 }
86
87 time1 = time(0);
88
89 /* Initial message */
90 if (rootcheck.notify != QUEUE) {
91 printf("\n");
92 printf("** Starting Rootcheck v0.9 by Daniel B. Cid **\n");
93 printf("** http://www.ossec.net/en/about.html#dev-team **\n");
94 printf("** http://www.ossec.net/rootcheck/ **\n\n");
95 printf("Be patient, it may take a few minutes to complete...\n");
96 printf("\n");
97 }
98
99 /* Clean the global variables */
100 rk_sys_count = 0;
101 rk_sys_file[rk_sys_count] = NULL;
102 rk_sys_name[rk_sys_count] = NULL;
103
104 /* Send scan start message */
105 notify_rk(ALERT_POLICY_VIOLATION, "Starting rootcheck scan.");
106 if (rootcheck.notify == QUEUE) {
107 merror("%s: INFO: Starting rootcheck scan.", ARGV0);
108 }
109
110 /* Check for Rootkits */
111 /* Open rootkit_files and pass the pointer to check_rc_files */
112 if (rootcheck.checks.rc_files) {
113 if (!rootcheck.rootkit_files) {
114 #ifndef WIN32
115 merror("%s: No rootcheck_files file configured.", ARGV0);
116 #endif
117 } else {
118 fp = fopen(rootcheck.rootkit_files, "r");
119 if (!fp) {
120 merror("%s: No rootcheck_files file: '%s'", ARGV0,
121 rootcheck.rootkit_files);
122 }
123
124 else {
125 check_rc_files(rootcheck.basedir, fp);
126
127 fclose(fp);
128 }
129 }
130 }
131
132 /* Check for trojan entries in common binaries */
133 if (rootcheck.checks.rc_trojans) {
134 if (!rootcheck.rootkit_trojans) {
135 #ifndef WIN32
136 merror("%s: No rootcheck_trojans file configured.", ARGV0);
137 #endif
138 } else {
139 fp = fopen(rootcheck.rootkit_trojans, "r");
140 if (!fp) {
141 merror("%s: No rootcheck_trojans file: '%s'", ARGV0,
142 rootcheck.rootkit_trojans);
143 } else {
144 #ifndef HPUX
145 check_rc_trojans(rootcheck.basedir, fp);
146 #endif
147 fclose(fp);
148 }
149 }
150 }
151
152 #ifdef WIN32
153 /* Get process list */
154 plist = os_get_process_list();
155
156 /* Windows audit check */
157 if (rootcheck.checks.rc_winaudit) {
158 if (!rootcheck.winaudit) {
159 merror("%s: No winaudit file configured.", ARGV0);
160 } else {
161 fp = fopen(rootcheck.winaudit, "r");
162 if (!fp) {
163 merror("%s: No winaudit file: '%s'", ARGV0,
164 rootcheck.winaudit);
165 } else {
166 check_rc_winaudit(fp, plist);
167 fclose(fp);
168 }
169 }
170 }
171
172 /* Windows malware */
173 if (rootcheck.checks.rc_winmalware) {
174 if (!rootcheck.winmalware) {
175 merror("%s: No winmalware file configured.", ARGV0);
176 } else {
177 fp = fopen(rootcheck.winmalware, "r");
178 if (!fp) {
179 merror("%s: No winmalware file: '%s'", ARGV0,
180 rootcheck.winmalware);
181 } else {
182 check_rc_winmalware(fp, plist);
183 fclose(fp);
184 }
185 }
186 }
187
188 /* Windows Apps */
189 if (rootcheck.checks.rc_winapps) {
190 if (!rootcheck.winapps) {
191 merror("%s: No winapps file configured.", ARGV0);
192 } else {
193 fp = fopen(rootcheck.winapps, "r");
194 if (!fp) {
195 merror("%s: No winapps file: '%s'", ARGV0,
196 rootcheck.winapps);
197 } else {
198 check_rc_winapps(fp, plist);
199 fclose(fp);
200 }
201 }
202 }
203
204 /* Free the process list */
205 del_plist((void *)plist);
206
207 #else
208 /* Checks for other non-Windows */
209
210 /* Unix audit check ***/
211 if (rootcheck.checks.rc_unixaudit) {
212 if (rootcheck.unixaudit) {
213 /* Get process list */
214 plist = os_get_process_list();
215
216 i = 0;
217 while (rootcheck.unixaudit[i]) {
218 fp = fopen(rootcheck.unixaudit[i], "r");
219 if (!fp) {
220 merror("%s: No unixaudit file: '%s'", ARGV0,
221 rootcheck.unixaudit[i]);
222 } else {
223 /* Run unix audit */
224 check_rc_unixaudit(fp, plist);
225 fclose(fp);
226 }
227
228 i++;
229 }
230
231 /* Free list */
232 del_plist(plist);
233 }
234 }
235
236 #endif /* !WIN32 */
237
238 /* Check for files in the /dev filesystem */
239 if (rootcheck.checks.rc_dev) {
240 debug1("%s: DEBUG: Going into check_rc_dev", ARGV0);
241 check_rc_dev(rootcheck.basedir);
242 debug1("%s: DEBUG: Exiting check_rc_dev", ARGV0);
243 }
244
245 /* Scan the whole system for additional issues */
246 if (rootcheck.checks.rc_sys) {
247 debug1("%s: DEBUG: Going into check_rc_sys", ARGV0);
248 check_rc_sys(rootcheck.basedir);
249 debug1("%s: DEBUG: Exiting check_rc_sys", ARGV0);
250 }
251
252 /* Check processes */
253 if (rootcheck.checks.rc_pids) {
254 debug1("%s: DEBUG: Going into check_rc_pids", ARGV0);
255 check_rc_pids();
256 debug1("%s: DEBUG: Exiting check_rc_pids", ARGV0);
257 }
258
259 /* Check all ports */
260 if (rootcheck.checks.rc_ports) {
261 debug1("%s: DEBUG: Going into check_rc_ports", ARGV0);
262 check_rc_ports();
263 debug1("%s: DEBUG: Exiting check_rc_ports", ARGV0);
264
265 /* Check open ports */
266 debug1("%s: DEBUG: Going into check_open_ports", ARGV0);
267 check_open_ports();
268 debug1("%s: DEBUG: Exiting check_open_ports", ARGV0);
269 }
270
271 /* Check interfaces */
272 if (rootcheck.checks.rc_if) {
273 debug1("%s: DEBUG: Going into check_rc_if", ARGV0);
274 check_rc_if();
275 debug1("%s: DEBUG: Exiting check_rc_if", ARGV0);
276 }
277
278 debug1("%s: DEBUG: Completed with all checks.", ARGV0);
279
280 /* Clean the global memory */
281 {
282 int li;
283 for (li = 0; li <= rk_sys_count; li++) {
284 if (!rk_sys_file[li] ||
285 !rk_sys_name[li]) {
286 break;
287 }
288
289 free(rk_sys_file[li]);
290 free(rk_sys_name[li]);
291 }
292 }
293
294 /* Final message */
295 time2 = time(0);
296
297 if (rootcheck.notify != QUEUE) {
298 printf("\n");
299 printf("- Scan completed in %d seconds.\n\n", (int)(time2 - time1));
300 } else {
301 sleep(5);
302 }
303
304 /* Send scan ending message */
305 notify_rk(ALERT_POLICY_VIOLATION, "Ending rootcheck scan.");
306 if (rootcheck.notify == QUEUE) {
307 merror("%s: INFO: Ending rootcheck scan.", ARGV0);
308 }
309
310 debug1("%s: DEBUG: Leaving run_rk_check", ARGV0);
311 return;
312 }
313
314