亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2780 | 回復(fù): 6
打印 上一主題 下一主題

截獲系統(tǒng)調(diào)用之改進版 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2007-06-18 15:25 |只看該作者 |倒序瀏覽
從網(wǎng)上看到有介紹截獲系統(tǒng)調(diào)用的文章,于是自己下載下來編譯執(zhí)行了一下。
但是發(fā)現(xiàn)這些例子都有缺點:像sys_execve(struct pt_regs regs)這樣的系統(tǒng)調(diào)用,
截獲后若要它仍然完成原有的功能需要調(diào)用do_execve()函數(shù),但是這個函數(shù)是內(nèi)核不導(dǎo)
出,很麻煩。另外,即算是截獲函數(shù)實現(xiàn)了它的功能,錯誤還是難免出現(xiàn)。

    于是就想怎么樣截獲后又能不留痕跡地實現(xiàn)原有功能。一個好的想法是直接在截獲函數(shù)中
直接調(diào)用sys_execve().然而想到信號處理時如果中斷了系統(tǒng)調(diào)用則可以重新執(zhí)行,那么
能不能通過類似的方法執(zhí)行系統(tǒng)調(diào)用呢?一個想法:替換之前將要替換的系統(tǒng)調(diào)用保存在其他
中斷向量中,然后在替換函數(shù)中調(diào)整內(nèi)核堆棧,讓系統(tǒng)重新以另一個調(diào)用號調(diào)用保存的系統(tǒng)調(diào)用。

經(jīng)過近兩天的編碼調(diào)試,終于如愿以償。先說明一下關(guān)鍵之處,然后是代碼。
關(guān)鍵之處:   
1.將原來的系統(tǒng)調(diào)用函數(shù)保存在向量__NR_save=17中,這里用17有兩個原因
    1) 在文件syscall_table.S中,向量17的函數(shù)是sys_ni_syscall,這是一個沒有使用的
        調(diào)用號。
       .long sys_ni_syscall    /* old break syscall holder */
    2) 一開始我用 319,因為NR_syscalls=318
        #define NR_syscalls 318
        大于NR_syscalls的調(diào)用號自然沒人用,然而這樣做不行。因為在entry.S中
        system_call:
            ...
            cmpl $(nr_syscalls), %eax
            jae syscall_badsys   
            . ...
       若調(diào)用號大于NR_syscalls,根本不會執(zhí)行調(diào)用函數(shù)
2.    信號處理中重新執(zhí)行中斷的調(diào)用是這樣做的:
       case -ERESTARTNOINTR:
          regs->eax = regs->orig_eax;
          regs->eip -= 2;
    于是我就想這樣做
          pr.eip-=2;
    然而老是出錯,后來查看匯編后的代碼發(fā)現(xiàn),減2操作是在寄存器中實現(xiàn)的,內(nèi)核堆棧
    根本沒有改變。于是改用匯編:
     __asm__("sub $0x2,%0" : "=m" (pr.eip));
3.  將內(nèi)核堆棧中regs.eax改為__NR_save,然而這一步不能通過在函數(shù)中賦值改變
    因為在entry.S中調(diào)用完函數(shù)后,內(nèi)核將寄存器eax值存入regs.eax中
         system_call:
            ...
            call *sys_call_table(,%eax,4)
            movl %eax,EAX(%esp)             # store the return value      
             . ...  
    我們知道寄存器eax存的是函數(shù)返回值,于是我將替換函數(shù)返回_NR_save,讓內(nèi)核自動
    將其保存在regs.eax。
以下是代碼:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xunil@bmy and hhj");
MODULE_DESCRIPTION("Different from others, this module automatically locate the entry of sys_call_table !");
unsigned long *sys_call_table=NULL;
//asmlinkage
int (*orig_exec)(struct pt_regs);
int __NR_save=17;
struct _idt
{
unsigned short offset_low,segment_sel;
unsigned char reserved,flags;
unsigned short offset_high;
};

unsigned long *getscTable(void)
{

unsigned char idtr[6],*shell,*sort;
struct _idt *idt;
unsigned long system_call,sct;
unsigned short offset_low,offset_high;
char *p;
int i;


/* get the interrupt descriptor table */

__asm__("sidt %0" : "=m" (idtr));

/* get the address of system_call */
idt=(struct _idt*)(*(unsigned long*)&idtr[2]+8*0x80);
offset_low = idt->offset_low;
offset_high = idt->offset_high;
system_call=(offset_high<<16)|offset_low;

shell=(char *)system_call;
sort="\xff\x14\x85";

/* get the address of sys_call_table */

for(i=0;i<(100-2);i++)
if(shell==sort[0]&&shell[i+1]==sort[1]&&shell[i+2]==sort[2])
{
printk("here ok!!\n");
break;

}
p=&shell;
p+=3;
sct=*(unsigned long*)p;

return (unsigned long*)(sct);
}
//asmlinkage
int hacked_exec(struct pt_regs pr){
    __asm__("sub $0x2,%0" : "=m" (pr.eip));
//    pr.eax=__NR_save;
    printk("PID %d called sys_execve !\n",current->pid);
    return __NR_save;
}


static int __init find_init(void){
sys_call_table = getscTable();
printk("here 1\n");

orig_exec=(int(*)(struct pt_regs))(sys_call_table[__NR_execve]);
printk("here 2,%d\n",__NR_save);
sys_call_table[__NR_execve]=(long)hacked_exec;
sys_call_table[__NR_save]=(long)orig_exec;
return 0;
}

static void __exit find_cleanup(void){
sys_call_table[__NR_execve]=(unsigned long)orig_exec;
}

module_init(find_init);
module_exit(find_cleanup);
有空到我的博客瞧瞧哦 hhj.cublog.cn

[ 本帖最后由 hauto 于 2007-6-18 15:27 編輯 ]

論壇徽章:
0
2 [報告]
發(fā)表于 2007-06-18 16:06 |只看該作者
說實話,我覺得符號不導(dǎo)出是一項shit一樣的功能,除了給程序員制造障礙以外別無所圖。

論壇徽章:
0
3 [報告]
發(fā)表于 2007-06-18 16:43 |只看該作者
原帖由 hauto 于 2007-6-18 15:25 發(fā)表于 1樓  
從網(wǎng)上看到有介紹截獲系統(tǒng)調(diào)用的文章,于是自己下載下來編譯執(zhí)行了一下。
但是發(fā)現(xiàn)這些例子都有缺點:像sys_execve(struct pt_regs regs)這樣的系統(tǒng)調(diào)用,
截獲后若要它仍然完成原有的功能需要調(diào)用do_execve() ...

我有一點疑問是,既然都要改kernel,為什么不改簡單一點呢?你可以直接在INT 80 的handler加一個hook,這個hook首先保存上下文(幾個寄存器的值),然后執(zhí)行你要的操作,最后返回時再恢復(fù)上下文即可。
另外如果是想在實際運用中截獲系統(tǒng)調(diào)用,使用ptrace()函數(shù)是正道。

[ 本帖最后由 zx_wing 于 2007-6-18 16:47 編輯 ]

論壇徽章:
0
4 [報告]
發(fā)表于 2007-06-18 16:54 |只看該作者
原帖由 zx_wing 于 2007-6-18 16:43 發(fā)表于 3樓  

我有一點疑問是,既然都要改kernel,為什么不改簡單一點呢?你可以直接在INT 80 的handler加一個hook,這個hook首先保存上下文(幾個寄存器的值),然后執(zhí)行你要的操作,最后返回時再恢復(fù)上下文即可。
另外如 ...

想法不錯!不過,實現(xiàn)起來恐怕沒那么簡單吧?

論壇徽章:
0
5 [報告]
發(fā)表于 2007-06-18 17:12 |只看該作者
關(guān)鍵是保存上下文,其它倒不難

[ 本帖最后由 zx_wing 于 2007-11-12 13:01 編輯 ]

論壇徽章:
0
6 [報告]
發(fā)表于 2007-11-12 10:53 |只看該作者
to  zx-wing  ;
     有沒有例子啊 , 發(fā)上來看看啊。。

論壇徽章:
0
7 [報告]
發(fā)表于 2007-12-04 14:33 |只看該作者
樓主,你這兒是不是錯了
if(shell==sort[0]&&shell[i+1]==sort[1]&&shell[i+2]==sort[2])
{
printk("here ok!!\n");
break;

}
p=&shell;
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP