Writeup

TAMUctf 2017 Writeups

noras noras |

Tags: #Cryptography #CTF #Forensics #Reverse engineering #Steganography

For the past year I’ve been competing in almost every CTF announced on CTFtime.org, with my team that we have created at our university called ChalmersCTF. For those who doesn’t know what CTF stands for I suggest reading this description.

Here are a list of challenges that I though were interesting for me that has steganography, forensics and basic reverse engineering and this is how I solved them.

Nine ball [350 points] – Forensics/Reverse

Problem description:

Be careful what you enter.
You have 18 attempts.
What you seek is at the deepest levels of this challenge.

Files: image , wav.zip.jpeg.unknown

We actually got five images, a text file and this file with several extensions. Let’s start with the text file.
The text file is named NameOfLocLatLong.txt and has the string title_of_file.exe.
We still don’t know what this means but we can leave this aside, it will make scene later.

After running strings, LSB with zsteg and binwalk I got nothing. After that tried to dig for exifdata using exiftool one of the images (The one I’ve uploaded) had GPS coordinates that leads to a point between the CIA museum and the kryptos sculpture 38.9521167,-77.14491111111111 .

Now lets look at the other file. Running the (file) command it was identified as a ZIP file but off course it was encrypted. Now it was time to connect the dots. We have GPS coordinates and the name of that place now that name of the text file (NameOfLocLatLong) was helpful because we found out that the password was CentralIntelligenceAgency3877 since the name says [NameOf][Lat][Long] in CamelCase. We were lucky and yeah forensic challenges can be weird some time.

Now we have a new file. When running the file command it was identified as data. Which means that the magic number of the file is missing. Looking at the hexdump (hexdump -C) reveals stuff like (libstdc++.so.6) which mean its an ELF executable (Remember the content of the text file?). I use hexeditor to add the magic number [\x7aELF] makes it executable. Running it doesn’t reveal anything interesting either, that means it’s time for reversing (my favorite lately).

First I check the strings and we have the following:

We try to submit, and we have a fail attempt and 17 submission left, seems like they were not kidding :P.

Another part got this:

Which also wasn’t the flag. studding the disassembly text I saw a huge chunk of data.

I extracted that and got three base64 encoded data strings. When decoding them, the first one returns JUNK and the other two returns a private key and a public key in PEM format.

dY6WBS8j3mDSLFGtIgQISyWIcezMXoXAKga7VDVDC0l+k5g3eTMsBytMExflbFkraJPIUOb4Qc2jncDDGyRihE5jq8+uVyLF27mXvW0KLSf4Z5l7kg8Sh7S+guTOn3R4wGfprCae3S6iwwS2CC+yaAtzX3MIRNCKe//1IerqKq4=

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQChxBqMIHRuCL1Jjp7BXo+gdpfnB7D0Bimt7ryjM8LMUz3BQWS1
++Ne5OtqPLeiqbuyrI/puduyq0M3l+1R49TYzjOktQr8buKpUTUNRU0laMOSevoX
6L1BDlNRto9q/DEN8KkXSG/lpHXoy4LTXr50y2F+YDkLYjJJgW5H5vUFLwIDAQAB
AoGBAIprsse7McXCJq7dok0W7FHDiSIA+9MjvuB9i98e+I48oHhQy6vJeXsG6cbD
Y+OF1/4BGThHeI4/bEoS79kF2me4Q+kx8jxrTEGfFIYscqq+8Fi+45U9LdyJ/4Ep
9S0gD37cYz9+jQ7wVngmL2s1hGhtgvQV8AsRJtDzA8WvaKqJAkEAtgtJSMFH5j8p
ylMM3yfOJKe/tVdG4kc3CLR4ET0Ucwv3V/DQ7om/6t8/XnTZGENVCt7BXdXWNHTl
G8dsqTcFqwJBAON74ptOKd1+gPx0FH1ZtaT5Bp69pPS3bei7qeTWW2x6fY0g+ll+
qVFtZGCnS6kEmn3AJNFSi6XWCJUNJBMiso0CQQCNygqhbVG4BzhgiwE6isFoEXQj
JUBjnD5EPHRMUPuthAN57mp9cLMXmBy+UFqLKF6Doe6QTK6Tmvyb/18mCWITAkEA
sIdNhWl1kX1+yOmnkNKR4/Cfk4XlQUYq02T15S/3CEpRrbf+rn5dFGRIdby9OO7q
mFUH/SwKVGmwhUIKUZMmbQJAQiBRFrgvnxhNdkapggkXTfQIKEG6WS6TVAPYmuYS
gbqdxcpBA8eDJlgv4Sy48TaXwzMygLD043HDs0TPdvTB4A==
-----END RSA PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChxBqMIHRuCL1Jjp7BXo+gdpfn
B7D0Bimt7ryjM8LMUz3BQWS1++Ne5OtqPLeiqbuyrI/puduyq0M3l+1R49TYzjOk
tQr8buKpUTUNRU0laMOSevoX6L1BDlNRto9q/DEN8KkXSG/lpHXoy4LTXr50y2F+
YDkLYjJJgW5H5vUFLwIDAQAB
-----END PUBLIC KEY-----

What I did is I tried to dump the junk I got from the decoding the first base64 string in a file and used the private key to decrypt it.

$ openssl rsautl -in junk -inkey private.pem -decrypt  -raw
Z2lnZW17ZW5nYWdlX2ZpbmFsX2RpcmVjdGl2ZV85ZDUyOWIyNjIxMjUxZTY0fQ==

It returned another base64 encoded string. Decoding that I got gigem{engage_final_directive_9d529b2621251e64} which was the flag.

Musical bits [200 points] – Steganography

A russian hacker detained by the CIA had this song in an ipod playlist. Something’s quite strange about it.

In this challenge we were given a wave file (Unfortunately i couldn’t upload it since its 120MB). This challenge was the most interesting challenge for me. As I’ve never worked with raw audio data before.

Since it’s a steganography challenge. An approach that I usually take is:

  • Check for possible embedded files using tools like (binwalk and foremost) .
  • Check for ascii pritnable strings in the file by running the (strings) command.
  • Look at hexdumps using tools and commands like (xxd  or hexdump -C).
  • Check commonly used tools like (steghide)

With that I got nothing. Now it was time for some audio specific steganography approaches, I usually use audacity and sonic-visualizer . In later stages I might use Fldigi to decode signals.

The first thing I do usually is look at the spectrogram  both linear and logarithmic. I also look at frequency analysis too. In this case I saw nothing interesting.

Looking at the wave form it self from the first moment  doesn’t reveal anything interesting. However when zooming in we could obviously see a pattern with two amplitude levels. This lead me to try giving the higher one the value of ONE and the lower one the value of ZERO which we can derive from the challenge name musicalbits.

Trying with the first few peaks I tried to covert the binary to hexadecimal value and I immediately  noticed that JPEG magic number [FF D8].

Now we should find a way to extract those bits because doing that with hand would take hours and will probably result in some errors. Off course python is my favorite language to use when doing CTFs. And after a small research online i found how to deal with the wave data.

What is left to do is to know the extract the exact amplitude levels of the peaks at my ZEROs and ONEs. Using python, I could actually plot the signal , zoom in and get those levels. Here is my script (PS: to lower the read time, just get rid of the part that writes to the standard output)

import wave,sys
import numpy as np

waveFile = wave.open('musicbits.wav', 'r')

signal = waveFile.readframes(-1)
signal=np.fromstring(signal,'Int16')
fs=waveFile.getframerate()

binarytext=''
c=0
for x in signal:
	if x==12481:
		binarytext+='1'
	if x==9914:
		binarytext+='0'
	c+=1
	sys.stdout.write(str(c) +' of '+str(len(signal))+'\r')
	sys.stdout.flush()

#incase somthin when wrong down
open('b.bintxt','w').write(binarytext)


open('musicbin.jpg','wb').write(chr(int(binarytext,2)))

Thank god I wrote the raw bits into a file because the script crashed after that points be case we got an error when trying to convert the binary string to a binary file in the last line of our script.

$ ./extract.py
Traceback (most recent call last):
  File "./extract.py", line 22, in <module>
    open('musicbin.jpg','wb').write(chr(int(binarytext,2)))
OverflowError: Python int too large to convert to C long

The solution is just to read chunks, covert them then write them to the final jpeg binary file using another python script as following .

#!/usr/bin/env python

import sys

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

print "".join([chr(int(x,2)) for x in chunks(open(sys.argv[1]).read(), 8)])

Finally we have a jpeg image that has our flag:

FLAG: gigem{sounds_good_7ce0cb725285d80f}

Rejective [175 points]

I love blending things. Dont you?

Files : rejective.bmp

This is the first time I encounter this kind of challenges. So we have a file that has a BMP file extention. Looking at the hexdump shows that nothing of the BMP header specification holds like (Magic number, Size, ..etc).

Trying XOR and other solution didn’t show any promise. However the solution appeared to be pretty simple. Since the BMP has raw data we can add a PPM header since its simple and requires only the knowledge of the image dimensions. But we have to first guess the dimensions of the image (height and width) which also can be derived from the file size with adding. Trying 1200×1200 did not work but 1600×900 did and revealed the flag. The bash command I used was:

$ (echo -e -n "P6\n1600\n900\n255\n";cat rejective.bmp)|pnmflip -tb|pnmtopng > out.png
$ display out.png


About the author

noras

"Senior Software Engineer. MSc in Computer systems and Networks with big interest in security. Loves to play with Android code and does security research for fun and profit. Speaks 4 languages and codes in much more."

Related articles

Tags: #Cryptography #CTF #Forensics #Reverse engineering #Steganography




Copyright © 2020 - nindoda.com