~ubuntu-branches/ubuntu/vivid/unhide/vivid

« back to all changes in this revision

Viewing changes to unhide-tcp.c

  • Committer: Package Import Robot
  • Author(s): Julien Valroff
  • Date: 2013-02-15 19:14:05 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20130215191405-rq074t0t0wo9bkdj
Tags: 20121229-1
* New upstream release
* Add unhide_rb and unhide-posix to the package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
          http://www.unhide-forensics.info
3
3
*/
4
4
 
23
23
#include <sys/socket.h>
24
24
#include <netinet/in.h>
25
25
#include <errno.h>
26
 
 
 
26
#include <getopt.h>
27
27
#include <string.h>
28
28
#include <unistd.h>
 
29
#include <time.h>
 
30
#include <sys/time.h>
 
31
#include <sys/resource.h>
 
32
 
 
33
#include "unhide-output.h"
 
34
#include "unhide-tcp.h"
 
35
 
 
36
// header
 
37
const char header[] =
 
38
       "Unhide-tcp 20121229\n"
 
39
       "Copyright © 2012 Yago Jesus & Patrick Gouin\n"
 
40
       "License GPLv3+ : GNU GPL version 3 or later\n"
 
41
       "http://www.unhide-forensics.info\n";
 
42
 
 
43
// options
 
44
int verbose = 0;
 
45
int use_fuser = 0;
 
46
int use_lsof = 0;
 
47
int use_ss = 1;   // use ss by default
 
48
int use_quick = 0;
 
49
 
 
50
char checker[10] = "ss" ;
 
51
 
 
52
// Temporary string for output
 
53
char scratch[1000];
 
54
 
 
55
// Temporary string for output
 
56
char used_options[1000] = "";
 
57
 
 
58
// For logging to file
 
59
int logtofile = 0;
 
60
FILE *unlog;
 
61
 
 
62
// Global hidden port counter, used only to set the exit code of the program
 
63
int hidden_found;
29
64
 
30
65
 
31
66
/* thx aramosf@unsec.net for the nice regexp! */
32
67
 
33
68
// Linux
34
 
char tcpcommand[]= "netstat -tan | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
35
 
char udpcommand[]= "netstat -uan | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
36
 
 
37
 
 
 
69
char tcpcommand1[]= "netstat -tan | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
 
70
char udpcommand1[]= "netstat -uan | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
 
71
 
 
72
// Alternative commands, needs iproute2
 
73
char tcpcommand2[]= "ss -tan sport = :%d | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
 
74
char udpcommand2[]= "ss -uan sport = :%d | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
 
75
 
 
76
// fuser commands
 
77
char fuserTCPcommand[]= "fuser -v -n tcp %d 2>&1" ;
 
78
char fuserUDPcommand[]= "fuser -v -n udp %d 2>&1" ;
 
79
 
 
80
// lsof commands
 
81
char lsofTCPcommand[]= "lsof +c 0 -iTCP:%d" ;
 
82
char lsofUDPcommand[]= "lsof +c 0 -iUDP:%d" ;
38
83
 
39
84
// OpenBSD
40
85
// char tcpcommand[]= "netstat -an -p tcp | sed -e '/[\\.:][0-9]/!d' -e 's/.*[\\.:]\\([0-9]*\\) .*[\\.:].*/\\1/'" ;
47
92
 
48
93
 
49
94
 
50
 
void checkport(int port, char command[]) {
51
 
 
52
 
        int statusfile;
53
 
        int statcommand;
54
 
        int ok = 0;
55
 
        char ports[30];
56
 
        char compare[100];
57
 
 
58
 
        FILE *fich_tmp ;
59
 
 
60
 
        fich_tmp=popen (command, "r") ;
61
 
 
62
 
 
63
 
        while (!feof(fich_tmp) && ok == 0) {
64
 
 
65
 
                fgets(ports, 30, fich_tmp);
66
 
 
67
 
                sprintf(compare,"%i\n",port);
68
 
 
69
 
                if (strcmp(ports, compare) == 0) {ok = 1;}
70
 
 
71
 
 
72
 
        }
73
 
 
74
 
        pclose(fich_tmp);
75
 
 
76
 
        if ( ok == 0 ) {
77
 
 
78
 
                printf ("Found Hidden port that not appears in netstat: %i\n", port) ;
79
 
 
80
 
        }
81
 
 
82
 
}
83
 
 
84
 
 
85
 
int main() {
86
 
 
87
 
 
88
 
        int i ;
89
 
        int u ;
90
 
 
91
 
        printf ("Unhide 20110113\n") ;
92
 
        printf ("http://www.unhide-forensics.info\n\n\n") ;
93
 
 
94
 
        printf ("Starting TCP checking\n\n") ;
95
 
 
96
 
        for (i =1; i < 65535; i++) {
97
 
 
98
 
                int socket_desc;
99
 
                struct sockaddr_in address;
100
 
 
101
 
 
102
 
                socket_desc=socket(AF_INET,SOCK_STREAM,0);
103
 
 
104
 
                address.sin_family = AF_INET;
105
 
                address.sin_addr.s_addr = INADDR_ANY;
106
 
                address.sin_port = htons(i);
107
 
                errno= 0 ;
108
 
                bind(socket_desc,(struct sockaddr *)&address,sizeof(address));
109
 
                listen(socket_desc,1);
110
 
 
111
 
                if ( errno != 0) {
112
 
 
113
 
                        close(socket_desc);
114
 
 
115
 
                        checkport(i, tcpcommand);
116
 
 
117
 
                }
118
 
 
119
 
                close(socket_desc);
120
 
        }
121
 
 
122
 
        printf ("Starting UDP checking\n\n") ;
123
 
 
124
 
 
125
 
        for (u =1; u < 65535; u++) {
126
 
 
127
 
                int socket_desc;
128
 
                struct sockaddr_in address;
129
 
 
130
 
 
131
 
                socket_desc=socket(AF_INET,SOCK_DGRAM,0);
132
 
 
133
 
                address.sin_family = AF_INET;
134
 
                address.sin_addr.s_addr = INADDR_ANY;
135
 
                address.sin_port = htons(u);
136
 
                errno= 0 ;
137
 
                bind(socket_desc,(struct sockaddr *)&address,sizeof(address));
138
 
 
139
 
                if ( errno != 0) {
140
 
 
141
 
                        close(socket_desc);
142
 
 
143
 
                        checkport(u, udpcommand);
144
 
 
145
 
                }
146
 
 
147
 
                close(socket_desc);
148
 
        }
 
95
/*
 
96
 *  Run a command to get more information about a port. 
 
97
 */
 
98
static void print_info(const char *prog_name, const char *command_fmt, int port)
 
99
{
 
100
 
 
101
   char buffer[1000];
 
102
   FILE* fp;
 
103
 
 
104
   sprintf(buffer, command_fmt, port);
 
105
   fp = popen(buffer, "r") ;
 
106
 
 
107
   if (NULL == fp)
 
108
   {
 
109
      warnln(verbose, unlog, "Couldn't run command: %s", buffer) ;
 
110
      return ;
 
111
   }
 
112
 
 
113
   msgln(unlog, 1, "%s reports :", prog_name) ;
 
114
 
 
115
   while (NULL != fgets(buffer, 1000, fp))
 
116
   {
 
117
      msgln(unlog, 1, buffer) ;
 
118
   }
 
119
 
 
120
   pclose(fp);
 
121
}
 
122
 
 
123
/* Print a port, optionally querying info about it via lsof or fuser. */
 
124
void print_port(enum Proto proto, int port)
 
125
{
 
126
      msgln(unlog, 0, "\nFound Hidden port that not appears in %s: %i", checker, port) ;
 
127
      if (1 == use_fuser)
 
128
      {
 
129
         if (TCP == proto)
 
130
         {
 
131
            print_info("fuser", fuserTCPcommand, port);
 
132
         }
 
133
         else
 
134
         {
 
135
            print_info("fuser", fuserUDPcommand, port);
 
136
         }
 
137
      }
 
138
      if (1 == use_lsof)
 
139
      {
 
140
         if (TCP == proto)
 
141
         {
 
142
            print_info("lsof", lsofTCPcommand, port);
 
143
         }
 
144
         else
 
145
         {
 
146
            print_info("lsof", lsofUDPcommand, port);
 
147
         }
 
148
      }
 
149
}
 
150
 
 
151
 
 
152
/*
 
153
 * Check if port is seen by netstat.
 
154
 *
 
155
 * If not, report it and optionnally run lsof and/or fuser
 
156
 * to show more info.
 
157
 */
 
158
int checkoneport(int port, char command[], enum Proto proto)
 
159
{
 
160
   int ok = 0;
 
161
   char ports[30];
 
162
   char compare[100];
 
163
 
 
164
   FILE *fich_tmp ;
 
165
 
 
166
   if (NULL != (fich_tmp=popen (command, "r")))
 
167
   {
 
168
      sprintf(compare,"%i\n",port);
 
169
      while ((NULL != fgets(ports, 30, fich_tmp)) && ok == 0) {
 
170
         if (strcmp(ports, compare) == 0) {ok = 1;}
 
171
      }
 
172
      pclose(fich_tmp);
 
173
   }
 
174
   else
 
175
   {
 
176
      die(unlog, "Couldn't execute command : %s while checking port %d", command, port) ;
 
177
   }
 
178
   return(ok) ;
 
179
}
 
180
 
 
181
/*
 
182
 * Check all TCP ports one by one.
 
183
 */
 
184
static void print_hidden_TCP_ports_1_by_1(enum Proto proto)
 
185
{
 
186
   int i ;
 
187
   char tcpcommand[512] ;
 
188
 
 
189
   hidden_found = 0 ;
 
190
   for (i =1; i <= 65535; i++)
 
191
   {
 
192
      int socket_desc;
 
193
      struct sockaddr_in address;
 
194
 
 
195
      if ( -1 != (socket_desc=socket(AF_INET,SOCK_STREAM,0)))
 
196
      {
 
197
         address.sin_family = AF_INET;
 
198
         address.sin_addr.s_addr = INADDR_ANY;
 
199
         address.sin_port = htons(i);
 
200
         errno= 0 ;
 
201
         if ( -1 != bind(socket_desc,(struct sockaddr *)&address,sizeof(address)))
 
202
         {
 
203
            listen(socket_desc,1);
 
204
            if ( EADDRINUSE == errno )    // port is listened by another process
 
205
            {
 
206
               if (1 == use_ss)
 
207
               {
 
208
                  sprintf(tcpcommand, tcpcommand2, i) ;
 
209
               }
 
210
               else
 
211
               {
 
212
                  strncpy(tcpcommand, tcpcommand1, 512) ;
 
213
               }
 
214
               if (0 == checkoneport(i, tcpcommand, TCP))
 
215
               {
 
216
                  // test again
 
217
                  listen(socket_desc,1);
 
218
                  if ( EADDRINUSE == errno )    // port is still listened by another process
 
219
                  {
 
220
                     hidden_found++;
 
221
                     print_port(proto, i) ;
 
222
                  }
 
223
               }
 
224
               close(socket_desc);
 
225
            }
 
226
            else
 
227
            {
 
228
               close(socket_desc);
 
229
            }
 
230
         }
 
231
         else
 
232
         {
 
233
            if (EADDRINUSE == errno)    //port is in use by another process
 
234
            {
 
235
               if (1 == use_ss)
 
236
               {
 
237
                  sprintf(tcpcommand, tcpcommand2, i) ;
 
238
               }
 
239
               else
 
240
               {
 
241
                  strncpy(tcpcommand, tcpcommand1, 512) ;
 
242
               }
 
243
               if (0 == checkoneport(i, tcpcommand, TCP))
 
244
               {
 
245
                  // test again
 
246
                  if ( -1 == bind(socket_desc,(struct sockaddr *)&address,sizeof(address)))
 
247
                  {
 
248
                     if ( EADDRINUSE == errno )    // port is still used by another process
 
249
                     {
 
250
                        hidden_found++;
 
251
                        print_port(proto, i) ;
 
252
                     }
 
253
                     else
 
254
                     {
 
255
                        warnln(verbose, unlog, "can't bind to socket while checking port %d", i) ;
 
256
                     }
 
257
                     close(socket_desc);
 
258
                  }
 
259
               }
 
260
               else
 
261
               {
 
262
                  close(socket_desc);
 
263
               }
 
264
            }
 
265
         }
 
266
      }
 
267
      else
 
268
      {
 
269
         warnln(verbose, unlog, "can't create socket while checking port %d/tcp", i) ;
 
270
      }
 
271
   }
 
272
}
 
273
 
 
274
/*
 
275
 * Check all UDP ports one by one.
 
276
 */
 
277
static void print_hidden_UDP_ports_1_by_1(enum Proto proto)
 
278
{
 
279
   int u ;
 
280
   char udpcommand[512] ;
 
281
 
 
282
   hidden_found = 0 ;
 
283
 
 
284
   for (u = 1; u <= 65535; u++)
 
285
   {
 
286
      int socket_desc;
 
287
      struct sockaddr_in address;
 
288
 
 
289
      if ( -1 != (socket_desc=socket(AF_INET,SOCK_DGRAM,0)))
 
290
      {
 
291
         address.sin_family = AF_INET;
 
292
         address.sin_addr.s_addr = INADDR_ANY;
 
293
         address.sin_port = htons(u);
 
294
         errno= 0 ;
 
295
         if ( 0 != bind(socket_desc,(struct sockaddr *)&address,sizeof(address)))
 
296
         {
 
297
            if ( EADDRINUSE == errno )   //port is in use by another process
 
298
            {
 
299
               if (1 == use_ss)
 
300
               {
 
301
                  sprintf(udpcommand, udpcommand2, u) ;
 
302
               }
 
303
               else
 
304
               {
 
305
                  strncpy(udpcommand, udpcommand1, 512) ;
 
306
               }
 
307
               ;
 
308
               if (0 == checkoneport(u, udpcommand, UDP))
 
309
               {
 
310
                  // test again
 
311
                  if ( 0 != bind(socket_desc,(struct sockaddr *)&address,sizeof(address)))    // port is still in use by another process
 
312
                  {
 
313
                     if ( EADDRINUSE == errno )   //port is in use by another process
 
314
                     {
 
315
                        hidden_found++;
 
316
                        print_port(proto, u) ;
 
317
                     }
 
318
                  }
 
319
               }
 
320
               close(socket_desc);
 
321
            }
 
322
            else      // other error
 
323
            {
 
324
               close(socket_desc);
 
325
               warnln(verbose, unlog, "can't bind to socket while checking port %d", u) ;
 
326
            }
 
327
         }
 
328
         else  // port is available
 
329
         {
 
330
            close(socket_desc);
 
331
         }
 
332
      }
 
333
      else 
 
334
      {
 
335
         warnln(verbose, unlog, "can't create socket while checking port %d/udp", u) ;
 
336
      }
 
337
   }
 
338
}
 
339
 
 
340
 
 
341
/*
 
342
 * Print usage. 
 
343
 */
 
344
void usage(char * command) {
 
345
 
 
346
   printf("Usage: %s [options] \n\n", command);
 
347
   printf("Options :\n");
 
348
   printf("   -V          Show version and exit\n");
 
349
   printf("   -v          verbose\n");
 
350
   printf("   -h          display this help\n");
 
351
   printf("   -f          show fuser output for hidden ports\n");
 
352
   printf("   -l          show lsof output for hidden ports\n");
 
353
   printf("   -o          log result into unhide-tcp.log file\n");
 
354
   printf("   -s          use very quick version for server with lot of opened ports\n");
 
355
   printf("   -n          use netstat instead of ss\n");
 
356
}
 
357
 
 
358
/*
 
359
 * Parse command line arguments (exiting if requested by any option).
 
360
 */
 
361
void parse_args(int argc, char **argv) 
 
362
{
 
363
   int c = 0;
 
364
   
 
365
   static struct option long_options[] =
 
366
   {
 
367
   /* These options set a flag. */
 
368
      {"verbose",  no_argument,      &verbose,   1},
 
369
      {"brief",    no_argument,      &verbose,   0},
 
370
      {"fuser",    no_argument,      &use_fuser, 1},
 
371
      {"lsof",     no_argument,      &use_lsof,  1},
 
372
      {"log",      no_argument,      &logtofile, 1},
 
373
      {"netstat",  no_argument,      &use_ss,    0},
 
374
      {"server",   no_argument,      &use_quick, 1},
 
375
      /* These options don't set a flag.
 
376
         We distinguish them by their indices. */
 
377
      {"help",     no_argument,      0,        'h'},
 
378
      {"version",  no_argument,      0,        'V'},
 
379
      {0, 0, 0, 0}
 
380
   };
 
381
 
 
382
   for(;;)  // until there's no more option
 
383
   {
 
384
      /* getopt_long stores the option index here. */
 
385
      int option_index = 0;
 
386
 
 
387
      c = getopt_long (argc, argv, "Vvhflosn",
 
388
                        long_options, &option_index);
 
389
 
 
390
      /* Detect the end of the options. */
 
391
      if (c == -1)
 
392
         break;
 
393
 
 
394
      switch(c)
 
395
      {
 
396
      case 0 :   // flag long options
 
397
         if (long_options[option_index].flag != 0) //if this option set a flag
 
398
         {
 
399
            break;  // nothing to do
 
400
         }
 
401
         printf ("option %s", long_options[option_index].name);
 
402
         if (optarg) // if there's an argument
 
403
         {
 
404
            printf (" with arg %s", optarg);
 
405
         }
 
406
         printf ("\n");
 
407
         break ;
 
408
      case 'f' :
 
409
         use_fuser = 1 ;
 
410
         break ;
 
411
      case 'h' :
 
412
         usage(argv[0]) ;
 
413
         exit (0) ;
 
414
         break ;
 
415
      case 'l' :
 
416
         use_lsof = 1 ;
 
417
         break;
 
418
      case 'o' :
 
419
         logtofile = 1 ;
 
420
         break ;
 
421
      case 's' :
 
422
         use_quick = 1 ;
 
423
         break ;
 
424
      case 'n' :
 
425
         use_ss = 0 ;
 
426
         break ;
 
427
      case 'v' :
 
428
         verbose++ ; ;
 
429
         break ;
 
430
      case 'V' :
 
431
         exit (0) ;
 
432
         break ;
 
433
      case '?' :     // invalid option
 
434
         exit (2) ;
 
435
         break ;
 
436
      default :      // something very nasty happened
 
437
         exit(-1) ;
 
438
         break ;
 
439
      }
 
440
     
 
441
   }
 
442
   
 
443
   // generate options string for logging
 
444
   strncpy(used_options, "Used options: ", 1000);
 
445
   if (verbose)
 
446
      strncat(used_options, "verbose ", 1000-1-strlen(used_options));
 
447
   if (use_lsof)
 
448
      strncat(used_options, "use_lsof ", 1000-1-strlen(used_options));
 
449
   if (use_fuser)
 
450
      strncat(used_options, "use_fuser ", 1000-1-strlen(used_options));
 
451
   if (!use_ss)
 
452
      strncat(used_options, "use_netscape ", 1000-1-strlen(used_options));
 
453
   if (use_quick)
 
454
      strncat(used_options, "use_quick ", 1000-1-strlen(used_options));
 
455
   if (logtofile)
 
456
      strncat(used_options, "logtofile ", 1000-1-strlen(used_options));
 
457
}
 
458
 
 
459
/*
 
460
 * Look for TCP and UDP ports that are hidden to netstat.
 
461
 *
 
462
 * Returns 0 if none is found, 1 if there is some internal error, 4 if TCP
 
463
 * hidden ports were found, 8 if UDP hidden ports were found or 12 (4 & 8) if
 
464
 * both were found.
 
465
 */
 
466
int main(int argc, char  **argv) 
 
467
{
 
468
   int ret_code = 0;
 
469
 
 
470
   printf(header) ;
 
471
 
 
472
   if(getuid() != 0){
 
473
      die(unlog, "You must be root to run %s !", argv[0]) ;
 
474
   }
 
475
 
 
476
   parse_args(argc, argv) ;
 
477
   
 
478
   if (1 == logtofile) 
 
479
   {
 
480
      unlog = init_log(logtofile, header, "unhide-tcp") ;
 
481
   }
 
482
   msgln(unlog, 0, used_options) ;
 
483
 
 
484
   if (1 == use_ss)
 
485
   {
 
486
      strncpy(checker, "ss", 10);
 
487
   }
 
488
   else
 
489
   {
 
490
      strncpy(checker, "netstat", 10);
 
491
   }
 
492
   
 
493
   setpriority(PRIO_PROCESS,0,-20);  /* reduce risk of race condition - may fail, dont care */
 
494
   
 
495
   msgln(unlog, 0, "[*]Starting TCP checking") ;
 
496
   if (1 == use_quick)
 
497
   {
 
498
      print_hidden_ports(TCP);
 
499
   }
 
500
   else
 
501
   {
 
502
      print_hidden_TCP_ports_1_by_1(TCP) ;
 
503
   }
 
504
   if (hidden_found)
 
505
   {
 
506
      ret_code += 4;
 
507
   }
 
508
 
 
509
   msgln(unlog, 0, "[*]Starting UDP checking") ;
 
510
   if (1 == use_quick)
 
511
   {
 
512
      print_hidden_ports(UDP);
 
513
   }
 
514
   else
 
515
   {
 
516
      print_hidden_UDP_ports_1_by_1(UDP) ;
 
517
   }
 
518
   if (hidden_found)
 
519
   {
 
520
      ret_code += 8;
 
521
   }
 
522
 
 
523
   if (logtofile == 1)
 
524
   {
 
525
      close_log(unlog, "unhide-tcp") ;
 
526
   }
 
527
   return(ret_code);
149
528
 
150
529
}
151
530