diff --git a/README.md b/README.md
index 6907b97..e4e8580 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# DHCPEyes :eyes:
**Intercept requests passively of DHCP from own network!**
-
@@ -9,14 +9,14 @@ alt="DemoImage"
# Authors
- **Vincenzo Gianfelice**
- **Contact**: _developer.vincenzog@gmail.com_
-- **BTC** (**donation**): *3EwV4zt9r5o4aTHyqjcM6CfqSVirSEmN6y*
+- **BTC**(donation): *3EwV4zt9r5o4aTHyqjcM6CfqSVirSEmN6y*
# Prerequisites
Require **python2.7** (also **python3.5**)
- scapy >= 2.4.4
- termcolor
-- colorama (if use on **windows**)
+- colorama (if you use **windows**)
###### Windows
- First, install [WinPcap](https://www.winpcap.org/install/)
@@ -55,6 +55,7 @@ Optional:
```
./dhcpeyes.py -i wlan0 -t DHCPR # Intercept only DHCPREQUEST on wlan0
./dhcpeyes.py -t DHCPI -i wlan0 -t DHCPD # Intercept DHCPINFORM and DHCPDISCOVER
+./dhcpeyes.py -i wlan0 # Intercept all
```
###### Windows
diff --git a/dhcpeyes.py b/dhcpeyes.py
index 690b862..6e69eb2 100755
--- a/dhcpeyes.py
+++ b/dhcpeyes.py
@@ -5,190 +5,194 @@
import time
import os
from termcolor import colored
-from scapy.all import Ether,DHCP,IP,sniff
+from scapy.all import Ether, DHCP, IP, sniff
if (os.name == 'nt'):
- import colorama
- colorama.init()
-
-## Variabili costanti
-VERSION='v1.2'
-
-## DHCP Message Type - RFC2132/Page-4 (https://tools.ietf.org/html/rfc2132#page-4) ##
-## Per il momento, non verranno utilizzate tutti i "tipi", dato che il client, una volta stabilito il server di destinazione DHCP,
-## invia direttamente i pacchetti a quest'ultimo (e non in broadcast), rendendo inefficace l intercettazione
-## in modo passivo.
-## Presto verra' aggiunta la possibilita' di intercettare le richieste/risposte tra il client/server (MITM)
-## Stay Tuned! ;)
-DHCPDISCOVER=1 #Used
-DHCPOFFER=2 #No
-DHCPREQUEST=3 #Used
-DHCPDECLINE=4 #No
-DHCPACK=5 #No
-DHCPNAK=6 #Used
-DHCPRELEASE=7 #No
-DHCPINFORM=8 #Used
-
-## DHCPOptions of Scapy
-## (https://github.com/secdev/scapy/blob/master/scapy/layers/dhcp.py)
-## `at line 112`. Actual version of scapy is 2.4.4.
-MESSAGE_DHCP='message-type'
-ERROR_MESSAGE='error_message'
-REQUEST_ADDRESS='requested_addr'
-ADDRESS_SERVER_DHCP='server_id'
-VENDOR='vendor_class_id'
-HOSTNAME='hostname'
-
-## Variabili globali per lo script
-REQUESTED=list()
+ import colorama
+ colorama.init()
+
+# Variabili costanti
+VERSION = 'v1.2'
+
+# DHCP Message Type - RFC2132/Page-4 (https://tools.ietf.org/html/rfc2132#page-4) ##
+# Per il momento, non verranno utilizzate tutti i "tipi", dato che il client, una volta stabilito il server di destinazione DHCP,
+# invia direttamente i pacchetti a quest'ultimo (e non in broadcast), rendendo inefficace l intercettazione
+# in modo passivo.
+# Presto verra' aggiunta la possibilita' di intercettare le richieste/risposte tra il client/server (MITM)
+# Stay Tuned! ;)
+DHCPDISCOVER = 1 # Used
+DHCPOFFER = 2 # No
+DHCPREQUEST = 3 # Used
+DHCPDECLINE = 4 # No
+DHCPACK = 5 # No
+DHCPNAK = 6 # Used
+DHCPRELEASE = 7 # No
+DHCPINFORM = 8 # Used
+
+# DHCPOptions of Scapy
+# (https://github.com/secdev/scapy/blob/master/scapy/layers/dhcp.py)
+# `at line 112`. Actual version of scapy is 2.4.4.
+MESSAGE_DHCP = 'message-type'
+ERROR_MESSAGE = 'error_message'
+REQUEST_ADDRESS = 'requested_addr'
+ADDRESS_SERVER_DHCP = 'server_id'
+VENDOR = 'vendor_class_id'
+HOSTNAME = 'hostname'
+
+# Variabili globali per lo script
+REQUESTED = list() # Dispositivi totali connessi alla rete (tramite DHCP)
+TOT_DEVICES = list() # Dispositivi totali catturati
def logo():
- LOGO='ICAgIF9fX18gIF9fICBfX19fX19fX19fX18gIF9fX19fXyAgICAgICAgICAgICAgIAogICAvIF9fIFwvIC8gLyAvIF9fX18vIF9fIFwvIF9fX18vXyAgX19fX18gIF9fX19fCiAgLyAvIC8gLyAvXy8gLyAvICAgLyAvXy8gLyBfXy8gLyAvIC8gLyBfIFwvIF9fXy8KIC8gL18vIC8gX18gIC8gL19fXy8gX19fXy8gL19fXy8gL18vIC8gIF9fKF9fICApIAovX19fX18vXy8gL18vXF9fX18vXy8gICAvX19fX18vXF9fLCAvXF9fXy9fX19fLyAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9fX19fLyAgICAgICAgICAgICAK'
+ LOGO = 'ICAgIF9fX18gIF9fICBfX19fX19fX19fX18gIF9fX19fXyAgICAgICAgICAgICAgIAogICAvIF9fIFwvIC8gLyAvIF9fX18vIF9fIFwvIF9fX18vXyAgX19fX18gIF9fX19fCiAgLyAvIC8gLyAvXy8gLyAvICAgLyAvXy8gLyBfXy8gLyAvIC8gLyBfIFwvIF9fXy8KIC8gL18vIC8gX18gIC8gL19fXy8gX19fXy8gL19fXy8gL18vIC8gIF9fKF9fICApIAovX19fX18vXy8gL18vXF9fX18vXy8gICAvX19fX18vXF9fLCAvXF9fXy9fX19fLyAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC9fX19fLyAgICAgICAgICAgICAK'
- print(base64.b64decode(LOGO).decode('ascii'))
- print('\t* Passive DHCP Listener! ('+VERSION+') *')
- print('')
+ print(base64.b64decode(LOGO).decode('ascii'))
+ print('\t* Passive DHCP Listener! ('+VERSION+') *')
+ print('')
def help():
- print('Usage: {} -i '.format(sys.argv[0]))
- print('')
- print(' -i Interface for listening')
- print('Optional:')
- print(' -o File Output Save')
- print(' -t Options types: DHCPD (discover)')
- print(' DHCPR (request)')
- print(' DHCPN (nak)')
- print(' DHCPI (inform)')
- print(' Default print all options')
-
- if (os.name == 'nt'):
- print('')
- print('')
- print('(PS). In Windows, digit "netsh interface show interface" for show the names of interfaces')
+ print('Usage: {} -i '.format(sys.argv[0]))
+ print('')
+ print(' -i Interface for listening')
+ print('Optional:')
+ print(' -o File Output Save')
+ print(' -t Options types: DHCPD (discover)')
+ print(' DHCPR (request)')
+ print(' DHCPN (nak)')
+ print(' DHCPI (inform)')
+ print(' Default print all options')
+
+ if (os.name == 'nt'):
+ print('')
+ print('')
+ print('(PS). In Windows, digit "netsh interface show interface" for show the names of interfaces')
def dhcp_options_search(pkts):
- data=[pkts.getlayer(DHCP).options[0][1]]
- for ex in pkts.getlayer(DHCP).options:
- if REQUEST_ADDRESS in ex:
- data.append((REQUEST_ADDRESS, ex[1]))
- elif ADDRESS_SERVER_DHCP in ex:
- data.append((ADDRESS_SERVER_DHCP, ex[1]))
- elif VENDOR in ex:
- data.append((VENDOR, ex[1]))
- elif HOSTNAME in ex:
- data.append((HOSTNAME, ex[1]))
- elif ERROR_MESSAGE in ex:
- data.append((ERROR_MESSAGE, ex[1]))
- return data
+ data = [pkts.getlayer(DHCP).options[0][1]]
+ for ex in pkts.getlayer(DHCP).options:
+ if REQUEST_ADDRESS in ex:
+ data.append((REQUEST_ADDRESS, ex[1]))
+ elif ADDRESS_SERVER_DHCP in ex:
+ data.append((ADDRESS_SERVER_DHCP, ex[1]))
+ elif VENDOR in ex:
+ data.append((VENDOR, ex[1]))
+ elif HOSTNAME in ex:
+ data.append((HOSTNAME, ex[1]))
+ elif ERROR_MESSAGE in ex:
+ data.append((ERROR_MESSAGE, ex[1]))
+ return data
def parser_packet(pkts):
- if (not pkts):
- return
-
- mac_addr=pkts.getlayer(Ether).src
- ip_src=pkts.getlayer(IP).src
- ip_dst=pkts.getlayer(IP).dst
- address='???'
- vendor='???'
- address_server_dhcp='???'
- hostname='???'
- error_msg=None
-
- data=dhcp_options_search(pkts)
- if (not data):
- return
-
- type_option=data[0]
- del data[0]
-
- time_capture=tuple(time.localtime())
- ## Check in base al valore dell'opzione '-t' e dal tipo di pacchetto
- # ## in entrata
- if type_option == DHCPDISCOVER and ('DHCPD' in type_dhcp or not type_dhcp):
- option_dhcp='DHCPDISCOVER'
- format_syntax='[%s] %s (%s (%s)) %s: %s'
- value_syntax='(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, mac_addr, vendor, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
- elif type_option == DHCPREQUEST and ('DHCPR' in type_dhcp or not type_dhcp):
- REQUESTED.append(mac_addr)
-
- option_dhcp=colored('DHCPREQUEST', 'white', attrs=['bold'])
- format_syntax='[%s] %s (%s) CLIENT -> [%s (%s)] %s: %s %s: %s'
- value_syntax='(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, colored(address_server_dhcp, \'blue\', attrs=[\'bold\']), mac_addr, vendor, colored(\'addr\', \'yellow\', attrs=[\'bold\']), address, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
- elif type_option == DHCPNAK and ('DHCPN' in type_dhcp or not type_dhcp):
- option_dhcp='DHCPNAK'
- format_syntax='[%s] %s (%s from %s) (%s) via %s'
- value_syntax='(time.strftime("%d/%m/%y %H:%M",time_capture), colored(option_dhcp, \'red\', attrs=[\'bold\']), mac_addr, colored(ip_src, \'blue\', attrs=[\'bold\']), error_msg, ip_dst)'
- elif type_option == DHCPINFORM and ('DHCPI' in type_dhcp or not type_dhcp):
- option_dhcp='DHCPINFORM'
- format_syntax='[%s] %s [%s (%s)] %s: %s %s: %s'
- value_syntax='(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, mac_addr, vendor, colored(\'addr\', \'yellow\', attrs=[\'bold\']), ip_src, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
- else:
- return
-
- for ex in data:
- if REQUEST_ADDRESS in ex:
- address=ex[1]
- elif ADDRESS_SERVER_DHCP in ex:
- address_server_dhcp=ex[1]
- elif VENDOR in ex:
- vendor=ex[1].decode('utf8')
- elif HOSTNAME in ex:
- hostname=ex[1].decode('utf8')
- elif ERROR_MESSAGE in ex:
- error_msg=ex[1].decode('utf8')
-
- if (file_out):
- with open(file_out,'a+') as fd:
- fd.write('{}: {} server_dhcp={} mac={} vendor={} address={} hostname={} errorr_msg={}'.format(time.strftime("%d-%m-%y-%H-%M",time_capture), option_dhcp, address_server_dhcp, mac_addr, vendor, address, hostname, error_msg))
- fd.write('\n')
-
- print((format_syntax) % eval(value_syntax))
+ if (not pkts):
+ return
+
+ mac_addr = pkts.getlayer(Ether).src
+ ip_src = pkts.getlayer(IP).src
+ ip_dst = pkts.getlayer(IP).dst
+ address = '???'
+ vendor = '???'
+ address_server_dhcp = '???'
+ hostname = '???'
+ error_msg = '???'
+
+ data = dhcp_options_search(pkts)
+ if (not data):
+ return
+
+ TOT_DEVICES.append(mac_addr)
+ type_option = data[0]
+
+ del data[0]
+
+ time_capture = tuple(time.localtime())
+ # Check in base al valore dell'opzione '-t' e/o dal tipo di pacchetto
+ # in entrata
+ if type_option == DHCPDISCOVER and ('DHCPD' in type_dhcp or not type_dhcp):
+ option_dhcp = 'DHCPDISCOVER'
+ format_syntax = '[%s] %s (%s (%s)) %s: %s'
+ value_syntax = '(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, mac_addr, vendor, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
+ elif type_option == DHCPREQUEST and ('DHCPR' in type_dhcp or not type_dhcp):
+ REQUESTED.append(mac_addr)
+
+ option_dhcp = colored('DHCPREQUEST', 'white', attrs=['bold'])
+ format_syntax = '[%s] %s (%s) CLIENT -> [%s (%s)] %s: %s %s: %s'
+ value_syntax = '(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, colored(address_server_dhcp, \'blue\', attrs=[\'bold\']), mac_addr, vendor, colored(\'addr\', \'yellow\', attrs=[\'bold\']), address, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
+ elif type_option == DHCPNAK and ('DHCPN' in type_dhcp or not type_dhcp):
+ option_dhcp = 'DHCPNAK'
+ format_syntax = '[%s] %s (%s from %s) (%s) via %s'
+ value_syntax = '(time.strftime("%d/%m/%y %H:%M",time_capture), colored(option_dhcp, \'red\', attrs=[\'bold\']), mac_addr, colored(ip_src, \'blue\', attrs=[\'bold\']), error_msg, ip_dst)'
+ elif type_option == DHCPINFORM and ('DHCPI' in type_dhcp or not type_dhcp):
+ option_dhcp = 'DHCPINFORM'
+ format_syntax = '[%s] %s [%s (%s)] %s: %s %s: %s'
+ value_syntax = '(time.strftime("%d/%m/%y %H:%M",time_capture), option_dhcp, mac_addr, vendor, colored(\'addr\', \'yellow\', attrs=[\'bold\']), ip_src, colored(\'host\', \'yellow\', attrs=[\'bold\']), hostname)'
+ else:
+ return
+
+ for ex in data:
+ if REQUEST_ADDRESS in ex:
+ address = ex[1]
+ elif ADDRESS_SERVER_DHCP in ex:
+ address_server_dhcp = ex[1]
+ elif VENDOR in ex:
+ vendor = ex[1].decode('utf8')
+ elif HOSTNAME in ex:
+ hostname = ex[1].decode('utf8')
+ elif ERROR_MESSAGE in ex:
+ error_msg = ex[1].decode('utf8')
+
+ if (file_out):
+ with open(file_out, 'a+') as fd:
+ fd.write('{}: {} server_dhcp={} mac={} vendor={} address={} hostname={} errorr_msg={}'.format(time.strftime("%d-%m-%y-%H-%M", time_capture), option_dhcp, address_server_dhcp, mac_addr, vendor, address, hostname, error_msg))
+ fd.write('\n')
+
+ print((format_syntax) % eval(value_syntax))
if __name__ == '__main__':
- interface=None
- type_dhcp=list()
- file_out=None
-
- logo()
-
- op=sys.argv[1::2]
- val=sys.argv[2::2]
- if (len(sys.argv) < 2 or len(op) != len(val)):
- help()
- sys.exit(1)
-
- ## Semplice parsing delle opzioni da input
- i=0
- for o in op:
- if ( o == '-o' ):
- file_out=val[index_op]
- elif ( o == '-t' ):
- if val[i] != 'DHCPD' and val[i] != 'DHCPR' and val[i] != 'DHCPN' and val[i] != 'DHCPI':
- help()
+ interface = None
+ type_dhcp = list()
+ file_out = None
+
+ logo()
+
+ op = sys.argv[1::2]
+ val = sys.argv[2::2]
+ if (len(sys.argv) < 2 or len(op) != len(val)):
+ help()
+ sys.exit(1)
+
+ # Semplice parsing delle opzioni da input
+ i = 0
+ for o in op:
+ if (o == '-o'):
+ file_out = val[index_op]
+ elif (o == '-t'):
+ if val[i] != 'DHCPD' and val[i] != 'DHCPR' and val[i] != 'DHCPN' and val[i] != 'DHCPI':
+ help()
+ sys.exit(1)
+
+ type_dhcp.append(val[i])
+ elif (o == '-i'):
+ interface = val[i]
+ i += 1
+
+ # Check root permissions
+ if (os.name == 'posix'):
+ if (os.getuid() != 0):
+ print('Please run as root')
sys.exit(1)
- type_dhcp.append(val[i])
- elif ( o == '-i'):
- interface=val[i]
- i+=1
-
- ## Check root permissions
- if (os.name == 'posix'):
- if (os.getuid() != 0):
- print('Please run as root')
- sys.exit(1)
-
- start=time.time()
- sniff(iface=interface, prn=parser_packet, store=False, filter=('udp port 67 and port 68'))
- end=time.time()-start
-
- if (end < 60):
- who_time = '{} seconds'.format(int(end))
- elif (end >= 60 and end < 3600):
- who_time = '{} minutes'.format(int(end/60))
- else:
- who_time = '{} hours'.format(int(end/3600))
-
- print('')
- print('\r[+] {}: {} devices {}'.format(who_time,
- len(set(REQUESTED)),
- colored('connected', 'yellow', attrs=['bold'])))
\ No newline at end of file
+ start = time.time()
+ sniff(iface=interface, prn=parser_packet, store=False, filter=('udp port 67 and port 68'))
+ end = time.time()-start
+
+ if (end < 60):
+ who_time = '{} seconds'.format(int(end))
+ elif (end >= 60 and end < 3600):
+ who_time = '{} minutes'.format(int(end/60))
+ else:
+ who_time = '{} hours'.format(int(end/3600))
+
+ print('')
+ print('\r[+] {}: {} devices ({} {})'.format(who_time,
+ len(set(TOT_DEVICES)),
+ len(set(REQUESTED)),
+ colored('connected', 'yellow', attrs=['bold'])))