diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
index 5c80bb9ed35..7cc8f4d2865 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
@@ -220,7 +220,7 @@ Each symbol entry contains:
#### GNU IFUNC (indirect functions)
-- GCC can emit `STT_GNU_IFUNC` symbols with the `__attribute__((ifunc("resolver")))` extension. The dynamic loader calls the resolver at load time to select the concrete implementation (commonly CPU dispatch).
+- GCC can emit `STT_GNU_IFUNC` symbols with the `__attribute__((ifunc("resolver")))` extension. The dynamic loader calls the resolver at load time to select the concrete implementation (commonly CPU dispatch).[[1]](#references)
- Quick triage: `readelf -sW ./bin | rg -i "IFUNC"`
#### GNU Symbol Versioning (dynsym/dynstr/gnu.version)
@@ -268,7 +268,7 @@ The NEEDED directory indicates that the program **needs to load the mentioned li
### Dynamic loader search order (RPATH/RUNPATH, $ORIGIN)
-The entries `DT_RPATH` (deprecated) and/or `DT_RUNPATH` influence where the dynamic loader searches for dependencies. Rough order:
+The entries `DT_RPATH` (deprecated) and/or `DT_RUNPATH` influence where the dynamic loader searches for dependencies.[[3]](#references) Rough order:
- `LD_LIBRARY_PATH` (ignored for setuid/sgid or otherwise "secure-execution" programs)
- `DT_RPATH` (only if `DT_RUNPATH` absent)
@@ -361,7 +361,7 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
#### Packed relative relocations (RELR)
-- Modern linkers can emit compact **relative** relocations with `-z pack-relative-relocs`. This adds `DT_RELR`, `DT_RELRSZ`, and `DT_RELRENT` entries to the dynamic section for PIEs/shared libraries (it is ignored for non-PIE executables).
+- Modern linkers can emit compact **relative** relocations with `-z pack-relative-relocs`. This adds `DT_RELR`, `DT_RELRSZ`, and `DT_RELRENT` entries to the dynamic section for PIEs/shared libraries (it is ignored for non-PIE executables).[[2]](#references)
- Recon: `readelf -d ./bin | egrep -i "DT_RELR|RELRSZ|RELRENT"`
### Static Relocations
@@ -478,7 +478,7 @@ The Linux kernel passes an auxiliary vector to processes containing useful addre
- `AT_RANDOM`: points to 16 random bytes used by glibc for the stack canary and other PRNG seeds.
- `AT_SYSINFO_EHDR`: base address of the vDSO mapping (handy to find `__kernel_*` syscalls and gadgets).
-- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, etc.
+- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, etc.[[4]](#references)
As an attacker, if you can read memory or files under `/proc`, you can often leak these without an infoleak in the target process:
@@ -501,8 +501,9 @@ Leaking `AT_RANDOM` gives you the canary value if you can dereference that point
## References
-- GCC Common Function Attributes (ifunc / STT_GNU_IFUNC): https://gcc.gnu.org/onlinedocs/gcc-14.3.0/gcc/Common-Function-Attributes.html
-- GNU ld `-z pack-relative-relocs` / `DT_RELR` docs: https://sourceware.org/binutils/docs/ld.html
-- ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE): https://man7.org/linux/man-pages/man8/ld.so.8.html
-- getauxval(3) – Auxiliary vector and AT_* constants: https://man7.org/linux/man-pages/man3/getauxval.3.html
+- [1] [GCC Common Function Attributes (ifunc / STT_GNU_IFUNC)](https://gcc.gnu.org/onlinedocs/gcc-14.3.0/gcc/Common-Function-Attributes.html)
+- [2] [GNU ld `-z pack-relative-relocs` / `DT_RELR` docs](https://sourceware.org/binutils/docs/ld.html)
+- [3] [ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE)](https://man7.org/linux/man-pages/man8/ld.so.8.html)
+- [4] [getauxval(3) – Auxiliary vector and AT_* constants](https://man7.org/linux/man-pages/man3/getauxval.3.html)
+
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
index 77f5b140aa2..2d42d15e4a1 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
@@ -175,7 +175,7 @@ pwn update
## ELF → raw shellcode packaging (loader_append)
-Pwntools can turn a standalone ELF into a single raw shellcode blob that self‑maps its segments and transfers execution to the original entrypoint. This is ideal for memory‑only loaders (e.g., Android apps invoking JNI to execute downloaded bytes).
+Pwntools can turn a standalone ELF into a single raw shellcode blob that self‑maps its segments and transfers execution to the original entrypoint. This is ideal for memory‑only loaders (e.g., Android apps invoking JNI to execute downloaded bytes).[[2]](#references)
Typical pipeline (amd64 example)
@@ -207,7 +207,7 @@ Notes
## References
-- [Pwntools](https://docs.pwntools.com/en/stable/)
-- [CoRPhone – ELF→shellcode pipeline used for Android in-memory execution](https://github.com/0xdevil/corphone)
+- [1] [Pwntools](https://docs.pwntools.com/en/stable/)
+- [2] [CoRPhone – ELF→shellcode pipeline used for Android in-memory execution](https://github.com/0xdevil/corphone)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
index 087d4902ca9..e539fa58e2d 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
@@ -13,7 +13,7 @@
2. If possible, add the chunk to the fast bin
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
-> Note: Starting with glibc 2.42, the tcache step can also take chunks up to a much larger size threshold if `glibc.malloc.tcache_max` was raised (up to 4 MiB). This changes when a free lands in tcache vs. unsorted/small/large bins.
+> Note: Starting with glibc 2.42, the tcache step can also take chunks up to a much larger size threshold if `glibc.malloc.tcache_max` was raised (up to 4 MiB). This changes when a free lands in tcache vs. unsorted/small/large bins.[[1]](#references)
## __libc_free
@@ -391,8 +391,8 @@ _int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
- Safe-Linking in tcache/fastbins: `free()` stores the `fd` pointer of singly-linked lists using the macro `PROTECT_PTR(pos, ptr) = ((size_t)pos >> 12) ^ (size_t)ptr`. This means crafting a fake next pointer for tcache poisoning requires the attacker to know a heap address (e.g., leak `chunk_addr`, then use `chunk_addr >> 12` as the XOR key). See more details and PoCs in the tcache page below.
- Tcache double-free detection: Before pushing a chunk into tcache, `free()` checks the per-entry `e->key` against the per-thread `tcache_key` and walks the bin up to `mp_.tcache_count` looking for duplicates, aborting with `free(): double free detected in tcache 2` when found.
-- Recent glibc change (2.42): `free()` can now keep **much larger arena chunks** inside tcache when `glibc.malloc.tcache_max` is raised above the historical ceiling (up to **4 MiB**). Therefore, assumptions such as “large free => unsorted bin” are no longer reliable on modern tuned targets. **Mmapped chunks are still not cached in tcache.**
-- Heap-grooming gotcha (glibc 2.42+): if your first heap activity uses **large chunks that never touch tcache**, the `tcache_perthread_struct` may be initialized **later** than in older labs. This can place tcache metadata **after attacker-controlled large chunks**, which is useful when an overflow/UAF can later target that metadata.
+- Recent glibc change (2.42): `free()` can now keep **much larger arena chunks** inside tcache when `glibc.malloc.tcache_max` is raised above the historical ceiling (up to **4 MiB**). Therefore, assumptions such as “large free => unsorted bin” are no longer reliable on modern tuned targets. **Mmapped chunks are still not cached in tcache.**[[1]](#references)
+- Heap-grooming gotcha (glibc 2.42+): if your first heap activity uses **large chunks that never touch tcache**, the `tcache_perthread_struct` may be initialized **later** than in older labs. This can place tcache metadata **after attacker-controlled large chunks**, which is useful when an overflow/UAF can later target that metadata.[[2]](#references)
### Quick crafting of a safe-linked fd (for tcache poisoning)
@@ -448,7 +448,7 @@ Related reading within HackTricks:
## References
-- GNU C Library 2.42 release notes (large-block tcache support via `glibc.malloc.tcache_max`)
-- how2heap `glibc_2.42/tcache_metadata_hijacking.c` (practical example of delayed tcache metadata placement on modern glibc)
+- [1] [GNU C Library 2.42 release notes (large-block tcache support via glibc.malloc.tcache_max)](https://lists.gnu.org/archive/html/info-gnu/2025-07/msg00011.html)
+- [2] [how2heap glibc_2.42/tcache_metadata_hijacking.c (practical example of delayed tcache metadata placement on modern glibc)](https://github.com/shellphish/how2heap/blob/master/glibc_2.42/tcache_metadata_hijacking.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/README.md b/src/binary-exploitation/rop-return-oriented-programing/README.md
index ea395fafd67..b8b10b610ec 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/README.md
@@ -34,7 +34,7 @@ First, let's assume we've identified the necessary gadgets within the binary or
### **ROP Chain**
-Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
+Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:[[1]](#references)
1. A `ret` instruction for alignment purposes (optional)
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/index.html))
@@ -289,7 +289,7 @@ G3:
## Shellcode via /proc/self/mem (Embedded Linux)
-If you already have a ROP chain but **no RWX mappings**, an alternative is to **write shellcode into the current process using** `/proc/self/mem` and then jump to it. This is common on embedded Linux targets where `/proc/self/mem` can ignore write protections on executable segments in default configurations.
+If you already have a ROP chain but **no RWX mappings**, an alternative is to **write shellcode into the current process using** `/proc/self/mem` and then jump to it. This is common on embedded Linux targets where `/proc/self/mem` can ignore write protections on executable segments in default configurations.[[5]](#references)[[6]](#references)
Typical chain idea:
@@ -334,19 +334,16 @@ rop-syscall-execv/
../stack-overflow/stack-pivoting.md
{{#endref}}
-## Other Examples & References
+## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
-- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
+- [1] [Exploiting calling conventions (ir0nstone notes)](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
+- [2] [Nightmare: hacklu15 stackstuff](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
+- [3] [Using mprotect to bypass NX protection (ARM64 Part 4, 8ksec)](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
-- [https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-4.html](https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-4.html)
-
-## References
-
-- [Now You See mi: Now You're Pwned](https://labs.taszk.io/articles/post/nowyouseemi/)
-- [TaszkSecLabs/xiaomi-c400-pwn](https://github.com/TaszkSecLabs/xiaomi-c400-pwn)
+- [4] [In-the-wild iOS exploit chain 4 (Google Project Zero)](https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-4.html)
+- [5] [Now You See mi: Now You're Pwned](https://labs.taszk.io/articles/post/nowyouseemi/)
+- [6] [TaszkSecLabs/xiaomi-c400-pwn](https://github.com/TaszkSecLabs/xiaomi-c400-pwn)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
index f87309944ac..5205a866c38 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
@@ -4,7 +4,7 @@
## Basic Information
-The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
+The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.[[1]](#references)[[2]](#references)\
This attack is based on the following scenario:
- A stack vulnerability and knowledge of how to trigger it.
@@ -35,7 +35,7 @@ These would be the gadgets:
- `pop rsi; pop r15; ret`
- `pop rdi; ret`
-Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
+Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.[[1]](#references)
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
@@ -104,7 +104,7 @@ However, the original paper only mentions the **`write`** one, so lets talk abou
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
-However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
+However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.[[1]](#references)
Behaviour signatures to find those functions:
@@ -118,8 +118,8 @@ Behaviour signatures to find those functions:
## References
-- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
-- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
+- [1] [Hacking Blind (original BROP paper)](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
+- [2] [Blind Return Oriented Programming - BROP (CTF Recipes)](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
index 56771fb14e7..596c8707146 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
@@ -56,7 +56,7 @@ ret
The conditions will be:
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- - If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
+ - If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:[[4]](#references)
```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
@@ -73,7 +73,7 @@ gef➤ search-pattern 0x400560
## RDI and RSI
-Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
+Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:[[1]](#references)
@@ -95,7 +95,7 @@ Here's where **ret2csu** comes into play:
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
-You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
+You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:[[2]](#references)
```python
from pwn import *
@@ -126,7 +126,7 @@ print(p.recvline()) # should receive "Awesome work!"
### Bypassing the call and reaching ret
-The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
+The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:[[3]](#references)[[4]](#references)
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
@@ -182,6 +182,13 @@ target.interactive()
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/index.html), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
+## References
+
+- [1] [Hacking Blind (original BROP paper)](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
+- [2] [ret2csu exploitation - ir0nstone notes](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation)
+- [3] [ROP Emporium - ret2csu (RootNetSec)](https://www.rootnetsec.com/ropemporium-ret2csu/)
+- [4] [ropemporium_ret2csu - Nightmare (guyinatuxedo)](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html)
+
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
index 5b942a0b49b..6aa2bee43ff 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
@@ -4,7 +4,7 @@
## **Ret2esp**
-**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
+**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.[[1]](#references)
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)).
@@ -35,7 +35,7 @@ print(rop.jmp_esp) # i386
print(rop.jmp_rsp) # amd64
```
-`pwntools` will also discard gadgets whose **address contains badchars**, which is useful when the instruction exists but cannot be used directly from the overflow.
+`pwntools` will also discard gadgets whose **address contains badchars**, which is useful when the instruction exists but cannot be used directly from the overflow.[[3]](#references)
You can also search more aggressively with `ROPgadget` because sometimes the binary does not contain a clean disassembled `jmp rsp`, but it still contains the raw opcode bytes inside some other executable instruction stream:
@@ -49,7 +49,7 @@ This is especially useful in amd64 because the opcode for **`jmp rsp`** is just
### Example
-You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
+You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:[[2]](#references)
```python
from pwn import *
@@ -71,7 +71,7 @@ p.sendlineafter('RSP!\n', payload)
p.interactive()
```
-You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled. The exploit uses a gadget to **reduce the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
+You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled. The exploit uses a gadget to **reduce the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:[[5]](#references)
```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
@@ -134,9 +134,9 @@ If the binary is protected with badchar restrictions, remember that the **gadget
You can find some examples here:
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
+- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)[[6]](#references)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- - **`strcpy`** stores in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** is not overwritten, so it is possible to use a `ret2eax`.
+ - **`strcpy`** stores in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** is not overwritten, so it is possible to use a `ret2eax`.[[7]](#references)
## ARM64
@@ -225,14 +225,17 @@ p.interactive()
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the target memory is not executable, **ret2esp/ret2reg only gives you control-flow redirection**, not code execution. In modern exploits this is often combined with a previous `mprotect`/`VirtualProtect`-style stage or with already executable memory.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) & [**PIE**](../common-binary-protections-and-bypasses/pie/index.html): These make it harder to know the address of the final `jmp/call ` gadget. Partial overwrites may still work when the gadget is close enough to the original return address.
- [**CET / Shadow Stack**](../common-binary-protections-and-bypasses/cet-and-shadow-stack.md): On x86_64, classic ret-based entry into `jmp esp` / `jmp rsp` / `jmp reg` gadgets becomes unreliable because the corrupted return address is checked against the hardware shadow stack before the gadget is reached.
-- **ARM64 PAC/BTI**: Pointer Authentication can break the classic saved-LR overwrite path, and Branch Target Identification means `br xN` jumps are expected to land on a valid BTI landing pad (`bti j` / `bti jc`). A `br xN` gadget may exist but still fault on hardened binaries if the destination bytes are not a valid indirect-branch target.
+- **ARM64 PAC/BTI**: Pointer Authentication can break the classic saved-LR overwrite path, and Branch Target Identification means `br xN` jumps are expected to land on a valid BTI landing pad (`bti j` / `bti jc`). A `br xN` gadget may exist but still fault on hardened binaries if the destination bytes are not a valid indirect-branch target.[[4]](#references)
## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
-- [https://docs.pwntools.com/en/stable/rop/rop.html](https://docs.pwntools.com/en/stable/rop/rop.html)
-- [https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/p3-enabling-pac-and-bti-on-aarch64](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/p3-enabling-pac-and-bti-on-aarch64)
+- [1] [ir0nstone - Reliable shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
+- [2] [ir0nstone - Reliable shellcode: using RSP](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
+- [3] [pwntools - ROP documentation](https://docs.pwntools.com/en/stable/rop/rop.html)
+- [4] [Arm Community - Enabling PAC and BTI on AArch64](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/p3-enabling-pac-and-bti-on-aarch64)
+- [5] [guyinatuxedo - xctf16 b0verflow (stack pivot)](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html)
+- [6] [ir0nstone - Reliable shellcode: using ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
+- [7] [florianhofhammer - ret2eax.c (ASLR Smack and Laugh reference)](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
index bc05889097d..5e02911dee5 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
@@ -152,19 +152,19 @@ This basically means abusing a **Ret2lib to transform it into a `printf` format
../../format-strings/
{{#endref}}
-## Other Examples & references
+## References
-- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+- [1] [guyinatuxedo - csaw19 babyboi](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- Ret2lib, given a leak to the address of a function in libc, using one gadget
-- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
+- [2] [guyinatuxedo - csawquals17 svc](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
-- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
+- [3] [guyinatuxedo - fb19 overfloat](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
-- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
+- [4] [guyinatuxedo - hs19 storytime](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
-- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
+- [5] [guyinatuxedo - asis17 marymorton](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
-- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
+- [6] [guyinatuxedo - tu guestbook](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
index c7bce6f2605..8162d4bbb7f 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
@@ -42,18 +42,18 @@ objdump -d rop-no-aslr | grep -E 'bti|paci|auti'
### AArch64 ROP reminders
-- **`x0`** to **`x7`** hold the first 8 function arguments, so a ret2libc chain must place the pointer to **`/bin/sh`** in **`x0`** before branching to **`system`**.
+- **`x0`** to **`x7`** hold the first 8 function arguments, so a ret2libc chain must place the pointer to **`/bin/sh`** in **`x0`** before branching to **`system`**.[[2]](#references)
- **`ret`** jumps to the address stored in **`x30`**. In practice, the saved return address is usually restored by an epilogue such as **`ldp x29, x30, [sp], #0x10; ret;`**.
- Keep **`sp` 16-byte aligned** at function boundaries. Misaligned stacks can crash in epilogues or inside libc before the chain reaches **`system`**.
- On AArch64, very useful gadgets often look like **`ldr x0, [sp, #imm]; ldp x29, x30, [sp], #off; ret;`** because they both set the first argument and advance the ROP chain.
### Find offset - x30 offset
-Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
+Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).[[1]](#references)
-Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
+Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:[[1]](#references)
@@ -73,7 +73,7 @@ Using ropper an interesting gadget was found:
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
```
-This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
+This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.[[1]](#references)
### Exploit
@@ -166,18 +166,18 @@ Setting a breakpoint before calling printf it's possible to see that there are a
-Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
+Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:[[1]](#references)
-Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
+Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**[[1]](#references)
> [!IMPORTANT]
> The exact format-string positions are **build-dependent**. The values **`%21$p`** and **`%25$p`** are valid for this binary/libc combination, but different compilers, optimization levels or libc versions can move the interesting pointers. On AArch64 this is especially visible because **`printf`** receives its first arguments in registers first, and only later consumes stack values. In a new target, brute-force several **`%p`** positions or inspect the state right before the **`printf`** call to re-discover the correct offsets.
### Re-discovering the leak positions fast
-The AArch64 PCS passes the first integer/pointer arguments in **`x0`** to **`x7`**, so a variadic call such as **`printf(buf)`** may expose useful pointers only after several stack slots. A practical way to re-find the interesting indexes in a fresh build is to brute-force the positions and keep the ones that look like:
+The AArch64 PCS passes the first integer/pointer arguments in **`x0`** to **`x7`**, so a variadic call such as **`printf(buf)`** may expose useful pointers only after several stack slots.[[2]](#references) A practical way to re-find the interesting indexes in a fresh build is to brute-force the positions and keep the ones that look like:
- A pointer into the PIE image (same high bytes as the main binary mapping)
- A pointer into libc (same high bytes as the libc mapping)
@@ -211,7 +211,7 @@ Using ropper another interesting gadget was found:
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
```
-This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
+This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.[[1]](#references)
When you need to re-find a similar gadget in another libc, a quick ARM64-oriented workflow is:
@@ -280,6 +280,6 @@ p.interactive()
## References
-- [ARM64 Reversing And Exploitation Part 7 – Bypassing ASLR and NX - 8kSec](https://8ksec.io/arm64-reversing-and-exploitation-part-7-bypassing-aslr-and-nx/)
-- [Procedure Call Standard for the Arm 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/releases)
+- [1] [ARM64 Reversing And Exploitation Part 7 – Bypassing ASLR and NX - 8kSec](https://8ksec.io/arm64-reversing-and-exploitation-part-7-bypassing-aslr-and-nx/)
+- [2] [Procedure Call Standard for the Arm 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/releases)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
index 19741d4ec16..d183f97fbc0 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
@@ -11,8 +11,8 @@
## Other tutorials and binaries to practice
-This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
-Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)[[1]](#references)\
+Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)[[2]](#references)[[3]](#references)
## Code
@@ -303,6 +303,12 @@ Try to **subtract 64 bytes to the address of "/bin/sh"**:
BINSH = next(libc.search("/bin/sh")) - 64
```
+## References
+
+- [1] [tasteofsecurity - ret2libc with unknown libc](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)
+- [2] [made0x78 - Binary exploitation series: ret2libc](https://made0x78.com/bseries-ret2libc/)
+- [3] [guyinatuxedo - csaw19 babyboi](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
index 21d5f280a6e..43ec441580e 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
@@ -12,7 +12,7 @@ The vDSO base address is passed in the auxiliary vector as `AT_SYSINFO_EHDR`, so
Once you have the base, treat the vDSO like a normal ELF DSO (`linux-vdso.so.1`): dump the mapping and use `readelf -Ws`/`objdump -d` (or the kernel reference parser `tools/testing/selftests/vDSO/parse_vdso.c`) to resolve exported symbols and look for gadgets. On x86 32-bit the vDSO commonly exports `__kernel_vsyscall`, `__kernel_sigreturn`, and `__kernel_rt_sigreturn`; on x86_64 typical exports include `__vdso_clock_gettime`, `__vdso_gettimeofday`, and `__vdso_time`. Because the vDSO uses symbol versioning, match the expected version when resolving symbols.
-Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
+Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:[[3]](#references)
```bash
# Find addresses
@@ -62,7 +62,7 @@ pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
```
> [!CAUTION]
-> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
+> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)[[4]](#references)
### ARM64
@@ -75,7 +75,9 @@ srop-sigreturn-oriented-programming/srop-arm64.md
## References
-- [https://man7.org/linux/man-pages/man7/vdso.7.html](https://man7.org/linux/man-pages/man7/vdso.7.html)
-- [https://www.kernel.org/doc/Documentation/ABI/stable/vdso](https://www.kernel.org/doc/Documentation/ABI/stable/vdso)
+- [1] [vdso(7) - Linux manual page](https://man7.org/linux/man-pages/man7/vdso.7.html)
+- [2] [Linux vDSO kernel ABI documentation](https://www.kernel.org/doc/Documentation/ABI/stable/vdso)
+- [3] [Maze of Mist - HTB Cyber Apocalypse writeup](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/)
+- [4] [Linux kernel: bypassing ASLR via VDSO](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
index 4c30698b230..bc753f14486 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
@@ -30,7 +30,7 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004498b5 : pop rdx ; ret
```
-With these addresses it's possible to **write the content in the stack and load it into the registers**.
+With these addresses it's possible to **write the content in the stack and load it into the registers**.[[1]](#references)
## Write string
@@ -184,13 +184,13 @@ target.sendline(payload)
target.interactive()
```
-## Other Examples & References
+## References
-- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
+- [1] [Defcon Quals 2019 Speedrun1](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
-- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
+- [2] [Boston Key Party 2016 Simple Calc](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
-- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
+- [3] [Defcon Quals 2016 feedme](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
index efd7eb2e584..008ff8a66f1 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
@@ -20,7 +20,7 @@ Note how this would be a **type of Ret2syscall** that makes much easier to contr
../rop-syscall-execv/
{{#endref}}
-If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
+If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):[[3]](#references)
```
+--------------------+--------------------+
@@ -58,7 +58,7 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
+--------------------+--------------------+
```
-For a better explanation check also:
+For a better explanation check also:[[1]](#references)
{{#ref}}
@@ -67,7 +67,7 @@ https://youtu.be/ADULSwnQs-s?feature=shared
## Example
-You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
+You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:[[2]](#references)
```python
from pwn import *
@@ -96,7 +96,7 @@ p.sendline(payload)
p.interactive()
```
-Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
+Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:[[4]](#references)
```python
from pwn import *
@@ -131,19 +131,19 @@ target.sendline(payload) # Send the target payload
target.interactive()
```
-## Other Examples & References
+## References
-- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
-- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
-- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
+- [1] [SROP walkthrough (YouTube)](https://youtu.be/ADULSwnQs-s?feature=shared)
+- [2] [ir0nstone - Sigreturn-Oriented Programming (SROP)](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
+- [3] [Nightmare - backdoor_funsignals (SROP)](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/index.html) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
-- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
+- [4] [Nightmare - csaw19 small_boi (SROP)](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/index.html) via a **sigreturn** structure (the binary has the string `/bin/sh`).
-- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
+- [5] [Nightmare - inctf17 stupidrop (SROP)](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/index.html). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
-- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
+- [6] [Nightmare - swamp19 syscaller (SROP)](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
-- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
+- [7] [CTF Recipes - Sigreturn-Oriented Programming (SROP)](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
index a74583d44cc..caefecd4066 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
@@ -195,7 +195,7 @@ And to bypass the address of `/bin/sh` you could create several env variables po
## Locating `rt_sigreturn` on ARM64 (2023-2025)
-On Linux/**AArch64** the most convenient SROP gadget is usually the **vDSO** trampoline exported as **`__kernel_rt_sigreturn`**. In current kernels the interesting sequence is intentionally tiny:
+On Linux/**AArch64** the most convenient SROP gadget is usually the **vDSO** trampoline exported as **`__kernel_rt_sigreturn`**. In current kernels the interesting sequence is intentionally tiny:[[1]](#references)
```armasm
nop // unwinder marker
@@ -249,7 +249,7 @@ If your payload reaches the `svc #0` but the kernel rejects the frame, checking
## Modern kernel parsing and branch-protection caveats
-Recent **arm64** kernels are stricter than many old SROP writeups assume. When you hand-craft a frame, keep in mind that:
+Recent **arm64** kernels are stricter than many old SROP writeups assume. When you hand-craft a frame, keep in mind that:[[2]](#references)
* `sigcontext.__reserved` parsing is **16-byte aligned**.
* Only **one** `extra_context` record is accepted.
@@ -267,7 +267,7 @@ For hardened userlands, also keep in mind:
## References
-* [Linux arm64 vDSO `__kernel_rt_sigreturn` source](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S)
-* [Linux arm64 signal-frame parsing (`signal.c`)](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c)
+- [1] [Linux arm64 vDSO `__kernel_rt_sigreturn` source](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S)
+- [2] [Linux arm64 signal-frame parsing (`signal.c`)](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/README.md b/src/binary-exploitation/stack-overflow/README.md
index d1f339e42da..62ae5a2ccf1 100644
--- a/src/binary-exploitation/stack-overflow/README.md
+++ b/src/binary-exploitation/stack-overflow/README.md
@@ -81,7 +81,7 @@ stack-shellcode/
### Windows SEH-based exploitation (nSEH/SEH)
-On 32-bit Windows, an overflow may overwrite the Structured Exception Handler (SEH) chain instead of the saved return address. Exploitation typically replaces the SEH pointer with a POP POP RET gadget and uses the 4-byte nSEH field for a short jump to pivot back into the large buffer where shellcode lives. A common pattern is a short jmp in nSEH that lands on a 5-byte near jmp placed just before nSEH to jump hundreds of bytes back to the payload start.
+On 32-bit Windows, an overflow may overwrite the Structured Exception Handler (SEH) chain instead of the saved return address. Exploitation typically replaces the SEH pointer with a POP POP RET gadget and uses the 4-byte nSEH field for a short jump to pivot back into the large buffer where shellcode lives. A common pattern is a short jmp in nSEH that lands on a 5-byte near jmp placed just before nSEH to jump hundreds of bytes back to the payload start.[[3]](#references)
{{#ref}}
@@ -117,7 +117,7 @@ There are several protections trying to prevent the exploitation of vulnerabilit
### Real-World Example: CVE-2026-2329 (Grandstream GXP1600 unauthenticated HTTP stack overflow)
-- `/app/bin/gs_web` (32-bit ARM) exposes `/cgi-bin/api.values.get` on TCP/80 with **no authentication**. The POST parameter `request` is colon-delimited; each character is copied into `char small_buffer[64]` and the token is NUL-terminated on `:` or end, **without any length check**, letting a single oversized token smash the saved registers/return address.
+- `/app/bin/gs_web` (32-bit ARM) exposes `/cgi-bin/api.values.get` on TCP/80 with **no authentication**. The POST parameter `request` is colon-delimited; each character is copied into `char small_buffer[64]` and the token is NUL-terminated on `:` or end, **without any length check**, letting a single oversized token smash the saved registers/return address.[[5]](#references)
- PoC overflow (crashes and shows attacker data in registers): `curl -ik http:///cgi-bin/api.values.get --data "request=$(python3 - <<'PY'\nprint('A'*256)\nPY)"`.
- **Delimiter-driven multi-NUL placement**: every colon restarts parsing and appends a trailing NUL. By using multiple overlong identifiers, each token’s terminator can be aligned to a different offset in the corrupted frame, letting the attacker place **several `0x00` bytes** even though each overflow normally adds only one. This is crucial because the non-PIE binary is mapped at `0x00008000`, so ROP gadget addresses embed NUL bytes.
- Example colon payload to drop five NULs at chosen offsets (lengths tuned per stack layout): `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE`
@@ -125,7 +125,7 @@ There are several protections trying to prevent the exploitation of vulnerabilit
### Real-World Example: CVE-2025-40596 (SonicWall SMA100)
-A good demonstration of why **`sscanf` should never be trusted for parsing untrusted input** appeared in 2025 in SonicWall’s SMA100 SSL-VPN appliance.
+A good demonstration of why **`sscanf` should never be trusted for parsing untrusted input** appeared in 2025 in SonicWall’s SMA100 SSL-VPN appliance.[[1]](#references)
The vulnerable routine inside `/usr/src/EasyAccess/bin/httpd` attempts to extract the version and endpoint from any URI that begins with `/__api__/`:
```c
@@ -152,7 +152,7 @@ Even though stack canaries abort the process, an attacker still gains a **Denial
### Real-World Example: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
-NVIDIA’s Triton Inference Server (≤ v25.06) contained multiple **stack-based overflows** reachable through its HTTP API.
+NVIDIA’s Triton Inference Server (≤ v25.06) contained multiple **stack-based overflows** reachable through its HTTP API.[[2]](#references)
The vulnerable pattern repeatedly appeared in `http_server.cc` and `sagemaker_server.cc`:
```c
@@ -202,7 +202,7 @@ A ~3 MB request is enough to overwrite the saved return address and **crash** th
### Real-World Example: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
-Synacktiv’s Pwn2Own 2025 chain abused a pre-auth overflow in `SYNO.BEE.AdminCenter.Auth` on port 5000. `AuthManagerImpl::ParseAuthInfo` Base64-decodes attacker input into a 4096-byte stack buffer but wrongly sets `decoded_len = auth_info->len`. Because the CGI worker forks per request, every child inherits the parent’s stack canary, so one stable overflow primitive is enough to both corrupt the stack and leak all required secrets.
+Synacktiv’s Pwn2Own 2025 chain abused a pre-auth overflow in `SYNO.BEE.AdminCenter.Auth` on port 5000. `AuthManagerImpl::ParseAuthInfo` Base64-decodes attacker input into a 4096-byte stack buffer but wrongly sets `decoded_len = auth_info->len`. Because the CGI worker forks per request, every child inherits the parent’s stack canary, so one stable overflow primitive is enough to both corrupt the stack and leak all required secrets.[[4]](#references)
#### Base64-decoded JSON as a structured overflow
The decoded blob must be valid JSON and include `"state"` and `"code"` keys; otherwise, the parser throws before the overflow is useful. Synacktiv solved this by Base64-encoding a payload that decodes to JSON, then a NUL byte, then the overflow stream. `strlen(decoded)` stops at the NUL so parsing succeeds, but `SLIBCBase64Decode` already overwrote the stack past the JSON object, covering the canary, saved RBP, and return address.
@@ -234,10 +234,11 @@ def bf_next_byte(prefix):
Once the library base is known, common gadgets (`pop rdi`, `pop rsi`, `mov [rdi], rsi; xor eax, eax; ret`) build an `arb_write` primitive that stages `/bin/bash`, `-c`, and the attacker command on the leaked stack address. Finally, the chain sets up the calling convention for `SLIBCExecl` (a BeeStation wrapper around `execl(2)`), yielding a root shell without needing a separate info-leak bug.
## References
-* [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
-* [Trail of Bits – Uncovering memory corruption in NVIDIA Triton](https://blog.trailofbits.com/2025/08/04/uncovering-memory-corruption-in-nvidia-triton-as-a-new-hire/)
-* [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
-* [Synacktiv – Breaking the BeeStation: Inside Our Pwn2Own 2025 Exploit Journey](https://www.synacktiv.com/en/publications/breaking-the-beestation-inside-our-pwn2own-2025-exploit-journey.html)
-* [Rapid7 – CVE-2026-2329 unauthenticated stack overflow in Grandstream GXP1600](https://www.rapid7.com/blog/post/ve-cve-2026-2329-critical-unauthenticated-stack-buffer-overflow-in-grandstream-gxp1600-voip-phones-fixed)
+
+- [1] [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
+- [2] [Trail of Bits – Uncovering memory corruption in NVIDIA Triton](https://blog.trailofbits.com/2025/08/04/uncovering-memory-corruption-in-nvidia-triton-as-a-new-hire/)
+- [3] [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
+- [4] [Synacktiv – Breaking the BeeStation: Inside Our Pwn2Own 2025 Exploit Journey](https://www.synacktiv.com/en/publications/breaking-the-beestation-inside-our-pwn2own-2025-exploit-journey.html)
+- [5] [Rapid7 – CVE-2026-2329 unauthenticated stack overflow in Grandstream GXP1600](https://www.rapid7.com/blog/post/ve-cve-2026-2329-critical-unauthenticated-stack-buffer-overflow-in-grandstream-gxp1600-voip-phones-fixed)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/pointer-redirecting.md b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
index 9c6366a2a72..41d6dc88901 100644
--- a/src/binary-exploitation/stack-overflow/pointer-redirecting.md
+++ b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
@@ -4,7 +4,7 @@
## String pointers
-If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
+If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.[[1]](#references)
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.
@@ -70,7 +70,7 @@ You can find an **example** of this in:
## Function pointers
-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`**).
+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`**).[[1]](#references)
Useful targets are not only explicit callback variables such as `void (*fp)()`. In practice, look for:
@@ -81,7 +81,7 @@ Useful targets are not only explicit callback variables such as `void (*fp)()`.
If the indirect call looks like `cb(ctx, len)` or `ops[idx](req)`, do not stop after finding the code pointer. In many real targets, the **context pointer / first argument** lives right next to the callback, so corrupting both fields is much more reliable than redirecting the function alone. Likewise, if the program selects the callback from a local table, corrupting the **index / selector** can be easier than replacing the whole function pointer.
-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.
+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.[[2]](#references)
### Pointer corruption to second-stage primitives
@@ -97,13 +97,13 @@ This is a good option when:
- 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
-A common real-world constraint is the **cleanup path**. If you corrupt locals that will later be passed to `free()`, `close()`, `gst_buffer_unmap()`, or another destructor-like helper, you may need to repoint them to **`NULL`** or a safe object first. Otherwise, allocator sanity checks or cleanup crashes can kill the process before your corrupted pointer is used.
+A common real-world constraint is the **cleanup path**. If you corrupt locals that will later be passed to `free()`, `close()`, `gst_buffer_unmap()`, or another destructor-like helper, you may need to repoint them to **`NULL`** or a safe object first. Otherwise, allocator sanity checks or cleanup crashes can kill the process before your corrupted pointer is used.[[4]](#references)
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.
+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.[[3]](#references)
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`**). Also, distinguish between plain indirect calls such as **`blr xN`** and authenticated ones such as **`blraa` / `blrab`**: the latter authenticate the branch target as part of the call, so redirecting the pointer to an unsigned gadget will usually fail even if the destination is executable. Therefore, when redirecting a stack function pointer on AArch64, prefer:
@@ -120,10 +120,10 @@ 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)
-- [https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
+- [1] [Stack buffer overflow internship notes – Pointer redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)
+- [2] [Exploiting CVE-2024-20017 four different ways](https://blog.coffinsec.com/0day/2024/08/30/exploiting-CVE-2024-20017-four-different-ways.html)
+- [3] [Arm – 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)
+- [4] [GHSL-2024-197: GStreamer security advisory](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/ret2win/README.md b/src/binary-exploitation/stack-overflow/ret2win/README.md
index a0e8464a397..de267cad4ee 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/README.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/README.md
@@ -80,30 +80,30 @@ The Python script sends a carefully crafted message that, when processed by the
- [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) should be also disabled or the compromised EIP return address won't never be followed.
-## Other examples & References
+## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
-- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
+- [1] [ir0nstone – Ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
+- [2] [Nightmare – tamu19 pwn1](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32bit, no ASLR
-- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
+- [3] [Nightmare – csaw16 warmup](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 bits with ASLR, with a leak of the bin address
-- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
+- [4] [Nightmare – csaw18 getit](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 bits, no ASLR
-- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
+- [5] [Nightmare – tu17 vulnchat](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
-- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
+- [6] [Nightmare – backdoor17 bbpwn](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
-- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
+- [7] [Nightmare – tamu19 pwn2](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
-- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
+- [8] [Nightmare – tuctf17 vulnchat2](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
-- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
+- [9] [Nightmare – integer overflow post](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
-- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
+- [10] [7rocky – fno-stack-protector (Black Hat CTF)](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
+- [11] [8kSec – ARM64 Reversing and Exploitation Part 3: A Simple ROP Chain](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
+- [12] [8kSec – ARM64 Reversing and Exploitation Part 9: Exploiting an Off-by-One Overflow](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64, off-by-one to call a win function
## ARM64 Example
diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
index 308d2cd65f0..440ef1fb9db 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
@@ -80,7 +80,7 @@ pattern search $x30
**The offset is 72 (9x48).**
-If you prefer **pwntools** for 64-bit patterns, generate the cyclic input with **8-byte unique subsequences**. The default `n=4` still works often, but on AArch64 it is cleaner to match the 8-byte saved `x30` directly:
+If you prefer **pwntools** for 64-bit patterns, generate the cyclic input with **8-byte unique subsequences**. The default `n=4` still works often, but on AArch64 it is cleaner to match the 8-byte saved `x30` directly:[[4]](#references)
```bash
python3 - << 'PY'
@@ -275,7 +275,7 @@ env DYLD_DISABLE_ASLR=1 ./bof_macos
### arm64e / PAC caveat
-On Apple Silicon, make sure you know whether you are testing a plain **`arm64`** binary or an **`arm64e`** slice. Apple uses **Pointer Authentication (PAC)** on `arm64e`, so a naive overwrite of `x30` may crash before your `win()` function runs with a message similar to **"possible pointer authentication failure"**. For a basic training lab, prefer a plain `arm64` slice; for real targets, assume you must stay PAC-compliant and reuse already-signed code/data pointers.
+On Apple Silicon, make sure you know whether you are testing a plain **`arm64`** binary or an **`arm64e`** slice. Apple uses **Pointer Authentication (PAC)** on `arm64e`, so a naive overwrite of `x30` may crash before your `win()` function runs with a message similar to **"possible pointer authentication failure"**. For a basic training lab, prefer a plain `arm64` slice; for real targets, assume you must stay PAC-compliant and reuse already-signed code/data pointers.[[3]](#references)
Quick checks:
@@ -526,11 +526,11 @@ p.interactive()
## Notes on modern AArch64 hardening (PAC/BTI) and ret2win
-- Current GCC/Clang toolchains support `-mbranch-protection=standard`, which enables the common PAC/BTI hardening profile. For labs, keep using `-mbranch-protection=none` so your saved-`x30` overwrite behaves like a classic ret2win.
+- Current GCC/Clang toolchains support `-mbranch-protection=standard`, which enables the common PAC/BTI hardening profile. For labs, keep using `-mbranch-protection=none` so your saved-`x30` overwrite behaves like a classic ret2win.[[1]](#references)
- If the binary is compiled with AArch64 Branch Protection, you may see `paciasp`/`autiasp` or `bti c` emitted in function prologues/epilogues. Some hardened entries use `paciasp`/`pacibsp` as the landing instruction instead of a separate `bti c`, so do not grep only for `bti`. In that case:
- Returning to an address that is not a valid BTI landing pad may raise a `SIGILL`. Prefer targeting the exact function entry that contains `bti c`.
- `pac-ret` signs functions that actually spill the return address to memory, so non-leaf functions are usually affected first. A leaf `win()` may still lack PAC unless the binary was built with `pac-ret+leaf`.
- - If PAC is enabled for returns, naive return-address overwrites may fail because the epilogue authenticates `x30`. For learning scenarios, rebuild with `-mbranch-protection=none` (shown above). When attacking real targets, prefer non-return hijacks (e.g., function pointer overwrites) or build ROP that never executes an `autiasp`/`ret` pair that authenticates your forged LR.
+ - If PAC is enabled for returns, naive return-address overwrites may fail because the epilogue authenticates `x30`. For learning scenarios, rebuild with `-mbranch-protection=none` (shown above). When attacking real targets, prefer non-return hijacks (e.g., function pointer overwrites) or build ROP that never executes an `autiasp`/`ret` pair that authenticates your forged LR.[[2]](#references)
- To check features quickly:
- `readelf --notes -W ./ret2win` and look for `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC` notes.
- `objdump -d ./ret2win | head -n 40` and look for `bti c`, `paciasp`, `autiasp`.
@@ -571,8 +571,8 @@ gdb-multiarch ./ret2win -ex 'set architecture arm64' -ex 'target remote :1234'
## References
-- GCC AArch64 options (`-mbranch-protection=standard`, `pac-ret`, `bti`). https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html
-- Enabling PAC and BTI on AArch64 for Linux (Arm Community, Nov 2024). https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64
-- Preparing your app to work with pointer authentication (Apple). https://developer.apple.com/documentation/security/preparing-your-app-to-work-with-pointer-authentication
-- pwntools cyclic documentation (`cyclic(..., n=8)` / `cyclic_find(..., n=8)`). https://docs.pwntools.com/en/stable/util/cyclic.html
+- [1] [GCC AArch64 options (`-mbranch-protection=standard`, `pac-ret`, `bti`)](https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html)
+- [2] [Enabling PAC and BTI on AArch64 for Linux (Arm Community, Nov 2024)](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64)
+- [3] [Preparing your app to work with pointer authentication (Apple)](https://developer.apple.com/documentation/security/preparing-your-app-to-work-with-pointer-authentication)
+- [4] [pwntools cyclic documentation (`cyclic(..., n=8)` / `cyclic_find(..., n=8)`)](https://docs.pwntools.com/en/stable/util/cyclic.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting.md b/src/binary-exploitation/stack-overflow/stack-pivoting.md
index 83221d2d869..41b889e83f4 100644
--- a/src/binary-exploitation/stack-overflow/stack-pivoting.md
+++ b/src/binary-exploitation/stack-overflow/stack-pivoting.md
@@ -23,7 +23,7 @@ And as the saved **EBP/RBP is in the stack** before the saved EIP/RIP, it's poss
This technique is particularly useful when you can **alter the saved EBP/RBP but have no direct way to change EIP/RIP**. It leverages the function epilogue behavior.
-If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode/ROP chain address is located (plus 8 bytes on amd64 / 4 bytes on x86 to account for the `pop`), you can indirectly control RIP. As the function returns, `leave` sets RSP to the crafted location and the subsequent `pop rbp` decreases RSP, **effectively making it point to an address stored by the attacker there**. Then `ret` will use that address.
+If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode/ROP chain address is located (plus 8 bytes on amd64 / 4 bytes on x86 to account for the `pop`), you can indirectly control RIP. As the function returns, `leave` sets RSP to the crafted location and the subsequent `pop rbp` decreases RSP, **effectively making it point to an address stored by the attacker there**. Then `ret` will use that address.[[1]](#references)[[2]](#references)
Note how you **need to know 2 addresses**: the address where ESP/RSP is going to go, and the value stored at that address that `ret` will consume.
@@ -44,7 +44,7 @@ Remember that before any of these addresses in the controlled area, there must b
There's a variant used when you can **only modify the least significant byte of the saved EBP/RBP**. In such a case, the memory location storing the address to jump to with **`ret`** must share the first three/five bytes with the original EBP/RBP so a 1-byte overwrite can redirect it. Usually the low byte (offset 0x00) is increased to jump as far as possible within a nearby page/aligned region.
-It’s also common to use a RET sled in the stack and put the real ROP chain at the end to make it more probable that the new RSP points inside the sled and the final ROP chain is executed.
+It’s also common to use a RET sled in the stack and put the real ROP chain at the end to make it more probable that the new RSP points inside the sled and the final ROP chain is executed.[[3]](#references)
### EBP Chaining
@@ -61,7 +61,7 @@ This way it's possible to chain several fake EBPs to control the flow of the pro
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), but more complex and only useful in edge-cases.
-Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
+Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function.[[8]](#references) This is the final payload from the page:
```python
from pwn import *
@@ -103,7 +103,7 @@ print(p.recvline())
## EBP might not be used
-As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations or with frame-pointer omission, the **EBP/RBP never controls ESP/RSP**. Therefore, any exploit working by controlling EBP/RBP will fail because the prologue/epilogue doesn’t restore from the frame pointer.
+As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations or with frame-pointer omission, the **EBP/RBP never controls ESP/RSP**. Therefore, any exploit working by controlling EBP/RBP will fail because the prologue/epilogue doesn’t restore from the frame pointer.[[9]](#references)
- Not optimized / frame pointer used:
@@ -137,7 +137,7 @@ On amd64 you’ll often see `pop rbp ; ret` instead of `leave ; ret`, but if the
### `pop rsp` gadget
-[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For that challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
+[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique.[[10]](#references) For that challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
@@ -230,7 +230,7 @@ A robust pivot strategy used in many CTFs/exploits:
### Windows: Destructor-loop weird-machine pivots (Revit RFA case study)
-Client-side parsers sometimes implement destructor loops that indirectly call a function pointer derived from attacker-controlled object fields. If each iteration offers exactly one indirect call (a “one-gadget” machine), you can convert this into a reliable stack pivot and ROP entry.
+Client-side parsers sometimes implement destructor loops that indirectly call a function pointer derived from attacker-controlled object fields. If each iteration offers exactly one indirect call (a “one-gadget” machine), you can convert this into a reliable stack pivot and ROP entry.[[7]](#references)
Observed in Autodesk Revit RFA deserialization (CVE-2025-5037):
@@ -286,10 +286,10 @@ grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wr
```
- Notes for labs/CTF:
- - Some modern distros enable SHSTK for CET-enabled binaries when hardware and glibc support is present. For controlled testing in VMs, SHSTK can be disabled system-wide via the kernel boot parameter `nousershstk`, or selectively enabled via glibc tunables during startup (see references). Don’t disable mitigations on production targets.
+ - Some modern distros enable SHSTK for CET-enabled binaries when hardware and glibc support is present. For controlled testing in VMs, SHSTK can be disabled system-wide via the kernel boot parameter `nousershstk`, or selectively enabled via glibc tunables during startup (see references). Don’t disable mitigations on production targets.[[5]](#references)
- JOP/COOP or SROP-based techniques might still be viable on some targets, but SHSTK specifically breaks `ret`-based pivots.
-- Windows note: Windows 10+ exposes user-mode and Windows 11 adds kernel-mode “Hardware-enforced Stack Protection” built on shadow stacks. CET-compatible processes prevent stack pivoting/ROP at `ret`; developers opt-in via CETCOMPAT and related policies (see reference).
+- Windows note: Windows 10+ exposes user-mode and Windows 11 adds kernel-mode “Hardware-enforced Stack Protection” built on shadow stacks. CET-compatible processes prevent stack pivoting/ROP at `ret`; developers opt-in via CETCOMPAT and related policies (see reference).[[6]](#references)
## ARM64
@@ -325,14 +325,17 @@ Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
## References
-- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
-- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
-- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
+- [1] [Binary ROP stack pivoting](https://bananamafia.dev/post/binary-rop-stackpivot/)
+- [2] [Stack Pivoting (ir0nstone notes)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
+- [3] [Nightmare: dcquals19 speedrun4 (stack pivot off-by-one)](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
-- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
+- [4] [Nightmare: insomnihack18 onewrite](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
-- Linux kernel documentation: Control-flow Enforcement Technology (CET) Shadow Stack — details on SHSTK, `nousershstk`, `/proc/$PID/status` flags, and enabling via `arch_prctl`. https://www.kernel.org/doc/html/next/x86/shstk.html
-- Microsoft Learn: Kernel Mode Hardware-enforced Stack Protection (CET shadow stacks on Windows). https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection
-- [Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)](https://www.thezdi.com/blog/2025/10/6/crafting-a-full-exploit-rce-from-a-crash-in-autodesk-revit-rfa-file-parsing)
+- [5] [Linux kernel documentation: Control-flow Enforcement Technology (CET) Shadow Stack](https://www.kernel.org/doc/html/next/x86/shstk.html)
+- [6] [Kernel Mode Hardware-enforced Stack Protection (Microsoft Learn)](https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection)
+- [7] [Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)](https://www.thezdi.com/blog/2025/10/6/crafting-a-full-exploit-rce-from-a-crash-in-autodesk-revit-rfa-file-parsing)
+- [8] [Stack Pivoting: leave; ret exploitation (ir0nstone)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)
+- [9] [Off-by-one and frame-pointer omission notes (stack-buffer-overflow-internship)](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1)
+- [10] [Stack Pivoting: pop rsp exploitation (ir0nstone)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
index cd1197d4206..bbd611052cb 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
@@ -78,9 +78,9 @@ The **NOP slide** (`asm('nop')`) is used to increase the chance that execution w
## Windows x64: Bypass NX with VirtualAlloc ROP (ret2stack shellcode)
-On modern Windows the stack is non-executable (DEP/NX). A common way to still execute stack-resident shellcode after a stack BOF is to build a 64-bit ROP chain that calls VirtualAlloc (or VirtualProtect) from the module Import Address Table (IAT) to make a region of the stack executable and then return into shellcode appended after the chain.
+On modern Windows the stack is non-executable (DEP/NX). A common way to still execute stack-resident shellcode after a stack BOF is to build a 64-bit ROP chain that calls VirtualAlloc (or VirtualProtect) from the module Import Address Table (IAT) to make a region of the stack executable and then return into shellcode appended after the chain.[[6]](#references)
-Key points (Win64 calling convention):
+Key points (Win64 calling convention):[[7]](#references)
- VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect)
- RCX = lpAddress → choose an address in the current stack (e.g., RSP) so the newly allocated RWX region overlaps your payload
- RDX = dwSize → large enough for your chain + shellcode (e.g., 0x1000)
@@ -150,23 +150,19 @@ Tips:
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) should be also disabled or the compromised EIP return address won't never be followed.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
-## Other Examples & References
+## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
-- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
+- [1] [ir0nstone - Stack Shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
+- [2] [Nightmare - csaw17 pilot](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- 64bit, ASLR with stack address leak, write shellcode and jump to it
-- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
+- [3] [Nightmare - tamu19 pwn3](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- 32 bit, ASLR with stack leak, write shellcode and jump to it
-- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
+- [4] [Nightmare - tu18 shellaeasy](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
+- [5] [ARM64 Reversing and Exploitation Part 4 - Using mprotect to bypass NX protection](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
-
-
-## References
-
-- [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
-- [VirtualAlloc documentation](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)
+- [6] [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
+- [7] [VirtualAlloc documentation](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
index aac01c05927..39cc95ea0a0 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
@@ -41,13 +41,13 @@ readelf -W -l ./bof | grep GNU_STACK
readelf --notes -W ./bof | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
```
-If you still see PAC/BTI notes or prologues such as `paciasp` / `autiasp`, the classic saved-`x30` overwrite may die before reaching your stack payload.
+If you still see PAC/BTI notes or prologues such as `paciasp` / `autiasp`, the classic saved-`x30` overwrite may die before reaching your stack payload.[[2]](#references)
### AArch64 shellcode reminders
- Linux syscalls pass arguments in **`x0`** to **`x7`**, place the syscall number in **`x8`**, and trigger the transition with **`svc #0`**.
- AArch64 instructions are always **4 bytes**, so a NOP sled is usually repeated `nop` instructions (`0xd503201f`, bytes `\x1f\x20\x03\xd5`) instead of x86's single-byte `\x90`.
-- Shellcode is usually **position independent** and commonly uses `adr` / `adrp` style addressing to reach embedded strings such as `/bin/sh`.
+- Shellcode is usually **position independent** and commonly uses `adr` / `adrp` style addressing to reach embedded strings such as `/bin/sh`.[[1]](#references)
### No ASLR & No canary - Stack Overflow
@@ -124,7 +124,7 @@ Check a macOS ret2win example in:
## References
-- [ARM64 Reversing And Exploitation Part 5 – Writing Shellcode](https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/)
-- [Enabling PAC and BTI on AArch64 for Linux](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64)
+- [1] [ARM64 Reversing And Exploitation Part 5 – Writing Shellcode](https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/)
+- [2] [Enabling PAC and BTI on AArch64 for Linux](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}}
diff --git a/src/binary-exploitation/stack-overflow/uninitialized-variables.md b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
index ac1619dc64c..f0a9150d11f 100644
--- a/src/binary-exploitation/stack-overflow/uninitialized-variables.md
+++ b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
@@ -65,7 +65,7 @@ int main() {
The classic "read-before-write" bug remains relevant because modern mitigations (ASLR, canaries) often rely on secrecy. Typical attack surfaces:
-- **Partially initialized structs copied to userland**: Kernel or drivers frequently `memset` only a length field and then `copy_to_user(&u, &local_struct, sizeof(local_struct))`. Padding and unused fields leak stack canary halves, saved frame pointers or kernel pointers. If the struct contains a function pointer, leaving it uninitialized may also allow **controlled overwrite** when later reused.
+- **Partially initialized structs copied to userland**: Kernel or drivers frequently `memset` only a length field and then `copy_to_user(&u, &local_struct, sizeof(local_struct))`. Padding and unused fields leak stack canary halves, saved frame pointers or kernel pointers. If the struct contains a function pointer, leaving it uninitialized may also allow **controlled overwrite** when later reused.[[2]](#references)
- **Uninitialized stack buffers reused as indexes/lengths**: An uninitialized `size_t len;` used to bound `read(fd, buf, len)` may give attackers out-of-bounds reads/writes or allow bypassing size checks when the stack slot still contains a large value from a prior call.
- **Compiler-added padding**: Even when individual members are initialized, implicit padding bytes between them are not. Copying the whole struct to userland leaks padding that often contains prior stack content (canaries, pointers).
- **ROP/Canary disclosure**: If a function copies a local struct to stdout for debugging, uninitialized padding can reveal the stack canary enabling subsequent stack overflow exploitation without brute-force.
@@ -90,7 +90,7 @@ ssize_t handler(int fd) {
## Mitigations & compiler options (keep in mind when bypassing)
- **Clang/GCC auto-init**: Recent toolchains expose `-ftrivial-auto-var-init=zero` or `-ftrivial-auto-var-init=pattern`, filling *every* automatic (stack) variable at function entry with zeros or a poison pattern (0xAA / 0xFE). This closes most uninitialized-stack info leaks and makes exploitation harder by converting secrets into known values.
-- **Linux kernel hardening**: Kernels built with `CONFIG_INIT_STACK_ALL` or the newer `CONFIG_INIT_STACK_ALL_PATTERN` zero/pattern-initialize every stack slot at function entry, wiping canaries/pointers that would otherwise leak. Look for distros shipping Clang-built kernels with these options enabled (common in 6.8+ hardening configs).
+- **Linux kernel hardening**: Kernels built with `CONFIG_INIT_STACK_ALL` or the newer `CONFIG_INIT_STACK_ALL_PATTERN` zero/pattern-initialize every stack slot at function entry, wiping canaries/pointers that would otherwise leak. Look for distros shipping Clang-built kernels with these options enabled (common in 6.8+ hardening configs).[[1]](#references)
- **Opt-out attributes**: Clang now allows `__attribute__((uninitialized))` on specific locals/structs to keep performance-critical areas uninitialized even when global auto-init is enabled. Review such annotations carefully—they often mark deliberate attack surface for side channels.
From an attacker perspective, knowing whether the binary was built with these flags determines if stack-leak primitives are viable or if you must pivot to heap/data-section disclosures.
@@ -103,12 +103,14 @@ From an attacker perspective, knowing whether the binary was built with these fl
## ARM64 Example
-This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
+This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.[[3]](#references)
## References
-- [CONFIG_INIT_STACK_ALL_PATTERN documentation](https://www.kernelconfig.io/config_init_stack_all_pattern)
-- [GHSL-2024-197: GStreamer uninitialized stack variable leading to function pointer overwrite](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
+- [1] [CONFIG_INIT_STACK_ALL_PATTERN documentation](https://www.kernelconfig.io/config_init_stack_all_pattern)
+- [2] [GHSL-2024-197: GStreamer uninitialized stack variable leading to function pointer overwrite](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
+- [3] [Exploiting an Uninitialized Stack Variable Vulnerability (ARM64 Reversing and Exploitation Part 6, 8ksec)](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/)
+
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/windows-seh-overflow.md b/src/binary-exploitation/stack-overflow/windows-seh-overflow.md
index 5eb4b9b84b7..4a23307e182 100644
--- a/src/binary-exploitation/stack-overflow/windows-seh-overflow.md
+++ b/src/binary-exploitation/stack-overflow/windows-seh-overflow.md
@@ -12,7 +12,7 @@ an attacker can take control of execution by:
1) Setting SEH to the address of a POP POP RET gadget in a non-protected module, so that when an exception is dispatched the gadget returns into attacker-controlled bytes, and
2) Using nSEH to redirect execution (typically a short jump) back into the large overflowing buffer where shellcode resides.
-This technique is specific to 32-bit processes (x86). On modern systems, prefer a module without SafeSEH and ASLR for the gadget. Bad characters often include 0x00, 0x0a, 0x0d (NUL/CR/LF) due to C-strings and HTTP parsing.
+This technique is specific to 32-bit processes (x86). On modern systems, prefer a module without SafeSEH and ASLR for the gadget. Bad characters often include 0x00, 0x0a, 0x0d (NUL/CR/LF) due to C-strings and HTTP parsing.[[3]](#references)
---
@@ -43,8 +43,8 @@ Validate by placing markers at those positions (e.g., nSEH=b"BB", SEH=b"CC"). Ke
You need a POP POP RET sequence to unwind the SEH frame and return into your nSEH bytes. Find it in a module without SafeSEH and ideally without ASLR:
-- Mona (Immunity/WinDbg): `!mona modules` then `!mona seh -m modulename`.
-- x64dbg plugin ERC.Xdbg: `ERC --SEH` to list POP POP RET gadgets and SafeSEH status.
+- Mona (Immunity/WinDbg): `!mona modules` then `!mona seh -m modulename`.[[4]](#references)
+- x64dbg plugin ERC.Xdbg: `ERC --SEH` to list POP POP RET gadgets and SafeSEH status.[[2]](#references)
Pick an address that contains no badchars when written little-endian (e.g., `p32(0x004094D8)`). Prefer gadgets inside the vulnerable binary if protections allow.
@@ -65,7 +65,7 @@ nasm> jmp -652 ; 8 bytes closer (to account for short-jmp hop)
E96FFDFFFF
```
-Layout idea for a 1000-byte payload with nSEH at offset 660:
+Layout idea for a 1000-byte payload with nSEH at offset 660:[[1]](#references)
```python
buffer_length = 1000
@@ -116,7 +116,7 @@ msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST= LP
## Delivering over HTTP (precise CRLF + Content-Length)
-When the vulnerable vector is an HTTP request body, craft a raw request with exact CRLFs and Content-Length so the server reads the entire overflowing body.
+When the vulnerable vector is an HTTP request body, craft a raw request with exact CRLFs and Content-Length so the server reads the entire overflowing body.[[1]](#references)
```python
# pip install pwntools
@@ -156,9 +156,10 @@ p.close()
- Service watchdogs that automatically restart on crash can make iterative exploit development easier.
## References
-- [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
-- [ERC.Xdbg – Exploit Research Plugin for x64dbg (SEH search)](https://github.com/Andy53/ERC.Xdbg)
-- [Corelan – Exploit writing tutorial part 7 (SEH)](https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-7-unicode-0day-buffer-overflow-seh-and-venetian-shellcode/)
-- [Mona.py – WinDbg/Immunity helper](https://github.com/corelan/mona)
+
+- [1] [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
+- [2] [ERC.Xdbg – Exploit Research Plugin for x64dbg (SEH search)](https://github.com/Andy53/ERC.Xdbg)
+- [3] [Corelan – Exploit writing tutorial part 7 (SEH)](https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-7-unicode-0day-buffer-overflow-seh-and-venetian-shellcode/)
+- [4] [Mona.py – WinDbg/Immunity helper](https://github.com/corelan/mona)
{{#include ../../banners/hacktricks-training.md}}
\ No newline at end of file
diff --git a/src/hardware-physical-access/escaping-from-gui-applications.md b/src/hardware-physical-access/escaping-from-gui-applications.md
index f67688fc3dc..faed42ec715 100644
--- a/src/hardware-physical-access/escaping-from-gui-applications.md
+++ b/src/hardware-physical-access/escaping-from-gui-applications.md
@@ -70,7 +70,7 @@ _bash, sh, zsh..._ More here: [https://gtfobins.github.io/](https://gtfobins.git
### Restricted Desktop Breakouts (Citrix/RDS/VDI)
-- **Dialog-box pivoting**: Use *Open/Save/Print-to-file* dialogs as Explorer-lite. Try `*.*` / `*.exe` in the filename field, right-click folders for **Open in new window**, and use **Properties → Open file location** to expand navigation.
+- **Dialog-box pivoting**: Use *Open/Save/Print-to-file* dialogs as Explorer-lite. Try `*.*` / `*.exe` in the filename field, right-click folders for **Open in new window**, and use **Properties → Open file location** to expand navigation.[[1]](#references)
- **Create execution paths from dialogs**: Create a new file and rename it to `.CMD` or `.BAT`, or create a shortcut pointing to `%WINDIR%\System32` (or a specific binary like `%WINDIR%\System32\cmd.exe`).
- **Shell launch pivots**: If you can browse to `cmd.exe`, try **drag-and-drop** any file onto it to launch a prompt. If Task Manager is reachable (`CTRL+SHIFT+ESC`), use **Run new task**.
- **Task Scheduler bypass**: If interactive shells are blocked but scheduling is allowed, create a task to run `cmd.exe` (GUI `taskschd.msc` or `schtasks.exe`).
@@ -181,7 +181,7 @@ Backup iKat versions:
[http://swin.es/k/](http://swin.es/k/)\
[http://www.ikat.kronicd.net/](http://www.ikat.kronicd.net)
-Create a common dialog using JavaScript and access file explorer: `document.write('')`\
+Create a common dialog using JavaScript and access file explorer: `document.write('')`[[6]](#references)\
Source: https://medium.com/@Rend\_/give-me-a-browser-ill-give-you-a-shell-de19811defa0
## iPad
@@ -198,11 +198,11 @@ Source: https://medium.com/@Rend\_/give-me-a-browser-ill-give-you-a-shell-de1981
- Swipe fast 1 finger from the centre of the screen to the right or left: To change to next/last App
- Press and hold the On/**Off**/Sleep button at the upper-right corner of the **iPad +** Move the Slide to **power off** slider all the way to the right: To power off
- Press the On/**Off**/Sleep button at the upper-right corner of the **iPad and the Home button for a few second**: To force a hard power off
-- Press the On/**Off**/Sleep button at the upper-right corner of the **iPad and the Home button quickly**: To take a screenshot that will pop up in the lower left of the display. Press both buttons at the same time very briefly as if you hold them a few seconds a hard power off will be performed.
+- Press the On/**Off**/Sleep button at the upper-right corner of the **iPad and the Home button quickly**: To take a screenshot that will pop up in the lower left of the display. Press both buttons at the same time very briefly as if you hold them a few seconds a hard power off will be performed.[[2]](#references)
### Shortcuts
-You should have an iPad keyboard or a USB keyboard adaptor. Only shortcuts that could help escaping from the application will be shown here.
+You should have an iPad keyboard or a USB keyboard adaptor. Only shortcuts that could help escaping from the application will be shown here.[[3]](#references)[[4]](#references)[[5]](#references)
| Key | Name |
| --- | ------------ |
@@ -291,10 +291,11 @@ These shortcuts are for the visual settings and sound settings, depending on the
## References
-- [https://www.pentestpartners.com/security-blog/breaking-out-of-citrix-and-other-restricted-desktop-environments/](https://www.pentestpartners.com/security-blog/breaking-out-of-citrix-and-other-restricted-desktop-environments/)
-- [https://www.macworld.com/article/2975857/6-only-for-ipad-gestures-you-need-to-know.html](https://www.macworld.com/article/2975857/6-only-for-ipad-gestures-you-need-to-know.html)
-- [https://www.tomsguide.com/us/ipad-shortcuts,news-18205.html](https://www.tomsguide.com/us/ipad-shortcuts,news-18205.html)
-- [https://thesweetsetup.com/best-ipad-keyboard-shortcuts/](https://thesweetsetup.com/best-ipad-keyboard-shortcuts/)
-- [http://www.iphonehacks.com/2018/03/ipad-keyboard-shortcuts.html](http://www.iphonehacks.com/2018/03/ipad-keyboard-shortcuts.html)
+- [1] [Breaking out of Citrix and other restricted desktop environments](https://www.pentestpartners.com/security-blog/breaking-out-of-citrix-and-other-restricted-desktop-environments/)
+- [2] [6 only-for-iPad gestures you need to know](https://www.macworld.com/article/2975857/6-only-for-ipad-gestures-you-need-to-know.html)
+- [3] [iPad keyboard shortcuts (Tom's Guide)](https://www.tomsguide.com/us/ipad-shortcuts,news-18205.html)
+- [4] [The Best iPad Keyboard Shortcuts](https://thesweetsetup.com/best-ipad-keyboard-shortcuts/)
+- [5] [iPad keyboard shortcuts (iPhone Hacks)](http://www.iphonehacks.com/2018/03/ipad-keyboard-shortcuts.html)
+- [6] [Give me a browser, I'll give you a shell](https://medium.com/@Rend_/give-me-a-browser-ill-give-you-a-shell-de19811defa0)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/README.md b/src/hardware-physical-access/firmware-analysis/README.md
index c2df5bd0e98..87a27e599e6 100644
--- a/src/hardware-physical-access/firmware-analysis/README.md
+++ b/src/hardware-physical-access/firmware-analysis/README.md
@@ -82,7 +82,7 @@ hexdump -C | head # might find signatures in header
fdisk -lu #lists a drives partition and filesystems if multiple
```
-If you don't find much with those tools check the **entropy** of the image with `binwalk -E `, if low entropy, then it's not likely to be encrypted. If high entropy, Its likely encrypted (or compressed in some way).
+If you don't find much with those tools check the **entropy** of the image with `binwalk -E `, if low entropy, then it's not likely to be encrypted. If high entropy, Its likely encrypted (or compressed in some way).[[2]](#references)
Moreover, you can use these tools to extract **files embedded inside the firmware**:
@@ -215,7 +215,7 @@ During firmware analysis you may find that `` is derived locally from the
- token = MD5( deviceId || STATIC_KEY ) and represented as uppercase hex
-This design enables anyone who learns a deviceId and the STATIC_KEY to reconstruct the URL and pull cloud config, often revealing plaintext MQTT credentials and topic prefixes.
+This design enables anyone who learns a deviceId and the STATIC_KEY to reconstruct the URL and pull cloud config, often revealing plaintext MQTT credentials and topic prefixes.[[5]](#references)
Practical workflow:
@@ -339,7 +339,7 @@ target remote :1234
### Zigbee / radio-co-processor message mapping
-On IoT hubs the RF stack is often split between a **radio MCU** and a Linux userland process. A useful workflow is to map the path:
+On IoT hubs the RF stack is often split between a **radio MCU** and a Linux userland process. A useful workflow is to map the path:[[8]](#references)
1. **RF frame** on the air
2. **controller-side parser** on the radio MCU
@@ -358,7 +358,7 @@ For Zigbee specifically, capture pairing traffic and check whether the target st
### Manufacturer-specific protocol handlers and FSM-gated reachability
-Vendor-specific Zigbee/ZCL commands are often a better target than standardized clusters because they feed **custom parsing code** and internal **FSMs** with less battle-tested validation.
+Vendor-specific Zigbee/ZCL commands are often a better target than standardized clusters because they feed **custom parsing code** and internal **FSMs** with less battle-tested validation.[[8]](#references)
Practical workflow:
@@ -371,7 +371,7 @@ For timing-sensitive protocols, packet replay from a Python framework may be too
### Fragmented-download bug class in embedded daemons
-A recurring firmware bug class appears in **fragmented blob/model/configuration downloads**:
+A recurring firmware bug class appears in **fragmented blob/model/configuration downloads**:[[8]](#references)
1. The **first fragment** (`offset == 0`) stores `ctx->total_size` and allocates `malloc(total_size)`.
2. Later fragments only validate the attacker-controlled **packet-local** fields such as `packet_total_size >= offset + chunk_len`.
@@ -393,7 +393,7 @@ In embedded daemons, the easiest way to trigger heap metadata exploitation is of
- Exceed the retry threshold so the daemon **resets context** and frees the corrupted buffer.
- Use this predictable `free()` to trigger allocator-side primitives before the process crashes for unrelated reasons.
-This is especially useful against **musl/uClibc/dlmalloc-like** allocators in embedded Linux, where corrupting chunk metadata can turn unlink/unbin logic into a write primitive. A stable pattern is to corrupt a **size field** to redirect allocator traversal into **fake chunks staged inside the overflowed buffer**, instead of immediately clobbering real bin pointers and crashing the process.
+This is especially useful against **musl/uClibc/dlmalloc-like** allocators in embedded Linux, where corrupting chunk metadata can turn unlink/unbin logic into a write primitive. A stable pattern is to corrupt a **size field** to redirect allocator traversal into **fake chunks staged inside the overflowed buffer**, instead of immediately clobbering real bin pointers and crashing the process.[[8]](#references)
## Binary Exploitation and Proof-of-Concept
@@ -454,7 +454,7 @@ firmware_v1.3.11.490_signed.bin
### Updater-only anti-rollback bypass in A/B slot designs
-Some vendors do implement an anti-downgrade **ratchet**, but only inside the *updater* logic (for example a UDS routine over CAN, a recovery command, or a userspace OTA agent). If the **bootloader** later checks only the image signature/CRC and trusts the partition table or slot metadata, rollback protection can still be bypassed.
+Some vendors do implement an anti-downgrade **ratchet**, but only inside the *updater* logic (for example a UDS routine over CAN, a recovery command, or a userspace OTA agent). If the **bootloader** later checks only the image signature/CRC and trusts the partition table or slot metadata, rollback protection can still be bypassed.[[7]](#references)
Typical weak design:
@@ -514,7 +514,7 @@ To practice discovering vulnerabilities in firmware, use the following vulnerabl
## Recovering firmware decryption keys from embedded KMS/Vault state
-When an update image mixes small plaintext metadata with a large high-entropy blob, do container triage before brute-forcing anything:
+When an update image mixes small plaintext metadata with a large high-entropy blob, do container triage before brute-forcing anything:[[4]](#references)
- Dump headers, offsets and line boundaries with `hexdump`, `xxd`, `strings -tx`, `base64 -d`, and `binwalk -E`.
- `Salted__` usually means OpenSSL `enc` format: the next 8 bytes are the salt and the remaining bytes are ciphertext.
@@ -559,13 +559,13 @@ This turns "encrypted firmware" into a more general problem: **recover the appli
## References
-- [Cracking Firmware with Claude: Senior-Level Skill, Junior-Level Autonomy](https://bishopfox.com/blog/cracking-firmware-with-claude-senior-level-skill-junior-level-autonomy)
-- [https://scriptingxss.gitbook.io/firmware-security-testing-methodology/](https://scriptingxss.gitbook.io/firmware-security-testing-methodology/)
-- [Practical IoT Hacking: The Definitive Guide to Attacking the Internet of Things](https://www.amazon.co.uk/Practical-IoT-Hacking-F-Chantzis/dp/1718500904)
-- [Exploiting zero days in abandoned hardware – Trail of Bits blog](https://blog.trailofbits.com/2025/07/25/exploiting-zero-days-in-abandoned-hardware/)
-- [How a $20 Smart Device Gave Me Access to Your Home](https://bishopfox.com/blog/how-a-20-smart-device-gave-me-access-to-your-home)
-- [Now You See mi: Now You're Pwned](https://labs.taszk.io/articles/post/nowyouseemi/)
-- [Synacktiv - Exploiting the Tesla Wall Connector from its charge port connector - Part 2: bypassing the anti-downgrade](https://www.synacktiv.com/en/publications/exploiting-the-tesla-wall-connector-from-its-charge-port-connector-part-2-bypassing)
-- [Make it Blink: Over-the-Air Exploitation of the Philips Hue Bridge](https://www.synacktiv.com/en/publications/make-it-blink-over-the-air-exploitation-of-the-philips-hue-bridge.html)
+- [1] [Cracking Firmware with Claude: Senior-Level Skill, Junior-Level Autonomy](https://bishopfox.com/blog/cracking-firmware-with-claude-senior-level-skill-junior-level-autonomy)
+- [2] [Firmware Security Testing Methodology](https://scriptingxss.gitbook.io/firmware-security-testing-methodology/)
+- [3] [Practical IoT Hacking: The Definitive Guide to Attacking the Internet of Things](https://www.amazon.co.uk/Practical-IoT-Hacking-F-Chantzis/dp/1718500904)
+- [4] [Exploiting zero days in abandoned hardware – Trail of Bits blog](https://blog.trailofbits.com/2025/07/25/exploiting-zero-days-in-abandoned-hardware/)
+- [5] [How a $20 Smart Device Gave Me Access to Your Home](https://bishopfox.com/blog/how-a-20-smart-device-gave-me-access-to-your-home)
+- [6] [Now You See mi: Now You're Pwned](https://labs.taszk.io/articles/post/nowyouseemi/)
+- [7] [Synacktiv - Exploiting the Tesla Wall Connector from its charge port connector - Part 2: bypassing the anti-downgrade](https://www.synacktiv.com/en/publications/exploiting-the-tesla-wall-connector-from-its-charge-port-connector-part-2-bypassing)
+- [8] [Make it Blink: Over-the-Air Exploitation of the Philips Hue Bridge](https://www.synacktiv.com/en/publications/make-it-blink-over-the-air-exploitation-of-the-philips-hue-bridge.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/android-mediatek-secure-boot-bl2_ext-bypass-el3.md b/src/hardware-physical-access/firmware-analysis/android-mediatek-secure-boot-bl2_ext-bypass-el3.md
index 690414e5583..a46887919b9 100644
--- a/src/hardware-physical-access/firmware-analysis/android-mediatek-secure-boot-bl2_ext-bypass-el3.md
+++ b/src/hardware-physical-access/firmware-analysis/android-mediatek-secure-boot-bl2_ext-bypass-el3.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-This page documents a practical secure-boot break on multiple MediaTek platforms by abusing a verification gap when the device bootloader configuration (seccfg) is "unlocked". The flaw allows running a patched bl2_ext at ARM EL3 to disable downstream signature verification, collapsing the chain of trust and enabling arbitrary unsigned TEE/GZ/LK/Kernel loading.
+This page documents a practical secure-boot break on multiple MediaTek platforms by abusing a verification gap when the device bootloader configuration (seccfg) is "unlocked". The flaw allows running a patched bl2_ext at ARM EL3 to disable downstream signature verification, collapsing the chain of trust and enabling arbitrary unsigned TEE/GZ/LK/Kernel loading.[[1]](#references)[[2]](#references)[[4]](#references)
> Caution: Early-boot patching can permanently brick devices if offsets are wrong. Always keep full dumps and a reliable recovery path.
@@ -18,7 +18,7 @@ Key trust boundary:
On affected devices, the Preloader does not enforce authentication of the bl2_ext partition when seccfg indicates an "unlocked" state. This allows flashing an attacker-controlled bl2_ext that runs at EL3.
-Inside bl2_ext, the verification policy function can be patched to unconditionally report that verification is not required (or always succeeds), forcing the boot chain to accept unsigned TEE/GZ/LK/Kernel images. Because this patch runs at EL3, it is effective even if downstream components implement their own checks.
+Inside bl2_ext, the verification policy function can be patched to unconditionally report that verification is not required (or always succeeds), forcing the boot chain to accept unsigned TEE/GZ/LK/Kernel images. Because this patch runs at EL3, it is effective even if downstream components implement their own checks.[[1]](#references)
## Practical exploit chain
@@ -56,7 +56,7 @@ Ensure the patch preserves stack/frame setup and returns expected status codes t
## Fenrir PoC workflow (Nothing/CMF)
-Fenrir is a reference patching toolkit for this issue (Nothing Phone (2a) fully supported; CMF Phone 1 partially). High level:
+Fenrir is a reference patching toolkit for this issue (Nothing Phone (2a) fully supported; CMF Phone 1 partially).[[1]](#references) High level:
- Place the device bootloader image as `bin/.bin`.
- Build a patched image that disables the bl2_ext verification policy.
- Flash the resulting payload (fastboot helper provided).
@@ -85,12 +85,12 @@ Use another flashing channel if fastboot is unavailable.
- Confirmed supported: Nothing Phone (2a) (Pacman)
- Known working (incomplete support): CMF Phone 1 (Tetris)
- Observed: Vivo X80 Pro reportedly did not verify bl2_ext even when locked
-- NothingOS 4 stable (BP2A.250605.031.A3, Nov 2025) re-enabled bl2_ext verification; fenrir `pacman-v2.0` restores the bypass by mixing the beta Preloader with a patched LK
+- NothingOS 4 stable (BP2A.250605.031.A3, Nov 2025) re-enabled bl2_ext verification; fenrir `pacman-v2.0` restores the bypass by mixing the beta Preloader with a patched LK[[3]](#references)
- Industry coverage highlights additional lk2-based vendors shipping the same logic flaw, so expect further overlap across 2024–2025 MTK releases.
## MTK DA readback and seccfg manipulation with Penumbra
-Penumbra is a Rust crate/CLI/TUI that automates interaction with MTK preloader/bootrom over USB for DA-mode operations. With physical access to a vulnerable handset (DA extensions allowed), it can discover the MTK USB port, load a Download Agent (DA) blob, and issue privileged commands such as seccfg lock flipping and partition readback.
+Penumbra is a Rust crate/CLI/TUI that automates interaction with MTK preloader/bootrom over USB for DA-mode operations. With physical access to a vulnerable handset (DA extensions allowed), it can discover the MTK USB port, load a Download Agent (DA) blob, and issue privileged commands such as seccfg lock flipping and partition readback.[[5]](#references)
- **Environment/driver setup**: On Linux install `libudev`, add the user to the `dialout` group, and create udev rules or run with `sudo` if the device node is not accessible. Windows support is unreliable; it sometimes works only after replacing the MTK driver with WinUSB using Zadig (per project guidance).
- **Workflow**: Read a DA payload (e.g., `std::fs::read("../DA_penangf.bin")`), poll for the MTK port with `find_mtk_port()`, and build a session using `DeviceBuilder::with_mtk_port(...).with_da_data(...)`. After `init()` completes the handshake and gathers device info, check protections via `dev_info.target_config()` bitfields (bit 0 set → SBC enabled). Enter DA mode and attempt `set_seccfg_lock_state(LockFlag::Unlock)`—this only succeeds if the device accepts extensions. Partitions can be dumped with `read_partition("lk_a", &mut progress_cb, &mut writer)` for offline analysis or patching.
@@ -136,10 +136,10 @@ async fn main() -> Result<()> {
## References
-- [Fenrir – MediaTek bl2_ext secure‑boot bypass (PoC)](https://github.com/R0rt1z2/fenrir)
-- [Cyber Security News – PoC Exploit Released For Nothing Phone Code Execution Vulnerability](https://cybersecuritynews.com/nothing-phone-code-execution-vulnerability/)
-- [Fenrir pacman-v2.0 release (NothingOS 4 bypass bundle)](https://github.com/R0rt1z2/fenrir/releases/tag/pacman-v2.0)
-- [The Cyber Express – Fenrir PoC breaks secure boot on Nothing Phone 2a/CMF1](https://thecyberexpress.com/fenrir-poc-for-nothing-phone-2a-cmf1/)
-- [Penumbra – MTK DA flash/readback & seccfg tooling](https://github.com/shomykohai/penumbra)
+- [1] [Fenrir – MediaTek bl2_ext secure‑boot bypass (PoC)](https://github.com/R0rt1z2/fenrir)
+- [2] [Cyber Security News – PoC Exploit Released For Nothing Phone Code Execution Vulnerability](https://cybersecuritynews.com/nothing-phone-code-execution-vulnerability/)
+- [3] [Fenrir pacman-v2.0 release (NothingOS 4 bypass bundle)](https://github.com/R0rt1z2/fenrir/releases/tag/pacman-v2.0)
+- [4] [The Cyber Express – Fenrir PoC breaks secure boot on Nothing Phone 2a/CMF1](https://thecyberexpress.com/fenrir-poc-for-nothing-phone-2a-cmf1/)
+- [5] [Penumbra – MTK DA flash/readback & seccfg tooling](https://github.com/shomykohai/penumbra)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/bootloader-testing.md b/src/hardware-physical-access/firmware-analysis/bootloader-testing.md
index 609b03cb401..7bd8806e7a4 100644
--- a/src/hardware-physical-access/firmware-analysis/bootloader-testing.md
+++ b/src/hardware-physical-access/firmware-analysis/bootloader-testing.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-The following steps are recommended for modifying device startup configurations and testing bootloaders such as U-Boot and UEFI-class loaders. Focus on getting early code execution, assessing signature/rollback protections, and abusing recovery or network-boot paths.
+The following steps are recommended for modifying device startup configurations and testing bootloaders such as U-Boot and UEFI-class loaders. Focus on getting early code execution, assessing signature/rollback protections, and abusing recovery or network-boot paths.[[1]](#references)
Related: MediaTek secure-boot bypass via bl2_ext patching:
@@ -63,7 +63,7 @@ android-mediatek-secure-boot-bl2_ext-bypass-el3.md
# tftpboot ${loadaddr} fit-signed.itb; bootm ${loadaddr} # should only boot if key trusted
```
- Absence of `CONFIG_FIT_SIGNATURE`/`CONFIG_(SPL_)FIT_SIGNATURE` or legacy `verify=n` behavior often allows booting arbitrary payloads.
- - Don’t stop at a simple allow/deny result: recent FIT research showed that the verification path itself can be a pre-auth attack surface. Negative-test externally stored FIT data (`data-offset`, `data-position`, `data-size`), signed configuration selection, `loadables`, and overlay / `extra-conf` handling.
+ - Don’t stop at a simple allow/deny result: recent FIT research showed that the verification path itself can be a pre-auth attack surface. Negative-test externally stored FIT data (`data-offset`, `data-position`, `data-size`), signed configuration selection, `loadables`, and overlay / `extra-conf` handling.[[9]](#references)
- If you have a matching source tree, `test/vboot/vboot_test.sh` is a fast way to reproduce FIT verification behaviour in U-Boot sandbox before touching real hardware.
8. Standard Boot (`bootstd`), `extlinux`, and script bootflows
@@ -78,12 +78,12 @@ android-mediatek-secure-boot-bl2_ext-bypass-el3.md
# bootmeth order "extlinux script pxe"
```
- Abuse cases to test: attacker-controlled USB/SD media earlier in `boot_targets`, writable `/boot/extlinux/extlinux.conf`, rogue TFTP supplying `boot.scr`, or SPI-backed script execution via `script_offset_f`.
- - If the platform relies on FIT verification, make sure configurations are signed at the configuration level and not only per-image; `required-mode=all` is stronger than accepting any single required key.
+ - If the platform relies on FIT verification, make sure configurations are signed at the configuration level and not only per-image; `required-mode=all` is stronger than accepting any single required key.[[9]](#references)
## Network-boot surface (DHCP/PXE) and rogue servers
9. PXE/DHCP parameter fuzzing
- - U-Boot’s legacy BOOTP/DHCP handling has had memory-safety issues. For example, CVE‑2024‑42040 describes memory disclosure via crafted DHCP responses that can leak bytes from U-Boot memory back on the wire. Exercise the DHCP/PXE code paths with overly long/edge-case values (option 67 bootfile-name, vendor options, file/servername fields) and observe for hangs/leaks.
+ - U-Boot’s legacy BOOTP/DHCP handling has had memory-safety issues. For example, CVE‑2024‑42040 describes memory disclosure via crafted DHCP responses that can leak bytes from U-Boot memory back on the wire. Exercise the DHCP/PXE code paths with overly long/edge-case values (option 67 bootfile-name, vendor options, file/servername fields) and observe for hangs/leaks.[[3]](#references)
- Minimal Scapy snippet to stress boot parameters during netboot:
```python
from scapy.all import *
@@ -136,7 +136,7 @@ Assess whether the device has secure-boot eFuses/OTP burned. If not, BootROM dow
- Try booting with downgraded or known-vulnerable signed boot components if Secure Boot revocations (dbx) aren’t current. If the platform still trusts old shims/bootmanagers, you can often load your own kernel or `grub.cfg` from the ESP to gain persistence.
12. Stale shim / SBAT / dbx revocation testing
- - Old Microsoft-signed shims and vendor forks can still act as a BYOVD-style bootkit path if revocations are stale. In an isolated lab, place a historically vulnerable shim on the ESP and attempt to chainload your own `grubx64.efi` or kernel.
+ - Old Microsoft-signed shims and vendor forks can still act as a BYOVD-style bootkit path if revocations are stale. In an isolated lab, place a historically vulnerable shim on the ESP and attempt to chainload your own `grubx64.efi` or kernel.[[10]](#references)
- Quick triage:
```bash
sbverify --list shimx64.efi
@@ -146,12 +146,12 @@ Assess whether the device has secure-boot eFuses/OTP burned. If not, BootROM dow
- If the shim still runs despite being on the revocation list, the firmware/OS has stale `dbx` updates or trusts a forked loader that never inherited upstream SBAT protections.
13. Boot logo parsing bugs (LogoFAIL class)
- - Several OEM/IBV firmwares were vulnerable to image-parsing flaws in DXE that process boot logos. If an attacker can place a crafted image on the ESP under a vendor-specific path (e.g., `\EFI\\logo\*.bmp`) and reboot, code execution during early boot may be possible even with Secure Boot enabled. Test whether the platform accepts user-supplied logos and whether those paths are writable from the OS.
+ - Several OEM/IBV firmwares were vulnerable to image-parsing flaws in DXE that process boot logos. If an attacker can place a crafted image on the ESP under a vendor-specific path (e.g., `\EFI\\logo\*.bmp`) and reboot, code execution during early boot may be possible even with Secure Boot enabled. Test whether the platform accepts user-supplied logos and whether those paths are writable from the OS.[[2]](#references)
## Android/Qualcomm ABL + GBL (Android 16) trust gaps
-On Android 16 devices that use Qualcomm's ABL to load the **Generic Bootloader Library (GBL)**, validate whether ABL **authenticates** the UEFI app it loads from the `efisp` partition. If ABL only checks for a UEFI app **presence** and does not verify signatures, a write primitive to `efisp` becomes **pre-OS unsigned code execution** at boot.
+On Android 16 devices that use Qualcomm's ABL to load the **Generic Bootloader Library (GBL)**, validate whether ABL **authenticates** the UEFI app it loads from the `efisp` partition. If ABL only checks for a UEFI app **presence** and does not verify signatures, a write primitive to `efisp` becomes **pre-OS unsigned code execution** at boot.[[4]](#references)[[6]](#references)
Practical checks and abuse paths:
@@ -160,13 +160,13 @@ Practical checks and abuse paths:
```bash
fastboot oem set-gpu-preemption 0 androidboot.selinux=permissive
```
- If the device is patched, the command should reject extra arguments.
-- **Bootloader unlock via persistent flags**: A boot-stage payload can flip persistent unlock flags (e.g., `is_unlocked=1`, `is_unlocked_critical=1`) to emulate `fastboot oem unlock` without OEM server/approval gates. This is a durable posture change after the next reboot.
+ If the device is patched, the command should reject extra arguments.[[5]](#references)
+- **Bootloader unlock via persistent flags**: A boot-stage payload can flip persistent unlock flags (e.g., `is_unlocked=1`, `is_unlocked_critical=1`) to emulate `fastboot oem unlock` without OEM server/approval gates. This is a durable posture change after the next reboot.[[5]](#references)
Defensive/triage notes:
- Confirm whether ABL performs signature verification on the GBL/UEFI payload from `efisp`. If not, treat `efisp` as a high‑risk persistence surface.
-- Track whether ABL fastboot OEM handlers are patched to **validate argument counts** and reject additional tokens.
+- Track whether ABL fastboot OEM handlers are patched to **validate argument counts** and reject additional tokens.[[7]](#references)[[8]](#references)
## Hardware caution
@@ -181,14 +181,14 @@ Be cautious when interacting with SPI/NAND flash during early boot (e.g., ground
## References
-- [https://scriptingxss.gitbook.io/firmware-security-testing-methodology/](https://scriptingxss.gitbook.io/firmware-security-testing-methodology/)
-- [https://www.binarly.io/blog/finding-logofail-the-dangers-of-image-parsing-during-system-boot](https://www.binarly.io/blog/finding-logofail-the-dangers-of-image-parsing-during-system-boot)
-- [https://nvd.nist.gov/vuln/detail/CVE-2024-42040](https://nvd.nist.gov/vuln/detail/CVE-2024-42040)
-- [https://www.androidauthority.com/qualcomm-snapdragon-8-elite-gbl-exploit-bootloader-unlock-3648651/](https://www.androidauthority.com/qualcomm-snapdragon-8-elite-gbl-exploit-bootloader-unlock-3648651/)
-- [https://bestwing.me/preempted-unlocking-xiaomi-via-two-unsanitized-strings.html](https://bestwing.me/preempted-unlocking-xiaomi-via-two-unsanitized-strings.html)
-- [https://source.android.com/docs/core/architecture/bootloader/generic-bootloader](https://source.android.com/docs/core/architecture/bootloader/generic-bootloader)
-- [https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f09c2fe3d6c42660587460e31be50c18c8c777ab](https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f09c2fe3d6c42660587460e31be50c18c8c777ab)
-- [https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/78297e8cfe091fc59c42fc33d3490e2008910fe2](https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/78297e8cfe091fc59c42fc33d3490e2008910fe2)
-- [https://www.binarly.io/blog/unfit-to-boot-breaking-u-boots-fit-signature-verification](https://www.binarly.io/blog/unfit-to-boot-breaking-u-boots-fit-signature-verification)
-- [https://kb.cert.org/vuls/id/616257](https://kb.cert.org/vuls/id/616257)
+- [1] [OWASP Firmware Security Testing Methodology](https://scriptingxss.gitbook.io/firmware-security-testing-methodology/)
+- [2] [Finding LogoFAIL: The Dangers of Image Parsing During System Boot](https://www.binarly.io/blog/finding-logofail-the-dangers-of-image-parsing-during-system-boot)
+- [3] [CVE-2024-42040 (U-Boot DHCP memory disclosure)](https://nvd.nist.gov/vuln/detail/CVE-2024-42040)
+- [4] [Qualcomm Snapdragon 8 Elite GBL exploit and bootloader unlock](https://www.androidauthority.com/qualcomm-snapdragon-8-elite-gbl-exploit-bootloader-unlock-3648651/)
+- [5] [Preempted: Unlocking Xiaomi via two unsanitized strings](https://bestwing.me/preempted-unlocking-xiaomi-via-two-unsanitized-strings.html)
+- [6] [Generic Bootloader (GBL) - Android Open Source Project](https://source.android.com/docs/core/architecture/bootloader/generic-bootloader)
+- [7] [CodeLinaro ABL/edk2 commit f09c2fe3](https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/f09c2fe3d6c42660587460e31be50c18c8c777ab)
+- [8] [CodeLinaro ABL/edk2 commit 78297e8c](https://git.codelinaro.org/clo/la/abl/tianocore/edk2/-/commit/78297e8cfe091fc59c42fc33d3490e2008910fe2)
+- [9] [unFIT to Boot: Breaking U-Boot's FIT Signature Verification](https://www.binarly.io/blog/unfit-to-boot-breaking-u-boots-fit-signature-verification)
+- [10] [Microsoft-signed UEFI shim bootloaders vulnerable to Secure Boot bypass (VU#616257)](https://kb.cert.org/vuls/id/616257)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/firmware-integrity.md b/src/hardware-physical-access/firmware-analysis/firmware-integrity.md
index 0b4f9794b39..85be97ef44b 100644
--- a/src/hardware-physical-access/firmware-analysis/firmware-integrity.md
+++ b/src/hardware-physical-access/firmware-analysis/firmware-integrity.md
@@ -26,7 +26,7 @@ If a root shell has already been obtained through dynamic analysis, bootloader m
## Unauthenticated transport bridges to privileged update protocols
-A common embedded design mistake is exposing the **same internal command protocol over several transports** but enforcing authentication on only one of them. For example, USB may require challenge-response while BLE simply forwards unauthenticated **GATT writes** into the same privileged firmware-update handler.
+A common embedded design mistake is exposing the **same internal command protocol over several transports** but enforcing authentication on only one of them. For example, USB may require challenge-response while BLE simply forwards unauthenticated **GATT writes** into the same privileged firmware-update handler.[[1]](#references)
Typical offensive workflow:
@@ -57,7 +57,7 @@ Things to verify while reversing:
## Checksum-only firmware containers are still attacker-controlled firmware
-A firmware container protected only by an **unkeyed checksum** (CRC32, SHA-256, MD5, etc.) provides corruption detection, **not authenticity**. If the attacker can reach the update routine, they can patch the image, recompute the checksum, and flash arbitrary code.
+A firmware container protected only by an **unkeyed checksum** (CRC32, SHA-256, MD5, etc.) provides corruption detection, **not authenticity**. If the attacker can reach the update routine, they can patch the image, recompute the checksum, and flash arbitrary code.[[1]](#references)
Red flags during RE:
@@ -78,7 +78,7 @@ If this works over a remotely reachable transport such as BLE/Wi-Fi, the bug is
## Turning a trusted USB peripheral into BadUSB via firmware reflashing
-When the target device is already trusted by the host over USB, malicious firmware may not need to implement a full new USB stack. A much easier pivot is often to **reuse existing HID support**.
+When the target device is already trusted by the host over USB, malicious firmware may not need to implement a full new USB stack. A much easier pivot is often to **reuse existing HID support**.[[1]](#references)
Useful pattern:
@@ -99,7 +99,7 @@ This turns firmware compromise into **host compromise** because the PC will trus
## Reliable payload execution inside RTOS firmware
-Instead of inserting fragile trampolines into random code paths, look for **existing RTOS tasks** that are unused or low-impact in normal operation.
+Instead of inserting fragile trampolines into random code paths, look for **existing RTOS tasks** that are unused or low-impact in normal operation.[[1]](#references)
Why this is useful:
@@ -111,7 +111,7 @@ Good targets are diagnostic, factory-test, telemetry, or coprocessor service tas
## Fast exploit iteration: repurpose benign protocol handlers
-Once firmware patching is possible, a compact way to accelerate RE is to overwrite a harmless command handler (for example an **echo/debug opcode**) with custom **memory read / write / execute** primitives. This avoids full reflashing for every experiment and is especially useful when the device supports the modified handler over a fast wired transport.
+Once firmware patching is possible, a compact way to accelerate RE is to overwrite a harmless command handler (for example an **echo/debug opcode**) with custom **memory read / write / execute** primitives. This avoids full reflashing for every experiment and is especially useful when the device supports the modified handler over a fast wired transport.[[1]](#references)
Use this to:
@@ -122,6 +122,6 @@ Use this to:
## References
-- [Pwnd Blaster: Hacking your PC using your speaker without ever touching it](https://blog.nns.ee/2026/06/03/katana-badusb/)
+- [1] [Pwnd Blaster: Hacking your PC using your speaker without ever touching it](https://blog.nns.ee/2026/06/03/katana-badusb/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/mediatek-xflash-carbonara-da2-hash-bypass.md b/src/hardware-physical-access/firmware-analysis/mediatek-xflash-carbonara-da2-hash-bypass.md
index 2d59c43f50c..16cebce7605 100644
--- a/src/hardware-physical-access/firmware-analysis/mediatek-xflash-carbonara-da2-hash-bypass.md
+++ b/src/hardware-physical-access/firmware-analysis/mediatek-xflash-carbonara-da2-hash-bypass.md
@@ -4,7 +4,7 @@
## Summary
-"Carbonara" abuses MediaTek's XFlash download path to run a modified Download Agent stage 2 (DA2) despite DA1 integrity checks. DA1 stores the expected SHA-256 of DA2 in RAM and compares it before branching. On many loaders, the host fully controls the DA2 load address/size, giving an unchecked memory write that can overwrite that in-memory hash and redirect execution to arbitrary payloads (pre-OS context with cache invalidation handled by DA).
+"Carbonara" abuses MediaTek's XFlash download path to run a modified Download Agent stage 2 (DA2) despite DA1 integrity checks. DA1 stores the expected SHA-256 of DA2 in RAM and compares it before branching. On many loaders, the host fully controls the DA2 load address/size, giving an unchecked memory write that can overwrite that in-memory hash and redirect execution to arbitrary payloads (pre-OS context with cache invalidation handled by DA).[[1]](#references)
## Trust boundary in XFlash (DA1 → DA2)
@@ -18,7 +18,7 @@
2. **Hash-slot overwrite:** Send a small payload that scans DA1 memory for the stored DA2-expected hash and overwrites it with the SHA-256 of the attacker-modified DA2. This leverages the user-controlled load to land the payload where the hash resides.
3. **Second `BOOT_TO` + digest:** Trigger another `BOOT_TO` with the patched DA2 metadata and send the raw 32-byte digest matching the modified DA2. DA1 recomputes SHA-256 over the received DA2, compares it against the now-patched expected hash, and the jump succeeds into attacker code.
-Because load address/size are attacker-controlled, the same primitive can write anywhere in memory (not just the hash buffer), enabling early-boot implants, secure-boot bypass helpers, or malicious rootkits.
+Because load address/size are attacker-controlled, the same primitive can write anywhere in memory (not just the hash buffer), enabling early-boot implants, secure-boot bypass helpers, or malicious rootkits.[[1]](#references)
## Minimal PoC pattern (mtkclient-style)
@@ -35,17 +35,17 @@ if self.xsend(self.Cmd.BOOT_TO):
- `payload` replicates the paid-tool blob that patches the expected-hash buffer inside DA1.
- `sha256(...).digest()` sends raw bytes (not hex) so DA1 compares against the patched buffer.
-- DA2 can be any attacker-built image; choosing the load address/size allows arbitrary memory placement with cache invalidation handled by DA.
+- DA2 can be any attacker-built image; choosing the load address/size allows arbitrary memory placement with cache invalidation handled by DA.[[3]](#references)
## Patch landscape (hardened loaders)
- **Mitigation**: Updated DAs hardcode the DA2 load address to `0x40000000` and ignore the address the host supplies, so writes cannot reach the DA1 hash slot (~0x200000 range). The hash remains computed but no longer attacker-writable.
-- **Detecting patched DAs**: mtkclient/penumbra scan DA1 for patterns indicating the address-hardening; if found, Carbonara is skipped. Old DAs expose writable hash slots (commonly around offsets like `0x22dea4` in V5 DA1) and remain exploitable.
+- **Detecting patched DAs**: mtkclient/penumbra scan DA1 for patterns indicating the address-hardening; if found, Carbonara is skipped. Old DAs expose writable hash slots (commonly around offsets like `0x22dea4` in V5 DA1) and remain exploitable.[[3]](#references)
- **V5 vs V6**: Some V6 (XML) loaders still accept user-supplied addresses; newer V6 binaries usually enforce the fixed address and are immune to Carbonara unless downgraded.
## Post-Carbonara (heapb8) note
-MediaTek patched Carbonara; a newer vulnerability, **heapb8**, targets the DA2 USB file download handler on patched V6 loaders, giving code execution even when `boot_to` is hardened. It abuses a heap overflow during chunked file transfers to seize DA2 control flow. The exploit is public in Penumbra/mtk-payloads and demonstrates that Carbonara fixes do not close all DA attack surface.
+MediaTek patched Carbonara; a newer vulnerability, **heapb8**, targets the DA2 USB file download handler on patched V6 loaders, giving code execution even when `boot_to` is hardened. It abuses a heap overflow during chunked file transfers to seize DA2 control flow. The exploit is public in Penumbra/mtk-payloads and demonstrates that Carbonara fixes do not close all DA attack surface.[[4]](#references)
## Notes for triage and hardening
@@ -54,9 +54,9 @@ MediaTek patched Carbonara; a newer vulnerability, **heapb8**, targets the DA2 U
## References
-- [Carbonara: The MediaTek exploit nobody served](https://shomy.is-a.dev/blog/article/serving-carbonara)
-- [Carbonara exploit documentation](https://shomy.is-a.dev/penumbra/Mediatek/Exploits/Carbonara)
-- [Penumbra Carbonara source code](https://github.com/shomykohai/penumbra/blob/main/core/src/exploit/carbonara.rs)
-- [heapb8: exploiting patched V6 Download Agents](https://blog.r0rt1z2.com/posts/exploiting-mediatek-datwo/)
+- [1] [Carbonara: The MediaTek exploit nobody served](https://shomy.is-a.dev/blog/article/serving-carbonara)
+- [2] [Carbonara exploit documentation](https://shomy.is-a.dev/penumbra/Mediatek/Exploits/Carbonara)
+- [3] [Penumbra Carbonara source code](https://github.com/shomykohai/penumbra/blob/main/core/src/exploit/carbonara.rs)
+- [4] [heapb8: exploiting patched V6 Download Agents](https://blog.r0rt1z2.com/posts/exploiting-mediatek-datwo/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md b/src/hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md
index 21aee1313b6..8d177b784da 100644
--- a/src/hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md
+++ b/src/hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md
@@ -6,7 +6,7 @@
Several Synology devices (DSM/BSM NAS, BeeStation, …) distribute their firmware and application packages in **encrypted PAT / SPK archives**. Those archives can be decrypted *offline* with nothing but the public download files thanks to hard-coded keys embedded inside the official extraction libraries.
-This page documents, step-by-step, how the encrypted format works and how to fully recover the clear-text **TAR** that sits inside each package. The procedure is based on Synacktiv research performed during Pwn2Own Ireland 2024 and implemented in the open-source tool [`synodecrypt`](https://github.com/synacktiv/synodecrypt).
+This page documents, step-by-step, how the encrypted format works and how to fully recover the clear-text **TAR** that sits inside each package. The procedure is based on Synacktiv research performed during Pwn2Own Ireland 2024 and implemented in the open-source tool [`synodecrypt`](https://github.com/synacktiv/synodecrypt).[[1]](#references)[[2]](#references)
> ⚠️ The format is exactly the same for both `*.pat` (system update) and `*.spk` (application) archives – they only differ in the pair of hard-coded keys that are selected.
@@ -22,7 +22,7 @@ $ wget https://archive.synology.com/download/Os/BSM/BSM_BST150-4T_65374.pat
## 2. Dump the PAT structure (optional)
-`*.pat` images are themselves a **cpio bundle** that embeds several files (boot loader, kernel, rootfs, packages…). The free utility [`patology`](https://github.com/sud0woodo/patology) is convenient to inspect that wrapper:
+`*.pat` images are themselves a **cpio bundle** that embeds several files (boot loader, kernel, rootfs, packages…). The free utility [`patology`](https://github.com/sud0woodo/patology) is convenient to inspect that wrapper:[[3]](#references)
```bash
$ python3 patology.py --dump -i BSM_BST150-4T_65374.pat
@@ -52,7 +52,7 @@ usr/lib/libsynocodesign.so: ELF 64-bit LSB shared object, ARM aarch64, …
## 4. Recover the hard-coded keys (`get_keys`)
-Inside `libsynocodesign.so` the function `get_keys(int keytype)` simply returns two 128-bit global variables for the requested archive family:
+Inside `libsynocodesign.so` the function `get_keys(int keytype)` simply returns two 128-bit global variables for the requested archive family:[[1]](#references)
```c
case 0: // PAT (system)
@@ -75,7 +75,7 @@ You only have to dump those two constants once for each DSM major version.
## 5. Header structure & signature verification
-`synoarchive_open()` → `support_format_synoarchive()` → `archive_read_support_format_synoarchive()` performs the following:
+`synoarchive_open()` → `support_format_synoarchive()` → `archive_read_support_format_synoarchive()` performs the following:[[1]](#references)
1. Read magic (3 bytes) `0xBFBAAD` **or** `0xADBEEF`.
2. Read little-endian 32-bit `header_len`.
@@ -110,7 +110,7 @@ crypto_kdf_derive_from_key(kdf_subkey, 32, subkey_id, ctx, master_key);
## 7. Synology’s custom **libarchive** backend
-Synology bundles a patched libarchive that registers a fake "tar" format whenever the magic is `0xADBEEF`:
+Synology bundles a patched libarchive that registers a fake "tar" format whenever the magic is `0xADBEEF`:[[1]](#references)
```c
register_format(
@@ -175,8 +175,8 @@ $ tar xf SynologyPhotos-rtd1619b-1.7.0-0794.tar
## References
-- [Extraction of Synology encrypted archives – Synacktiv (Pwn2Own IE 2024)](https://www.synacktiv.com/publications/extraction-des-archives-chiffrees-synology-pwn2own-irlande-2024.html)
-- [synodecrypt on GitHub](https://github.com/synacktiv/synodecrypt)
-- [patology on GitHub](https://github.com/sud0woodo/patology)
+- [1] [Extraction of Synology encrypted archives – Synacktiv (Pwn2Own IE 2024)](https://www.synacktiv.com/publications/extraction-des-archives-chiffrees-synology-pwn2own-irlande-2024.html)
+- [2] [synodecrypt on GitHub](https://github.com/synacktiv/synodecrypt)
+- [3] [patology on GitHub](https://github.com/sud0woodo/patology)
{{#include ../../banners/hacktricks-training.md}}
\ No newline at end of file
diff --git a/src/hardware-physical-access/physical-attacks.md b/src/hardware-physical-access/physical-attacks.md
index 198cf8805e0..93d739e42c2 100644
--- a/src/hardware-physical-access/physical-attacks.md
+++ b/src/hardware-physical-access/physical-attacks.md
@@ -28,7 +28,7 @@ RAM retains data briefly after power is cut, usually for **1 to 2 minutes**. Thi
## GPU Rowhammer Against Page Tables
-Modern GPU Rowhammer attacks become much more useful when they target **GPU virtual-memory metadata** instead of ordinary buffers. Recent work on **GDDR6 NVIDIA Ampere GPUs** shows that an attacker running unprivileged CUDA code can build GPU-specific hammering patterns, use **memory massaging** to place paging structures in vulnerable rows, and then flip bits in the **last-level page table** or an intermediate **page directory**. Once a single translation entry is corrupted, the attacker can bootstrap **arbitrary GPU memory read/write** and then pivot into host compromise.
+Modern GPU Rowhammer attacks become much more useful when they target **GPU virtual-memory metadata** instead of ordinary buffers. Recent work on **GDDR6 NVIDIA Ampere GPUs** shows that an attacker running unprivileged CUDA code can build GPU-specific hammering patterns, use **memory massaging** to place paging structures in vulnerable rows, and then flip bits in the **last-level page table** or an intermediate **page directory**. Once a single translation entry is corrupted, the attacker can bootstrap **arbitrary GPU memory read/write** and then pivot into host compromise.[[1]](#references)
### Exploitation Pattern
@@ -40,10 +40,10 @@ Modern GPU Rowhammer attacks become much more useful when they target **GPU virt
### Host Pivot and Mitigations
- With **IOMMU disabled**, forged system-aperture mappings can expose arbitrary **host physical memory** to the GPU, turning the GPU primitive into full host compromise.
-- **GDDRHammer** targets last-level page-table entries, while **GeForge** shows that corrupting a page-directory level can be easier because one bit flip can retarget a larger translation subtree. Do not treat only one paging layer as security-critical.
-- **IOMMU** still matters because it blocks the direct arbitrary-host-memory path used by GDDRHammer/GeForge, but it is **not a complete mitigation**. **GPUBreach** shows a second-stage pivot where the attacker corrupts GPU-writable, driver-owned CPU buffers and then triggers NVIDIA driver memory-safety bugs to obtain a kernel write primitive and a **root shell** even with IOMMU enabled.
-- **System-level ECC** is a practical hardening step on supported workstation/server GPUs. Consumer GPUs without ECC expose a weaker defense surface.
-- These attacks are not purely theoretical: **GeForge** reported **1,171** bit flips on an RTX 3060 and **202** on an RTX A6000, which was enough to build a working host-privilege-escalation chain.
+- **GDDRHammer** targets last-level page-table entries, while **GeForge** shows that corrupting a page-directory level can be easier because one bit flip can retarget a larger translation subtree. Do not treat only one paging layer as security-critical.[[2]](#references)[[3]](#references)
+- **IOMMU** still matters because it blocks the direct arbitrary-host-memory path used by GDDRHammer/GeForge, but it is **not a complete mitigation**. **GPUBreach** shows a second-stage pivot where the attacker corrupts GPU-writable, driver-owned CPU buffers and then triggers NVIDIA driver memory-safety bugs to obtain a kernel write primitive and a **root shell** even with IOMMU enabled.[[4]](#references)
+- **System-level ECC** is a practical hardening step on supported workstation/server GPUs. Consumer GPUs without ECC expose a weaker defense surface.[[5]](#references)
+- These attacks are not purely theoretical: **GeForge** reported **1,171** bit flips on an RTX 3060 and **202** on an RTX A6000, which was enough to build a working host-privilege-escalation chain.[[3]](#references)
---
@@ -81,7 +81,7 @@ Administrator privileges allow for the creation of copies of sensitive files, in
### Wi-Fi managed cable implants
-- ESP32-S3 based implants such as **Evil Crow Cable Wind** hide inside USB-A→USB-C or USB-C↔USB-C cables, enumerate purely as a USB keyboard, and expose their C2 stack over Wi-Fi. The operator only needs to power the cable from the victim host, create a hotspot named `Evil Crow Cable Wind` with password `123456789`, and browse to [http://cable-wind.local/](http://cable-wind.local/) (or its DHCP address) to reach the embedded HTTP interface.
+- ESP32-S3 based implants such as **Evil Crow Cable Wind** hide inside USB-A→USB-C or USB-C↔USB-C cables, enumerate purely as a USB keyboard, and expose their C2 stack over Wi-Fi. The operator only needs to power the cable from the victim host, create a hotspot named `Evil Crow Cable Wind` with password `123456789`, and browse to [http://cable-wind.local/](http://cable-wind.local/) (or its DHCP address) to reach the embedded HTTP interface.[[9]](#references)
- The browser UI provides tabs for *Payload Editor*, *Upload Payload*, *List Payloads*, *AutoExec*, *Remote Shell*, and *Config*. Stored payloads are tagged per OS, keyboard layouts are switched on the fly, and VID/PID strings can be altered to mimic known peripherals.
- Because the C2 lives inside the cable, a phone can stage payloads, trigger execution, and manage Wi-Fi credentials without touching the host OS—ideal for short dwell-time physical intrusions.
@@ -141,7 +141,7 @@ Many modern laptops and small-form-factor desktops include a **chassis-intrusion
### Real-World Example – Framework 13 Laptop
-The recovery shortcut for the Framework 13 (11th/12th/13th-gen) is:
+The recovery shortcut for the Framework 13 (11th/12th/13th-gen) is:[[6]](#references)[[7]](#references)
```text
Press intrusion switch → hold 2 s
@@ -172,7 +172,7 @@ After the tenth cycle the EC sets a flag that instructs the BIOS to wipe NVRAM a
### Sensor Characteristics
- Commodity “wave-to-exit” sensors pair a near-IR LED emitter with a TV-remote style receiver module that only reports logic high after it has seen multiple pulses (~4–10) of the correct carrier (≈30 kHz).
-- A plastic shroud blocks the emitter and receiver from looking directly at each other, so the controller assumes any validated carrier came from a nearby reflection and drives a relay that opens the door strike.
+- A plastic shroud blocks the emitter and receiver from looking directly at each other, so the controller assumes any validated carrier came from a nearby reflection and drives a relay that opens the door strike.[[8]](#references)
- Once the controller believes a target is present it often changes the outbound modulation envelope, but the receiver keeps accepting any burst that matches the filtered carrier.
### Attack Workflow
@@ -194,14 +194,14 @@ After the tenth cycle the EC sets a flag that instructs the BIOS to wipe NVRAM a
## References
-- [Bruce Schneier - Rowhammer Attack Against NVIDIA Chips](https://www.schneier.com/blog/archives/2026/05/rowhammer-attack-against-nvidia-chips.html)
-- [GDDRHammer: Greatly Disturbing DRAM Rows — Cross-Component Rowhammer Attacks from Modern GPUs](https://gddr.fail/files/gddrhammer.pdf)
-- [GeForge: Hammering GDDR Memory to Forge GPU Page Tables for Fun and Profit](https://stefan1wan.github.io/files/GeForge.pdf)
-- [GPUBreach: Privilege Escalation Attacks on GPUs using Rowhammer](https://gururaj-s.github.io/assets/pdf/SP26_GPUBreach.pdf)
-- [NVIDIA - Security Notice: Rowhammer - July 2025](https://nvidia.custhelp.com/app/answers/detail/a_id/5671/~/security-notice%3A-rowhammer---july-2025)
-- [Pentest Partners – “Framework 13. Press here to pwn”](https://www.pentestpartners.com/security-blog/framework-13-press-here-to-pwn/)
-- [FrameWiki – Mainboard Reset Guide](https://framewiki.net/guides/mainboard-reset)
-- [SensePost – “Noooooooo Touch! – Bypassing IR No-Touch Exit Sensors with a Covert IR Torch”](https://sensepost.com/blog/2025/noooooooooo-touch/)
-- [Mobile-Hacker – “Plug, Play, Pwn: Hacking with Evil Crow Cable Wind”](https://www.mobile-hacker.com/2025/12/01/plug-play-pwn-hacking-with-evil-crow-cable-wind/)
+- [1] [Bruce Schneier - Rowhammer Attack Against NVIDIA Chips](https://www.schneier.com/blog/archives/2026/05/rowhammer-attack-against-nvidia-chips.html)
+- [2] [GDDRHammer: Greatly Disturbing DRAM Rows — Cross-Component Rowhammer Attacks from Modern GPUs](https://gddr.fail/files/gddrhammer.pdf)
+- [3] [GeForge: Hammering GDDR Memory to Forge GPU Page Tables for Fun and Profit](https://stefan1wan.github.io/files/GeForge.pdf)
+- [4] [GPUBreach: Privilege Escalation Attacks on GPUs using Rowhammer](https://gururaj-s.github.io/assets/pdf/SP26_GPUBreach.pdf)
+- [5] [NVIDIA - Security Notice: Rowhammer - July 2025](https://nvidia.custhelp.com/app/answers/detail/a_id/5671/~/security-notice%3A-rowhammer---july-2025)
+- [6] [Pentest Partners – “Framework 13. Press here to pwn”](https://www.pentestpartners.com/security-blog/framework-13-press-here-to-pwn/)
+- [7] [FrameWiki – Mainboard Reset Guide](https://framewiki.net/guides/mainboard-reset)
+- [8] [SensePost – “Noooooooo Touch! – Bypassing IR No-Touch Exit Sensors with a Covert IR Torch”](https://sensepost.com/blog/2025/noooooooooo-touch/)
+- [9] [Mobile-Hacker – “Plug, Play, Pwn: Hacking with Evil Crow Cable Wind”](https://www.mobile-hacker.com/2025/12/01/plug-play-pwn-hacking-with-evil-crow-cable-wind/)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/iframe-traps.md b/src/pentesting-web/iframe-traps.md
index b7a1f01be3f..ccbe971027a 100644
--- a/src/pentesting-web/iframe-traps.md
+++ b/src/pentesting-web/iframe-traps.md
@@ -4,7 +4,7 @@
## Basic Information
-This technique abuses **same-origin XSS** to keep code execution alive while the victim keeps browsing the application. The classic write-ups were published by TrustedSec [here](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) and [here](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).
+This technique abuses **same-origin XSS** to keep code execution alive while the victim keeps browsing the application. The classic write-ups were published by TrustedSec [here](https://trustedsec.com/blog/persisting-xss-with-iframe-traps) and [here](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams).[[3]](#references)[[4]](#references)
The idea is to land the victim on a page vulnerable to XSS and then **trap the rest of their navigation inside a full-page iframe**. If the victim keeps clicking links, submitting forms, and moving through the application **inside the frame**, the original attacker-controlled page stays alive in the top window and can keep collecting data.
@@ -82,14 +82,14 @@ if (window.top === window.self) {
## Overlay & skimmer usage
-- Compromised checkout pages can **hide a legitimate hosted payment iframe and overlay it with a pixel-perfect fake collector** that forwards or replays data while the real payment flow still succeeds.
+- Compromised checkout pages can **hide a legitimate hosted payment iframe and overlay it with a pixel-perfect fake collector** that forwards or replays data while the real payment flow still succeeds.[[2]](#references)
- A more aggressive variant is to **rewrite the URL of the hosted-field iframe itself** so the browser loads an attacker-controlled frame that proxies the PSP flow and skims PAN/CVV inside the iframe context.
- Trapping users in the top frame is also useful for collecting **autofill/password-manager** data before they notice the real browser URL never changed.
## Recent chaining ideas
- **POST-only reflected XSS** can be upgraded into a usable trap by landing the victim on the poisoned response with CSRF or an auto-submitting form, and then immediately switching into iframe-trap mode so the payload survives after the first POST response.
-- **`credentialless` iframe chains** can turn some self-XSS/login-CSRF scenarios into practical account-takeover paths without destroying the victim's live session. The full details are better covered in [Iframes in XSS, CSP and SOP](xss-cross-site-scripting/iframes-in-xss-and-csp.md).
+- **`credentialless` iframe chains** can turn some self-XSS/login-CSRF scenarios into practical account-takeover paths without destroying the victim's live session. The full details are better covered in [Iframes in XSS, CSP and SOP](xss-cross-site-scripting/iframes-in-xss-and-csp.md).[[1]](#references)
## Quick OPSEC tips
@@ -109,6 +109,8 @@ xss-cross-site-scripting/iframes-in-xss-and-csp.md
## References
-- [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/)
-- [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/)
+- [1] [Make Self-XSS Great Again](https://blog.slonser.info/posts/make-self-xss-great-again/)
+- [2] [New Stealth Magecart Attack Bypasses Payment Services Using Iframes](https://www.humansecurity.com/learn/blog/new-stealth-magecart-attack-bypasses-payment-services-using-iframes/)
+- [3] [Persisting XSS with IFrame Traps](https://trustedsec.com/blog/persisting-xss-with-iframe-traps)
+- [4] [JS-Tap: Weaponizing JavaScript for Red Teams](https://trustedsec.com/blog/js-tap-weaponizing-javascript-for-red-teams)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/oauth-to-account-takeover.md b/src/pentesting-web/oauth-to-account-takeover.md
index 134f7d3b707..ffed6c5c74a 100644
--- a/src/pentesting-web/oauth-to-account-takeover.md
+++ b/src/pentesting-web/oauth-to-account-takeover.md
@@ -62,7 +62,7 @@ Host: socialmedia.com
### Open redirect_uri
-Per [RFC 6749 §3.1.2](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2), the authorization server must redirect the browser only to **pre-registered, exact redirect URIs**. Any weakness here lets an attacker send a victim through a malicious authorization URL so that the IdP delivers the victim’s `code` (and `state`) straight to an attacker endpoint, who can then redeem it and harvest tokens.
+Per [RFC 6749 §3.1.2](https://www.rfc-editor.org/rfc/rfc6749#section-3.1.2), the authorization server must redirect the browser only to **pre-registered, exact redirect URIs**. Any weakness here lets an attacker send a victim through a malicious authorization URL so that the IdP delivers the victim’s `code` (and `state`) straight to an attacker endpoint, who can then redeem it and harvest tokens.[[4]](#references)[[5]](#references)
Typical attack workflow:
@@ -84,7 +84,7 @@ Also review auxiliary redirect-style parameters (`client_uri`, `policy_uri`, `to
### Redirect token leakage on allowlisted domains with attacker-controlled subpaths
-Locking `redirect_uri` to “owned/first-party domains” doesn’t help if any allowlisted domain exposes **attacker-controlled paths or execution contexts** (legacy app platforms, user namespaces, CMS uploads, etc.). If the OAuth/federated login flow **returns tokens in the URL** (query or hash), an attacker can:
+Locking `redirect_uri` to “owned/first-party domains” doesn’t help if any allowlisted domain exposes **attacker-controlled paths or execution contexts** (legacy app platforms, user namespaces, CMS uploads, etc.).[[1]](#references) If the OAuth/federated login flow **returns tokens in the URL** (query or hash), an attacker can:
1. Start a legitimate flow to mint a pre-token (e.g., an `etoken` in a multi-step Accounts Center/FXAuth flow).
2. Send the victim an authorization URL that sets the allowlisted domain as `redirect_uri`/`base_uri` but points `next`/path into an attacker-controlled namespace (e.g., `https://apps.facebook.com/`).
@@ -102,7 +102,7 @@ https://accountscenter.facebook.com/profiles//name/?auth_flow=reauth&
### XSS in redirect implementation
-As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**. Possible payload to test:
+As mentioned in this bug bounty report [https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html](https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html) it might be possible that the redirect **URL is being reflected in the response** of the server after the user authenticates, being **vulnerable to XSS**.[[16]](#references) Possible payload to test:
```
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard
test
@@ -110,7 +110,7 @@ https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard[[8]](#references)[[9]](#references)
- **Reflecting `error_description` into HTML** without strict output encoding turns the callback into a **trusted-origin phishing page**. Even when `
```
-Impact: real-time exfiltration of streamed data (e.g., captured emails/notifications) without user credentials when any `Origin` is accepted and the endpoint skips authentication.
+Impact: real-time exfiltration of streamed data (e.g., captured emails/notifications) without user credentials when any `Origin` is accepted and the endpoint skips authentication.[[12]](#references)
### Simple Attack
Note that when **establishing** a **websocket** connection the **cookie** is **sent** to the server. The **server** might be using it to **relate** each **specific** **user** with his **websocket** **session based on the sent cookie**.
-Then, if for **example** the **websocket** **server** **sends back the history of the conversation** of a user if a msg with "**READY"** is sent, then a **simple XSS** establishing the connection (the **cookie** will be **sent** **automatically** to authorise the victim user) **sending** "**READY**" will be able to **retrieve** the history of the **conversation**.:
+Then, if for **example** the **websocket** **server** **sends back the history of the conversation** of a user if a msg with "**READY"** is sent, then a **simple XSS** establishing the connection (the **cookie** will be **sent** **automatically** to authorise the victim user) **sending** "**READY**" will be able to **retrieve** the history of the **conversation**.:[[1]](#references)
```html
```
-The request itself also becomes a login-state oracle if the script only loads for authenticated users.
+The request itself also becomes a login-state oracle if the script only loads for authenticated users.[[6]](#references)
### Service Workers
@@ -904,7 +904,7 @@ Upon arrival of the request initiated in the preceding step, the **service worke
- **Inclusion Methods**: HTML Elements (script), Frames
- **Detectable Difference**: DNS/HTTP load success, CORB/header changes
- **Summary:** If identifiers live in subdomain labels (e.g., `www..sb.facebook.com`), request resources on candidate hosts and treat `onload` vs `onerror`/timeouts as a Boolean. Combine with login-only scripts (e.g., `/signals/iwl.js`) to brute-force usernames and verify auth to related properties.
-- **Note:** Signals can be amplified with different inclusion types (`script`, `iframe`, `object`) to detect `X-Frame-Options`, `CORB`, or redirect differences per candidate.
+- **Note:** Signals can be amplified with different inclusion types (`script`, `iframe`, `object`) to detect `X-Frame-Options`, `CORB`, or redirect differences per candidate.[[6]](#references)
## With HTML or Re Injection
@@ -988,12 +988,12 @@ There are mitigations recommended in [https://xsinator.com/paper.pdf](https://xs
## References
-- [https://xsinator.com/paper.pdf](https://xsinator.com/paper.pdf)
-- [https://xsleaks.dev/](https://xsleaks.dev)
-- [https://github.com/xsleaks/xsleaks](https://github.com/xsleaks/xsleaks)
-- [https://xsinator.com/](https://xsinator.com/)
-- [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
-- [Cross-Site Leaks (XS-Leaks) across Meta platforms](https://ysamm.com/uncategorized/2026/01/16/cross-site-leaks.html)
+- [1] [XSinator.com: From a Formal Model to the Automatic Evaluation of Cross-Site Leaks in Web Browsers (paper)](https://xsinator.com/paper.pdf)
+- [2] [XS-Leaks Wiki](https://xsleaks.dev)
+- [3] [xsleaks/xsleaks - GitHub](https://github.com/xsleaks/xsleaks)
+- [4] [XSinator - XS-Leaks Browser Test Suite](https://xsinator.com/)
+- [5] [ka0labs CTF writeups - nn9ed x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
+- [6] [Cross-Site Leaks (XS-Leaks) across Meta platforms](https://ysamm.com/uncategorized/2026/01/16/cross-site-leaks.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/xs-search/connection-pool-example.md b/src/pentesting-web/xs-search/connection-pool-example.md
index a86b8087206..1e9dcfef8a7 100644
--- a/src/pentesting-web/xs-search/connection-pool-example.md
+++ b/src/pentesting-web/xs-search/connection-pool-example.md
@@ -4,7 +4,7 @@
## Sekaictf2022 - safelist
-In the [**Sekaictf2022 - safelist**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/safelist/solution) challenge, [**@Strellic\_**](https://twitter.com/Strellic_) gives an example of how to use a **variation** of the **Connection Pool** technique to perform a **XS-Leak**.
+In the [**Sekaictf2022 - safelist**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/safelist/solution) challenge, [**@Strellic\_**](https://twitter.com/Strellic_) gives an example of how to use a **variation** of the **Connection Pool** technique to perform a **XS-Leak**.[[3]](#references)
In this challenge, the goal is to exfiltrate a flag that will appear in the bots web session inside a post. These are the assets the attacker has:
@@ -175,7 +175,7 @@ This is the exploit code, taken from [https://github.com/project-sekai-ctf/sekai
### Exploit 2
-Same tactic but different code from [https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/](https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/)
+Same tactic but different code from [https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/](https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/)[[4]](#references)
```html
@@ -313,7 +313,7 @@ Same tactic but different code from [https://blog.huli.tw/2022/10/05/en/sekaictf
These examples are still useful, but some assumptions from 2022 are **less portable** in modern browsers:
-- **Do not assume a globally shared socket pool anymore.** Firefox's **State Partitioning / Network Partitioning** also covers **connection pooling**, and Brave shipped **pool-party** mitigations after showing that many browser resource pools could be turned into side channels.
+- **Do not assume a globally shared socket pool anymore.** Firefox's **State Partitioning / Network Partitioning** also covers **connection pooling**, and Brave shipped **pool-party** mitigations after showing that many browser resource pools could be turned into side channels.[[1]](#references)[[2]](#references)
- When the **global** connection-pool oracle is noisy or simply dead, prefer scenarios where the attacker and victim requests still live in the **same partition** (for example attacker-controlled content rendered by the target site), or switch to the [Connection Pool by Destination Example](connection-pool-by-destination-example.md) where the primitive is the **per-destination queue** instead of the global pool.
- **Calibrate every browser/profile/run.** The effective limits can change between **headless/headful** runs, and **HTTP/1.1, HTTP/2 and HTTP/3** may **reuse** existing connections. Moreover, **HTTP/2 connection coalescing** means that **different hostnames are not always different sockets** if they end up on the same backend/certificate.
- In practice, make your probes more stable by using **`cache: "no-store"`**, random query strings, a short **warm-up round**, and keeping the **same `credentials` mode** across all measurements. If your socket blockers stop blocking, suspect **connection reuse/coalescing** before assuming the leak is gone.
@@ -542,6 +542,8 @@ In the exploit you can see:
## References
-- [MDN - State Partitioning](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/State_Partitioning)
-- [Brave - Preventing pool-party attacks](https://brave.com/privacy-updates/13-pool-party-side-channels/)
+- [1] [MDN - State Partitioning](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/State_Partitioning)
+- [2] [Brave - Preventing pool-party attacks](https://brave.com/privacy-updates/13-pool-party-side-channels/)
+- [3] [Project SEKAI CTF 2022 - safelist challenge solution](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/safelist/solution)
+- [4] [SekaiCTF 2022 - safelist XS-Leak writeup (huli.tw)](https://blog.huli.tw/2022/10/05/en/sekaictf2022-safelist-xsleak/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md b/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md
index 59aee74d87d..79700ed3ff7 100644
--- a/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md
+++ b/src/pentesting-web/xs-search/event-loop-blocking-+-lazy-images.md
@@ -2,7 +2,7 @@
{{#include ../../banners/hacktricks-training.md}}
-In [**this exploit**](https://gist.github.com/aszx87410/155f8110e667bae3d10a36862870ba45), [**@aszx87410**](https://twitter.com/aszx87410) mixes the **lazy image side channel** technique through a HTML injection with kind of **event loop blocking technique** to leak chars.
+In [**this exploit**](https://gist.github.com/aszx87410/155f8110e667bae3d10a36862870ba45), [**@aszx87410**](https://twitter.com/aszx87410) mixes the **lazy image side channel** technique through a HTML injection with kind of **event loop blocking technique** to leak chars.[[1]](#references)
This is a **different exploit for the CTF chall** that was already commented in the following page. take a look for more info about the challenge:
@@ -11,7 +11,7 @@ This is a **different exploit for the CTF chall** that was already commented in
connection-pool-example.md
{{#endref}}
-This technique is useful when the attacker can create a **Boolean oracle** based on whether a **lazy-loaded image** is fetched or not, but **cannot** directly observe that request because of CSP, `img-src` restrictions, or `Cache-Control: no-store`. Instead of waiting for an external callback, the exploit converts image loading into a **timing side channel** by making those image requests compete with other requests.
+This technique is useful when the attacker can create a **Boolean oracle** based on whether a **lazy-loaded image** is fetched or not, but **cannot** directly observe that request because of CSP, `img-src` restrictions, or `Cache-Control: no-store`. Instead of waiting for an external callback, the exploit converts image loading into a **timing side channel** by making those image requests compete with other requests.[[1]](#references)
The idea behind this exploit is:
@@ -166,10 +166,10 @@ Let's check the code:
This trick is **fragile** and needs to be **calibrated per environment**:
-- The **lazy-loading distance threshold** is browser-dependent and can change with browser version, connection type, and headless/headful mode. Chromium loads off-screen images **before** they are visible, so the right `