-
Notifications
You must be signed in to change notification settings - Fork 1
/
client.cpp
196 lines (165 loc) · 5.29 KB
/
client.cpp
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
/*
*
* Using Flush + Reload to perform covert-channel communication
* between sender + receiver
*
* sender side code
*
*/
#include "util.hpp"
#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <time.h>
#include <string.h>
int RECV_MODE = 0;
int SEND_MODE = 1;
int SEND_TIMES = 50000;
int PAGE_SIZE = 4096;
int STRIDE = PAGE_SIZE * 2;
int offset[] = {12, 135, 235, 345, 465, 568, 648, 771};
inline unsigned long probe(const uint8_t* addr){
volatile unsigned long time;
asm __volatile__(
" mfence \n"
" lfence \n"
" rdtsc \n"
" lfence \n"
" movl %%eax, %%esi \n"
" movl (%1), %%eax \n"
" lfence \n"
" rdtsc \n"
" subl %%esi, %%eax \n"
" clflush 0(%1) \n"
: "=a" (time)
: "c" (addr)
: "%esi", "%edx"
);
return time;
}
inline void flush(const uint8_t* addr){
asm __volatile__("mfence\nclflush 0(%0)" : : "r"(addr) :);
}
void sleep(int i);
char getSentChar(const uint8_t* base_addr);
void flushMem(const uint8_t* base_addr, int size_in_bytes);
int main(int argc, char** argv){
// Allocate the memory and get base address
int map_length = PAGE_SIZE * 17;
int stride = PAGE_SIZE*2;
int fd = open("/bin/ls", O_RDONLY);
assert(fd > 0);
const uint8_t* base_addr = (const uint8_t*)mmap(NULL, map_length, PROT_READ, MAP_SHARED, fd, 0);
base_addr = (uint8_t*) ((( (uintptr_t)base_addr >> 12) + 1) << 12);
// flush all the memory
flushMem(base_addr, PAGE_SIZE * 16);
char char_recv = '0';
char char_sent = '0';
char foo = '0';
bool flag = false;
bool mode = SEND_MODE;
printf("\n\n * * * Welcome to the cache side-channel world. * * * \n\n\n");
while(1){
if (mode == SEND_MODE){
printf("You're in SENDER mode. Press 'recv' to enter RECEIVER mode.\n");
}
if (mode == RECV_MODE){
char_recv = getSentChar(base_addr);
if(flag && char_recv != 1){
printf("%c\n", char_recv);
flag = false;
if(char_recv == '\n')
mode = SEND_MODE;
}
if(char_recv == 1){
flag = true;
}
} else if (mode == SEND_MODE){
char text_buf[128];
for(int i=0; i<128; i++){
text_buf[i] = 0;
}
fgets(text_buf, sizeof(text_buf), stdin);
if(strcmp(text_buf, "recv\n") == 0){
printf("You're in RECEIVER mode. Now send message on the other end.\n");
mode = RECV_MODE;
continue;
}
clock_t begin = clock();
// send text
for(int i=0; i<128; i++){
for(int r=0; r<SEND_TIMES; r++){
char_sent = 1;
// send char_sent
for(int j=0; j<8; j++){
if(char_sent & 0x1) { // send 1
const uint8_t* target_addr = base_addr + j * STRIDE + offset[j];
foo = *target_addr;
}
char_sent = char_sent >> 1;
}
}
for(int r=0; r<SEND_TIMES; r++){
char_sent = text_buf[i];
// send char_sent
for(int j=0; j<8; j++){
if(char_sent & 0x1) { // send 1
const uint8_t* target_addr = base_addr + j * STRIDE + offset[j];
foo = *target_addr;
}
char_sent = char_sent >> 1;
}
}
if (text_buf[i] == '\n')
break;
}
clock_t end = clock();
double bytes_per_sec = strlen(text_buf) / ( (double) (end-begin) / CLOCKS_PER_SEC );
printf("%f bytes per second\n\n", bytes_per_sec);
} else {
assert(0);
}
}
return 0;
}
void flushMem(const uint8_t* base_addr, int size_in_bytes){
for(int i=0; i<size_in_bytes; i++)
flush(base_addr + i);
}
char getSentChar(const uint8_t* base_addr){
unsigned long res_time[8];
char prev_char = (char) 1;
char curr_char = (char) 0;
while(prev_char != curr_char){
prev_char = curr_char;
curr_char = (char) 0;
for (int j=0; j<8; j++){
res_time[j] = 0;
}
// flush every lines in every sets
for(int j=0; j<8; j++){
const uint8_t* flush_addr = base_addr + j * STRIDE + offset[j];
flush(flush_addr);
}
sleep(10);
// probe every lines in every sets
// prefetching works after print 8 res_time_new
for(int j=0; j<8; j++){
const uint8_t* probe_addr = base_addr + j * STRIDE + offset[j];
res_time[j] += probe(probe_addr);
}
for (int i=0; i<8; i++){
if (res_time[i] < 200){ // hit
curr_char = curr_char | (1 << i);
}
}
}
return curr_char;
}
void sleep(int i){
for (int ii =0; ii < i; ii++){
for (int jj=0; jj<10000; jj++){
;
}
}
}