Skip to content

Instantly share code, notes, and snippets.



Last active Oct 20, 2015
What would you like to do?
HITCON CTF 2015 Quals Simple
import urllib
import urllib2
import cookielib
url = ""
params = {"username" : "A"*19 + '!,!admin!:true,!' + "A"*13, "password" : "a"}
print urllib.urlencode(params)
# 1234567890123456
# {"username":"AAA
# !,!admin!:true,!
# password":"a","d
# b":"hitcon-ctf"}
class MyHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
def http_error_302(self, req, fp, code, msg, headers):
# Cookie Manip Right Here
return urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
http_error_301 = http_error_303 = http_error_307 = http_error_302
while True:
cookieprocessor = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(MyHTTPRedirectHandler, cookieprocessor)
response = urllib2.urlopen(url,urllib.urlencode(params))
r =
if "Something wrong QQ" in r:
print r
cj = cookieprocessor.cookiejar
for a in cj:
if == "auth":
auth = a.value
print auth
data = urllib.unquote_plus(auth)
print "%r" % data
print len(data)
q = '!,!admin!:true,!'
qq = '","admin":true,"'
ans = ""
for z in range(0,16):
ans = ans + chr( ord(data[z+48]) ^ ord(q[z]) ^ ord(qq[z]))
fin = data[:48] + ans + data[64:]
cookie = 'auth=' + urllib.quote_plus(fin,"")
opener = urllib2.build_opener()
opener.addheaders.append(('Cookie', cookie))
f =
q =
if "flag" in q:
print q
# You're admin! The flag is hitcon{WoW_CFB_m0dE_5o_eAsY}

We were provided a ruby source file(simple-260e49e58afc505131f19cd348b435c4.rb).

According to this file, our input(username and password) would be converted to the JSON format like this( {"username":"XXX","password":"YYY","db":"hitcon-ctf"}) and encoded by AES-128-CFB. Because this cryptosystem used CFB mode ( , we could modify one block’s plaintext by modifying next block’s ciphertext. “(ciphertext) xor (true plaintext) xor (fake plaintext)” gave us the modified next block. Ofcourse next block would be decoded messy, but once we quote the messy text by double-quote(“), it was treated as a part of JSON data and thanks to CFB mode, the block after the next block was decoded properly.

In our payload, we set username = "A"*19 + '!,!admin!:true,!' + "A"*13 and password = "a". All we need was changing (!) into (“) to get the “admin” JSON data (“admin”:true)! The problem was, due to the encoding problem, if some wrong charactor was included in ciphertext, not only our payload but sometimes genuine ciphertexts were not accepted by remote server. We needed some bruteforce to get a good IV which did not make ciphertext with wrong charactor. Once we got good IV and modified ciphertext was accepted by the remote server, the flag appeared promptly. (This problem was corrected by admins later in the competition: “auth = auth.b”)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.