IT技ji)躉? 渙髕教/h4>

甘肃福彩网官网

作者(zhe)︰佚名  發布日期︰2020-02-20 02:46:50

前(qian)言︰ 《Linux Rootkit 系列一︰ LKM的mu)”嘈醇耙cang)》的作者(zhe)似乎跑路了(liao);留下的這個口鍋,我(wo)試著背(bei)一下。鑒于筆者(zhe)知識能力(li)上的不足,如有問題(ti)歡迎(ying)各(ge)位扔豆腐,不要砸yi)┤貳br />與第一篇文章(zhang)作者(zhe)所想象(xiang)的不同,本文不打算給大家介(jie)紹三(san)種不同的系統調用掛鉤技ji)  嚳矗 疚慕魷 附步庾羆jian)單(dan)的系統調用掛鉤方案,並(bing)且(qie)基于這個方案實現最基本的文件(jian)監視工具。這樣,既可(ke)以讓(rang)讀者(zhe)輕松上手進行(xing)實dao)視τ茫又可(ke)以加深、鞏固(gu)讀者(zhe)對LKM 的理(li)解,同時還免(mian)去了(liao)一次學習多種掛鉤方案的理(li)論知識壓力(li)。
所以,本文力(li)求以實驗為核心mo) 懇桓霾街瓚伎ke)能有對應的實驗代碼。代碼倉庫︰ https://github.com/NoviceLive/research-rootkit 。代碼在(zai)最新的 64 比(bi)特 Arch 與Kali 上面測試正常。
測試建議︰ 不要在(zai)物理(li)機測試!不要在(zai)物理(li)機測試!不要在(zai)物理(li)機測試!
如果讀者(zhe)使(shi)用 tmux 或(huo)者(zhe)類(lei)似的工具,則可(ke)以垂直分zhi)金ni)的終端(duan)窗口, 一個窗口開一個 sudo dmesg -C && dmesg -w,用于查看日志; 另一個窗口用來做其(qi)他操(cao)作,比(bi)如構建、加載(zai)內(na)核模(mo)塊。 不用tmux 也(ye)沒關系,開兩(liang)個終端(duan),各(ge)佔半個屏幕(mu)。
第一部(bu)分︰基于修改(gai) sys_call_table 的系統調用掛鉤
在(zai)系統調用掛鉤技ji)踔校 羆jian)單(dan)、最流行(xing)的方案是修改(gai)sys_call_table, 成(cheng)員類(lei)型(xing)為函數(shu)指(zhi)針的一維數(shu)組。
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
 /*
  * Smells like a compiler bug -- it doesn't work
  * when the & below is removed.
  */
 [0 ... __NR_syscall_max] = &sys_ni_syscall,
#include
};
要修改(gai)它,首先得拿到它在(zai)內(na)存里的位置。 然huan)螅 捎ys_call_table所在(zai)的內(na)存是有xing)幢bao)護的mo)所以我(wo)們需要先去掉寫保(bao)護,再做修改(gai)。
1. 獲(huo)得 sys_call_table 的內(na)存地址
在(zai)綜合考量了(liao)幾種可(ke)選的mu)袢》槳鋼 螅 收zhe)決定采用從(cong)內(na)核起始地址開始暴力(li)搜索(suo)內(na)存空間的方案。 (但(dan)是這種方案有可(ke)能被欺騙 。)
其(qi)他可(ke)能的方案有,一,從(cong)/boot/System.map 中讀取,感xing)巳?畝琳zhe)可(ke)以查閱(yue) Hooking the Linux System CallTable, 這篇文章(zhang)便是使(shi)用這種方案來獲(huo)取sys_call_table的地址的。
二,從(cong)使(shi)用了(liao)sys_call_table的某些未導(dao)出函數(shu)的mu)qi)碼里面進行(xing)特征搜索(suo), 感xing)巳?畝琳zhe)可(ke)以查閱(yue)Kernel-LandRootkits, 作者(zhe)花了(liao)幾張 slides 闡述了(liao)如何從(cong)導(dao)出的函數(shu)中獲(huo)取使(shi)用了(liao)sys_call_table的未導(dao)出函數(shu), 進而搜索(suo)那個未導(dao)出函數(shu)的mu)qi)碼, 得到sys_call_table的地址;等等。
值得指(zhi)fu)齙氖牽感xing)巳?畝琳zhe)在(zai)測試這些本文未涉及的方案時bao) 綣齙攪liao)疑惑或(huo)者(zhe)困難,也(ye)可(ke)以與筆者(zhe)聯系、交流。
直接看代碼。
unsigned long **
get_sys_call_table(void)
{
  unsigned long **entry = (unsigned long **)PAGE_OFFSET;
  for (;(unsigned long)entry 1) {
    if (entry[__NR_close] == (unsigned long *)sys_close) {
        return entry;
      }
  }
  return NULL;
}
PAGE_OFFSET是內(na)核內(na)存空間的起始地址。 因為sys_close是導(dao)出函數(shu)(需要指(zhi)fu)齙氖牽sys_open 、 sys_read 等並(bing)不是導(dao)出的mo)  wo)們qiang)梢災苯擁玫剿牡?罰灰蛭 低車饔煤(也(ye)就是sys_call_table這個一維數(shu)組的索(suo)引(yin)) 在(zai)同一ABI (x86跟 x64 不是同一 ABI)上具有高度的後向兼容性,更重要的是,我(wo)們qiang)梢災苯郵shi)用這個索(suo)引(yin)(代碼中的 __NR_close )!
從(cong)內(na)核內(na)存的起始地址開始, 逐一嘗(chang)試每一個指(zhi)針大小的內(na)存︰把它當bei)墑ys_call_table的地址, 用某個系統調用的編號(也(ye)就是索(suo)引(yin))訪問數(shu)組中的成(cheng)員bao) 綣夢實玫降鬧蹈蘸檬鞘欽飧魷低車饔煤潘雜Φ南低車饔玫牡?罰 敲次wo)們就認(ren)為當前(qian)嘗(chang)試的這塊指(zhi)針大小的內(na)存就是我(wo)們qie) 業ys_call_table的地址。
實驗效果如圖。

2. 關閉寫保(bao)護
寫保(bao)護指(zhi)的是寫入只讀內(na)存時bei)齟懟這個特性yue)ke)以通(tong)過CR0寄存器(qi)控制︰開啟或(huo)者(zhe)關閉, 只需要修改(gai)一個比(bi)特,也(ye)就是從(cong) 0 開始ji)shu)的第 16個比(bi)特。
看代碼。我(wo)們qiang)梢允shi)用read_cr0 /write_cr0 來讀取 /寫入 CR0 寄存器(qi),免(mian)去我(wo)們自己寫內(na)聯匯編的麻煩。
函數(shu)原型(xing)。
static inline unsigned long read_cr0(void);
static inline void write_cr0(unsigned long x);
關閉寫保(bao)護的源代碼︰將CR0 寄存器(qi)從(cong) 0開始ji)shu)的第 16 個比(bi)特置為 0。
void
disable_write_protection(void)
{
  unsigned long cr0 = read_cr0();
  clear_bit(16, &cr0);
  write_cr0(cr0);
}
開啟寫保(bao)護的源代碼︰將CR0 寄存器(qi)從(cong) 0開始ji)shu)的第 16 個比(bi)特置為 1。
void
enable_write_protection(void)
{
  unsigned long cr0 = read_cr0();
  set_bit(16, &cr0);
  write_cr0(cr0);
}
在(zai)設置或(huo)者(zhe)清除某個比(bi)特,我(wo)們使(shi)用了(liao)set_bit與clear_bit。 它們是 Linux 內(na)核提供給內(na)核模(mo)塊使(shi)用的編程(cheng)接口,簡(jian)單(dan)易(yi)懂,同時還免(mian)去了(liao)我(wo)們自己寫那種很難讀的位運算的痛苦(ku)。
函數(shu)原型(xing)。
static __always_inline void
set_bit(long nr, volatile unsigned long *addr);
static __always_inline void
clear_bit(long nr, volatile unsigned long *addr);
實驗結(jie)果截圖。

3. 修改(gai) sys_call_table
一維數(shu)組賦(fu)值,當之無愧(kui)最簡(jian)單(dan)的方案。當bi)唬 wo)們需要先把真正的值保(bao)存好,以備後面之需。
disable_write_protection();
real_open = (void *)sys_call_table[__NR_open];
sys_call_table[__NR_open] = (unsigned long*)fake_open;

real_unlink = (void *)sys_call_table[__NR_unlink];
sys_call_table[__NR_unlink] = (unsigned long*)fake_unlink;
real_unlinkat = (void *)sys_call_table[__NR_unlinkat];
sys_call_table[__NR_unlinkat] = (unsigned long*)fake_unlinkat;
enable_write_protection();
4. 恢zhi)fu)
disable_write_protection();
sys_call_table[__NR_open] = (unsigned long*)real_open;
sys_call_table[__NR_unlink] = (unsigned long*)real_unlink;
sys_call_table[__NR_unlinkat] = (unsigned long*)real_unlinkat;
enable_write_protection();
第二部(bu)分︰基于系統調用掛鉤的初級(ji)文件(jian)監視
監視文件(jian)的創建與刪除。 我(wo)們掛鉤sys_open,sys_unlink,sys_unlinkat這三(san)個函數(shu), 並(bing)且(qie)在(zai)我(wo)們的鉤子函數(shu)把操(cao)作到的文件(jian)名打印出來,然huan)蟀芽?平桓嬲南低車饔麼 li)。
1. sys_open 的鉤子函數(shu)︰ fake_open
考慮到在(zai)系統運行(xing)時bao) 暈募jian)的讀寫操(cao)作從(cong)未中斷(duan),這里只打印了(liao)進行(xing)創建操(cao)作的文件(jian)名,準確(que)地說是,sys_open 的 flags中包含(han) O_CREAT 。
asmlinkage long
fake_open(const char __user *filename, int flags, umode_t mode)
{
  if ((flags & O_CREAT) && strcmp(filename, "/dev/null") != 0) {
    printk(KERN_ALERT "open: %s ", filename);
  }
  return real_open(filename, flags, mode);
}
注︰這里的strcmp也(ye)是內(na)核提供的。
2. sys_unlink 與 sys_unlinkat 的鉤子函數(shu)︰ fake_unlink 與 fake_unlinkat
簡(jian)單(dan)處理(li),直接打印路徑(jing)名。
asmlinkage long
fake_unlink(const char __user *pathname)
{
  printk(KERN_ALERT "unlink: %s ", pathname);
  return real_unlink(pathname);
}
asmlinkage long
fake_unlinkat(int dfd, const char __user * pathname, int flag)
{
  printk(KERN_ALERT "unlinkat: %s ", pathname);
  return real_unlinkat(dfd, pathname, flag);
}
3. 測試我(wo)們的文件(jian)監視工具
初級(ji)的文件(jian)監視就到這了(liao),以後我(wo)們在(zai)做進一步的改(gai)進與完善。
效果見下圖。

第三(san)部(bu)分︰參考資(zi)料與延伸閱(yue)讀
1. 參考資(zi)料
Linux Cross Reference
The Linux KernelAPI
How the Linux kernel handles a systemcall
CR0
2. 延伸閱(yue)讀
Hooking the Linux System CallTable
Kernel-LandRootkits
 
Tag標簽︰系統  
  • 甘肃福彩网官网

About IT165 - 天天PK10官网廣告(gao)服務 - 隱私聲明 - 版權(quan)申明 - 免(mian)責(ze)條款 - 網站地圖 - 網友投稿(gao) - 聯系方式(shi)
本站內(na)容來自于互聯網,僅供用于網絡技ji)躚 學習中請遵循相關法律(lv)法規
甘肃福彩网官网 | 下一页