I am currently trying to reproduce a microarchitectural attack(CacheZoom) on SGX enclave, while doing so I have to hook one of the interrupt service routine(apic_timer_interrupt). The original author go on by doing some weird calculation of target address which I do not completely understand. And on top of that, the memcpy instruction causes my system to crash.
What I understand about how the interrupt service handler is evoked is that there is an interrupt vector table which stores the base address for the handler for different interrupts, so If we want to hook the interrupt service handler we could do so by overwriting the interrupt vector table to point to our handler. I am not sure whether the kernel symbol table(/proc/kallsysms) stores the address of the interrupt vector tables row entry or the address of the handler itself. If in case it stores the address of interrupt vector table entry then is not enough if I only copy the address of my new handler function to the address corresponding to the address from the kernel symbol table. Is it that am i missing something?
I have attached the function which does the hooking part. here, plocal_apic_timer_interrupt store the address returned by(sudo cat /proc/kallsyms | grep "T apic_timer_interrupt) and plapic_next_deadLine stores the address returned by(sudo cat /proc/kallsyms | grep "t lapic_next_deadline" | awk '{print $1}'). attack_handler is just the handler function definition.
static void attack_handler(void);
static int deadline_handler(unsigned long delta, void * evt);
static void enable_attack_timer()
{
unsigned int target_addr;
unsigned char call_stub[] = {0xe8, 0xf1, 0xf2, 0xf3, 0xf4};
unsigned char jmp_stub[] = {0xe9, 0xf1, 0xf2, 0xf3, 0xf4};
m_counter = 0;
write_cr0 (read_cr0 () & (~ 0x10000));
target_addr = attack_handler - plocal_apic_timer_interrupt - 5;
call_stub[1] = ((char*)&target_addr)[0];
call_stub[2] = ((char*)&target_addr)[1];
call_stub[3] = ((char*)&target_addr)[2];
call_stub[4] = ((char*)&target_addr)[3];
printk(KERN_ALERT "CACHEZOOM: %p\n", plocal_apic_timer_interrupt);
printk(KERN_ALERT "CACHEZOOM: %p\n", plapic_next_deadLine);
printk(KERN_ALERT "CACHEZOOM: %p\n", call_stub);
memcpy((void*)plocal_apic_timer_interrupt, call_stub, sizeof(call_stub));
target_addr = deadline_handler - plapic_next_deadLine - 5;
jmp_stub[1] = ((char*)&target_addr)[0];
jmp_stub[2] = ((char*)&target_addr)[1];
jmp_stub[3] = ((char*)&target_addr)[2];
jmp_stub[4] = ((char*)&target_addr)[3];
memcpy((void*)plapic_next_deadLine, jmp_stub, sizeof(jmp_stub));
write_cr0 (read_cr0 () | 0x10000);
hooked = true;
printk("\nCACHEZOOM: ENABLED\n");
}
I tried running the code without both the memcpy instruction and the output to kernel log is as follows. The address associated with the variables(I hope it helps to understand what is happening):
[ 131.153507] CACHEZOOM, plocal_apic_timer_interrupt: 00000000a7cbf5a5
[ 131.153511] CACHEZOOM, plapic_next_deadLine: 000000005f70f4fc
[ 131.153512] CACHEZOOM, call_stub: 000000005b2b7d9c
[ 131.153512] CACHEZOOM: hellooo
[ 131.153513]
CACHEZOOM: ENABLED