import os
import sys
import time
import socket
import struct
import fcntl
import argparse
import threading

# 定义常量
ETH_P_ALL = 0x0003
ETH_HEADER_LEN = 14
ARP_HEADER_LEN = 28
ARP_REQUEST = 1
ARP_REPLY = 2

# 定义全局变量
ip_mac_dict = {}
attack_dict = {}

# 获取本机IP地址
def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15].encode())
    )[20:24])

# 获取本机MAC地址
def get_mac_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15].encode()))
    return ':'.join(['%02x' % b for b in info[18:24]])

# 发送ARP请求
def send_arp_request(ifname, src_ip, src_mac, dst_ip):
    s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
    s.bind((ifname, ETH_P_ALL))
    src_mac_bytes = bytes.fromhex(src_mac.replace(':', ''))
    src_ip_bytes = socket.inet_aton(src_ip)
    dst_ip_bytes = socket.inet_aton(dst_ip)
    eth_header = struct.pack('!6s6sH', b'\xff\xff\xff\xff\xff\xff', src_mac_bytes, ETH_P_ALL)
    arp_header = struct.pack('!HHBBH6s4s6s4s', 0x0001, 0x0800, 6, 4, ARP_REQUEST, src_mac_bytes, src_ip_bytes, b'\x00\x00\x00\x00\x00\x00', dst_ip_bytes)
    packet = eth_header + arp_header
    s.send(packet)

# 发送ARP响应
def send_arp_reply(ifname, src_ip, src_mac, dst_ip, dst_mac):
    s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
    s.bind((ifname, ETH_P_ALL))
    src_mac_bytes = bytes.fromhex(src_mac.replace(':', ''))
    src_ip_bytes = socket.inet_aton(src_ip)
    dst_mac_bytes = bytes.fromhex(dst_mac.replace(':', ''))
    dst_ip_bytes = socket.inet_aton(dst_ip)
    eth_header = struct.pack('!6s6sH', dst_mac_bytes, src_mac_bytes, ETH_P_ALL)
    arp_header = struct.pack('!HHBBH6s4s6s4s', 0x0001, 0x0800, 6, 4, ARP_REPLY, src_mac_bytes, src_ip_bytes, dst_mac_bytes, dst_ip_bytes)
    packet = eth_header + arp_header
    s.send(packet)

# 处理ARP请求
def handle_arp_request(packet):
    eth_header = packet[:ETH_HEADER_LEN]
    arp_header = packet[ETH_HEADER_LEN:ETH_HEADER_LEN+ARP_HEADER_LEN]
    src_mac = ':'.join(['%02x' % b for b in eth_header[6:12]])
    src_ip = socket.inet_ntoa(arp_header[8:12])
    dst_ip = socket.inet_ntoa(arp_header[20:24])
    send_arp_reply(ifname, dst_ip, my_mac, src_ip, src_mac)

# 处理ARP响应
def handle_arp_reply(packet):
    eth_header = packet[:ETH_HEADER_LEN]
    arp_header = packet[ETH_HEADER_LEN:ETH_HEADER_LEN+ARP_HEADER_LEN]
    src_mac = ':'.join(['%02x' % b for b in eth_header[6:12]])
    src_ip = socket.inet_ntoa(arp_header[8:12])
    dst_mac = ':'.join(['%02x' % b for b in arp_header[18:24]])
    dst_ip = socket.inet_ntoa(arp_header[20:24])
    ip_mac_dict[src_ip] = src_mac
    ip_mac_dict[dst_ip] = dst_mac

# 处理ARP数据包
def handle_arp_packet(packet):
    eth_header = packet[:ETH_HEADER_LEN]
    eth_type = struct.unpack('!H', eth_header[12:14])[0]
    if eth_type == 0x0806:
        arp_op = struct.unpack('!H', packet[ETH_HEADER_LEN+6:ETH_HEADER_LEN+8])[0]
        if arp_op == ARP_REQUEST:
            handle_arp_request(packet)
        elif arp_op == ARP_REPLY:
            handle_arp_reply(packet)

# 监听ARP数据包
def listen_arp_packets(ifname):
    s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ETH_P_ALL))
    s.bind((ifname, ETH_P_ALL))
    while True:
        packet = s.recv(2048)
        handle_arp_packet(packet)

# 检测ARP欺骗攻击
def detect_arp_spoofing(ifname, interval):
    while True:
        for ip, mac in ip_mac_dict.items():
            if ip != my_ip and mac != my_mac:
                if ip in attack_dict:
                    attack_dict[ip] += 1
                else:
                    attack_dict[ip] = 1
                if attack_dict[ip] > 10:
                    print('检测到ARP欺骗攻击,攻击者IP地址:', ip, '攻击者MAC地址:', mac)
                    attack_dict[ip] = 0
        time.sleep(interval)

# 主函数
if __name__ == '__main__':
    # 解析命令行参数
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--interface', dest='ifname', required=True, help='network interface name')
    parser.add_argument('-t', '--interval', dest='interval', type=int, default=5, help='detection interval')
    args = parser.parse_args()

    # 获取本机IP地址和MAC地址
    my_ip = get_ip_address(args.ifname)
    my_mac = get_mac_address(args.ifname)
    ifname = args.ifname # 定义ifname

    # 启动ARP监听线程和ARP欺骗检测线程
    arp_listen_thread = threading.Thread(target=listen_arp_packets, args=(ifname,))
    arp_detect_thread = threading.Thread(target=detect_arp_spoofing, args=(ifname, args.interval))
    arp_listen_thread.start()
    arp_detect_thread.start()

如何解决'unresolved reference ifname'的问题

在代码中,'ifname'是一个变量,需要先定义或从外部传入才能使用。 在这段代码中,'ifname' 应该从命令行参数中获取。

解决方法是在主函数中定义 'ifname' 变量,并将其传递给需要使用的函数。

    # ...

    # 主函数
if __name__ == '__main__':
    # 解析命令行参数
    # ...
    args = parser.parse_args()

    # 获取本机IP地址和MAC地址
    # ...
    
    # 定义ifname
    ifname = args.ifname 
    
    # 启动ARP监听线程和ARP欺骗检测线程
    # ...

通过以上修改,代码就能正确获取命令行参数中指定的网络接口名,并将其传递给相关函数使用,从而解决 'unresolved reference ifname' 的问题。

Python实现ARP欺骗攻击检测

原文地址: http://www.cveoy.top/t/topic/jnKu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录