Return Oriented Programming
This time i gonna introduce about ROP attack(Return Oriented Programming). Before doing ROP, there are prior knowledges. 'RTL Chaining', 'GOT Overwrite/Dereference', 'Gadget', etc...
- RTL Chaining
'RTL Chaining' means continuously executed RTL. By using pop-..-ret gadget, function's arguments will be popped by 'pop' and next function will be executed by 'ret'. and going on and on.
Gadgets are set of assembly instructions which ends with 'ret' assembly instruction. Why we need this? By using this, we can bypass escaping characters(0x00, 0x0b, ..) and pop-..-ret for RTL chaining, etc.. and there are lots of tools that find useful gadgets like ropme, ROPgadget, etc...
- GOT Overwrite/Dereference
Before reading this, you need to know about PLT and GOT. 'GOT Overwrite' literally means overwriting GOT address :). For example, if there is printf() on binary, then by overwriting printf@got address with system(), when printf() executed, system() will be executed instead of printf(). Dereference is similar with GOT Overwriting. Let printf() address is 0x10 and system is 0x20, and there is printf() on binary. Then we can increase printf@got address by 0x10 to make it system() by using add-... gadget.
- ROP(Return Oriented Programming)
ROP is a technique that uses the ones introduces above or etc appropriately.
Let's see an example of ROP attack with plaid ctf 2013 ropasaurusrex.
It's 32bit stripped elf binary. And NX and ASLR are on. So we can't use static function address like before. And also a shellcode which executes /bin/sh. We need to leak addresses from the binary.
There is simple buffer overflow vulnerability. buffer size is 0x88 but input size is 0x100. And RET is on 0x8c~0x90.
Our purpose is to execute system("/bin/sh") to get shell. How could we do that?
First, we need to leak some address to get system() address. There is read() in the binary. So let's leak that function. write(1, read@got, 4) will print read@got address to stdout. And calculating offset of read() and system. So when read() address is leaked, we can get system() with that offset by doing this(system = read - offset_read_system). Then we can finally get real system() address.
Second, we need to input "/bin/sh" string to anywhere or find "/bin/sh" on memory. I tried to find "/bin/sh" string on my environment but i can't find. So i just put it in .dynamic section where w permission is enabled(bss and data section are so small to put it in). We can out it by following code. read(0, &.dynamic, len(binsh)). And send "/bin/sh" to stdin.
Additionally, There is no space for writing /bin/sh. we should use mprotect() to make arbitrary space which has wx permission. Then we could use a shellcode again.
Finally, now we are ready to exploit. We have system() address and the address where "/bin/sh" is put. But how could we execute system(). Maybe we can make another RTL chain like system(&.dynamic) but this time, i just use 'GOT Overwrite'. Target function is read(). If we overwrite system() address to read@got, when read() is executed, system() will be executed instead of read(). And All we have to is writing read() to system(). read(1, read@got, 4) could make it success. And send system() address what we leak to stdin.
Final Exploit Code
'Security > System Hacking' 카테고리의 다른 글
|[System Hacking] 7. Several Leaking & Stack Smashing Techniques (0)||2016.12.28|
|[System Hacking] 6. SigReturn Oriented Programming (0)||2016.12.27|
|[System Hacking] 4. Memory Mitigations on Linux and Windows (0)||2016.12.25|
|[System Hacking] 3. Return To Library(RTL) (0)||2016.12.24|
|[System Hacking] 2. Basic Format String Bug (0)||2016.12.23|