Nice VM,isn’t it? Beware of #43501
We were given a VM, consisting of a qemu migration image and needed to find the hidden key.
The first challenge was getting the extracted file to run, the file command identified it as a qemu migration image.
However running those turned out to be tricky:
After aligning all of this we were able to resume the image using the following command:
kvm -m 384 -incoming "exec:cat /tmp/migration" -cpu phenom,vendor=AuthenticAMD -curses
This greeted us with a login screen. In order to login we decided to modify the password hash for the root account to a known hash for the password abc.
$ grep --binary-files=text 'root:\$' migration
root:$6$LHU01Kv2$BvZXIGFfWkXHtT/JVNRlvmo9MzwyTrhOayRr3ak9Ovmh2EN8z57E2yPOvWxBW.o.XOh/Qc8F.wfGZxnwkqAAU0
$ sed -i 's!\$6\$LHU01Kv2$BvZXIGFfWkXHtT/JVNRlvmo9MzwyTrhOayRr3ak9Ovmh2EN8z57E2yPOvWxBW.o.XOh/Qc8F.wfGZxnwkqAAU0!
$6$b4lx.m0q$KIkP7fu8.jpTZy5nn6nQLlVVJ9EYLDp1e7cWDr4FTfOK85I1fIFvK2GW8SwmTUSgsghbJkXt1bb8nyEK0r0f21!' migration
Note later we found out there was an already logged in session running at console terminal 1 which can be access using alt-f1.
Once we were in, we had to find out what we were looking for. We noticed that in the home directory of root there is a directory called key, which contains a mounted tmpfs. However it seems to be empty:
root@challenging:~# ls -l /root
total 0
drwxr-xr-x 2 root root 0 Sep 8 15:27 key
root@challenging:~# ls -al /root/key
total 0
drwxr-xr-x 2 root root 0 Sep 8 15:27 .
drwx------ 3 root root 0 Sep 8 15:36 ..
root@challenging:~# mount | grep key
none on /root/key type tmpfs (rw)
The only thing that makes any sense is that the creator of the challenge was using some kind of mechanism to hide the content of the mount point from us. One trick that came to mind which could be used for this is mount namespaces, which allow a Linux system to have different mountpoints for each process. The mounts for each specific process can be observed in /proc/PID/mountinfo.
root@challenging:~# for x in /proc/*/mountinfo; do cmp $x /proc/self/mountinfo; done
/proc/857/mountinfo /proc/self/mountinfo differ: char 1, line 1
/proc/9/mountinfo /proc/self/mountinfo differ: char 1, line 1
root@challenging:~# ps auxw | egrep ' 9 |857' | grep -v grep
root 9 0.0 0.0 0 0 ? S 15:26 0:00 [kdevtmpfs]
root 857 0.0 0.2 5536 916 ? Ss 15:27 0:00 /usr/sbin/sshd
So in this case the ssh process as well as kdevtmps are running under a differnt mount namespace than the rest of the system.
Exploring /proc of the sshd process some more we found out that if you cd to /proc/857/root you actually see the filesystem from the mount namespace of 857. This was a surprise to us, we didn’t see it documented anywhere, also it seems to be a different method than what the challenge creator intended to be used, however it works!
root@challenging:~# cd /proc/857/root
root@challenging:/proc/857/root# ls
bin dev home lib mnt proc sbin srv tmp var
boot etc init media opt root selinux sys usr
root@challenging:/proc/857/root# cd root/key
root@challenging:/proc/857/root/root/key# ls | head
xaa
xab
xac
xad
xae
xaf
xag
xah
xai
xaj
Those xaa.. files you typically get when you use the split command to split a large file into smaller parts, so let’s concatenate them together.
root@challenging:/proc/857/root/root/key# cat * ljljhjhjjjjjjjjjjhjijljjjjjjjjjhjjiiikjjjjjjjjjjjjjjjjjjjjkjkjkjjiiikjjjjjjjjjjjjjjjjjjjjjjjkjkjkijjjikjjjkjiiijljjjjjjjjjjjjj(i)jjjjjjjjjkjiiijljjjj(i)jjjjjkjkjjjjjj
jljVjhiiijjijjjihjhiljlijiijiiiljmnn.jijiijiiijjjiijijijiikjkikjkiijjijiijjjiiijjijjjijjiijikjkiijkjkjiiijkjkihjhiiijjiiijjiiijiiijjjiiiiikjkihjhiiijjijijiijkjkijiiij
jjljhhjijlkjkjkjkjjijjkj'iihjijlmnn.jlj'ijmjijljhjimjkj'iikjiikjjiikkj'ijljhjijlkjkjkjkhjimjkj'ijlkjkhjijlkjjjjhhjijlhjiikhjijljljljhjhjijljjiihhjijlkjkj'ijlkjiihjiik
jjkjkj(i)jkjkikjkjkjkjkjkjkjjiihliihjhjkjkjkjkjkj(ikjkjkjjkjkikjkiiikjkjkjkj(i)jkjkikjkj(ikjkjkjkjkjkj(i)jkjkljljjiihj(iikjjiihjkljVjhjjiihjkjjkj(i)jkjkjkjkjkjkiliijl
jjlihliiihjlii,ilikjkihikjjliiiliiiihkikjkikjkiklii,ikikjjjliiliiiihkikjkikliiihjlii,iklii,jkikjkilihliiihlikjliliiikliiikliiikikjlihjliiilikjjjliiihkikikjkikliikiiih
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiihjkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkiiihjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
Lots of random looking garbage… that can’t be the key… Then we remembered a hint was shown from /etc/motd when we logged in:
root@challenging:~# cat /etc/motd
Maybe this relieves your headache: tr '\/_ |\\`-' h-z
Sounds like the text we see was produced using that tr since we only see characters in the range h-z. So we decided to translate back:
root@challenging:/proc/857/root/root/key# cat * | tr h-z '\/_ |\\`-'
\ \ / / / _ \ / ___| | | | ___| | | |_ _| | ___ \ (_) | ___ \ (_) | |
\ V /___ _ _/ /_\ \_ __ ___\ `--. _ __ ___ __ _ _ __| |_| |__ _ __ ___ _ _ __ _| |__ | | ___ | |_/ /___ ___ ___ ___ _____| |_/ /___ _ _ __ | |_ ___
\ // _ \| | | | _ | '__/ _ \`--. \ '_ ` _ \ / _` | '__| __| __|| '_ \ / _ \| | | |/ _` | '_ \| |/ _ \| // _ \/ __|/ _ \ \ \ / / _ \ __// _ \| | '_ \| __/ __|
| | (_) | |_| | | | | | | __/\__/ / | | | | | (_| | | | |_| |___| | | | (_) | |_| | (_| | | | | | (_) | |\ \ __/ (__| __/ |\ V / __/ | | (_) | | | | | |_\__ \
\_/\___/ \__,_\_| |_/_| \___\____/|_| |_| |_|\__,_|_| \__\____/|_| |_|\___/ \__,_|\__, |_| |_\_/\___/\_| \_\___|\___|\___|_| \_/ \___\_| \___/|_|_| |_|\__|___/
__/ |
|___/
Flag: YouAreSmartEnoughToReceivePoints
For the grab bag 500 challenge we used exactly the same technique as described above: change the root password hash, boot the image, find the process with different mount namespace and extracting the key via the proc filesystem. Clearly the /proc was a shortcut not intended by the creator of the challenge, but hey it got us 900 points, so we can’t complain.
Can I ask you how did you find the correct tr replacement sequence for GB500? bruteforcing (there were only few possibilities…) ? Searching in the migration stream? It was written in iptables with –comment on the other network namespace.
Really nice solution, your 900 points are well earned even if you totally bypassed the extra difficulty of the GB500 over GB400…..