flag{Lif3_i5_5h0r7_U_n33d_Py7h0n}
描述
YOU NEED PYTHON:人生苦短我用Python。
文件下载地址:https://dn.jarvisoj.com/challengefiles/%E9%A2%98%E7%9B%AE%EF%BC%9Ayou_need_python.zip.74d515955b9aa607b488a48437591a14
#!/usr/bin/env python
#coding=utf-8
#flag.py
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='))))
分析
- 第一眼看到marshal,先把源代码拿到再说。涉及到python marshal 对象序列化和反序列化,marshal.loads()将二进制数据反序列为Python对象,由于在不同版本的Python中,marshal的实现可能不一样,我们先命令行里测试一下。3里loads失败,2可以。
>>> a=zlib.decompress(base64.b64decode(r'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='))
b'c\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00@\x00\x00\x00s\x92\x00\x00\x0
0d\x00\x00d\x01\x00l\x00\x00Z\x00\x00d\x02\x00\x84\x00\x00Z\x01\x00d\x03\x00\x84
\x00\x00Z\x02\x00d\x04\x00\x84\x00\x00Z\x03\x00e\x04\x00d\x05\x00k\x02\x00r\x8e\
x00e\x05\x00d\x06\x00\x83\x01\x00Z\x06\x00e\x05\x00d\x07\x00\x83\x01\x00Z\x07\x0
0e\x03\x00e\x07\x00e\x06\x00\x83\x02\x00Z\x08\x00d\x08\x00Z\t\x00e\x08\x00e\t\x0
0k\x02\x00r\x7f\x00d\t\x00e\x07\x00\x16GHe\n\x00\x83\x00\x00\x01q\x8e\x00d\n\x00
GHe\n\x00\x83\x00\x00\x01n\x00\x00d\x01\x00S(\x0b\x00\x00\x00i\xff\xff\xff\xffNc
\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x13\x00\x00\x00t\
x00\x00j\x01\x00|\x00\x00\x83\x01\x00j\x02\x00\x83\x00\x00S(\x01\x00\x00\x00N(\x
03\x00\x00\x00t\x07\x00\x00\x00hashlibt\x04\x00\x00\x00sha1t\t\x00\x00\x00hexdig
est(\x01\x00\x00\x00t\x06\x00\x00\x00string(\x00\x00\x00\x00(\x00\x00\x00\x00t\x
00\x00\x00\x00R\x01\x00\x00\x00\x06\x00\x00\x00s\x02\x00\x00\x00\x00\x01c\x01\x0
0\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00C\x00\x00\x00s2\x00\x00\x00d\x01\x00}\x
01\x00x%\x00|\x00\x00D]\x1d\x00}\x02\x00|\x01\x00t\x00\x00d\x02\x00|\x02\x00\x16
d\x03\x00\x83\x02\x007}\x01\x00q\r\x00W|\x01\x00S(\x04\x00\x00\x00Ni\x00\x00\x00
\x00s\x04\x00\x00\x000x%si\x10\x00\x00\x00(\x01\x00\x00\x00t\x03\x00\x00\x00int(
\x03\x00\x00\x00t\x07\x00\x00\x00strSHA1t\x01\x00\x00\x00rt\x01\x00\x00\x00i(\x0
0\x00\x00\x00(\x00\x00\x00\x00R\x04\x00\x00\x00t\x04\x00\x00\x00calc\t\x00\x00\x
00s\x08\x00\x00\x00\x00\x01\x06\x01\r\x01\x1b\x01c\x02\x00\x00\x00\x06\x00\x00\x
00\x08\x00\x00\x00C\x00\x00\x00s\xba\x00\x00\x00t\x00\x00|\x01\x00\x83\x01\x00}\
x02\x00t\x01\x00|\x02\x00\x83\x01\x00}\x03\x00g\x00\x00}\x04\x00x\x80\x00t\x02\x
00t\x03\x00|\x00\x00\x83\x01\x00\x83\x01\x00D]l\x00}\x05\x00|\x04\x00j\x04\x00t\
x05\x00|\x00\x00|\x05\x00\x19\x83\x01\x00t\x06\x00d\x01\x00|\x02\x00|\x05\x00d\x
02\x00\x16\x19\x16d\x03\x00\x83\x02\x00\x17|\x03\x00\x18\x83\x01\x00\x01t\x01\x0
0t\x00\x00|\x00\x00|\x05\x00d\x04\x00\x17 \x83\x01\x00d\x05\x00 t\x00\x00t\x07\x
00|\x03\x00\x83\x01\x00\x83\x01\x00d\x05\x00 \x17\x83\x01\x00}\x03\x00q1\x00Wd\x
06\x00j\x08\x00t\t\x00d\x07\x00\x84\x00\x00|\x04\x00\x83\x02\x00\x83\x01\x00S(\x
08\x00\x00\x00Ns\x04\x00\x00\x000x%si(\x00\x00\x00i\x10\x00\x00\x00i\x01\x00\x00
\x00i\x14\x00\x00\x00R\x04\x00\x00\x00c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\
x00\x00S\x00\x00\x00s\n\x00\x00\x00t\x00\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\
x00N(\x01\x00\x00\x00t\x03\x00\x00\x00str(\x01\x00\x00\x00t\x01\x00\x00\x00x(\x0
0\x00\x00\x00(\x00\x00\x00\x00R\x04\x00\x00\x00t\x08\x00\x00\x00<lambda>\x16\x00
\x00\x00s\x00\x00\x00\x00(\n\x00\x00\x00R\x01\x00\x00\x00R\t\x00\x00\x00t\x05\x0
0\x00\x00ranget\x03\x00\x00\x00lent\x06\x00\x00\x00appendt\x03\x00\x00\x00ordR\x
05\x00\x00\x00R\n\x00\x00\x00t\x04\x00\x00\x00joint\x03\x00\x00\x00map(\x06\x00\
x00\x00t\x05\x00\x00\x00plaint\x03\x00\x00\x00keyt\x07\x00\x00\x00keySHA1t\x07\x
00\x00\x00intSHA1R\x07\x00\x00\x00R\x08\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x0
0\x00R\x04\x00\x00\x00t\x07\x00\x00\x00encrypt\x0f\x00\x00\x00s\x0e\x00\x00\x00\
x00\x01\x0c\x01\x0c\x01\x06\x01\x19\x014\x016\x01t\x08\x00\x00\x00__main__s\x15\
x00\x00\x00[*] Please input key:s\x16\x00\x00\x00[*] Please input flag:s\x84\x00
\x00\x00-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-164s \x00\x00\x00[>] Co
ngratulations! Flag is: %ss%\x00\x00\x00[!] Key or flag is wrong, try again:)(\x
0b\x00\x00\x00R\x00\x00\x00\x00R\x01\x00\x00\x00R\t\x00\x00\x00R\x17\x00\x00\x00
t\x08\x00\x00\x00__name__t\t\x00\x00\x00raw_inputR\x14\x00\x00\x00R\x13\x00\x00\
x00t\x0b\x00\x00\x00encryptTextt\n\x00\x00\x00cipherTextt\x04\x00\x00\x00exit(\x
00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00R\x04\x00\x00\x00t\x08\x00\x00\x
00<module>\x04\x00\x00\x00s\x1a\x00\x00\x00\x0c\x02\t\x03\t\x06\t\t\x0c\x01\x0c\
x01\x0c\x01\x0f\x01\x06\x01\x0c\x01\t\x01\n\x02\x05\x01'
>>> marshal.loads(a)
<code object <module> at 000000000373A930, file "", line 4>
- 熟悉的c\x00\x00\x00……要用到熟悉的uncompile6,先来补一下pyc文件头。
import zlib, base64
f1 = open(r'C:\Users\ben\Desktop\1.pyc', 'wb')
f1.write( b'''\x03\xF3\x0D\x0A\x02\x6B\x0D\x5B''')
f1.close()
f1 = open(r'C:\Users\ben\Desktop\1.pyc', 'ab')
f1.write(zlib.decompress(base64.b64decode(r'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=')))
f1.close()
执行后反编译一下得到的pyc文件,拿到源代码。
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()
3.现在来处理下key,文件提示是key_is_here_but_do_you_know_rfc4042,开心的import utf9解决。
import utf9
f = open(r'C:\Users\ben\Desktop\key_is_here_but_do_you_know_rfc4042', 'rb').read()
key = utf9.utf9decode(f)
print key
#key=_____*((__//__+___+______-____%____)**((___%(___-_))+________+(___%___+_____+_______%__+______-(______//(_____%___)))))+__*(((________/__)+___%__+_______-(________//____))**(_*(_____+_____)+_______+_________%___))+________*(((_________//__+________%__)+(_______-_))**((___+_______)+_________-(______//__)))+_______*((___+_________-(______//___-_______%__%_))**(_____+_____+_____))+__*(__+_________-(___//___-_________%_____%__))**(_________-____+_______)+(___+_______)**(________%___%__+_____+______)+(_____-__)*((____//____-_____%____%_)+_________)**(_____-(_______//_______+_________%___)+______)+(_____+(_________%_______)*__+_)**_________+_______*(((_________%_______)*__+_______-(________//________))**_______)+(________/__)*(((____-_+_______)*(______+____))**___)+___*((__+_________-_)**_____)+___*(((___+_______-______/___+__-_________%_____%__)*(___-_+________/__+_________%_____))**__)+(_//_)*(((________%___%__+_____+_____)%______)+_______-_)**___+_____*((______/(_____%___))+_______)*((_________%_______)*__+_____+_)+___//___+_________+_________/___
此情此景看着又有点眼熟,因为之前也做过一道长长短短下划线计算式,连代码都没有改丢上来就是
_ = 1
__ = 2
___ = 3
____ = 4
_____ = 5
______ = 6
_______ = 7
________ = 8
_________ = 9
s = eval(key)
print s, hex(s), hex(s)[2:-1], hex(s)[2:-1].decode('hex')
#输出:5287002131074331513 0x495f346d2d6b3379L 495f346d2d6b3379 I_4m-k3y
此时得到key='I_4m-k3y'
- 然后密码学苦手有点烦,为找思路把
print i,ord(plain[i]) ,int('0x%s' % keySHA1[i % 40], 16) ,intSHA1
都打印出来发现第一位变成了一个一元一次方程。
ord(x)+15-302=-185,ord(x)=102,x='f'
既然这样那估计开头就是flag了……
key = 'I_4m-k3y'
plain = 'flag'
encryptText = encrypt(plain, key)
print(encryptText)
#输出:-185-147-211-221
和cipher的开头匹配,破案了。每次的a+b-c=d中,b和d是已知的,a只和plain[i]有关系,c是上一轮计算得出因此也相当于已知(仅和上上轮的c、plain[:i]有关),理顺逻辑后直接写代码顺序爆破(其实要爆破吗我觉得写个减法是不是更快一点……算了,写代码的时间也是时间())。统计cipher一共有33个‘-’,即len(plain)=33.
import hashlib,string
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) #fd7259647f1cf139d0aeaacc5c8223b79657a091
intSHA1 = calc(keySHA1) #302
r = []
for i in range(len(plain)):
#print i,ord(plain[i]) ,int('0x%s' % keySHA1[i % 40], 16) ,intSHA1
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))
def decrypt(cipher, key):
keySHA1 = sha1(key) #fd7259647f1cf139d0aeaacc5c8223b79657a091
intSHA1 = calc(keySHA1) #302
cipher = cipher.split('-')[1:]
plain = 'flag'
for i in range(33):
if i>3:
for x in string.printable:
if (ord(x) + int('0x%s' % keySHA1[i % 40], 16) - intSHA1) == -int(cipher[i]):
plain += x
intSHA1 = calc(sha1(plain[:i + 1])[:20] + sha1(str(intSHA1))[:20])
print plain
def trial():
import utf9
f = open(r'C:\Users\ben\Desktop\key_is_here_but_do_you_know_rfc4042', 'rb').read()
key = utf9.utf9decode(f)
#print key
_ = 1
__ = 2
___ = 3
____ = 4
_____ = 5
______ = 6
_______ = 7
________ = 8
_________ = 9
s = eval(key)
#print s, hex(s), hex(s)[2:-1], hex(s)[2:-1].decode('hex')
key = 'I_4m-k3y'
cipher = '-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'
decrypt(cipher, key)
trial()
总结
- 看到代码里有marshal就用uncompile6先拿到源代码
- 提示rfc4042如无意外就是UTF-9/11解码了,python3里已经装好了库。
- 下划线长度可以用来替换1~9到底是谁先想出来的。
- 密码学逆向先找起止位或者已知位突破,尤其一般来说如果出题人善良,密码都是用flag{}等这种固定格式……
好吧最后还是把减法给写了,免得老师嫌弃作业质量不佳……
def decrypt(cipher, key):
keySHA1 = sha1(key) #fd7259647f1cf139d0aeaacc5c8223b79657a091
intSHA1 = calc(keySHA1) #302
cipher = cipher.split('-')[1:]
plain = 'flag'
for i in range(33):
if i>3:
x = chr(-int(cipher[i])-int('0x%s' % keySHA1[i % 40], 16) +intSHA1)
plain += x
intSHA1 = calc(sha1(plain[:i + 1])[:20] + sha1(str(intSHA1))[:20])
print plain
网友评论