rm -rf 的“幸存者”
2016-05-30 10:11
288 查看
原文:http://blog.jobbole.com/70971/
以 root 用户执行 rm –rf / 命令,然后观察下哪些文件或者指令会幸存下来。结果是什么也没少!因此你必须增加 —no-preserce-root 再试一遍:
当你按下 Enter 时,一些重要的工具,比如
将会应声消失!但是你当前的 SSH 连接以及 bash 终端都还在,这表明所有 bash 相关的内建指令都没有受影响,比如 echo。
成为 Bash 达人
执行以上命令,发现已没有 ls 可用,但是 echo 和 fileglobs 还在。利用这些“幸存者”们,我们可以做点什么呢?
注意!/dev,/proc,/run,/sys还在,我们一定要保存好它们。如果有了ls指令,那么对目录下内容的读取操作将会更加简单。
许多 Reddit 用户指出,printf 仍是可用的。CAMH 说:printf 会将参数依次格式化到输出字符串中去。
既然在bash下可以定义函数,那么我们可以自建一个ls工具,虽然功能还不是很完善。
不对啊,这种操作应该完全合法才对,难道 ls 已经被映射,或者它是其他命令的别名?
原来如此,我们上面的指令被扩展成了
把函数存储到 utils.sh 文件
cat 命令怎么样实现呢?借助 read!read 是幸存者之一,使用 read 结合管道和重定向,一个基本的 cat 就基本成型了!
结合上述通过“幸存者”逐渐恢复一些指令的方法,以及 echo 可以写入任意多字节的特性,我们可以重新构建出 linux 的工具系统,并可以通过 curl 或者 wget 直接获得我们想要的二进制文件。首先,参照 echoed by others,获取 busybox。Busybox 是嵌入式 Linux 的瑞士军刀,内嵌 wget、dd、tar等许多工具。Eusebeîa 详细介绍了如何获得一个 busybox 的 escaped 版本,我在这里就不多做赘述了。
但是,还有一个问题。
即使我们 echo 了整个二进制文件需要的所有字节,这些二进制文件仍无法执行。没法启动 busybox!针对这个问题,早期的解决方法是找到一些可执行的程序,然后用 echo 覆盖它们。我们对 /usr 和 /bin 下的文件进行了诸如此类的改造,但这确实稍显复杂。
可以利用 shell 通配符和 bash 筛选出带有可执行位组的文件,记住要把目录排除在外。
找到了可执行文件!
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:/# for ii in /*/*/*; do executable $ii; done
噩耗,什么输出也没有。或许可以利用内核层面的东西,毕竟,我们可以使用Magic Sysrq组合键重启busybox。
Shell
root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq
我们现在已经骑虎难下了,周五的时候,我会继续研究下去。感谢关注,如果您发现了什么获取可执行位组的好方法,请及时知会我。
UPDATE: Reddit 用户 throw_away5046 提出了一种解决方法:a full solution to this。
获取一个可信任的、适用于本机架构的box
执行 rm –rf 之后的机器
创建一个可以改变 busybox 访问权限的对象
以内建工具的方式使能 setx,使 busybox 可执行
操作如下:
加入伯乐在线专栏作者。
以 root 用户执行 rm –rf / 命令,然后观察下哪些文件或者指令会幸存下来。结果是什么也没少!因此你必须增加 —no-preserce-root 再试一遍:
1 | # rm -rf --no-preserve-root / |
1 2 3 4 5 6 7 | /bin/ls /bin/cat /bin/chmod /usr/bin/file |
成为 Bash 达人
1 2 3 | root@rmrf:/# ls -bash: /bin/ls: No such file or directory |
1 2 3 4 5 6 7 | root@rmrf:/# echo * dev proc run sys # echo /dev/pts/* /dev/pts/0 /dev/pts/3 /dev/pts/ptmx |
1 2 3 4 5 6 7 | root@rmrf:/# for ii in /dev/pts/*; do echo $ii; done /dev/pts/0 /dev/pts/3 /dev/pts/ptmx |
1 | root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; } |
1 | root@rmrf:/# ls() { printf '%s\n' ${1:+${1%/}/}*; } |
1 | -bash: syntax error near unexpected token `(' |
1 2 3 | root@rmrf:/# type ls</code> ls is aliased to `ls --color=auto'</code> |
ls--color=auto () { printf '%s\n' ${1:+${1%/}/}*; }。那么,我们可以先使用unalias 指令,去掉 ls 与 ls—color 的关联。
1 | root@rmrf:/# ls () { for ii in $1/*; do echo $ii; done } |
1 2 3 4 5 6 7 8 9 | root@rmrf:/# ls /dev /proc /run /sys |
1 2 3 | root@rmrf:/# ls /dev /dev/pts |
1 | root@rmrf:/# echo 'ls () { for ii in $1/*; do echo $ii; done }' >> utils.sh |
1 | root@rmrf:/# source utils.sh |
1 2 3 | root@rmrf:/# (while read line; do echo "$line"; done) < utils.sh ls () { for ii in $1/*; do echo $ii; done } |
但是,还有一个问题。
即使我们 echo 了整个二进制文件需要的所有字节,这些二进制文件仍无法执行。没法启动 busybox!针对这个问题,早期的解决方法是找到一些可执行的程序,然后用 echo 覆盖它们。我们对 /usr 和 /bin 下的文件进行了诸如此类的改造,但这确实稍显复杂。
可以利用 shell 通配符和 bash 筛选出带有可执行位组的文件,记住要把目录排除在外。
1 | executable () { if [[ ( ! -d $1 ) && -x $1 ]] ; then echo "$1"; fi } |
1 | root@rmrf:/# for ii in /*; do executable $ii; done |
1 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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 |
1 | root@rmrf:/# executable () { if [[ ( ! -d $1 ) && ( ! -h $1 ) && -x $1 ]] ; then echo "$1"; fi } |
1 | root@rmrf:/# for ii in /*/*/*; do executable $ii; done |
1 | root@rmrf:/# for ii in /*/*/*/*; do executable $ii; done |
1 | root@rmrf:/# for ii in /*/*/*/*/*; do executable $ii; done |
1 | root@rmrf:/# for ii in /*/*/*/*/*/*; do executable $ii; done |
Shell
root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq
1 | root@rmrf:/# echo 1 > /proc/sys/kernel/sysrq |
1 | root@rmrf:/# echo "b" > /proc/sysrq-trigger |
UPDATE: Reddit 用户 throw_away5046 提出了一种解决方法:a full solution to this。
获取一个可信任的、适用于本机架构的box
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ 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 |
1 2 3 4 5 6 7 | # 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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | $ 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 |
1 2 3 4 5 6 7 | # ( download > setx; enable -f ./setx setx; setx; ) # /busybox mkdir .bin # /busybox --install -s .bin # PATH=/.bin |
加入伯乐在线专栏作者。
相关文章推荐
- Python3 爬虫(五) -- 单线程爬取我的CSDN全部博文
- backBarButtonItem 颜色/文字修改
- 文件File操作总结
- 分针与时针之间夹角的计算
- 关于fragement滑动切换与点击切换
- C语言getopt()函数的使用
- 那些年我们手足无措的警告
- Firefox 插件推荐 不定期记录
- 对象的串行化(Serialization)
- LoadRunner之安装、破解、汉化教程(一)
- css
- linux socket select非阻塞模式多台客户端与服务器通信
- Android禁用横竖屏切换那些事
- [C/C++]_[初级]_[Trim掉字符串的前后空格]
- mysql的update子查询写法
- Jquery 获取 iframe 父页面与子页面的元素和方法
- NSLog 不执行
- 115个Java面试题和答案
- spring boot使用redis
- [C/C++]_[初级]_[Trim掉字符串的前后空格]