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

📄 dns.c

📁 FERRET - a broadcast analysis tool This tool is designed to demonstrate the problem of "data seap
💻 C
📖 第 1 页 / 共 3 页
字号:
	unsigned name_length;
	char name2[256];
	unsigned name2_length;
	unsigned offset = rec->rdata_offset;
	unsigned offset_max = MIN(rec->rdata_offset+rec->rdata_length, length);


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

	switch (rec->type<<16 | rec->clss) {
	case TYPECLASS(32,1): /*NetBIOS*/
		ip_address = ex32be(px+rec->rdata_offset+2);

		if (rec->rdata_length != 6)
			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);

		translate_netbios_name(frame, name, name2, sizeof(name2));

		process_record(seap,
			"proto",	REC_SZ,			"NETBIOS",						-1,
			opcode,		REC_SZ,			"registration",			-1,
			"name",		REC_PRINTABLE,	name2,				strlen(name2),
			"address",	REC_IPv4,		&ip_address,				sizeof(ip_address),
			"ip.src",	REC_FRAMESRC,	frame, -1,
			0);

		process_record(seap,
			"ID-IP",	REC_IPv4,		&ip_address,				sizeof(ip_address),
			"netbios",	REC_PRINTABLE,	name2,				strlen(name2),
			0);

		break;
	case TYPECLASS(6,1): /*SOA*/
		/*
		 * Authoritative Name Server
		 */
		name2_length = dns_extract_name(frame, px, length, offset, name2, sizeof(name2));
		process_record(seap,
			"proto",	REC_SZ,			"DNS",						-1,
			opcode,	REC_SZ,			"SOA",					-1,
			"domain",	REC_PRINTABLE,	name,						name_length,
			"NS",		REC_PRINTABLE,	name2,						name2_length,
			0);
		ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);
		if (ip_address)
		process_record(seap,
			"proto",	REC_SZ,			"DNS",						-1,
			opcode,	REC_SZ,			"SOA",					-1,
			"domain",	REC_PRINTABLE,	name,						name_length,
			"NS",		REC_IPv4,		&ip_address,				sizeof(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));
			process_record(seap,
				"proto",	REC_SZ,			"DNS",						-1,
				opcode,	REC_SZ,			"SOA",					-1,
				"domain",	REC_PRINTABLE,	name,						name_length,
				"contact",	REC_PRINTABLE,	name2,						name2_length,
				0);
			skip_name(px, length, &offset);
		}

		break;
	case TYPECLASS(2,1): /* NS */
		dns_extract_name(frame, px, length, rec->rdata_offset, name2, sizeof(name2));
		ip_address = dns_resolve_alias(frame, px, length, dns, name2, 0);

		process_record(seap,
			"proto",	REC_SZ,			"DNS",						-1,
			opcode,	REC_SZ,			"NS",			-1,
			"domain",	REC_PRINTABLE,	name,						strlen(name),
			"NS",		REC_PRINTABLE,	name2,						strlen(name2),
			"sender",	REC_FRAMESRC,	frame, -1,
			0);
		process_record(seap,
			"proto",	REC_SZ,			"DNS",						-1,
			opcode,	REC_SZ,			"NS",			-1,
			"domain",	REC_PRINTABLE,	name,						strlen(name),
			"NS",		REC_IPv4,		&ip_address,				sizeof(ip_address),
			"sender",	REC_FRAMESRC,	frame, -1,
			0);
		break;
	default:
		FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
	}
}


void process_dns(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length)
{
	unsigned offset;
	struct DNS dns[1] = {0};
	unsigned record_count;
	unsigned total_records;
	unsigned i;

	memset(dns, 0, sizeof(dns[0]));

	if (length < 12) {
		FRAMERR(frame, "dns: frame too short\n");
		return;
	}

	dns->id = ex16be(px+0);
	dns->is_response = ((px[2]&0x80) != 0);
	dns->opcode = (px[2]>>3)&0x01F;
	dns->flags = ex16be(px+2)&0x7F0;
	dns->rcode = px[3]&0x0F;

	dns->question_count = ex16be(px+4);
	dns->answer_count = ex16be(px+6);
	dns->authority_count = ex16be(px+8);
	dns->additional_count = ex16be(px+10);

	total_records = dns->question_count + dns->answer_count + dns->authority_count + dns->additional_count;

	offset = 12;
	record_count = 0;

	/*
	 * After processing the header, now process all the records
	 */
	while (offset < length && record_count < 100) {
		struct DNSRECORD *rec = &dns->records[record_count];

		if (record_count >= total_records) {
			SAMPLE("dns", "too-many-records",	REC_UNSIGNED, &total_records,	sizeof(total_records));
			break;
		}

		rec->name_offset = offset;
		while (offset < length) {
			if (px[offset] == 0x00) {
				offset++;
				break;
			}
			if (px[offset] & 0xC0) {
				offset += 2;
				break;
			}
			offset += px[offset] + 1;

			if (offset > length) {
				FRAMERR(frame, "dns: past end of packet\n");
				return;
			}
		}

		if (offset + 4 > length) {
			FRAMERR(frame, "dns: past end of packet\n");
			return;
		}

		rec->type = ex16be(px+offset+0);
		rec->clss = ex16be(px+offset+2);
		offset += 4;
		
		record_count++;
		if (record_count <= dns->question_count)
			continue;
		
		
		if (offset + 6 > length) {
			FRAMERR(frame, "dns: past end of packet\n");
			return;
		}

		rec->ttl = ex32be(px+offset+0);
		rec->rdata_length = ex16be(px+offset+4);
		offset += 6;
		rec->rdata_offset = offset;
		offset += rec->rdata_length;

		if (offset > length) {
			FRAMERR(frame, "dns: past end of packet\n");
			return;
		}
	}
	dns->record_count = record_count;

	dns->questions = &dns->records[0];
	dns->answers = &dns->records[dns->question_count];
	dns->authorities = &dns->records[dns->question_count + dns->answer_count];
	dns->additionals = &dns->records[dns->question_count + dns->answer_count + dns->authority_count];

	switch (dns->opcode) {
	case 0x00: /*query request*/
		for (i=0; i<dns->question_count; i++) {
			char name[256];
			unsigned name_length;
			struct DNSRECORD *rec = &dns->questions[i];

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

			switch (rec->type) {
			case 0x0001: /*A = IPv4 address */
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"query",		REC_SZ,			"A",					-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 0x001c: /*AAAA = IPv6 address */
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"query",		REC_SZ,		"AAAA",					-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				case 0x8001:
					process_record(seap,
						"proto",	REC_SZ,			"MDNS",						-1,
						"query",		REC_SZ,		"AAAA",					-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"flush",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 0x0002: /*NS*/
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"query",	REC_SZ,			"NS",					-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 0x0006: /*SOA - Start of Authority */
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"query",		REC_SZ,		"SOA",					-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 0x0020: /*NETBIOS */
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					{
						unsigned ip_address = ex32be(px+rec->rdata_offset);
						char netbios_name[300];
						
						translate_netbios_name(frame, name, netbios_name, sizeof(netbios_name));

						process_record(seap,
							"proto",	REC_SZ,			"NETBIOS",						-1,
							"query",	REC_SZ,			"netbios",			-1,
							"ip.src",	REC_FRAMESRC,	frame, -1,
							"name",		REC_PRINTABLE,	netbios_name,				strlen(netbios_name),
							"address",	REC_IPv4,		&ip_address,				sizeof(ip_address),
							0);
					}
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 0x0021: /*SRV (Service Location) */
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"query",	REC_SZ,			"srv",					-1,
						"ip.src",	dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 12: /*PTR*/
				switch (rec->clss) {
				case 0x0001: /*INTERNET*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"op",		REC_SZ,			"reverse",					-1,
						"ip.src",	dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					break;
				case 0x8001: /*FLUSH*/
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			case 255: /*any*/
				switch (rec->clss) {
				case 0x8001: /*FLUSH*/
					process_record(seap,
						"proto",	REC_SZ,			"DNS",						-1,
						"op",		REC_SZ,			"flush",					-1,
						"ip.src",	dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
						"name",		REC_PRINTABLE,	name,						strlen(name),
						0);
					if (endsWith(name, "._ipp._tcp.local")) {
						process_record(seap,
							"Bonjour",	dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
							"Printer",		REC_PRINTABLE,	name,						strlen(name)-strlen("._ipp._tcp.local"),
							0);
					} else if (endsWith(name, ".local"))
						process_record(seap,
							"ID-IP",	dns->is_response?REC_FRAMEDST:REC_FRAMESRC, frame, -1,
							"name",		REC_PRINTABLE,	name,						strlen(name)-strlen(".local"),
							0);
					else
						FRAMERR(frame, "%s: unknown value: %s\n", "dns", name);

					break;
				case 1:
					break;
				default:
					FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
				}
				break;
			default:
				FRAMERR(frame, "dns: unknown class=%d (type=%d, name=%s)\n", rec->clss, rec->type, name);
			}
		}
		break;
	case 0x10: /*query response */
		switch (dns->rcode) {
		case 0:
			for (i=0; i<dns->answer_count; i++) {
				char name[256];
				unsigned name_length;
				struct DNSRECORD *rec = &dns->answers[i];

				if (rec->type == 0x8001)
					FRAMERR(frame, "test\n");

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

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

⌨️ 快捷键说明

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