Example #1
0
void process_upnp_response(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	unsigned offset=0;

	while (offset < length) {
		const unsigned char *line = px+offset;
		unsigned line_length;

		for (line_length=0; offset+line_length < length && px[offset+line_length] != '\n'; line_length++)
			;
		offset += line_length;
		if (offset<length && px[offset] == '\n')
			offset++;
		while (line_length && isspace(line[line_length-1]))
			line_length--;

		if (line_length>3 && strnicmp((const char*)line, "ST:", 3) == 0) {
			JOTDOWN(ferret,
				JOT_SZ("proto","upnp"),
				JOT_SRC("ip.src", frame),
				JOT_PRINT("ST",		 	line+3, line_length-3),
				0);
		}
	}
}
Example #2
0
/*TODO: currently, nobody references this function*/
void dns_dynamic_update(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length, struct DNS *dns)
{
	unsigned i;


	for (i=0; i<dns->answer_count; i++) {
		char name[256];
		unsigned name_length;
		unsigned x;
		struct DNSRECORD *rec = &dns->answers[i];

		name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name));

		x = rec->clss<<16 | rec->type;
		
		SAMPLE(ferret,"DynDNS", JOT_NUM("Prereq", x));

		switch (rec->type) {
		case 0x0001: /*A*/
			switch (rec->clss) {
			case 0x0001: /*INTERNET*/
				{
					unsigned ip_address = ex32be(px+rec->rdata_offset);

					if (rec->rdata_length != 4)
						FRAMERR(frame, "dns: data not 4-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name);


					JOTDOWN(ferret,
						JOT_IPv4("ID-IP", ip_address),
						JOT_PRINT("name",		 	name,				name_length),
						0);

					JOTDOWN(ferret,
						JOT_SZ("proto","NETBIOS"),
						JOT_SZ("op","register"),
						JOT_SRC("ip.src", frame),
						JOT_PRINT("name",		 	name,				name_length),
						JOT_IPv4("address", ip_address),
						0);
				}
				break;
			default:
				FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
			}
			break;

		}
	}
}
Example #3
0
void process_cups(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	unsigned offset = 0;
	unsigned type=0;
	unsigned state = 0;
	const unsigned char *uri;
	unsigned uri_length;
	const unsigned char *location;
	unsigned location_length;
	const unsigned char *information;
	unsigned information_length;
	const unsigned char *model;
	unsigned model_length;

	extract_num(px, length, &offset, &type);
	extract_num(px, length, &offset, &state);

	extract_string(px, length, &offset, &uri, &uri_length);
	extract_string(px, length, &offset, &location, &location_length);
	extract_string(px, length, &offset, &information, &information_length);
	extract_string(px, length, &offset, &model, &model_length);

	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_NUM("type",type),
			0);
	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_NUM("state",state),
			0);
	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_PRINT("uri",		 	uri, uri_length),
			0);
	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_PRINT("location",		 	location, location_length),
			0);
	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_PRINT("info",		 	information, information_length),
			0);
	JOTDOWN(ferret,
			JOT_SZ("proto", "CUPS"),
			JOT_SRC("ip.src", frame),
			JOT_PRINT("model",	 	model, model_length),
			0);
}
Example #4
0
void process_simple_smtp_data(struct TCPRECORD *sess, struct TCP_STREAM *to_server, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct FerretEngine *eng = sess->eng;
	struct Ferret *ferret = eng->ferret;
	unsigned offset=0;
	unsigned command;
	unsigned command_length;
	unsigned parm;
	unsigned parm_length;

	if (sess == NULL)
		return;

	frame->layer7_protocol = LAYER7_SMTP;

	while (offset<length) {

		/* Handle end-of-email '.' issue */
		if (offset<length && px[offset] == '.') {
			if (offset+1<length && px[offset] == '\n' && offset+2<length && px[offset] == '\r' && px[offset+1] == '\n') {
				to_server->app.smtpreq.is_body = 0;
				to_server->app.smtpreq.is_data = 0;
				return;
			}
		}
		if (to_server->app.smtpreq.is_body) {
			while (offset<length && px[offset] != '\n')
				offset++;
			if (offset<length && px[offset] == '\n')
				offset++;
			continue;
		}


		while (offset<length && isspace(px[offset]) && px[offset] != '\n')
			offset++;
		command = offset;
		
		while (offset<length && px[offset] != ':' && px[offset] != '\n')
			offset++;
		command_length = offset-command;
		if (command_length == 0) {
			to_server->app.smtpreq.is_body = 1;
			continue;
		}

		while (command_length && isspace(px[offset+command_length]))
			command_length--;
		if (command_length && px[offset+command_length] == ':')
			command_length--;
		while (command_length && isspace(px[offset+command_length]))
			command_length--;
	
		while (offset<length && px[offset] == ':')
			offset++;
		while (offset<length && isspace(px[offset]) && px[offset] != '\n')
			offset++;

		parm = offset;
		if ((offset<length && px[offset] == '\n') || (offset+1<length && px[offset] == '\r' && px[offset+1] == '\n')) {
			to_server->app.smtpreq.is_body = 1;
			return;
		}
again:
		while (offset<length && px[offset] != '\n')
			offset++;
		if (offset<length && px[offset] == '\n')
			offset++;
		if (offset<length && px[offset] != '\n' && isspace(px[offset]) && (offset+1<length && px[offset] != '\r' && px[offset] != '\n'))
			goto again;
		parm_length = offset-parm;
		while (parm_length && isspace(px[parm+parm_length-1]))
			parm_length--;

		JOTDOWN(ferret,
				JOT_SZ("proto","RFC822msg"),
				JOT_PRINT("header",			 	px+command,					command_length),
				JOT_PRINT("value",			 	px+parm, parm_length),
				JOT_SRC("client", frame),
				JOT_DST("server", frame),
				0);
		if (is_command("subject", px+command, command_length)) {
			smtp_copy(to_server->app.smtpreq.subject, px+parm, parm_length);
		}
		if (is_command("X-Mailer", px+command, command_length)) {
			JOTDOWN(ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("X-Mailer",			   px+parm, parm_length),
				0);
		}
		if (is_command("X-MimeOLE", px+command, command_length)) {
			JOTDOWN(ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("X-MimeOLE",			   px+parm, parm_length),
				0);
		}
	}
}
Example #5
0
void process_simple_smtp_request(struct TCPRECORD *sess, struct TCP_STREAM *to_server, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct FerretEngine *eng = sess->eng;
	struct Ferret *ferret = eng->ferret;
	char command[16];
	const char *parm;
	unsigned parm_length;
	unsigned i;
	unsigned  x;

	/* IF CLOSING CONNECTION */
	if (px == NULL) {
		return;
	}

	frame->layer7_protocol = LAYER7_SMTP;

	if (to_server->app.smtpreq.is_data) {
		process_simple_smtp_data(sess, to_server, frame, px, length);
		return;
	}

	/* Remove leading whitespace */
	for (i=0; i<length && isspace(px[i]); i++)
		;

	/* Grab command. This means parsing up to the first space
	 * character, or the first ':' character in the case of 
	 * mailfrom: or rcptto: */
	x=0;
again:
	while (i<length && !isspace(px[i]) && px[i] != ':') {
		if (x < sizeof(command) -1) {
			command[x++] = (char)toupper(px[i]);
			command[x] = '\0';
		}
		i++;
	}
	if (i<length && px[i] == ':')
		i++;

	/* skip space after command */
	while (i<length && isspace(px[i]))
		i++;

	if (stricmp(command, "mail")==0 || stricmp(command, "rcpt")==0) {
		if (i >= length)
			return;
		goto again;
	}

	SAMPLE(ferret,"SMTP", JOT_SZ("command", command));

	/* Grab parm */
	parm = (const char*)px+i;
	x=i;
	while (i<length && px[i] != '\n')
		i++;
	parm_length = i-x;

	if (parm_length && parm[parm_length-1] == '\n')
		parm_length--;
	if (parm_length && parm[parm_length-1] == '\r')
		parm_length--;

	JOTDOWN(ferret,
		JOT_SZ("proto", "SMTP"),
		JOT_SZ("op", command),
		JOT_PRINT("parm", parm, parm_length),
		JOT_SRC("client", frame),
		JOT_DST("server", frame),
		0);

	/* test parms */
	if (stricmp(command, "MAILFROM")==0) {
		strip_address(&parm, &parm_length);

		if (sess)
			smtp_copy(to_server->app.smtpreq.from, parm, parm_length);

		JOTDOWN(ferret,
			JOT_SRC("IP", frame),
			JOT_PRINT("e-mail", parm, parm_length),
			0);
	}
	if (stricmp(command, "RCPTTO")==0) {
		strip_address(&parm, &parm_length);

		if (sess)
			smtp_copy(to_server->app.smtpreq.to, parm, parm_length);
		JOTDOWN(ferret,
			JOT_SRC("IP", frame),
			JOT_PRINT("friend",			   parm, parm_length),
			0);
	}

	if (stricmp(command, "DATA")==0 && sess) {
		to_server->app.smtpreq.is_data = 1;
	}
	if (stricmp(command, "RSET")==0 && sess) {
		to_server->app.smtpreq.is_data = 0;
	}


}
Example #6
0
/**
 * This is the main function of the DNS parser.
 *
 * This is where the each DNS 'answer' (or 'additional' or 'authoritative') 
 * record is parsed. Mostly, we ignore the return code, though some functions
 * pay attention to and provide slightly different information depending
 * upon the opcode.
 */
static void 
dns_parse_resource_record(struct Ferret *ferret, struct NetFrame *frame, 
						  const unsigned char *px, unsigned length, 
						  struct DNSRECORD *rec, struct DNS *dns)
{
	char name[512]; /* reserve a longer name than the max theoretical limit */
	unsigned name_length;
	char name2[512]; /* reserve a longer name than the max theoretical limit */
	unsigned name2_length;
	unsigned ip_address;
	unsigned offset = rec->rdata_offset;
	unsigned offset_max = MIN(rec->rdata_offset+rec->rdata_length, length);

	/* MULTICAST DNS (mDNS): handle the multicast DNS records differently
	 * from normal DNS records. */
	if (!dns->is_response && frame->dst_port == 5353) {
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		return; 
	} else if (dns->is_response && (frame->src_port == 5353 || (frame->dst_port == 5353 && frame->src_port != 53))) {
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		return;
	}

	/* NETBIOS: handle NetBIOS records differently from normal DNS records */
	if (!dns->is_response && frame->dst_port == 137) {
		netbios_parse_resource_record(ferret, frame, px, length, rec, dns);
		return; 
	} else if (dns->is_response && frame->src_port == 137) {
		netbios_parse_resource_record(ferret, frame, px, length, rec, dns);
		return;
	}


	/* First, let's extract a pretty version of the name */
	name_length = dns_extract_name(frame, px, length, rec->name_offset, name, sizeof(name));
	
	if (rec->type == 0x8001)
		FRAMERR(frame, "TODO\n");

	if (rec->clss == 0xfe)
		return;

	/* RFC2671 - Extension Mechanisms for DNS (EDNS0) */
	if (rec->type == 41) {
		/* Regress: defcon2008/dump000.pca(12541) */
		/* TODO: parse this */
		return;
	}

	/* Haven't implemented dynamic update yet
	 * TODO: */
	if (dns->opcode == 21 || dns->opcode == 5)
		return;

	switch (rec->type<<16 | rec->clss) {
	case TYPECLASS(1,0x8001): /* type=A(IPv4 address), class=INTERNET(cache flush) */
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		break;
	case TYPECLASS(1,1): /* type=A(IPv4 address), class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}

		ip_address = ex32be(px+rec->rdata_offset);
		if (rec->rdata_length != 4)
			FRAMERR(frame, "dns: data not 4-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name);

		JOTDOWN(ferret,
			JOT_PRINT("ID-DNS", name,	name_length),
			JOT_IPv4("address",	ip_address),
			0);
		break;
	case TYPECLASS(2,1): /* type=NS, class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}
		name2_length = dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2));
		ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);

		JOTDOWN(ferret,
			JOT_PRINT("ID-DNS",	name, name_length),
			JOT_PRINT("Name-Server", name2, name2_length),
			JOT_IPv4("address", ip_address),
			0);
		break;
	case TYPECLASS(5,1): /*type=CNAME(aliased canonical name), class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}
		name2_length = dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2));

		ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);

		if (ip_address != 0) {
			JOTDOWN(ferret,
				JOT_PRINT("ID-DNS", name,	name_length),
				JOT_IPv4("alias",ip_address),
				0);
		}
		JOTDOWN(ferret,
			JOT_PRINT("ID-DNS", name,	name_length),
			JOT_PRINT("alias", name2, name2_length),
			0);
		break;
	case TYPECLASS(6,1): /*type=SOA, class=INTERNET*/
		if (!is_valid_opcode(dns->opcode, 0x10, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}
		/*
		 * Authoritative Name Server
		 */
		name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));
		JOTDOWN(ferret,
			JOT_PRINT("ID-DNS",	name, name_length),
			JOT_SZ("SOA", "Start of zone authority"),
			JOT_PRINT("Name-Server", name2, name2_length),
			0);
		ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);
		if (ip_address)
		JOTDOWN(ferret,
			JOT_PRINT("ID-DNS",	name, name_length),
			JOT_SZ("SOA", "Start of zone authority"),
			JOT_PRINT("Name-Server", name2, name2_length),
			JOT_IPv4("address", ip_address),
			0);
		skip_name(px, length, &offset);

		/* Contact */
		if (offset < offset_max) {
			name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));
			JOTDOWN(ferret,
				JOT_PRINT("ID-DNS",	name, name_length),
				JOT_SZ("SOA", "Start of zone authority"),
				JOT_PRINT("Contact", name2, name2_length),
				0);
			skip_name(px, length, &offset);
		}

		break;
	case TYPECLASS(10,1): /* type=NULL, class=INTERNET*/
		/* Regress: defcon2008-dns2.pcap(100803): name=Vaaaaiaqaac.tunnel.fastcoder.net */
		/* I'm not sure what this is, other than passing data as Null records.
		 * This would be a good thing for an intrusion-detection system to trigger
		 * on. */
		break;
	case TYPECLASS(12,0x8001): /*type=PTR, class=INTERNET */
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		break;
	case TYPECLASS(12,1): /*type=PTR(pointer reverse lookup), class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}
		if (name_length > 6 && memcmp(name+name_length-6, ".local", 6) == 0) {

			JOTDOWN(ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("Service", name,name_length),
				0);

			/* Extract MAC address */
			{
				const unsigned char *p_name;
				unsigned name_length;
				const unsigned char *p_mac = find_mac(px, MIN(length, rec->rdata_offset+rec->rdata_length), rec->rdata_offset, &p_name, &name_length);
				if (p_mac) {
					JOTDOWN(ferret,
						JOT_SRC("ID-IP", frame),
						JOT_PRINT("mac",		 	p_mac,						19),
						0);
					JOTDOWN(ferret,
						JOT_SRC("ID-IP", frame),
						JOT_PRINT("name",		 	p_name,						name_length),
						0);
				}
			}

		} else if (endsWith(name, ".in-addr.arpa")) {
			/* Extract a 4-byte IPv4 address 
			 * Example: "18.0.0.10.in-addr.arpa"*/
			unsigned ipv4=0;
			unsigned i;
			unsigned j=0;

			for (i=0; i<4; i++) {
				unsigned num = 0;

				for (; name[j] && name[j] != '.'; j++) {
					if ('0' <= name[j] && name[j] <= '9')
						num = num * 10 + name[j]-'0';
				}
				while (name[j] == '.')
					j++;
				ipv4 |= num<<(i*8);
			}
			/* Now get the name it points to */
			name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));

			JOTDOWN(ferret,
				JOT_PRINT("ID-DNS", name2, name2_length),
				JOT_IPv4("ID-IP", ipv4),
				JOT_SRC("dnssrv", frame),
				0);
		} else
			; //FRAMERR(frame, "dns: unknown PTR record\n");
		break;
	case TYPECLASS(13,0x8001): /*type=HINFO, class=INTERNET */
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		break;
	case TYPECLASS(15,1): /*type=MX, class=INTERNET */
		/* Regress: defcon2008-dns2.pcap(18661) */
		break;
	case TYPECLASS(16,0x8001):		/*type=TXT, class=INTERNET(cache flush)*/
		bonjour_parse_resource_record(ferret, frame, px, length, rec, dns);
		break;
	case TYPECLASS(16,1):		/*type=TXT, class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}

		if (stricmp(name, "current.cvd.clamav.net") == 0) {
			/* This is a single string containing a version string, like:
			 * 0.91.1:44:3855:1186270141:1
			 */
			break;
		} else if (starts_with("_DM-NOTIFICATION.", name, strlen(name))) {
			/* Regress: defcon2008\dump001.pcap(87082) */
			/* TODO */
			break;
		} else if (endsWith(name, "._workstation._tcp.local")) {
			/* Regress: defcon2008-dns2.pcap(56127): "mike-desktop [00:0c:29:f6:58:ca]._workstation._tcp.local" */
			break;
		} else if (endsWith(name, ".asn.cymru.com")) {
			/* Regress: defcon2008-dns2.pcap(98958) */
			/* This is a system for mapping IP to ASN numbers:
			 * http://www.team-cymru.org/Services/ip-to-asn.html */
			break;
		} else if (endsWith(name, ".wrs.trendmicro.com")) {
			/* Regress: defcon2008-dns2.pcap(184904) */
			/* Appears to check whether IP addresses are trustworthy */
			break;
		} else {
			FRAMERR(frame, "%s: unknown TXT record %s", "DNS", name);
		}
		break;
	case TYPECLASS(0x1c,1): /*type=AAAA(IPv6 address), class=INTERNET*/
	case TYPECLASS(0x1c,255): /*type=AAAA(IPv6 address), class=INTERNET*/
		if (!is_valid_opcode(dns->opcode, 0x10, 5, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}
		switch (dns->opcode) {
		case 0x10:
			{
				const unsigned char *ipv6_address = px+rec->rdata_offset;
				if (rec->rdata_length != 16)
					FRAMERR(frame, "dns: data not 16-bytes long, was %d-bytes instead (class=%d, type=%d, name=%s)\n", rec->rdata_length, rec->clss, rec->type, name);

				JOTDOWN(ferret,
					JOT_SZ("proto","DNS"),
					JOT_SZ("op","lookup"),
					JOT_SRC("ip.src", frame),
					JOT_PRINT("name", name, name_length),
					JOT_IPv6("address", ipv6_address,				16),
					0);
			}
		case 5: /* dynamic update*/
			/* Regress: defcon2008-dns2.pcap(7958) */
			break;
		default:
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
		}
		break;
	case TYPECLASS(33,1): /*type=SRV, class=INTERNET */
		if (!is_valid_opcode(dns->opcode, 0x10, -1)) {
			FRAMERR(frame, "%s: unknown opcode=%d\n", "DNS", dns->opcode);
			return;
		}

		if (rec->rdata_length < 7)
			FRAMERR(frame, "dns: unknown type=%d (class=%d, name=%s)\n", rec->type, rec->clss, name);
		else {
			unsigned port = px[rec->rdata_offset+4]<<8 | px[rec->rdata_offset+5];
			name2_length = dns_extract_name(frame, px, length, rec->rdata_offset+6, name2, sizeof(name2));
			ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);

			if (ip_address != 0) {
				JOTDOWN(ferret,
					JOT_PRINT("ID-DNS", name,	name_length),
					JOT_PRINT("Server", name2,	name2_length),
					JOT_NUM("Port", port),
					JOT_IPv4("IPv4",ip_address),
					0);
			} else
				JOTDOWN(ferret,
					JOT_PRINT("ID-DNS", name,	name_length),
					JOT_PRINT("Server", name2,	name2_length),
					JOT_NUM("Port", port),
					0);
		}
		break;
	default:
		FRAMERR(frame, "dns: unknown type=%d (class=%d, name=%s)\n", rec->type, rec->clss, name);
	}
}
Example #7
0
/**
 * This code analyzes a <name=value> pair within a cookie, within the
 * context of an HTTP request, which includes relavent information
 * about the host that it comes from
 */
void parse_http_cookie(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *name, unsigned name_length, const unsigned char *value, unsigned value_length)
{
	struct HTTPREQUEST *req = &sess->layer7.httpreq;
	unsigned char *dec;
	unsigned dec_length = value_length;

	if (dec_length > 1000)
		dec_length = 1000;


	switch (toupper(name[0])) {
	case 'C':
		/* MYSPACE COUNTRY CODE 
		 * Example:
		 * COUNTRYCODE=MFMGCisGAQQBgjdYA%2FmgRTBDBgorBgEEAYI3WAMBoDUwMwIDAgABAgJmAwICAMAECOOUmLvDDv%2BRBBB6gRxsNuYMZ2M7SXM7N4fdBAgyFGPRkgkD7Q%3D%3D;
		 */
		if (match_name("COUNTRYCODE", name, name_length) && ends_with_t(".myspace.com", req->host)) {
			unsigned char *dec0;
			unsigned dec0_length;
			unsigned i;

			/* First, "uudecode" this */
			dec0 = alloca(value_length);
			dec0_length = 0;
			for (i=0; i<value_length; i++) {
				if (value[i] != '%')
					dec0[dec0_length++] = value[i];
				else {
					unsigned c=0;
					i++;
					if (i<value_length && isxdigit(value[i]))
						c = hexval(value[i++])<<4;
					if (i<value_length && isxdigit(value[i]))
						c |= hexval(value[i++]);
					dec0[dec0_length++] = (unsigned char)c;
					i--;
				}
			}

			/* Second, "base64 decode" this */
			dec = alloca(dec0_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);

			/* Third, "asn.1 decode" this */
			{
				unsigned tag, len;
				const unsigned char *px = dec;
				unsigned offset = 0;
				unsigned length = dec_length;
				unsigned max_offset;

				tag = asn1_tag(px,length,&offset);
				len = asn1_length(frame,px,length, &offset);

				/* Process the big object */
				if (tag == 0x30 && len != 0xFFFFFFFF) {
					max_offset = offset+len;

					tag = asn1_tag(px,max_offset,&offset);
					len = asn1_length(frame,px,max_offset, &offset);

					/* Process the OID */
					if (tag == 0x06) {
						JOTDOWN(sess->eng->ferret,
							JOT_SRC("ID-IP", frame),
							JOT_OID("MySpace-CountryCode", px+offset, len),
							0);
					}
					offset += len;


				}


			}
		}
		break;
	case 'D':
		/*
		 go.com (including such properties as espn.com) put in their cookies 
		 some sort of location information. Here are some examples that were googled
		 from the web:

		Z2JyO2VuZztsb25kb247YnJvYWRiYW5kOzU7NTs0Oy0xOzA1MS41MDA7LTAwMC4xMTc7ODI2OzEwMTk4OzQ3ODI7NTsK
		Z2JyO2VuZztsb25kb247YnJvYWRiYW5kOzU7NTs1Oy0xOzA1MS41MDA7LTAwMC4xMTc7ODI2OzEwMTk4OzQ3ODI7NTsK
		dXNhO21kO2NvbGxlZ2UgcGFyazt0MTs1OzQ7NDs1MTE7MDM4Ljk5NzstMDc2LjkyODs4NDA7MjE7MTU7NjsK
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO2dhO2F0bGFudGE7YnJvYWRiYW5kOzU7NTs1OzUyNDswMzMuNzQ5Oy0wODQuMzg4Ozg0MDsxMTszOzY7Cg==
		dXNhO29yO2JlYXZlcnRvbjticm9hZGJhbmQ7NTszOzM7ODIwOzA0NS40OTE7LTEyMi44MDU7ODQwOzM4OzYyOzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzQ7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		dXNhO3R4O2RhbGxhczticm9hZGJhbmQ7NTs0OzM7NjIzOzAzMi43ODc7LTA5Ni43OTk7ODQwOzQ0Ozc3OzY7Cg==
		*/
		if (match_name("DE2", name, name_length) && ends_with_t(".go.com", req->host)) {
			dec = alloca(dec_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("GO-LOC", dec, dec_length),
				0);
		}
		break;
	case 'E':
		if (starts_with("EMAIL", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, value_length),
				0);
		}
		if (starts_with("E-MAIL", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, value_length),
				0);
		}
		break;

	case 'G':
		/*
		d78da8e7eb998e8f571c4c641b104c60cxsAAABVUyxnYSxsYXdyZW5jZXZpbGxlLCwsLCw1MjQ=
		bf8e3d7c0474fa9da14b6551e6846ec7cxUAAABVUyxnYSxhdGxhbnRhLCwsLCw1MjQ=

		*/
		if (match_name("GEO", name, name_length) && ends_with_t(".youtube.com", req->host)) {
			unsigned i;
			unsigned comma_count=0;
			dec = alloca(dec_length);
			dec_length = base64_decode(dec, dec_length, value, value_length);

			for (i=dec_length; i>0; i--) {
				if (dec[i-1] == ',') {
					/*US,ga,lawrenceville,,,,,524*/
					if (++comma_count == 7)
						break;
				}
			}
			if (i>3 && isalpha(dec[i-2]) && isalpha(dec[i-3])) {
				unsigned offset=i-3;
				while (i<dec_length && comma_count > 5) {
					if (dec[i] == ',')
						comma_count--;
					i++;
				}
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("YouTube-Loc", dec+offset, i-offset-1),
					0);
			}
		}
		/*Example:
		 * [email protected]/769779 
		 */
		if (match_name("GMAILCHAT", name, name_length) && ends_with_t("mail.google.com", req->host)) {
			unsigned j;
			for (j=0; j<value_length && value[j] != '/'; j++)
				;
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("e-mail", value, j),
				0);
		}
		break;
	case 'I':
		if (match_name("ID", name, name_length) && ends_with_t(".doubleclick.net", req->host)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("DoubleClick", value, value_length),
				0);
		}
		break;
	case 'L':
		if (match_name("LOGIN", name, name_length) || match_name("LOGIN_X", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("login", value, value_length),
				0);

			if (ends_with_t(".facebook.com", req->host)) {
				req->login = stringtab_lookup(sess->eng->stringtab, value, value_length);
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("Facebook-user", req->login->str, req->login->length),
					0);
			}

			if (contains("@", value, value_length)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			} else if (contains("%40", value, value_length)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}
		break;
	case 'M':
		/*http://facebook.com
		 *m_user = warnerc2%40gpc.edu%3A71101757%3ASwUchOEuvzIbYo7E*/
		if (match_name("M_USER", name, name_length)) {
			if (ends_with_t(".facebook.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}

		/* http://login.live.com/login.srf
		 * [email protected] */
		if (match_name("MSPPRE", name, name_length)) {
			if (ends_with_t(".live.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("e-mail", value, value_length),
					0);
			}
		}

		/* Canadian Broadcasting */
		if (match_name("MyCBCSignIn", name, name_length)) {
			if (ends_with_t(".cbc.ca", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("e-mail", value, value_length),
					0);
			}
		}
		if (match_name("ME", name, name_length)) {
			if (ends_with_t(".myspace.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("ID-IP", frame),
					JOT_URLENC("e-mail", value, value_length),
					0);
			}
		}
		 
		break;
	case 'P':
		if (starts_with("PASSWORD", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("password", value, value_length),
				0);
		}
		break;
	case 'U':
		if (starts_with("USERNAME", name, name_length)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_PRINT("username", value, value_length),
				0);
		}
		break;
	case 'W':
		if (starts_with("WATCHED_VIDEO_ID_LIST_", name, name_length)) {
			size_t l = sizeof("WATCHED_VIDEO_ID_LIST_")-1;
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("YouTube-ID", name+l, name_length-l),
				0);
		}
		break;
	}
}
Example #8
0
/**
 * This parses a TLV record instead of a SNAC packet, which is itself 
 * inside of a FLAP PDU. We identify the precise item by the SNAC-family,
 * SNAC-subtype, and TLV-tag */
static void 
parse_tlv(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct FerretEngine *eng = sess->eng;
	struct Ferret *ferret = eng->ferret;
	struct AIMPARSER *aim = &sess->layer7.aim;
	unsigned h;

	/* This function is going to process the data within a SNAC TLV field. 
	 * We are just going to handle this all in a big switch/case statement. */
#define HASH(x,y,z) (((x)<<16)|((y)<<8)|(z))
	h = HASH(aim->pdu.family, aim->pdu.subtype, aim->tlv_tag);

	/* If we are in the middle of parsing the string, just grab
	 * it in our re-assembly buffer */
	if (px != NULL) {
		strfrag_append(sess->str, px, length);
		return;
	}
	
	/* Process the string we've reassembled. We are going to hash on the full context
	 * of the PDU rather than just the TLV tag */
	switch (h) {
	case 0x00170203: /* family=Sign-on, subtype=Logon, tag=client-id-string */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_PRINT("AIM-Client-ID", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x0017020e: /* family=Sign-on, subtype=Logon, tag=country */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_PRINT("AIM-Country", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x0017020f: /* family=Sign-on, subtype=Logon, tag=language */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_PRINT("AIM-Language", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x00170225: /* family=Sign-on, subtype=Logon, tag=password hash */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_HEXSTR("AIM-Password-Hash", sess->str->the_string, sess->str->length),
			0);
		break;
		break;
	case 0x00170201: /* family=Sign-on, subtype=Logon, tag=screen-name */
	case 0x00170601: /* family=Sign-on, subtype=Sign-on, tag=screen-name  */
		/* This is the sign-on 'screen-name' in the packet that the user sends to
		 * the logon server (logon.oscar.aol.com). The server will respond with
		 * a 'challenge'. The user will then send the screen-name and hash of 
		 * challenge and password to the real server he wants to connect to */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_PRINT("AIM-Screen-Name", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x00170301: /* family=Logon, subtype=Reply, tag=screen-name  */
		JOTDOWN(ferret, 
			JOT_DST("ID-IP",frame), /* logon reply screen name sent from server*/
			JOT_PRINT("AIM-Screen-Name", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x00170311: /* family=Logon, subtype=Reply, tag=email  */
		JOTDOWN(ferret, 
			JOT_DST("ID-IP",frame), /* logon reply screen name sent from server*/
			JOT_PRINT("e-mail", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x00170349: /* family=Logon, subtype=Reply, tag=auth-protocol  */
		JOTDOWN(ferret, 
			JOT_DST("ID-IP",frame), /* logon reply screen name sent from server*/
			JOT_HEXSTR("AIM-digest-sig", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x00170700: /*AIM Sign-on(0x17), Sign-on Reply(7), Challenge(10)*/
		/* This is the 'challenge' sent back by logon.oscar.aol.com. The user
		 * will hash this with his password in order to logon to all the other
		 * servers.
		 *
		 * Because of this, we need to attach this string to the session going
		 * in the reverse direction. That will enable us to log the authentication
		 * process in case we want to log the hashes */
		JOTDOWN(ferret, 
			JOT_SRC("ID-IP",frame),
			JOT_PRINT("AIM-Challenge", sess->str->the_string, sess->str->length),
			0);
		break;
	case 0x0017038e: /* authorization cookie */
		/* This is a long string to pull out, but it gives anybody who has
		 * this cookie the ability to log onto any AIM service */
		JOTDOWN(ferret, 
			JOT_DST("ID-IP",frame),
			JOT_HEXSTR("AIM-Auth-Cookie", sess->str->the_string, sess->str->length),
			0);
		break;	
	case  0x00030b00: /* INCOMING oncoming buddy name */
	case  0x00020600:
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str->the_string, sess->str->length),
				0);
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("friend", sess->str->the_string, sess->str->length),
				0);
		}
		break;
	case 0x00021500: /* OUTGOING user info query*/
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str->the_string, sess->str->length),
				0);
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("friend", sess->str->the_string, sess->str->length),
				0);
		}
		break;
	case 0x00040700: /* Messaging, incoming */
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str->the_string, sess->str->length),
				0);
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("friend", sess->str->the_string, sess->str->length),
				0);

			strfrag_xfer(sess->str+1, sess->str);
		}
		break;
	case 0x00040702: /* Messaging, INCOMING */
		decode_message(sess, frame, sess->str[0].the_string, sess->str[0].length, 0);
		break;
	case 0x00040600: /* Messaging, outgoing */
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str->the_string, sess->str->length),
				0);
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("friend", sess->str->the_string, sess->str->length),
				0);

			strfrag_xfer(sess->str+1, sess->str);
		}
		break;
	case 0x00040602: /* Messaging, outgoing */
		decode_message(sess, frame, sess->str[0].the_string, sess->str[0].length, 1);
		break;
	case 0x00020604: /* Buddy Info - away message */
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str[1].the_string, sess->str[1].length),
				JOT_PRINT("Away-Message", sess->str[0].the_string, sess->str[0].length),
				0);
		}
		break;
	case 0x00041400: /* typing, outgoing */
		if (sess->str->length) {
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str->the_string, sess->str->length),
				0);
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("friend", sess->str->the_string, sess->str->length),
				0);
		}
		break;
	case 0x00040605: /* File transfer */
		parse_message_filexfer_rendezvous(sess, frame, sess->str->the_string, sess->str->length);
		break;

	case 0x00040701:
	case 0x00040703:
	case 0x00040705:
	case 0x0004070b:
	case 0x0004070f:
	case 0x00040713:
	case 0x00040716:
	case 0x0004071d:
	case 0x00040603: /* Messaging, outgoing, server-ack requested */
		break;
	case 0x00130601: /* SNAC Server Side Information Entry List*/
	case 0x001306c9: 
	case 0x001306d6: 
	case 0x0013066a:
	case 0x0013066d: 
	case 0x00130631: 
		/* This is the start of an SSI Entry list, maybe we should 
		 * remember this??? */
		break;
	case 0x00130731:
		if (sess->str[1].length && sess->str[0].length) {
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("AIM-Buddy", sess->str[1].the_string, sess->str[1].length),
				JOT_PRINT("AIM-Description", sess->str[0].the_string, sess->str[0].length),
				0);
		}
		break;
	/* Others that I've seen */
	case 0x0017064b:
	case 0x0017065a:
	case 0x0017024c:
	case 0x00170216:
	case 0x00170217:
	case 0x00170218:
	case 0x00170219:
	case 0x0017021a:
	case 0x00170214:
	case 0x0017024a:
	case 0x00170305:
	case 0x00170306:
	case 0x00170313:
	case 0x00170354:
	case 0x00170340:
	case 0x00170343:
	case 0x00170341:
	case 0x00170342:
	case 0x00170348:
	case 0x00170344:
	case 0x00170347:
	case 0x00170345:
	case 0x00170346:
	case 0x00020301:
	case 0x00020302:
	case 0x00020305:
	case 0x00020303:
	case 0x00020304:
	case 0x00030302:
	case 0x00030301:
	case 0x00030304:
	case 0x00040504:
	case 0x00090302:
	case 0x00090301:
	case 0x00020405:
	case 0x00011e1d:
	case 0x00011e06:
	case 0x0004060d:
	case 0x00020601: /* Buddy Info - User Class */
	case 0x00020603: /* Buddy Info - Online Since AND Away Msg Encoding ??? */
	case 0x00020605: /* Buddy Info - Member Since */
	case 0x0002060b: /* Buddy Info - unknown timestamp */
	case 0x0002060d: /* Buddy Info - Capabilities List */
	case 0x0002060f: /* Buddy Info - Session Length */
	case 0x0002061d: /* Buddy Info - Available Message */
	case 0x0002061f: /* Buddy Info - unknown */
	case 0x00020623: /* Buddy Info - unknown timestamp */
	case 0x00020626: /* Buddy Info - unknown timestamp (member since?) */
	case 0x00020627: /* Buddy Info - unknown timestamp */

		break;
	case 0x001306C8: /*SSI: members of this group */
		break;
	default:
		/* TODO: add SAMPLE here */
		switch (h&0xFFFFFF00) {
		case 0x00130300:
			break;
		default:
			FRAMERR(frame, "%s: unknown TLV tag: 0x%08x\n", "AIM", h);
		}
		break;
	}
	strfrag_finish(sess->str);
}
Example #9
0
void decode_message(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *px, unsigned length, unsigned is_outgoing)
{
	struct FerretEngine *eng = sess->eng;
	struct Ferret *ferret = eng->ferret;
	const unsigned char *msg = px;
	unsigned msg_length = length;
	unsigned msg_offset = 0;

	if (msg_length > 2 && ex16be(msg+msg_offset) == 0x501) {
		/*unsigned flags = ex16be(msg+msg_offset);*/
		unsigned len=0;
		msg_offset += 2;
		
		if (msg_offset+2 < msg_length) {
			len = ex16be(msg+msg_offset);
			msg_offset += len+2;
		}

		if (msg_offset+2 < msg_length)
			msg_offset += 2; /* block info */

		if (msg_offset+2 < msg_length) {
			len = ex16be(msg+msg_offset);
			msg_offset += 2; /* block length */
		}

		msg_offset += 4; /* character set */
		if (len > 4)
			len -= 4; /* subtract the charset info from the block lenght*/

		if (msg_offset > msg_length) {
			FRAMERR(frame, "%s: integer overflow\n", "AIM");
			return;
		}

		if (msg_offset + len > msg_length)
			len = msg_length - msg_offset;

		if (len > 6 && strnicmp((const char*)msg+msg_offset, "<HTML>", 6)==0) {
			unsigned char *msg2 = alloca(len);
			unsigned msg2_len;

			msg2_len = strip_html_tags(msg+msg_offset, len, msg2, len);

			if (is_outgoing)
				JOTDOWN(ferret, 
					JOT_SRC("ID-IP",frame),
					JOT_PRINT("AIM-Message-To", sess->str[1].the_string, sess->str[1].length),
					JOT_PRINT("AIM-Message", msg2, msg2_len),
					0);
			else
				JOTDOWN(ferret, 
					JOT_DST("ID-IP",frame),
					JOT_PRINT("AIM-Message-From", sess->str[1].the_string, sess->str[1].length),
					JOT_PRINT("AIM-Message", msg2, msg2_len),
					0);

		} else  {
			if (is_outgoing)
				JOTDOWN(ferret, 
					JOT_SRC("ID-IP",frame),
					JOT_PRINT("AIM-Message-To", sess->str[1].the_string, sess->str[1].length),
					JOT_PRINT("AIM-Message", msg+msg_offset, msg_length-msg_offset),
					0);
			else
				JOTDOWN(ferret, 
					JOT_DST("ID-IP",frame),
					JOT_PRINT("AIM-Message-From", sess->str[1].the_string, sess->str[1].length),
					JOT_PRINT("AIM-Message", msg+msg_offset, msg_length-msg_offset),
					0);
		}

	} else {
		while (msg_offset<msg_length && msg[msg_offset] < 26)
			msg_offset++;

		if (is_outgoing)
			JOTDOWN(ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_PRINT("AIM-Message-To", sess->str[1].the_string, sess->str[1].length),
				JOT_PRINT("AIM-Message", msg+msg_offset, msg_length-msg_offset),
				0);
		else
			JOTDOWN(ferret, 
				JOT_DST("ID-IP",frame),
				JOT_PRINT("AIM-Message-From", sess->str[1].the_string, sess->str[1].length),
				JOT_PRINT("AIM-Message", msg+msg_offset, msg_length-msg_offset),
				0);
	}
}
Example #10
0
/**
 * Parse the "rendez-vous" TLV within a packet. Since this is a TLV, it has
 * already been reassembled by our string frag parser.
 */
static void
parse_message_filexfer_rendezvous(struct TCPRECORD *sess, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	unsigned offset=0;

	/* skip some fields */
	offset += 2+8;

	/* verify we have the file transfer ID */
	while (offset < 2+8+16) {
		if (px[offset] != (unsigned char)("\x09\x46\x13\x43\x4c\x7f\x11\xd1\x82\x22\x44\x45\x53\x54\x00\x00"[offset-8-2]))
			return; /* not a file transfer command */ /*TODO: SAMPLE this */
		offset++;
	}

	/* go through the embeded TLVs */
	while (offset<length) {
		unsigned tag;
		unsigned len;

		if (offset+4>length)
			break;

		tag = ex16be(px+offset+0);
		len = ex16be(px+offset+2);

		offset += 4;

		/*
            TLV: Unknown
                Value ID: Unknown (0x000a)
                Length: 2
                Value
            TLV: Unknown
                Value ID: Unknown (0x000f)
                Length: 0
                Value
            TLV: Internal IP
                Value ID: Internal IP (0x0003)
                Length: 4
                Value: 12625930
            TLV: External Port
                Value ID: External Port (0x0005)
                Length: 2
                Value: 5190
            TLV: Extended Data
                Value ID: Extended Data (0x2711)
                Length: 17
                Value
		*/
		switch (tag) {
		case 0x000a:
		case 0x000f:
		case 0x0010:
			break;
		case 3: /* Internet IP */
			{
				unsigned j;
				unsigned ip=0;
				for (j=0; j<4 && offset+j<length; j++)
					ip = ip << 8 | px[offset+j];

				JOTDOWN(sess->eng->ferret, 
					JOT_SRC("ID-IP",frame),
					JOT_SZ("AIM", "File-Transfer"),
					JOT_IPv4("Internal-IP", ip),
					0);
			}
			break;
		case 5: /* Internal Port */
			{
				unsigned j;
				unsigned port=0;
				for (j=0; j<2 && offset+j<length; j++)
					port = port << 8 | px[offset+j];

				JOTDOWN(sess->eng->ferret, 
					JOT_SRC("ID-IP",frame),
					JOT_SZ("AIM", "File-Transfer"),
					JOT_NUM("Internal-Port", port),
					0);
			}
			break;
		case 0x2711: /* filename */
			if (len > length-offset)
				len = length-offset;
			if (len > 4) {
				len -= 4;
				offset += 4;
			}

			while (offset < length && len && px[offset] < 26) {
				offset++;
				len--;
			}

			JOTDOWN(sess->eng->ferret, 
				JOT_SRC("ID-IP",frame),
				JOT_SZ("AIM", "File-Transfer"),
				JOT_PRINT("Filename", px+offset, len),
				0);
			break;
		default:
			/* TODO: SAMPLE this */
			FRAMERR(frame, "%s: unknown\n", "AIM");
			break;
		}

		offset += len;
	}
	
}
Example #11
0
void parse_atalk_ddp(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
    unsigned offset=0;
    struct {
        unsigned hop_count;
        unsigned datagram_length;
        unsigned checksum;
        unsigned protocol_type;
        unsigned address_src;
        unsigned address_dst;
        unsigned port_src;
        unsigned port_dst;
    } ddp;

    ferret->statistics.atalk++;

    if (length < 13) {
        FRAMERR(frame, "%s: truncated\n", "DDP");
        return;
    }



    ddp.hop_count = px[0]>>4;
    ddp.datagram_length = (px[0]&0xF)<<8 | px[1];
    ddp.checksum = ex16be(px+2);
    ddp.address_dst = ex16be(px+4)<<8;
    ddp.address_src = ex16be(px+6)<<8;
    ddp.address_dst |= px[8];
    ddp.address_src |= px[9];
    ddp.port_dst = px[10];
    ddp.port_src = px[11];
    ddp.protocol_type = px[12];

    if (length > ddp.datagram_length) {
        if (length-ddp.datagram_length == 4)
            ferret->statistics.remaining_4++; /*hints that an FCS trails*/
        length = ddp.datagram_length;
    }

    frame->ipver = ADDRESS_ATALK_EDDP;
    frame->src_ipv4 = ddp.address_src;
    frame->dst_ipv4 = ddp.address_dst;
    frame->src_port = ddp.port_src;
    frame->dst_port = ddp.port_dst;

    /* skip the header */
    offset += 13;

    /* If this is a broadcast packet, we can make the assumption
     * that the sender is on the local subnet */
    JOTDOWN(ferret,
            JOT_MACADDR("ID-MAC", frame->src_mac),
            JOT_SRC("AppleTalk", frame),
            0);

    /* Parse the next layer */
    SAMPLE(ferret, "ATALK-DDP",JOT_NUM("protocol", ddp.protocol_type));
    SAMPLE(ferret, "ATALK-DDP",JOT_NUM("dst-port", ddp.port_dst));

    switch (ddp.protocol_type) {
    case 0x02: /* NBP - Name Binding Protocol */
        parse_atalk_nbp(ferret, frame, px+offset, length-offset);
        break;
    case 0x06: /* ZIP (Zone Information Protocol) */
        break;
    case 0x01: /* RTMP (Routing Table Maintenance Protocol), works like RIP */
    case 0x03: /* ATP (Appletalk Transfer Protocol) */
    case 0x04: /* Echo, works like ICMP Echo */
    case 0x05: /* RTMP requests */
    case 0x07: /* ADSP (Appletalk Data Stream Protocol) */
    case 0x08: /* SNMP, same as normal SNMP */
    case 0x16: /* IP over AppleTalk */
    default:
        FRAMERR(frame, "%s: unknown protocol=%d, srcport=%d, dstport=%d\n", "DDP", ddp.protocol_type,
                ddp.port_src, ddp.port_dst);
    }

}
Example #12
0
/**
 * Parses the <name=value> pairs in HTTP URLs and HTTP POST content data
 */
void  http_parse_form_field(struct TCPRECORD *sess, struct NetFrame *frame,
				struct StringT *name,
				const unsigned char *value,
				unsigned value_length)
{
	struct TCP_STREAM *stream = &sess->to_server;
	struct HTTPREQUEST *req = &stream->app.httpreq;

	if (name == NULL)
		return;

	switch (toupper(name->str[0])) {
	case 'E':
		if (match_name_t("EMAIL", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("e-mail", value, value_length),
				0);

			if (ends_with_t(".myspace.com", req->host)) {
				req->login = stringtab_lookup(sess->eng->stringtab, value, value_length);
				if (req->password) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						JOT_URLENC("password", req->password->str, req->password->length),
						0);
				} else
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						0);

			}
		}
		break;
	case 'P':
		if (match_name_t("PASSWORD", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("form-password", value, value_length),
				0);

			if (ends_with_t(".myspace.com", req->host)) {
				req->password = stringtab_lookup(sess->eng->stringtab, value, value_length);
				if (req->login) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("ID-IP", frame),
						JOT_URLENC("MySpace-user", req->login->str, req->login->length),
						JOT_URLENC("password", req->password->str, req->password->length),
						0);
				}
			}
		}
		if (match_name_t("PASSWD", name)) {
			JOTDOWN(sess->eng->ferret,
				JOT_SRC("ID-IP", frame),
				JOT_URLENC("password", value, value_length),
				0);
		}
		break;
	case 'Q':
		if (match_name_t("Q", name)) {
			if (ends_with_t(".google.com", req->host)) {
				if (!starts_with("cache:", req->url, req->url_length)) {
					JOTDOWN(sess->eng->ferret,
						JOT_SRC("IP", frame),
						JOT_URLENC("search", value, value_length),
						0);

				}
			}

		}
		break;
	case 'V':
		if (match_name_t("VIDEO_ID", name)) {
			if (ends_with_t(".youtube.com", req->host)) {
				JOTDOWN(sess->eng->ferret,
					JOT_SRC("Watches", frame),
					JOT_URLENC("YouTube", value, value_length),
					0);
				req->youtube_video_id = stringtab_lookup(sess->eng->stringtab, value, value_length);
			}
		}
		break;
	}
}
Example #13
0
void process_ymsg_client_request(
		struct TCPRECORD *sess, 
		struct NetFrame *frame, 
		struct StringReassembler *ymsg_packet)
{
	struct FerretEngine *eng = sess->eng;
	struct Ferret *ferret = eng->ferret;
	unsigned service = sess->layer7.ymsg.service;
	unsigned status = sess->layer7.ymsg.status;
	struct Atom atom;

	switch (service) {
	
	case 18: /* Ping */

		break;
	
	case 0x54: /*YAHOO_SERVICE_AUTHRESP - Response to server challenge */
		switch (status) {
		case 0:
		case 1515563605: /* Web Login: Ref: 2009-01-24-1.pcap(6243) */
			atom = ymsg_get_enumerated_item(ymsg_packet, "0"); /* "yahoo_id" */
			if (atom.len) {
				JOTDOWN(ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("username", atom.px+atom.offset, atom.len),
					0);
				strncpy_s(sess->layer7.ymsg.username, sizeof(sess->layer7.ymsg.username), atom.px+atom.offset, atom.len);
			}
			atom = ymsg_get_enumerated_item(ymsg_packet, "1"); /* "active_id", which may differ from "yahoo_id" */
			if (atom.len) {
				JOTDOWN(ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("username", atom.px+atom.offset, atom.len),
					0);
				strncpy_s(sess->layer7.ymsg.username, sizeof(sess->layer7.ymsg.username), atom.px+atom.offset, atom.len);
			}

			/* 
			 * Report challenge/response for password-cracking tools
			 */
			if (sess->reverse && sess->reverse->str[1].length) { /* if we have a challenge from the other direction */
				strfrag_init(&sess->reverse->str[1]);
			}

			break;
		default:
			FRAMERR_UNPARSED(frame, "YMSG.service", service);
		}
		break;

	/*YAHOO_SERVICE_AUTH		Authentication */
	case 0x57: 
		switch (status) {
		case 0:
			atom = ymsg_get_enumerated_item(ymsg_packet, "1"); /* "yahoo_id" */
			if (atom.len) {
				JOTDOWN(ferret,
					JOT_SRC("ID-IP", frame),
					JOT_PRINT("username", atom.px+atom.offset, atom.len),
					0);
				strncpy_s(sess->layer7.ymsg.username, sizeof(sess->layer7.ymsg.username), atom.px+atom.offset, atom.len);
			}
			break;
		default:
			FRAMERR_UNPARSED(frame, "YMSG.service", service);
		}
		break;
	case 198: /* Yahoo v6 Status Update */
		break;
	case 138:
		/* Ref: 2009-01-24-1.pcap(1441) */
		/* Appears to be the user's login name as the one
		 * field in this packet */
		break;
	case 21: /* skin name */
		/* Ref: 2009-01-24-1.pcap(6394) */
		/* TODO
		 * This contains some information about the user's machine, such as 
		 * what type of machine it is */
		break;
	default:
		FRAMERR_UNPARSED(frame, "YMSG.service", service);
	}
}
Example #14
0
void parse_atalk_nbp(struct Ferret *ferret, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	struct {
		unsigned op;
		unsigned count;
		unsigned xid;
	} nbp;
	unsigned offset=0;

	if (length < 2) {
		FRAMERR(frame, "%s: truncated\n", "NBP");
		return;
	}

	/*
	 * Parse the header first
	 */
	nbp.op = (px[0]>>4)&0x0F;
	nbp.count = (px[0]>>0)&0x0F;
	nbp.xid = px[1];

	offset = 2;

	/*
	 * Parse all the name-bindings
	 */
	while (nbp.count) {
		unsigned atalk_addr;
		unsigned atalk_port;
		unsigned enumerator;
		unsigned object_len;
		const unsigned char *object;
		unsigned type_len;
		const unsigned char *type;
		unsigned zone_len;
		const unsigned char *zone;

		nbp.count--;

		if (offset + 6 > length) {
			FRAMERR(frame, "%s: truncated\n", "NBP");
			return;
		}

		atalk_addr = ex24be(px+offset);
		offset += 3;
		atalk_port = px[offset++];
		enumerator = px[offset++];
		

		/* Extract the items */
		extract_item(ferret, frame, px, length, &offset, &object, &object_len);
		extract_item(ferret, frame, px, length, &offset, &type, &type_len);
		extract_item(ferret, frame, px, length, &offset, &zone, &zone_len);

		if (offset > length)
			break;

		switch (nbp.op) {
		case 2:
			JOTDOWN(ferret,
				JOT_SRC("ID-ATALK", frame),
				JOT_PRINT("Lookup",  type, type_len),
				JOT_PRINT("Object",  object, object_len),
				JOT_PRINT("Zone",  zone, zone_len),
				0);
			break;
		default:
			FRAMERR(frame, "%s: not implemented\n", "NBP");
		}

	}


	
}