1 /*
2 ettercap -- TCP decoder module
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_decode.h>
24 #include <ec_fingerprint.h>
25 #include <ec_checksum.h>
26 #include <ec_session.h>
27 #include <ec_session_tcp.h>
28 #include <ec_inject.h>
29
30
31 /* globals */
32
33 struct tcp_header {
34 u_int16 sport; /* source port */
35 u_int16 dport; /* destination port */
36 u_int32 seq; /* sequence number */
37 u_int32 ack; /* acknowledgement number */
38 #ifndef WORDS_BIGENDIAN
39 u_int8 x2:4; /* (unused) */
40 u_int8 off:4; /* data offset */
41 #else
42 u_int8 off:4; /* data offset */
43 u_int8 x2:4; /* (unused) */
44 #endif
45 u_int8 flags;
46 #define TH_FIN 0x01
47 #define TH_SYN 0x02
48 #define TH_RST 0x04
49 #define TH_PSH 0x08
50 #define TH_ACK 0x10
51 #define TH_URG 0x20
52 #define TH_ECE 0x40 /* rfc 2481/3168 */
53 #define TH_CWR 0x80 /* rfc 2481/3168 */
54 u_int16 win; /* window */
55 u_int16 csum; /* checksum */
56 u_int16 urp; /* urgent pointer */
57 };
58
59 /* tcp options */
60 #define TCPOPT_EOL 0
61 #define TCPOPT_NOP 1
62 #define TCPOPT_MAXSEG 2
63 #define TCPOPT_WSCALE 3
64 #define TCPOPT_SACKOK 4
65 #define TCPOPT_TIMESTAMP 8
66
67
68 /* Session identifier
69 * It has to be even-lengthed for session hash matching */
70 struct tcp_ident {
71 u_int32 magic;
72 #define TCP_MAGIC 0x0400e77e
73 struct ip_addr L3_src;
74 struct ip_addr L3_dst;
75 u_int16 L4_src;
76 u_int16 L4_dst;
77 };
78
79 #define TCP_IDENT_LEN sizeof(struct tcp_ident)
80
81
82 /* protos */
83
84 FUNC_DECODER(decode_tcp);
85 FUNC_INJECTOR(inject_tcp);
86 void tcp_init(void);
87 int tcp_match(void *id_sess, void *id_curr);
88 void tcp_create_session(struct ec_session **s, struct packet_object *po);
89
90 /*******************************************/
91
92 /*
93 * this function is the initializer.
94 * it adds the entry in the table of registered decoder
95 */
96
tcp_init(void)97 void __init tcp_init(void)
98 {
99 add_decoder(PROTO_LAYER, NL_TYPE_TCP, decode_tcp);
100 add_injector(CHAIN_ENTRY, NL_TYPE_TCP, inject_tcp);
101 }
102
103
FUNC_DECODER(decode_tcp)104 FUNC_DECODER(decode_tcp)
105 {
106 FUNC_DECODER_PTR(next_decoder);
107 struct tcp_header *tcp;
108 u_char *opt_start, *opt_end;
109 struct ec_session *s = NULL;
110 void *ident = NULL;
111 struct tcp_status *status = NULL;
112 int direction = 0;
113 u_int16 sum;
114
115 tcp = (struct tcp_header *)DECODE_DATA;
116
117 opt_start = (u_char *)(tcp + 1);
118 opt_end = (u_char*)tcp + tcp->off * 4;
119
120 DECODED_LEN = (u_int32)(tcp->off * 4);
121
122 /* source and dest port */
123 PACKET->L4.src = tcp->sport;
124 PACKET->L4.dst = tcp->dport;
125
126 PACKET->L4.len = DECODED_LEN;
127 PACKET->L4.header = (u_char *)DECODE_DATA;
128
129 if (opt_start < opt_end) {
130 PACKET->L4.options = opt_start;
131 PACKET->L4.optlen = opt_end - opt_start;
132 } else {
133 PACKET->L4.options = NULL;
134 PACKET->L4.optlen = 0;
135 }
136
137 /* this is TCP */
138 PACKET->L4.proto = NL_TYPE_TCP;
139
140 /* save the flags */
141 PACKET->L4.flags = tcp->flags;
142
143 /* save the seq number */
144 PACKET->L4.seq = tcp->seq;
145 PACKET->L4.ack = tcp->ack;
146
147 /* set up the data pointers */
148 PACKET->DATA.data = opt_end;
149 if (PACKET->L3.payload_len < (u_int32)DECODED_LEN)
150 return NULL;
151 PACKET->DATA.len = PACKET->L3.payload_len - DECODED_LEN;
152
153 /* create the buffer to be displayed */
154 packet_disp_data(PACKET, PACKET->DATA.data, PACKET->DATA.len);
155
156 /*
157 * if the checsum is wrong, don't parse it (avoid ettercap spotting)
158 * the checksum is should be CSUM_RESULT and not equal to tcp->csum ;)
159 *
160 * don't perform the check in unoffensive mode
161 */
162 if (EC_GBL_CONF->checksum_check) {
163 if (!EC_GBL_OPTIONS->unoffensive && (sum = L4_checksum(PACKET)) != CSUM_RESULT) {
164 char tmp[MAX_ASCII_ADDR_LEN];
165 #if defined(OS_DARWIN) || defined (OS_WINDOWS) || defined(OS_LINUX)
166 /*
167 * XXX - hugly hack here ! Mac OS X really sux
168 *
169 * Packets transmitted on interfaces with TCP checksum offloading
170 * don't have valid checksums as presented to the machine's packet-capture
171 * mechanism, as those packets are wrapped around internally rather
172 * than being captured after passing through the network interface, as
173 * the OS doesn't bother computing the checksum and adding it to the packet
174 * it leaves that up to the network interface.
175 * (taken from a bug report by Guy Harris - libpcap engineer)
176 *
177 * For Windows at least, TCP checksum off-loading can be disabled with a
178 * registry setting.
179 *
180 * Same for Linux, but sometimes even ethtool doesn't turn this feature off.
181 *
182 * if the source is the ettercap host, don't display the message
183 */
184 if (ip_addr_is_ours(&PACKET->L3.src) == E_FOUND)
185 return NULL;
186 #endif
187 if (EC_GBL_CONF->checksum_warning)
188 USER_MSG("Invalid TCP packet from %s:%d : csum [%#x] should be (%#x)\n", ip_addr_ntoa(&PACKET->L3.src, tmp),
189 ntohs(tcp->sport), ntohs(tcp->csum), checksum_shouldbe(tcp->csum, sum));
190 return NULL;
191 }
192 }
193
194 /*
195 * complete the passive fingerprint (started at IP layer)
196 * we are interested only in SYN or SYN+ACK packets
197 * else we can destroy the fingerprint
198 */
199 if ( tcp->flags & TH_SYN ) {
200
201 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_WINDOW, ntohs(tcp->win));
202 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_TCPFLAG, (tcp->flags & TH_ACK) ? 1 : 0);
203 /* this is added to the len of ip header (automatic) */
204 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_LT, tcp->off * 4);
205
206 while (opt_start < opt_end) {
207 switch (*opt_start) {
208 case TCPOPT_EOL:
209 /* end option EXIT */
210 opt_start = opt_end;
211 break;
212 case TCPOPT_NOP:
213 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_NOP, 1);
214 opt_start++;
215 break;
216 case TCPOPT_SACKOK:
217 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_SACK, 1);
218 opt_start += 2;
219 break;
220 case TCPOPT_MAXSEG:
221 opt_start += 2;
222 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_MSS, pntos(opt_start));
223 opt_start += 2;
224 break;
225 case TCPOPT_WSCALE:
226 opt_start += 2;
227 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_WS, *opt_start);
228 opt_start++;
229 break;
230 case TCPOPT_TIMESTAMP:
231 fingerprint_push(PACKET->PASSIVE.fingerprint, FINGER_TIMESTAMP, 1);
232 opt_start++;
233 if ((*opt_start) > 0)
234 opt_start += ((*opt_start) - 1);
235 break;
236 default:
237 opt_start++;
238 if (*opt_start > 0)
239 opt_start += (*opt_start - 1);
240 break;
241 }
242 }
243
244 } else {
245 /* not an interesting packet */
246 memset(PACKET->PASSIVE.fingerprint, 0, FINGER_LEN);
247 }
248
249 /* HOOK POINT: HOOK_PACKET_TCP */
250 hook_point(HOOK_PACKET_TCP, po);
251
252 /* don't save the sessions in unoffensive mode */
253 /* don't save sessions if no filters chain are defined */
254 if (EC_GBL_FILTERS && !EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read) {
255
256 /* Find or create the correct session */
257 tcp_create_ident(&ident, PACKET);
258 if (session_get(&s, ident, TCP_IDENT_LEN) == -E_NOTFOUND) {
259 tcp_create_session(&s, PACKET);
260 session_put(s);
261 }
262
263 /* Trace the sessions for injectors */
264 SESSION_PASSTHRU(s, PACKET);
265
266 /* Select right comunication way */
267 direction = tcp_find_direction(s->ident, ident);
268 SAFE_FREE(ident);
269
270 /* Record last packet's seq */
271 status = (struct tcp_status *)s->data;
272 status->way[direction].last_seq = ntohl(tcp->seq) + PACKET->DATA.len;
273 if ( tcp->flags & TH_ACK )
274 status->way[direction].last_ack = ntohl(tcp->ack);
275
276 /* SYN counts as one byte */
277 if ( tcp->flags & TH_SYN )
278 status->way[direction].last_seq++;
279
280 /* Take trace of the RST flag (to block injection) */
281 if ( tcp->flags & TH_RST ) {
282 status->way[direction].injectable |= INJ_FIN;
283 status->way[!direction].injectable |= INJ_FIN;
284 }
285
286 /* Take trace if this side of connection is mitm'd */
287 if (PACKET->flags & PO_FORWARDABLE)
288 status->way[direction].injectable |= INJ_FWD;
289 else if (status->way[direction].injectable & INJ_FWD)
290 status->way[direction].injectable ^= INJ_FWD;
291 }
292
293 /* get the next decoder */
294 next_decoder = get_decoder(APP_LAYER, PL_DEFAULT);
295 EXECUTE_DECODER(next_decoder);
296
297 /* don't save the sessions in unoffensive mode */
298 if (EC_GBL_FILTERS && !EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read) {
299
300 /*
301 * Take trace of the FIN flag (to block injection)
302 * It's here to permit some strange tricks with filters.
303 */
304 if ( tcp->flags & TH_FIN )
305 status->way[direction].injectable |= INJ_FIN;
306
307 /*
308 * Modification checks and adjustments.
309 * - tcp->seq and tcp->ack accoridng to injected/dropped bytes
310 * - seq_adj according to PACKET->delta for modifications
311 * or the whole payload for dropped packets.
312 * Don't adjust sequence if not forwardable.
313 */
314
315 /* XXX [...] over TCP encapsulation not supported yet:
316 * upper layer may modify L3 structure
317 */
318
319 if ((PACKET->flags & PO_DROPPED) && (PACKET->flags & PO_FORWARDABLE))
320 status->way[direction].seq_adj += PACKET->DATA.delta;
321 else if (((PACKET->flags & PO_MODIFIED) ||
322 (status->way[direction].seq_adj != 0) ||
323 (status->way[!direction].seq_adj != 0)) &&
324 (PACKET->flags & PO_FORWARDABLE)) {
325
326 /* adjust with the previously injected/dropped seq/ack */
327 ORDER_ADD_LONG(tcp->seq, status->way[direction].seq_adj);
328 ORDER_ADD_LONG(tcp->ack, -status->way[!direction].seq_adj);
329
330 /* and now save the new delta */
331 status->way[direction].seq_adj += PACKET->DATA.delta;
332
333 /* Recalculate checksum */
334 tcp->csum = CSUM_INIT;
335 tcp->csum = L4_checksum(PACKET);
336 }
337 }
338 return NULL;
339 }
340
341 /*******************************************/
342
FUNC_INJECTOR(inject_tcp)343 FUNC_INJECTOR(inject_tcp)
344 {
345 struct ec_session *s = NULL;
346 void *ident = NULL;
347 struct tcp_status *status;
348 int direction;
349 struct tcp_header *tcph;
350 u_char *tcp_payload;
351 u_int32 magic;
352
353 /* Find the correct session */
354 tcp_create_ident(&ident, PACKET);
355 if (session_get(&s, ident, TCP_IDENT_LEN) == -E_NOTFOUND) {
356 SAFE_FREE(ident);
357 return -E_NOTFOUND;
358 }
359
360 /* Rember where the payload has to start */
361 tcp_payload = PACKET->packet;
362
363 /* Allocate stack for tcp header */
364 PACKET->packet -= sizeof(struct tcp_header);
365
366 /* Create the tcp header */
367 tcph = (struct tcp_header *)PACKET->packet;
368
369 tcph->sport = PACKET->L4.src;
370 tcph->dport = PACKET->L4.dst;
371 tcph->x2 = 0;
372 tcph->off = 5;
373 tcph->win = htons(32120);
374 tcph->csum = CSUM_INIT;
375 tcph->urp = 0;
376 tcph->flags = TH_PSH;
377
378 /* Take the rest of the data from the sessions */
379 status = (struct tcp_status *)s->data;
380 direction = tcp_find_direction(s->ident, ident);
381 SAFE_FREE(ident);
382
383 /* Is this an injectable connection? */
384 if ((status->way[direction].injectable & INJ_FIN) || !(status->way[direction].injectable & INJ_FWD) || !(status->way[!direction].injectable & INJ_FWD))
385 return -E_NOTHANDLED;
386
387 tcph->seq = htonl(status->way[direction].last_seq + status->way[direction].seq_adj);
388 tcph->ack = htonl(status->way[direction].last_ack - status->way[!direction].seq_adj);
389
390 if (status->way[direction].last_ack!=0)
391 tcph->flags |= TH_ACK;
392
393 /* Prepare data for next injector */
394 PACKET->session = s->prev_session;
395 LENGTH += sizeof(struct tcp_header);
396 memcpy(&magic, s->prev_session->ident, 4);
397
398 /* Go deeper into injectors chain */
399 EXECUTE_INJECTOR(CHAIN_LINKED, magic);
400
401 /*
402 * Attach the data (LENGTH was adjusted by LINKED injectors).
403 * Set LENGTH to injectable data len.
404 */
405 LENGTH = EC_GBL_IFACE->mtu - LENGTH;
406 if (LENGTH > PACKET->DATA.inject_len)
407 LENGTH = PACKET->DATA.inject_len;
408 memcpy(tcp_payload, PACKET->DATA.inject, LENGTH);
409
410 /* Update inject counter into the session */
411 status->way[direction].seq_adj += LENGTH;
412
413 /* Calculate checksum */
414 PACKET->L4.header = (u_char *)tcph;
415 PACKET->L4.len = sizeof(struct tcp_header);
416 PACKET->DATA.len = LENGTH;
417 tcph->csum = L4_checksum(PACKET);
418
419 return E_SUCCESS;
420 }
421
422 /*******************************************/
423
424 /* Sessions' stuff for tcp packets */
425
426
427 /*
428 * create the ident for a session
429 */
430
tcp_create_ident(void ** i,struct packet_object * po)431 size_t tcp_create_ident(void **i, struct packet_object *po)
432 {
433 struct tcp_ident *ident;
434
435 /* allocate the ident for that session */
436 SAFE_CALLOC(ident, 1, sizeof(struct tcp_ident));
437
438 /* the magic */
439 ident->magic = TCP_MAGIC;
440
441 /* prepare the ident */
442 memcpy(&ident->L3_src, &po->L3.src, sizeof(struct ip_addr));
443 memcpy(&ident->L3_dst, &po->L3.dst, sizeof(struct ip_addr));
444
445 ident->L4_src = po->L4.src;
446 ident->L4_dst = po->L4.dst;
447
448 /* return the ident */
449 *i = ident;
450
451 /* return the length of the ident */
452 return sizeof(struct tcp_ident);
453 }
454
455
456 /*
457 * compare two session ident
458 *
459 * return 1 if it matches
460 */
461
tcp_match(void * id_sess,void * id_curr)462 int tcp_match(void *id_sess, void *id_curr)
463 {
464 struct tcp_ident *ids = id_sess;
465 struct tcp_ident *id = id_curr;
466
467 /* sanity check */
468 BUG_IF(ids == NULL);
469 BUG_IF(id == NULL);
470
471 /*
472 * is this ident from our level ?
473 * check the magic !
474 */
475 if (ids->magic != id->magic)
476 return 0;
477
478 /* from source to dest */
479 if (ids->L4_src == id->L4_src &&
480 ids->L4_dst == id->L4_dst &&
481 !ip_addr_cmp(&ids->L3_src, &id->L3_src) &&
482 !ip_addr_cmp(&ids->L3_dst, &id->L3_dst) )
483 return 1;
484
485 /* from dest to source */
486 if (ids->L4_src == id->L4_dst &&
487 ids->L4_dst == id->L4_src &&
488 !ip_addr_cmp(&ids->L3_src, &id->L3_dst) &&
489 !ip_addr_cmp(&ids->L3_dst, &id->L3_src) )
490 return 1;
491
492 return 0;
493 }
494
495
496 /*
497 * prepare the ident and the pointer to match function
498 * for a dissector.
499 */
500
tcp_create_session(struct ec_session ** s,struct packet_object * po)501 void tcp_create_session(struct ec_session **s, struct packet_object *po)
502 {
503 void *ident;
504
505 DEBUG_MSG("tcp_create_session");
506
507 /* allocate the session */
508 SAFE_CALLOC(*s, 1, sizeof(struct ec_session));
509
510 /* create the ident */
511 (*s)->ident_len = tcp_create_ident(&ident, po);
512
513 /* link to the session */
514 (*s)->ident = ident;
515
516 /* the matching function */
517 (*s)->match = &tcp_match;
518
519 /* alloca of data elements */
520 SAFE_CALLOC((*s)->data, 1, sizeof(struct tcp_status));
521 }
522
523 /*
524 * Find right comunication way for session data.
525 * First array data is relative to the direction first caught.
526 */
tcp_find_direction(void * ids,void * id)527 int tcp_find_direction(void *ids, void *id)
528 {
529 if (memcmp(ids, id, TCP_IDENT_LEN))
530 return 1;
531
532 return 0;
533 }
534
535 /* EOF */
536
537 // vim:ts=3:expandtab
538
539