得到一个.py文件,一般是没壳的,不过还是要养成习惯,查个壳:

意料之中,啥也没有,打开文件:

给了我们一个加密逻辑,然后最后一行给了一个结果:那么就是根据上述的逻辑,反解密出flag就好了
分析一下上述逻辑:
首先对list进行变化得到key的值(怎么变化不用理,因为用不到,为啥?因为是异或昂,而且list表里的数据是题目已知的并没有变化,异或的特性就是异或后再异或一次就回来了)

其次,对拿flag来对key进行异或后,转为十六进制,再转为字符串的形式后,进行切割,切割后不足位数的在前边填上0补充(.zfill()),最后赋给result
怎么理解这个切割和填充呢呢,上个图:


这样就能直观的理解怎么切割,又怎么补位的
这里再细讲一下[2:],是指从该字符串下标为 2的数据拿起,拿到最后一位,用这些数据组成一个新的字符串。而.zfill(2)是指,判断留下的字符是否有两个,如果不足两个则在前边添加0
如果:‘2’.zfill(2)则会变成 --> ‘02’;‘2’.zfill(3)则会变成 --> ‘002’
理解程序后,那么我们就可以开始逆推了,给了一个result = ‘bcfba4d0038d48bd4b00f82796d393dfec’
根据刚才的理解可以知道,这是由异或后,转为十六进制,切割补位后拿到的
也就是说,我们先要将他们分开(分为两两一组)
然后转化为十六进制
最后异或,并转化为char类型,就可以拿到答案了,脚本如下:
| flag = 'xxxxxxxxxxxxxxxxxx' |
| list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25] |
| result = 'bcfba4d0038d48bd4b00f82796d393dfec' |
| flag1 = '' |
| result1 = '' |
| for i in range(len(list)): |
| key = (list[i] >> 4) + ((list[i] & 0xf) << 4) |
| |
| flag1 += chr((int(result[2 * i: 2 * i + 2], 16) ^ key)) |
| print(flag1) |
爆破也行,这里也提供下爆破的思路吧,依旧是定向爆破就好了(结果都是一样的):
| for i in range(len(list)): |
| key = (list[i] >> 4) + ((list[i] & 0xf) << 4) |
| for a in range(32, 127): |
| if str(hex(a ^ key))[2:].zfill(2) == result[2 * i: 2 * i + 2].zfill(2): |
| flag1 += chr(a) |
| print(flag1) |
有人可能看不懂result[2 * i: 2 * i + 2]这是啥意思。这是指从字符串中拿下标为(2 * i)到下标为(2 * i + 2)- 1 的字符出来,用他们来合成一个字符串。(也就是前边说的讲目的字符串两两组合进行拆分)(.zfill(2)是啥意思就不多讲了)
拿到NSSCTF{EZEZ_RERE}(如果还有不懂的可以私信我)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?