1 diff -urN dsniff-2.3/ChangeLog.ggsniff dsniff-2.3-gg/ChangeLog.ggsniff
2 --- dsniff-2.3/ChangeLog.ggsniff Thu Jan 1 01:00:00 1970
3 +++ dsniff-2.3-gg/ChangeLog.ggsniff Wed Oct 30 14:49:43 2002
6 + - dsniff doesn't compile with newest libnet, use older version (1.0.x)
10 + - added password sniffing (switch -w)
13 + - sometimes local user's nick was incorrectly displayed
14 + - added switch -s for simple output (without IP addresses)
15 + - updated man page for msgsnarf
16 + - added short documentation for ggsniff
19 + - fixed silly "cut&paste" bug
22 + - fixed silly segfault in process_gg()
25 + - added printing remote GG user's IP (if available)
28 + - fixed segfault in process_msn() [dsniff-2.3-segfault.patch]
29 + - added switch -d for debugging info
30 + - added switch -p for disabling promiscous mode (useful on routers)
31 +[dsniff-2.3-promisc.patch]
32 + - sniffer recognizes data direction
33 + - different connections from single IP do not share client_info
34 + - sniffing GG connections to port 443
35 + - support for extensions in new GG protocol (client version 4.9.3+)
38 + - added printing local GG user's IP
42 diff -urN dsniff-2.3/msgsnarf.8 dsniff-2.3-gg/msgsnarf.8
43 --- dsniff-2.3/msgsnarf.8 Sun Nov 19 07:10:50 2000
44 +++ dsniff-2.3-gg/msgsnarf.8 Wed Oct 30 12:28:00 2002
49 -\fBmsgsnarf\fR [\fB-i \fIinterface\fR] [[\fB-v\fR] \fIpattern [\fIexpression\fR]]
50 +\fBmsgsnarf\fR [\fB-d\fR] [\fB-p\fR] [\fB-s\fR] [\fB-w\fR] [\fB-i \fIinterface\fR] [[\fB-v\fR] \fIpattern [\fIexpression\fR]]
54 \fBmsgsnarf\fR records selected messages from AOL Instant
55 -Messenger, ICQ 2000, IRC, MSN Messenger, or Yahoo Messenger chat
56 +Messenger, ICQ 2000, IRC, MSN Messenger, Gadu-Gadu, or Yahoo Messenger chat
60 +Debug mode (prints more information about Gadu-Gadu connections).
61 .IP "\fB-i \fIinterface\fR"
62 Specify the interface to listen on.
64 +Disable promiscous mode.
66 +Simple output, without IP addresses.
68 +Enable Gadu-Gadu password sniffing.
70 "Versus" mode. Invert the sense of matching, to select non-matching
72 diff -urN dsniff-2.3/msgsnarf.c dsniff-2.3-gg/msgsnarf.c
73 --- dsniff-2.3/msgsnarf.c Fri Dec 15 21:12:19 2000
74 +++ dsniff-2.3-gg/msgsnarf.c Wed Oct 30 12:36:19 2002
79 - Sniff chat messages (AIM, ICQ, IRC, MSN, Yahoo) on a network.
80 + Sniff chat messages (AIM, ICQ, IRC, MSN, Yahoo, Gadu-Gadu) on a network.
82 Copyright (c) 1999 Dug Song <dugsong@monkey.org>
92 +#define GGVERSION "1.2"
95 +#define PACKED __attribute__ ((packed))
102 + unsigned short port;
103 + in_addr_t local_ip;
104 SLIST_ENTRY(client_info) next;
107 SLIST_HEAD(, client_info) client_list;
109 regex_t *pregex = NULL;
117 - fprintf(stderr, "Version: " VERSION "\n"
118 - "Usage: msgsnarf [-i interface] [[-v] pattern [expression]]\n");
119 + fprintf(stderr, "Version: " VERSION " (ggsniff " GGVERSION ")\n"
120 + "Usage: msgsnarf [-d] [-p] [-s] [-w] [-i interface] [[-v] pattern [expression]]\n");
128 -process_aim(struct client_info *info, u_char *data, int len)
129 +process_aim(struct client_info *info, u_char *data, int len, int dir)
131 struct buf *msg, *word, buf;
137 -process_irc(struct client_info *info, u_char *data, int len)
138 +process_irc(struct client_info *info, u_char *data, int len, int dir)
140 struct buf *line, *word, *prefix, buf;
146 -process_msn(struct client_info *info, u_char *data, int len)
147 +process_msn(struct client_info *info, u_char *data, int len, int dir)
149 struct buf *word, *line, buf;
155 -process_yahoo(struct client_info *info, u_char *data, int len)
156 +process_yahoo(struct client_info *info, u_char *data, int len, int dir)
160 @@ -544,11 +554,338 @@
161 return (len - buf_len(&buf));
166 + Support for GG messages added by Ryba <ryba_84@hotmail.com>
169 + Protocol description taken from EKG (http://dev.null.pl/ekg/)
170 + by <wojtekka@irc.pl>, <speedy@atman.pl> and others.
171 + Thanks to all of them!
173 + Gadu-Gadu (http://www.gadu-gadu.pl) is a Polish communicator.
174 + I believe it is a most popular instant messenger in Poland.
177 +struct remote_client_info {
181 + unsigned short port;
182 + SLIST_ENTRY(remote_client_info) next;
185 +SLIST_HEAD(, remote_client_info) remote_client_list;
187 +#define GG_NETWORK "217.17.41.80"
188 +#define GG_NETMASK "255.255.255.248"
189 +unsigned int gg_network;
190 +unsigned int gg_netmask;
192 +#define GG_LOGIN 0x000c
193 +#define GG_LOGIN_EXT 0x0013
194 +#define GG_SEND_MSG 0x000b
195 +#define GG_RECV_MSG 0x000a
196 +#define GG_NOTIFY_REPLY 0x000c
197 +#define GG_NOTIFY 0x0010
199 +#define GG_STATUS_NOT_AVAIL_DESCR 0x0015
200 +#define GG_STATUS_AVAIL_DESCR 0x0004
201 +#define GG_STATUS_BUSY_DESCR 0x0005
208 +struct gg_send_msg {
215 +struct gg_recv_msg {
229 + u_short local_port;
232 +struct gg_login_ext {
240 + short external_port;
243 +struct gg_notify_reply {
252 +struct in_addr int2in_addr(u_int i) {
258 +struct remote_client_info *find_remote_client(int uin) {
260 + struct remote_client_info *rc;
263 + SLIST_FOREACH(rc, &remote_client_list, next) {
264 + if (rc->uin == uin) {
276 +struct remote_client_info *add_remote_client(struct remote_client_info newrc) {
277 + struct remote_client_info *rc;
279 + if ((rc = malloc(sizeof(*rc))) == NULL)
280 + nids_params.no_mem("sniff_msgs");
281 + memset(rc, 0, sizeof(*rc));
282 + rc->uin = newrc.uin;
284 + rc->port = newrc.port;
285 + SLIST_INSERT_HEAD(&remote_client_list, rc, next);
289 +#define GG_NICK_SIZE 45
290 +#define GG_IP_SIZE 16
292 +int process_gg(struct client_info *info, u_char *data, int len, int dir) {
294 + struct buf *msg, buf;
295 + struct gg_header *header;
296 + struct gg_send_msg *send_msg;
297 + struct gg_recv_msg *recv_msg;
298 + struct gg_login *login;
299 + struct gg_login_ext *login_ext;
300 + struct gg_notify_reply *notify_reply;
301 + struct remote_client_info *rc;
302 + struct remote_client_info new_rc;
304 + char sbuff[GG_NICK_SIZE];
305 + char local_ip[GG_IP_SIZE];
309 + buf_init(&buf, data, len);
311 + while (buf_len(&buf) > sizeof(*header)) {
312 + header = (struct gg_header *)buf_ptr(&buf);
313 + i = sizeof(*header) + header->length;
315 + if ((msg = buf_tok(&buf, NULL, i)) == NULL)
318 + buf_skip(msg, sizeof(*header));
320 + if ((header->type == GG_LOGIN || header->type == GG_LOGIN_EXT)&& dir == TO_SERVER) {
322 + login_ext = (struct gg_login_ext *)buf_ptr(msg);
324 + if (Opt_simple != 0) {
325 + snprintf(sbuff, GG_NICK_SIZE, "%u", login_ext->uin);
327 + if (info->ip == login_ext->local_ip) {
328 + snprintf(sbuff, GG_NICK_SIZE, "%s/%u", inet_ntoa(int2in_addr(info->ip)), login_ext->uin);
330 + snprintf(local_ip, GG_IP_SIZE, inet_ntoa(int2in_addr(login_ext->local_ip)));
331 + snprintf(sbuff, GG_NICK_SIZE, "%s/%s/%u", inet_ntoa(int2in_addr(info->ip)), local_ip, login_ext->uin);
334 + if (info->nick) free(info->nick);
335 + info->nick = strdup(sbuff);
337 + if (Opt_debug != 0) {
338 + if (header->type == GG_LOGIN) {
339 + printf("%s GG_LOGIN %s\n", timestamp(), info->nick);
341 + printf("%s GG_LOGIN_EXT %s\n", timestamp(), info->nick);
346 + if (header->type == GG_SEND_MSG && dir == TO_SERVER) {
347 + send_msg = (struct gg_send_msg *)buf_ptr(msg);
348 + buf_skip(msg, sizeof(*send_msg));
350 + p = buf_strdup(msg);
351 + if (regex_match(p)) {
352 + rc = find_remote_client(send_msg->recipient);
353 + if (rc && rc->ip != 0) {
354 + snprintf(sbuff, GG_NICK_SIZE, "%s:%u/%u", inet_ntoa(int2in_addr(rc->ip)), rc->port, rc->uin);
356 + snprintf(sbuff, GG_NICK_SIZE, "%u", send_msg->recipient);
358 + printf("%s GG_SEND %s > %s: %s\n", timestamp(), info->nick, sbuff, p);
363 + if (header->type == GG_RECV_MSG && dir == TO_CLIENT) {
364 + recv_msg = (struct gg_recv_msg *)buf_ptr(msg);
365 + buf_skip(msg, sizeof(*recv_msg));
367 + p = buf_strdup(msg);
368 + if (regex_match(p)) {
369 + rc = find_remote_client(recv_msg->sender);
370 + if (rc && rc->ip != 0) {
371 + snprintf(sbuff, GG_NICK_SIZE, "%s:%u/%u", inet_ntoa(int2in_addr(rc->ip)), rc->port, rc->uin);
373 + snprintf(sbuff, GG_NICK_SIZE, "%u", recv_msg->sender);
375 + printf("%s GG_RECV %s < %s: %s\n", timestamp(), info->nick, sbuff, p);
380 + if (header->type == GG_NOTIFY_REPLY && dir == TO_CLIENT) {
381 + notify_reply = (struct gg_notify_reply *)buf_ptr(msg);
383 + if (notify_reply->status == GG_STATUS_NOT_AVAIL_DESCR ||
384 + notify_reply->status == GG_STATUS_AVAIL_DESCR ||
385 + notify_reply->status == GG_STATUS_BUSY_DESCR) {
388 + count = header->length / sizeof(*notify_reply);
391 + for (i = 0; i < count; i++) {
392 + rc = find_remote_client(notify_reply->uin);
395 + rc->ip = notify_reply->remote_ip;
396 + rc->port = notify_reply->remote_port;
399 + new_rc.uin = notify_reply->uin;
400 + new_rc.ip = notify_reply->remote_ip;
401 + new_rc.port = notify_reply->remote_port;
402 + rc = add_remote_client(new_rc);
404 + if (Opt_debug != 0) {
405 + printf("%s GG_NOTIFY_REPLY #%u [%s:%u/%u]\n", timestamp(),
406 + i, inet_ntoa(int2in_addr(rc->ip)), rc->port, rc->uin);
408 + buf_skip(msg, sizeof(*notify_reply));
409 + notify_reply = (struct gg_notify_reply *)buf_ptr(msg);
413 + if (header->type == GG_NOTIFY && dir == TO_SERVER) {
414 + if (Opt_debug != 0) {
415 + printf("%s GG_NOTIFY (%u)\n", timestamp(), header->length);
420 + return(len - buf_len(&buf));
423 +char* get_value(struct buf *b, char *param, int len) {
430 + l = strstr(p, param);
431 + while (l && l != p && l[-1] != '\n' && l[-1] != '\r'
432 + && l[-1] != '&' && l[-1] != '?') {
433 + l = strstr(l+1, param);
437 + i = strcspn(l, "&");
438 + if ((v = malloc(i + 1)) == NULL)
447 +int process_gg_pass(struct client_info *info, u_char *data, int len, int dir) {
448 + struct buf *line, *word, buf;
449 + char *pass, *fmnum, *pwd, *email, *fmnumber, *fmpwd, *delete;
452 + buf_init(&buf, data, len);
454 + if (dir == TO_SERVER) {
455 + fmnum = get_value(&buf, "FmNum=", 6);
456 + fmnumber = get_value(&buf, "fmnumber=", 9);
457 + pwd = get_value(&buf, "pwd=", 4);
460 + pass = get_value(&buf, "Pass=", 5);
461 + printf("GG_UIN = %s, GG_PASS = %s\n", fmnum, pass);
462 + if (pass) free(pass);
465 + if (pwd && !fmnumber) {
466 + email = get_value(&buf, "email=", 6);
467 + printf("GG_NEW_UIN: GG_PASS = %s, GG_EMAIL = %s\n", pwd, email);
468 + if (email) free(email);
472 + fmpwd = get_value(&buf, "fmpwd=", 6);
473 + delete = get_value(&buf, "delete=", 7);
474 + pwd = get_value(&buf, "pwd=", 4);
476 + printf("GG_DELETE: GG_UIN = %s, GG_PASS = %s\n", fmnumber, fmpwd);
477 + } else if (fmpwd) {
478 + printf("GG_CHANGE: GG_UIN = %s, GG_OLDPASS = %s, GG_NEWPASS = %s\n", fmnumber, fmpwd, pwd);
480 + if (fmpwd) free(fmpwd);
481 + if (delete) free(delete);
482 + if (pwd) free(pwd);
487 + buf_skip(&buf, buf_len(&buf));
488 + return(len - buf_len(&buf));
492 sniff_msgs(struct tcp_stream *ts, void **conn_save)
494 struct client_info *c;
495 - int (*process_msgs)(struct client_info *, u_char *, int);
496 + int (*process_msgs)(struct client_info *, u_char *, int, int);
499 if (ts->addr.dest >= 6660 && ts->addr.dest <= 6680) {
501 else if (ts->addr.dest == 1863) {
502 process_msgs = process_msn;
504 + else if (ts->addr.dest == 8074 || (ts->addr.dest == 443 &&
505 + (ts->addr.daddr & gg_netmask) == gg_network)) {
506 + process_msgs = process_gg;
508 + else if (Opt_pass != 0 && ts->addr.dest == 80 &&
509 + (ts->addr.daddr & gg_netmask) == gg_network) {
510 + process_msgs = process_gg_pass;
515 switch (ts->nids_state) {
518 @@ -573,15 +918,18 @@
521 SLIST_FOREACH(c, &client_list, next) {
522 - if (c->ip == ts->addr.saddr) {
523 + if (c->ip == ts->addr.saddr && c->port == ts->addr.source) {
528 if ((c = malloc(sizeof(*c))) == NULL)
529 nids_params.no_mem("sniff_msgs");
530 + memset(c, 0, sizeof(*c));
531 c->ip = ts->addr.saddr;
532 + c->port = ts->addr.source;
533 c->nick = strdup("unknown");
535 SLIST_INSERT_HEAD(&client_list, c, next);
537 *conn_save = (void *)c;
538 @@ -592,12 +940,14 @@
540 if (ts->server.count_new > 0) {
541 i = process_msgs(c, ts->server.data,
542 - ts->server.count - ts->server.offset);
543 + ts->server.count - ts->server.offset,
547 else if (ts->client.count_new > 0) {
548 i = process_msgs(c, ts->client.data,
549 - ts->client.count - ts->client.offset);
550 + ts->client.count - ts->client.offset,
555 @@ -608,10 +958,12 @@
557 if (ts->server.count > 0)
558 process_msgs(c, ts->server.data,
559 - ts->server.count - ts->server.offset);
560 + ts->server.count - ts->server.offset,
562 else if (ts->client.count > 0)
563 process_msgs(c, ts->client.data,
564 - ts->client.count - ts->client.offset);
565 + ts->client.count - ts->client.offset,
574 - while ((c = getopt(argc, argv, "i:hv?V")) != -1) {
575 + while ((c = getopt(argc, argv, "sdpwi:hv?V")) != -1) {
578 nids_params.device = optarg;
593 + // disable promiscous mode
594 + nids_params.promisc = 0;
599 @@ -653,19 +1018,35 @@
600 nids_params.scan_num_hosts = 0;
601 nids_params.syslog = null_syslog;
603 + gg_network = inet_addr(GG_NETWORK);;
604 + gg_netmask = inet_addr(GG_NETMASK);
607 errx(1, "%s", nids_errbuf);
609 SLIST_INIT(&client_list);
610 + SLIST_INIT(&remote_client_list);
612 nids_register_tcp(sniff_msgs);
614 + warnx("ggsniff " GGVERSION " enabled");
616 if (nids_params.pcap_filter != NULL) {
617 warnx("listening on %s [%s]", nids_params.device,
618 nids_params.pcap_filter);
620 else warnx("listening on %s", nids_params.device);
622 + if (nids_params.promisc == 0) {
623 + warnx("promiscous mode disabled");
625 + warnx("promiscous mode enabled");
627 + if (Opt_pass == 0) {
628 + warnx("password sniffing disabled");
630 + warnx("password sniffing enabled");