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

📄 dns.c

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

#ifndef MIN
#define MIN(a,b) ( (a)<(b) ? (a) : (b) )
#endif

struct DNSRECORD
{
	unsigned name_offset;
	unsigned type;
	unsigned clss;
	unsigned ttl;
	unsigned rdata_offset;
	unsigned rdata_length;
};
struct DNS {
	unsigned id;
	unsigned is_response;
	unsigned opcode;
	unsigned rcode;
	unsigned flags;
	unsigned question_count;
	unsigned answer_count;
	unsigned authority_count;
	unsigned additional_count;

	struct DNSRECORD records[256];
	unsigned record_count;

	struct DNSRECORD *questions;
	struct DNSRECORD *answers;
	struct DNSRECORD *authorities;
	struct DNSRECORD *additionals;
};

unsigned dns_extract_name(struct NetFrame *frame, const unsigned char *px, unsigned length, unsigned offset, char *name, unsigned sizeof_name)
{
	int recurse_count = 0;
	unsigned name_offset = 0;

	name[0] = '\0';

	while (offset < length) {
		if (px[offset] == 0x00) {
			break;
		} else if (px[offset] & 0xC0) {
			if (recurse_count > 100) {
				FRAMERR(frame, "dns: name: recursion exceeded %d\n", recurse_count);
				break;
			}
			recurse_count++;
			if (offset+2 > length) {
				FRAMERR(frame, "dns: name: not enough bytes\n");
				strcpy(name, "(err)");
				return 5;
			}
			offset = ex16be(px+offset)&0x3FF;
		} else {
			unsigned len = px[offset++];
			if (offset >= length) {
				FRAMERR(frame, "dns: name: not enough bytes\n");
				strcpy(name, "(err)");
				return 5;
			}
			if (offset+len > length) {
				FRAMERR(frame, "dns: name: not enough bytes\n");
				strcpy(name, "(err)");
				return 5;
			}

			if (name_offset > 0) {
				if (name_offset+1 >= sizeof_name) {
					FRAMERR(frame, "dns: name: too long\n");
					strcpy(name, "(err)");
					return 5;
				}
				name[name_offset++] = '.';
			}
			if (name_offset+len+1 >= sizeof_name) {
				FRAMERR(frame, "dns: name: too long\n");
				strcpy(name, "(err)");
				return 5;
			}
			memcpy(name+name_offset, px+offset, len);
			name_offset += len;
			name[name_offset] = '\0';
			offset += len;
		}
	}

	return name_offset;
}

static unsigned dns_resolve_alias(struct NetFrame *frame, const unsigned char *px, unsigned length, struct DNS *dns, const char *alias, int depth)
{
	unsigned i;

	for (i=dns->question_count; i<dns->record_count; i++) {
		struct DNSRECORD *rec = &dns->records[i];
		char name[256];
		unsigned name_length;

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

		if ((rec->type != 1 && rec->type != 5)|| rec->clss != 1)
			continue;

		if (stricmp(alias, name) == 0) {
			switch (rec->type) {
			case 1:
				return ex32be(px+rec->rdata_offset);
			case 5:
				name_length = dns_extract_name(frame, px, length, rec->rdata_offset, name, sizeof(name));
				if (depth > 10)
					FRAMERR(frame, "dns: too much recursion, alias=\"%s\"\n", alias);
				else
					return dns_resolve_alias(frame, px, length, dns, name, depth+1);
			}
		}
	}

	//FRAMERR(frame, "dns: could not resolve IP for alias=\"%s\"\n", alias);

	return 0;
}

static void translate_netbios_name(struct NetFrame *frame, const char *name, char *netbios_name, unsigned sizeof_netbios_name)
{
	unsigned j;
	unsigned k;

	sizeof_netbios_name;

	k=0;
	for (j=0; name[j] && name[j] != '.'; j++) {
		if (name[j] < 'A' || name[j] > 'A'+15)
			FRAMERR(frame, "netbios: bad netbios name char %c (0x%02x) \n", name[j], name[j]);
		netbios_name[k] = (char)((name[j]-'A')<<4);
		j++;
		if (name[j] < 'A' || name[j] > 'A'+15)
			FRAMERR(frame, "netbios: bad netbios name char %c (0x%02x) \n", name[j], name[j]);

		if (name[j] && name[j] != '.')
			netbios_name[k++] |= (char)((name[j]-'A')&0x0F);
	}

	/* handle trailing byte */
	if (k && !isprint(netbios_name[k])) {
		unsigned code = netbios_name[k];
		k--;

		while (k && isspace(netbios_name[k-1]))
			k--;
		netbios_name[k++] = '<';
		netbios_name[k++] = "0123456789ABCDEF"[(code>>4)&0x0f];
		netbios_name[k++] = "0123456789ABCDEF"[(code>>0)&0x0f];
		netbios_name[k++] = '>';
	}


	while (name[j] && k<sizeof_netbios_name-1)
		netbios_name[k++] = name[j++];
	netbios_name[k] = '\0';
}

static void cleanse_netbios_name(struct NetFrame *frame, const char *name, char *netbios_name, unsigned sizeof_netbios_name)
{
	unsigned j;
	unsigned k;

	frame;sizeof_netbios_name;

	k=0;
	for (j=0; j<16; j++) {
		netbios_name[k++] = name[j];
	}
	netbios_name[k] = '\0';

	/* handle trailing byte */
	if (k && !isprint(netbios_name[k-1])) {
		unsigned code = netbios_name[k-1];
		k--;

		while (k && isspace(netbios_name[k-1]))
			k--;
		netbios_name[k++] = '<';
		netbios_name[k++] = "0123456789ABCDEF"[(code>>4)&0x0f];
		netbios_name[k++] = "0123456789ABCDEF"[(code>>0)&0x0f];
		netbios_name[k++] = '>';
	}

	netbios_name[k] = '\0';
}

static void process_request_update(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length, struct DNS *dns)
{
	unsigned i;

	if (dns->additional_count == 0)
		FRAMERR(frame, "dns: corrupt\n");

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

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

		switch (rec->type) {
		case 0x0020: /*NETBIOS */
			switch (rec->clss) {
			case 0x0001: /*INTERNET*/
				{
					unsigned ip_address = ex32be(px+rec->rdata_offset);
					char netbios_name[256];

					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, netbios_name, sizeof(netbios_name));

					process_record(seap,
						"proto",	REC_SZ,			"NETBIOS",						-1,
						"op",		REC_SZ,			"register",			-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;

		default:
			FRAMERR(frame, "dns: unknown type=%d (class=%d, name=%s)\n", rec->type, rec->clss, name);
		}
	}
}

static void dns_dynamic_update(struct Seaper *seap, 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("DynDNS", "Prereq", REC_UNSIGNED, &x, sizeof(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);


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

					process_record(seap,
						"proto",	REC_SZ,			"NETBIOS",						-1,
						"op",		REC_SZ,			"register",			-1,
						"ip.src",	REC_FRAMESRC,	frame, -1,
						"name",		REC_PRINTABLE,	name,				strlen(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;

		}
	}
}

const unsigned char *find_mac(const unsigned char *px, unsigned length, unsigned offset, const unsigned char **r_name, unsigned *r_name_length)
{
	unsigned len;

	if (offset >= length)
		return 0;

	len = px[offset];
	if (len > 64)
		return 0;

	offset++;
	if (length > offset+len)
		length = offset+len;


	*r_name = px+offset;
	*r_name_length = 0;
	while (offset < length && px[offset] != '[') {
		(*r_name_length)++;
		offset++;
	}

	while (*r_name_length && isspace((*r_name)[(*r_name_length)-1]))
		(*r_name_length)--;

	if (offset +19  <= length && px[offset] == '[') {
		const unsigned char *result = px+offset;
		return result;
	}
	return 0;
}

static unsigned endsWith(const void *v_basestr, const void *v_pattern)
{
	const char *basestr = (const char *)v_basestr;
	const char *pattern = (const char *)v_pattern;
	unsigned base_length = strlen(basestr);
	unsigned pattern_length = strlen(pattern);

	if (base_length < pattern_length)
		return 0;
	return memcmp(basestr+base_length-pattern_length, pattern, pattern_length) == 0;

}

#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif

#define TYPECLASS(n,m) ((n)<<16|(m))

static void skip_name(const unsigned char *px, unsigned length, unsigned *r_offset)
{
	while (*r_offset < length) {
		if (0xC0 & px[*r_offset]) {
			(*r_offset) += 2;
			return;
		}
		if (0x00 == px[*r_offset]) {
			(*r_offset) += 1;
			return;
		}
		*r_offset += 1 + px[*r_offset];
	}
}
static void DECODEANSWER(struct Seaper *seap, struct NetFrame *frame, const unsigned char *px, unsigned length, struct DNS *dns, struct DNSRECORD *rec, const char *opcode)
{
	unsigned ip_address;
	char name[256];

⌨️ 快捷键说明

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