Writeup

UIUCTF 2017 writeups

noras noras |

Tags: #CTF #Reverse engineering #Side channel attack #Steganography

From time-based side-channel, automated reverse-engineering and classic steganography… Here is a list of challenges I thought were interesting and how I solved them.

Let’s begin by summing up the mentioned problems:

scratches 400 Points – reversing

Problem description:

nc challenge.uiuc.tf 11347

every day I do
100 push ups
100 sit ups
100 squats
100 crackmes

ALL YOUR SOLUTIONS SHOULD BE ASCII

This was an interesting challenge in which I had to use both coding and basic reverse engineering skills in order to solve it. The first thing to do is to check what the socket will throw back at us.
When connected:
1- We get a huge base64 encoded string, then
2- A question “what’s the flag?”
3- Finally, the socket expects an input

$ nc challenge.uiuc.tf 11347
.... a huge base64 string ...
What's the flag?
(Waiting for input)

First, I started with decoding the base64 string by dumping it to a file and piping that to “base64 -d” command (Yeah it’s common knowledge but I’m also trying to help newbies who are entering reverse engineering world). After that I ran the file command, which revealed that its an ELF file.

$ cat data.b64 | base64 -d > raw.dump
$ file raw.dump
raw.dump: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=98136fc416b58dacc5e1855f649edd5c46f100a7, not stripped

Now it’s time for some reversing.. Analyzing the binary with IDA and looking at the assembly dump, I could see that there is a very basic string comparison going on. The compared string is statically mentioned, but divided into three parts. The first two parts are a reversed string pushed to a register and a character at the end for the third part.

Gathering these three parts and submitting the string to the already waiting socket returns Seems legit which indicates the correctness of the submission. After that we get another base64 string..

Now let’s take a second to remember the hint/description, it mentioned 100 crackmes, which probably means we have to repeat this 100 times, since it’s time consuming to run it for 100 times manually, I used objdump and greped the addresses that these strings have.

My final script was:

import socket
import base64
import os
 
sock = socket.create_connection(('challenge.uiuc.tf', 11347))
for i in range(100):
	 data=''
	 b64string=[]
	 while "What's the flag?" not in data:
		 data = sock.recv(8192)
		 b64string+=data.split('\n')
	  
	 b64s=''
	 for part in b64string:
		 if part=="What's the flag?":
			break
		 b64s+=part
	  
	 open('bin','wb').write(base64.b64decode(b64s)) 
	 print 'DONE'
	  
	 p = os.popen('objdump -M intel -d bin | grep 400664')
	 part1 = p.readline().split(',')[1].replace('\n','')[2:].decode('hex')[::-1]
	 p = os.popen('objdump -M intel -d bin | grep 400672')
	 part2 = p.readline().split(',')[1].replace('\n','')[2:].decode('hex')[::-1]
	 p = os.popen('objdump -M intel -d bin | grep 400680')
	 part3 = p.readline().split(',')[1].replace('\n','')[2:].decode('hex')
	 ans=part1+part2+part3
	 print ans
	 
	 sock.sendall(ans+'\n')
	 data = sock.recv(128)
	 print str(i)+' '+data
	 if 'Seems legit' not in data:
		break # crashed
	 if i==99:
		break
# I dont know how much data I will recive ..
print data
data = sock.recv(8192)
print data
data = sock.recv(8192)
print data
data = sock.recv(8192)
print data

The output of the script:

....
....

DONE
nhgifxjonchcfvomr
98 Seems legit

DONE
uzkkttdflrujezyuh
99 Seems legit

Seems legit

------
You got all the crackmes we have right now!
...
(A bunch of errors :P)
...
Success, flag is flag{powered_up_like_a_mophie}

Bingo, got the flag!

Taylor’s Magical Flag Oracle 150 Points – reversing

problem description:

We set up a service to check if you’ve found the correct flag for this challenge. It’d take 1.7*10^147 years to brute force, so don’t bother trying it.
Note: flag follows the “flag{” format
Update: Scores have been reset due to a bug that caused the flag to be printed without a legitimate solve. Scripts that solve the challenge in the intended way should still work.
nc challenge.uiuc.tf 11340

The challenge came with a python script that shows the code of the service:

from time import sleep
from itertools import zip_longest
from flag import flag

def compare_flag(input_flag):
    if(len(input_flag) == 0):
        return False
    for left, right in zip_longest(input_flag, flag):
        if(left != right):
            return False
        sleep(0.25) # prevent brute forcing
    return True

So lets try to analyze what’s going on here. Whenever we input a string, it will start looping through each character of this string and compare it with our flag.
In case the character is right it will delay by 250ms otherwise no delay is performed. Do if we only observe the timing between the submission and getting an answer, its enough to know if we have the right character. By doing so we will notice the time difference and chose the character that takes the longest time. An example of the output i get from my script is:

 [*] FLAG : -->; flag{
a       1.42299985886
b       1.42199993134
c       1.42200016975
d       1.42199993134
e       1.42300009727
f       1.42300009727
g       1.42699980736
h       1.42200016975
i       1.42999982834
j       1.4240000248
k       1.42300009727
l       1.42199993134
m       1.42300009727
n       1.42299985886
o       1.42600011826
p       1.42199993134
q       1.42200016975
r       1.42199993134
s       1.42499995232
t       1.67499995232  <--- NOTICE HERE
u       1.4240000248 
v       1.42299985886 
w       1.42299985886
x       1.44800019264 
y       1.42199993134
z       1.42199993134
_       1.43099999428
}       1.42599987984 
 [*] Found letter: --> t
 [*] FLAG : --> flag{t

The script I came up with:

import socket
import time  
import string

#alphabet=string.letters+string.digits+string.punctuation 	#this takes too long
alphabet=string.ascii_lowercase+'_}' # make the alphabet smaller

sock = socket.create_connection(('challenge.uiuc.tf', 11340))
data = sock.recv(5) # get the input indecator ">" sign

flag='flag{'

while '}' not in flag:
	print ' [*] FLAG : --> '+flag	
	nominated=''
	timec=0
	for c in alphabet:
		before = time.time()
		sock.sendall(flag+c+'\n')
		data = sock.recv(15)
		after = time.time()
		diff=after-before
		if diff>timec:
			timec=diff
			nominated=c
		print c+'\t'+str(diff)
	print ' [*] Found letter: --> '+nominated	
	flag+=nominated

And the final flag was flag{trchrus}

salted wounds 200 Points ● forensics

problem description:

There are some challenges I’d rather forget.
File: zmap.pdf

I did not add the pdf file since its a paper that I don’t have the rights to publish. Running the file command affirms that its a pdf file. After that I started with binwalk to extract possible contents.

$ binwalk -e zmap.pdf

As expected I got a lot of zlib compressed data, ASCII data and font files. My first though was to examine the ascii files:

$ file _zmap.pdf.extracted/* | grep ASCII
_zmap.pdf.extracted/10F72:       ASCII text, with very long lines
_zmap.pdf.extracted/14210:       ASCII text, with very long lines
_zmap.pdf.extracted/1D19D:       ASCII text, with very long lines
_zmap.pdf.extracted/1E790:       ASCII text
_zmap.pdf.extracted/21038:       ASCII text
_zmap.pdf.extracted/2114A:       ASCII text, with very long lines
_zmap.pdf.extracted/2244A:       ASCII text, with very long lines
_zmap.pdf.extracted/252CD:       ASCII text, with very long lines
_zmap.pdf.extracted/2B6F4:       ASCII text, with very long lines
_zmap.pdf.extracted/3746:        ASCII text, with very long lines
_zmap.pdf.extracted/409C8:       ASCII text, with very long lines
_zmap.pdf.extracted/42598:       ASCII text, with very long lines
_zmap.pdf.extracted/43D53:       ASCII text, with very long lines, with no line terminators
_zmap.pdf.extracted/454E5:       ASCII text, with very long lines
_zmap.pdf.extracted/46AB0:       ASCII text, with very long lines
_zmap.pdf.extracted/48227:       ASCII text, with very long lines
_zmap.pdf.extracted/5062:        ASCII text, with very long lines
_zmap.pdf.extracted/6212B:       ASCII text, with very long lines
_zmap.pdf.extracted/EC5:         ASCII text, with very long lines

Starting from the bottom of the list I found that the file 6212B had a base64 encoded string. So I tried to decoded it and then check what it reveals with the file command, and apparently it was a png image with Taylor Swift.

$ cat _zmap.pdf.extracted/6212B | base64 -d > dump
$ file dump 
dump: PNG image data, 1221 x 651, 8-bit/color RGBA, non-interlaced
$ mv dump dump.png

Running strings doesn’t reveal anything, however when trying zsteg for LSB analysis with -a option reveals the flag:

$ zsteg dump.png -a
...
...
b4,r,lsb,xy,prime   .. text: "v6UEEEDDUUUUTDUUUTTTCDDCDDC343Cy"
b5,r,msb,xy,prime   .. text: "cL(c4wD8"
b6,abgr,msb,xy,prime.. text: "?O\"?O\"?O\"?O"
b8,r,lsb,xy,prime   .. text: "\"0-2752/+"
b8,g,lsb,xy,prime   .. text: ")/7=?=8, "
b8,b,lsb,xy,prime   .. text: "*38787#"
b1,rgb,lsb,yx       .. text: "flag{say_y0ull_r3memb3r_m3}\n+o"
b1,rgba,lsb,yx      .. text: "wwwwwwwy"
b1,abgr,msb,yx      .. text: "ywwwwwww"
b2,r,msb,yx         .. text: "jU*KjUUU"
...
...

Finally

There is another reversing challenge I solved with the help and collaboration of my team mate Michael Dubell. Make sure to check the writeup on his blog — https://dubell.io/


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: #CTF #Reverse engineering #Side channel attack #Steganography




Copyright © 2020 - nindoda.com