Simple examples for how intentional bugs can be abused to ovecome modern security measures.
Caveats:
- Only works for Linux and x86-64 CPUs (probably).
- Due to potential differences in how compilers might lay out the stack, offsets used in exploits might differ, or they might not work at all*.
*: This could happen if for example, a critical local variable is overwritten with a bad value,
like a loop index (i
), which would cause additional misbehavior.
If the provided paddings do not work, figuring out the required padding would require disassembling
your program or firing up gdb
.
Source: no-stack-protector.c
Note: requires ASLR to be disabled and compiling without stack protector (no-stack-protector
).
This will print the address of bad
, which will be used in the second step:
bin/no-stack-protector <<< "ok"
tools/payload --padding 72 0x5555555547d0 | bin/no-stack-protector
Source: with-stack-protector.c
The GCC Stack Protector appends a prologue and epilogue to functions it deems sensitive to
overflows (or all if -fstack-protector-all
is specified).
The prologue will store a random canary value immediately before the return pointer on the stack,
and the epologue will verify that this value hasn't been tampered with.
The idea being that it will be hard to tamper with the return pointer without corrupting the canary.
The stack protector will also reorder local variables stored on the stack so that buffers (e.g.
char[64]
) are stored at the top. The reasoning being that overflowing these buffers should not
permit overwriting local variables so easily.
The program can be circumvent this protection by exploiting an intentional overflow to overwrite a
locally stored function pointer (h
) to point to our bad function.
Since the local variables have been reordered, we have to abuse an overflow in reverse, causing
memory prior to the buffer to be overwritten.
Find pointer to the bad function:
bin/with-stack-protector <<< "foo"
Use it here:
tools/payload --padding 71 --reverse 0x400667 | bin/with-stack-protector
Source: with-aslr.c
This is an example of a program that will leak memory on input overflows.
It accomplishes this by overwriting a variable on the stack that is supposed to point to a fixed
string Everything is OK!
, with a memory location of our choice.
This uses the same principle as the program circumventing the GCC Stack Protector.
tools/payload --length-prefix --padding 64 --reverse 0x55555555478b | bin/with-aslr | xxd
With our leaky program, we have the ability to scan the memory for secrets or to find the location of our bad function which will be crucial to perform the exploit.
ALSR is a kernel feature which causes libraries and applications to be loaded from a randomized offset in virtual memory. This makes it harder to write exploits which require memory locations to be fixed.
Disabling ASLR will be required for some of these examples, this can be done temporarily through
sysctl
:
sudo sysctl -w kernel.randomize_va_space=0
You can test if ASLR is disabled by running:
bin/no-stack-protector <<< "ok"
bad = ...
If the same address for bad
is printed every time it has been successfully disabled.