sipcrack-0.2/0000755000175000017500000000000010571617453010103 5ustar sipcrack-0.2/CHANGELOG0000644000175000017500000000060710571617450011315 0ustar 0.2: sipcrack: * Added support for qop/cnonce/nonce_count * Changed usage * Cleanup sipdump: * Changed usage * Option '-f' to support custom filter * Added method detection * Added support for qop/cnonce/nonce_count * Major cleanup generic: * Added support for Proxy-Authorization and Authorization * Using non-fixed-size login data * Added debug * Cleanup 0.1: * Initial sipcrack-0.2/pcapstuff.h0000644000175000017500000000335410567700640012250 0ustar /* Copyright (C) 2007 Martin J. Muench */ #ifndef SIPCRACK_PCACSTUFF_H #define SIPCRACK_PCAPSTUFF_H /* pcap stuff */ #define SNAP_LEN 1518 #define SIZE_ETHERNET 14 #define ETHER_ADDR_LEN 6 /* Ethernet header */ struct ethernet_header { unsigned char ether_dhost[ETHER_ADDR_LEN]; unsigned char ether_shost[ETHER_ADDR_LEN]; unsigned short ether_type; }; /* IP header */ struct ip_header { unsigned char ip_vhl; unsigned char ip_tos; unsigned short ip_len; unsigned short ip_id; unsigned short ip_off; #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ unsigned char ip_ttl; unsigned char ip_p; unsigned short ip_sum; struct in_addr ip_src,ip_dst; }; #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f) #define IP_V(ip) (((ip)->ip_vhl) >> 4) /* TCP header */ typedef unsigned int tcp_seq; struct tcp_header { unsigned short th_sport; unsigned short th_dport; tcp_seq th_seq; tcp_seq th_ack; unsigned char th_offx2; #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4) unsigned char th_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) unsigned short th_win; unsigned short th_sum; unsigned short th_urp; }; struct udp_header { u_int16_t uh_sport; u_int16_t uh_dport; u_int16_t uh_ulen; u_int16_t uh_sum; }; #endif /* SIPCRACK_PCAPSTUFF_H */ sipcrack-0.2/LICENSE0000644000175000017500000000271010567700640011104 0ustar Copyright (c) 2007 Martin J. Muench. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistribution of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistribution in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sipcrack-0.2/Makefile0000644000175000017500000000144410571617245011545 0ustar CC = gcc FLAGS = -O2 #-DDEBUG -g -Wall -pedantic LIBS = LIBSSL = -lcrypto LIBPCAP = -lpcap SIPCRACK = SIPcrack.c SIPDUMP = SIPdump.c OBJS = wrap.o debug.o MD5 = md5.o .PHONY: default no-openssl clean .c.o: ${CC} ${FLAGS} -c $< default: ${SIPCRACK} ${SIPDUMP} ${OBJS} ${CC} ${FLAGS} -o sipcrack ${OBJS} ${SIPCRACK} ${LIBS} ${LIBSSL} ${CC} ${FLAGS} -o sipdump ${OBJS} ${SIPDUMP} ${LIBS} ${LIBPCAP} strip sipcrack sipdump @echo \* All done no-openssl: ${SIPCRACK} ${SIPDUMP} ${OBJS} ${MD5} ${CC} ${FLAGS} -o sipcrack -DNO_OPENSSL ${OBJS} ${MD5} ${SIPCRACK} ${LIBS} ${CC} ${FLAGS} -o sipdump ${OBJS} ${SIPDUMP} ${LIBS} ${LIBPCAP} strip sipcrack sipdump @echo \* All done clean: rm -f sipdump sipcrack *.o SIPcrack.o: global.h wrap.h SIPdump.o: global.h wrap.h sipcrack-0.2/README0000644000175000017500000000256010567700640010762 0ustar [ SIPcrack ] -[ Introduction SIPcrack is a suite for sniffing and cracking the digest authentification used in the SIP protocol. For more details regarding the digest authentication mechanism see: RFC3261 - SIP: Session Initiation Protocol RFC2617 - HTTP Authentication: Basic and Digest Access Authentication -[ Compile Just type 'make'. If you don't have OpenSSL installed or encounter any building problems try 'make no-openssl' to build with integrated MD5 function (which is slower than the OpenSSL implementation). -[ Usage Use sipdump to dump SIP digest authentications to a file. If a login is found, the sniffed login is written to the dump file. See 'sipdump -h' for options. Use sipcrack to bruteforce the user password using the dump file generated by sipdump. If a password is found, the sniffed login in the dump file is updated See 'sipcrack -h' for options. USAGE_EXAMPLES contains some extended usage examples. -[ Support && Bugs If you find any SIP logins that sipdump does not detect or sipcrack is not able to crack please create a packet dump: e.g. 'tcpdump -s 0 -w packetdump.txt tcp or udp') ...and send it to mjm'at'codito.de! NOTE: For this purpose use a wrong password and include it in your bug report. -[ Author Martin J. Muench Mail: mjm'at'codito.de Web: www.codito.de | www.remote-exploit.org -[ Thanks Max Moser Lucian Hanga sipcrack-0.2/SIPcrack.c0000644000175000017500000002742310571616774011723 0ustar /* * Copyright (C) 2007 Martin J. Muench * * SIP digest authentication password (hash) cracker */ #include #include #include #include #include #include #ifdef NO_OPENSSL # include "md5.h" #else # include #endif #include "global.h" #include "wrap.h" #include "debug.h" int opterr = 0; /* shutup getopt() */ /* Local functions */ static int get_login_data(login_t *, const char *); static int crack_login_data(login_t *, const char *, char *, int, int); static int parse_sniffed_line(login_t *, char *); static void usage(const char *); /* * sipcrack main */ int main(int argc, char *argv[]) { int c, use_stdin=0, print_process=0; char *wordlist_file=NULL, *dump_file=NULL; char cracked_pass[PW_MAXLEN]; login_t login_info; memset(&login_info, 0, sizeof(login_info)); printf("\nSIPcrack %s ( MaJoMu | www.codito.de ) \n" \ "----------------------------------------\n\n", VERSION); /* Parse command line */ while((c = getopt(argc, argv, "w:p:s")) != -1) { switch(c) { case 'w': wordlist_file = (char *)Malloc(strlen(optarg)+1); strcpy(wordlist_file, optarg); break; case 's': use_stdin = 1; break; case 'p': print_process = atoi(optarg); break; default: usage("Invalid arguments"); } } /* Check for mode */ if((wordlist_file == NULL && !use_stdin) || (wordlist_file != NULL && use_stdin)) usage("Either -w or -s has to be given"); /* Get dump file */ argv += optind; argc -= optind; if(argc != 1) { SAFE_DELETE(wordlist_file); usage("You need to specify dump file"); } dump_file = (char *)Malloc(strlen(argv[0])+1); strcpy(dump_file, argv[0]); /* Get Login data that shall be cracked */ debug(("Reading and parsing dump file...\n")); if(get_login_data(&login_info, dump_file) < 0) { SAFE_DELETE(wordlist_file); SAFE_DELETE(dump_file); exit(EXIT_FAILURE); } /* Start main cracking function */ if(crack_login_data(&login_info, wordlist_file, cracked_pass, use_stdin, print_process) == 1) { printf("* Updating dump file '%s'... ", dump_file); fflush(stdout); update_login_data(&login_info, cracked_pass, dump_file); printf("done\n"); } /* Clean up and exit */ SAFE_DELETE(wordlist_file); SAFE_DELETE(dump_file); exit(EXIT_SUCCESS); } /* * Display content of dump file and request selection from user */ static int get_login_data(login_t *login_info, const char *dump_file) { FILE *lfile=NULL; char buffer[LOGIN_MAXLEN], input[8]; char *login_buffer=NULL; login_t *login_ptr; unsigned int i=0, j=0, use=0; login_buffer = Malloc(sizeof(login_t)); login_ptr = (login_t*)login_buffer; /* Open dump file */ if((lfile = fopen(dump_file, "r")) == NULL) { fprintf(stderr, "* Cannot open dump file: %s\n", strerror(errno)); SAFE_DELETE(login_buffer); return -1; } /* Parse each line from dump file */ while((fgets(buffer, sizeof(buffer), lfile)) != NULL) { /* Copy buffer to struct, if fails ignore line */ if(parse_sniffed_line(login_ptr, buffer) < 0) continue; i++; /* Increase buffer as we have more lines */ login_buffer = Realloc(login_buffer, sizeof(login_t) * (i + 1)); login_ptr = (login_t*)(login_buffer + sizeof(login_t) * i); } fclose(lfile); /* We found any logins? */ if(!i) { printf("* No sniffed logins found, exiting\n"); SAFE_DELETE(login_buffer); return -1; } /* Print parsed login data */ printf("* Found Accounts:\n\nNum\tServer\t\tClient\t\tUser\tHash|Password\n\n"); for(j = 0 ; j < i ; j++) { login_ptr = (login_t*)(login_buffer + sizeof(login_t) * j); printf("%d\t%s\t%s\t%s\t%s\n", j + 1, login_ptr->server, login_ptr->client, login_ptr->user, login_ptr->hash ); login_ptr = (login_t*)(login_buffer + sizeof(login_t) * (j + 1)); } printf("\n"); /* Get selection from user */ do { get_string_input(input, sizeof(input), "* Select which entry to crack (1 - %d): ", i); use = atoi(input); } while(!use || use > i); /* Check if already cracked */ login_ptr = (login_t*)(login_buffer + sizeof(login_t) * (use - 1)); if(!strncmp(login_ptr->algorithm, "PLAIN", sizeof(login_ptr->algorithm))) { printf("* Password already cracked: '%s'\n", login_ptr->hash); SAFE_DELETE(login_buffer); exit(EXIT_SUCCESS); } /* Copy selected structure to pointer */ memcpy(login_info, login_ptr , sizeof(login_t)); /* Free buffer and return */ SAFE_DELETE(login_buffer); return 1; } /* * Main cracking function */ static int crack_login_data(login_t *login, const char *wordlist, char *cracked_pw, int use_stdin, int print_process) { /* Hash */ MD5_CTX md5_ctx; unsigned char md5_bin_hash[MD5_LEN]; char static_hash[MD5_LEN_HEX+1], dynamic_hash[MD5_LEN_HEX+1], final_hash[MD5_LEN_HEX+1]; char dynamic_hash_data[DYNAMIC_HASH_SIZE]; /* USER:REALM: */ char static_hash_data[STATIC_HASH_SIZE]; /* :nonce:nonce_count:cnonce:qop:static_hash */ size_t static_hash_data_len, dynamic_hash_data_len; /* password */ char pw[PW_MAXLEN]; size_t pw_len=0; FILE *passdb=NULL; unsigned int num_pass=0; int found=0; /* misc */ time_t begin, end; char bin2hex_table[256][2]; /* table for bin<->hex mapping */ /* For now only support MD5 till I saw another one in the wild */ if(strncmp(login->algorithm, "MD5", strlen(login->algorithm))) { printf("\n* Cannot crack '%s' hash, only MD5 supported so far...\n", login->algorithm); return -1; } /* Init bin 2 hex table for faster conversions later */ init_bin2hex(bin2hex_table); /* Generating MD5 static hash: 'METHOD:URI' */ printf("\n* Generating static %s hash... ", login->algorithm); fflush(stdout); MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, (unsigned char*)login->method, strlen( login->method )); MD5_Update(&md5_ctx, (unsigned char*)":", 1); MD5_Update(&md5_ctx, (unsigned char*)login->uri, strlen( login->uri )); MD5_Final(md5_bin_hash, &md5_ctx); bin_to_hex(bin2hex_table, md5_bin_hash, MD5_LEN, static_hash, MD5_LEN_HEX); printf("%s\n", static_hash); /* Constructing first part of dynamic hash: 'USER:REALM:' */ snprintf(dynamic_hash_data, sizeof(dynamic_hash_data), "%s:%s:", login->user, login->realm); /* Construct last part of final hash data: ':NONCE(:CNONCE:NONCE_COUNT:QOP):' */ /* no qop */ if(!strlen(login->qop)) snprintf(static_hash_data, sizeof(static_hash_data), ":%s:%s", login->nonce, static_hash); /* qop/conce/cnonce_count */ else snprintf(static_hash_data, sizeof(static_hash_data), ":%s:%s:%s:%s:%s", login->nonce, login->nonce_count, login->cnonce, login->qop, static_hash); /* Get lens of static buffers */ dynamic_hash_data_len = strlen(dynamic_hash_data); static_hash_data_len = strlen(static_hash_data); /* Set filepointer to wordlist file or stdin */ if(!use_stdin) { /* Open wordlist */ if((passdb=fopen(wordlist, "rb")) == NULL) { fprintf(stderr, "* Cannot open wordlist '%s'\n", wordlist); return -1; } printf("* Loaded wordlist: '%s'\n", wordlist); } else { passdb=stdin; printf("* Type your passwords:\n"); } time(&begin); /* Begin brute force attack */ printf("* Starting bruteforce against user '%s' (%s: '%s')\n", login->user, login->algorithm, login->hash); /* Generate hashes for each password and check for matching response */ while(fgets(pw, sizeof(pw), passdb) != NULL) { num_pass++; /* Generate dynamic hash including pw (see above) */ MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, (unsigned char*)dynamic_hash_data, dynamic_hash_data_len); pw_len = strlen(pw); MD5_Update(&md5_ctx, (unsigned char*)pw, (pw[pw_len-2] == 0x0d ? pw_len-2 : pw[pw_len-1] == 0x0a ? pw_len -1 : pw_len)); MD5_Final(md5_bin_hash, &md5_ctx); bin_to_hex(bin2hex_table, md5_bin_hash, MD5_LEN, dynamic_hash, MD5_LEN_HEX); /* Generate digest response hash */ MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, (unsigned char*)dynamic_hash, MD5_LEN_HEX); MD5_Update(&md5_ctx, (unsigned char*)static_hash_data, static_hash_data_len); MD5_Final(md5_bin_hash, &md5_ctx); bin_to_hex(bin2hex_table, md5_bin_hash, MD5_LEN, final_hash, MD5_LEN_HEX); /* Check for match */ if(!strncmp(final_hash, login->hash, MD5_LEN_HEX)) { found = 1; break; } /* Debug print */ if(print_process) { if(num_pass % print_process == 0) printf("* Already tried %d passwords (last '%s')\n", num_pass, pw); } } /* while */ time(&end); printf("* Tried %u passwords in %d seconds\n", num_pass, (int)(end - begin)); /* Close file fd */ if(!use_stdin) fclose(passdb); /* Print result */ if(found == 1) { /* remove %0d%0a */ if(pw[pw_len-2] == 0x0d) pw[pw_len-2] = 0x00; else if(pw[pw_len-1] == 0x0a) pw[pw_len-1] = 0x00; printf("\n* Found password: '%s'\n", pw); /* copy to return buffer for dump file update */ memset(cracked_pw, 0, PW_MAXLEN); strncpy(cracked_pw, pw, PW_MAXLEN - 1); return 1; } else { printf("\n* Tried all passwords, no match\n"); return 0; } } /* * Parse sniffed login data line and copy to struct */ static int parse_sniffed_line(login_t *login, char *buffer) { char **lines; int num_lines, i; size_t len; memset(login, 0, sizeof(login_t)); len = strlen(buffer); /* Remove \r\n */ for(i = 0; i < len; i++) { if(buffer[i] == 0x0a) { buffer[i] = 0x00; break; } else if(buffer[i] == 0x0d) { buffer[i] = 0x00; break; } } /* split by separator '"' */ lines = stringtoarray(buffer, '"', &num_lines); /* Copy to struct */ if(num_lines == 12) { strncpy(login->server, lines[0], sizeof(login->server) - 1 ); strncpy(login->client, lines[1], sizeof(login->client) - 1 ); strncpy(login->user, lines[2], sizeof(login->user) - 1 ); strncpy(login->realm, lines[3], sizeof(login->realm) - 1 ); strncpy(login->method, lines[4], sizeof(login->method) - 1 ); strncpy(login->uri, lines[5], sizeof(login->uri) - 1 ); strncpy(login->nonce, lines[6], sizeof(login->nonce) - 1 ); strncpy(login->cnonce, lines[7], sizeof(login->cnonce) - 1 ); strncpy(login->nonce_count, lines[8], sizeof(login->nonce_count) - 1 ); strncpy(login->qop, lines[9], sizeof(login->qop) - 1 ); strncpy(login->algorithm, lines[10], sizeof(login->algorithm) - 1 ); strncpy(login->hash, lines[11], sizeof(login->hash) - 1 ); } /* Free mem */ for(i = 0 ; i < num_lines ; i++) { SAFE_DELETE(lines[i]); } /* Return */ if(num_lines != 12) return -1; return 0; } /* * Show usage and exit */ static void usage(const char *err_msg) { printf("Usage: sipcrack [OPTIONS] [ -s | -w ] \n\n" \ " = file containing logins sniffed by SIPdump \n\n" \ " Options: \n" \ " -s = use stdin for passwords \n" \ " -w wordlist = file containing all passwords to try \n" \ " -p num = print cracking process every n passwords (for -w)\n" \ " (ATTENTION: slows down heavily) \n" \ "\n* %s\n", err_msg); exit(EXIT_FAILURE); } sipcrack-0.2/SIPdump.c0000644000175000017500000004735510567700640011602 0ustar /* * Copyright (C) 2007 Martin J. Muench * * SIP digest authentication login sniffer */ #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "pcapstuff.h" #include "wrap.h" #include "debug.h" #define SIP_LINE_LEN 1024 /* Maximum length of SIP protocol lines */ #define SIP_METHOD_LEN 32 /* Maximum length of SIP method string */ #define MAX_SIP_CON 128 /* Maximum parallel SIP connections */ /* Structure for full connection table */ typedef struct { int active; uint32_t client_ip; uint16_t client_port; uint32_t server_ip; uint16_t server_port; char method[SIP_METHOD_LEN]; char buffer[SIP_LINE_LEN]; } sip_conn_t; /* Basic connection table */ typedef struct { uint32_t client_ip; uint16_t client_port; uint32_t server_ip; uint16_t server_port; } conn_t; /* Function declarations */ static void sniff_logins(unsigned char *, const struct pcap_pkthdr *, const unsigned char *); static void parse_payload(const conn_t *, unsigned char *, size_t); static int parse_sip_proto(char *, size_t, unsigned char *, size_t); static int find_sip_client_proto(unsigned char *, size_t); static void manual_mode(); static void usage(const char *); static void parse_n_write_login_data(uint32_t, uint32_t, const char *, const char *); /* Globals */ static char *dump_file=NULL; /* dump file */ static unsigned int num_logins=0; /* sniffed login counter */ int opterr = 0; /* shutup getopt() */ /* * sipdump main */ int main(int argc, char *argv[]) { char *dev=NULL, *pcap_file=NULL, *filter=DEFAULT_PCAP_FILTER; char errbuf[PCAP_ERRBUF_SIZE]; int c, manual=0, retval=0; pcap_t *handle=NULL; bpf_u_int32 mask, net; struct bpf_program fp; memset(&fp, 0, sizeof(struct bpf_program)); printf("\nSIPdump %s ( MaJoMu | www.codito.de ) \n" \ "---------------------------------------\n\n", VERSION); /* Parse command line */ while((c = getopt(argc, argv, "i:mp:f:")) != -1) { switch(c) { case 'i': dev = (char *)Malloc(strlen(optarg)+1); strcpy(dev, optarg); break; case 'f': filter = (char *)Malloc(strlen(optarg)+1); strcpy(filter, optarg); break; case 'm': manual = 1; break; case 'p': pcap_file = (char *)Malloc(strlen(optarg)+1); strcpy(pcap_file, optarg); break; default: usage("Invalid arguments"); } } /* Check if both modes set */ if(pcap_file != NULL && dev != NULL) usage("Specify either interface or pcap file"); /* Get dump file */ argv += optind; argc -= optind; if(argc != 1) { SAFE_DELETE(pcap_file); SAFE_DELETE(dev); usage("You need to specify dump file"); } dump_file = (char *)Malloc(strlen(argv[0])+1); strcpy(dump_file, argv[0]); /* Check for manual mode */ if(manual) { manual_mode(); goto cleanup; } /* Open pcap stream */ if(pcap_file != NULL) { printf("* Using pcap file '%s' for sniffing\n", pcap_file); handle = pcap_open_offline(pcap_file, errbuf); if (handle == NULL) { fprintf(stderr, "* Cannot open %s: %s\n", pcap_file ? pcap_file : dev, errbuf); retval=EXIT_FAILURE; goto cleanup; } } else { /* For live capture, euid0 is neeed */ if(geteuid() != 0) { fprintf(stderr, "* You need to have root privileges to run live capture\n"); retval=EXIT_FAILURE; goto cleanup; } /* Get interface if not specified on command line */ if(dev == NULL) { dev = pcap_lookupdev(errbuf); if (dev == NULL) { fprintf(stderr, "* Couldn't find default device: %s\n", errbuf); retval=EXIT_FAILURE; goto cleanup; } } printf("* Using dev '%s' for sniffing\n", dev); /* Get network number and mask associated with capture device */ if(pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { fprintf(stderr, "* Couldn't get netmask for device %s: %s\n", dev, errbuf); net = 0; mask = 0; } /* Open capture device */ handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf); if(handle == NULL) { fprintf(stderr, "* Cannot open device %s: %s\n", dev, errbuf); retval=EXIT_FAILURE; goto cleanup; } /* make sure we're capturing on an Ethernet device [2] */ if(pcap_datalink(handle) != DLT_EN10MB) { fprintf(stderr, "* Invalid device '%s' (non ethernet)\n", dev); retval=EXIT_FAILURE; goto cleanup; } } /* Compile the sniffer filter */ if(pcap_compile(handle, &fp, filter, 0, net) == -1) { fprintf(stderr, "* Invalid packet filter: %s\n", pcap_geterr(handle)); retval=EXIT_FAILURE; goto cleanup; } /* Apply the compiled filter */ if(pcap_setfilter(handle, &fp) == -1) { fprintf(stderr, "* Installing packet filter failed: %s\n", pcap_geterr(handle)); retval=EXIT_FAILURE; goto cleanup; } /* Run main sniffing function */ printf("* Starting to sniff with packet filter '%s'\n\n", filter); pcap_loop(handle, -1, sniff_logins, NULL); printf("\n* Exiting, sniffed %u logins\n", num_logins); /* Cleanup and exit */ cleanup: pcap_freecode(&fp); if(handle) pcap_close(handle); SAFE_DELETE(dump_file); SAFE_DELETE(dev); SAFE_DELETE(pcap_file); if(strncmp(DEFAULT_PCAP_FILTER, filter, strlen(DEFAULT_PCAP_FILTER))) SAFE_DELETE(filter); exit(retval); } /* * Parse payload and search for SIP connections */ static void parse_payload(const conn_t *connection, unsigned char *payload, size_t payload_len) { static sip_conn_t conn_table[MAX_SIP_CON]; static int first=1, replace_entry=0; int i, ret, recorded=0; char buffer[SIP_LINE_LEN]; char *payload_buffer=NULL; size_t payload_buffer_len=0; /* Clear connection table on first call */ if(first) { memset(&conn_table, 0, sizeof(sip_conn_t) * MAX_SIP_CON); first=0; } /* Return on empty payload */ if (payload_len <= 0) return; /* Ignore packet if it contains binary data */ if(is_binary(payload, payload_len)) return; /* * Check if this is a recorded connection where Authorization was * not found yet */ for(i=0; i < MAX_SIP_CON; i++) { /* Known connection, check data */ if(conn_table[i].active && connection->server_ip == conn_table[i].server_ip && connection->client_ip == conn_table[i].client_ip && connection->server_port == conn_table[i].server_port && connection->client_port == conn_table[i].client_port) { struct in_addr cli, srv; cli.s_addr = connection->client_ip; srv.s_addr = connection->server_ip; debug(("New traffic on monitored connection %d:", i)); debug(("Client: %s", inet_ntoa(cli))); debug(("Server: %s", inet_ntoa(srv))); /* Set recorded flag to prevent new parsing*/ recorded=1; /* No old data recorded (no unterminated lines in last packet) */ if(conn_table[i].buffer[0] == 0x00) { /* Parse payload and check if we've got digest auth */ ret = parse_sip_proto(buffer, sizeof(buffer), payload, payload_len); } /* Already recorded SIP data, append new payload to buffer and recheck */ else { /* Append new payload to existing buffer*/ payload_buffer_len = payload_len + strlen(conn_table[i].buffer) + 1; payload_buffer = (char *)Malloc(payload_buffer_len); strncpy(payload_buffer, conn_table[i].buffer, payload_buffer_len - 1); strncat(payload_buffer, (char *)payload, payload_buffer_len - strlen(payload_buffer) - 1); /* Parse buffer (saved buffer + packet payload) */ ret = parse_sip_proto(buffer, sizeof(buffer), (unsigned char *)payload_buffer, payload_buffer_len); /* Free payload buffer */ free(payload_buffer); } /* Error or no digets found, removing connection from table */ if(ret < 0) { memset(&conn_table[i], 0, sizeof(sip_conn_t)); return; } /* Found challenge response */ if(ret) { /* Extract all needed values and write to dump file */ parse_n_write_login_data(conn_table[i].server_ip, conn_table[i].client_ip, conn_table[i].method, buffer); /* Remove entry from connection table */ memset(&conn_table[i], 0, sizeof(sip_conn_t)); } /* Keep non-line-terminated buffer, new data will be appended */ else if(!ret) { if(buffer[0] != 0x00) strncpy(conn_table[i].buffer, buffer, sizeof(conn_table[i].buffer) - 1); } /* Break lookup in connection table */ break; } } /* for(i=0; i < MAX_SIP_CON; i++) */ /* Unrecorded connection */ if(!recorded) { /* Check for SIP protocol */ if(!find_sip_client_proto(payload, payload_len)) return; /* Parse payload and search for digest auth */ ret = parse_sip_proto(buffer, sizeof(buffer), payload, payload_len); /* Ignore packet on error or no digest authentication found */ if(ret < 0) { return; } /* Found challenge response */ if(ret) { /* Get method from payload */ char method[SIP_METHOD_LEN]; extract_method(method, (char *)payload, sizeof(method)); /* Extract all needed values and write to dump file */ parse_n_write_login_data(connection->server_ip, connection->client_ip, method, buffer); } /* * Add to connection table for further checks * (digest authentification line still missing) */ else if(!ret) { struct in_addr cli, srv; cli.s_addr = connection->client_ip; srv.s_addr = connection->server_ip; debug(("Adding connection to list:")); debug(("Client: %s:%d ", inet_ntoa(cli), connection->client_port)); debug(("Server: %s:%d ", inet_ntoa(srv), connection->server_port)); /* Find free entry in connection table */ for(i=0; i < MAX_SIP_CON; i++) { if(!conn_table[i].active) { recorded=1; break; } } /* If no free entry found, replace another one */ if(!recorded) { debug(("Connection table full, replacing %d", replace_entry)); i = replace_entry; if(replace_entry == MAX_SIP_CON - 1) replace_entry = 0; else replace_entry++; } /* Connection information */ conn_table[i].active = 1; conn_table[i].client_ip = connection->client_ip; conn_table[i].server_ip = connection->server_ip; conn_table[i].client_port = connection->client_port; conn_table[i].server_port = connection->server_port; /* Copy method */ extract_method(conn_table[i].method, (char *)payload, sizeof(conn_table[i].method)); debug(("Method: %s", conn_table[i].method)); /* Keep non-line-terminated data (new data will be appended) */ if(buffer[0] != '\0') { strncpy(conn_table[i].buffer, buffer, SIP_LINE_LEN); debug(("Saving buffer '%s'", buffer)); } } } /* if(!recorded) */ return; } /* * Initial check for received packets */ static void sniff_logins(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { const struct ethernet_header *ethernet; const struct ip_header *ip; const struct tcp_header *tcp; const struct udp_header *udp; unsigned char *payload; conn_t connection; size_t size_ip=0, size_proto=0, size_payload=0; /* Get ethernet header */ ethernet = (struct ethernet_header *)(packet); /* Get IP header */ ip = (struct ip_header *)(packet + SIZE_ETHERNET); size_ip = IP_HL(ip)*4; if (size_ip < 20) { debug(("Got packet with invalid IP header length (%d bytes), ignoring...", size_ip)); return; } /* Assign IP's */ connection.server_ip = ip->ip_src.s_addr; connection.client_ip = ip->ip_dst.s_addr; /* Check proto and get source and destination port */ switch(ip->ip_p) { case IPPROTO_TCP: tcp = (struct tcp_header *)(packet + SIZE_ETHERNET + size_ip); size_proto = TH_OFF(tcp)*4; if (size_proto < 20) { debug(("Got packet with invalid TCP header length (%d bytes), ignoring...", size_proto)); return; } connection.server_port = tcp->th_sport; connection.client_port = tcp->th_dport; break; case IPPROTO_UDP: udp = (struct udp_header *)(packet + SIZE_ETHERNET + size_ip); size_proto = sizeof(struct udp_header); connection.server_port = udp->uh_sport; connection.client_port = udp->uh_dport; break; default: return; } /* Extract payload from packet */ payload = (unsigned char *)(packet + SIZE_ETHERNET + size_ip + size_proto); size_payload = ntohs(ip->ip_len) - (size_ip + size_proto); payload[size_payload] = 0x00; /* If we have a payload send to payload and connection information to parser */ if(size_payload > 0) { parse_payload(&connection, payload, size_payload); } return; } /* * Extract all needed SIP parameters from buffer */ static int parse_sip_proto(char *out, size_t out_len, unsigned char *buffer, size_t buffer_len) { char **lines; int num_lines, i, found=0, error=0; /* Clear output buffer */ memset(out, 0, out_len); /* Iterate through sip data (line by line) */ lines = stringtoarray((char *)buffer, '\n', &num_lines); for(i = 0 ; i < num_lines - 1; i++) { /* We are only interested in lines beginning with these strings */ if((!strncmp(lines[i], "Proxy-Authorization:", strlen("Proxy-Authorization:")) || !strncmp(lines[i], "WWW-Authenticate:", strlen("WWW-Authenticate:")) || !strncmp(lines[i], "Authorization:", strlen("Authorization:"))) && !found && !error) { /* found the digest auth line, copy to output buffer */ if(out_len - 1 < strlen(lines[i])) { debug(("Buffer too small for line, ignoring...")); error=1; } strncpy(out, lines[i], out_len - 1); found = 1; } /* free obsolete lines */ free(lines[i]); } /* Error or regular end of SIP header and no auth found */ if(error || (!found && lines[num_lines-1][0] == 0x00)) { free(lines[num_lines - 1]); return -1; } /* Challenge response sniffed */ if(found) { free(lines[num_lines - 1]); return 1; } /* Nothing found so far, recording remaining buffer */ if(out_len - 1 < strlen(lines[num_lines - 1])) { debug(("Buffer too small for line, ignoring...")); free(lines[num_lines - 1]); return -1; } strncpy(out, lines[num_lines - 1], out_len - 1); /* Free last line */ free(lines[num_lines - 1]); return 0; } /* * Check if given buffer is a SIP header with methods * that might require digest authentication */ static int find_sip_client_proto(unsigned char *buffer, size_t len) { int i; char c=0; /* Ignore all other SIP requests as they won't be challenged */ if(strncmp((char *)buffer, "REGISTER ", 9) && strncmp((char *)buffer, "MESSAGE " , 8) && strncmp((char *)buffer, "OPTIONS " , 8) && strncmp((char *)buffer, "INVITE " , 7) && strncmp((char *)buffer, "BYE " , 4)) return 0; /* Remove replace \r\n with \0 for strstr check */ for(i = 0; i < len; i++) { if(buffer[i] == 0x0a || buffer[i] == 0x0d) { c = buffer[i]; buffer[i] = 0x00; break; } } /* Check for valid SIP request and restore buffer */ if(strstr((char *)buffer, " sip:") && strstr((char *)buffer, " SIP/")) { buffer[i] = c; return 1; } return 0; } /* * Manual mode to insert a login into dump file */ static void manual_mode() { login_t login; memset(&login, 0, sizeof(login)); /* Get user input */ printf("* Enter login information manually:\n\n"); get_string_input(login.server, sizeof(login.server), "* Enter server IP : "); get_string_input(login.client, sizeof(login.client), "* Enter client IP : "); get_string_input(login.user, sizeof(login.user), "* Enter username : "); get_string_input(login.realm, sizeof(login.realm), "* Enter realm : "); get_string_input(login.method, sizeof(login.method), "* Enter Method : "); get_string_input(login.uri, sizeof(login.uri), "* Enter URI : "); get_string_input(login.nonce, sizeof(login.nonce), "* Enter nonce : "); get_string_input(login.qop, sizeof(login.qop), "* Enter qop : "); /* Read cnonce and cnonce_count only if qop is set */ if(strlen(login.qop)) { get_string_input(login.cnonce, sizeof(login.cnonce), "* Enter cnonce : "); get_string_input(login.nonce_count, sizeof(login.nonce_count), "* Enter nonce_count: "); } /* Get algorithm */ get_string_input(login.algorithm, sizeof(login.algorithm), "* Enter algoritm : "); Toupper(login.algorithm, strlen(login.algorithm)); /* Get response hash */ get_string_input(login.hash, sizeof(login.hash), "* Enter response : "); /* Write to file */ write_login_data(&login, dump_file); return; } /* * Show usage and exit */ static void usage(const char *err_msg) { printf("Usage: sipdump [OPTIONS] \n\n" \ " = file where captured logins will be written to\n\n" \ " Options: \n" \ " -i = interface to listen on \n" \ " -p = use pcap data file \n" \ " -m = enter login data manually \n" \ " -f \"\" = set libpcap filter \n" \ "\n* %s\n", err_msg); exit(EXIT_FAILURE); } /* * Parse all SIP digest auth related values from buffer and write to dump file */ static void parse_n_write_login_data(uint32_t server, uint32_t client, const char *method, const char *buffer) { login_t login_data; struct in_addr cli, srv; memset(&login_data, 0, sizeof(login_data)); /* Copy server and client IP */ cli.s_addr = client; srv.s_addr = server; strncpy(login_data.server, inet_ntoa(srv), sizeof(login_data.server) - 1); strncpy(login_data.client, inet_ntoa(cli), sizeof(login_data.client) - 1); /* Copy method */ strncpy(login_data.method, method, sizeof(login_data.method) - 1); /* Extract Authorization options from buffer */ if(find_value("username=", buffer, login_data.user, sizeof(login_data.user)) || find_value("realm=", buffer, login_data.realm, sizeof(login_data.realm)) || find_value("uri=", buffer, login_data.uri, sizeof(login_data.uri)) || find_value("nonce=", buffer, login_data.nonce, sizeof(login_data.nonce)) || find_value("response=", buffer, login_data.hash, sizeof(login_data.hash)) ) { debug(("Couldn't parse buffer (ignoring data):\n---------\n%s\n---------", buffer)); return; } /* Check for qop */ if(!find_value("qop=", buffer, login_data.qop, sizeof(login_data.qop))) { /* get cnonce and nonce_count */ if(find_value("cnonce=", buffer, login_data.cnonce, sizeof(login_data.cnonce)) || find_value("nc=", buffer, login_data.nonce_count, sizeof(login_data.nonce_count))) { debug(("Couldn't parse cnonce/nonce_count (ignoring data):\n---------\n%s\n---------", buffer)); return; } } /* Get algorithm or set MD5 */ if(find_value("algorithm=", buffer, login_data.algorithm, sizeof(login_data.algorithm))) strncpy(login_data.algorithm, "MD5", sizeof(login_data.algorithm)); else Toupper(login_data.algorithm, strlen(login_data.algorithm)); /* Write to dump file */ write_login_data(&login_data, dump_file); printf("* Dumped login from %s -> %s (User: '%s')\n", login_data.client, login_data.server, login_data.user); num_logins++; return; } sipcrack-0.2/USAGE_EXAMPLES0000644000175000017500000000226610567700640012172 0ustar Using sipdump in combination with pcap packet dump files -------------------------------------------------------- Create pcap packet dump file (using tcpdump): $ tcpdump -s 0 -w pcap-capture.txt tcp or udp Passing capture file to sipdump to search for sniffed logins: $ sipdump -p pcap-capture.txt logins.dump Using SIPcrack in combination with John the ripper -------------------------------------------------- John the ripper: http://www.openwall.com/john/ Make a fifo file pipe: $ mkfifo myfifofile Start john using the desired settings. Below is an example which generates passwords with max 8 letter length and only contains alpha characters. Using > redirect johns output into the fifo file you just created: $ john --incremental=alpha --stdout=8 > myfifofile Start sipcrack and use the fifo file pipe as the wordlist source: $ sipcrack -w myfifofile logins.dump John has some great permutation algorithm which also enhances your wordlist files by permutate some letters and numbers. This allows you to have a smaller wordlistfile. See John's homepage at http://www.openwall.com/john/doc/EXAMPLES.shtml for more examples. But dont forget to redirect output into the fifo file pipe. sipcrack-0.2/debug.c0000644000175000017500000000060410567700640011331 0ustar /* * Copyright (C) 2007 Martin J. Muench * * Debug function that is activated through "-DDEBUG" switch */ #include "debug.h" void ic_debug(const char *fmt, ...) { char buffer[4096]; va_list ap; memset(buffer, 0, sizeof(buffer)); va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); va_end(ap); fprintf(stderr, "+ %s\n", buffer); } sipcrack-0.2/debug.h0000644000175000017500000000051510567700640011337 0ustar /* Copyright (C) 2007 Martin J. Muench */ #ifndef SIPCRACK_DEBUG_H #define SIPCRACK_DEBUG_H #include #include #include #ifdef DEBUG #define debug(x) ic_debug x; #else #define debug(x) do { } while(1!=1); #endif void ic_debug(const char *fmt, ...); #endif /* SIPCRACK_DEBUG_H */ sipcrack-0.2/global.h0000644000175000017500000000344510567700640011516 0ustar /* * Copyright (C) 2007 Martin J. Muench */ #ifndef SIPCRACK_GLOBAL_H #define SIPCRACK_GLOBAL_H #define VERSION "0.2" /* sipdump/sipcrack version */ #define DEFAULT_PCAP_FILTER "tcp or udp" /* default packet capture filter */ /* sip field sizes */ #define HOST_MAXLEN 256 /* Max len of hostnames */ #define USER_MAXLEN 128 /* Max len of user names */ #define URI_MAXLEN 256 /* Max len of uri */ #define NONCE_MAXLEN 128 /* Max len of nonce value */ #define CNONCE_MAXLEN 128 /* Max len for cnonce value */ #define NONCECOUNT_MAXLEN 8 /* Max len for nonce count */ #define QOP_MAXLEN 12 /* Max len for qop value */ #define LOGIN_MAXLEN 1024 /* Max len of login entry */ #define ALG_MAXLEN 8 /* Max len of algorithm name */ #define METHOD_MAXLEN 16 /* Max len of method string */ /* Hash stuff */ #define MD5_LEN 16 /* Len of MD5 binary hash */ #define MD5_LEN_HEX 32 /* Len of MD5 hex hash */ #define PW_MAXLEN 32 /* Max len of password */ #define DYNAMIC_HASH_SIZE USER_MAXLEN + HOST_MAXLEN + 3 #define STATIC_HASH_SIZE NONCE_MAXLEN + CNONCE_MAXLEN + NONCECOUNT_MAXLEN \ + QOP_MAXLEN + MD5_LEN_HEX + 6 /* Structure to hold login information */ typedef struct { char server[HOST_MAXLEN]; char client[HOST_MAXLEN]; char user[USER_MAXLEN]; char realm[HOST_MAXLEN]; char method[METHOD_MAXLEN]; char uri[URI_MAXLEN]; char nonce[NONCE_MAXLEN]; char cnonce[NONCE_MAXLEN]; char nonce_count[CNONCE_MAXLEN]; char qop[QOP_MAXLEN]; char algorithm[ALG_MAXLEN]; char hash[MD5_LEN_HEX+1]; } login_t; #define SAFE_DELETE(x) if(x) free(x); #endif /* SIPCRACK_GLOBAL_H */ sipcrack-0.2/md5.c0000644000175000017500000002431010567700640010730 0ustar /* $FreeBSD: src/sys/crypto/md5.c,v 1.1.2.2 2001/07/03 11:01:27 ume Exp $ */ /* $KAME: md5.c,v 1.5 2000/11/08 06:13:08 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include "md5.h" #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s)))) #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) #define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z))) #define H(X, Y, Z) ((X) ^ (Y) ^ (Z)) #define I(X, Y, Z) ((Y) ^ ((X) | (~Z))) #define ROUND1(a, b, c, d, k, s, i) { \ (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \ (a) = SHIFT((a), (s)); \ (a) = (b) + (a); \ } #define ROUND2(a, b, c, d, k, s, i) { \ (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \ (a) = SHIFT((a), (s)); \ (a) = (b) + (a); \ } #define ROUND3(a, b, c, d, k, s, i) { \ (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \ (a) = SHIFT((a), (s)); \ (a) = (b) + (a); \ } #define ROUND4(a, b, c, d, k, s, i) { \ (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \ (a) = SHIFT((a), (s)); \ (a) = (b) + (a); \ } #define Sa 7 #define Sb 12 #define Sc 17 #define Sd 22 #define Se 5 #define Sf 9 #define Sg 14 #define Sh 20 #define Si 4 #define Sj 11 #define Sk 16 #define Sl 23 #define Sm 6 #define Sn 10 #define So 15 #define Sp 21 #define MD5_A0 0x67452301 #define MD5_B0 0xefcdab89 #define MD5_C0 0x98badcfe #define MD5_D0 0x10325476 /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */ static const u_int32_t T[65] = { 0, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, }; static const u_int8_t md5_paddat[MD5_BUFLEN] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static void md5_calc __P((u_int8_t *, md5_ctxt *)); void md5_init(ctxt) md5_ctxt *ctxt; { ctxt->md5_n = 0; ctxt->md5_i = 0; ctxt->md5_sta = MD5_A0; ctxt->md5_stb = MD5_B0; ctxt->md5_stc = MD5_C0; ctxt->md5_std = MD5_D0; bzero(ctxt->md5_buf, sizeof(ctxt->md5_buf)); } void md5_loop(ctxt, input, len) md5_ctxt *ctxt; u_int8_t *input; u_int len; /* number of bytes */ { u_int gap, i; ctxt->md5_n += len * 8; /* byte to bit */ gap = MD5_BUFLEN - ctxt->md5_i; if (len >= gap) { bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i), gap); md5_calc(ctxt->md5_buf, ctxt); for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN) { md5_calc((u_int8_t *)(input + i), ctxt); } ctxt->md5_i = len - i; bcopy((void *)(input + i), (void *)ctxt->md5_buf, ctxt->md5_i); } else { bcopy((void *)input, (void *)(ctxt->md5_buf + ctxt->md5_i), len); ctxt->md5_i += len; } } void md5_pad(ctxt) md5_ctxt *ctxt; { u_int gap; /* Don't count up padding. Keep md5_n. */ gap = MD5_BUFLEN - ctxt->md5_i; if (gap > 8) { bcopy((void *)md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i), gap - sizeof(ctxt->md5_n)); } else { /* including gap == 8 */ bcopy((void *)md5_paddat, (void *)(ctxt->md5_buf + ctxt->md5_i), gap); md5_calc(ctxt->md5_buf, ctxt); bcopy((void *)(md5_paddat + gap), (void *)ctxt->md5_buf, MD5_BUFLEN - sizeof(ctxt->md5_n)); } /* 8 byte word */ #if BYTE_ORDER == LITTLE_ENDIAN bcopy(&ctxt->md5_n8[0], &ctxt->md5_buf[56], 8); #endif #if BYTE_ORDER == BIG_ENDIAN ctxt->md5_buf[56] = ctxt->md5_n8[7]; ctxt->md5_buf[57] = ctxt->md5_n8[6]; ctxt->md5_buf[58] = ctxt->md5_n8[5]; ctxt->md5_buf[59] = ctxt->md5_n8[4]; ctxt->md5_buf[60] = ctxt->md5_n8[3]; ctxt->md5_buf[61] = ctxt->md5_n8[2]; ctxt->md5_buf[62] = ctxt->md5_n8[1]; ctxt->md5_buf[63] = ctxt->md5_n8[0]; #endif md5_calc(ctxt->md5_buf, ctxt); } void md5_result(digest, ctxt) u_int8_t *digest; md5_ctxt *ctxt; { /* 4 byte words */ #if BYTE_ORDER == LITTLE_ENDIAN bcopy(&ctxt->md5_st8[0], digest, 16); #endif #if BYTE_ORDER == BIG_ENDIAN digest[ 0] = ctxt->md5_st8[ 3]; digest[ 1] = ctxt->md5_st8[ 2]; digest[ 2] = ctxt->md5_st8[ 1]; digest[ 3] = ctxt->md5_st8[ 0]; digest[ 4] = ctxt->md5_st8[ 7]; digest[ 5] = ctxt->md5_st8[ 6]; digest[ 6] = ctxt->md5_st8[ 5]; digest[ 7] = ctxt->md5_st8[ 4]; digest[ 8] = ctxt->md5_st8[11]; digest[ 9] = ctxt->md5_st8[10]; digest[10] = ctxt->md5_st8[ 9]; digest[11] = ctxt->md5_st8[ 8]; digest[12] = ctxt->md5_st8[15]; digest[13] = ctxt->md5_st8[14]; digest[14] = ctxt->md5_st8[13]; digest[15] = ctxt->md5_st8[12]; #endif } #if BYTE_ORDER == BIG_ENDIAN u_int32_t X[16]; #endif static void md5_calc(b64, ctxt) u_int8_t *b64; md5_ctxt *ctxt; { u_int32_t A = ctxt->md5_sta; u_int32_t B = ctxt->md5_stb; u_int32_t C = ctxt->md5_stc; u_int32_t D = ctxt->md5_std; #if BYTE_ORDER == LITTLE_ENDIAN u_int32_t *X = (u_int32_t *)b64; #endif #if BYTE_ORDER == BIG_ENDIAN /* 4 byte words */ /* what a brute force but fast! */ u_int8_t *y = (u_int8_t *)X; y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0]; y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4]; y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8]; y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12]; y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16]; y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20]; y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24]; y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28]; y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32]; y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36]; y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40]; y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44]; y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48]; y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52]; y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56]; y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60]; #endif ROUND1(A, B, C, D, 0, Sa, 1); ROUND1(D, A, B, C, 1, Sb, 2); ROUND1(C, D, A, B, 2, Sc, 3); ROUND1(B, C, D, A, 3, Sd, 4); ROUND1(A, B, C, D, 4, Sa, 5); ROUND1(D, A, B, C, 5, Sb, 6); ROUND1(C, D, A, B, 6, Sc, 7); ROUND1(B, C, D, A, 7, Sd, 8); ROUND1(A, B, C, D, 8, Sa, 9); ROUND1(D, A, B, C, 9, Sb, 10); ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12); ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14); ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16); ROUND2(A, B, C, D, 1, Se, 17); ROUND2(D, A, B, C, 6, Sf, 18); ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A, 0, Sh, 20); ROUND2(A, B, C, D, 5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22); ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A, 4, Sh, 24); ROUND2(A, B, C, D, 9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26); ROUND2(C, D, A, B, 3, Sg, 27); ROUND2(B, C, D, A, 8, Sh, 28); ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C, 2, Sf, 30); ROUND2(C, D, A, B, 7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32); ROUND3(A, B, C, D, 5, Si, 33); ROUND3(D, A, B, C, 8, Sj, 34); ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36); ROUND3(A, B, C, D, 1, Si, 37); ROUND3(D, A, B, C, 4, Sj, 38); ROUND3(C, D, A, B, 7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40); ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C, 0, Sj, 42); ROUND3(C, D, A, B, 3, Sk, 43); ROUND3(B, C, D, A, 6, Sl, 44); ROUND3(A, B, C, D, 9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46); ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A, 2, Sl, 48); ROUND4(A, B, C, D, 0, Sm, 49); ROUND4(D, A, B, C, 7, Sn, 50); ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A, 5, Sp, 52); ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C, 3, Sn, 54); ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A, 1, Sp, 56); ROUND4(A, B, C, D, 8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58); ROUND4(C, D, A, B, 6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60); ROUND4(A, B, C, D, 4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62); ROUND4(C, D, A, B, 2, So, 63); ROUND4(B, C, D, A, 9, Sp, 64); ctxt->md5_sta += A; ctxt->md5_stb += B; ctxt->md5_stc += C; ctxt->md5_std += D; } sipcrack-0.2/md5.h0000644000175000017500000000537310567700640010745 0ustar /* $FreeBSD: src/sys/crypto/md5.h,v 1.1.2.1 2000/07/15 07:14:18 kris Exp $ */ /* $KAME: md5.h,v 1.4 2000/03/27 04:36:22 sumikawa Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _NETINET6_MD5_H_ #define _NETINET6_MD5_H_ #define MD5_BUFLEN 64 typedef struct { union { u_int32_t md5_state32[4]; u_int8_t md5_state8[16]; } md5_st; #define md5_sta md5_st.md5_state32[0] #define md5_stb md5_st.md5_state32[1] #define md5_stc md5_st.md5_state32[2] #define md5_std md5_st.md5_state32[3] #define md5_st8 md5_st.md5_state8 union { u_int64_t md5_count64; u_int8_t md5_count8[8]; } md5_count; #define md5_n md5_count.md5_count64 #define md5_n8 md5_count.md5_count8 u_int md5_i; u_int8_t md5_buf[MD5_BUFLEN]; } md5_ctxt; extern void md5_init __P((md5_ctxt *)); extern void md5_loop __P((md5_ctxt *, u_int8_t *, u_int)); extern void md5_pad __P((md5_ctxt *)); extern void md5_result __P((u_int8_t *, md5_ctxt *)); /* compatibility */ #define MD5_CTX md5_ctxt #define MD5Init(x) md5_init((x)) #define MD5Update(x, y, z) md5_loop((x), (y), (z)) #define MD5Final(x, y) \ do { \ md5_pad((y)); \ md5_result((x), (y)); \ } while (0) #define MD5_Init MD5Init #define MD5_Update MD5Update #define MD5_Final MD5Final #endif /* ! _NETINET6_MD5_H_*/ sipcrack-0.2/wrap.c0000644000175000017500000001470310567700640011221 0ustar /* * Copyright (C) 2007 Martin J. Muench * * Some small hacked wrapper functions */ #include #include #include #include #include #include "wrap.h" #include "debug.h" /* malloc() wrapper */ void *Malloc(size_t size) { void *buffer; buffer = malloc(size); if(buffer == NULL) { fprintf(stderr, "malloc() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } memset(buffer, 0, size); return(buffer); } /* realloc() wrapper */ void *Realloc(void *buffer, size_t size) { buffer = realloc(buffer, size); if(buffer == NULL) { fprintf(stderr, "realloc() failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } return(buffer); } /* convert string to array */ char **stringtoarray(char *string, char delimiter, int *size) { char **array = NULL; char *ptr, *oldptr; int flag = 1; int count; *size = 0; ptr = string; for(count=0 ; flag ; count++) { for (oldptr=ptr;*ptr&&*ptr!=delimiter;*ptr++) ; if (!*ptr) flag = 0; *ptr++ = 0x00; (*size)++; array = realloc(array, (count+1)*sizeof(char *)); array[count] = strdup(oldptr); } return array; } /* read input from stdin */ void get_string_input(char *outbuf, size_t outbuf_len, const char *fmt, ...) { char msg[128]; va_list ap; memset(msg, 0, sizeof(msg)); va_start(ap, fmt); vsnprintf(msg, sizeof(msg)-1, fmt, ap); va_end(ap); do { printf("%s", msg); fflush(stdout); } while(!fgets(outbuf, outbuf_len, stdin)); /* Remove newline */ if(outbuf[strlen(outbuf)-1] == 0x0d) outbuf[strlen(outbuf)-1] = 0x00; return; } /* check whether buffer contains binary characters */ int is_binary(const unsigned char *buffer, size_t len) { int i; for(i = 0; i < len ; i++) { if(!isascii(buffer[i])) return 1; } return 0; } /* init bin 2 hex table */ void init_bin2hex(char bin2hex_table[256][2]) { unsigned i=0; for(i=0;i<256;i++) { bin2hex_table[i][0] = ( ((i >> 4) & 0x0F) <= 0x09) ? (((i >> 4) & 0x0F) + '0') : (((i >> 4) & 0x0F) + 'a' - 10); bin2hex_table[i][1] = ( ((i) & 0x0F) <= 0x09) ? (((i) & 0x0F) + '0') : (((i) & 0x0F) + 'a' - 10); } return; } /* convert bin to hex */ void bin_to_hex(char bin2hex_table[256][2], const unsigned char *bin_buffer, size_t bin_buffer_size, char * hex_buffer, size_t hex_buffer_size) { unsigned i; for(i=0;iserver, data->client, data->user, data->realm, data->method, data->uri, data->nonce, data->cnonce, data->nonce_count, data->qop, data->algorithm, data->hash); fclose(lfile); debug(("write_login_data() done")); return; } /* Update line in dump file with password */ void update_login_data(login_t *data, const char *pw, const char *file) { FILE *login_file, *temp_file; char buffer[1024], orig_string[1024]; char *tempfile; size_t tempfile_len; debug(("update_login_data(): %s", file)); tempfile_len = (strlen(file) + strlen(".tmp") + 1); tempfile = (char *)Malloc(tempfile_len); snprintf(tempfile, tempfile_len, "%s.tmp", file); if((login_file = fopen(file, "r")) == NULL) { fprintf(stderr, "* Cannot open dump file: %s\n", strerror(errno)); free(tempfile); return; } if((temp_file = fopen(tempfile, "w")) == NULL) { fprintf(stderr, "* Cannot open temp file: %s\n", strerror(errno)); fclose(login_file); free(tempfile); return; } snprintf(orig_string, sizeof(orig_string), "%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\n", data->server, data->client, data->user, data->realm, data->method, data->uri, data->nonce, data->cnonce, data->nonce_count, data->qop, data->algorithm, data->hash); while((fgets(buffer, sizeof(buffer), login_file)) != NULL) { if(!strncmp(buffer, orig_string, sizeof(buffer))) { fprintf(temp_file, "%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\"%s\n", data->server, data->client, data->user, data->realm, data->method, data->uri, data->nonce, data->cnonce, data->nonce_count, data->qop, "PLAIN", pw); } else { fprintf(temp_file, "%s", buffer); } } fclose(login_file); fclose(temp_file); /* rename */ if(rename(tempfile, file) < 0) { fprintf(stderr, "* Cannot rename tempfile to dump file: %s\n", strerror(errno)); free(tempfile); return; } free(tempfile); debug(("update_login_data() done")); } /* find value in buffer */ int find_value(const char *value, const char *buffer, char *outbuf, size_t outbuf_len) { char *ptr1, *tempbuf; int i, b; /* debug(("find_value() %s", value)); */ ptr1 = strstr(buffer, value); if(ptr1 == NULL) return -1; ptr1 += strlen(value); b = strlen(ptr1); tempbuf = Malloc(b + 1); /* value is quoted */ if(ptr1[0] == '"') { for(i = 1 ; i < b ; i++) { ptr1++; if(ptr1[0] == '"') break; tempbuf[i-1]=ptr1[0]; } } /* copy till ',', '\r' or '\n' */ else { for(i = 0 ; i < b ; i++) { if(ptr1[0] == ',' || ptr1[0] == 0x0d || ptr1[0] == 0x0a) break; tempbuf[i]=ptr1[0]; ptr1++; } } memset(outbuf, 0, sizeof(outbuf)); strncpy(outbuf, tempbuf, outbuf_len - 1); free(tempbuf); debug(("find_value: %s'%s'", value, outbuf)); return 0; } void Toupper(char *buffer, size_t buffer_len) { int i; for(i = 0 ; i < buffer_len ; i++) buffer[i] = toupper(buffer[i]); return; } void extract_method(char *out, const char *in, size_t out_len) { int i; debug(("extract_method() begin")); for(i = 0 ; i < out_len ; i++) { if(in[i] == ' ') break; out[i] = in[i]; } out[i]=0x00; debug(("extract_method(): %s", out)); return; } sipcrack-0.2/wrap.h0000644000175000017500000000136610567700640011227 0ustar /* Copyright (C) 2007 Martin J. Muench */ #ifndef SIPCRACK_WRAPPER_H #define SIPCRACK_WRAPPER_H #include #include "global.h" void *Malloc(size_t); void *Realloc(void *, size_t); char **stringtoarray(char *, char, int *); void get_string_input(char *, size_t, const char *, ...); int is_binary(const unsigned char *, size_t); void init_bin2hex(char [256][2]); void bin_to_hex(char [256][2], const unsigned char *, size_t, char *, size_t); void write_login_data(login_t *, const char *); void update_login_data(login_t *, const char *, const char *); int find_value(const char *, const char *, char *, size_t); void Toupper(char *, size_t); void extract_method(char *, const char *, size_t); #endif /* SIPCRACK_WRAPPER_H */