1 /* Copyright (C) 2009 Trend Micro Inc.
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
13 #include "rootcheck.h"
15 #if defined(sun) || defined(__sun__)
16 #define NETSTAT "netstat -an -P %s | "\
17 "grep \"[^0-9]%d \" > /dev/null 2>&1"
19 #define NETSTAT "netstat -an | grep \"^%s\" | " \
20 "grep \"[^0-9]%d \" > /dev/null 2>&1"
24 static int run_netstat(int proto, int port);
25 static int conn_port(int proto, int port);
26 static void test_ports(int proto, int *_errors, int *_total);
29 static int run_netstat(int proto, int port)
32 char nt[OS_SIZE_1024 + 1];
34 if (proto == IPPROTO_TCP) {
35 snprintf(nt, OS_SIZE_1024, NETSTAT, "tcp", port);
36 } else if (proto == IPPROTO_UDP) {
37 snprintf(nt, OS_SIZE_1024, NETSTAT, "udp", port);
39 merror("%s: Netstat error (wrong protocol)", ARGV0);
47 } else if (ret == 1) {
54 static int conn_port(int proto, int port)
58 struct sockaddr_in server;
59 struct sockaddr_in6 server6;
61 if (proto == IPPROTO_UDP) {
62 if ((ossock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
65 } else if (proto == IPPROTO_TCP) {
66 if ((ossock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
73 memset(&server, 0, sizeof(server));
74 server.sin_family = AF_INET;
75 server.sin_port = htons(port);
76 server.sin_addr.s_addr = htonl(INADDR_ANY);
78 /* If we can't bind, it means the port is open */
79 if (bind(ossock, (struct sockaddr *) &server, sizeof(server)) < 0) {
83 /* Setting if port is open or closed */
84 if (proto == IPPROTO_TCP) {
85 total_ports_tcp[port] = (char) rc;
87 total_ports_udp[port] = (char) rc;
93 if (proto == IPPROTO_UDP) {
94 if ((ossock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
97 } else if (proto == IPPROTO_TCP) {
98 if ((ossock = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) {
104 memset(&server6, 0, sizeof(server6));
105 server6.sin6_family = AF_INET6;
106 server6.sin6_port = htons( port );
107 memcpy(&server6.sin6_addr.s6_addr, &in6addr_any, sizeof in6addr_any);
110 /* If we can't bind, it means the port is open */
111 if(bind(ossock, (struct sockaddr *) &server6, sizeof(server6)) < 0) {
115 /* Setting if port is open or closed */
116 if(proto == IPPROTO_TCP) {
117 total_ports_tcp[port] = rc;
119 total_ports_udp[port] = rc;
127 static void test_ports(int proto, int *_errors, int *_total)
131 for (i = 0; i <= 65535; i++) {
133 if (conn_port(proto, i)) {
134 /* Check if we can find it using netstat. If not,
135 * check again to see if the port is still being used.
137 if (run_netstat(proto, i)) {
142 /* If we are in the context of OSSEC-HIDS, sleep here (no rush) */
143 debug1("%s: DEBUG: pause for %u", ARGV0, rootcheck.tsleep);
144 sleep(rootcheck.tsleep);
147 if (!run_netstat(proto, i) && conn_port(proto, i)) {
148 char op_msg[OS_SIZE_1024 + 1];
152 snprintf(op_msg, OS_SIZE_1024, "Port '%d'(%s) hidden. "
153 "Kernel-level rootkit or trojaned "
154 "version of netstat.", i,
155 (proto == IPPROTO_UDP) ? "udp" : "tcp");
157 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
161 if ((*_errors) > 20) {
162 char op_msg[OS_SIZE_1024 + 1];
164 snprintf(op_msg, OS_SIZE_1024, "Excessive number of '%s' ports "
165 "hidden. It maybe a false-positive or "
166 "something really bad is going on.",
167 (proto == IPPROTO_UDP) ? "udp" : "tcp" );
168 notify_rk(ALERT_SYSTEM_CRIT, op_msg);
175 void check_rc_ports()
183 total_ports_tcp[i] = 0;
184 total_ports_udp[i] = 0;
188 /* Test both TCP and UDP ports */
189 test_ports(IPPROTO_TCP, &_errors, &_total);
190 test_ports(IPPROTO_UDP, &_errors, &_total);
193 char op_msg[OS_SIZE_1024 + 1];
195 snprintf(op_msg, OS_SIZE_1024, "No kernel-level rootkit hiding any port."
196 "\n Netstat is acting correctly."
197 " Analyzed %d ports.", _total);
198 notify_rk(ALERT_OK, op_msg);
206 /* Not implemented on Windows */
207 void check_rc_ports()