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:
- Overflow buffer till RIP
- Overwrite RIP with the address of
strcpy@plt
- Use a clean gadget from
.text
, e.g.pop edi ; pop ebp ; ret
, as return address forstrcpy
- Write arguments for
strcpy
:&bss
-address as destination and one byte of/bin/sh
using.text
- Repeat steps 2-4 until
/bin/sh
is completely written to&bss
- Overwrite GOT-entry of
strcpy
withsystem
(using offset, requires knowledge about the used version of Libc - let's ignore this here) - Write
strcpy@plt
on the stack, followed by some 4-byte chunk and finally address of&bss
which points to/bin/sh
- 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:
- 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:
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 tostrcpy
and taking advantage of the NULL-terminating characterstrcpy
always writes. But one may only callstrcpy
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?
x86-64 does not prevent these type of exploits. See this tutorial.