8

I have a code snippet which has the classic strcpy vulnerability

int main(int argc, char argv[][]){
    char buffer[8];
    strcpy(buffer, argv[1]);
}

By disassembling the binary file, we can see rsp is decreased by 0x10 bytes (=16)

So we can actually overwrite the rbp after 16 bytes and return address after 24 bytes. Before the function returns, rax is pointing to the beginning of our shellcode.

Here is my approach to attacking the program. Our shellcode will be in the following format

"A"*16 + "B"*8 + "C"*8

As ASLR is enabled, I replaced return address to an address of jmpq *%rax, so the payload will now become

"A"*16 + "B"*8 + "\x77\x04\x40"

and by stepping through in gdb, I can see execution is being directed to the beginning of "A"s. However, the buffer is too small to put in a (system(/bin/sh)) shellcode. What am I supposed to do here?

Here is what I am thinking:

  1. Use egghunter approach. However, I am not able to send more than 24 bytes data to the application, as the return address include null bytes, it terminates my shellcode.

  2. Find a shellcode that is smaller than 24 bytes for 64 bits Linux. (I guess this is not possible)

  3. ROP approach, however, ASLR is enabled, I can't figure out the base address of libc

I have read through many tutorials and most of them have a big buffer like char buffer[500] instead char buffer[8]. It will be great if someone can guide me to the right place.

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • 2
    The problem isn't the 24 bytes limit. If you send it more bytes, those bytes would still end up somewhere on the stack that you can call through jmpq instruction. However, execution from stack is disabled due to DEP. In order to bypass ASLR, you need a memory leak which can point to a system library and from there to construct the ROP. – void_in Aug 30 '15 at 12:35
  • @void_in Thank you for your reply and it seems like I cant send more than 24 bytes, because return address have to be 0x0000000000400477 . If I send more bytes after \x77\x04\x40, I will not able to run jmp eax instruction. And I guess DEP is disabled in my case –  Aug 30 '15 at 12:37
  • Similar Question here : http://security.stackexchange.com/questions/42852/insert-string-to-memory-with-null-character –  Aug 30 '15 at 12:39
  • 3
    3 years later, but in case someone comes across. There are other places where you could store your shellcode (argv[2], envp[]). – domen Aug 14 '18 at 14:01
  • 3 years later, @domen is right. Just need to be creative and find some place to store shellcode in the memory –  Nov 30 '18 at 04:28
  • But how would you then overwrite the return address to point to your shellcode since you still have leading zero bytes and only one write with strcpy so you can only write one continous block of data? Another idea would be to use a magic gadget (addresses in libc which automatically spawn a shell, and there are several) and then brute force the address of such a magic gadget. However ASLR on 64 bit Linux is quite strong so this might take a day or so to succeed. – Sebastian Walla Nov 30 '18 at 06:27

1 Answers1

1

There are multiple possible ways around this, it's just a matter of being creative.

Here are some things you could try:

  • If you know your current libc's version, you could find a one-gadget with constrains meeting your register values.

  • Also, if you know your current libc's version, there should be enough size for a small shellcode that overwrites the least significant bytes for the strcpy()'s GOT entry to point to system() instead.

  • There is a nice 23 bytes long 64 bits Linux shellcode you could use here: https://www.exploit-db.com/exploits/46907.

  • Depending on the way this binary was compiled, there might be just enough gadgets for you to build a 1st stage ROP chain that increases your buffer size before jumping back to strcpy() to get the rest of the payload from the stack.

I hope this few examples shed some light on the endless possibilities you have here.