本文最后更新于230 天前,其中的信息可能已经过时,如有错误可以直接在文章下留言
这一题和NewStarCTF 2023 Week2 PZthon的步骤几乎一模一样,只是pycdc反编译后的python源码不一样,这类题目的什么是.pyc文件、byte数组等知识已经在NewStarCTF 2023这题里面详细说明了,建议先看那一篇,在这篇文章就不多说了。用IDA打开压缩包给的.exe文件,Shift+F12看Strings window,一样有星期、月份还有 26 个大小写字母,如图,有python的痕迹
直接用pyinstxtractor工具解包,解包后的文件夹里有一个如图ezpyc.pyc文件,如图。
然后用pycdc和在线网站都反编译,发现pycdc会少一些代码。以下为python源码
def custom_b64encode(b):
old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
new_table = old_table[::-1]
import base64
b = base64.b64encode(b)
table = dict(zip(old_table, new_table))
b = list(b)
for i in range(len(b)):
b[i] = table[b[i]]
return bytes(b)
print('Welcome to GZHU CTF')
print('This is a ....... Program')
print('Maybe you should use PE tools to check what am I')
a = input()
flag = ''
key = 'gzhu'
encrypted = ''
for i in range(len(flag)):
encrypted += str(ord(flag[i]) ^ ord(key[i % 4]))
encrypted += ' '
encrypted = custom_b64encode(encrypted.encode())
encrypted = b'zt/Nzd/G387H383H38zfx8ffz9/Kyd/Kyt/G38zP38fL38zI383L38vL38vfxs7fysrfycffxt/IyN/I38vN383M38zK38jM38ff'
一个”空变量“flag经过种种操作便可以得到encrypted,所以我们通过已知的变量encrypted反推可以得到flag。encrypted最后一步经过自定义函数custom_b64encode得到最终的变量encrypted,所以我们首先分析这个函数。
old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
new_table = old_table[::-1]
#new_table = b'/+9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA'
b = base64.b64encode(b)
#将传入函数的参数base64加密
table = dict(zip(old_table, new_table))
#产生一个映射表,两个表中的相同位置的字符相对应
b = list(b)
#转化成列表
for i in range(len(b)):
b[i] = table[b[i]]
#这里将在参数中且在old_table中的字符全部替换为映射后的new_table中的字符
return bytes(b)
上面代码的意思比如,在b中的字符’A’,经过函数处理后变成了’/’,我们就可以写一个脚本还原一下,逻辑应该不难理解。
import base64
encrypted = b'zt/Nzd/G387H383H38zfx8ffz9/Kyd/Kyt/G38zP38fL38zI383L38vL38vfxs7fysrfycffxt/IyN/I38vN383M38zK38jM38ff'
def custom_b64encode(b):
old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
new_table = old_table[::-1]
table = dict(zip(old_table, new_table))
b = list(b)
for i in range(len(b)):
b[i] = table[b[i]]
b=bytes(b)
return base64.b64decode(b)
print(custom_b64encode(encrypted))
#输出b'1 22 9 18 28 3 88 0 56 55 9 30 84 37 24 44 4 91 55 68 9 77 7 42 23 35 73 8 '
data=custom_b64encode(encrypted)
data=data.decode()
data=data.split(' ')
key= 'gzhu'
flag=''
for i in range(len(data)-1):
flag+=chr(int(data[i])^ord(key[i%4]))
print(flag)
#输出flag{y0u_Mak3_pYc!_1n7o_pY!}
异或那里直接再异或一次就好了,数据处理的时候唯一要注意的就是字节串里面每个数字后面都是加了空格的,所flag就是flag{y0u_Mak3_pYc!_1n7o_pY!}