歡迎您光臨本站 註冊首頁

Linux下用gdb檢測內核rootkit

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

導讀:
  本文涉及的技術原理都不是新的,對研究人員沒什麼特別大的價值,
  不過對工程人員應急相應來說不失為一種新的方法.
  【理解攻擊向量】
  前面兩段廢話直接掠過...實在浪費感情-_-!
  內核rookit通常以系統調用為攻擊目標,主要出於兩個原因:
  a.在內核態劫持系統調用能以較小的代價控制整個系統,不必修太多東西;
  b.應用層大多數函數是一個或多個系統調用不同形式的封裝,更改系統調用意味著其上層所有的
  函數都會被欺騙;
  在kernel-2.4.27中大約有230多個系統調用,而kernel-2.6.9中大約有290多個系統調用,系統調
  用的個數取決於內核版本.完整的系統調用列表可以在 /usr/include/asm/unistd.h頭文件中獲得.
  另外需要注意的是入侵者並不更改所有的系統調用,而只是替換其中一些比較有用的.這些系統調用
  如表一所示,他們可以被系統管理員及入侵檢測系統(OS kernel級IDS)監視,可以用man命令得到
  每個系統調用的完整描述.
  System call name    Short description          ID
  -------------------------------------------------------------------------------------------
  sys_read      used for reading from files       3
  sys_write      used for writing to files         4
  sys_open      used to create or open files       5
  sys_getdents/sys_getdents64  used to list a content of directories(also /proc)   141/220
  sys_socketcall    used for managing sockets        102
  sys_query_module    used for querying loaded modules       167


  sys_setuid/sys_getuid  used for managing UIDs         23/24
  sys_execve    used for executing binary files       11
  sys_chdir      used to change the directory       12
  sys_fork/sys_clone    used to create a child process       2/120
  sys_ioctl      used to control devices         54
  sys_kill      used to send signal to processes       37
  我們注意上表的系統調用號,這些ID都是針對kernel-2.4.18-3的.
  本文所有的例子都在Redhat7.3 kernel-2.4.18-3上通過測試,我們也可以在其他版本包括最新的2.6.x上
  用相似的步驟研究,不同之處可能在於2.6的一些內部結構,比如系統調用表的地址原來內含在系統調用
  處理常式system_call中,現在改成在syscall_call函數中.
  【更改系統調用表】
  當前的系統調用地址保存在系統調用表中,位於操作系統為內核保留的內存空間(虛擬地址最高1GB),系統
  調用入口地址的存放順序同/usr/include/asm/unistd.h中的排列順序,按系統調用號遞增.
  -_-!鑒於原文廢話很多,我就跳著翻譯或者概括起來翻譯,有興趣的可以找本Linux內核的書看看(e.g:ULK2)
  在0x80軟中斷髮生之前,對應的系統調用號被壓入eax寄存器,例如sys_write被調用時,其對應的系統調用
  ID:4會被壓入eax
  入侵者使用的第一種方法是:更改系統調用表中的系統調用地址,這樣系統調用發生時會跳轉到攻擊者自己
  編寫的函數去執行.通過觀察系統調用表中的系統調用入口地址,使用gdb我們可以比較容易檢測到這種攻


  擊行為.
  原始的系統調用地址在內核編譯階段被指定,不會更改,通過比較原始的系統調用地址和當前內核態中的系統
  調用地址我們就可以發現系統調用有沒有被更改.原始的系統調用地址在編譯階段被寫入兩個文件:
  a.System.map該文件包含所有的符號地址,系統調用也包含在內
  b.系統初始化時首先被讀入內存的內核映像文件vmlinux-2.4.x
  vmlinux-2.4.x文件通常以壓縮的格式存放在/boot目錄下,在比較之前必須解壓這個文件,另一個問題是:
  我們的比較的前提是假設system.map及vmlinuz image都沒有被入侵者更改,更安全的做法是在系統乾淨
  時已經創建這兩個文件的可信任的拷貝,並創建文件的md5 hash.
  原文中也列舉了一個內核模塊[gcc -c scprint.c -I/usr/src/`uname -r`/include/ ]使用該模塊列印系統
  調用地址,並自動寫入syslog,這樣可以進行實時的比較.
  在大多數被裝載內核後門情況中,內核在系統初始化之後才被更改,更改發生在載入了rootkit的module或者被
  植入直接讀寫/dev/kmem的on-the-fly kernel patch之後.而通常情況下rootkit並不更改vmlinuz和system.map
  這兩個文件,列印這兩個文件中的符號地址就可以知道系統原始的系統調用地址,系統當前運行中的系統
  調用地址(可能被更改)可以同過/proc下的kcore文件得到,比較兩者就知道結果.
  1.首先找出系統調用表地址:
  [root@rh8 boot]# cat System.map-2.4.18-13 | grep sys_call_table c0302c30 D sys_call_table
  2.使用nm命令可以列印出未被strip過的image文件中所有的符號地址:
  [root@rh8 boot]# nm vmlinux-2.4.18-13 | grep sys_call_table


  c0302c30 D sys_call_table
  使用gdb可以列印出所有的系統調用入口地址,這些對應的地址在內核源代碼的entry.S文件中定義,例如:
  entry 0 (0xc01261a0)是sys_ni_syscall系統調用
  entry 1 (0xc011e1d0)是sys_exit系統調用
  entry 2 (0xc01078a0)是sys_fork系統調用
  #gdb /boot/vmlinux-2.4.*
  (gdb) x/255 0xc0302c30
  0xc0302c30 :  0xc01261a0 0xc011e1d0 0xc01078a0 0xc013fb70
  0xc0302c40 : 0xc013fcb0 0xc013f0e0 0xc013f230 0xc011e5b0
  0xc0302c50 : 0xc013f180 0xc014cb10 0xc014c670 0xc0107940
  0xc0302c60 : 0xc013e620 0xc011f020 0xc014bcd0 0xc013e9a0
  ...
  我們也可以通過系統調用名列印出系統調用的地址:
  (gdb) x/x sys_ni_syscall
  0xc01261a0 :   0xffffdab8
  ((gdb) x/x sys_fork
  0xc01078a0 :  0x8b10ec83
  要列印出當前運行系統中的系統調用地址我們必須給gdb加兩個參數:
  a.第一個參數是內核映像文件vmliux-2.4.x
  b.第二個參數是/proc/kcore二進位文件
  #gdb /boot/vmlinux-2.4.* /proc/kcore
  (gdb) x/255x 0xc0302c30          
  0xc0302c30 :  0xc01261a0  0xc011e1d0  0xc01078a0  0xc88ab11a <<--
  0xc0302c40   0xc0302c50 : 0xc013f180  0xc014cb10  0xc014c670  0xc0107940
  0xc0302c60 : 0xc013e620  0xc011f020  0xc014bcd0  0xc013e9a0
  ...
  我們注意到第一行的0xc88ab11a這個地址明顯不正常,這是系統調用號為3的系統調用,即
  sys_read (系統調用從0開始)
  我們說它不正常的顯著標志是它的地址高於0xc8xxxxxx,Linux默認4GB線性地址,其中最高1GB
  0x00000000-0xffffffff為內核保留,當一個模塊被插入內核時,vmalloc函數為其分配一段地址空間,


  這個地址通常從0xc8800000開始...到這裡已經很明顯了吧?
  【系統調用劫持】
  劫持系統調用與上一種方法不同之處在於:它並不直接修改系統調用表中的入口地址,即指向
  每個系統調用的跳轉指針,而是在想要hook的系統調用之前加一段跳轉代碼,使執行流重定向到入
  侵者自己的內核態函數,這些被hook的系統調用前部通常有call,jmp之類的彙編指令.
  要檢測這種攻擊,同樣使用gdb加vmlinux-2.4.*及/proc/kcore兩個參數,然後反彙編系統調用:
  #gdb /boot/vmlinux-2.4.* /proc/kcore
  (gdb) disass sys_read
  Dump of assembler code for function sys_read:
  0xc013fb70 :         mov   $0xc88ab0a6,


[火星人 ] Linux下用gdb檢測內核rootkit已經有605次圍觀

http://coctec.com/docs/linux/show-post-51453.html