/*
   m00-fuckr.c - fuck rootkit;
   oh.. :) i don't know what to write here..
   
   This code will show you all listened ports on the
   local computer. Even if they are hidden by rootkit.
   The idea is simple up to horror. Look the code and all
   of you will understand =)
   
   For check of ports with numbers from 1 to 1023, you 
   should be root. You remember it? |-]
   
   Ok, but remember about "temp range" ports, which opened 
   for outgoing connections ;) They also will be displayed
   how "listen".
   Hint: outcomes without garbage you recive if will reset
         (dropped) all current outgoing connections

   Tested: Redhat 9.0, Mandrake 8.0, FreeBSD 5.2;
   I think it will work everywhere.
   My english - my death, sorry :)
	 
   PS: the leg of the Akula was here ;)
   
   by / rash / m00 / m00.void.ru /
   
   PLEASE, DO NOT DISRIBUTIVE IT. USE IT FOR YOUSELF, FOR FUN.
*/


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  int fd, i, lent, lenu, opt = 1;
  struct sockaddr_in sin;
  int from, to;
  int listen_tcp[65535];
  int listen_udp[65535];
  
  
  if (argc != 3){
    printf("Usage: %s <from_port> <to_port> \n", argv[0]);
    printf("  Sample: %s 1 65535\n",argv[0]);
    return 0;
  }
  from = atoi(argv[1]);
  to = atoi(argv[2]);
  
  if (from<1||to>65535||from>to){
    printf("Error: invalid port range\n");
    return 0;  
  }else if(from<1024||to<1024) if (getuid()!=0){
    printf("Error: hey!? You must be root for test this range!\n");
    return 0;
  }
  
  printf("Checkinf ports: from %d to %d\n", from, to);
    
    
  /* check tcp proto */
  fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  sin.sin_family = AF_INET;  
  sin.sin_addr.s_addr = 0; 
  lent = -1;
  printf("+Begining TCP..    ");
  fflush(stdout);
  
  for (i=from; i<=to; i++){
    sin.sin_port = htons(i);    
    if (bind(fd,(struct sockaddr *)&sin,sizeof(struct sockaddr))<0){
      if (errno==EADDRINUSE){       /* Addr in use */
        lent+=1;
	listen_tcp[lent] = i;	 
      }
    }else{
      close(fd);
      fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    }
  }
  printf("OK\n");
  
  
  /* check udp proto */
  fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  sin.sin_family = AF_INET;  
  sin.sin_addr.s_addr = 0; 
  lenu = -1;
  printf("+Begining UDP..    ");
  fflush(stdout);
  
  for (i=from; i<=to; i++){
    sin.sin_port = htons(i);    
    if (bind(fd,(struct sockaddr *)&sin,sizeof(struct sockaddr))<0){
      if (errno==EADDRINUSE){     /* Addr in use */
        lenu+=1;
	listen_udp[lenu] = i;
      }
    }else{
      close(fd);
      fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    }
  }
  printf("OK\n");
  
  
  printf("List of listening ports:\n");
  printf("  TCP:\n");
  for(i=0; i<=lent; i++)  printf("    %d - listen\n", listen_tcp[i]);
  printf("  UDP:\n");
  for(i=0; i<=lenu; i++)  printf("    %d - listen\n", listen_udp[i]);  
  printf("That's all :)\n");
}
