Imported Upstream version 0.4a debian upstream upstream/0.4a
authorDevon Kearns <dookie@kali.org>
Mon, 14 Jan 2013 13:38:45 +0000 (06:38 -0700)
committerDevon Kearns <dookie@kali.org>
Mon, 14 Jan 2013 13:38:45 +0000 (06:38 -0700)
15 files changed:
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
base.mk [new file with mode: 0644]
charmap.c [new file with mode: 0644]
charmap.h [new file with mode: 0644]
config.h [new file with mode: 0644]
dict [new file with mode: 0644]
enumiax.h [new file with mode: 0644]
exit.c [new file with mode: 0644]
inet_hton.c [new file with mode: 0644]
main.c [new file with mode: 0644]
outputs.c [new file with mode: 0644]
socket.c [new file with mode: 0644]
usage.c [new file with mode: 0644]
worditer.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a98dd28
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+all: enumiax 
+
+include base.mk
+
+install: all
+       strip enumiax
+       ienumiaxtall -m 755 enumiax ${BINDIR}
+       @echo
+       @echo "enumiax installed!"
+       @echo
+
+uninstall:
+       rm -f ${BINDIR}/enumiax
+       @echo
+       @echo "enumiax uninstalled!"
+       @echo
+
+       
+OBJS = charmap.o exit.o inet_hton.o main.o outputs.o worditer.o socket.o usage.o
+INCLUDES = enumiax.h charmap.h config.h
+
+# enumiax
+enumiax: ${OBJS}
+       @echo
+       @echo "Compiling enumiax..."
+       ${CC} ${CFLAGS} ${LINCLUDES} ${LIBS} -o $@ ${OBJS}
+
+${OBJS}: ${INCLUDES}
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..add08f9
--- /dev/null
+++ b/README
@@ -0,0 +1,127 @@
+                                  enumIAX 
+             Dustin D. Trammell <dtrammell (at) tippingpoint.com>
+
+==============================================================================
+
+enumIAX is an Inter Asterisk Exchange protocol username brute-force
+enumerator.
+
+                             Modes of Operation
+                             ==================
+
+enumIAX may operate in two distinct modes; Sequential Username Guessing or
+Dictionary Attack.
+
+Sequential Username Guessing
+------------------------------
+
+In Sequential Username Guessing mode, the tool will auto-construct
+usernames sequentially from a range of characters defined in the charmap.h
+file.  By default, the character map should be the following characters:
+
+  "0123456789abcdefghijklmnopqrstuvwxyz "
+
+This character map should be able to guess any alpha-numerically constructed
+username with or without space characters.  For a more exhaustive search,
+expand the character map to include other character sets already defined in
+charmap.h, or create your own entirely new and customized character map!
+Remember however that the more characters you include in your character map,
+the longer the session will take as you will be increasing the potential
+passphrase "keyspace" exponentially.
+
+NOTE: VoIP usernames, like email addresses, are usually case-insensitive.
+
+Dictionary Attack
+-----------------
+
+enumIAX may also use usernames from a dictionary file rather than construct
+usernames itself.  "Dict" files are generally just a long list of words or
+phrases, one word per line.  If you already have a favorite Dict file, you
+can use it here.
+
+                           Building and Installing
+                           =======================
+
+enumIAX should build without issue on most unix-like platforms.
+
+Once enumIAX is built, execute the following commands from the enumIAX
+source directory to install the binaries to your system:
+
+   make
+   make install  
+
+enumIAX will be installed /usr/local/bin for your use, however you will most
+likely want to create and run enumIAX from a working directory where it can
+save session state and result information.
+
+                         Executing a enumIAX Session
+                         ===========================
+
+Executing enumIAX
+-----------------
+
+enumIAX has many command-line options to tweak it's behavior, however normal
+execution can be accomplished with a command-line similar to the following:
+
+   enumiax <target>
+
+In the above example, <target> is the target hostname or IP address that you
+want to enumerate.
+
+Other command-line options you may include can be found with the "-h" command-
+line option:
+
+   enumiax -h
+
+   Usage: enumiax [options] target
+     options:
+       -d <dict>   Dictionary attack using <dict> file
+       -i <count>  Interval for auto-save (# of operations, default 1000)
+       -m #        Minimum username length (in characters)
+       -M #        Maximum username length (in characters)
+       -r #        Rate-limit calls (in microseconds)
+       -s <file>   Read session state from state file
+       -v          Increase verbosity (repeat for additional verbosity)
+       -V          Print version information and exit
+       -h          Print help/usage information and exit
+
+By default, enumIAX only prints it's title and version information, and any 
+successfully found usernames.  These results are also appended to a results
+file of the format <target>.results in the current working directory.  To
+make enumIAX more verbose at runtime, use the "-v" command-line option,
+which is repeatable for more verbosity.
+
+Resuming a Previous Session
+---------------------------
+
+If your session was stopped prematurely, you can resume the session from it's
+state file.  State files are saved at regular intervals as well as enumIAX
+receiving most signals which would cause it to terminate.  You can resume a
+previous session with commands similar to the following:
+
+   enumiax -s <target>.state <target>
+
+   enumiax -d <dictfile> -s <target>.state <target>
+
+Rate-Limiting
+-------------
+
+By using the -r command-line option, you can rate-limit enumIAX to prevent
+flooding of the server.  The default is 500000 microseconds, or a half
+of a second.
+
+If the server begins to send Lag Requests (LAGRQ packets), enumIAX will
+automatically increase it's rate-limit value by 100000 microseconds to
+compensate.  Conversely, inumIAX is always trying to speed up by decreasing
+it's rate-limit value by 1000 microseconds per transaction.
+
+
+                                   License
+                                   =======
+
+enumIAX is released under the GNU General Public License v.2, the text of
+which can be found at the following URL:
+
+       http://www.gnu.org/copyleft/gpl.html
+
+
diff --git a/base.mk b/base.mk
new file mode 100644 (file)
index 0000000..cd16351
--- /dev/null
+++ b/base.mk
@@ -0,0 +1,27 @@
+# Compiler Options
+#CC = gcc
+CFLAGS = -O2 -Wall ${DEBUG}
+DEBUG = -g
+
+# Installation Options
+BINDIR = /usr/local/bin
+
+clean:
+       rm -f core *.o *~ enumiax
+       for i in `ls -l | grep "^d" | awk '{ print $$8 }'`; do \
+               cd $$i; \
+               if [ -e Makefile ]; then \
+                       make clean; \
+               fi; \
+               cd ../; \
+       done
+
+recurse:
+       for i in `ls -l | grep "^d" | awk '{ print $$8 }'`; do \
+               cd $$i; \
+               if [ -e Makefile ]; then \
+                       make; \
+               fi; \
+               cd ../; \
+       done
+
diff --git a/charmap.c b/charmap.c
new file mode 100644 (file)
index 0000000..89c8af3
--- /dev/null
+++ b/charmap.c
@@ -0,0 +1,19 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "enumiax.h"
+#include "charmap.h"
+
+
+int charmap_c_to_d( char ch ) {
+       int d;
+
+       for( d = 0; charmap[d] != '\0'; d++ )
+               if( charmap[d] == ch ) break;
+
+       return d;
+}
+
diff --git a/charmap.h b/charmap.h
new file mode 100644 (file)
index 0000000..2bd7d4f
--- /dev/null
+++ b/charmap.h
@@ -0,0 +1,19 @@
+static char charmap[] = \
+       /* Numbers */
+       "0123456789" \
+       /* Lowercase Alpha */
+       "abcdefghijklmnopqrstuvwxyz" \
+       /* Uppercase Alpha */
+/*     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ */ 
+       /* Special Character Set 1 */
+/*     "!@#$%^&*()-_+=~`" \ */
+       /* Special Character Set 2 */
+/*     "[]{}|\\:;"'<>,.?/" \ */
+       /* Space */
+       " " \
+       /* Tab */
+/*     "\t" \ */
+                       /* NULL Terminator - DO NOT REMOVE!!! */
+                       "\0" \
+;
+
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..7162be3
--- /dev/null
+++ b/config.h
@@ -0,0 +1,9 @@
+
+/* Auto-Generated Passphrase Options */
+
+/* Minimum & maximum default passphrase length in characters */
+#define MIN_USER_LEN 1
+#define MAX_USER_LEN 8
+#define MIN_PASS_LEN 1
+#define MAX_PASS_LEN 6
+
diff --git a/dict b/dict
new file mode 100644 (file)
index 0000000..bfff618
--- /dev/null
+++ b/dict
@@ -0,0 +1,9 @@
+guest
+iaxtel
+iaxtel2
+markster
+demo
+dynamichost
+biggateway
+marko
+test
diff --git a/enumiax.h b/enumiax.h
new file mode 100644 (file)
index 0000000..005cc94
--- /dev/null
+++ b/enumiax.h
@@ -0,0 +1,32 @@
+#include </usr/include/stdint.h>
+
+#include "config.h"
+
+
+#define VERSION "0.4a"
+
+/* charmap.c */
+int charmap_c_to_d( char ch );
+
+/* exit.c */
+void state_exit( int signum );
+int save_state( int signum );
+
+/* inet_hton.c */
+uint32_t inet_hton( char *host );
+
+/* outputs.c */
+void printbin( int buf, int bits );
+void printhex( unsigned char *buf, int size );
+
+/* worditer.c */
+int nextword();
+int nextdict();
+
+/* socket.c */
+int socket_build( char *target, int protocol, int port );
+
+/* usage.c */
+void version();
+void usage( char *prog );
+
diff --git a/exit.c b/exit.c
new file mode 100644 (file)
index 0000000..ec0d409
--- /dev/null
+++ b/exit.c
@@ -0,0 +1,57 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "enumiax.h"
+#include "charmap.h"
+
+
+void state_exit( int signum ) {
+       extern int verbosity;
+
+       /* For platforms that reset to SIG_DFL upon signal trap */
+       signal( signum, state_exit );
+
+       /* Save the state */
+       fprintf( stderr, "Caught signal %d, saving state...\n", signum );
+       verbosity++;
+       save_state( signum );
+
+       exit(0);
+}
+
+int save_state( int signum ) {
+       FILE *f1;
+       int x = 0;
+       char filename[64];
+       extern int verbosity;
+       extern char username[256];      
+       extern char *target;
+       extern char *dict;
+       extern time_t start, statetime;
+       time_t now;
+
+       now = time(NULL);
+
+       if( signum && ! dict ) {
+               /* If called from a sigtrap, and not dictionary mode, step username back one just in case the current one has not been tested yet */
+               x = strlen(username) -1;
+               username[x] = charmap[charmap_c_to_d(username[x]) - 1];
+       }
+
+       /* Create filename and open file */
+       snprintf( filename, sizeof(filename), "%s.state", target );
+       if( !(f1 = fopen( filename, "w" )) ) {
+               fprintf( stderr, "Error opening file %s to save state, manually save the following state line:\n", filename );
+               fprintf( stderr, "%s:%ld:%s\n", target, ((long)(now - start)) + statetime, username );
+               exit(0);
+       }
+       /* Write to file and close */
+       fprintf( f1, "%s:%ld:%s\n", target, ((long)(now - start)) + statetime, username );
+       fclose(f1);
+
+       if(verbosity) printf( "State (%s) saved in %s at: %s", username, filename, ctime(&now) );
+       return(0);
+}
diff --git a/inet_hton.c b/inet_hton.c
new file mode 100644 (file)
index 0000000..da1ab2b
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * inet_hton.c
+ * I)ruid <druid@caughq.org>
+ *
+ * Function to convert hostname (or IP address) into network byte
+ * order.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+
+uint32_t inet_hton( char *host ) {
+       struct in_addr addr;
+       struct hostent *h;
+
+       if( (inet_aton( host, &addr )) == 0 ) {
+               if( ! (h = gethostbyname( host )) ) {
+                       perror(host);
+                       return 0;
+               }
+               memcpy( &addr, h->h_addr_list[0], sizeof(addr) );
+       }
+       return addr.s_addr;
+}
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..a598460
--- /dev/null
+++ b/main.c
@@ -0,0 +1,371 @@
+/*
+ *  enumIAX
+ *  Dustin D. Trammell
+ *  <dtrammell@tippingpoint.com>
+ *
+ *  This tool will brute-force enumerate an IAX2 server's valid registration usernames
+ *
+ */
+
+#include <errno.h>
+#include <libgen.h>
+#include <locale.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "enumiax.h"
+#include "charmap.h"
+
+
+#define BUFFSIZE 276
+
+int verbosity;
+FILE *file;
+char username[256];
+char passphrase[256];
+short min_user_len, max_user_len;
+char *target;
+char *dict = NULL;
+time_t start, finish, statetime;
+int lower, upper;
+
+struct iax2_header {
+       unsigned int src_call : 15;
+       unsigned int packet_type : 1;
+       unsigned int dst_call : 15;
+       unsigned int retransmission : 1;
+       unsigned int timestamp;
+       unsigned char outseq;
+       unsigned char inseq;
+       unsigned char type;
+       unsigned char subclass;
+};
+
+
+int main( int argc, char *argv[] ) {
+       FILE *f1;
+       int seconds, minutes, hours, days, weeks, years;
+       int loop_count, save_interval;
+       int lkeys;
+       int sock;
+       int datalen;
+       int retry;
+       char ch;
+       char *prog;
+       char *statefile = NULL;
+       char *resultfile = NULL;
+       char *buff;
+       unsigned char *iax2_send;
+       unsigned char *iax2_recv;
+       struct protoent *proto;
+       struct iax2_header *iax2hdr_send, *iax2hdr_recv;
+       unsigned short scall;
+       unsigned long ratelimit = 500000;
+
+       /* Signals */
+       signal( SIGINT, state_exit );
+       signal( SIGQUIT, state_exit );
+       signal( SIGABRT, state_exit );
+       signal( SIGTERM, state_exit );
+
+       /* Defaults */
+       verbosity = 0;
+       lkeys = 0;
+       prog = basename( argv[0] );
+       target = NULL;
+       start = finish = statetime = 0;
+       seconds = minutes = hours = days = weeks = years = 0;
+       loop_count = 0;
+       save_interval = 50;
+       memset( username, '\0', sizeof(username) );
+       memset( passphrase, '\0', sizeof(passphrase) );
+       min_user_len = MIN_USER_LEN;
+       max_user_len = MAX_USER_LEN;
+       buff = malloc(BUFFSIZE);
+       memset( buff, 0, BUFFSIZE );
+       lower = 0;
+       upper = strlen(charmap) - 1;
+
+
+       while( (ch = getopt(argc, argv, "+d:i:m:M:r:s:vVh")) != EOF ) {
+               switch( ch ) {
+                       case 'd':
+                               dict = optarg;
+                               break;
+                       case 'i':
+                               save_interval = atoi(optarg);
+                               break;
+                       case 'm':
+                               min_user_len = atoi(optarg);
+                               break;
+                       case 'M':
+                               max_user_len = atoi(optarg);
+                               break;
+                       case 'r':
+                               ratelimit = atoi(optarg);
+                               break;
+                       case 's':
+                               statefile = optarg;
+                               break;
+                       case 'v':
+                               verbosity++;
+                               break;
+                       case 'V':
+                               version();
+                               exit(0);
+                       case 'h':
+                       default:
+                               usage( prog );
+               }
+       }
+       /* not enough arguments */
+       if( argv[optind] ) target = argv[optind];
+       else usage( prog );
+
+       /* too many arguments */
+       if( argv[optind+1] ) usage( prog );
+
+       version();
+       srand(time(NULL));
+
+       if( statefile ) {
+               if( !(f1 = fopen( statefile, "r" )) ) {
+                       fprintf( stderr, "Unable to open statefile %s for reading... exiting.\n", statefile );
+                       exit(1);
+               }
+               if( !(fgets( buff, BUFFSIZE, f1 )) ) {
+                       fprintf( stderr, "Unable to read from open statefile %s... exiting.\n", statefile ); 
+                       exit(1);
+               }
+               if( strcmp( strsep( &buff, ":" ), target ) != 0 ) {
+                       fprintf( stderr, "State found in statefile %s does not match target of %s... exiting.\n", statefile, target );
+                       exit(1);
+               }
+               statetime = (time_t) atoi( strsep( &buff, ":" ) );
+               snprintf( username, sizeof(username), "%s", strsep( &buff, "\n" ) );
+       }
+
+       if(verbosity) printf( "Target Aquired: %s\n", target );
+       if(verbosity>=2) printf( "Save Interval: %d attempts\n", save_interval );
+       if(verbosity>=2) printf( "Using Charmap (%d characters):\n  \"%s\"\n", strlen(charmap) - 1, charmap );
+
+       /* Build result filename */
+       resultfile = malloc(strlen(target)+8);
+       snprintf( resultfile, (strlen(target)+8), "%s.result", target );
+
+       /* Determine whether we're generating passphrases or using a dict file */
+       if( dict ) {
+               if( (file = fopen( dict, "r" )) == NULL ) {
+                       fprintf( stderr, "Error: Could not open dict file %s\n", dict );
+                       exit(-1);
+               }
+               if( statefile ) {
+                       /* Wind forward file pointer to current username in dict file */
+                       do {
+                               if( ! fgets( buff, BUFFSIZE, file ) ) {
+                                       fprintf( stderr, "Error: State Mismatch:\n  Dict file (%s) did not contain word (%s) found in state file (%s), exiting.\n", dict, username, statefile );
+                                       exit(-1);
+                               }
+                               buff[strlen(buff)-1] = '\0';
+                       } while( strcmp( buff, username ) != 0 );
+               }
+       }
+
+       /* Build IAX2 REGREQ payloads (sans username) */
+       iax2_send = malloc(256);
+       iax2hdr_send = (struct iax2_header *)iax2_send;
+       iax2_recv = malloc(256);
+       iax2hdr_recv = (struct iax2_header *)iax2_recv;
+       const char iax2userhdr[] = "\x06\x00";
+       const char iax2trailer[] = "\x13\x02\x07\x08";
+
+       /* Resolve target and set up UDP socket */
+       if( !(proto = getprotobyname( "UDP" )) ) {
+               fprintf( stderr, "Error: Protocol \"%s\" not recognized.\n", "UDP" );
+               exit(-1);
+       }
+       if( (sock = socket_build( target, proto->p_proto, 4569 )) == -1 ) exit(-1);
+
+       /* Start enum routine */
+       start = time(NULL);
+       if(verbosity) printf( "Starting enum process at: %s", ctime(&start) );
+
+       /* Initialize username */
+       if( dict ) nextdict();
+       else nextword();
+
+       while(1) {
+               /* Update IAX2 REGREQ payload with current username */
+               iax2hdr_send->packet_type = 1;
+               scall = (rand()%32766)+1;
+               iax2hdr_send->src_call = scall;
+               iax2hdr_send->retransmission = 0;
+               iax2hdr_send->dst_call = 0;
+               ch = iax2_send[0]; iax2_send[0] = iax2_send[1]; iax2_send[1] = ch;
+               ch = iax2_send[2]; iax2_send[2] = iax2_send[3]; iax2_send[3] = ch;
+               iax2hdr_send->timestamp = time(NULL);
+               iax2hdr_send->outseq = 0;
+               iax2hdr_send->inseq = 0;
+               iax2hdr_send->type = 6;
+               iax2hdr_send->subclass = 13;
+
+               memcpy( iax2_send+12, iax2userhdr, 2 );
+               iax2_send[13] = strlen(username); /* Size of Username to try */
+               memcpy( iax2_send+14, username, strlen(username) ); /* Username to try */
+               memcpy( iax2_send+(14+strlen(username)), iax2trailer, 4 );
+               datalen = 12 + 2 + strlen(username) + 4;
+
+               /* Send payload to IAX server */
+               if(verbosity>=2) printf( "\nSending %d byte REGREQ message:\n", datalen );
+               if(verbosity>=3) printhex( iax2_send, datalen );
+               retry = 0;
+               while( (write( sock, iax2_send, datalen )) == -1 ) {
+                       fprintf( stderr, "write: %s\n", strerror(errno) );
+                       fprintf( stderr, "Sleeping 1 sec before retry...\n" );
+                       sleep(1);
+                       if( retry++ >= 3 ) {
+                               fprintf( stderr, "Retries exhausted, exiting.\n" );
+                               exit(-1);
+                       }
+               }
+               if(verbosity>=3) printf( "Send succeeded.\n" );
+
+               /* Read response */
+               readresponse:
+               datalen = read( sock, iax2_recv, 256 );
+               if( datalen == -1 ) {
+                       fprintf( stderr, "read: %s\n", strerror(errno) );
+                       exit(-1);
+               }
+               if(verbosity>=2) printf( "%d byte response received: (IAX2 type %d)\n", datalen, iax2_recv[11] );
+               if(verbosity>=3) printhex( iax2_recv, datalen );
+
+               /* Swap byte order for first four bytes */
+               ch = iax2_recv[0]; iax2_recv[0] = iax2_recv[1]; iax2_recv[1] = ch;
+               ch = iax2_recv[2]; iax2_recv[2] = iax2_recv[3]; iax2_recv[3] = ch;
+
+               /* Verify IAX2 packet */
+               if( iax2_recv[10] != 6 ) fprintf( stderr, "Error: Received packet is not IAX2!\n" );
+
+               /* Send ACK for specific response types */
+               if( iax2_recv[11] == 14 || iax2_recv[11] == 15 || iax2_recv[11] == 16 ) { /* REGAUTH || REGACK || REGREJ */
+                       iax2hdr_send->packet_type = 1;
+                       iax2hdr_send->src_call = iax2hdr_recv->dst_call;
+                       iax2hdr_send->retransmission = 0;
+                       iax2hdr_send->dst_call = iax2hdr_recv->src_call;
+                       ch = iax2_send[0]; iax2_send[0] = iax2_send[1]; iax2_send[1] = ch;
+                       ch = iax2_send[2]; iax2_send[2] = iax2_send[3]; iax2_send[3] = ch;
+                       iax2hdr_send->timestamp = time(NULL);
+                       iax2hdr_send->inseq = 1;
+                       iax2hdr_send->outseq = 1;
+                       iax2hdr_send->type = 6;
+                       iax2hdr_send->subclass = 4;
+                       datalen = sizeof(iax2hdr_send);
+       
+                       if(verbosity>=2) printf( "Sending %d byte ACK message:\n", datalen );
+                       if(verbosity>=3) printhex( iax2_send, datalen );
+                       retry = 0;
+                       while( (write( sock, iax2_send, 12 )) == -1 ) {
+                               fprintf( stderr, "write: %s\n", strerror(errno) );
+                               fprintf( stderr, "Sleeping 1 sec before retry...\n" );
+                               sleep(1);
+                               if( retry++ >= 3 ) {
+                                       fprintf( stderr, "Retries exhausted, exiting.\n" );
+                                       exit(-1);
+                               }
+                       }
+                       if(verbosity>=3) printf( "Send succeeded.\n" );
+               }
+
+               /* Check for Lag Request (LAGRQ) */
+               if( iax2_recv[11] == 11 ) {
+                       if(verbosity>=3) printf( "Received Lag Request (LAGRQ) from target, throttling...\n" );
+                       ratelimit += 100000;
+               }
+
+               /* Verify packet received is for current call */
+               if( (unsigned short)iax2hdr_recv->dst_call != scall ) {
+                       if(verbosity>=3) printf( "Packet received (call %d) is not from current call (call %d).\n  Waiting for subsequent response...\n", iax2hdr_recv->dst_call, scall );
+                       goto readresponse;
+               }
+
+               /* Check Response IE type */
+               if( iax2_recv[11] == 4 ) {
+                       if(verbosity>=3) printf( "Packet received is IAX2 ACK.  Waiting for subsequent response...\n" );
+                       goto readresponse;
+               }
+
+               /* SUCCESS */
+               if( iax2_recv[11] == 14 || iax2_recv[11] == 15 ) { /* REGAUTH || REGACK */
+                       finish = time(NULL);
+                       if( iax2_recv[11] == 14 ) printf( "  !!! Found valid username (%s) at: %s\n", username, ctime(&finish) );
+                       if( iax2_recv[11] == 15 ) printf( "  !!! Found valid UNAUTHENTICATED username (%s) at: %s\n", username, ctime(&finish) );
+                       seconds = (int)(finish - start);
+                       if( seconds > 60 ) {
+                               minutes = seconds / 60;
+                               seconds = seconds % 60;
+                       }
+                       if( minutes > 60 ) {
+                               hours = minutes / 60;
+                               minutes = minutes % 60;
+                       }
+                       if( hours > 24 ) {
+                               days = hours / 24;
+                               hours = hours % 24;
+                       }
+                       if( days > 7 ) {
+                               weeks = days / 7;
+                               days = days % 7;
+                       }
+                       if( weeks > 52 ) {
+                               years = weeks / 52;
+                               weeks = weeks % 52;
+                       }
+                       if(verbosity) {
+                               printf( "Total time to find:" ); 
+                               if( years ) printf( " %d years", years );
+                               if( weeks ) printf( " %d weeks", weeks);
+                               if( days ) printf( " %d days", days );
+                               if( hours ) printf( " %d hours", hours );
+                               if( minutes ) printf( " %d minutes", minutes );
+                               printf( " %d seconds\n", seconds );
+                       }
+                       /* write valid out to file */
+                       f1 = fopen( resultfile, "a" );
+                       if( iax2_recv[11] == 14 ) fprintf( f1, "username: %s\n", username );
+                       if( iax2_recv[11] == 15 ) fprintf( f1, "unauthenticated username: %s\n", username );
+                       fclose(f1);
+               } else {
+                       /* ERROR */
+                       if(verbosity>=2) printf( "IAX2 packet (Subclass %d) was not REGAUTH or REGACK, invalid username.\n", iax2_recv[11] );
+               }
+
+               /* FAILURE */
+               loop_count++;
+               if( loop_count >= save_interval) {
+                       save_state(0);
+                       loop_count = 0;
+               }
+
+               /* Rate Limiting */
+               if( ratelimit ) {
+                       if(verbosity>=2) fprintf( stderr, "Rate-Limiting: Sleeping for %ld microseconds.\n", ratelimit );
+                       usleep(ratelimit);
+                       if( ratelimit >= 1000 ) ratelimit = ratelimit - 1000;
+               }
+
+               /* increment username */
+               if( dict ) nextdict();
+               else nextword();
+
+       }
+
+       /* Cleanup */
+       if(dict) fclose(file);
+       exit(-1);
+}
diff --git a/outputs.c b/outputs.c
new file mode 100644 (file)
index 0000000..f40498d
--- /dev/null
+++ b/outputs.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+
+void printbin( int buf, int bits ) {
+       for( ; bits>0 ; bits-- ) {
+               if( buf & 1 )
+                       printf( "1" );
+               else
+                       printf( "0" );
+       buf>>=1;
+       }
+}
+
+void printhex( unsigned char *buf, int size ) {
+       int x;
+       for( x=0; x<size; x++ ) {
+               if( x % 8 == 0 ) printf( " " );
+               if( x % 16 == 0 ) printf( "\n%04x  ", x );
+               printf( "%02x ", buf[x] );
+       }
+       printf( "\n\n" );
+}
+
diff --git a/socket.c b/socket.c
new file mode 100644 (file)
index 0000000..2693198
--- /dev/null
+++ b/socket.c
@@ -0,0 +1,48 @@
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "enumiax.h"
+
+
+int socket_build( char *target, int protocol, int port ) {
+       extern int verbosity;
+       struct protoent *proto;
+       int sock;
+       int type;
+
+       /* Resolve target */
+       struct in_addr address;
+       address.s_addr = inet_hton(target);
+
+       /* Create socket based on selected transport */
+       proto = getprotobynumber(protocol);
+       if(verbosity) printf( "Connecting to %s via %s on port %d...\n", inet_ntoa(address), proto->p_name, port ); 
+       type = SOCK_STREAM;
+       if( protocol == 6 ) type = SOCK_STREAM;
+       if( protocol == 17 ) type = SOCK_DGRAM;
+       if( (sock = socket( PF_INET, type, protocol )) == -1 ) {
+               fprintf( stderr, "socket: %s\n", strerror(errno) );
+               return -1;
+       }
+
+       /* Connect the socket */
+       struct sockaddr_in addr;
+       addr.sin_family = PF_INET;
+       addr.sin_addr.s_addr = address.s_addr;
+       addr.sin_port = htons(port);
+       if( (connect( sock, (struct sockaddr *)&addr, sizeof(addr) )) == -1 ) {
+               fprintf( stderr, "connect: %s\n", strerror(errno) );
+               return -1;
+       }
+
+       if(verbosity>=2) fprintf( stderr, "Connected to: %s\n", inet_ntoa(address));
+
+       return sock;
+}
diff --git a/usage.c b/usage.c
new file mode 100644 (file)
index 0000000..2e83e25
--- /dev/null
+++ b/usage.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "enumiax.h"
+
+
+void version() {
+       fprintf( stderr, "enumIAX %s\n", VERSION );
+       fprintf( stderr, "Dustin D. Trammell <dtrammell@tippingpoint.com>\n\n" );
+}
+
+void usage( char *prog ) {
+       version();
+       fprintf( stderr, "Usage: %s [options] target\n", prog );
+       fprintf( stderr, "  options:\n" );
+       fprintf( stderr, "    -d <dict>   Dictionary attack using <dict> file\n" );
+       fprintf( stderr, "    -i <count>  Interval for auto-save (# of operations, default 1000)\n" );
+       fprintf( stderr, "    -m #        Minimum username length (in characters)\n" );
+       fprintf( stderr, "    -M #        Maximum username length (in characters)\n" );
+       fprintf( stderr, "    -r #        Rate-limit calls (in microseconds)\n" );
+       fprintf( stderr, "    -s <file>   Read session state from state file\n" );
+       fprintf( stderr, "    -v          Increase verbosity (repeat for additional verbosity)\n" );
+       fprintf( stderr, "    -V          Print version information and exit\n" );
+       fprintf( stderr, "    -h          Print help/usage information and exit\n" );
+       exit(-1);
+}
+
diff --git a/worditer.c b/worditer.c
new file mode 100644 (file)
index 0000000..74487e5
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * passcb.c - GPGuess Passphrase Callback Functions
+ *
+ * These functions provide usernames for the GPGME crypto
+ * operations.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "enumiax.h"
+#include "charmap.h"
+
+
+int nextword() {
+       int x = 0, y = 0;
+       extern int lower, upper;
+       extern int verbosity;
+       extern int min_user_len, max_user_len;
+       extern char username[256];
+
+       /* If username doesn't exist, build start username */
+       if( ! username[0] ) {
+               /* enforce minimum username length requirement */
+               for( x = 0; x < min_user_len; x++ ) username[x] = charmap[lower];
+               if(verbosity) printf( "Now working on %d character usernames...\n", min_user_len );
+               goto ret;
+       }
+
+       /* Determine username's current length and set current char index at last char */
+       y = x = strlen(username) - 1;
+
+       for( ; x >= 0; x-- ) {
+               if( username[x] != charmap[upper] ) { /* Has current char hit upper bound? */
+                       /* If not, iterate current char to next char in charmap and break */
+                       username[x] = charmap[charmap_c_to_d(username[x]) + 1];
+                       break;
+               } else {
+                       /* If so, reset current char to lower bound */
+                       username[x] = charmap[lower];
+                       /* Check to see if we're resetting the first char in username */
+                       if( x == 0 ) {
+                               /* If so, check to see if adding another char would exceed max_user_length */
+                               if( y+1 == max_user_len ) { 
+                                       printf( "Username combinations exausted, exiting...\n" );
+                                       exit(-1);
+                               }
+                               /* Add another char to the username length */
+                               y++;
+                               username[y] = charmap[lower];
+                               if(verbosity) printf( "Now working on %d character usernames...\n", y+1 );
+                       }
+               }
+       }
+
+       ret:
+       if(verbosity) printf( "\n#################################\n" );
+       if(verbosity>=1) printf( "Trying username: \"%s\"\n", username );
+       return 0;
+}
+
+int nextdict() {
+       extern int verbosity;
+       extern FILE *file;
+       extern char username[256];
+
+       if( !(fgets( username, sizeof(username), file )) ) {
+               if(verbosity) printf( "End of dictionary file reached, exiting.\n" );
+               exit(0);
+       }
+       username[strlen(username)-1] = '\0';
+
+       if(verbosity) printf( "\n#################################\n" );
+       if(verbosity>=1) printf( "Trying username: \"%s\"\n", username );
+       return 0;
+}
+