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

📄 hunt.c

📁 linux或unix下回话劫持工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *	This is free software. You can redistribute it and/or modify under *	the terms of the GNU General Public License version 2. * * 	Copyright (C) 1998 by kra * */#include "hunt.h"#include <sys/types.h>#include <sys/time.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <unistd.h>#include <assert.h> /* * dont fragment with reset ??? */int linksock = -1;int mac_learn_from_ip = 0;int conn_list_mac = 0;int conn_list_seq = 0;struct hash conn_table;struct hash mac_table;int hunt_ready = 0;pthread_mutex_t mutex_hunt_ready = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond_hunt_ready = PTHREAD_COND_INITIALIZER;/* * list of struct packet_info with information which packets skip in process * of updating connection */struct list l_skip_update = LIST_INIT(struct packet_info, next);/* * lists of functions which pass packets to modules */struct list l_ifunc_ip = LIST_INIT(struct ifunc_item, next_ip);struct list l_ifunc_tcp = LIST_INIT(struct ifunc_item, next_tcp);struct list l_ifunc_udp = LIST_INIT(struct ifunc_item, next_udp);struct list l_ifunc_icmp = LIST_INIT(struct ifunc_item, next_icmp);struct list l_ifunc_arp = LIST_INIT(struct ifunc_item, next_arp);struct list l_ifunc_fast_tcp = LIST_INIT(struct ifunc_item, next_tcp);/* *  * packet operations *  */static struct list l_packets = LIST_INIT(struct packet, p_next_free);int packets_allocated = 0;struct packet *packet_new(void){	struct packet *p;	if (!(p = list_pop(&l_packets))) {		if (!(p = malloc(sizeof(struct packet)))) {			perror("malloc");			return NULL;		}		pthread_mutex_init(&p->p_mutex, NULL);		p->p_use_count = 0;		p->p_hdr.p_tcph = NULL;		p->p_data = NULL;		p->p_type = PACKET_NONE;		p->p_ipc = 0;		p->p_ipc_arg = NULL;				packets_allocated++;	}	p->p_use_count = 1;	return p;}void packet_copy_data(struct packet *dst, struct packet *src){	memcpy(dst->p_raw, src->p_raw, src->p_raw_len);	dst->p_raw_len = src->p_raw_len;	dst->p_type = src->p_type;	dst->p_ethh = (struct ethhdr *)(dst->p_raw + 				((char *)src->p_ethh - src->p_raw));	dst->p_iph = (struct iphdr *)(dst->p_raw +				((char *)src->p_iph - src->p_raw));	dst->p_arph = (struct arphdr *)(dst->p_raw +				((char *)src->p_arph - src->p_raw));	dst->p_hdr.p_tcph = (struct tcphdr *)(dst->p_raw +				((char *)src->p_hdr.p_tcph - src->p_raw));	dst->p_data_len = src->p_data_len;	dst->p_data = dst->p_raw + (src->p_data - src->p_raw);	memcpy(dst->p_arg, src->p_arg, sizeof(src->p_arg));	dst->p_ipc = src->p_ipc;	dst->p_ipc_arg = src->p_ipc_arg;}void packet_free(struct packet *p){	int is_free;		pthread_mutex_lock(&p->p_mutex);	if (--p->p_use_count == 0)		is_free = 1;	else		is_free = 0;	pthread_mutex_unlock(&p->p_mutex);	if (is_free)		list_push(&l_packets, p);}void packet_want(struct packet *p){	pthread_mutex_lock(&p->p_mutex);	++p->p_use_count;	pthread_mutex_unlock(&p->p_mutex);}void packet_flush(struct list *l){	struct packet *p;		while ((p = list_pop(l)))		packet_free(p);}void packet_preallocate(int count){	struct packet **p = alloca(count * sizeof(struct packet *));	int i;		for (i = 0; i < count; i++)		p[i] = packet_new();	for (i = 0; i < count; i++)		packet_free(p[i]);}int packet_count(void){	return list_count(&l_packets);}/* *  * TCP connection database *  */static inline void fill_uci(struct user_conn_info *uci, struct packet *p){	uci->src_addr = p->p_iph->saddr;	uci->dst_addr = p->p_iph->daddr;	uci->src_port = p->p_hdr.p_tcph->source;	uci->dst_port = p->p_hdr.p_tcph->dest;}#if 0static int ht_eq(unsigned int key, struct conn_info *c,		 struct packet *p){	if (c->src_addr == p->p_iph->saddr && 	    c->dst_addr == p->p_iph->daddr &&	    c->src_port == p->p_hdr.p_tcph->source && 	    c->dst_port == p->p_hdr.p_tcph->dest)		return 1;	if (c->src_addr == p->p_iph->daddr && 	    c->dst_addr == p->p_iph->saddr &&	    c->src_port == p->p_hdr.p_tcph->dest && 	    c->dst_port == p->p_hdr.p_tcph->source)		return 1;	return 0;}#endifstatic int ht_eq(unsigned int key, struct conn_info *c,		 struct user_conn_info *uci){	if (c->src_addr == uci->src_addr && 	    c->dst_addr == uci->dst_addr &&	    c->src_port == uci->src_port && 	    c->dst_port == uci->dst_port)		return 1;	if (c->src_addr == uci->dst_addr && 	    c->dst_addr == uci->src_addr &&	    c->src_port == uci->dst_port && 	    c->dst_port == uci->src_port)		return 1;	return 0;}void remove_conn_if_dont_match(void){	struct hash_iterator hi;	struct conn_info *ci;	unsigned int key;	int count_to_remove = 0;	unsigned int *key_to_remove;	struct conn_info **ci_to_remove;		hash_lock(&conn_table);	count_to_remove = 0;	key_to_remove = alloca(sizeof(unsigned int) * hash_count(&conn_table));	ci_to_remove = alloca(sizeof(struct conn_info *) * hash_count(&conn_table));	hash_iter_set(&hi, &conn_table);	while ((ci = hash_iter_get(&hi, &key))) {		if (!conn_add_match(ci->src_addr, ci->dst_addr, ci->src_port, ci->dst_port)) {			ci_to_remove[count_to_remove] = ci;			key_to_remove[count_to_remove++] = key;		}	}	hash_iter_end(&hi);	for ( ; count_to_remove >= 0; count_to_remove--)		hash_remove(&conn_table, key_to_remove[count_to_remove],			    ci_to_remove[count_to_remove]);	hash_unlock(&conn_table);}void conn_free(struct conn_info *ci){	int free_it;		pthread_mutex_lock(&ci->mutex);	if (--ci->use_count == 0)		free_it = 1;	else		free_it = 0;	pthread_mutex_unlock(&ci->mutex);	if (free_it)		free(ci);}struct conn_info *conn_get(struct user_conn_info *uci){	unsigned int key;	struct conn_info *ci;		key = uci_generate_key(uci);	hash_lock(&conn_table);	if ((ci = hash_get(&conn_table, key, uci))) {		pthread_mutex_lock(&ci->mutex);		++ci->use_count;		pthread_mutex_unlock(&ci->mutex);	}	hash_unlock(&conn_table);	return ci;}int conn_exist(struct user_conn_info *uci){	unsigned int key;	struct conn_info *ci;		key = uci_generate_key(uci);	if ((ci = hash_get(&conn_table, key, uci)))		return 1;	else		return 0;}static int packet_match(struct packet_info *pi, struct packet *p){	struct iphdr *iph = p->p_iph;	struct tcphdr *tcph = p->p_hdr.p_tcph;		if (pi->src_addr == iph->saddr &&	    pi->dst_addr == iph->daddr &&	    pi->src_port == tcph->source &&	    pi->dst_port == tcph->dest &&	    pi->src.next_seq == tcph->seq &&	    pi->src.next_d_seq == tcph->ack_seq &&	    memcmp(pi->src.src_mac, p->p_ethh->h_source, ETH_ALEN) == 0 &&	    memcmp(pi->src.dst_mac, p->p_ethh->h_dest, ETH_ALEN) == 0)		return 1;	else		return 0;}static int conn_skip_update(struct conn_info *ci, struct packet *p){	struct list_iterator iter;	struct packet_info *pi;		list_iter_set(&iter, &l_skip_update);	while ((pi = list_iter_get(&iter))) {		if (packet_match(pi, p)) {			list_iter_end(&iter);			list_remove(&l_skip_update, pi);			return 1;		}	}	list_iter_end(&iter);	return 0;}static void __conn_add(struct packet *p, unsigned int key){	struct iphdr *iph = p->p_iph;	struct tcphdr *tcph = p->p_hdr.p_tcph;	struct conn_info *ci;	struct host_info *h_src, *h_dst;		assert(ci = malloc(sizeof(struct conn_info)));	memset(ci, 0, sizeof(struct conn_info));	ci->use_count = 1;	pthread_mutex_init(&ci->mutex, NULL);		if (ntohs(tcph->dest) >= 1024 && ntohs(tcph->source) < 1024) {		ci->src_addr = iph->daddr;		ci->dst_addr = iph->saddr;		ci->src_port = tcph->dest;		ci->dst_port = tcph->source;		h_src = &ci->dst;		h_dst = &ci->src;	} else {		ci->src_addr = iph->saddr;		ci->dst_addr = iph->daddr;		ci->src_port = tcph->source;		ci->dst_port = tcph->dest;				h_src = &ci->src;		h_dst = &ci->dst;	}	h_src->next_seq = htonl(ntohl(tcph->seq) + p->p_data_len +				tcph->syn ? 1 : 0);	if (tcph->ack)		h_src->next_d_seq = tcph->ack_seq;	h_src->window = tcph->window;	h_src->id = iph->id;	memcpy(h_src->dst_mac, p->p_ethh->h_dest, ETH_ALEN);	memcpy(h_src->src_mac, p->p_ethh->h_source, ETH_ALEN);	/* guess or try to fill h_dst too */	h_dst->next_seq = h_src->next_d_seq;	h_dst->next_d_seq = h_src->next_seq;	h_dst->window = tcph->window;	h_dst->id = iph->id;	memcpy(h_dst->dst_mac, h_src->src_mac, ETH_ALEN);	memcpy(h_dst->src_mac, h_src->dst_mac, ETH_ALEN);		hash_put(&conn_table, key, ci);}static void ack_storm_notify(struct conn_info *ci, struct user_conn_info *uci){	struct timeval tv;	int print_it = 0;		if (!ci->ack_storm_notify_sec) {		gettimeofday(&tv, NULL);		print_it = 1;	} else {		gettimeofday(&tv, NULL);		if (tv.tv_sec - ci->ack_storm_notify_sec >= 10)			print_it = 1;	}	if (print_it) {		set_tty_color(COLOR_BRIGHTRED);		printf("\nhunt: possible ACK storm: ");		print_user_conn_info(uci, 1);		set_tty_color(COLOR_LIGHTGRAY);		ci->ack_storm_notify_sec = tv.tv_sec;	}}static void conn_add_update(struct packet *p){	static struct user_conn_info last_toadd = {0, 0, 0, 0};	static last_count = 0;	unsigned int key;	struct conn_info *ci;	struct user_conn_info uci;	unsigned int old_next_d_seq;		fill_uci(&uci, p);	key = uci_generate_key(&uci);		hash_lock(&conn_table);	if ((ci = hash_get(&conn_table, key, &uci)) && 	    ht_eq(key, ci, &uci) == 1) {		if (!conn_skip_update(ci, p)) {			struct host_info *h_src, *h_dst;			struct iphdr *iph = p->p_iph;			struct tcphdr *tcph = p->p_hdr.p_tcph;						if (ci->src_addr == iph->saddr &&			    ci->dst_addr == iph->daddr &&			    ci->src_port == tcph->source && 			    ci->dst_port == tcph->dest) {				h_src = &ci->src;				h_dst = &ci->dst;			} else {				h_src = &ci->dst;				h_dst = &ci->src;			}			old_next_d_seq = h_src->next_d_seq;						h_src->next_seq = htonl(ntohl(tcph->seq) + 						p->p_data_len);			if (tcph->ack)				h_src->next_d_seq = tcph->ack_seq;			h_src->id = iph->id;	/* well, this should be in IP updater not in TCP */			h_src->window = tcph->window;			/* well these can change too :-) */			memcpy(h_src->dst_mac, p->p_ethh->h_dest, ETH_ALEN);			memcpy(h_src->src_mac, p->p_ethh->h_source, ETH_ALEN);			/*			 * ACK storm detection			 */			h_src->delta_d_seq += ntohl(h_src->next_d_seq) - 						ntohl(old_next_d_seq);			if (++ci->update_count % 400 == 0) {				if (ci->src.delta_d_seq == 0 &&				    ci->dst.delta_d_seq == 0) {					ack_storm_notify(ci, &uci);				} else {					ci->src.delta_d_seq = 0;					ci->dst.delta_d_seq = 0;				}			}		}	} else {		 /* test if we could add the connection */		if (p->p_data_len > 0) {			/*			 * well, it contains data - add it			 */			if (conn_add_policy(p->p_iph, p->p_hdr.p_tcph))				__conn_add(p, key);		} else {			/*			 * well, check it this way because we don't want			 * to add RST, ACK to FIN, ... as connectinos.			 */			if ((last_toadd.src_addr == p->p_iph->saddr &&			    last_toadd.dst_addr == p->p_iph->daddr &&			    last_toadd.src_port == p->p_hdr.p_tcph->source &&			    last_toadd.dst_port == p->p_hdr.p_tcph->dest) ||			    (last_toadd.src_addr == p->p_iph->daddr &&			    last_toadd.dst_addr == p->p_iph->saddr &&			    last_toadd.src_port == p->p_hdr.p_tcph->dest &&			    last_toadd.dst_port == p->p_hdr.p_tcph->source)) {				if (++last_count >= 10) {					last_count = 0;					if (conn_add_policy(p->p_iph, p->p_hdr.p_tcph))						__conn_add(p, key);				}			} else {				last_count = 0;				last_toadd.src_addr = p->p_iph->saddr;				last_toadd.dst_addr = p->p_iph->daddr;				last_toadd.src_port = p->p_hdr.p_tcph->source;				last_toadd.dst_port = p->p_hdr.p_tcph->dest;			}		}	}	hash_unlock(&conn_table);}static void conn_del(struct packet *p){	struct conn_info *ci;	struct user_conn_info uci;	unsigned int key;	int remove_it = 0;#if 0	fill_uci(&uci, p);	key = uci_generate_key(&uci);	if ((ci = hash_remove(&conn_table, key, &uci))) {		conn_free(ci);	}#endif	fill_uci(&uci, p);	key = uci_generate_key(&uci);	hash_lock(&conn_table);	if ((ci = hash_get(&conn_table, key, &uci)) && 	    ht_eq(key, ci, &uci) == 1) {

⌨️ 快捷键说明

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