Michael Lohr
Michi's Blog

Michi's Blog

Hacking Google CTF - Episode 2

Hacking Google CTF - Episode 2

Michael Lohr's photo
Michael Lohr
·Nov 5, 2022·

6 min read

Subscribe to my newsletter and never miss my upcoming articles

This is a write-up about how I solved the third episode of the H4CK1NG GOOGL3 security CTF. If you didn't read my post about the first episode, I highly recommend you to check it out, since it introduces the concept of a CTF.

Challenge 01: LSB stego


  • There are two similar images
  • One of the images has slightly different pixel data

The challenge consists of the following image and the following description:


This image might look familiar. But where have you seen it before?

Hint: Sometimes the answers are hidden in plain site

Indeed the image is hidden in plain site! It is the background of the hacking google webSITE: https://h4ck1ng.google/assets/website.png. When comparing both images in terms of checksum and with the help of diff tools, it becomes apparent that this is not the same image. The background image seems to contain some extra information.

Running in through the string utility (as previously used in the last episode, we get the following output:

strings website.png | head
IHDR        pHYssRGBgAMAtEXtAuthorCrash OverrideRiTXtComment
D&R found our last message
 so just using base64-encoding isn't going to be enough. Maybe hide it in an SSL certificate? Should pass DLP checks. And use LSB stego, I'm sure that'll fool them. I found an online tool that works to read it (I'll send you a link) so we can probably deprecate your custom decoding tool. Oh and remember to delete this message before you check in the changes

There are a few interesting things here: The message author references "stego", which is an abbreviation for Steganography, which describes the practice of hiding information in a different message or data (like an image). LSB stands for "least significant bit", meaning each pixel contains part of the secret message in the least significant bits of the pixel's data. Those can be extracted with tools like this: stegonline.georgeom.net/upload.

After running the original challenge image through the stego tool we get some text-based data, which looks like a certificate, which was also mentioned in the hidden message from the website.png. But apparently, they hide the information we aim to get (the flag) in the certificate somehow.

The certificate can be parsed with the openssl x509 -in cert -text command, which reveals the hidden flag in the organization name of both the issuer and subject data.

After solving the challenge, someone pointed out to me that there is a tool called "Cyber Chef" that can do all the steps to decode the data, at once. It can do even more and is quite handy for such things: gchq.github.io/CyberChef/#recipe=Extract_LS..

Challenge 02: Timesketch


  • You don't need Timesketch
  • Look for things that look like a flag

This challenge was a bit boring. They want you to analyze some server logs using Timesketch. They included instructions on how to set it up (even using Docker), but I didn't feel like it.

Since the flag has to be somewhere in the logs, I just looked for some keywords that appear in a flag. Weirdly enough searching for "h4ck1ng" etc. yielded no results. However "HTTP" did!

cat data.csv | grep http returned the URL, which was scramled like this: https://h[4]ck[1]n/g.go[og]le/s[ol]ve/....

Challenge 03: Quarantine Shell


  • Focus on the available commands
  • Maybe you can somehow overwrite existing commands

The command command: socat FILE:tty,raw,echo=0 TCP:quarantine-shell.h4ck.ctfcompetition.com:1337 is given. It connects you to a remote shell. However, this shell is quarantined, meaning you supposedly can't execute commands:

❯ socat FILE:`tty`,raw,echo=0 TCP:quarantine-shell.h4ck.ctfcompetition.com:1337
== proof-of-work: disabled ==
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell

   ___                                    _    _                ____   _            _  _
  / _ \  _   _   __ _  _ __  __ _  _ __  | |_ (_) _ __    ___  / ___| | |__    ___ | || |
 | | | || | | | / _` || `__|/ _` || `_ \ | __|| || `_ \  / _ \ \___ \ | `_ \  / _ \| || |
 | |_| || |_| || (_| || |  | (_| || | | || |_ | || | | ||  __/  ___) || | | ||  __/| || |
  \__\_\ \__,_| \__,_||_|   \__,_||_| |_| \__||_||_| |_| \___| |____/ |_| |_| \___||_||_|

The D&R team has detected some suspicious activity on your account and has quarantined you while they investigate
961 days stuck at ~
~ $ echo test
command blocked: echo test
check completions to see available commands

There are quite some interesting things there, like the == proof-of-work: disabled == output. But after some research, it turned out that this is just something from the CTF virtualization environment.

Pressing the tab key reveals the possible commands - so it seems like autocomplete still works. By typing cd / and then pressing tabs, we actually see all the files in the root file system. This reveals that there is a /flag file, which probably contains the flag URL.

By looking through the command list, I found some interesting commands that I actually was able to execute. One of the was the function command/keyword.

After some research, I found the following article: blog.dnmfarrell.com/post/bash-function-name... After playing around with redefining the default echo command, I finally got the flag by using the following commands:

function echo
command echo $(</flag);

We now have the flag, but we can now also access the shell files that implement the quarantine. After looking through the code, the relevant part seems to be this:

    function quarantine_protocol() {
        if [[ "${COMP_WORDS[0]}" == '_dnr_toolkit' ]]; 
            # Removing the trap here then setting it again in the completions has the 
            # effect of allowing all the code in the completions function to run 
            # while preventing any user commands. 
            trap - DEBUG true else echo "command blocked: ${BASH_COMMAND}" 
            echo "check completions to see available commands" false 

    function quarantine() { 
        # Remove the environment, but only env vars, not functions. 
        set -o posix unset $(set | grep '=' | grep -v '^_' | grep -v 'flag' | cut -d'=' -f1) 2>/dev/null 
        set +o posix 
        # Keep these at least, we're not THAT cruel. 
        PS1='~ $ ' 
        PS2='> ' 
        PS4='+ ' 
        # Trap every command and ignore it. 
        # Credit to https://stackoverflow.com/a/55977897 # This inadvertently has the effect of leaving them stuck at ~ and unable # to `exit` :^) 
        set -T 
        # Enable for subshells 
        shopt -s extdebug 
        # From the man pages: "If the command run by the DEBUG trap returns a non-zero value, the next command is skipped and not executed" 
        trap quarantine_protocol DEBUG 
        # Trap every single command 


Again, an interesting challenge - though I would say this was the weakest of the five episodes. You can read my write-up for the next episode over here.

Episode Overview:

Share this