posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          讀核筆記(3) - 系統調用

          Posted on 2008-02-18 14:35 ZelluX 閱讀(559) 評論(4)  編輯  收藏 所屬分類: LinuxSystem
          _syscall 宏:
          最簡單的沒有參數的系統調用的實現:
          /*?XXX?-?_foo?needs?to?be?__foo,?while?__NR_bar?could?be?_NR_bar.?*/
          #define?_syscall0(type,name)?\
          type?name(
          void)?\
          {?\
          long?__res;?\
          __asm__?
          volatile?("int?$0x80"?\
          ????:?
          "=a"?(__res)?\
          ????:?
          "0"?(__NR_##name));?\
          __syscall_return(type,__res);?\
          }

          以getuid()為例,_syscall0(int, getuid)展開后就變成
          int?getuid(void)
          {
          ????
          long?__res;
          ????__asm__?
          volatile("int?$0x80"
          ????????????????????:
          "=a"?(__res)
          ????????????????????:
          "0"??(__NR_getuid));
          ????__syscall_return(
          int,?__res);
          }

          程序把系統調用號__NR_getuid放入eax寄存器,然后調用軟中斷。
          include/asm-i386/hw_irq.h中的定義:
          00025?? #define SYSCALL_VECTOR??0x80;

          arch/i386/kernel/traps.c中把該中斷號綁定到system_call函數:
          00944?? set_system_gate(SYSCALL_VECTOR,&system_call);

          system_call函數在arch/i386/kernel/entry.S中:
          ENTRY(system_call)
          ????pushl?%eax????????????#?save?orig_eax
          ????SAVE_ALL
          ????GET_CURRENT(%ebx)
          ????testb?$0x02
          ,tsk_ptrace(%ebx)????#?PT_TRACESYS
          ????jne?tracesys
          ????cmpl?$(NR_syscalls)
          ,%eax
          ????jae?badsys
          ????call?*SYMBOL_NAME(sys_call_table)(
          ,%eax,4)
          ????movl?%eax
          ,EAX(%esp)????????#?save?the?return?value
          ENTRY(ret_from_sys_call)
          ????cli????????????????#?need_resched?and?signals?atomic?test
          ????cmpl?$
          0,need_resched(%ebx)
          ????jne?reschedule
          ????cmpl?$
          0,sigpending(%ebx)
          ????jne?signal_return
          restore_all:
          ????RESTORE_ALL
          主要步驟:
          1. 保留一份系統調用號的最初拷貝
          2. 保存堆棧環境(SAVE_ALL)
          3. 得到當前task_struct的地址,保存到ebx中
          4. 檢查系統調用號
          5. 根據%eax調用號計算地址,調用相應函數
          6. 在entry.S后面可以看到,
          .data
          ENTRY(sys_call_table)
          ????.long?SYMBOL_NAME(sys_ni_syscall)????/*?
          0??-??old?"setup()"?system?call*/
          ????????
          ????.long?SYMBOL_NAME(sys_getuid16)
          ????.long?SYMBOL_NAME(sys_stime)????????/*?
          25?*/
          ????.long?SYMBOL_NAME(sys_ptrace)
          ????????
          sys_call_table + %eax * 4是sys_getuid16地址,kernel/uid16.c中:
          asmlinkage?long?sys_getuid16(void)
          {
          ????
          return?high2lowuid(current->uid);
          }
          很簡單的處理代碼,返回當前進程的uid。這里asmlinkage修飾符表示函數必須從堆棧中,而不是從寄存器中拿參數(防止gcc用寄存器傳參優化)。
          7. 保存返回值eax到堆棧中的eax
          8. RESTORE_ALL

          另外這里再提一下GET_CURRENT的實現
          #define?GET_CURRENT(reg)?\
          ????movl?$-
          8192,?reg;?\
          ????andl?%esp,?reg
          很巧妙的實現,把棧指針與掩碼-8192做與操作,末尾13位清零,就是當前的進程的task_struct地址了。


          接下來是利用內核模塊動態添加一個系統調用的例程,由于2.4.20以后sys_call_table符號不再被導出了,要獲得這個地址得手動hack。尚未成功,下次回過頭來看看。

          評論

          # re: 讀核筆記(3) - 系統調用  回復  更多評論   

          2008-02-18 16:07 by overboming
          版主,代碼高亮怎么做方便來著?

          # re: 讀核筆記(3) - 系統調用  回復  更多評論   

          2008-02-18 16:09 by ZelluX
          @overboming
          這個博客網站的編輯器有相關的功能

          # re: 讀核筆記(3) - 系統調用  回復  更多評論   

          2008-02-26 16:03 by luohandsome
          水木的kerneltech板5507講系統調用劫持的:
          LKM Rootkits on Linux x86 v2.6

          # re: 讀核筆記(3) - 系統調用  回復  更多評論   

          2008-02-26 16:18 by ZelluX
          @luohandsome
          恩,多謝啦~~
          主站蜘蛛池模板: 武宁县| 孟津县| 博爱县| 德令哈市| 钟祥市| 马尔康县| 博客| 翼城县| 胶州市| 宁国市| 汤阴县| 东至县| 沧州市| 台江县| 驻马店市| 盐城市| 台南县| 广东省| 江西省| 柳林县| 北海市| 铜陵市| 屏山县| 翁牛特旗| 隆昌县| 台湾省| 卫辉市| 盐池县| 漳浦县| 高安市| 老河口市| 府谷县| 东乡| 潞城市| 临朐县| 菏泽市| 双流县| 保靖县| 东平县| 五大连池市| 临安市|