mirror of
https://github.com/lgandx/Responder.git
synced 2025-08-20 05:13:34 -07:00
Merge 85bafe1670
into 398a1fce31
This commit is contained in:
commit
b002b623ab
4 changed files with 155 additions and 31 deletions
|
@ -28,10 +28,21 @@ MQTT = On
|
||||||
; Use "Random" for generating a random challenge for each requests (Default)
|
; Use "Random" for generating a random challenge for each requests (Default)
|
||||||
Challenge = Random
|
Challenge = Random
|
||||||
|
|
||||||
|
; Database Management System
|
||||||
|
; Use "sqlite" or "psql"
|
||||||
|
Dbms = sqlite
|
||||||
|
|
||||||
; SQLite Database file
|
; SQLite Database file
|
||||||
; Delete this file to re-capture previously captured hashes
|
; Delete this file to re-capture previously captured hashes
|
||||||
Database = Responder.db
|
Database = Responder.db
|
||||||
|
|
||||||
|
; Psql Database
|
||||||
|
PsqlHost = 127.0.0.1
|
||||||
|
PsqlPort = 5432
|
||||||
|
PsqlUser= dbuser
|
||||||
|
PsqlPassword = dbpass
|
||||||
|
PsqlDatabase = responder
|
||||||
|
|
||||||
; Default log file
|
; Default log file
|
||||||
SessionLog = Responder-Session.log
|
SessionLog = Responder-Session.log
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
aioquic
|
aioquic
|
||||||
netifaces>=0.10.4
|
netifaces>=0.10.4
|
||||||
|
psycopg>=3.2.3
|
||||||
|
|
12
settings.py
12
settings.py
|
@ -139,9 +139,19 @@ class Settings:
|
||||||
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos'))
|
||||||
self.SNMP_On_Off = self.toBool(config.get('Responder Core', 'SNMP'))
|
self.SNMP_On_Off = self.toBool(config.get('Responder Core', 'SNMP'))
|
||||||
|
|
||||||
# Db File
|
# Db
|
||||||
|
self.Dbms = config.get('Responder Core', 'Dbms')
|
||||||
|
|
||||||
|
# Db File Sqlite
|
||||||
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
|
self.DatabaseFile = os.path.join(self.ResponderPATH, config.get('Responder Core', 'Database'))
|
||||||
|
|
||||||
|
# Db Psql
|
||||||
|
self.PsqlHost = config.get('Responder Core', 'PsqlHost')
|
||||||
|
self.PsqlPort = config.get('Responder Core', 'PsqlPort')
|
||||||
|
self.PsqlUser = config.get('Responder Core', 'PsqlUser')
|
||||||
|
self.PsqlPassword = config.get('Responder Core', 'PsqlPassword')
|
||||||
|
self.PsqlDatabase = config.get('Responder Core', 'PsqlDatabase')
|
||||||
|
|
||||||
# Log Files
|
# Log Files
|
||||||
self.LogDir = os.path.join(self.ResponderPATH, 'logs')
|
self.LogDir = os.path.join(self.ResponderPATH, 'logs')
|
||||||
|
|
||||||
|
|
162
utils.py
162
utils.py
|
@ -25,6 +25,7 @@ import datetime
|
||||||
import codecs
|
import codecs
|
||||||
import struct
|
import struct
|
||||||
import random
|
import random
|
||||||
|
import psycopg
|
||||||
try:
|
try:
|
||||||
import netifaces
|
import netifaces
|
||||||
except:
|
except:
|
||||||
|
@ -318,7 +319,26 @@ def NetworkRecvBufferPython2or3(data):
|
||||||
else:
|
else:
|
||||||
return str(data.decode('latin-1'))
|
return str(data.decode('latin-1'))
|
||||||
|
|
||||||
def CreateResponderDb():
|
def PsqlConnect():
|
||||||
|
conn = psycopg.connect(dbname=settings.Config.PsqlDatabase,
|
||||||
|
host=settings.Config.PsqlHost,
|
||||||
|
user=settings.Config.PsqlUser,
|
||||||
|
password=settings.Config.PsqlPassword,
|
||||||
|
port=settings.Config.PsqlPort)
|
||||||
|
return conn
|
||||||
|
|
||||||
|
def _CreateResponderDbPsql():
|
||||||
|
conn = PsqlConnect()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('CREATE TABLE IF NOT EXISTS Poisoned (timestamp TIMESTAMP, Poisoner TEXT, SentToIp CIDR, ForName TEXT, AnalyzeMode TEXT)')
|
||||||
|
conn.commit()
|
||||||
|
cursor.execute('CREATE TABLE IF NOT EXISTS responder (timestamp TIMESTAMP, module TEXT, type TEXT, client CIDR, hostname TEXT, username TEXT, cleartext TEXT, hash TEXT, fullhash TEXT)')
|
||||||
|
conn.commit()
|
||||||
|
cursor.execute('CREATE TABLE IF NOT EXISTS DHCP (timestamp TIMESTAMP, MAC MACADDR8, IP CIDR, RequestedIP CIDR)')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def _CreateResponderDbSqlite():
|
||||||
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 Poisoned (timestamp TEXT, Poisoner TEXT, SentToIp TEXT, ForName TEXT, AnalyzeMode TEXT)')
|
cursor.execute('CREATE TABLE Poisoned (timestamp TEXT, Poisoner TEXT, SentToIp TEXT, ForName TEXT, AnalyzeMode TEXT)')
|
||||||
|
@ -329,34 +349,84 @@ def CreateResponderDb():
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
def CreateResponderDb():
|
||||||
|
if settings.Config.Dbms.lower() == 'psql':
|
||||||
|
_CreateResponderDbPsql()
|
||||||
|
else:
|
||||||
|
_CreateResponderDbSqlite()
|
||||||
|
|
||||||
|
|
||||||
|
def _SaveToDbPsql(result):
|
||||||
|
conn = PsqlConnect()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
if len(result['cleartext']):
|
||||||
|
cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=%s AND type=%s AND client=%s AND LOWER(username)=LOWER(%s) AND cleartext=%s", (result['module'], result['type'], result['client'], result['user'], result['cleartext']))
|
||||||
|
else:
|
||||||
|
cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=%s AND type=%s AND client=%s AND LOWER(username)=LOWER(%s)", (result['module'], result['type'], result['client'], result['user']))
|
||||||
|
|
||||||
|
(count,) = cursor.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO responder VALUES(NOW(), %s, %s, %s, %s, %s, %s, %s, %s)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
if count and not settings.Config.Verbose and not len(result['cleartext']):
|
||||||
|
print(color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1))
|
||||||
|
text('[*] Skipping previously captured hash for %s' % result['user'])
|
||||||
|
cursor.execute("UPDATE responder SET timestamp=NOW() WHERE user=%s AND client=%s", (result['user'], result['client']))
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
return count
|
||||||
|
|
||||||
|
def _SaveToDbSqlite(result):
|
||||||
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
|
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
||||||
|
|
||||||
|
if len(result['cleartext']):
|
||||||
|
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?) AND cleartext=?", (result['module'], result['type'], result['client'], result['user'], result['cleartext']))
|
||||||
|
else:
|
||||||
|
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user']))
|
||||||
|
|
||||||
|
(count,) = res.fetchone()
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
||||||
|
cursor.commit()
|
||||||
|
|
||||||
|
if count and not settings.Config.Verbose and not len(result['cleartext']):
|
||||||
|
print(color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1))
|
||||||
|
text('[*] Skipping previously captured hash for %s' % result['user'])
|
||||||
|
cursor.execute("UPDATE responder SET timestamp=datetime('now') WHERE user=? AND client=?", (result['user'], result['client']))
|
||||||
|
cursor.commit()
|
||||||
|
cursor.close()
|
||||||
|
return count
|
||||||
|
|
||||||
def SaveToDb(result):
|
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] = ''
|
||||||
|
if isinstance(result[k], str) and '\x00' in result[k]:
|
||||||
|
# some strings have a mixed encoding in a single string
|
||||||
|
# correct decoding is not possible
|
||||||
|
result[k] = result[k].replace("\x00","")
|
||||||
|
|
||||||
result['client'] = result['client'].replace("::ffff:","")
|
result['client'] = result['client'].replace("::ffff:","")
|
||||||
if len(result['user']) < 2:
|
if len(result['user']) < 2:
|
||||||
print(color('[*] Skipping one character username: %s' % result['user'], 3, 1))
|
print(color('[*] Skipping one character username: %s' % result['user'], 3, 1))
|
||||||
text("[*] Skipping one character username: %s" % result['user'])
|
text("[*] Skipping one character username: %s" % result['user'])
|
||||||
return
|
return
|
||||||
|
|
||||||
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
if settings.Config.Dbms.lower() == 'psql':
|
||||||
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
count = _SaveToDbPsql(result)
|
||||||
|
else:
|
||||||
|
count = _SaveToDbSqlite(result)
|
||||||
|
|
||||||
if len(result['cleartext']):
|
if len(result['cleartext']):
|
||||||
fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client'])
|
fname = '%s-%s-ClearText-%s.txt' % (result['module'], result['type'], result['client'])
|
||||||
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?) AND cleartext=?", (result['module'], result['type'], result['client'], result['user'], result['cleartext']))
|
|
||||||
else:
|
else:
|
||||||
fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client'])
|
fname = '%s-%s-%s.txt' % (result['module'], result['type'], result['client'])
|
||||||
res = cursor.execute("SELECT COUNT(*) AS count FROM responder WHERE module=? AND type=? AND client=? AND LOWER(user)=LOWER(?)", (result['module'], result['type'], result['client'], result['user']))
|
|
||||||
|
|
||||||
(count,) = res.fetchone()
|
|
||||||
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
|
logfile = os.path.join(settings.Config.ResponderPATH, 'logs', fname)
|
||||||
|
|
||||||
if not count:
|
|
||||||
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
|
||||||
cursor.commit()
|
|
||||||
|
|
||||||
if not count or settings.Config.CaptureMultipleHashFromSameHost:
|
if not count or settings.Config.CaptureMultipleHashFromSameHost:
|
||||||
with open(logfile,"a") as outf:
|
with open(logfile,"a") as outf:
|
||||||
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
||||||
|
@ -392,11 +462,30 @@ def SaveToDb(result):
|
||||||
elif len(result['cleartext']):
|
elif len(result['cleartext']):
|
||||||
print(color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1))
|
print(color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1))
|
||||||
text('[*] Skipping previously captured cleartext password for %s' % result['user'])
|
text('[*] Skipping previously captured cleartext password for %s' % result['user'])
|
||||||
else:
|
|
||||||
print(color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1))
|
def _SavePoisonersToDbPsql(result):
|
||||||
text('[*] Skipping previously captured hash for %s' % result['user'])
|
conn = PsqlConnect()
|
||||||
cursor.execute("UPDATE responder SET timestamp=datetime('now') WHERE user=? AND client=?", (result['user'], result['client']))
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=%s AND SentToIp=%s AND ForName=%s AND AnalyzeMode=%s", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
||||||
|
(count,) = cursor.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO Poisoned VALUES(NOW(), %s, %s, %s, %s)", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
def _SavePoisonersToDbSqlite(result):
|
||||||
|
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.commit()
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def SavePoisonersToDb(result):
|
def SavePoisonersToDb(result):
|
||||||
|
@ -405,13 +494,32 @@ def SavePoisonersToDb(result):
|
||||||
if not k in result:
|
if not k in result:
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
result['SentToIp'] = result['SentToIp'].replace("::ffff:","")
|
result['SentToIp'] = result['SentToIp'].replace("::ffff:","")
|
||||||
|
|
||||||
|
if settings.Config.Dbms.lower() == 'psql':
|
||||||
|
_SavePoisonersToDbPsql(result)
|
||||||
|
else:
|
||||||
|
_SavePoisonersToDbSqlite(result)
|
||||||
|
|
||||||
|
def _SaveDHCPToDbPsql(result):
|
||||||
|
conn = PsqlConnect()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT COUNT(*) AS count FROM DHCP WHERE MAC=%s AND IP=%s AND RequestedIP=%s", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
|
(count,) = cursor.fetchone()
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
cursor.execute("INSERT INTO DHCP VALUES(NOW(), %s, %s, %s)", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
def _SaveDHCPToDbSqlite(result):
|
||||||
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
||||||
res = cursor.execute("SELECT COUNT(*) AS count FROM Poisoned WHERE Poisoner=? AND SentToIp=? AND ForName=? AND AnalyzeMode=?", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
res = cursor.execute("SELECT COUNT(*) AS count FROM DHCP WHERE MAC=? AND IP=? AND RequestedIP=?", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
(count,) = res.fetchone()
|
(count,) = res.fetchone()
|
||||||
|
|
||||||
if not count:
|
if not count:
|
||||||
cursor.execute("INSERT INTO Poisoned VALUES(datetime('now'), ?, ?, ?, ?)", (result['Poisoner'], result['SentToIp'], result['ForName'], result['AnalyzeMode']))
|
cursor.execute("INSERT INTO DHCP VALUES(datetime('now'), ?, ?, ?)", (result['MAC'], result['IP'], result['RequestedIP']))
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
|
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
@ -421,17 +529,11 @@ def SaveDHCPToDb(result):
|
||||||
if not k in result:
|
if not k in result:
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
|
||||||
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
if settings.Config.Dbms.lower() == 'psql':
|
||||||
cursor.text_factory = sqlite3.Binary # We add a text factory to support different charsets
|
_SaveDHCPToDbPsql(result)
|
||||||
res = cursor.execute("SELECT COUNT(*) AS count FROM DHCP WHERE MAC=? AND IP=? AND RequestedIP=?", (result['MAC'], result['IP'], result['RequestedIP']))
|
else:
|
||||||
(count,) = res.fetchone()
|
_SaveDHCPToDbSqlite(result)
|
||||||
|
|
||||||
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)] == b'\x00\x1c\x00\x01':
|
if data[len(data)-4:len(data)] == b'\x00\x1c\x00\x01':
|
||||||
return 'IPv6'
|
return 'IPv6'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue