
自娛自樂,我決定啟動一台linux伺服器,然後以root使用者執行“rm –rf /”指令,然後觀察下哪些檔案或者指令會幸存下來。結果是什麼也沒少!是以你必須增加 —no-preserce-root 再試一遍:
# rm -rf --no-preserve-root /
當你按下“enter”時,一些重要的工具,比如
/bin/ls
/bin/cat
/bin/chmod
/usr/bin/file
将會應聲消失!但是你目前的ssh連接配接以及bash終端都還在,這表明所有bash相關的内建指令都沒有受影響,比如echo。
成為bash達人
root@rmrf:/# ls
-bash: /bin/ls: no such file or directory
執行以上指令,發現已沒有ls可用,但是echo和fileglobs還在。利用這些“幸存者”們,我們可以做點什麼呢?
root@rmrf:/# echo *
dev proc run sys
# echo /dev/pts/*
/dev/pts/0 /dev/pts/3 /dev/pts/ptmx
注意!/dev,/proc,/run,/sys還在,我們一定要儲存好它們。如果有了ls指令,那麼對目錄下内容的讀取操作将會更加簡單。
root@rmrf:/# for file in /dev/pts/*; do echo $file; done
/dev/pts/0
/dev/pts/3
/dev/pts/ptmx
許多reddit使用者指出,printf仍是可用的。camh-說:printf會将參數依次格式化到輸出字元串中去。
root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }
既然在bash下可以定義函數,那麼我們可以自建一個ls工具,雖然功能還不是很完善。
-bash: syntax error near unexpected token `('
不對啊,這種操作應該完全合法才對,難道ls已經被映射,或者它是其他指令的别名?
root@rmrf:/# type ls
ls is aliased to `ls --color=auto'
原來如此,我們上面的指令被擴充成了ls--color=auto () { printf '%s\n' ${1:+${1%/}/}*; }。那麼,我們可以先使用unalias指令,去掉ls與ls—color的關聯。
root@rmrf:/# unalias ls
/dev
/proc
/run
/sys
root@rmrf:/# ls /dev
/dev/pts
把函數存儲到utils.sh檔案
root@rmrf:/# echo 'ls() { printf '%s\n' ${1:+${1%/}/}*; }' >> utils.sh
root@rmrf:/# source utils.sh
cat指令怎麼樣實作呢?借助read!read是幸存者之一,使用read結合管道和重定向,一個基本的cat就基本成型了!
root@rmrf:/# (while read line; do echo "$line"; done) < utils.sh
ls() { printf '%s\n' ${1:+${1%/}/}*; }
但是,還有一個問題。
即使我們echo了整個二進制檔案需要的所有位元組,這些二進制檔案仍無法執行。沒法啟動busybox!針對這個問題,早期的解決方法是找到一些可執行的程式,然後用echo覆寫它們。我們對/usr和/bin下的檔案進行了諸如此類的改造,但這确實稍顯複雜。
可以利用shell通配符和bash篩選出帶有可執行位組的檔案,記住要把目錄排除在外。
executable () { if [[ ( ! -d $1 ) && -x $1 ]] ; then echo "$1"; fi }
找到了可執行檔案!
root@rmrf:/# for file in /*; do executable $file; done
root@rmrf:/# for file in /*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*; do executable $file; done
/proc/1107/exe
/proc/1136/exe
/proc/1149/exe
/proc/1179/exe
/proc/1215/exe
/proc/1217/exe
/proc/1220/exe
/proc/1221/exe
/proc/1223/exe
/proc/1248/exe
/proc/1277/exe
/proc/1468/exe
/proc/1478/exe
/proc/1625/exe
/proc/1644/exe
/proc/1/exe
/proc/374/exe
/proc/378/exe
/proc/471/exe
/proc/616/exe
/proc/657/exe
/proc/self/exe
太好了!但是别急,這些隻是軟連結到可執行檔案的連結檔案,原檔案在磁盤上已經不存在了。那麼現在我們要重新改寫executable(),排除這些軟連結。
root@rmrf:/# executable () { if [[ ( ! -d $1 ) && ( ! -h $1 ) && -x $1 ]] ; then echo "$1"; fi }
root@rmrf:/# for file in /*/*/*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*/*/*; do executable $file; done
root@rmrf:/# for file in /*/*/*/*/*/*; do executable $file; done
噩耗,什麼輸出也沒有。或許可以利用核心層面的東西,畢竟,我們可以使用magic sysrq組合鍵重新開機busybox。
root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq
root@rmrf:/# echo "b" > /proc/sysrq-trigger
擷取一個可信任的、适用于本機架構的box
$ mkdir $(xxd -p -l 16 /dev/urandom)
$ cd $_
$ apt-get download busybox-static
$ dpkg -x *.deb .
$ alias encode='{ tr -d \\n | sed "s#\\(..\\)#\\\\x\\1#g"; echo; }'
$ alias upload='{ xxd -p | encode | nc -q0 -lp 5050; }'
$ upload < bin/busybox
執行rm –rf之後的機器
# cd /
# alias decode='while read -ru9 line; do printf "$line"; done'
# alias download='( exec 9<>/dev/tcp/{ip of non hosed box}/5050; decode )'
# download > busybox
建立一個可以改變busybox通路權限的對象
$ cat > setx.c <<eof
extern int chmod(const char *pathname, unsigned int mode);
int entry(void) {
return !! chmod("busybox", 0700);
}
char *desc[] = {0};
struct quick_hack {
char *name; int (*fn)(void); int on;
char **long_doc, *short_doc, *other;
} setx_struct = { "setx", entry, 1, desc, "chmod 0700 busybox", 0 };
eof
$ gcc -wall -wextra -pedantic -nostdlib -os -fpic -shared setx.c -o setx
$ upload < setx
以内建工具的方式使能setx,使busybox可執行
# ( download > setx; enable -f ./setx setx; setx; )
# /busybox mkdir .bin
# /busybox --install -s .bin
# path=/.bin
操作如下:
final.gif
原文釋出時間:2014-06-16
本文來自雲栖合作夥伴“linux中國”