Pragyan CTF 2017: New Avenger (300pts)

3 minute read

By: [noras] from ChalmersCTF

Challenge Description :
The Avengers are scouting for a new member. They have travelled all around the world, looking for suitable candidates for the new position.
Finally, they have found the perfect candidate. But, they are in a bad situation. They do not know who the guy is behind the mask.
Can you help the Avengers to uncover the identity of the person behind the mask ?

Hint! When all strings are of the same length, it starts to make sense.

Solution:

Unfortunately, I solved this challenge 10 minutes after the CTF was over. So the first step is to run binwalk or foremost. Doing that I could see that there was a zip file included.

$binwalk avengers.gif
 
DECIMAL         HEX             DESCRIPTION
-------------------------------------------------------------------------------------------------------
0               0x0             GIF image data, version 8"9a", 500 x 272
885278          0xD821E         Zip archive data, at least v2.0 to extract, compressed size: 13422, uncompressed size: 13780, name: "1_image.jpg"
898769          0xDB6D1         Zip archive data, at least v1.0 to extract, compressed size: 1796904, uncompressed size: 1796904, name: "image_2.zip"

Unzipping the file revealed an image: 1_image.jpg and another zip file: image_2.zip.

$ unzip ./avengers.gif
Archive:  avengers.gif
warning [avengers.gif]:  885278 extra bytes at beginning or within zipfile
  (attempting to process anyway)
  inflating: 1_image.jpg
 extracting: image_2.zip

I tried to unzip the new file and it was password protected. So I ran strings on the image an it revealed the password:

$ unzip ./image_2.zip
Archive:  image_2.zip
[image_2.zip] 2_image.jpg password:

$ strings 1_image.jpg | tail -1
The password for the next file is :- sgtgFhswhfrighaulmvCavmpsb

And I could unzip it, and revealed other zip file and another image with the same thing, so I wrote a script to do that automatically as following.

import os

def extractzip(password,filename):
    cmd='unzip -P '+password+' '+filename
    p = os.popen(cmd,"r")
    line = p.readline()
    if line=='':
        print ' [x] no file named '+filename
        exit(1)

def getPassword(filename):
    cmd='strings '+filename+' | tail -1'
    print ' [+] Extracting Password from '+filename
    p = os.popen(cmd,"r")
    output = p.readline()
    for passwd in output.split(' '):
        if len(passwd)>8:
            print ' [+] Password: '+passwd
            return passwd
    print ' [x] No password found for  '+filename
    exit(1)

imagecount=1
while 1:
    filename=str(imagecount)+'_image.'
    password=getPassword(filename+'jpg')
    imagecount+=1
    filename='image_'+str(imagecount)
    extractzip(password,filename+'.zip')

This resulted in 16 images with 15 passwords. Now since the organizers dropped a hint that about the strings being the same length where they referred to the passwords, I dumped the passwords in one file by modifying my previous script and dumped it in the file passwords.txt:

sgtgFhswhfrighaulmvCavmpsb
lppujmioEaynaqrctesAnztgib
lrphntGpzjhkswskepnilrwwjm
hmohAmgcomgpjjhLnqpkepuazi
qjqxzuSkiyjzazwwsqchiqvgoQ
ujinpqyghiulozjnyprZpnswnp
tsquviQwxtgpgarlxelvakaOpo
jljykvfZSycpvscqvzjwelKhok
cqjausmhroogiuabcbpRmsyzpo
qakrlxrGswfovmxhxpjzfyfrie
jyxbLszctbveelbgxtilzfbQng
heojthirkakqvvmxjgAWzuekcp
nkpbhyUmiabnymvzmcppejiisy
mIsmsmsmxpfvkolTbnkafkgvgx
tsYinxviqeykguqznjscomgqbh

So we have 16 passwords where each one is 26-character long. After spending two days on this trying to XOR and extracting capital letters. I tried to map indexes of the caps to the alphabet. This revealed a new string that was meaningless. But trying to brute force ROTing it revealed the flag at ROT 11. My final script was:

import string

f=open('passwords.txt','r')
caps=string.ascii_uppercase
flag=""

for line in f:
	for char in line:
		if char in caps:
				flag+=caps[line.index(char)]

print 'step1 = '+ flag

print '------------------'

for i in range(1,27,1):
	rot=""
	for c in flag:
		rot+=caps[(caps.index(c)+i)% 26 ]
	print 'ROT'+str(i)+"\t"+rot

output

step1 = ETITGEPGZTGXHIWTHEXSTGBPC
------------------
ROT1    FUJUHFQHAUHYIJXUIFYTUHCQD
ROT2    GVKVIGRIBVIZJKYVJGZUVIDRE
ROT3    HWLWJHSJCWJAKLZWKHAVWJESF
ROT4    IXMXKITKDXKBLMAXLIBWXKFTG
ROT5    JYNYLJULEYLCMNBYMJCXYLGUH
ROT6    KZOZMKVMFZMDNOCZNKDYZMHVI
ROT7    LAPANLWNGANEOPDAOLEZANIWJ
ROT8    MBQBOMXOHBOFPQEBPMFABOJXK
ROT9    NCRCPNYPICPGQRFCQNGBCPKYL
ROT10   ODSDQOZQJDQHRSGDROHCDQLZM
ROT11   PETERPARKERISTHESPIDERMAN
ROT12   QFUFSQBSLFSJTUIFTQJEFSNBO
ROT13   RGVGTRCTMGTKUVJGURKFGTOCP
ROT14   SHWHUSDUNHULVWKHVSLGHUPDQ
ROT15   TIXIVTEVOIVMWXLIWTMHIVQER
ROT16   UJYJWUFWPJWNXYMJXUNIJWRFS
ROT17   VKZKXVGXQKXOYZNKYVOJKXSGT
ROT18   WLALYWHYRLYPZAOLZWPKLYTHU
ROT19   XMBMZXIZSMZQABPMAXQLMZUIV
ROT20   YNCNAYJATNARBCQNBYRMNAVJW
ROT21   ZODOBZKBUOBSCDROCZSNOBWKX
ROT22   APEPCALCVPCTDESPDATOPCXLY
ROT23   BQFQDBMDWQDUEFTQEBUPQDYMZ
ROT24   CRGRECNEXREVFGURFCVQREZNA
ROT25   DSHSFDOFYSFWGHVSGDWRSFAOB
ROT26   ETITGEPGZTGXHIWTHEXSTGBPC