一、反编译题目pyc文件
题目下载解压后是一个.pyc文件,那就去反编译看看呗,因为之前用过uncompyle6,直接去命令行执行
uncompyle6 -o ez_re.py ez_re.pyc
得到ez_re.py源码一份~
但是这里我用uncompyle6反编译的结果不知道为啥就出来很多奇怪的b,感觉不太对就又用在线网站反编译了一下,嗯,果然没有多余的b了。
用的在线工具网站是:https://tool.lu/pyc/
以下是uncompyle6反编译的结果,可以看到code变量中有好多元素前面带b:
# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.10 (v3.8.10:3d8993a744, May 3 2021, 08:55:58)
# [Clang 6.0 (clang-600.0.57)]
# Embedded file name: enpyc.py
# Compiled at: 2023-03-29 18:30:23
print 'Welcome to CTFshow Re!'
print 'your flag is here!'
flag = ''
l = len(flag)
for i in range(l):
num = ((flag[i] + i) % 114514 + 114514) % 114514
code += chr(num)
code = map(ord, code)
for i in range(l - 4 + 1):
code[i] = code[i] ^ code[(i + 1)]
print code
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', b'\xff', b'\xd0', ',', '\x03', '\x02', '\x14', '8', 'm', '\x01', 'C', 'D', b'\xbd', b'\xf7', '*', '\r', b'\xda', b'\xf9', '\x1c', '&', '5', "'", b'\xda', b'\xd4', b'\xd1', '\x0b', b'\xc7', b'\xc7', '\x1a', b'\x90', 'D', b'\xa1']
我就手动处理下code了,把多余的b去掉,可以直接复制粘贴拿去用:
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', '\xff', '\xd0', ',', '\x03', '\x02', '\x14', '8', 'm', '\x01', 'C', 'D', '\xbd', '\xf7', '*', '\r', '\xda', '\xf9', '\x1c', '&', '5', "'", '\xda', '\xd4', '\xd1', '\x0b', '\xc7', '\xc7', '\x1a', '\x90', 'D', '\xa1']
二、分析源码
可以看出是有两个操作:flag[i] + i(我感觉了一下114514在这里运算与否不影响结果)和code[i] = code[i] ^ code[(i + 1)],注意异或的操作是没有处理最后三个元素的。
那想得到flag的话,大体的思路就是先倒过来异或,再减去下标值就可以了。
因为异或的操作是没有处理最后三个元素的,即倒过来时最先计算的是「倒数第四个元素=倒数第四个元素^倒数第三个元素」,然后依次往前,倒数第五个元素=倒数第五个元素^倒数第四个元素,依此类推,最后是第一个元素=第一个元素^第二个元素。中间操作都是用ascii码进行的,这里不太容易描述的很具体(好像该说的也都说了),直接上脚本吧。
三、解题脚本
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', '\xff', '\xd0', ',', '\x03', '\x02', '\x14', '8', 'm', '\x01', 'C', 'D', '\xbd', '\xf7', '*', '\r', '\xda', '\xf9', '\x1c', '&', '5', "'", '\xda', '\xd4', '\xd1', '\x0b', '\xc7', '\xc7', '\x1a', '\x90', 'D', '\xa1']
temp=list(map(ord,code)) #将code中的字符转换成ascii码值放入temp
#temp=[22, 29, 30, 26, 24, 9, 255, 208, 44, 3, 2, 20, 56, 109, 1, 67, 68, 189, 247, 42, 13, 218, 249, 28, 38, 53, 39, 218, 212, 209, 11, 199, 199, 26, 144, 68, 161]
#从倒数第四个元素开始,从后往前做异或,依然是下标i处元素与下标i+1处元素异或
for i in range(len(temp)-3)[::-1]: #这里写成for i in range(len(temp)-4,-1,-1)也可哟
temp[i]=temp[i]^temp[i+1]
#temp=[99, 117, 104, 118, 108, 116, 125, 130, 82, 126, 125, 127, 107, 83, 62, 63, 124, 56, 133, 114, 88, 85, 143, 118, 106, 76, 121, 94, 132, 80, 129, 138, 77, 138, 144, 68, 161]
for i in range(len(temp)):
print(chr(temp[i]-i),end='') #目测这里没有小于下标i的数所以不用关心模数运算(可以这么说吗?
#ctfshow{Just_F00l's_D@y_R3_Ch3ck-in!}
更新:
看了官方wp里的脚本感觉好优雅,仔细一看原来是用的Python2啊……这样code中的元素前面有b也不影响,可以直接像题目源码中那样用map函数计算每个元素的ord值,这里前面有b能否处理应该是涉及到了Python2和Python3在编码上的不同,具体我没有去深究,因为觉得以后还是用3……但这里用2感觉就很优雅哎,所以也在这里贴上官方wp里的脚本吧,记得运行时用Python2
flag = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', b'\xff', b'\xd0', ',', '\x03',
'\x02', '\x14', '8', 'm', '\x01', 'C', 'D', b'\xbd', b'\xf7', '*', '\r',
b'\xda', b'\xf9', '\x1c', '&', '5', "'", b'\xda', b'\xd4', b'\xd1', '\x0b',
b'\xc7', b'\xc7', '\x1a', b'\x90', 'D', b'\xa1']
l = len(flag)
flag = map(ord,flag)
for i in range(l - 3 ,0,-1):
flag[i-1] = flag[i-1]^flag[i]
code = ''
for i in range(l):
num = (flag[i]-i) % 114514
code += chr(num)
print code