Google CTF 2019 Beginner's Quest writeup: Part 2
Part 2! Today we'll be looking at the Home Computer and Work Computer challenges.
I haven't gotten any feedback so far, although positive thinking that means I haven't gotten negative feedback yet!
[<-shameless I'll continue doing these in the same style then.
We got a
family.ntfs file, along with a note explaining we can rename it to .dmg if we're using a Mac. I'm using Linux, so we'll just proceed to
As suspected, this seems to be a NTFS partition. We can mount it just using
mount, although I'm adding the
ro flag to make sure it's read only and I'm not damaging anything.
The first place I looked was in the
Users folder, since Windows usually puts the user's home directory in
C:\Users\[username]\. We see a
You can use
find to quickly list all the files in this directory and all subdirectories, just to see what's interesting:
There's a bunch of images and movies and all that, but
credentials.txt seem really interesting. What's there?
Well, the flag isn't here, but a hint is.
Viewing extended attributes
I vaguely remember attribute stuff from watching Ippsec's videos, where he explained in one video that NTFS filesystems allow you to put multiple file streams into one file. When you open the file normally, only one of the file streams is available, and the others provide additional information. On a related note, if you download a file through a browser, Windows will mark the file as "downloaded from the internet" and ask for your permission before you run them. I suspect this is done by using the extended attributes.
Anyway, how do we actually view all the extended attributes?
The second link got me somewhere, telling me to use
Hmm! We're getting somewhere. The link also mentioned using
-n to see the attribute itself:
That looks like a PNG file, from the PNG header and the random junk that's printed out. We'll pipe it into a file and take a look:
Nice! We got the flag.
All we get is a server and a port:
readme.ctfcompetition.com 1337. Let's
nc into it and see what we get.
It looks like we get a shell! That one was easy.
Uh...? I should've know it can't be that easy. We don't have
cat on the system.
chmod doesn't work either, so getting the
ORME.flag would be tricky as well. Let's see what we do have on the system:
Exploring busybox and the limited shell
It looks like everything is done using busybox. If you aren't familiar, busybox can combine a lot of common tools like
chmod and all the essentials into one single binary. You symlink all the required binaries to
busybox, and busybox will do whatever you want based on its
argv. You can also invoke a command like
busybox cat. That means we can just
busybox cat README.flag!
Well, darn you aliens. What in Area 51 is preventing us from doing this?
Oh. It turns out that our shell is not a standard bash shell at all, it's at
/bin/shell, and is most likely a custom binary trying to thwart us busybox invoking hackers.
Let's experiment a bit and try to see if common things we expect, like output redirection, is available in this shell:
Nope. Everything is interpreted literally, which severely limits our options. Oh well, let's see what tools we do have access to by checking every binary in
Finding a way to read files
Here's where trial and error comes in. I know there are commands that won't help me at all, like
rmdir, but there are plenty of commands I haven't heard of. That said,
tar jumped out at me because it compresses files, potentially to stdout. If we can tar
README.flag to stdout, we can get the output, untar it and get the flag!
Note: I skipped like two hours of looking at other programs in
/usr/bin, like trying to persuade
unix2dos to print the file, strangling
unlzma into actually doing lzma compression stuff, and even trying to put the contents of the file into an environment variable somehow. I didn't come up with
tar magically, so don't feel bad if you didn't catch it. I nearly didn't either.
Noice! We got the flag by letting the created tar file be
-, or stdout. That said, we can't use the same trick for the
If you look at it, the file doesn't have read permission, so we can't read it. We do own the file, though, so we can change the permissions so we can read the file. That requires
chmod though, and we don't have access to that. We also can't use the
tar trick to put a
chmod binary on the system, because we can make files but they won't have the execute permissions by default. How do we deal with this catch 22?
Well, it looks like we're going back to the drawing board. I'll look in other directories and see what I can find.
Note: The following is my method of doing it, which is almost certainly not intended and made the challenge easier. I'll put the intended solution later.
The dynamic linker
/lib folder usually contains shared libraries, like
libc.so, but it also contains the dynamic linker
ld. To explain what's going on, let's write a simple hello world program on my own system:
This program uses
stdio for input and output, like 99% of all other programs. It would be pretty wasteful to store the code for
puts a million times in a million binaries, when you can have a shared library that can be stored once and used by everyone. You can see this by using the
hello program requires
libc to function, since it doesn't store any code for stuff inside
libc. When you run the program, a dynamic linker comes along and loads libc into memory so your program can use it. We can see this process by using
strace to trace the syscalls.
With all that said, have you wondered where the dynamic linker is? It's actually in /lib, and the kernel transparently invokes this dynamic linker when you call your program. When you run it, you can see this:
You can see that the linker can run executables passed as an argument! I wonder if the "no busybox allowed" restriction would still function if we're invoking
ld and asking it to run `busybox instead..
!!! We can actually invoke busybox! Looking at the commands busybox supports, we can see
cat and everything we ever needed!
We did it! However, as the flag said, there is always another way. The
ld trick seems more like an oversight than an intentional solution, and after a hint given to me on the IRC channel (sorry I forgot your name so I can't credit you!), I began looking at the
install program, which is in
man install tells me what
That means we can copy
busybox to some other place. Hopefully the restricted shell only checks for busybox in the executable's file name.
It works! Since
busybox checks for which "applet" to run from its
argv, if we rename the executable to be
chmod then busybox will happily run
chmod for you.
However, there is always another way... can we do even better? I'm sure there are plenty of other ways I'm not aware of. Just from looking at the challenge again, I see commands like
setpriv that allows running commands and could lead to running busybox. I seem to also recall someone on IRC mentioning they planted a shellscript using
tar and invoking a program (I forgot which) that runs all scripts inside a directory. If you do know alternative ways, feel free to let me know!
Exfiltrating the restricted shell
As a bonus, we can now find out what
/bin/shell does exactly, with our newfound power of invoking
We can copy over the base64, decode it and fire it up in ghidra:
init_shell just prints out some unimportant stuff:
lsh_loop finally explains why our exploits work, while just running
The program uses
strstr to check for
busybox in the first argument only. It doesn't prevent
busybox from appearing elsewhere.
I have put up the binary for download, if you are interested in digging through the restricted shell. There are lots of functions inside it to make everything work, so whether you're interested in writing the simplest shell possible or just want to understand the challenge better, go ahead!
Again, feedback is more than welcome, even a simple "I like it" or "I dislike it" helps me to make decisions. I want these writeups to feel more like a 1-on-1 explanation rather than a news article, which is why all the excessive screenshots and random relevant-but-not-that-relevant tangents. Let me know if this works!