This commit is contained in:
2025-02-20 19:31:32 +01:00
commit fb14fd90a4
14 changed files with 17085 additions and 0 deletions

22
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.10)
project(cache_attacks C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-O0" CACHE STRING "C Compiler flags" FORCE)
set(CMAKE_CXX_FLAGS "-O0" CACHE STRING "C++ Compiler flags" FORCE)
# Add shared library
add_library(sharedlib SHARED sharedlib.c sharedlib.h)
# Add the sender executable
add_executable(send send.c lib.c lib.h)
target_link_libraries(send sharedlib)
# Add the receiver executable
add_executable(recv recv.c lib.c lib.h)
target_link_libraries(recv sharedlib)
# add the cache-test executable
add_executable(cache_test cache_test.c lib.c lib.h)
target_link_libraries(cache_test sharedlib)

56
src/cache_test.c Normal file
View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "lib.h"
#include "sharedlib.h"
#define NUM_ACCESSES 1000000
void measure_multiple_accesses(void (*addr)(void), size_t num_accesses, size_t* hits, size_t* misses)
{
for (size_t i = 0; i < num_accesses; i++)
{
flush((void*) addr);
misses[i] = time_maccess(addr);
maccess((void*) addr);
hits[i] = time_maccess(addr);
}
}
size_t find_crossover_point(size_t* hits, size_t* misses, size_t num_accesses)
{
size_t hit_sum = 0, miss_sum = 0;
for (size_t i = 0; i < num_accesses; i++)
{
hit_sum += hits[i];
miss_sum += misses[i];
}
size_t avg_hit = hit_sum / num_accesses;
size_t avg_miss = miss_sum / num_accesses;
return (avg_hit + avg_miss) / 2; // Midpoint as threshold
}
int main()
{
size_t* hits = malloc(NUM_ACCESSES * sizeof(size_t));
size_t* misses = malloc(NUM_ACCESSES * sizeof(size_t));
if (!hits || !misses)
{
perror("Memory allocation failed");
return 1;
}
measure_multiple_accesses((void*) function, NUM_ACCESSES, hits, misses);
size_t threshold = find_crossover_point(hits, misses, NUM_ACCESSES);
printf("Suggested threshold: %zu\n", threshold);
free(hits);
free(misses);
return 0;
}

59
src/lib.c Normal file
View File

@@ -0,0 +1,59 @@
#include "lib.h"
size_t time_flush(void (* addr)(void))
{
uint64_t start, end, delta;
uint64_t lo, hi;
asm volatile ("LFENCE");
asm volatile ("RDTSC": "=a" (lo), "=d" (hi));
start = (hi<<32) | lo;
asm volatile ("LFENCE");
asm volatile ("CLFLUSH 0(%0)\n":: "c" (addr): "rax");
asm volatile ("MFENCE");
asm volatile ("RDTSC": "=a" (lo), "=d" (hi));
end = (hi<<32) | lo;
asm volatile ("LFENCE");
delta = end - start;
return delta;
}
size_t time_maccess(void (* addr)(void))
{
uint64_t start, end, delta;
uint64_t lo, hi;
asm volatile ("LFENCE");
asm volatile ("RDTSC": "=a" (lo), "=d" (hi));
start = (hi<<32) | lo;
asm volatile ("LFENCE");
asm volatile ("movq (%0), %%rax\n"
:
: "c" (addr)
: "rax");
asm volatile ("LFENCE");
asm volatile ("RDTSC": "=a" (lo), "=d" (hi));
end = (hi<<32) | lo;
asm volatile ("LFENCE");
delta = end - start;
return delta;
}
void maccess(void* p)
{
asm volatile ("movq (%0), %%rax\n"
:
: "c" (p)
: "rax");
}
void flush(void* p)
{
asm volatile ("clflush 0(%0)\n"
:
: "c" (p)
: "rax");
}

9
src/lib.h Normal file
View File

@@ -0,0 +1,9 @@
# pragma once
#include <stddef.h> // For size_t
#include <stdint.h> // For uint64_t
void maccess(void* p);
void flush(void* p);
size_t time_maccess(void (*addr)(void));
size_t time_flush(void (*addr)(void));

27
src/mksharedlib.py Normal file
View File

@@ -0,0 +1,27 @@
import os
def generate_nop_function(filename="sharedlib.c"):
with open(filename, "w") as f:
f.write("#include \"sharedlib.h\"\n\n")
f.write("void padding_before(void) { asm volatile (\n")
for _ in range(64):
f.write(" \"nop\\n\\t\"\n")
f.write(" :::\n); }\n\n")
f.write("void function(void)\n{")
f.write(" asm volatile (\n")
size = 64 * 256
for _ in range(size):
f.write(" \"nop\\n\\t\"\n")
f.write(" :::\n );\n}")
f.write("\n\nvoid padding_after(void) { asm volatile (\n")
for _ in range(64):
f.write(" \"nop\\n\\t\"\n")
f.write(" :::\n); }\n")
if __name__ == "__main__":
generate_nop_function()

98
src/recv.c Normal file
View File

@@ -0,0 +1,98 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include "lib.h"
#include "sharedlib.h"
#define BITS 8
#define BUFFER_SIZE 256
volatile uint8_t buffer[BUFFER_SIZE];
volatile size_t byte_index = 0;
volatile int sample_interval = 100; // Default: 100 µs
volatile int threshold = 245; // Default: 245 cycles
void signal_handler(int signo) {
if (signo == SIGALRM)
{
// Check if buffer is full
if (byte_index >= BUFFER_SIZE)
{
ualarm(0, 0); // Stop sampling
printf("Buffer full. Stopping capture.\n");
return;
}
// Receive a byte
uint8_t byte = 0;
for (int i = 0; i < BITS; i++)
{
size_t time = time_maccess((void *) function + (i << 9));
if (time < threshold)
{
// set the ith bit of byte to 1 if it was a cache hit
byte |= (1 << i);
}
}
// flush the cache
for (int i = 0; i < BITS; i++)
{
flush((void *) function + (i << 9));
}
buffer[byte_index++] = byte; // Store received byte
}
}
int main(int argc, char *argv[]) {
if (argc < 3)
{
fprintf(stderr, "Usage: %s <sample_interval> <threshold>\n", argv[0]);
return 1;
}
sample_interval = atoi(argv[1]);
threshold = atoi(argv[2]);
printf("Receiver started with sample interval: %d µs, threshold: %d cycles\n", sample_interval, threshold);
// Flush the cache once before starting
for (int i = 0; i < BITS; i++)
{
flush((void *) function + (i << 9));
}
signal(SIGALRM, signal_handler);
ualarm(sample_interval, sample_interval);
while (byte_index < BUFFER_SIZE) {
pause();
}
// Print received bytes in hex
printf("Received %zu bytes:\n", byte_index);
for (size_t i = 0; i < byte_index; i++) {
printf("%02X ", buffer[i]);
}
printf("\n");
// Print as ASCII characters
printf("ASCII Output:\n");
for (size_t i = 0; i < byte_index; i++) {
//if (buffer[i] >= 32 && buffer[i] <= 126) // Printable ASCII
if (isalnum(buffer[i]))
{
printf("%c", buffer[i]);
} else
{
printf("."); // Placeholder for non-printables
}
}
printf("\n");
return 0;
}

64
src/send.c Normal file
View File

@@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include "lib.h"
#include "sharedlib.h"
#define BITS 8
volatile uint8_t *buffer = NULL;
volatile size_t buffer_len = 0;
volatile size_t current_index = 0;
volatile uint8_t byte_to_send = 0;
void signal_handler(int signo)
{
if (signo == SIGALRM)
{
if (current_index < buffer_len)
{
byte_to_send = buffer[current_index++];
} else
{
current_index = 0;
}
}
}
int main(int argc, char *argv[])
{
if (argc < 3)
{
fprintf(stderr, "Usage: %s <string> <sample_interval>\n", argv[0]);
return 1;
}
buffer = (uint8_t *) argv[1];
buffer_len = strlen(argv[1]);
int sample_interval = atoi(argv[2]);
// set up an alarm signal that triggers every timeframe
signal(SIGALRM, signal_handler);
ualarm(sample_interval, sample_interval);
// during the timeframe, continuously send the signal
while (1)
{
for (int i = 0; i < BITS; i++)
{
if (byte_to_send & (1 << i))
{
maccess((void *) function + (i<<9));
}
else
{
flush((void *) function + (i<<9));
}
}
}
return 0;
}

16527
src/sharedlib.c Normal file

File diff suppressed because it is too large Load Diff

9
src/sharedlib.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef SHAREDLIB_H
#define SHAREDLIB_H
// Function declarations
void padding_before(void);
void function(void);
void padding_after(void);
#endif // SHAREDLIB_H