Payloads
Last updated
Last updated
libc contains code to execve("/bin/sh")
in several places. If you know the libc in use and its loaded base address (see ), you can just jump there.
Tools:
Good to know:
call
on x86-64 requires a 16-byte aligned stack. Not always an issue, but it can be. Pad your ROP chain.
TODO: Learn about this
.got
is populated by the linker (ld) on demand, when a .plt
function is called for the first time.
Lookups are performed using some giant tables (JMPREL
, SYMTAB
, STRTAB
), and string matching in these tables.
The top of .plt
is a stub which calls dl-resolve
, and takes an index into these tables as a parameter.
Write a fake SYMTAB
and STRTAB
somewhere, containing an entry for "system"
ROP into dl-resolve
with a well-chosen table index (overflow the existing STRTAB
into our fake buffer)
dl-resolve
will go find system
and call it for us!
If you can push to the stack and execute syscall 15, you can control all the registers at once. Neat.
If you've got ROP control, maybe you can emulate a system call?
Set $eax
and find an int 0x80
instruction to lift off! Arguments are in $ebx
, $ecx
, $edx
, $esi
.
Making a system call is as easy as setting $rax
and executing the syscall
instruction. Arguments are in $rdi
, $rsi
, $rdx
.
If there's a blocklist, here are some less obvious tricks:
The ax
registers which control syscall number also happen to be the return value registers in the SystemV calling convention. If you control a read()
before your ROP chain, for example, it will return the number of bytes read. Send it 11 bytes and you've lined yourself up for execve()
!
Alternatively, check out the Sigreturn syscall below to control all the registers!
Danger is an issue, and system()
relies on the stack being 16-byte aligned when it's called. If your chain doesn't work, try adding a ret;
gadget to it for a different alignment.
32-bit syscalls are also available, see for more info about that.
arch_prctl
can be used for an arbitrary write ()
brk
can be used to find the address of the heap ()