You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-[Keras Model Deserialization Rce And Gadget Hunting](generic-methodologies-and-resources/python/keras-model-deserialization-rce-and-gadget-hunting.md)
Copy file name to clipboardExpand all lines: src/binary-exploitation/format-strings/README.md
+45-2Lines changed: 45 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -153,7 +153,7 @@ Arbitrary reads can be useful to:
153
153
154
154
## **Arbitrary Write**
155
155
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.
157
157
158
158
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**.
159
159
@@ -227,6 +227,46 @@ p.interactive()
227
227
228
228
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.
229
229
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:
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"
# ... 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.
@@ -240,6 +280,9 @@ It's possible to abuse the write actions of a format string vulnerability to **w
240
280
- 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.
Copy file name to clipboardExpand all lines: src/binary-exploitation/libc-heap/unsorted-bin-attack.md
+64-2Lines changed: 64 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,9 @@ bins-and-memory-allocations.md
13
13
14
14
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.
15
15
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.
17
19
18
20
> [!TIP]
19
21
> 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*
27
29
28
30
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`**
29
31
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.
- 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.
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
+
30
88
## Unsorted Bin Infoleak Attack
31
89
32
90
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
71
129
- 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).
72
130
- 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`.
Copy file name to clipboardExpand all lines: src/binary-exploitation/stack-overflow/README.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,15 @@ In this scenario the attacker could place a shellcode in the stack and abuse the
79
79
stack-shellcode/
80
80
{{#endref}}
81
81
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
+
82
91
### ROP & Ret2... techniques
83
92
84
93
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:
0 commit comments