This repository has been archived by the owner on Jul 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 57
/
chkproc.c
386 lines (347 loc) · 9.79 KB
/
chkproc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/*
(C) Nelson Murilo - 2004/09/13
Version 0.10
C port from chkproc.pl code from Klaus Steding-Jessen <jessen@nic.br>
and Cristine Hoepers <cristine@nic.br> +little output changes.
2002/03/02 - Segmentation fault in ps for non ASCII user name, by RainbowHat
2002/06/13 Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
- corrected the program return value ;
- added a verbose mode displaying information about the hidden process.
2002/08/08 - Value of MAX_PROCESSES was increased to 99999 (new versions
of FreeBSD, HP-UX and others), reported by Morohoshi Akihiko, Paul
and others.
2002/09/03 - Eliminate (?) false-positives. Original idea from Aaron Sherman.
2002/11/15 - Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
- ported to SunOS.
2003/01/19 - Another Adore based lkm test. Original idea from Junichi Murakami
2003/02/02 - More little fixes - Nelson Murilo
2003/02/23 - Use of kill to eliminate false-positives abandonated, It is
preferable false-positives that false-negatives. Uncomment kill() functions
if you like it.
2003/06/07 - Fix for NPTL threading mechanisms - patch by Mike Griego
2003/09/01 - Fix for ps mode detect, patch by Bill Dupree and others
2004/04/03 - More fix for linux's threads - Nelson Murilo
2004/09/13 - More and more fix for linux's threads - Nelson Murilo
2005/02/23 - More and more and more fix for linux's threads - Nelson Murilo
2005/10/28 - Bug fix for FreeBSD: chkproc was sending a SIGXFSZ (kill -25)
to init, causing a reboot. Patch by Nelson Murilo.
Thanks to Luiz E. R. Cordeiro.
2005/11/15 - Add check for Enye LKM - Nelson Murilo
2005/11/25 - Fix for long lines in PS output - patch by Lantz Moore
2006/01/05 - Add getpriority to identify LKMs, ideas from Yjesus(unhide) and
Slider/Flimbo (skdet)
2006/01/11 - Fix signal 25 on parisc linux and return of kill() -
Thanks to Lantz Moore
2014/07/16 - MAX_PROCESSES now is 999999 -
Thanks to Nico Koenrades
2017/04/13 - MAX_PROCESSES now is 4194384 if linux64
Thanks to DS Store
*/
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__sun)
int main (){ return 0; }
#else
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#if defined(__sun)
#include <procfs.h>
#include <fcntl.h>
#endif
#include <sys/resource.h>
#define PS_SUN 0
#define PS_LOL 1
#define PS_COM 2
#define PS_LNX 3
#define PS_MAX 3
#define ENYELKM "/proc/12345"
// #define ENYELKM "/tmp/12345"
#if defined(__sun)
#define FIRST_PROCESS 0
#else
#define FIRST_PROCESS 1
#endif
#define MAX_PROCESSES 999999
#if defined (__x86_64) > 0
#undef MAX_PROCESSES
#define MAX_PROCESSES 4194384
#endif
#define MAX_BUF 1024
#if !defined (SIGXFSZ)
#define SIGXFSZ 25
#endif
static char *ps_cmds[] = {
"ps -edf",
"ps auxw",
"ps mauxw 2>&1 ",
"ps auxw -T|tr -s ' '|cut -d' ' -f2-",
};
int psproc [MAX_PROCESSES+1];
int dirproc[MAX_PROCESSES+1];
#if defined(__linux__)
int isathread[MAX_PROCESSES+1];
#endif
/*
* read at most the first (size-1) chars into s and terminate with a '\0'.
* stops reading after a newline or EOF. if a newline is read, it will be
* the last char in the string. if no newline is found in the first
* (size-1) chars, then keep reading and discarding chars until a newline
* is found or EOF.
*/
char *readline(char *s, int size, FILE *stream)
{
char *rv = fgets(s, size, stream);
if (strlen(s) == (size-1) && s[size-1] != '\n')
{
char buf[MAX_BUF];
fgets(buf, MAX_BUF, stream);
while (strlen(buf) == (MAX_BUF-1) && buf[MAX_BUF-1] != '\n')
{
fgets(buf, MAX_BUF, stream);
}
}
return rv;
}
int main(int argc, char **argv)
{
char buf[MAX_BUF], *p, path[MAX_BUF];
char *pscmd = (char *)0;
FILE *ps;
DIR *proc = opendir("/proc");
struct dirent *dir;
struct stat sb;
int i, j, retps, retdir, pv, verbose;
long ret = 0L;
char * tmp_d_name;
#if defined(__linux__)
int maybeathread;
#endif
#if defined(__sun)
psinfo_t psbuf;
#endif
pv = verbose = 0;
if (!proc)
{
perror("proc");
exit (1);
}
for (i = 1; i < argc; i++)
{
if (!memcmp(argv[i], "-v", 2))
verbose++;
else if (!memcmp(argv[i], "-?", 2))
{
printf("Usage: %s [-v] [-v] -p <num>\n", argv[0]);
return 0;
}
#if defined(__linux__)
else if (!memcmp(argv[i], "-p", 2))
{
if (i+1 < argc)
pv = atoi(argv[++i]);
else
{
printf("Usage: %s [-v] [-v] [-p procps version]\n", argv[0]);
return 0;
}
}
#endif
}
#if defined(__sun)
pscmd = ps_cmds[PS_SUN];
#elif !defined (__linux__)
pscmd = ps_cmds[PS_COM];
#endif
#if defined(__linux__)
if (pv < 1 || pv > PS_MAX)
pv = 1;
pscmd = ps_cmds[pv];
/* printf("pv = %d\n\r", pv); /* -- DEBUG */
#endif
/* printf("pscmd = %s\n\r", pscmd); /* -- DEBUG */
if (!(ps = popen(pscmd, "r")))
{
perror("ps");
exit(errno);
}
*buf = 0;
readline(buf, MAX_BUF, ps); /* Skip header */
#if defined(__sun)
if (!isspace(*buf))
#else
if (!isalpha(*buf))
#endif
{
readline(buf, MAX_BUF, ps); /* Skip header */
if (!isalpha(*buf) && pv != PS_LNX)
{
if (pv != PS_LOL)
execlp(argv[0], argv[0], "-p 1", NULL);
fprintf(stderr, "OooPS!\n");
exit(2);
}
}
if (!memcmp(buf, "ps:", 3) && (pv != PS_LOL))
execlp(argv[0], argv[0], "-p 1", NULL);
for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++) { /* Init matrix */
psproc[i] = dirproc[i] = 0;
#if defined(__linux__)
isathread[i] = 0;
#endif
}
while (readline(buf, MAX_BUF, ps))
{
p = buf;
#if defined(__sun)
while (isspace(*p)) /* Skip spaces */
p++;
#endif
while (!isspace(*p)) /* Skip User */
p++;
while (isspace(*p)) /* Skip spaces */
p++;
/* printf(">>PS %s<<\n", p); /* -- DEBUG */
ret = atol(p);
if ( ret < 0 || ret > MAX_PROCESSES )
{
fprintf (stderr, " OooPS, not expected %ld value\n", ret);
exit (2);
}
psproc[ret] = 1;
}
pclose(ps);
while ((dir = readdir(proc)))
{
#if defined(__linux__)
maybeathread = 0;
#endif
tmp_d_name = dir->d_name;
if (!strcmp(tmp_d_name, ".") || !strcmp(tmp_d_name, ".."))
continue;
#if defined(__linux__)
if (*tmp_d_name == '.') { /* here we catch the new NTPL threads in linux. They are listed in /proc as PIDs with a period prepended */
tmp_d_name++;
maybeathread = 1;
}
#endif
if(!isdigit(*tmp_d_name))
continue;
#if defined(__linux__)
else if (maybeathread) {
isathread[atol(tmp_d_name)] = 1; /* mark it as a linux NTPL thread if it's in the form of "\.[0-9]*" */
if (verbose)
printf("%ld is a Linux Thread, marking as such...\n", atol(tmp_d_name));
}
#endif
/* printf("%s\n", tmp_d_name); /* -- DEBUG */
dirproc[atol(tmp_d_name)] = 1;
}
closedir(proc);
/* Brute force */
strcpy(buf, "/proc/");
retps = retdir = 0;
for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++)
{
// snprintf(&buf[6], 6, "%d", i);
snprintf(&buf[6], 8, "%d", i);
if (!chdir(buf))
{
if (!dirproc[i] && !psproc[i])
{
#if defined(__linux__)
if (!isathread[i]) {
#endif
retdir++;
if (verbose)
printf ("PID %5d(%s): not in readdir output\n", i, buf);
#if defined(__linux__)
}
#endif
}
if (!psproc[i] ) /* && !kill(i, 0)) */
{
#if defined(__linux__)
if(!isathread[i]) {
#endif
retps++;
if (verbose)
printf ("PID %5d: not in ps output\n", i);
#if defined(__linux__)
}
#endif
}
#if defined(__linux__)
if(!isathread[i]) {
#endif
/* if ((!dirproc[i] || !psproc[i]) && !kill(i, 0) && (verbose > 1)) */
if ((!dirproc[i] || !psproc[i]) && (verbose > 1))
{
#if defined(__linux__)
j = readlink ("./cwd", path, sizeof(path));
path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
printf ("CWD %5d: %s\n", i, path);
j = readlink ("./exe", path, sizeof(path));
path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
printf ("EXE %5d: %s\n", i, path);
#elif defined(__FreeBSD__)
j = readlink ("./file", path, sizeof(path));
path[(j < sizeof(path)) ? j : sizeof(path) - 1] = 0;
printf ("FILE %5d: %s\n", i, path);
#elif defined(__sun)
if ((j = open("./psinfo", O_RDONLY)) != -1)
{
if (read(j, &psbuf, sizeof(psbuf)) == sizeof(psbuf))
printf ("PSINFO %5d: %s\n", i, psbuf.pr_psargs);
else
printf ("PSINFO %5d: unknown\n", i);
close(j);
}
else
printf ("PSINFO %5d: unknown\n", i);
#endif
}
#if defined(__linux__)
}
#endif
}
#ifndef __FreeBSD__
else
{
errno = 0;
getpriority(PRIO_PROCESS, i);
if (!errno)
{
retdir++;
if (verbose)
printf ("PID %5d(%s): not in getpriority readdir output\n", i, buf);
}
}
#endif
}
if (retdir)
printf("You have % 5d process hidden for readdir command\n", retdir);
if (retps)
printf("You have % 5d process hidden for ps command\n", retps);
#if defined(__linux__)
kill(1, 100); /* Check for SIGINVISIBLE Adore signal */
if (kill (1, SIGXFSZ) < 0 && errno == 3)
{
printf("SIGINVISIBLE Adore found\n");
retdir+= errno;
}
/* Check for Enye LKM */
if (stat(ENYELKM, &sb) && kill (12345, 58) >= 0)
{
printf("Enye LKM found\n");
retdir+= errno;
}
#endif
return (retdir+retps);
}
#endif