Skip to content

Commit 3790263

Browse files
authored
zero to hero corrections
1 parent 3f97cf2 commit 3790263

File tree

1 file changed

+40
-31
lines changed

1 file changed

+40
-31
lines changed

pwn/zero_to_hero/README.md

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,53 @@
1-
# zero to hero - 500
1+
# zero to hero
2+
**Category:** Binary Exploitation
23

3-
## Description
4+
**Points:** 500
5+
6+
**Description:**
47
Now you're really cooking. Can you pwn [this]() service?. Connect with `nc 2019shell1.picoctf.com 49928`. [libc.so.6]() [ld-2.29.so]()
58

6-
## Analysis
7-
The binary uses glibc version 2.29, which patches the double free vulnerability.
9+
----------
810

9-
## Solution
1011
We are given the libc base address, so no leaks are needed. All we have to do is get a write.
1112

12-
### House of Poortho
13+
The issue is that the binary uses libc 2.29, which patches the double free vulnerability (or does it? :o).
1314

14-
The vulnerability is that read() overwrites the first byte of the next chunk header with a null byte. If the next chunk has a size header with least significant byte not equal to 0x00, the size of the next chunk changes.
15+
Googling common exploits in libc 2.29 didn't help because they involved the use of unsorted bin and/or fastbin, and the checks on chunk size and slot count restricted allocations to tcache.
1516

16-
```
17-
+-------------------+------------------+
18-
current | ... | 0x51 |
19-
+--------------------------------------+
20-
| ... |
21-
+-------------------+------------------+
22-
next | ... | 0x171 |
23-
+--------------------------------------+
24-
| ... |
25-
+--------------------------------------+
26-
```
27-
*Before null byte overflow*
17+
The vulnerability is that read() overwrites the first byte of the next chunk header with a null byte. By asking for a chunk divisible by 0x8 but not 0x10 and triggering the vuln, the size of the next chunk changes. When the next chunk is freed again, it will be placed into a separate tcache bin, and the double free patch only checks for chunks within the same list.
18+
19+
Everything is self-explanatory from here. Once we get double free, we overwrite `__free_hook` with the win function.
20+
21+
------------
22+
23+
I was under the assumption that chunk headers were 16 bytes long, and chunk size was at offset 8, so the null byte overrun wouldn't do anything. It turns out that this was false. When the previous chunk is in use, the chunk header is actually 8 bytes.
2824

2925
```
30-
+-------------------+------------------+
31-
current | ... | 0x51 |
32-
+--------------------------------------+
33-
| AAAAAAAA |
34-
+-------------------+------------------+
35-
next | AAAAAAAA | 0x100 |
36-
+--------------------------------------+
37-
| ... |
38-
+--------------------------------------+
26+
+-------------------+------------------+
27+
-0x010 | data in previous chunk |
28+
+-------------------+------------------+
29+
0x000 | prev data/padding | 0x171 |
30+
+--------------------------------------+
31+
| ... |
32+
+--------------------------------------+
33+
+0x170 | next chunk |
34+
+--------------------------------------+
3935
```
40-
*After null byte overflow*
4136

42-
Assuming that we have freed the next chunk already, when it is freed again, it will be placed into a separate tcache bin, bypassing the double free patch (which only checks for chunks within the same bin). From here, we can control the `fd` pointer of the tcache chunk, doing a standard [tcache poisoning](https://github.com/shellphish/how2heap/blob/master/glibc_2.26/tcache_poisoning.c) to overwrite `__free_hook` with the win function.
37+
Then what about the size of the previous chunk that the heap manager uses to find the previous chunk header during forward consolidation?
38+
39+
This only applies when the previous-in-use flag is 0.
40+
Since the heap manager owns the previous chunk, it can store the size of the previous chunk at the end of the chunk data when the previous chunk is freed.
41+
In short, the chunk header is applicable only when the previous-in-use flag is 0.
4342

44-
Using a single null byte overflow to bypass the new double free protections in glibc 2.29 is a novel exploit. As common with binary exploitation techniques, naming rights go to the person the challenge author. Thus, we would like to refer to this as the House of Poortho, in honor of the problem creator.
43+
```
44+
+-------------------+------------------+
45+
-0x010 | data in previous chunk |
46+
+-------------------+------------------+
47+
0x000 | prev chunk size | 0x170 |
48+
+--------------------------------------+
49+
| ... |
50+
+--------------------------------------+
51+
+0x170 | next chunk |
52+
+--------------------------------------+
53+
```

0 commit comments

Comments
 (0)