歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

rm -rf 的“幸存者”

自娛自樂,我決定啟動一台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 ii in /dev/pts/*; do echo $ii; done
/dev/pts/0
/dev/pts/3
/dev/pts/ptmx

許多Reddit用戶指出,printf仍是可用的。CAMH-說:printf會將參數依次格式化到輸出字符串中去。
root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }

既然在bash下可以定義函數,那麼我們可以自建一個ls工具,雖然功能還不是很完善。
root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }
-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:/# ls () { for ii in $1/*; do echo $ii; done }
root@rmrf:/# ls
/dev
/proc
/run
/sys
root@rmrf:/# ls /dev
/dev/pts

把函數存儲到utils.sh文件
root@rmrf:/# echo 'ls () { for ii in $1/*; do echo $ii; done }' >> utils.sh
root@rmrf:/# source utils.sh

cat命令怎麼樣實現呢?借助read!read是幸存者之一,使用read結合管道和重定向,一個基本的cat就基本成型了!
root@rmrf:/# (while read line; do echo "$line"; done) < utils.sh
ls () { for ii in $1/*; do echo $ii; done }

結合上述通過“幸存者”逐漸恢復一些指令的方法,以及echo可以寫入任意多字節的特性,我們可以重新構建出linux的工具系統,並可以通過curl或者wget直接獲得我們想要的二進制文件。首先,參照echoed by others,獲取busybox。Busybox是嵌入式Linux的瑞士軍刀,內嵌wget,dd,tar等許多工具。Eusebeîa詳細介紹了如何獲得一個busybox的escaped版本,我在這裡就不多做贅述了。

但是,還有一個問題。

即使我們echo了整個二進制文件需要的所有字節,這些二進制文件仍無法執行。沒法啟動busybox!針對這個問題,早期的解決方法是找到一些可執行的程序,然後用echo覆蓋它們。我們對/usr和/bin下的文件進行了諸如此類的改造,但這確實稍顯復雜。

可以利用shell通配符和bash篩選出帶有可執行位組的文件,記住要把目錄排除在外。
executable () { if [[ ( ! -d $1 ) && -x $1 ]] ; then echo "$1"; fi }

找到了可執行文件!
root@rmrf:/# for ii in /*; do executable $ii; done
root@rmrf:/# for ii in /*/*; do executable $ii; done
root@rmrf:/# for ii in /*/*/*; do executable $ii; 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 ii in /*/*/*; do executable $ii; done
root@rmrf:/# for ii in /*/*/*/*; do executable $ii; done
root@rmrf:/# for ii in /*/*/*/*/*; do executable $ii; done
root@rmrf:/# for ii in /*/*/*/*/*/*; do executable $ii; done

噩耗,什麼輸出也沒有。或許可以利用內核層面的東西,畢竟,我們可以使用Magic Sysrq組合鍵重啟busybox。
root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq
root@rmrf:/# echo "b" > /proc/sysrq-trigger

我們現在已經騎虎難下了,周五的時候,我會繼續研究下去。感謝關注,如果您發現了什麼獲取可執行位組的好方法,請及時知會我。

UPDATE: Reddi用戶throw_away5046提出了一種解決方法:a full solution to this。

獲取一個可信任的、適用於本機架構的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 <

以內建工具的方式使能setx,使busybox可執行
# ( download > setx; enable -f ./setx setx; setx; )
# /busybox mkdir .bin
# /busybox --install -s .bin
# PATH=/.bin

rm -rf 的“幸存者”
 

 

Copyright © Linux教程網 All Rights Reserved