⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 FERRET - a broadcast analysis tool This tool is designed to demonstrate the problem of "data seap
💻 C
字号:
/* Copyright (c) 2007 by Errata Security */
#include "protos.h"
#include "ferret.h"
#include "netframe.h"
#include "formats.h"

#include <ctype.h>
#include <string.h>

enum {
	TCP_FIN=1,
	TCP_SYN=2,
	TCP_RST=4,
	TCP_PSH=8,
	TCP_ACK=16,
	TCP_URG=32,
};

static void tcp_syn(struct Seaper *seap, struct NetFrame *frame)
{
	seap;frame;
}
static void tcp_synack(struct Seaper *seap, struct NetFrame *frame)
{
	seap;frame;
}
static void tcp_ack(struct Seaper *seap, struct NetFrame *frame)
{
	seap;frame;
}
static void tcp_fin(struct Seaper *seap, struct NetFrame *frame)
{
	seap;frame;
}


int smellslike_httprequest(const unsigned char *data, unsigned length)
{
	unsigned i;
	unsigned method;
	unsigned url;

	for (i=0; i<length && isspace(data[i]); i++)
		;
	method = i;
	while (i<length && !isspace(data[i]))
		i++;
	if (i>10)
		return 0;
	while (i<length && isspace(data[i]))
		i++;
	url = i;
	while (i<length && data[i] != '\n')
		i++;

	if (i>0 && data[i] == '\n') {
		i--;

		if (i>0 && data[i] == '\r')
			i--;

		if (i>10 && memicmp(&data[i-7], "HTTP/1.0", 8) == 0)
			return 1;
		if (i>10 && memicmp(&data[i-7], "HTTP/1.1", 8) == 0)
			return 1;
		if (i>10 && memicmp(&data[i-7], "HTTP/0.9", 8) == 0)
			return 1;
		
	}

	return 0;
}

int smellslike_msn_messenger(const unsigned char *data, unsigned length)
{
	unsigned i=0;
	unsigned method;
	unsigned method_length=0;
	unsigned parms;
	unsigned non_printable_count = 0;
	unsigned line_length;

	if (smellslike_httprequest(data, length))
		return 0;


	method = i;
	while (i<length && !isspace(data[i]))
		i++, method_length++;;
	while (i<length && data[i] != '\n' && isspace(data[i]))
		i++;
	parms = i;
	while (i<length && data[i] != '\n')
		i++;
	line_length = i;

	for (i=0; i<length; i++)
		if (!(isprint(data[i]) || isspace(data[i])))
			non_printable_count++;


	if (method_length == 3 && data[line_length] == '\n' && non_printable_count == 0)
		return 1;

	return 0;
}

static unsigned tcp_record_hash(struct TCPRECORD *rec)
{
	unsigned i;
	unsigned hash=0;

	for (i=0; i<16; i++) {
		hash += rec->ip_dst[i];
		hash += rec->ip_src[i] << 8;
	}
	hash += rec->tcp_dst;
	hash += rec->tcp_src << 8;

	return hash;
}
static unsigned tcp_record_equals(struct TCPRECORD *left, struct TCPRECORD *right)
{
	unsigned i;

	for (i=0; i<16; i++) {
		if (left->ip_src[i] != right->ip_src[i])
			return 0;
		if (left->ip_dst[i] != right->ip_dst[i])
			return 0;
	}
	if (left->ip_ver != right->ip_ver)
		return 0;
	if (left->tcp_dst != right->tcp_dst)
		return 0;
	if (left->tcp_src != right->tcp_src)
		return 0;

	return 1;
}
static void tcp_lookup_session(struct Seaper *seap, struct NetFrame *frame)
{
	struct TCPRECORD rec = {0};
	struct TCPRECORD *session;

	seap->session = 0;

	if (frame->ipver != 0) {
		return;
	}

	rec.ip_ver = frame->ipver;
	memcpy(rec.ip_dst, &frame->dst_ipv4, 4);
	memcpy(rec.ip_src, &frame->src_ipv4, 4);
	rec.tcp_dst = (unsigned short)frame->dst_port;
	rec.tcp_src = (unsigned short)frame->src_port;

	session = &seap->sessions[tcp_record_hash(&rec) % (sizeof(seap->sessions)/sizeof(seap->sessions[0]))];

	if (!tcp_record_equals(session, &rec)) {
		memcpy(session, &rec, sizeof(rec));
	}

	seap->session = session;
}

static void tcp_data(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	tcp_lookup_session(seap, frame);

	if (smellslike_httprequest(px, length))
		process_simple_http(seap, frame, px, length);

	if (frame->src_port == 1863 || frame->dst_port == 1863) {
		if (smellslike_msn_messenger(px, length)) {
			if (frame->src_port == 1863)
				process_simple_msnms_server_response(seap, frame, px, length);
			else
				process_simple_msnms_client_request(seap, frame, px, length);
		}
	}

	if (frame->src_port == 110)
		process_simple_pop3_response(seap, frame, px, length);
	else if (frame->dst_port == 110)
		process_simple_pop3_request(seap, frame, px, length);

	if (frame->src_port == 25)
		process_simple_smtp_response(seap, frame, px, length);
	else if (frame->dst_port == 25)
		process_simple_smtp_request(seap, frame, px, length);

	seap->session = 0;
}

void process_tcp(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct {
		unsigned src_port;
		unsigned dst_port;
		unsigned seqno;
		unsigned ackno;
		unsigned header_length;
		unsigned flags;
		unsigned window;
		unsigned checksum;
		unsigned urgent;
	} tcp;

	if (length == 0) {
		FRAMERR(frame, "tcp: frame empty\n");
		return;
	}
	if (length < 20) {
		FRAMERR(frame, "tcp: frame too short\n");
		return;
	}

/*
	    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

	tcp.src_port = ex16be(px+0);
	tcp.dst_port = ex16be(px+2);
	tcp.seqno = ex32be(px+4);
	tcp.ackno = ex32be(px+8);
	tcp.header_length = px[12]>>2;
	tcp.flags = px[13];
	tcp.window = ex16be(px+14);
	tcp.checksum = ex16be(px+16);
	tcp.urgent = ex16be(px+18);

	frame->src_port = tcp.src_port;
	frame->dst_port = tcp.dst_port;

	if (tcp.header_length < 20) {
		FRAMERR(frame, "tcp: header too short, expected length=20, found length=%d\n", tcp.header_length);
		return;
	}
	if (tcp.header_length > length) {
		FRAMERR(frame, "tcp: header too short, expected length=%d, found length=%d\n", tcp.header_length, length);
		return;
	}
	if ((tcp.flags & 0x20) && tcp.urgent > 0) {
		FRAMERR(frame, "tcp: found %d bytes of urgent data\n", tcp.urgent);
		return;
	}

	if (tcp.header_length > 20) {
		unsigned o = 20;
		unsigned max = tcp.header_length;

		while (o < tcp.header_length) {
			unsigned tag = px[o++];
			unsigned len;

			if (tag == 0)
				break;
			if (tag == 1)
				continue;

			if (o >= max) {
				FRAMERR(frame, "tcp: options too long\n");
				break;
			}
			len = px[o++];

			if (len < 2) {
				FRAMERR(frame, "tcp: invalid length field\n");
				break;
			}
			if (o+len-2 > max) {
				FRAMERR(frame, "tcp: options too long\n");
				break;
			}

			switch (tag) {
			case 0x02: /* max seg size */
				if (len != 4)
					FRAMERR(frame, "tcp: unknown length: option=%d, length=%d\n", tag, len);
				break;
			case 0x04: /* SACK permitted */
				if (len != 2)
					FRAMERR(frame, "tcp: unknown length: option=%d, length=%d\n", tag, len);
				break;
			case 0x05: /* SACK */
				break;
			case 0x08: /*timestamp*/
				break;
			case 0x03: /*window scale*/
				break;
			default:
				FRAMERR(frame, "tcp: unknown option=%d, length=%d\n", tag, len);
			}

			o += len-2;
		}
	}


	switch (tcp.flags & 0x3F) {
	case TCP_SYN:
		tcp_syn(seap, frame);
		break;
	case TCP_SYN|TCP_ACK:
		tcp_synack(seap, frame);
		break;
	case TCP_FIN:
	case TCP_FIN|TCP_ACK:
	case TCP_FIN|TCP_ACK|TCP_PSH:
		tcp_fin(seap, frame);
		break;
	case TCP_ACK:
	case TCP_ACK|TCP_PSH:
		if (tcp.header_length >= length) {
			tcp_ack(seap, frame);
		} else
			tcp_data(seap, frame, px+tcp.header_length, length-tcp.header_length);
		break;
	case TCP_RST:
	case TCP_RST|TCP_ACK:
		break;
	case 0x40|TCP_ACK:
		break;
	case TCP_RST|TCP_ACK|TCP_FIN:
		break;
	default:
		FRAMERR(frame, "tcp: unexpected combo of flags: 0x%03x\n", tcp.flags);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -