簡體   English   中英

使用 python scapy 發送 DHCP 發現

[英]Sending DHCP Discover using python scapy

我是 python 新手,正在學習一些網絡編程,我希望通過我的 Tap 接口向我的 DHCP 服務器發送一個 DHCP 數據包,並期待它的一些響應。 我嘗試了幾種數據包構建技術,例如 structs 和 ctypes,最終使用了 scapy。 在這里,我能夠發送 DHCP 數據包,但無法從 DHCP 服務器獲得任何響應(使用wireshark 和 tcpdump 分析)。我的數據包看起來與原始 DHCP 數據包相同,但無法獲得響應。 這是我的代碼

import socket
from scapy.all import *

def main():

 if len(sys.argv)<3:
   print " fewer arguments."
   sys.exit(1)
 else:
   tap_interface = sys.argv[1]
   src_mac_address = sys.argv[2]

 ethernet = Ether(dst='ff:ff:ff:ff:ff:ff',src=src_mac_address,type=0x800)
 ip = IP(src ='0.0.0.0',dst='255.255.255.255')
 udp =UDP (sport=68,dport=67)
 fam,hw = get_if_raw_hwaddr(tap_interface)
 bootp = BOOTP(chaddr = hw, ciaddr = '0.0.0.0',xid =  0x01020304,flags= 1)
 dhcp = DHCP(options=[("message-type","discover"),"end"])
 packet = ethernet / ip / udp / bootp / dhcp

 fd = open('/dev/net/tun','r+')
 TUNSETIFF = 0x400454ca
 IFF_TAP = 0x0002
 IFF_NO_PI = 0x1000
 mode = IFF_TAP | IFF_NO_PI
 ifr = struct.pack('16sH', tap_interface, IFF_TAP | IFF_NO_PI)
 fcntl.ioctl(fd,TUNSETIFF,ifr)


 while True:
    sendp(packet, iface = tap_interface)
    time.sleep(10)


 if __name__ == '__main__':
     main()

有沒有其他方法可以實現這一目標? 如果是這樣,請也提及它們。 提前致謝。

解決了 ! 我有同樣的問題,

我認為問題出在 srp() 函數上,它無法在端口 68 上接收數據包,但是我創建了一個新函數,該函數帶有一個新線程,用於嗅探 BOOTP 消息並顯示數據包字段。 你可以模擬它:

嗅探(iface=myiface,過濾器=“端口 68 和端口 67”)

然后使用 srp() 或 sendp() func 發送數據包:)

注意:我使用了多線程機制,因為如果網絡上有流氓 DHCP 服務器,我的程序會發送消息和嗅探

我不確定這是否有資格作為答案,但我們使用 scapy 來模擬 DHCP 服務器/客戶端交換,以下為我們完成了這項工作:

discover = Ether(dst='ff:ff:ff:ff:ff:ff', src=cliMAC, type=0x0800) / IP(src='0.0.0.0', dst='255.255.255.255') / UDP(dport=67,sport=68) / BOOTP(op=1, chaddr=cliMACchaddr) / DHCP(options=[('message-type','discover'), ('end')])

我的代碼和你的代碼之間的主要區別似乎是如何定義 BOOTP 標頭。 也許你可以試試我的數據包定義,看看它是否有效?

這是我所做的一個示例,它獲取一個 dhcp 地址並將其分配給一個 ip 接口:

我的粗略 POC,同時為我的項目創建代碼:

 #!/usr/bin/python

    from scapy.all import Ether,IP,UDP,DHCP,BOOTP,get_if_raw_hwaddr,get_if_hwaddr,conf,sniff,sendp
    from pyroute2 import IPDB
    from Queue import Empty
    from multiprocessing import Process, Queue, Manager
    from wpa_supplicant.core import WpaSupplicantDriver
    from twisted.internet.selectreactor import SelectReactor
    import threading
    import time
    import errno
    import sys
    import types
    import netifaces
    import dbus
    import json 
    import re

    class PythonDHCPScanner:

        def change_ip(self,ipObject,netInterface):
            ipdb = IPDB()
            ips= ipdb.interfaces[self.get_interface(netInterface)]
            ipAddrs = ips.ipaddr.ipv4[0]
            ips.del_ip(ipAddrs['address'],ipAddrs['prefixlen'])
            ips.add_ip(ipObject['ipAddr'],24)
            ipdb.commit()
            ipdb.routes.add(dst="default",gateway=ipObject['router'])
            ipdb.commit()


        def queue_get_all(self):
            items = []
            maxItems = 50
            for numOfItemsRetrieved in range(0, maxItems):
               try:
                   items.append(self.q.get_nowait())
               except Empty, e:
                   break
            return items

        def __init__(self):
            self.net_iface = netifaces.interfaces()

        def dhcp_print(self,pkt):
            self.q.put(str(pkt))

        def get_interface(self,number):
            return str(self.net_iface[number].decode())

        def get_interfaces(self):
            return self.net_iface

        def get_dhcp_object(self,interfaceNumber):
            self.q = Manager().Queue()
            c = Process(target=self.callSniffer,args=(interfaceNumber,)).start()
            time.sleep(0.1)
            p = Process(target=self.callPacket(interfaceNumber)).start()
            time.sleep(5)
            if c is not None:
                c.join()
            dhcp = {}
            for strPkt in self.queue_get_all():
                try:
                    pkt = Ether(strPkt)
                    pkt.show()
                    if pkt[Ether].dst == get_if_hwaddr(self.get_interface(interfaceNumber)):
                        if pkt[DHCP]:
                            if pkt.getlayer(DHCP).fields['options'][0][1] == 2:
                                 if pkt[IP]:
                                     dhcp['ipAddr'] = pkt[IP].dst
                                 for option in pkt.getlayer(DHCP).fields['options']:
                                     if option == 'end':
                                        break
                                     dhcp[option[0]] = option[1]
                                 print dhcp['router']
                                 print dhcp['subnet_mask']
                                 break
                except:
                        continue
            return dhcp

        def callSniffer(self,interfaceNumber):
            inter = self.get_interface(interfaceNumber)
            conf.iface = inter
            print inter
            sniff(iface=inter,filter="udp",prn=self.dhcp_print, timeout=10)

        def callPacket(self,interfaceNumber):
            inter = self.get_interface(interfaceNumber) 
            print inter
            fam,hw = get_if_raw_hwaddr(inter)
            macaddress= get_if_hwaddr(inter)
            conf.iface = inter
            ethernet = Ether(dst="ff:ff:ff:ff:ff:ff",src=macaddress,type=0x800)
            ip = IP(src="0.0.0.0",dst="255.255.255.255")
            udp = UDP(sport=68,dport=67)
            bootp = BOOTP(chaddr =hw,xid=0x10000000)
            dhcp = DHCP(options=[("message-type","discover"),("end")])
            packet=ethernet/ip/udp/bootp/dhcp
            sendp(packet,iface=inter)

    # get dhcp object

    dave  = PythonDHCPScanner()
    dhcpObject = dave.get_dhcp_object(3)

 # Pick interface number 3 on my box

    time.sleep(1)
    for dhcpKey in dhcpObject.keys():
        print str(dhcpKey) + ":" + str(dhcpObject[dhcpKey])
    time.sleep(1)
    dave.change_ip(dhcpObject,3)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM