Skip to content

Commit d2d11f9

Browse files
authored
Merge branch 'master' into update_HTB__TheFrizz_20250827_141120
2 parents 9754d1c + 40ff109 commit d2d11f9

36 files changed

Lines changed: 1730 additions & 49 deletions

File tree

.github/workflows/build_master.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ jobs:
4949
git config pull.rebase false
5050
5151
# Ensure we're on the target branch and up to date
52-
git pull --ff-only
52+
git fetch origin
53+
git reset --hard origin/master
5354
5455
# Choose the file to keep at HEAD:
5556
# 1) Prefer freshly built version from book/

searchindex.js

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

src/SUMMARY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
- [Python Sandbox Escape & Pyscript](generic-methodologies-and-resources/python/README.md)
7171
- [Bypass Python sandboxes](generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
7272
- [LOAD_NAME / LOAD_CONST opcode OOB Read](generic-methodologies-and-resources/python/bypass-python-sandboxes/load_name-load_const-opcode-oob-read.md)
73+
- [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)
7374
- [Class Pollution (Python's Prototype Pollution)](generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
7475
- [Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
7576
- [Python Internal Read Gadgets](generic-methodologies-and-resources/python/python-internal-read-gadgets.md)
@@ -233,6 +234,7 @@
233234
- [Authentication Credentials Uac And Efs](windows-hardening/authentication-credentials-uac-and-efs.md)
234235
- [Checklist - Local Windows Privilege Escalation](windows-hardening/checklist-windows-privilege-escalation.md)
235236
- [Windows Local Privilege Escalation](windows-hardening/windows-local-privilege-escalation/README.md)
237+
- [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md)
236238
- [Dll Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking.md)
237239
- [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md)
238240
- [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md)
@@ -283,6 +285,7 @@
283285
- [Kerberoast](windows-hardening/active-directory-methodology/kerberoast.md)
284286
- [Kerberos Authentication](windows-hardening/active-directory-methodology/kerberos-authentication.md)
285287
- [Kerberos Double Hop Problem](windows-hardening/active-directory-methodology/kerberos-double-hop-problem.md)
288+
- [Lansweeper Security](windows-hardening/active-directory-methodology/lansweeper-security.md)
286289
- [LAPS](windows-hardening/active-directory-methodology/laps.md)
287290
- [MSSQL AD Abuse](windows-hardening/active-directory-methodology/abusing-ad-mssql.md)
288291
- [Over Pass the Hash/Pass the Key](windows-hardening/active-directory-methodology/over-pass-the-hash-pass-the-key.md)
@@ -430,6 +433,7 @@
430433
- [H2 - Java SQL database](network-services-pentesting/pentesting-web/h2-java-sql-database.md)
431434
- [IIS - Internet Information Services](network-services-pentesting/pentesting-web/iis-internet-information-services.md)
432435
- [ImageMagick Security](network-services-pentesting/pentesting-web/imagemagick-security.md)
436+
- [Ispconfig](network-services-pentesting/pentesting-web/ispconfig.md)
433437
- [JBOSS](network-services-pentesting/pentesting-web/jboss.md)
434438
- [Jira & Confluence](network-services-pentesting/pentesting-web/jira.md)
435439
- [Joomla](network-services-pentesting/pentesting-web/joomla.md)
@@ -775,6 +779,7 @@
775779
- [SROP - Sigreturn-Oriented Programming](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md)
776780
- [SROP - ARM64](binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md)
777781
- [Synology Encrypted Archive Decryption](hardware-physical-access/firmware-analysis/synology-encrypted-archive-decryption.md)
782+
- [Windows Seh Overflow](binary-exploitation/stack-overflow/windows-seh-overflow.md)
778783
- [Array Indexing](binary-exploitation/array-indexing.md)
779784
- [Chrome Exploiting](binary-exploitation/chrome-exploiting.md)
780785
- [Integer Overflow](binary-exploitation/integer-overflow.md)

src/binary-exploitation/format-strings/README.md

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ Arbitrary reads can be useful to:
153153

154154
## **Arbitrary Write**
155155

156-
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> 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 **`%<num>$n`** write an arbitrary number in an arbitrary address.
156+
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the <num> 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 **`%<num>$n`** write an arbitrary number in an arbitrary address.
157157

158158
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 **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
159159

@@ -227,6 +227,46 @@ p.interactive()
227227

228228
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.
229229

230+
231+
## Windows x64: Format-string leak to bypass ASLR (no varargs)
232+
233+
On Windows x64 the first four integer/pointer parameters are passed in registers: RCX, RDX, R8, R9. In many buggy call-sites the attacker-controlled string is used as the format argument but no variadic arguments are provided, for example:
234+
235+
```c
236+
// keyData is fully controlled by the client
237+
// _snprintf(dst, len, fmt, ...)
238+
_snprintf(keyStringBuffer, 0xff2, (char*)keyData);
239+
```
240+
241+
Because no varargs are passed, any conversion like "%p", "%x", "%s" will cause the CRT to read the next variadic argument from the appropriate register. With the Microsoft x64 calling convention the first such read for "%p" comes from R9. Whatever transient value is in R9 at the call-site will be printed. In practice this often leaks a stable in-module pointer (e.g., a pointer to a local/global object previously placed in R9 by surrounding code or a callee-saved value), which can be used to recover the module base and defeat ASLR.
242+
243+
Practical workflow:
244+
245+
- Inject a harmless format such as "%p " at the very start of the attacker-controlled string so the first conversion executes before any filtering.
246+
- Capture the leaked pointer, identify the static offset of that object inside the module (by reversing once with symbols or a local copy), and recover the image base as `leak - known_offset`.
247+
- Reuse that base to compute absolute addresses for ROP gadgets and IAT entries remotely.
248+
249+
Example (abbreviated python):
250+
251+
```python
252+
from pwn import remote
253+
254+
# Send an input that the vulnerable code will pass as the "format"
255+
fmt = b"%p " + b"-AAAAA-BBB-CCCC-0252-" # leading %p leaks R9
256+
io = remote(HOST, 4141)
257+
# ... drive protocol to reach the vulnerable snprintf ...
258+
leaked = int(io.recvline().split()[2], 16) # e.g. 0x7ff6693d0660
259+
base = leaked - 0x20660 # module base = leak - offset
260+
print(hex(leaked), hex(base))
261+
```
262+
263+
Notes:
264+
- The exact offset to subtract is found once during local reversing and then reused (same binary/version).
265+
- If "%p" doesn’t print a valid pointer on the first try, try other specifiers ("%llx", "%s") or multiple conversions ("%p %p %p") to sample other argument registers/stack.
266+
- This pattern is specific to the Windows x64 calling convention and printf-family implementations that fetch nonexistent varargs from registers when the format string requests them.
267+
268+
This technique is extremely useful to bootstrap ROP on Windows services compiled with ASLR and no obvious memory disclosure primitives.
269+
230270
## Other Examples & References
231271

232272
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
@@ -240,6 +280,9 @@ It's possible to abuse the write actions of a format string vulnerability to **w
240280
- 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.
241281

242282

243-
{{#include ../../banners/hacktricks-training.md}}
283+
## References
244284

285+
- [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
286+
- [x64 calling convention (MSVC)](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention)
245287

288+
{{#include ../../banners/hacktricks-training.md}}

src/binary-exploitation/libc-heap/unsorted-bin-attack.md

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ bins-and-memory-allocations.md
1313

1414
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.
1515

16-
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).
16+
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 traditional target was **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin attack to a fast bin attack).
17+
18+
- Modern note (glibc ≥ 2.39): `global_max_fast` became an 8‑bit global. Blindly writing a pointer there via an unsorted-bin write will clobber adjacent libc data and will not reliably raise the fastbin limit anymore. Prefer other targets or other primitives when running against glibc 2.39+. See "Modern constraints" below and consider combining with other techniques like a [large bin attack](large-bin-attack.md) or a [fast bin attack](fast-bin-attack.md) once you have a stable primitive.
1719

1820
> [!TIP]
1921
> 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.
@@ -27,6 +29,62 @@ So, basically, this attack allows to **set a big number at an arbitrary address*
2729
2830
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`**
2931

32+
### How the write actually happens
33+
34+
- The unsorted-bin write is triggered on `free` when the freed chunk is inserted at the head of the unsorted list.
35+
- During insertion, the allocator performs `bck = unsorted_chunks(av); fwd = bck->fd; victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;`
36+
- If you can set `victim->bk` to `(mchunkptr)(TARGET - 0x10)` before calling `free(victim)`, the final statement will perform the write: `*(TARGET) = victim`.
37+
- Later, when the allocator processes the unsorted bin, integrity checks will verify (among other things) that `bck->fd == victim` and `victim->fd == unsorted_chunks(av)` before unlinking. Because the insertion already wrote `victim` into `bck->fd` (our `TARGET`), these checks can be satisfied if the write succeeded.
38+
39+
## Modern constraints (glibc ≥ 2.33)
40+
41+
To use unsorted‑bin writes reliably on current glibc:
42+
43+
- Tcache interference: for sizes that fall into tcache, frees are diverted there and won’t touch the unsorted bin. Either
44+
- make requests with sizes > MAX_TCACHE_SIZE (≥ 0x410 on 64‑bit by default), or
45+
- fill the corresponding tcache bin (7 entries) so that additional frees reach the global bins, or
46+
- if the environment is controllable, disable tcache (e.g., GLIBC_TUNABLES glibc.malloc.tcache_count=0).
47+
- Integrity checks on the unsorted list: on the next allocation path that examines the unsorted bin, glibc checks (simplified):
48+
- `bck->fd == victim` and `victim->fd == unsorted_chunks(av)`; otherwise it aborts with `malloc(): unsorted double linked list corrupted`.
49+
- This means the address you target must tolerate two writes: first `*(TARGET) = victim` at free‑time; later, as the chunk is removed, `*(TARGET) = unsorted_chunks(av)` (the allocator rewrites `bck->fd` back to the bin head). Choose targets where simply forcing a large non‑zero value is useful.
50+
- Typical stable targets in modern exploits
51+
- Application or global state that treats "large" values as flags/limits.
52+
- Indirect primitives (e.g., set up for a subsequent [fast bin attack]({{#ref}}fast-bin-attack.md{{#endref}}) or to pivot a later write‐what‐where).
53+
- Avoid `__malloc_hook`/`__free_hook` on new glibc: they were removed in 2.34. Avoid `global_max_fast` on ≥ 2.39 (see next note).
54+
- About `global_max_fast` on recent glibc
55+
- On glibc 2.39+, `global_max_fast` is an 8‑bit global. The classic trick of writing a heap pointer into it (to enlarge fastbins) no longer works cleanly and is likely to corrupt adjacent allocator state. Prefer other strategies.
56+
57+
## Minimal exploitation recipe (modern glibc)
58+
59+
Goal: achieve a single arbitrary write of a heap pointer to an arbitrary address using the unsorted‑bin insertion primitive, without crashing.
60+
61+
- Layout/grooming
62+
- Allocate A, B, C with sizes large enough to bypass tcache (e.g., 0x5000). C prevents consolidation with the top chunk.
63+
- Corruption
64+
- Overflow from A into B’s chunk header to set `B->bk = (mchunkptr)(TARGET - 0x10)`.
65+
- Trigger
66+
- `free(B)`. At insertion time the allocator executes `bck->fd = B`, therefore `*(TARGET) = B`.
67+
- Continuation
68+
- If you plan to continue allocating and the program uses the unsorted bin, expect the allocator to later set `*(TARGET) = unsorted_chunks(av)`. Both values are typically large and may be enough to change size/limit semantics in targets that only check for "big".
69+
70+
Pseudocode skeleton:
71+
72+
```c
73+
// 64-bit glibc 2.35–2.38 style layout (tcache bypass via large sizes)
74+
void *A = malloc(0x5000);
75+
void *B = malloc(0x5000);
76+
void *C = malloc(0x5000); // guard
77+
78+
// overflow from A into B’s metadata (prev_size/size/.../bk). You must control B->bk.
79+
*(size_t *)((char*)B - 0x8) = (size_t)(TARGET - 0x10); // write fake bk
80+
81+
free(B); // triggers *(TARGET) = B (unsorted-bin insertion write)
82+
```
83+
84+
> [!NOTE]
85+
> • If you cannot bypass tcache with size, fill the tcache bin for the chosen size (7 frees) before freeing the corrupted chunk so the free goes to unsorted.
86+
> • If the program immediately aborts on the next allocation due to unsorted-bin checks, re‑examine that `victim->fd` still equals the bin head and that your `TARGET` holds the exact `victim` pointer after the first write.
87+
3088
## Unsorted Bin Infoleak Attack
3189
3290
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)**.\
@@ -71,6 +129,10 @@ Then C was deallocated, and consolidated with A+B (but B was still in used). A n
71129
- 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).
72130
- 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`.
73131
74-
{{#include ../../banners/hacktricks-training.md}}
75132
76133
134+
## References
135+
136+
- Glibc malloc unsorted-bin integrity checks (example in 2.33 source): https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c
137+
- `global_max_fast` and related definitions in modern glibc (2.39): https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c
138+
{{#include ../../banners/hacktricks-training.md}}

src/binary-exploitation/stack-overflow/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ In this scenario the attacker could place a shellcode in the stack and abuse the
7979
stack-shellcode/
8080
{{#endref}}
8181

82+
### Windows SEH-based exploitation (nSEH/SEH)
83+
84+
On 32-bit Windows, an overflow may overwrite the Structured Exception Handler (SEH) chain instead of the saved return address. Exploitation typically replaces the SEH pointer with a POP POP RET gadget and uses the 4-byte nSEH field for a short jump to pivot back into the large buffer where shellcode lives. A common pattern is a short jmp in nSEH that lands on a 5-byte near jmp placed just before nSEH to jump hundreds of bytes back to the payload start.
85+
86+
87+
{{#ref}}
88+
windows-seh-overflow.md
89+
{{#endref}}
90+
8291
### ROP & Ret2... techniques
8392

8493
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:
@@ -202,6 +211,7 @@ Lessons learned:
202211
## References
203212
* [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/)
204213
* [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/)
214+
* [HTB: Rainbow – SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
205215
206216
{{#include ../../banners/hacktricks-training.md}}
207217

0 commit comments

Comments
 (0)