aboutsummaryrefslogtreecommitdiffstats
path: root/connector
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2024-07-30 19:37:48 +0800
committerWe-unite <3205135446@qq.com>2024-07-30 19:37:48 +0800
commitd6c6e13796435f9e1e59fec891aa53680748a2d7 (patch)
tree8a43fc36ec69a67dd5fd9809ac4588b5fbbac61c /connector
parent5d244e33672d0dd29a10c40c923c1decd645a1f7 (diff)
downloadgodo-d6c6e13796435f9e1e59fec891aa53680748a2d7.tar.gz
godo-d6c6e13796435f9e1e59fec891aa53680748a2d7.zip
Try to use kernel connector
Diffstat (limited to 'connector')
-rw-r--r--connector/hello.c162
-rwxr-xr-xconnector/proc_collector_linux.cpp618
-rwxr-xr-xconnector/proc_mon_linux.cpp487
-rw-r--r--connector/test.c64
4 files changed, 1331 insertions, 0 deletions
diff --git a/connector/hello.c b/connector/hello.c
new file mode 100644
index 0000000..5240c15
--- /dev/null
+++ b/connector/hello.c
@@ -0,0 +1,162 @@
1#include <stdio.h>
2#include <poll.h>
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <sys/time.h>
7#include <sys/select.h>
8#include <signal.h>
9#include <linux/netlink.h>
10#include <linux/connector.h>
11// #include <linux/cn_proc.h>
12#include <unistd.h>
13#include <errno.h>
14#include <time.h>
15#include "cn_proc.h"
16
17typedef struct __attribute__((aligned(NLMSG_ALIGNTO)))
18{
19 struct nlmsghdr nl_hdr;
20 struct __attribute__((__packed__))
21 {
22 struct cn_msg cn_msg;
23 enum proc_cn_mcast_op cn_mcast;
24 };
25} register_msg_t;
26
27typedef struct __attribute__((aligned(NLMSG_ALIGNTO)))
28{
29 struct nlmsghdr nl_hdr;
30 struct __attribute__((__packed__))
31 {
32 struct cn_msg cn_msg;
33 struct proc_event proc_ev;
34 };
35} event_msg_t;
36
37event_msg_t proc_msg;
38
39void Now()
40{
41 struct timespec ts;
42 struct tm *tm_info;
43 char buffer[64];
44
45 if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
46 {
47 perror("clock_gettime");
48 return;
49 }
50
51 tm_info = localtime(&ts.tv_sec);
52 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_info);
53 printf("Localtime %s.%03ld ", buffer, ts.tv_nsec / 1000000);
54}
55
56void printEvent()
57{
58 union unnamed *procEvent = &proc_msg.proc_ev.event_data;
59 switch (proc_msg.proc_ev.what)
60 {
61 case PROC_EVENT_FORK:
62 Now();
63 printf("Fork\t%6d\t%6d\t%6d\t%6d\n", procEvent->fork.parent_pid, procEvent->fork.parent_tgid, procEvent->fork.child_pid, procEvent->fork.child_tgid);
64 break;
65 case PROC_EVENT_EXIT:
66 Now();
67 printf("Exit\t%6d\t%6d\t%6d\t%6d\n", procEvent->exit.process_pid, procEvent->exit.process_tgid, procEvent->exit.exit_code, procEvent->exit.exit_signal);
68 break;
69 case PROC_EVENT_EXEC:
70 default:
71 break;
72 }
73}
74
75int main()
76{
77 int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
78
79 register_msg_t nlcn_msg;
80 struct sockaddr_nl l_local;
81 l_local.nl_family = AF_NETLINK;
82 l_local.nl_groups = 12345;
83 l_local.nl_pid = 0;
84
85 if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1)
86 {
87 perror(bind);
88 close(s);
89 return -1;
90 }
91
92 // int on = l_local.nl_groups;
93 // setsockopt(s,270,1,&on,sizeof(on));
94 memset(&nlcn_msg, 0, sizeof(nlcn_msg));
95 nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
96 nlcn_msg.nl_hdr.nlmsg_pid = getpid();
97 nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
98
99 nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
100 nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
101 nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
102
103 nlcn_msg.cn_mcast = PROC_CN_MCAST_LISTEN;
104
105 if (send(s, &nlcn_msg, sizeof(nlcn_msg), 0) == -1)
106 {
107 perror("can't register to netlink");
108 close(s);
109 return -1;
110 }
111
112 // 震惊,拿到socket了,开听!
113 printf("Hello, kernel-connector!\n");
114 // fd_set readfds;
115 // struct timeval tv = {
116 // .tv_sec = 5,
117 // .tv_usec = 0};
118 struct pollfd fds;
119
120 fds.fd = s;
121 fds.events = POLLIN;
122 int rc;
123
124 while (1)
125 {
126 // FD_ZERO(&readfds);
127 // FD_SET(s, &readfds);
128
129 // int rc = select(s + 1, &readfds, NULL, NULL, &tv);
130 rc = poll(&fds, 1, 5000);
131
132 if (rc == -1)
133 {
134 if (errno == EINTR)
135 {
136 continue;
137 }
138 fprintf(stderr, "Failed to listen to netlink socket: %s\n", strerror(errno));
139 return -1;
140 }
141 else if (rc == 0)
142 {
143 printf("No message in 5s...\n");
144 }
145 else
146 {
147 rc = recv(s, &proc_msg, sizeof(proc_msg), 0);
148 if (rc == -1)
149 {
150 if (errno == EINTR)
151 {
152 continue;
153 }
154 fprintf(stderr, "Failed to listen to netlink socket: %s\n", strerror(errno));
155 }
156 else
157 {
158 printEvent();
159 }
160 }
161 }
162} \ No newline at end of file
diff --git a/connector/proc_collector_linux.cpp b/connector/proc_collector_linux.cpp
new file mode 100755
index 0000000..478ac2b
--- /dev/null
+++ b/connector/proc_collector_linux.cpp
@@ -0,0 +1,618 @@
1#ifndef WIN32
2#include <sys/socket.h>
3#include <linux/netlink.h>
4#include <linux/connector.h>
5#include <linux/cn_proc.h>
6#include <errno.h>
7#include <sys/select.h>
8#include <sys/types.h>
9#include <sys/time.h>
10#include <unistd.h>
11
12#include "os_crypto/md5/md5_op.h"
13#include "external/procps/readproc.h"
14#include "proc_collector.h"
15
16static struct
17{
18 int queue_fd;
19 int proc_fd;
20} proc_monitor =
21{
22 .queue_fd = -1,
23 .proc_fd = -1
24};
25
26typedef struct __attribute__((aligned(NLMSG_ALIGNTO)))
27{
28 struct nlmsghdr nl_hdr;
29 struct __attribute__((__packed__))
30 {
31 struct cn_msg cn_msg;
32 enum proc_cn_mcast_op cn_mcast;
33 };
34} register_msg_t;
35
36typedef struct __attribute__((aligned(NLMSG_ALIGNTO)))
37{
38 struct nlmsghdr nl_hdr;
39 struct __attribute__((__packed__))
40 {
41 struct cn_msg cn_msg;
42 struct proc_event proc_ev;
43 };
44} event_msg_t;
45
46#define MAX_TEMP_PROCESS 5000
47#define TEMP_WAIT_TIME 1
48#define PROCESS_SLOT_EMPTY 0
49#define MAX_PATH_NAME 4096
50#define MAX_PIPE_WAIT_USECOND 100
51
52
53typedef struct
54{
55 pid_t pid;
56 pid_t ppid;
57 time_t fork_time;
58 int status;
59 char path[MAX_PATH_NAME];
60 os_md5 md5;
61 char parent_path[MAX_PATH_NAME];
62 os_md5 parent_md5;
63} process_parent_child_pair_t;
64static process_parent_child_pair_t temp_processes[ MAX_TEMP_PROCESS ];
65
66
67/*
68typedef struct
69{
70 pid_t pid; // process id
71 char *name; // process name
72 char *state; //program running state
73 pid_t ppid; // parent process id
74 char *pname; // parent process name
75 ulong utime; // process time in user mode
76 ulong stime; // process time in kernel mode
77 char **cmd_line; // command line
78 char *real_user; //
79 char *effective_user;
80 char *saved_user;
81 char *fs_user;
82 char *real_group;
83 char *effective_group;
84 char *saved_group;
85 char *fs_group;
86 int priority; // process priority
87 int nice; // nice value
88 long size; // the toal memory
89 long vm_size; // virtual memory
90 long resident; // occupied physical memory
91 long share; // shared memory
92 time_t start_time; // process startup time
93 int pgrp; /// process group
94 int session; // session id
95 long nlwp; // number of thread
96 int tgid; // task group id
97 int tty; // control terminal
98 int processor; // cpu number last executed on
99} proc_info_t;
100*/
101
102
103static void wm_proc_cleanup()
104{
105 if ( proc_monitor.proc_fd > 0 )
106 {
107 close( proc_monitor.proc_fd );
108 proc_monitor.proc_fd = -1;
109 }
110
111 if ( proc_monitor.queue_fd > 0 )
112 {
113 close( proc_monitor.queue_fd );
114 proc_monitor.queue_fd = -1;
115 }
116}
117
118
119static int wm_setup_netlink( )
120{
121 int rc;
122 int nl_sock;
123 struct sockaddr_nl sa_nl;
124 register_msg_t nlcn_msg;
125
126 nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
127 if (nl_sock == -1)
128 {
129 mterror( WM_PROC_LOGTAG, "Can't open netlink socket");
130 return -1;
131 }
132
133 sa_nl.nl_family = AF_NETLINK;
134 sa_nl.nl_groups = CN_IDX_PROC;
135 sa_nl.nl_pid = getpid(); // 向内核注册
136
137 rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
138 if (rc == -1)
139 {
140 mterror( WM_PROC_LOGTAG, "Can't bind netlink socket");
141 close(nl_sock);
142 return -1;
143 }
144
145 // create listener
146 memset(&nlcn_msg, 0, sizeof(nlcn_msg));
147 nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
148 nlcn_msg.nl_hdr.nlmsg_pid = getpid();
149 nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
150
151 nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
152 nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
153 nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
154
155 nlcn_msg.cn_mcast = PROC_CN_MCAST_LISTEN ;
156
157 rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
158 if (rc == -1)
159 {
160 mterror(WM_PROC_LOGTAG, "can't register to netlink");
161 close( nl_sock );
162 return -1;
163 }
164
165 proc_monitor.proc_fd = nl_sock;
166 return 0;
167}
168
169static int wm_setup_mq( wm_proc_t *proc )
170{
171 unsigned int indx;
172 // Connect to socket
173 for (indx = 0; indx < WM_MAX_ATTEMPTS; indx++)
174 {
175 proc_monitor.queue_fd = StartMQ(DEFAULTQPATH, WRITE);
176 if ( proc_monitor.queue_fd > 0 )
177 {
178 break;
179 }
180 wm_delay(1000 * WM_MAX_WAIT);
181 }
182
183 if (indx == WM_MAX_ATTEMPTS)
184 {
185 mterror(WM_PROC_LOGTAG, "Can't connect to queue.");
186 pthread_exit(NULL);
187 }
188
189 // Cleanup exiting
190 atexit(wm_proc_cleanup);
191
192 return 0;
193}
194
195 int wm_proc_linux_setup( wm_proc_t *proc )
196 {
197 memset( temp_processes, 0, sizeof( temp_processes ) );
198 if ( wm_setup_netlink() < 0 )
199 {
200 return -1;
201 }
202 return wm_setup_mq(proc);
203 }
204
205static void get_path_and_md5( pid_t pid, char *path, char *md5 )
206{
207 char pid_path[MAX_PATH_NAME];
208 struct stat dir_stat;
209
210 memset( pid_path, 0, MAX_PATH_NAME);
211 snprintf( pid_path, MAX_PATH_NAME-1, "/proc/%d", pid );
212 if ( stat( pid_path, &dir_stat ) < 0 )
213 {
214 //mterror(WM_PROC_LOGTAG, "failed to open directory %s, errno=(%d:%m)", pid_path, errno );
215 return;
216 }
217
218 memset( pid_path, 0, MAX_PATH_NAME);
219 snprintf( pid_path, MAX_PATH_NAME-1, "/proc/%d/exe", pid );
220 memset( path, 0, MAX_PATH_NAME );
221 memset( md5, 0, sizeof(os_md5));
222 if ( readlink( pid_path, path, MAX_PATH_NAME ) < 0 )
223 {
224 memset(pid_path, 0, MAX_PATH_NAME);
225 snprintf(pid_path, MAX_PATH_NAME - 1, "/proc/%d/comm", pid);
226 memset(path, 0, MAX_PATH_NAME);
227 FILE* fp = fopen(pid_path, "rb");
228 if ( NULL == fp )
229 {
230 return;
231 }
232 fread( path, MAX_PATH_NAME, 1, fp );
233 if ( strlen( path ) > 0 )
234 {
235 path[strlen(path)-1] = '\0';
236 }
237 fclose( fp );
238 return;
239 }
240
241 OS_MD5_File(path, md5, OS_BINARY);
242
243 return;
244}
245
246
247
248static void get_process_baseinfo( const process_parent_child_pair_t *pair, const char *location )
249{
250 proc_t curr_proc;
251
252 memset( &curr_proc, 0, sizeof( proc_t ));
253
254 cJSON *process = cJSON_CreateObject();
255 if( NULL == process)
256 {
257 return;
258 }
259 cJSON_AddStringToObject(process, "type", "new process");
260 cJSON_AddNumberToObject(process, "pid", pair->pid);
261 cJSON_AddNumberToObject(process, "eventTime", pair->fork_time);
262 cJSON_AddNumberToObject(process, "ppid", pair->ppid);
263 if (strlen(pair->path) > 0)
264 {
265 cJSON_AddStringToObject(process, "exe", pair->path);
266 }
267 if (strlen(pair->md5) > 0)
268 {
269 cJSON_AddStringToObject(process, "md5", pair->md5);
270 }
271 if (strlen(pair->parent_path) > 0)
272 {
273 cJSON_AddStringToObject(process, "parent_exe", pair->parent_path);
274 }
275 if (strlen(pair->parent_md5) > 0)
276 {
277 cJSON_AddStringToObject(process, "parent_md5", pair->parent_md5);
278 }
279
280 // get process information
281 if (NULL != get_proc_stats(pair->pid, &curr_proc))
282 {
283 cJSON_AddStringToObject(process, "state", &curr_proc.state);
284 cJSON_AddNumberToObject(process, "utime", curr_proc.utime);
285 cJSON_AddNumberToObject(process, "stime", curr_proc.stime);
286 if (curr_proc.cmdline && curr_proc.cmdline[0])
287 {
288 cJSON *argvs = cJSON_CreateArray();
289 cJSON_AddStringToObject(process, "cmd", curr_proc.cmdline[0]);
290 for (int i = 1; curr_proc.cmdline[i]; i++)
291 {
292 if (!strlen(curr_proc.cmdline[i]) == 0)
293 {
294 cJSON_AddItemToArray(argvs, cJSON_CreateString(curr_proc.cmdline[i]));
295 }
296 }
297 if (cJSON_GetArraySize(argvs) > 0)
298 {
299 cJSON_AddItemToObject(process, "argvs", argvs);
300 }
301 else
302 {
303 cJSON_Delete(argvs);
304 }
305 }
306 cJSON_AddStringToObject(process, "euser", curr_proc.euser);
307 cJSON_AddStringToObject(process, "egroup", curr_proc.egroup);
308 cJSON_AddNumberToObject(process, "resident", curr_proc.resident);
309 cJSON_AddNumberToObject(process, "nlwp", curr_proc.nlwp);
310 cJSON_AddNumberToObject(process, "tty", curr_proc.tty);
311 cJSON_AddNumberToObject(process, "processor", curr_proc.processor);
312 /*
313 cJSON_AddStringToObject(process, "ruser", curr_proc.ruser);
314 cJSON_AddStringToObject(process, "suser", curr_proc.suser);
315 cJSON_AddStringToObject(process, "rgroup", curr_proc.rgroup);
316 cJSON_AddStringToObject(process, "sgroup", curr_proc.sgroup);
317 cJSON_AddStringToObject(process, "fgroup", curr_proc.fgroup);
318 cJSON_AddNumberToObject(process, "priority", curr_proc.priority);
319 cJSON_AddNumberToObject(process, "nice", curr_proc.nice);
320 cJSON_AddNumberToObject(process, "size", curr_proc.size);
321 cJSON_AddNumberToObject(process, "vm_size", curr_proc.vm_size);
322 cJSON_AddNumberToObject(process, "share", curr_proc.share);
323 cJSON_AddNumberToObject(process, "pgrp", curr_proc.pgrp);
324 cJSON_AddNumberToObject(process, "session", curr_proc.session);
325 cJSON_AddNumberToObject(process, "tgid", curr_proc.tgid);
326 */
327 }
328
329 char *msg = cJSON_PrintUnformatted(process);
330 wm_sendmsg( MAX_PIPE_WAIT_USECOND, proc_monitor.queue_fd, msg, location, PROC_COLLECTOR_MQ );
331 free(msg);
332 cJSON_Delete( process );
333
334 return;
335}
336
337 static void get_process_info( const process_parent_child_pair_t *pair, const char *location )
338 {
339 // get process base info
340 get_process_baseinfo( pair, location );
341
342 // get process library info
343
344 // find rootkit in user mode
345
346 // check process is a malware
347 }
348
349static void handle_temp_process( const char *location )
350{
351 int i = 0;
352 for ( i = 0; i < MAX_TEMP_PROCESS; i++ )
353 {
354 if ( ( temp_processes[i].status != PROCESS_SLOT_EMPTY ) && ( temp_processes[i].ppid != 0 ) )
355 {
356 mtdebug1(WM_PROC_LOGTAG, "handle process: %d, parent process:%d", temp_processes[i].pid, temp_processes[i].ppid );
357 get_process_info( &temp_processes[i], location );
358 temp_processes[i].status = PROCESS_SLOT_EMPTY;
359 }
360 }
361}
362
363static void handle_process_fork( const event_msg_t *proc_msg )
364{
365 int i = 0;
366 for ( i = 0; i < MAX_TEMP_PROCESS; i++ )
367 {
368 if ( temp_processes[i].status == PROCESS_SLOT_EMPTY )
369 {
370 get_path_and_md5( proc_msg->proc_ev.event_data.fork.child_pid, temp_processes[i].path, temp_processes[i].md5 );
371 get_path_and_md5( proc_msg->proc_ev.event_data.fork.parent_pid, temp_processes[i].parent_path, temp_processes[i].parent_md5);
372 temp_processes[i].pid = proc_msg->proc_ev.event_data.fork.child_pid;
373 temp_processes[i].ppid = proc_msg->proc_ev.event_data.fork.parent_pid;
374 temp_processes[i].fork_time = time(0);
375 temp_processes[i].status = !PROCESS_SLOT_EMPTY;
376 mtdebug1(WM_PROC_LOGTAG, "fork process: %d, parent process:%d", temp_processes[i].pid, temp_processes[i].ppid );
377 break;
378 }
379 }
380}
381
382static void handle_process_exec( const event_msg_t *proc_msg, const char *location )
383{
384 int i = 0;
385 for ( i = 0; i < MAX_TEMP_PROCESS; i++ )
386 {
387 if (temp_processes[i].pid == proc_msg->proc_ev.event_data.exec.process_pid
388 && temp_processes[i].status != PROCESS_SLOT_EMPTY)
389 {
390 get_path_and_md5( proc_msg->proc_ev.event_data.exec.process_pid, temp_processes[i].path, temp_processes[i].md5 );
391 mtdebug1(WM_PROC_LOGTAG, "exec process: %d, parent process:%d", temp_processes[i].pid, temp_processes[i].ppid );
392 get_process_info( &temp_processes[i], location );
393 temp_processes[i].status = PROCESS_SLOT_EMPTY;
394 break;
395 }
396 }
397}
398
399static void handle_process_exit( const event_msg_t *proc_msg, const char* location )
400{
401 int i = 0;
402 for ( i = 0; i < MAX_TEMP_PROCESS; i++ )
403 {
404 if ( ( temp_processes[i].status != PROCESS_SLOT_EMPTY )
405 && ( proc_msg->proc_ev.event_data.exit.process_pid == temp_processes[i].pid )
406 && ( temp_processes[i].ppid == 0 ) )
407 {
408 temp_processes[i].status = PROCESS_SLOT_EMPTY;
409 return;
410 }
411 }
412
413 cJSON *process = cJSON_CreateObject();
414 cJSON_AddStringToObject(process, "type", "exit");
415 cJSON_AddNumberToObject( process, "pid", proc_msg->proc_ev.event_data.exit.process_pid );
416 cJSON_AddNumberToObject( process, "eventTime", time(0) );
417 cJSON_AddNumberToObject(process, "exitCode", proc_msg->proc_ev.event_data.exit.exit_code);
418 cJSON_AddNumberToObject(process, "exitSignal", (int)proc_msg->proc_ev.event_data.exit.exit_signal);
419
420 char *exit_msg = cJSON_PrintUnformatted( process );
421 wm_sendmsg( MAX_PIPE_WAIT_USECOND, proc_monitor.queue_fd, exit_msg, location, PROC_COLLECTOR_MQ );
422 free( exit_msg );
423 cJSON_Delete( process );
424}
425
426static time_t get_process_start_time( pid_t pid )
427{
428 char path[MAX_PATH_NAME];
429 memset( path, 0, MAX_PATH_NAME);
430
431 snprintf( path, MAX_PATH_NAME-1, "/proc/%d", pid );
432
433 struct stat dir_stat;
434
435 if ( stat( path, &dir_stat) < 0 )
436 {
437 return 0;
438 }
439
440 return dir_stat.st_mtime;
441}
442
443static void get_inventory_processes(const char *location)
444{
445 DIR *proc_dir = opendir( "/proc" );
446 if ( NULL == proc_dir )
447 {
448 mterror( WM_PROC_LOGTAG, "failed to open /proc, errno=(%d:%m)", errno );
449 return;
450 }
451
452 struct dirent *entry = NULL;
453 while ( NULL != ( entry = readdir( proc_dir )))
454 {
455 if ( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) )
456 {
457 continue;
458 }
459 int pid = atoi( entry->d_name );
460 if ( 0 == pid )
461 {
462 continue;
463 }
464
465 char pid_path[MAX_PATH_NAME];
466 os_md5 md5;
467 memset( pid_path, 0, sizeof( MAX_PATH_NAME));
468 memset( md5, 0, sizeof( os_md5 ) );
469 get_path_and_md5( pid, pid_path, md5 );
470
471 cJSON *process = cJSON_CreateObject();
472 cJSON_AddStringToObject(process, "type", "new process");
473 cJSON_AddNumberToObject(process, "eventTime", time(0));
474 cJSON_AddNumberToObject(process, "pid", pid);
475 cJSON_AddNumberToObject(process, "startTime", get_process_start_time(pid));
476 if (strlen(pid_path) > 0)
477 {
478 cJSON_AddStringToObject(process, "exe", pid_path);
479 }
480 if (strlen(md5) > 0)
481 {
482 cJSON_AddStringToObject(process, "md5", md5);
483 }
484
485 proc_t curr_proc;
486 memset( &curr_proc, 0, sizeof( proc_t ));
487 if ( NULL != get_proc_stats(pid, &curr_proc ))
488 {
489 cJSON_AddStringToObject(process, "state", &curr_proc.state);
490 cJSON_AddNumberToObject(process, "utime", curr_proc.utime);
491 cJSON_AddNumberToObject(process, "stime", curr_proc.stime);
492 cJSON_AddStringToObject(process, "euser", curr_proc.euser);
493 cJSON_AddStringToObject(process, "egroup", curr_proc.egroup);
494 cJSON_AddNumberToObject(process, "resident", curr_proc.resident);
495 cJSON_AddNumberToObject(process, "nlwp", curr_proc.nlwp);
496 cJSON_AddNumberToObject(process, "tty", curr_proc.tty);
497 cJSON_AddNumberToObject(process, "processor", curr_proc.processor);
498 /*
499 cJSON_AddStringToObject(process, "ruser", curr_proc.ruser);
500 cJSON_AddStringToObject(process, "suser", curr_proc.suser);
501 cJSON_AddStringToObject(process, "rgroup", curr_proc.rgroup);
502 cJSON_AddStringToObject(process, "sgroup", curr_proc.sgroup);
503 cJSON_AddStringToObject(process, "fgroup", curr_proc.fgroup);
504
505 cJSON_AddNumberToObject(process, "priority", curr_proc.priority);
506 cJSON_AddNumberToObject(process, "nice", curr_proc.nice);
507 cJSON_AddNumberToObject(process, "size", curr_proc.size);
508 cJSON_AddNumberToObject(process, "vm_size", curr_proc.vm_size);
509 cJSON_AddNumberToObject(process, "share", curr_proc.share);
510 cJSON_AddNumberToObject(process, "pgrp", curr_proc.pgrp);
511 cJSON_AddNumberToObject(process, "session", curr_proc.session);
512 cJSON_AddNumberToObject(process, "tgid", curr_proc.tgid);
513 */
514
515 memset(pid_path, 0, sizeof(MAX_PATH_NAME));
516 memset(md5, 0, sizeof(os_md5));
517 get_path_and_md5(curr_proc.ppid, pid_path, md5);
518 if (strlen(pid_path) > 0)
519 {
520 cJSON_AddStringToObject(process, "parent_exe", pid_path);
521 }
522 if (strlen(md5) > 0)
523 {
524 cJSON_AddStringToObject(process, "parent_md5", md5);
525 }
526 }
527
528 char *msg = cJSON_PrintUnformatted(process);
529 wm_sendmsg(MAX_PIPE_WAIT_USECOND, proc_monitor.queue_fd, msg, location, PROC_COLLECTOR_MQ);
530 free(msg);
531 cJSON_Delete(process);
532 }
533
534 closedir( proc_dir);
535}
536
537int wm_proc_linux_process(wm_proc_t *proc, const char *location)
538{
539 int rc;
540 event_msg_t proc_msg;
541 fd_set readfds;
542 int max_fd = proc_monitor.proc_fd + 1;
543 struct timeval tv;
544
545 if (proc->flags.enabled == 0)
546 {
547 return 0;
548 merror("process collector disabled, let us rest.");
549 }
550
551
552 merror("process collector enabled, let us work.");
553
554 get_inventory_processes(location);
555
556 tv.tv_sec = 5;
557 tv.tv_usec = 0;
558
559 while (1)
560 {
561 FD_ZERO(&readfds);
562 FD_SET(proc_monitor.proc_fd, &readfds);
563
564 rc = select(max_fd, &readfds, NULL, NULL, &tv);
565 if (0 == rc)
566 {
567 handle_temp_process(location);
568 tv.tv_sec = 5;
569 tv.tv_usec = 0;
570 continue;
571 }
572 if (-1 == rc)
573 {
574 if (errno == EINTR)
575 {
576 continue;
577 }
578 mterror(WM_PROC_LOGTAG, "failed to listen to netlink socket, errno=(%d:%m)", errno);
579 return rc;
580 }
581 if (FD_ISSET(proc_monitor.proc_fd, &readfds))
582 {
583 rc = recv(proc_monitor.proc_fd, &proc_msg, sizeof(proc_msg), 0);
584 if (rc > 0)
585 {
586 switch (proc_msg.proc_ev.what)
587 {
588 case proc_event::PROC_EVENT_FORK:
589 handle_process_fork(&proc_msg);
590 tv.tv_sec = 1;
591 tv.tv_usec = 1000;
592 break;
593 case proc_event::PROC_EVENT_EXEC:
594 handle_process_exec(&proc_msg, location);
595 break;
596 case proc_event::PROC_EVENT_COMM:
597 break;
598 case proc_event::PROC_EVENT_EXIT:
599 handle_process_exit(&proc_msg, location);
600 break;
601 default:
602 break;
603 }
604 }
605 else if (rc == -1)
606 {
607 if (errno == EINTR)
608 {
609 continue;
610 }
611 mterror(WM_PROC_LOGTAG, "failed to received from netlink socket, errno=(%d:%m)", errno);
612 }
613 }
614 }
615
616 return 0;
617}
618#endif \ No newline at end of file
diff --git a/connector/proc_mon_linux.cpp b/connector/proc_mon_linux.cpp
new file mode 100755
index 0000000..16dd51c
--- /dev/null
+++ b/connector/proc_mon_linux.cpp
@@ -0,0 +1,487 @@
1#ifndef WIN32
2#include <unistd.h>
3#include <sys/socket.h>
4#include <algorithm>
5#include "shared.h"
6#include "proc_mon_linux.h"
7#include <malloc.h>
8#include "linux_proc_baseline.h"
9
10
11#define MAX_PIPE_WAIT_USECOND 100
12#define PROCESS_SCAN_ITERTIME 10
13const char *WM_PROC_LOCATION = "proc_collector";
14
15ProcMon* ProcMon::m_instance = NULL;
16
17ProcMon& ProcMon::instance()
18{
19 if ( m_instance == NULL )
20 {
21 m_instance = new ProcMon;
22 }
23
24 return *m_instance;
25}
26
27void ProcMon::destroy()
28{
29 delete m_instance;
30 m_instance = NULL;
31}
32
33int ProcMon::init( const wm_proc_t* config )
34{
35 pthread_mutex_init(&m_mutex, NULL);
36 setConfig( config );
37
38 int ret = setupNetlink();
39 if (ret != 0 )
40 {
41 fini();
42 return -1;
43 }
44
45 ret = setupMQ();
46 if (ret != 0 )
47 {
48 fini();
49 return -1;
50 }
51
52 return 0;
53}
54
55int ProcMon::working()
56{
57 int rc;
58 event_msg_t procMsg;
59 fd_set readfds;
60 int maxfd = m_procFd + 1;
61 struct timeval tv;
62 time_t last = time(0);
63
64 if ( m_config.flags.enabled == 0 )
65 {
66 return 0;
67 }
68
69 getInventoryProcesses();
70
71
72 while ( 1 )
73 {
74 FD_ZERO(&readfds);
75 FD_SET( m_procFd, &readfds );
76 tv.tv_sec = 1;
77 tv.tv_usec = 0;
78
79 if ( time(0) - last > PROCESS_SCAN_ITERTIME )
80 {
81 // scan processes
82 scanProcesses(last);
83 last = time(0);
84 }
85
86 rc = select( maxfd, &readfds, NULL, NULL, &tv );
87 if ( 0 == rc )
88 {
89 continue;
90 }
91
92 if ( -1 == rc )
93 {
94 if ( errno == EINTR )
95 {
96 continue;
97 }
98
99 mterror(WM_PROC_LOGTAG, "failed to listen to netlink socket, errno=(%d:%m)", errno);
100 return rc;
101 }
102
103 if ( FD_ISSET( m_procFd, &readfds ) )
104 {
105 rc = recv( m_procFd, &procMsg, sizeof(procMsg), 0 );
106 if( rc > 0 )
107 {
108 switch (procMsg.proc_ev.what)
109 {
110 case proc_event::PROC_EVENT_FORK:
111 handleForkMsg(procMsg);
112 break;
113 case proc_event::PROC_EVENT_EXEC:
114 handleExecMsg(procMsg);
115 break;
116 case proc_event::PROC_EVENT_COMM:
117 break;
118 case proc_event::PROC_EVENT_EXIT:
119 handleExitMsg(procMsg);
120 break;
121 default:
122 break;
123 }
124 }
125 else if (rc == -1)
126 {
127 if (errno == EINTR)
128 {
129 continue;
130 }
131 mterror(WM_PROC_LOGTAG, "failed to received from netlink socket, errno=(%d:%m)", errno);
132 }
133 }
134
135 malloc_trim(0);
136 }
137}
138
139ProcMon::ProcMon()
140{
141 m_mutex = PTHREAD_MUTEX_INITIALIZER;
142 m_processes.clear();
143 m_pidCache.clear();
144 m_procFd = -1;
145 m_queueFd = -1;
146}
147
148ProcMon::~ProcMon()
149{
150 fini();
151}
152
153void ProcMon::setConfig( const wm_proc_t* config )
154{
155 m_config.flags.enabled = config->flags.enabled;
156 m_config.flags.rootcheck = config->flags.rootcheck;
157 m_config.flags.limitcheck = config->flags.limitcheck;
158 m_config.flags.environcheck = config->flags.environcheck;
159 m_config.flags.statuscheck = config->flags.statuscheck;
160 m_config.flags.threadcheck = config->flags.threadcheck;
161 m_config.flags.cgroupcheck = config->flags.cgroupcheck;
162 m_config.flags.libcheck = config->flags.libcheck;
163 m_config.flags.malwarecheck = config->flags.malwarecheck;
164 m_config.interval = config->interval;
165}
166
167int ProcMon::setupNetlink()
168{
169 int rc;
170 int nl_sock;
171 struct sockaddr_nl sa_nl;
172 register_msg_t nlcn_msg;
173
174 nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
175 if (nl_sock == -1)
176 {
177 mterror(WM_PROC_LOGTAG, "Can't open netlink socket");
178 return -1;
179 }
180
181 sa_nl.nl_family = AF_NETLINK;
182 sa_nl.nl_groups = CN_IDX_PROC;
183 sa_nl.nl_pid = getpid();
184
185 rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
186 if (rc == -1)
187 {
188 mterror(WM_PROC_LOGTAG, "Can't bind netlink socket");
189 close(nl_sock);
190 return -1;
191 }
192
193 // create listener
194 memset(&nlcn_msg, 0, sizeof(nlcn_msg));
195 nlcn_msg.nl_hdr.nlmsg_len = sizeof(nlcn_msg);
196 nlcn_msg.nl_hdr.nlmsg_pid = getpid();
197 nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE;
198
199 nlcn_msg.cn_msg.id.idx = CN_IDX_PROC;
200 nlcn_msg.cn_msg.id.val = CN_VAL_PROC;
201 nlcn_msg.cn_msg.len = sizeof(enum proc_cn_mcast_op);
202
203 nlcn_msg.cn_mcast = PROC_CN_MCAST_LISTEN;
204
205 rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0);
206 if (rc == -1)
207 {
208 mterror(WM_PROC_LOGTAG, "can't register to netlink");
209 close(nl_sock);
210 return -1;
211 }
212
213 m_procFd = nl_sock;
214 return 0;
215}
216
217int ProcMon::setupMQ()
218{
219 unsigned int indx;
220 // Connect to socket
221 for (indx = 0; indx < WM_MAX_ATTEMPTS; indx++)
222 {
223 m_queueFd = StartMQ(DEFAULTQPATH, WRITE);
224 if (m_queueFd > 0)
225 {
226 break;
227 }
228 wm_delay(1000 * WM_MAX_WAIT);
229 }
230
231 if (indx == WM_MAX_ATTEMPTS)
232 {
233 mterror(WM_PROC_LOGTAG, "Can't connect to queue.");
234 pthread_exit(NULL);
235 }
236
237 return 0;
238}
239
240
241void ProcMon::fini()
242{
243 m_processes.clear();
244 m_pidCache.clear();
245 if (m_procFd != -1 )
246 {
247 close( m_procFd);
248 m_procFd = -1;
249 }
250
251 if (m_queueFd != -1 )
252 {
253 close( m_queueFd);
254 m_queueFd = -1;
255 }
256}
257
258void ProcMon::getInventoryProcesses()
259{
260 DIR *procDir = opendir( "/proc" );
261 if ( NULL == procDir )
262 {
263 mterror(WM_PROC_LOGTAG, "failed to open /proc, errno=(%d:%m)", errno);
264 return;
265 }
266
267 struct dirent *entry = NULL;
268 while (NULL != (entry = readdir(procDir)))
269 {
270 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
271 {
272 continue;
273 }
274 int pid = atoi(entry->d_name);
275 if (0 == pid)
276 {
277 continue;
278 }
279
280 Process *proc = new Process(pid);
281 if ( NULL == proc )
282 {
283 continue;
284 }
285 if(0 != proc->init())
286 {
287 delete proc;
288 proc = NULL;
289 continue;
290 }
291 std::pair<std::map<pid_t, Process*>::iterator,bool> ret = m_processes.insert(std::make_pair(pid, proc));
292 if(!ret.second)
293 {
294 delete proc;
295 proc = NULL;
296 continue;
297 }
298 std::vector<std::string> events = proc->getEvents();
299 if ( !events.empty() )
300 {
301 reportEvents(events);
302 }
303 usleep( 500 );
304 }
305
306 return;
307}
308
309void ProcMon::handleForkMsg( const event_msg_t& procMsg )
310{
311 pid_t pid = procMsg.proc_ev.event_data.fork.child_pid;
312 auto iter = m_pidCache.find( pid );
313 if ( iter != m_pidCache.end() )
314 {
315 m_pidCache.erase(iter);
316 return;
317 }
318
319 PidRelation relation;
320 relation.pid = pid;
321 relation.ppid = procMsg.proc_ev.event_data.fork.parent_pid;
322 relation.pidEvent = PidRelation::FORKEVENT;
323 relation.born = time(0);
324
325 m_pidCache.insert( std::make_pair(relation.pid, relation ));
326}
327
328void ProcMon::handleExecMsg( const event_msg_t& procMsg )
329{
330 pid_t pid = procMsg.proc_ev.event_data.exec.process_pid;
331 auto iter = m_pidCache.find( pid );
332 if ( iter == m_pidCache.end() )
333 {
334 return;
335 }
336
337 //mterror(WM_PROC_LOGTAG, "cache size:%lu", m_pidCache.size());
338 Process *proc = new Process( pid, iter->second.ppid, iter->second.born );
339 if ( NULL == proc )
340 {
341 return;
342 }
343 // check hidden process
344 if ( 0 != proc->init() )
345 {
346 return;
347 }
348 m_processes.insert( std::make_pair(pid, proc ));
349 std::vector<std::string> events = proc->getEvents();
350 if (!events.empty())
351 {
352 reportEvents(events);
353 }
354// m_pidCache.erase(iter);
355 //mterror(WM_PROC_LOGTAG, "exec process:%d exe:%s", pid, proc.exe().c_str());
356}
357
358void ProcMon::handleExitMsg( const event_msg_t& procMsg )
359{
360 pid_t pid = procMsg.proc_ev.event_data.exit.process_pid;
361 auto iter = m_pidCache.find( pid );
362 if ( iter != m_pidCache.end() )
363 {
364 m_pidCache.erase(iter);
365 }
366
367 auto procIter = m_processes.find(pid);
368 if ( procIter == m_processes.end() )
369 {
370 return;
371 }
372
373 std::vector<int> signals{ 3, 9, 10, 12, 15,16,17,30,31};
374
375 //if ( signals.end() == std::find( signals.begin(), signals.end(), procMsg.proc_ev.event_data.exit.exit_signal )
376 //|| (procMsg.proc_ev.event_data.exit.exit_code != 0))
377 {
378 // report abnormal events
379 cJSON *obj= cJSON_CreateObject();
380 cJSON_AddStringToObject(obj, "type", "exit");
381 cJSON_AddStringToObject(obj, "exe", procIter->second->exe().c_str());
382 cJSON_AddNumberToObject(obj, "pid", procIter->first);
383 cJSON_AddNumberToObject(obj, "event_time", time(0));
384 cJSON_AddNumberToObject(obj, "exit_signal", procMsg.proc_ev.event_data.exit.exit_signal);
385 cJSON_AddNumberToObject(obj, "exit_code", procMsg.proc_ev.event_data.exit.exit_code);
386 char *data = cJSON_PrintUnformatted( obj );
387 std::string msg(data);
388 free(data);
389 reportEvent( msg );
390 cJSON_Delete(obj);
391 //mterror(WM_PROC_LOGTAG, "%s", msg.c_str());
392 }
393
394 delete procIter->second;
395 m_processes.erase(procIter);
396 //mterror(WM_PROC_LOGTAG, "process collection:%d", m_processes.size());
397}
398
399void ProcMon::scanProcesses(time_t last)
400{
401 time_t now = time(0);
402// mterror(WM_PROC_LOGTAG, "pid cache size: %d , process collection size : %d", m_pidCache.size(), m_processes.size());
403 for (auto iter = m_pidCache.begin(); iter != m_pidCache.end(); )
404 {
405 if ( now - iter->second.born < 1 || m_processes.find(iter->second.pid) != m_processes.end())
406 {
407 iter++;
408 }
409 else
410 {
411 Process *proc = new Process( iter->second.pid, iter->second.ppid, iter->second.born);
412 if (NULL != proc )
413 {
414 if(0 != proc->init())
415 {
416 delete proc;
417 proc = NULL;
418 continue;
419 }
420 std::pair<std::map<pid_t, Process*>::iterator, bool> ret = m_processes.insert(std::make_pair(iter->first, proc));
421 if(!ret.second)
422 {
423 delete proc;
424 proc = NULL;
425 continue;
426 }
427 std::vector<std::string> events = proc->getEvents();
428 if (!events.empty())
429 {
430 reportEvents(events);
431 }
432
433 }
434 else
435 {
436 // hidden process found
437 cJSON *obj = cJSON_CreateObject();
438 cJSON_AddStringToObject(obj, "type", "rootkit");
439 cJSON_AddNumberToObject(obj, "pid", iter->first);
440 cJSON_AddNumberToObject(obj, "event_time", iter->second.born);
441 cJSON_AddNumberToObject(obj, "ppid", iter->second.ppid);
442 auto parent = m_processes.find(iter->second.ppid);
443 if (parent != m_processes.end())
444 {
445 cJSON_AddStringToObject(obj, "parent exe", parent->second->exe().c_str());
446 }
447 char *data = cJSON_PrintUnformatted(obj);
448 std::string msg(data);
449 free(data);
450 reportEvent(msg);
451 cJSON_Delete(obj);
452 }
453 iter = m_pidCache.erase(iter);
454 }
455 usleep( 500 );
456 }
457/*
458 if ( now - last < 60 )
459 {
460 return;
461 }
462*/
463 for (auto& procIter : m_processes )
464 {
465 procIter.second->scan();
466 std::vector<std::string> events = procIter.second->getEvents();
467 if (!events.empty())
468 {
469 reportEvents(events);
470 }
471 usleep( 5000 );
472 }
473}
474
475void ProcMon::reportEvent( const std::string& event )
476{
477 wm_sendmsg(MAX_PIPE_WAIT_USECOND, m_queueFd, event.c_str(), WM_PROC_LOCATION, PROC_COLLECTOR_MQ);
478}
479
480void ProcMon::reportEvents(const std::vector<std::string> &events)
481{
482 for (auto it : events)
483 {
484 wm_sendmsg(MAX_PIPE_WAIT_USECOND, m_queueFd, it.c_str(), WM_PROC_LOCATION, PROC_COLLECTOR_MQ);
485 }
486}
487#endif
diff --git a/connector/test.c b/connector/test.c
new file mode 100644
index 0000000..c12ad10
--- /dev/null
+++ b/connector/test.c
@@ -0,0 +1,64 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <sys/types.h>
6#include <sys/wait.h>
7#include <sys/syscall.h>
8#include <unistd.h>
9#include <pthread.h>
10
11#define STACK_SIZE (1024 * 1024) // 定义栈大小
12
13// 子任务的入口函数
14void *child_func(void *arg)
15{
16 printf("子任务: PID=%ld, PPID=%ld, TID=%ld\n", (long)getpid(),
17 (long)getppid(), (long)syscall(SYS_gettid));
18 sleep(3);
19}
20
21int main()
22{
23 char *stack; // 栈的指针
24 char *stack_top; // 栈顶的指针
25 pid_t child_tid;
26 pid_t forkPid;
27 pid_t threadPid;
28
29 printf("主任务:我是%d\n", getpid());
30 if ((forkPid = fork()) == 0)
31 {
32 sleep(3);
33 exit(0);
34 }
35 printf("主任务:fork子任务 %d\n", forkPid);
36
37 pthread_create(&threadPid, NULL, child_func, NULL);
38 printf("主任务:create新线程%d\n", threadPid);
39
40 // 使用 clone 创建子任务
41 child_tid = clone(child_func, stack_top, SIGCHLD, NULL);
42 if (child_tid == -1)
43 {
44 perror("clone");
45 free(stack);
46 exit(EXIT_FAILURE);
47 }
48
49 printf("主任务: 创建了子任务, TID=%ld\n", (long)child_tid);
50
51 // 等待子任务结束
52 if (waitpid(child_tid, NULL, 0) == -1)
53 {
54 perror("waitpid");
55 free(stack);
56 exit(EXIT_FAILURE);
57 }
58
59 // 释放分配的栈
60 // free(stack);
61
62 printf("主任务: 子任务结束\n");
63 return 0;
64}