YOU NEED PYTHON writeup

第一次独立做出来的ctf题目,记录一下。以后也会把ctf记录和总结写出来

题目地址:https://dn.jarvisoj.com/challengefiles/%E9%A2%98%E7%9B%AE%EF%BC%9Ayou_need_python.zip.74d515955b9aa607b488a48437591a14

下载附件解压缩后发现有两个文件
两个文件
先看第一个

import marshal, zlib, base64

exec(marshal.loads(zlib.decompress(base64.b64decode('eJxtVP9r21YQvyd/ieWm66Cd03QM1B8C3pggUuzYCSWstHSFQijyoJBhhGq9OXJl2ZFeqAMOK6Q/94f9Ofvn1s+d7Lgtk/3O997du/vc584a0eqpYP2GVfwDEeOrKCU6g2LRRyiK4oooFsVVUSqkqxTX6J1F+SfSNYrrdKPorC76luhbpOEGCZNFZw2KG3Rmk26QtuXi3xTb7ND6/aVu0g2RuvhEcZNut5lAGbTvAFbyH57TkYLKy8J6xpDvQxiiiaIlcdqJxVcHbXY6bXNlZgviPCrO0+StqfKd88gzNh/qRZyMdWHE29TZZvIkG7eZFRGGRcBmsXJaUoKCQ9fWKHwSqNeKFnsM5PnwJ7q2aKk4AFhcWtQCh+ChB5+Lu/RmyYUxmtOEYxas7i/2iuR7Ti14OEOSmU0RADd4+dQzbM1FJhukAUeQ+kZROuLyioagrau76kc1slY1NNaY/y3LAxDQBrAICJisV2hMdF2lxQcyFuMoqcX3+TCl6xotqzSpkqmxYVmjXVjAXiwBsEfBrd1VvTvLCj2EXRnhoryAKdpxcIgJcowUB68yAx/tlCAuPHqDuZo0CN3CUGHwkPhGMA7aXMfphjbmQLhLhJcHa0a+mpgB191c1U1lnHJQbgkHx+WGxeJbejnpkzSavo2jkxZ7i725npGAaTc8FXmUjbUETHUmkxXN5zqL5WiWxwE7Bc11yyYzNJpN02jerq+DzNNodfxOX8kE4FcmYKscDdYD1oPGGucXYNmgs1F+NTf3GOt3Mg7b+NTVruqoQyX1hOEUacKw+AGbP38ZOq9THRXaSbL5pXGQ8bho/Z/lrzQaHxdoCrlev+t6nZ7re57r+57rHXag93Deh37k+vuw9zorO/Qj/B50cAf2oyOsvut3D+ADWxdxfN/1Drqu39mHzvcRswv/Hvz7sHeg9w8Qzy99DzuFwxhPhs6zWTbOI3OZRiaZZcVj5wVwOklx7OwVxR47PR46r/SVM8ulBJic9zku/eqY/MqJxiDj+Gd55wS3f35pbLCzHoEwzKKpDkN5i+TR+1AYCWTo5IV0Z0P9H3phDDd6lMzPdS5bbo9eJGbTsW9nbDqLL1N9Iq+rRxDbll2x67a9Lf27hw5uK1s1rZr6DOPF+FI='))))

不妨先运行一下
运行结果
输入key和flag,暂且不知道key和flag的值是多少。

返回到代码:
exec()函数可用来执行执行储存在字符串或文件中的Python语句(应该可以是.pyo文件)。
marshal.loads()将二进制流反序列化为对象
zlib.decompress()对字符串进行解压缩
base64.b64decode()为base64解码

分析可知,代码中marshal.loads()处理后的字符串是pyo格式的编译程序。利用uncompyle2.uncompyle()将其反编译为py文件,得到程序的源码

import hashlib

def sha1(string):
    return hashlib.sha1(string).hexdigest()


def calc(strSHA1):
    r = 0
    for i in strSHA1:
        r += int('0x%s' % i, 16)

    return r


def encrypt(plain, key):
    keySHA1 = sha1(key)
    intSHA1 = calc(keySHA1)
    r = []
    for i in range(len(plain)):
        r.append(ord(plain[i]) + int('0x%s' % keySHA1[i % 40], 16) - intSHA1)
        intSHA1 = calc(sha1(plain[:i + 1])[:20] + sha1(str(intSHA1))[:20])

    return ''.join(map(lambda x: str(x), r))


if __name__ == '__main__':
    key = raw_input('[*] Please input key:')
    plain = raw_input('[*] Please input flag:')
    encryptText = encrypt(plain, key)
    cipherText = '-185-147-211-221-164-217-188-169-205-174-211-225-191-234-148-199-198-253-175-157-222-135-240-229-201-154-178-187-244-183-212-222-164'
    if encryptText == cipherText:
        print '[>] Congratulations! Flag is: %s' % plain
        exit()
    else:
        print '[!] Key or flag is wrong, try again:)'
        exit()

分析代码可知,程序接受两个参数key和plain,encrypt(key,plain)的返回值与代码给出的字符串相等的话则说明找到了正确的flag。

key参数可从题目给的第二个文件中找到。文件名为key_is_here_but_do_you_know_rfc4042,rfc4042中定义了utf-9编码。github上找到了utf-9的编解码库,通过解码,获取了文件中的内容

a = open('C:\\Users\\lenovo\\Desktop\\txt_a', 'r')
b = a.read()
print utf9.utf9decode(b)
输出结果为:#输出为: _____*((__//__+___+______-____%____)**((___%(___-_))+________+(___%___+_____+_______%__+______-(______//(_____%___)))))+__*(((________/__)+___%__+_______-(________//____))**(_*(_____+_____)+_______+_________%___))+________*(((_________//__+________%__)+(_______-_))**((___+_______)+_________-(______//__)))+_______*((___+_________-(______//___-_______%__%_))**(_____+_____+_____))+__*(__+_________-(___//___-_________%_____%__))**(_________-____+_______)+(___+_______)**(________%___%__+_____+______)+(_____-__)*((____//____-_____%____%_)+_________)**(_____-(_______//_______+_________%___)+______)+(_____+(_________%_______)*__+_)**_________+_______*(((_________%_______)*__+_______-(________//________))**_______)+(________/__)*(((____-_+_______)*(______+____))**___)+___*((__+_________-_)**_____)+___*(((___+_______-______/___+__-_________%_____%__)*(___-_+________/__+_________%_____))**__)+(_//_)*(((________%___%__+_____+_____)%______)+_______-_)**___+_____*((______/(_____%___))+_______)*((_________%_______)*__+_____+_)+___//___+_________+_________/___

看样子是一个很长的表达式,很轻松的想到“_”的个数表示数字,于是通过以下代码对其进行解析

a = open('C:\\Users\\lenovo\\Desktop\\txt_a', 'r')
b = a.read()
c = utf9.utf9decode(b)

num = 0
data = ''
for i in c:
    if i == '_':
        num += 1
    else:
        if num != 0:
            data += repr(num)
            num = 0
        data += i
data += repr(num)
print eval(data)
结果为5287002131074331513

第一次做的时候我直接把这个当作key进行暴力破解,发现得出的结果是一堆乱码。于是又返回这里,想到这个可能是一个字符串的ascii编码的10进制表示,尝试解码

str_data = hex(d)[2:-1]
key = ''

for i in range(len(str_data)/2):
    key += chr(eval('0x'+str_data[2*i:2*i+2]))

print key

得到key为I_4m-k3y

最后,直接利用反编译的代码,爆破出flag值

import hashlib
def sha1(string):
    return hashlib.sha1(string).hexdigest()


def calc(strSHA1):
    r = 0
    for i in strSHA1:
        r += int('0x%s' % i, 16)

    return r


def encrypt(plain, key):
    keySHA1 = sha1(key)
    intSHA1 = calc(keySHA1)
    r = []
    for i in range(len(plain)):
        r.append(ord(plain[i]) + int('0x%s' % keySHA1[i % 40], 16) - intSHA1)
        intSHA1 = calc(sha1(plain[:i + 1])[:20] + sha1(str(intSHA1))[:20])

    return ''.join(map(lambda x: str(x), r))

string = '-185-147-211-221-164-217-188-169-205-174-211-225-191-234-148-199-198-253-175-157-222-135-240-229-201-154-178-187-244-183-212-222-164'
flag = ''
flag_list = []

for i in range(len(string)/4):
    for j in range(200):
        if encrypt(flag + chr(j), 'I_4m-k3y') == string[0:4*(i+1)]:
            flag += chr(j)
            flag_list.append(j)
            break
print flag

结果为flag{Lif3_i5_5h0r7_U_n33d_Py7h0n}

你可能感兴趣的:(ctf记录)