Created
September 3, 2014 19:55
-
-
Save Cr4sh/fe910f0d1b0559efd43d to your computer and use it in GitHub Desktop.
Dynamically finding sys_call_table on Linux x86_64 systems
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment