WPICTF - jocipher
14 Apr 2019
description: Decrypt PIY{zsxh-sqrvufwh-nfgl} to get the flag!
category: Crypto - 100
The code was provided as a .pyc file (available at https://ctf.wpictf.xyz/files/d9543469d876cffa70bb84667ed5d369/jocipher.pyc).
It’s a compiled python file which means we can get the code back with uncompyle
.
pacaur -S python-uncompyle6
uncompyle6 jocipher.pyc jocipher.py
And we get the following python code.
# uncompyle6 version 3.2.6
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.7.3 (default, Mar 26 2019, 21:43:19)
# [GCC 8.2.1 20181127]
# Embedded file name: ./jocipher.py
# Compiled at: 2019-03-01 18:41:21
import argparse , re
num = ''
first = ''
second = ''
third = ''
def setup ():
global first
global num
global second
global third
num += '1'
num += '2'
num += '3'
num += '4'
num += '5'
num += '6'
num += '7'
num += '8'
num += '9'
num += '0'
first += 'q'
first += 'w'
first += 'e'
first += 'r'
first += 't'
first += 'y'
first += 'u'
first += 'i'
first += 'o'
first += 'p'
second += 'a'
second += 's'
second += 'd'
second += 'f'
second += 'g'
second += 'h'
second += 'j'
second += 'k'
second += 'l'
third += 'z'
third += 'x'
third += 'c'
third += 'v'
third += 'b'
third += 'n'
third += 'm'
def encode ( string , shift ):
result = ''
for i in range ( len ( string )):
char = string . lower ()[ i ]
if char in num :
new_char = num [( num . index ( char ) + shift ) % len ( num )]
result += new_char
elif char in first :
new_char = first [( first . index ( char ) + shift ) % len ( first )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
elif char in second :
new_char = second [( second . index ( char ) + shift ) % len ( second )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
elif char in third :
new_char = third [( third . index ( char ) + shift ) % len ( third )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
else :
result += char
print result
return 0
def decode ( string , shift ):
result = ''
shift = - 1 * shift
for i in range ( len ( string )):
char = string . lower ()[ i ]
if char in num :
new_char = num [( num . index ( char ) + shift ) % len ( num )]
result += new_char
elif char in first :
new_char = first [( first . index ( char ) + shift ) % len ( first )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
elif char in second :
new_char = second [( second . index ( char ) + shift ) % len ( second )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
elif char in third :
new_char = third [( third . index ( char ) + shift ) % len ( third )]
if string [ i ] . isupper ():
result += new_char . upper ()
else :
result += new_char
else :
result += char
print result
return 0
def main ():
parser = argparse . ArgumentParser ()
parser . add_argument ( '--string' , '-s' , type = str , required = True , help = 'the string to encode or decode' )
parser . add_argument ( '--shift' , '-t' , type = int , required = True , help = 'the shift value to use' )
parser . add_argument ( '--encode' , '-e' , required = False , action = 'store_true' , help = 'encode the string' )
parser . add_argument ( '--decode' , '-d' , required = False , action = 'store_true' , help = 'decode the string' )
args = parser . parse_args ()
setup ()
p = re . compile ( '[a-zA-Z0-9 \\ -{}]' )
if p . match ( args . string ) is not None :
if args . encode :
ret = encode ( args . string , args . shift )
else :
if args . decode :
ret = decode ( args . string , args . shift )
if ret is not 0 :
print 'Sorry, this cipher only uses the [a-zA-Z0-9 \\ -{}]'
else :
print 'Sorry, this cipher only uses the [a-zA-Z0-9 \\ -{}]'
return
if __name__ == '__main__' :
main ()
# okay decompiling jocipher.pyc
The challenge’s author left a decode
function, and a command line helper.
We can use the python jocipher.py --decode STRING_TO_DECODE
and try to bruteforce the shift, unfortunately there were multiple flags starting by WPI
The flag was WPICTF{xkcd-keyboard-mash}