Sending DHCP Discover using python scapy

吃可爱长大的小学妹 提交于 2019-12-03 00:28:32

Solved ! I had the same problem,

The problem I think was on the srp() function, it can't receive packets on port 68, but I've created a new function with a new thread that sniffs BOOTP messages and displays the packet fields. you can simulate it :

sniff(iface=myiface, filter="port 68 and port 67")

then send the packet using srp() or sendp() func :)

NOTE: I have used multithreading mechanism cause my program sends messages and sniffs if a rogue DHCP Server is on the network

I am not sure if this would qualify as an answer, but we use scapy to simulate DHCP server/client exchange, and the following does the job for us:

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')])

The main difference between my code and yours seem to be how the BOOTP header is defined. Maybe you could try my packet definition and see if it works?

Here is an example that I did that gets a dhcp address and assigns it to an ip interface:

My rough POC, while creating code for my project:

 #!/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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!