天天看点

“rm -rf”之后“rm -rf”之后

“rm -rf”之后“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 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

操作如下:

“rm -rf”之后“rm -rf”之后

final.gif

原文发布时间:2014-06-16

本文来自云栖合作伙伴“linux中国”

继续阅读