void **find_sys_call_table(void *kernel_addr, int kernel_size) { /* Check for the system_call_fastpath() signature, hand-written piece of assembly code from arch/x86/kernel/entry_64.S: ja badsys mov rcx, r10 call sys_call_table[rax * 8] mov [rsp + 20h], rax ret_from_sys_call: mov edi, 1000FEFFh This instructions are unchanged for the last 7 years (and maybe even more, haven't older kernels on my test machines), so, looks reliable enough. */ unsigned char *mask = "\xff\xff\x00\x00\x00\x00" "\xff\xff\xff" "\xff\xff\xff\x00\x00\x00\x00" "\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff"; unsigned char *sign = "\x0f\x87\x00\x00\x00\x00" "\x4c\x89\xd1" "\xff\x14\xc5\x00\x00\x00\x00" "\x48\x89\x44\x24\x20" "\xbf\xff\xfe\x00\x10"; int i = 0, n = 0, sign_len = 26; for (i = 0; i < kernel_size; i += 1) { unsigned char *p = (unsigned char *)kernel_addr + i; char matched = 1; for (n = 0; n < sign_len; n += 1) { // match signature byte if ((*(p + n) & mask[n]) != sign[n]) { matched = 0; break; } } if (matched > 0) { // get sys_call_table address return (void **)(((unsigned long long)kernel_addr & 0xffffffff00000000) + *(unsigned long *)(p + 0x0c)); } } return NULL; }