1 #include "hydra-mod.h"
2 
3 /*
4 
5 RFC 1459: Internet Relay Chat Protocol
6 
7 */
8 
9 extern char *HYDRA_EXIT;
10 char buffer[300] = "";
11 int32_t myport = PORT_IRC, mysslport = PORT_IRC_SSL;
12 
start_oper_irc(int32_t s,char * ip,int32_t port,unsigned char options,char * miscptr,FILE * fp)13 int32_t start_oper_irc(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp) {
14   char *empty = "";
15   char *login, *pass;
16   int32_t ret;
17 
18   if (strlen(login = hydra_get_next_login()) == 0)
19     login = empty;
20   if (strlen(pass = hydra_get_next_password()) == 0)
21     pass = empty;
22 
23   sprintf(buffer, "OPER %s %s\r\n", login, pass);
24   if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
25     return 3;
26   }
27   ret = hydra_recv(s, buffer, sizeof(buffer) - 1);
28   if (ret >= 0)
29     buffer[ret] = 0;
30   /* :irc.debian.org 381 koma :You are now an IRC Operator */
31   /* :irc.debian.org 464 koma :Invalid password */
32   if ((ret > 0) && (strstr(buffer, " 381 ") != NULL)) {
33     hydra_report_found_host(port, ip, "irc", fp);
34     hydra_completed_pair_found();
35   } else {
36     hydra_completed_pair();
37   }
38 
39   if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
40     return 3;
41   return 2;
42 }
43 
send_nick(int32_t s,char * ip,char * pass)44 int32_t send_nick(int32_t s, char *ip, char *pass) {
45   if (strlen(pass) > 0) {
46     sprintf(buffer, "PASS %s\r\n", pass);
47     if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
48       return -1;
49     }
50   }
51   sprintf(buffer, "CAP LS\r\n");
52   if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
53     return -1;
54   }
55   sprintf(buffer, "NICK hydra%d\r\nUSER hydra%d hydra %s :hydra\r\n", (int32_t)getpid(), (int32_t)getpid(), hydra_address2string(ip));
56   if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
57     return -1;
58   }
59   return 0;
60 }
61 
irc_server_connect(char * ip,int32_t sock,int32_t port,unsigned char options,char * hostname)62 int32_t irc_server_connect(char *ip, int32_t sock, int32_t port, unsigned char options, char *hostname) {
63   if (sock >= 0)
64     sock = hydra_disconnect(sock);
65   //        usleepn(275);
66   if ((options & OPTION_SSL) == 0) {
67     if (port != 0)
68       myport = port;
69     sock = hydra_connect_tcp(ip, myport);
70     port = myport;
71   } else {
72     if (port != 0)
73       mysslport = port;
74     sock = hydra_connect_ssl(ip, mysslport, hostname);
75     port = mysslport;
76   }
77   return sock;
78 }
79 
start_pass_irc(int32_t s,char * ip,int32_t port,unsigned char options,char * miscptr,FILE * fp,char * hostname)80 int32_t start_pass_irc(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp, char *hostname) {
81   char *empty = "";
82   char *pass;
83   int32_t ret;
84 
85   if (strlen(pass = hydra_get_next_password()) == 0)
86     pass = empty;
87 
88   s = irc_server_connect(ip, s, port, options, hostname);
89   if (s < 0) {
90     hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t)getpid());
91     return 3;
92   }
93 
94   if (send_nick(s, ip, pass) < 0) {
95     return 3;
96   }
97 
98   ret = hydra_recv(s, buffer, sizeof(buffer) - 1);
99   if (ret >= 0)
100     buffer[ret] = 0;
101 #ifdef HAVE_PCRE
102   if ((ret > 0) && (!hydra_string_match(buffer, "ERROR\\s.*password"))) {
103 #else
104   if ((ret > 0) && (strstr(buffer, "ERROR") == NULL)) {
105 #endif
106     hydra_report_pass_found(port, ip, "irc", fp);
107     hydra_completed_pair_found();
108     hydra_report(stderr,
109                  "[INFO] Server password '%s' is working, you can pass it as "
110                  "argument\nto irc module to then try login/password oper mode\n",
111                  pass);
112   } else {
113     if (verbose && (miscptr != NULL))
114       hydra_report(stderr,
115                    "[VERBOSE] Server is requesting a general password, '%s' "
116                    "you entered is not working\n",
117                    miscptr);
118     hydra_completed_pair();
119   }
120 
121   if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
122     return 3;
123   return 4;
124 }
125 
126 void service_irc(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
127   int32_t run = 1, next_run = 1, sock = -1, ret;
128   char *buf;
129 
130   hydra_register_socket(sp);
131 
132   if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
133     return;
134   while (1) {
135     next_run = 0;
136     switch (run) {
137     case 1: /* connect and service init function */
138 
139       sock = irc_server_connect(ip, sock, port, options, hostname);
140       if (sock < 0) {
141         hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t)getpid());
142         hydra_child_exit(1);
143       }
144 
145       if (miscptr == NULL) {
146         miscptr = "";
147       }
148       if (send_nick(sock, ip, miscptr) < 0) {
149         hydra_child_exit(1);
150       }
151 
152       buffer[0] = 0;
153       if ((ret = hydra_recv(sock, buffer, sizeof(buffer) - 1)) >= 0)
154         buffer[ret] = 0;
155 
156         /* ERROR :Bad password */
157 #ifdef HAVE_PCRE
158       if ((ret > 0) && (hydra_string_match(buffer, "ERROR\\s.*password"))) {
159 #else
160       if ((ret > 0) && (strstr(buffer, "ERROR") != NULL)) {
161 #endif
162         if (verbose)
163           hydra_report(stderr, "[INFO] Server is requesting a password, will try to find it\n");
164         if (sock >= 0)
165           sock = hydra_disconnect(sock);
166         next_run = 4;
167         break;
168       }
169 
170       while (hydra_data_ready(sock)) {
171         buf = hydra_receive_line(sock);
172         free(buf);
173       }
174 
175       if ((ret > 0) && (strstr(buffer, " 432 ") != NULL)) {
176         /* :irc.debian.org 432 * hydra_5075 :Erroneous nickname */
177         if (verbose)
178           hydra_report(stderr, "[ERROR] Erroneous nickname\n");
179         hydra_child_exit(0);
180       }
181 
182       if ((ret > 0) && (strstr(buffer, " 433 ") != NULL)) {
183         /* :irc.debian.org 433 * hydra :Nickname already in use */
184         if (verbose)
185           hydra_report(stderr, "[ERROR] Nickname already in use\n");
186         hydra_child_exit(0);
187       }
188 
189       /* ERROR :Bad password is returned from ngircd when it s waiting for a
190        * server password */
191       if ((ret > 0) && (strstr(buffer, " 001 ") == NULL)) {
192         /* seems we not successfully connected */
193         hydra_report(stderr,
194                      "[ERROR] should not be able to identify server msg, "
195                      "please report it\n%s\n",
196                      buffer);
197         hydra_child_exit(0);
198       }
199 
200       next_run = 2;
201       break;
202     case 2: /* run the cracking function */
203       next_run = start_oper_irc(sock, ip, port, options, miscptr, fp);
204       break;
205     case 3: /* clean exit */
206       if (sock >= 0)
207         sock = hydra_disconnect(sock);
208       hydra_child_exit(0);
209       return;
210     case 4:
211       next_run = start_pass_irc(sock, ip, port, options, miscptr, fp, hostname);
212       break;
213     default:
214       hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
215       hydra_child_exit(2);
216     }
217     run = next_run;
218   }
219 }
220 
221 int32_t service_irc_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
222   // called before the childrens are forked off, so this is the function
223   // which should be filled if initial connections and service setup has to be
224   // performed once only.
225   //
226   // fill if needed.
227   //
228   // return codes:
229   //   0 all OK
230   //   -1  error, hydra will exit, so print a good error message here
231 
232   return 0;
233 }
234 
235 void usage_irc(const char *service) {
236   printf("Module irc is optionally taking the general server password, if the "
237          "server is requiring one, and if none is passed the password from "
238          "-p/-P will be used\n\n");
239 }
240