GIT – Just for fun, I decided to launch a new and run rm -rf/ as to see what remains. As I found out, rm lives in the future with idiots like me, so you have to specify --no-preserve-root to kick this exercise off.

# rm -rf --no-preserve-root /

After committing this act of tomfoolery, great utilities like

  • /bin/ls
  • /bin/cat
  • /bin/chmod
  • /usr/bin/file

will all be gone! You should still have your connection over SSH as well as your existing bash session. This means you have all the bash builtins, like echo.

Becoming Bash McGyver

[email protected]:/# ls
-bash: /bin/ls:No such file or directory

There is no ls, but echo and fileglobs are still around. What can we do with those?

[email protected]:/# echo *
dev proc run sys
# echo /dev/pts/*
/dev/pts/0 /dev/pts/3 /dev/pts/ptmx

Hey, we got to keep /dev/proc/run, and /sys. Now that we have ls, we might as well make it a little easier to read.

[email protected]:/# for file in /dev/pts/*; do echo $file; done

Several Redditors pointed out that printf is available.

[email protected]:/# ls() { printf '%s\n' ${1:+${1%/}/}*;}

printf will [apply] the format string until it runs out of args.” – camh-

Since you can define functions in bash, we can create an ls utility, albeit very limited.

[email protected]:/# ls() { printf '%s\n' ${1:+${1%/}/}*;}-bash: syntax error near unexpected token `('

What? That should be completely valid. Is ls already hashed or aliased?

[email protected]:/# type ls
ls is aliased to `ls --color=auto'

Ah, that gets expanded to ls--color=auto () { printf '%s\n'${1:+${1%/}/}*; }. Yuck. Well, we can unalias that.

[email protected]:/# unalias ls
[email protected]:/# ls() { printf '%s\n' ${1:+${1%/}/}*; }
[email protected]:/# ls
[email protected]:/# ls /dev

And save our work.

[email protected]:/# echo 'ls() { printf '%s\n' ${1:+${1%/}/}*;}' >>
[email protected]:/# source

How about cat? The read builtin comes in handy along with pipes and redirection, so we can piece together a rudimentary cat.

[email protected]:/# (while read line; do echo "$line"; done) <
ls() { printf '%s\n' ${1:+${1%/}/}*;}

With these abilities and the fact that we can write arbitrary bytes withecho, we could rebuild and then curl or wget the binaries we want directly. My first choice, echoed by others, would be to get busybox. Busybox is the Swiss Army Knife of Embedded Linux, with builtin versions of wgetddtar, and many others. Eusebeîa goes into great detail about how to get a fully escaped version of busybox on your system, so I won’t do that here.

There is a problem though.

Even if we echo all the bytes we need into creating entire binaries, those files won’t be executable. No way to start busybox. The easiest workaround for this is to find something which is executable and overwrite it with echo. We’ve nuked all of /usr and /bin at this point though, so that’s a bit tricky.

We can use shell globs and bash logic to find files with the executable bit set, making sure to ignore directories.

executable (){if[[(!-d $1 )&&-x $1 ]];then echo "$1";fi}

Find the executables!

[email protected]:/# for file in /*;do executable $file;done
[email protected]:/# for file in /*/*; do executable $file; done
[email protected]:/# for file in /*/*/*; do executable $file; done

Great! Hold on a minute though, those are all symbolic links to executables that no longer exist on disk. We’ll just updateexecutable() to ignore symbolic links.

[email protected]:/# executable () { if [[ ( ! -d $1 ) && ( ! -h $1 ) && -x $1 ]] ; then echo "$1"; fi }
[email protected]:/# for file in /*/*/*; do executable $file; done
[email protected]:/# for file in /*/*/*/*;do executable $file;done
[email protected]:/# for file in /*/*/*/*/*; do executable $file; done
[email protected]:/# for file in /*/*/*/*/*/*; do executable $file; done

Well now, that’s bad news bears. Perhaps there is something at the level we can use. After all, we can restart the box using sysrqmagic:

[email protected]:/# echo 1 > /proc/sys/kernel/sysrq
[email protected]:/# echo "b" > /proc/sysrq-trigger

From a non-hosed, same architecture box:

$ mkdir $(xxd -p -l 16/dev/urandom)
$ cd $_
$ apt-get  busybox-static
$ dpkg -x *.deb .
$ alias encode='{ tr -d \\n |  "s#\\(..\\)#\\\\x\\1#g"; echo; }'
$ alias upload='{ xxd -p | encode | nc -q0 -lp 5050; }'
$ upload < bin/busybox

Back on the rmrf’ed machine

# 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

Now to create a shared object that will change permissions on busybox

$ cat > setx.c <<EOF
externint chmod(constchar*pathname,unsignedint 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};
$ gcc -Wall-Wextra-pedantic -nostdlib -Os-fpic -shared setx.c -o setx
$ upload < setx

Time to enable setx as a built in and get busybox executable

# ( download > setx; enable -f ./setx setx; setx; )# /busybox mkdir .bin# /busybox  --install -s .bin# PATH=/.bin

In action:

Print Friendly



Bài viết liên quan