No cON Name CTF 2014 : imMISCible 200 Write-up

Hi guys,  this writeup will be about the challenge imMISCible.

Description: No hints 😦 Just go and get the flag.

Url: https://ctf.noconname.org/chdownloads/immiscible

Points: 200

After checking the file it’s obvious that it’s a ZIP file. Once we extract it we got a file called CTF.py.

#!/usr/bin/env python
# -*- coding: rot13 -*-
vzcbeg bf
vzcbeg znefuny
vzcbeg arj

tybony synt

qrs s():
    tybony synt
    synt = "Abcr!".qrpbqr("rot13")

olgrpbqr = """
LjNNNNNNNNNNNjNNNRNNNNOmyjNNNTDNNTDONTjNNT0ONSbONNSxNNOxNtOfNtOgNjOnNjNOMDZN
MNZNMNDNtjVNMNHNnjVNpcZNMNLNLDDNqNDNMNpNA2RRNUDRNTDVNQquONO0ONOxPDN3LDDNqNDN
ntHNMNbNMNDNtjVNLDDNqNDNntLNMNfNtjRNLDDNMNjNMDRNqNDNtjRNntpNtjNNS2RRNT4NNTDA
NSZbQtNNNTa/////XNRNNNOmONNNNUAbLGRbNDNNNUZTNNNNM2I0MJ52pjfNNNOBG19QG05sGxSA
EKZNNNNNpjRNNNOMpmRNNNNtAGptAwttAwRtAmDtZwNtAwxtAmZtZwNtAmDtAwttAwHtZwNtAwRt
AwxtAmVtZzDtpmRNNNNtAmZtAmNtAwHtAwHtAwDtZwNtAmLtAwHtAzZtAzLtAwZtAwxtAmDtAmxt
ZwNtAzLtpmRNNNNtAwLtZwNtAwRtAzHtZwNtAmHtAzHtAzZtAwRtAwDtAwHtAzHtZwNtAmZtAmpt
AwRtpkNNNNNtAzZtAzZtAzLtAmptZ2LtpjRNNNNtpjZNNNObMKumNjNNNR5QGx4bPNNNNUZUNNNN
nTSmnTkcLaZRNNNNp2uuZKZPNNNNo3AmOtNNNTqyqTIhqaZRNNNNMzkuM3ZUNNNNpzIjoTSwMKZT
NNNNMTIwo2EypjxNNNObMKuxnJqyp3DbNNNNNPtNNNNNXNNNNNOmPNNNNQkmqUWcozp+pjtNNNN8
oJ9xqJkyCtVNNNOmRtNNNONORNRINtLOPtRXNDbORtRCND==
"""

vs __anzr__ != "__znva__".qrpbqr("rot13"):
    pbqrbow = znefuny.ybnqf(olgrpbqr.qrpbqr("rot13"))
    s = arj.shapgvba(pbqrbow, tybonyf(), "s".qrpbqr("rot13"), Abar, Abar)

s()

cevag synt

In order to make this code readable, we apply ROT-13 to every piece of it, we uncomment the bytecode and we get :

import os
import marshal
import new

global flag

def s():
 global flag
 flag = "Abcr!".decode("rot13")

bytecode = "LjNNNNNNNNNNNjNNNRNNNNOmyjNNNTDNNTDONTjNNT0ONSbONNSxNNOxNtOfNtOgNjOnNjNOMDZNMNZNMNDNtjVNMNHNnjVNpcZNMNLNLDDNqNDNMNpNA2RRNUDRNTDVNQquONO0ONOxPDN3LDDNqNDNntHNMNbNMNDNtjVNLDDNqNDNntLNMNfNtjRNLDDNMNjNMDRNqNDNtjRNntpNtjNNS2RRNT4NNTDANSZbQtNNNTa/////XNRNNNOmONNNNUAbLGRbNDNNNUZTNNNNM2I0MJ52pjfNNNOBG19QG05sGxSAEKZNNNNNpjRNNNOMpmRNNNNtAGptAwttAwRtAmDtZwNtAwxtAmZtZwNtAmDtAwttAwHtZwNtAwRtAwxtAmVtZzDtpmRNNNNtAmZtAmNtAwHtAwHtAwDtZwNtAmLtAwHtAzZtAzLtAwZtAwxtAmDtAmxtZwNtAzLtpmRNNNNtAwLtZwNtAwRtAzHtZwNtAmHtAzHtAzZtAwRtAwDtAwHtAzHtZwNtAmZtAmptAwRtpkNNNNNtAzZtAzZtAzLtAmptZ2LtpjRNNNNtpjZNNNObMKumNjNNNR5QGx4bPNNNNUZUNNNNnTSmnTkcLaZRNNNNp2uuZKZPNNNNo3AmOtNNNTqyqTIhqaZRNNNNMzkuM3ZUNNNNpzIjoTSwMKZTNNNNMTIwo2EypjxNNNObMKuxnJqyp3DbNNNNNPtNNNNNXNNNNNOmPNNNNQkmqUWcozp+pjtNNNN8oJ9xqJkyCtVNNNOmRtNNNONORNRINtLOPtRXNDbORtRCND=="

if __name__ != "__main__".decode("rot13"):
 codeobj = marshal.loads(bytecode.decode("rot13"))
 s = new.function(codeobj, globals().decode("rot13"), "s", None, None)

  s()

print flag

Next step is to execute the python script, but when we execute it we get :

Traceback (most recent call last):
  File "main.py", line 14, in 
    codeobj = marshal.loads(bytecode.decode("rot13"))
ValueError: bad marshal data (unknown type code)
Because we are not giving a valid bytecode to marshal.loads which is used to deserialize an encoded string from a byte array, so we should use bytecode.decode(“rot13”) then convert the Base64 we have to Hex.
Final script edited to print the bytecode:
bytecode = "\x63\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x40\x00\x00\x00\x73\x97\x00\x00\x00\x64\x00\x00\x64\x01\x00\x6c\x00\x00\x6d\x01\x00\x5a\x01\x00\x01\x64\x00\x00\x64\x02\x00\x6c\x02\x00\x6d\x03\x00\x5a\x03\x00\x01\x65\x03\x00\x64\x03\x00\x64\x04\x00\x83\x02\x00\x64\x05\x00\x6b\x02\x00\x72\x93\x00\x64\x06\x00\x61\x04\x00\x74\x04\x00\x64\x07\x00\x37\x61\x04\x00\x74\x04\x00\x64\x08\x00\x37\x61\x04\x00\x74\x04\x00\x64\x09\x00\x37\x61\x04\x00\x74\x04\x00\x6a\x05\x00\x64\x0a\x00\x64\x04\x00\x83\x02\x00\x61\x04\x00\x74\x04\x00\x6a\x06\x00\x64\x0b\x00\x83\x01\x00\x61\x04\x00\x64\x0c\x00\x65\x01\x00\x74\x04\x00\x83\x01\x00\x6a\x07\x00\x83\x00\x00\x17\x61\x04\x00\x6e\x00\x00\x64\x0d\x00\x53\x28\x0e\x00\x00\x00\x69\xff\xff\xff\xff\x28\x01\x00\x00\x00\x73\x04\x00\x00\x00\x73\x68\x61\x31\x28\x01\x00\x00\x00\x73\x06\x00\x00\x00\x67\x65\x74\x65\x6e\x76\x73\x0b\x00\x00\x00\x4e\x4f\x5f\x43\x4f\x4e\x5f\x4e\x41\x4d\x45\x73\x00\x00\x00\x00\x73\x01\x00\x00\x00\x59\x73\x31\x00\x00\x00\x20\x35\x37\x20\x36\x38\x20\x36\x31\x20\x37\x34\x20\x32\x30\x20\x36\x39\x20\x37\x33\x20\x32\x30\x20\x37\x34\x20\x36\x38\x20\x36\x35\x20\x32\x30\x20\x36\x31\x20\x36\x39\x20\x37\x32\x20\x32\x64\x20\x73\x31\x00\x00\x00\x20\x37\x33\x20\x37\x30\x20\x36\x35\x20\x36\x35\x20\x36\x34\x20\x32\x30\x20\x37\x36\x20\x36\x35\x20\x36\x63\x20\x36\x66\x20\x36\x33\x20\x36\x39\x20\x37\x34\x20\x37\x39\x20\x32\x30\x20\x36\x66\x20\x73\x31\x00\x00\x00\x20\x36\x36\x20\x32\x30\x20\x36\x31\x20\x36\x65\x20\x32\x30\x20\x37\x35\x20\x36\x65\x20\x36\x63\x20\x36\x31\x20\x36\x34\x20\x36\x35\x20\x36\x65\x20\x32\x30\x20\x37\x33\x20\x37\x37\x20\x36\x31\x20\x73\x10\x00\x00\x00\x20\x36\x63\x20\x36\x63\x20\x36\x66\x20\x37\x37\x20\x33\x66\x20\x73\x01\x00\x00\x00\x20\x73\x03\x00\x00\x00\x68\x65\x78\x73\x03\x00\x00\x00\x4e\x43\x4e\x4e\x28\x08\x00\x00\x00\x73\x07\x00\x00\x00\x68\x61\x73\x68\x6c\x69\x62\x73\x04\x00\x00\x00\x73\x68\x61\x31\x73\x02\x00\x00\x00\x6f\x73\x73\x06\x00\x00\x00\x67\x65\x74\x65\x6e\x76\x73\x04\x00\x00\x00\x66\x6c\x61\x67\x73\x07\x00\x00\x00\x72\x65\x70\x6c\x61\x63\x65\x73\x06\x00\x00\x00\x64\x65\x63\x6f\x64\x65\x73\x09\x00\x00\x00\x68\x65\x78\x64\x69\x67\x65\x73\x74\x28\x00\x00\x00\x00\x28\x00\x00\x00\x00\x28\x00\x00\x00\x00\x73\x08\x00\x00\x00\x3c\x73\x74\x72\x69\x6e\x67\x3e\x73\x08\x00\x00\x00\x3c\x6d\x6f\x64\x75\x6c\x65\x3e\x02\x00\x00\x00\x73\x12\x00\x00\x00\x10\x01\x10\x01\x15\x02\x06\x01\x0a\x01\x0a\x01\x0a\x01\x12\x01\x0f\x01"

if __name__ != "__main__":
 codeobj = marshal.loads(bytecode)
 s = new.function(codeobj, globals(), "s", None, None)

 s()

print bytecode

We got some strings here :

c@s�ddlmZddlmZedd�dkr�datd7atd7atd	7atjd
d�atjd�adet�j�and
S(i����(ssha1(sgetenvsNO_CON_NAMEssYs1 57 68 61 74 20 69 73 20 74 68 65 20 61 69 72 2d s1 73 70 65 65 64 20 76 65 6c 6f 63 69 74 79 20 6f s1 66 20 61 6e 20 75 6e 6c 61 64 65 6e 20 73 77 61 s 6c 6c 6f 77 3f s shexsNCNN(shashlibssha1sossgetenvsflagsreplacesdecodes	hexdigest(((sss
After checking deeply we found that it might be a python code used to hash with sha1 the following string :
NO_CON_NAME = Hex2ASCII(57 68 61 74 20 69 73 20 74 68 65 20 61 69 72 2d 73 70 65 65 64 20 76 65 6c 6f 63 69 74 79 20 6f 66 20 61 6e 20 75 6e 6c 61 64 65 6e 20 73 77 61 6c 6c 6f 77 3f)
NO_CON_NAME = “What is the air-speed velocity of an unladen swallow?”
Then the final string is replaced or concatenated somehow in the following way :
NCN+sha1(“What is the air-speed velocity of an unladen swallow?”)
After trying this method , I was able to validate the challenge.
 Flag : NCN6ceeeff26e72a40b71e6029a7149ad0626fcf310