Exploiting a string-based overflow on x86-64 with NX (DEP) and ASLR enabled
Asked Answered
C

1

6

Consider the following vulnerable code/program:

#include <string.h>

int main(int argc, char *argv[]) {
    char buf[16];
    strcpy(buf, argv[1]);

    return 0;
}

On IA-32 (x86, 32-bit) running Linux with NX and ASLR enabled, I would exploit this using GOT-overwrite technique, which essentially includes the following steps:

  1. Overflow buffer till RIP
  2. Overwrite RIP with the address of strcpy@plt
  3. Use a clean gadget from .text, e.g. pop edi ; pop ebp ; ret, as return address for strcpy
  4. Write arguments for strcpy: &bss-address as destination and one byte of /bin/sh using .text
  5. Repeat steps 2-4 until /bin/sh is completely written to &bss
  6. Overwrite GOT-entry of strcpy with system (using offset, requires knowledge about the used version of Libc - let's ignore this here)
  7. Write strcpy@plt on the stack, followed by some 4-byte chunk and finally address of &bss which points to /bin/sh
  8. Profit

I want to exploit this on x86-64 with the same mitigation measures enabled. But this is more difficult as imagined. Basically for the following reasons:

  1. x86-64 register-based calling convention: Function arguments are passed using registers, not the stack. Therefore some additional ROP-gadgets are required to transfer the arguments from the stack into the appropriate register. This is a minor problem, but is also affected by the following problem:
  2. 64-bit return address: The RIP in x86-64 points to .text which is not even 32-bit long. Therefore NULL-bytes must be written on the stack to chain function calls. Basically one can write as much NULL-bytes as desired using chained calls to strcpy and taking advantage of the NULL-terminating character strcpy always writes. But one may only call strcpy once by only overwriting the least significant bytes of the RIP.

    |0x00000000|        (most significant bytes)
    |0x00deadbe| <- RIP (least significant bytes)
    |0x41414141|
    |0x41414141| <- SFP
    |   ...    | 
    

These are the major problems I got with exploiting the program on x86-64 with NX and ASLR enabled. Are there any techniques which solve these problems? Or does x86-64 really prevent a working, shell-opening exploit?

Condemnation answered 11/7, 2013 at 9:35 Comment(1)
If RIP is supposed to stand for the return-address, you need new terminology for x86-64. Just like EAX is extended to RAX, EIP (the current Instruction Pointer) is extended to RIP. So in x86-64, RIP is a register name, and doesn't (by itself) make a good name for the return address that RET will read.Unemployed
F
0

x86-64 does not prevent these type of exploits. See this tutorial.

Frequently answered 13/9, 2016 at 8:59 Comment(1)
As this question assumes x86-64 with both ASLR and NX enabled, your link does not provide a solution: "I had to cheat on this one a bit by turning off ASLR. Due to the nature of addressing on 64-bit systems, null bytes become a really big problem. For this particular challenge, it’s easy to overwrite RIP, but I could only return to a single gadget due to the null bytes."Condemnation

© 2022 - 2024 — McMap. All rights reserved.