攻防世界—first
first
将文件导入ida,查看main函数的代码
我们直接看最后的关键字符串,发现flag就存在unk_602220数组当中,因此关键点就在于怎么得到该数组的值
往上一步步追踪,发现了一个关键的循环,该循环将原unk_602220数组中的字符与已知数组的值和v10进行了异或操作,然后将结果存入byte_60221F数组的从1索引开始的位置并以此往后,而60221F+1刚好就等于602220,因此该循环异或操作的结果就是最终的flag
我们先追踪v10,发现v10由用户的输入进行异或操作得来,因此关键是要找到正确的用户输入
继续阅读代码发现有一个创建线程的操作,总共创建了6个线程,而每个线程都执行了一个函数start_routine()而参数则是0~5
点进该函数进行分析,此时发现该函数对关键数组unk_602220进行赋值操作,因此这是一个关键函数,我们继续分析
点进sub_400E10()函数进行分析,发现这是一个MD5编码函数,将用户输入的其中四个字节进行编码,然后存入v8
然后用v8和已知的数组qword_602120的对应部分进行比较,若相同则将用户的输入中的这四个字节存入数组unk_602220当中,因此我们可以通过一个MD5在线解密网站获得用户输入的各个部分https://www.somd5.com/:
将其逐个拼接就是用户的输入,然而并不一定是最终的unk_602220数组,因为该线程函数前面有一个usleep函数,作用是挂起当前线程一段时间,然后再锁住线程对数据进行写操作,因此6个线程相互竞争,我们无法确定线程写入的顺序,也就无法确定unk_602220数组最终的取值,也就是最终的flag
因此此时的想法是将所有的这六个部分的排列组合都列举出来并执行相应的程序流程,最后再看能否得出最终的flag,
此时的整个解题脚本的流程为:
按上图MD5解密流程拼接各个解密出来的字符串即为用户的输入→将用户的输入执行第一层变换得到v10→枚举出全部的用户的该输入的六个部分的排列组合→将每一种排列组合与v10和已知数组进行异或→将不符合条件的情况去除(ASCII码大于122)→得到所有可能的flag
完整解题脚本如下:
import itertools
input1 = 'juhuhfenlapsiuerhjifdunu'
list1 = [0xFE, 0xE9, 0xF4, 0xE2, 0xF1, 0xFA, 0xF4, 0xE4, 0xF0, 0xE7,
0xE4, 0xE5, 0xE3, 0xF2, 0xF5, 0xEF, 0xE8, 0xFF, 0xF6, 0xF4,
0xFD, 0xB4, 0xA5, 0xB2]
v10 = 0
for i in range(len(input1)):
v11 = ord(input1[i])+i
v10 ^= v11
# 遍历用户输入的各部分的全部排列组合
input1_part = ['juhu', 'hfen', 'laps', 'iuer', 'hjif', 'dunu']
permutations = list(itertools.permutations(input1_part, 6))
for perm in permutations:
sample = ''.join(perm)
flag = ''
for i in range(len(sample)):
flag_temp = (v10 ^ list1[i] ^ ord(sample[i]))
if flag_temp>122:
flag = ''
break
else:
flag+=chr(flag_temp)
if i == len(sample)-1:
print(flag)
程序的输出结果为:
此时发现了一个极有可能是flag的结果:
提交后发现成功了,因此本题的flag为:
goodjobyougetthisflag233
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程