diff --git a/src/binary-exploitation/stack-overflow/pointer-redirecting.md b/src/binary-exploitation/stack-overflow/pointer-redirecting.md index 8dfe839a124..fc61995aa6e 100644 --- a/src/binary-exploitation/stack-overflow/pointer-redirecting.md +++ b/src/binary-exploitation/stack-overflow/pointer-redirecting.md @@ -8,6 +8,22 @@ If a function call is going to use an address of a string that is located in the If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary. +In real targets, **repointing a stack string pointer is usually more interesting than just changing the printed text**: + +- Redirect a later **`system`/`popen`/`execl*`** argument to an existing `"/bin/sh"` or attacker-controlled command string already present in memory. +- Redirect a later **read** sink such as **`puts("%s", ptr)`** or **`write(fd, ptr, len)`** to leak stack, heap or binary data. +- Redirect a later **write** sink such as **`strcpy(dst, ...)`**, **`memcpy(dst, src, len)`**, or a structure field assignment through `ptr->field = value` to turn the stack overflow into a **second-stage arbitrary write**. + +When auditing, prioritise stack locals such as **`char *cmd`**, **`char *path`**, **`char *buf`**, **`FILE *fp`**, or **pointers inside temporary request/response structs** that are used **after** the overflow but **before** the function returns. This is especially useful when the overflow cannot safely reach the saved return address because of a canary or because corrupting a nearby pointer is enough. + +If the corruption is limited to a **partial overwrite** (for example because the bug appends a `0x00`), try to redirect the pointer to: + +- A nearby string in the **same stack frame** +- Another object in the **same module / non-PIE image** +- A controlled region whose **high bytes stay unchanged** + +For the related ASLR-oriented case where a trailing NUL modifies an **existing stack pointer** instead of a dedicated local variable, check [Ret2ret & Reo2pop](../common-binary-protections-and-bypasses/aslr/ret2ret.md). + You can find an **example** of this in: - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c) @@ -18,6 +34,43 @@ You can find an **example** of this in: Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**). +Useful targets are not only explicit callback variables such as `void (*fp)()`. In practice, look for: + +- **Callbacks stored in local structs** passed later to helper functions +- **Destructor / cleanup handlers** invoked on error paths +- **Parser dispatch tables** or **state-machine handlers** copied to the stack +- **Local structs / objects** that later dispatch through an indirect call + +In modern exploitation, **pointer redirection is often the last primitive available before touching the canary**. A 2024 exploitation writeup for CVE-2024-20017 shows the typical pattern: the overflow reaches several local variables before the stack canary, the attacker corrupts a **stack pointer plus its associated length/value**, and a later assignment through that pointer becomes an **arbitrary write** without ever needing to return through the corrupted frame. + +### Pointer corruption to second-stage primitives + +If a nearby pointer is later dereferenced for a store, the goal is usually not to jump directly with the first overflow, but to **upgrade the primitive**: + +1. Overflow a local buffer and corrupt a **pointer** plus any associated **length / integer / index**. +2. Wait for the function to perform a **post-overflow dereference** such as `ptr->len = x`, `memcpy(ptr, src, n)` or `*ptr = value`. +3. Use that resulting **write-what-where** to overwrite a GOT slot, callback, config pointer, or another indirect callsite. + +This is a good option when: + +- The bug stops at the canary +- The function pointer itself is not directly reachable +- A 4-byte or 8-byte **data write** is easier to get than an immediate control-flow hijack + +The same idea also works for **read** primitives if the corrupted pointer is later passed to logging, printing, or network send helpers. + +### Modern AArch64 note: PAC / BTI + +On current AArch64 targets, a classic **saved return address overwrite** may fail because the epilogue authenticates `x30` with PAC. In those cases, **non-return hijacks** such as corrupted local function pointers or callback pointers become more attractive. + +However, if **BTI** is enabled, the overwritten indirect-call target must still land on a **valid landing pad** (typically a function entry with **`bti c`**, or in PAC-enabled code a prologue starting with **`paciasp`/`pacibsp`**). Therefore, when redirecting a stack function pointer on AArch64, prefer: + +- Real function entries instead of mid-function gadgets +- Targets whose prologue already satisfies BTI +- Targets where the indirect-call pointer is not additionally authenticated before use + +For a related AArch64 stack-overflow context, check [ret2win-arm64](ret2win/ret2win-arm64.md). + You can find an example in: - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c) @@ -25,8 +78,8 @@ You can find an example in: ## References - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting) +- [https://blog.coffinsec.com/0day/2024/08/30/exploiting-CVE-2024-20017-four-different-ways.html](https://blog.coffinsec.com/0day/2024/08/30/exploiting-CVE-2024-20017-four-different-ways.html) +- [https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64) {{#include ../../banners/hacktricks-training.md}} - -