Google CTF 2019 Beginner's Quest writeup: Part 2

Published on 2019-09-25 by rkevin

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.

Home Computer

Initial recon

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 file it.


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 Family user.


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 getfattr:


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.

Work computer

Initial recon

All we get is a server and a port: 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 ls, cat, 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[0]. You can also invoke a command like cat using 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 /bin.


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 ORME.flag, unfortunately.


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


Hmmmm. The /lib folder usually contains shared libraries, like, 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 printf and 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 ldd command:


Our hello program requires libc to function, since it doesn't store any code for stuff inside stdio and 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 chmod, 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 /usr/bin.

Abusing install

Checking man install tells me what install does:


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[0], 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 setsid and 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 busybox.


We can copy over the base64, decode it and fire it up in ghidra:


The init_shell just prints out some unimportant stuff:


The lsh_loop finally explains why our exploits work, while just running busybox doesn't:


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!