📄 spp_arpspoof.c
字号:
/* $Id$ *//*** Copyright (C) 2001-2004 Jeff Nathan <jeff@snort.org>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License Version 2 as** published by the Free Software Foundation. You may not use, modify or** distribute this program under any other version of the GNU General** Public License.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.** ** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* Snort ARPspoof Preprocessor Plugin * by Jeff Nathan <jeff@snort.org> * Version 0.1.4 * * Purpose: * * This preprocessor looks for anomalies in ARP traffic and attempts to * maliciously overwrite ARP cache information on hosts. * * Arguments: * * To check for unicast ARP requests use: * arpspoof: -unicast * * WARNING: this can generate false positives as Linux systems send unicast * ARP requests repetatively for entries in their cache. * * This plugin also takes a list of IP addresses and MAC address in the form: * arpspoof_detect_host: 10.10.10.10 29:a2:9a:29:a2:9a * arpspoof_detect_host: 192.168.40.1 f0:0f:00:f0:0f:00 * and so forth... * * Effect: * By comparing information in the Ethernet header to the ARP frame, obvious * anomalies are detected. Also, utilizing a user supplied list of IP * addresses and MAC addresses, ARP traffic appearing to have originated from * any IP in that list is carefully examined by comparing the source hardware * address to the user supplied hardware address. If there is a mismatch, an * alert is generated as either an ARP request or REPLY can be used to * overwrite cache information on a remote host. This should only be used for * hosts/devices on the **same layer 2 segment** !! * * Bugs: * This is a proof of concept ONLY. It is clearly not complete. Also, the * lookup function LookupIPMacEntryByIP is in need of optimization. The * arpspoof_detect_host functionality may false alarm in redundant environments. * Also, see the comment above pertaining to Linux systems. * * Thanks: * * First and foremost Patrick Mullen who sat beside me and helped every step of * the way. Andrew Baker for graciously supplying the tougher parts of this * code. W. Richard Stevens for readable documentation and finally * Marty for being a badass. All your packets are belong to Marty. * *//* I N C L U D E S ************************************************/#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#if !defined(WIN32) #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#elif defined(WIN32) #include <time.h>#endif#include "generators.h"#include "log.h"#include "detect.h"#include "decode.h"#include "event.h"#include "plugbase.h"#include "parser.h"#include "mstring.h"#include "debug.h"#include "util.h"#include "event_queue.h"#include "snort.h"#include "profiler.h"#undef inet_ntoa/* D E F I N E S **************************************************/#define MODNAME "spp_arpspoof"#define WITHUNICAST "-unicast"/* D A T A S T R U C T U R E S **********************************/typedef struct _IPMacEntry{ u_int32_t ipv4_addr; u_int8_t mac_addr[6]; u_int8_t pad[2];} IPMacEntry;typedef struct _IPMacEntryListNode{ IPMacEntry *ip_mac_entry; struct _IPMacEntryListNode *next;} IPMacEntryListNode;typedef struct _IPMacEntryList{ int size; IPMacEntryListNode *head; IPMacEntryListNode *tail;} IPMacEntryList;/* G L O B A L S **************************************************/int check_unicast_arp, check_overwrite;u_int8_t bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};static IPMacEntryList *ipmel = NULL;#ifdef PERF_PROFILINGPreprocStats arpPerfStats;#endif/* P R O T O T Y P E S ********************************************/void ARPspoofInit(char *args);void ARPspoofHostInit(char *args);void ParseARPspoofArgs(char *args);void ParseARPspoofHostArgs(char *args);void DetectARPattacks(Packet *p, void *context);void ARPspoofCleanExit(int signal, void *unused);void FreeIPMacEntryList(IPMacEntryList *ip_mac_entry_list);int AddIPMacEntryToList(IPMacEntryList *ip_mac_entry_list, IPMacEntry *ip_mac_entry);IPMacEntry *LookupIPMacEntryByIP(IPMacEntryList *ip_mac_entry_list, u_int32_t ipv4_addr);#if defined(DEBUG) void PrintIPMacEntryList(IPMacEntryList *ip_mac_entry_list);#endifvoid SetupARPspoof(void){ RegisterPreprocessor("arpspoof", ARPspoofInit); RegisterPreprocessor("arpspoof_detect_host", ARPspoofHostInit); DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Preprocessor: ARPspoof is setup...\n");); return;}void ARPspoofInit(char *args){ DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Preprocessor: ARPspoof Initialized\n");); /* Parse the arpspoof arguments from snort.conf */ ParseARPspoofArgs(args);#ifdef PERF_PROFILING RegisterPreprocessorProfile("arpspoof", &arpPerfStats, 0, &totalPerfStats);#endif /* Add arpspoof to the preprocessor function list */ AddFuncToPreprocList(DetectARPattacks, PRIORITY_NETWORK, PP_ARPSPOOF); /* Restart and CleanExit are identical */ AddFuncToPreprocCleanExitList(ARPspoofCleanExit, NULL, PRIORITY_LAST, PP_ARPSPOOF); AddFuncToPreprocRestartList(ARPspoofCleanExit, NULL, PRIORITY_LAST, PP_ARPSPOOF); return;}/** * Parse arguments passed to the arpspoof keyword. * * @param args preprocessor argument string * * @return void function */void ParseARPspoofArgs(char *args){ char **toks; int num_toks; int num; if (!args) return; toks = mSplit(args, " ", 2, &num_toks, '\\'); if (num_toks > 1) { FatalError(MODNAME ": ERROR: %s (%d) => ARPspoof configuration " "format: -unicast\n", file_name, file_line); } for (num = 0; num < num_toks; num++) { if (!strncasecmp(WITHUNICAST, toks[num], sizeof WITHUNICAST)) check_unicast_arp = 1; } mSplitFree(&toks, num_toks);}void ARPspoofHostInit(char *args){ DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Preprocessor: ARPspoof (overwrite list) Initialized\n");); if (ipmel == NULL) ipmel = (IPMacEntryList *)SnortAlloc(sizeof(IPMacEntryList)); /* Add MAC/IP pairs to ipmel */ ParseARPspoofHostArgs(args); if (check_overwrite == 0) check_overwrite = 1; return;}/** * Parse arguments passed to the arpspoof_detect_host keyword. * * @param args preprocessor argument string * * @return void function */void ParseARPspoofHostArgs(char *args){ char **toks; char **macbytes; int num_toks, num_macbytes; int i; struct in_addr IP_struct; IPMacEntry *ipme = NULL; if (ipmel == NULL) { FatalError("%s(%d) => Please activate arpspoof before trying to " "use arpspoof_detect_host\n", file_name, file_line); } toks = mSplit(args, " ", 2, &num_toks, '\\'); if (num_toks != 2) { FatalError("Arpspoof %s(%d) => Invalid arguments to " "arpspoof_detect_host\n", file_name, file_line); } /* Add entries */ ipme = (IPMacEntry *)SnortAlloc(sizeof(IPMacEntry)); if ((IP_struct.s_addr = inet_addr(toks[0])) == -1) { FatalError("Arpspoof %s(%d) => Invalid IP address as first argument of " "IP/MAC pair to arpspoof_detect_host\n", file_name, file_line); } ipme->ipv4_addr = (u_int32_t)IP_struct.s_addr; macbytes = mSplit(toks[1], ":", 6, &num_macbytes, '\\'); if (num_macbytes < 6) { FatalError("Arpspoof %s(%d) => Invalid MAC address as second " "argument of IP/MAC pair to arpspoof_detect_host\n", file_name, file_line); } else { for (i = 0; i < 6; i++) ipme->mac_addr[i] = (u_int8_t) strtoul(macbytes[i], NULL, 16); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -