拿到的是一个 win32 控制台程序
运行一下, 输入一个字符串,返回正确或错误,没有其他
ida 打开程序看看
main 主要逻辑如下,传入一个字符串,长度为 22对传入的 字符串有一个check 函数,一个字符一个字符判断
字符check 过了之后会调用一个 main_logic_401C40 函数,这里就是主要逻辑了
main logic 函数, 将我们输入的字符串切割,然后存放到局部变量上有点乱,后面直接调试看内存可以比较快看出来
_Ref_count_obj 这个函数进行一些内存分配的操作注意 &TrieTree::`vftable' 这里,这是 c++ 对象的写法Tire Tree ?? 想起题目名字叫数据结构,是不是和这个有关?找了一下资料,Tire Tree ,字典树,大概就是数据放到树上方便检索的操作这个函数主要就是 创建一个 TireTree 对象,然后返回其指针,后续操作都在这个上面进行
再次回到 main_logic 函数 后续的内容这里在两个函数重复操作了 8 次, 后续分析之后发现这里是
如果两个树一样,后面还会有一个 check 函数, 对 字符串 子串进行一些值的判断,现在还没有用,这个可以在后面帮助反推输入的值
okay 到这里思路就很明确了,程序利用我们的输入构建了一棵字典树这棵树要和一棵预先准备好的树一样,那么我们就需要先找到这棵树ida 看一下引用找到函数 sub_40190看其调用可以知道这里程序是通过
这个函数进行了一些预处理,然后再通过它调用main 函数,去除一些初始化的操作, 预先准备好的字典树 的初始化大体是下面程序调用了 initterm 函数,这个函数的效果大致是传两个地址,这两个地址之间的值不为0的 指针都当作函数从头到尾调用一遍
somefunc 里面是下面, 前面是一些初始化 TireTree 对象的操作,主要是最后一个函数
sub_401150 函数包含了 我们用于比较的字典树的生成的操作主要逻辑如下下面的几个函数都是一样的操作,生成一个字符串然后存放到 一个地址里面比如 f_4015D0(&v12) 这个函数 生成了 'f' 然后存放到 v12 这个局部变量里面
后面执行了和之前 前面 main logic 生成字典树差不多的操作猜测这里就是在 构造字典树了
存放之后会进行一系列的操作,一开始不知道是干什么观察 copysome_403940 函数 可以猜测这里应该是在构建字典树的过程给一个节点孩子什么的比如 copysome_403940(&node_M, &node_k)操作的效果就是 node_M 是父节点, node_k 加入成为 node_M 的子节点通过下面的操作我们也可以构建出一棵树出来
字典树构建完成之后, 会给每个节点 执行 sub_403650 函数,赋一个数字值,估计就是引用计数了
很好,到了这里,自己重构一下 字典树就可以找出所有可能的字符串了mspaint 画了一棵树,勿喷
因为 M 的引用计数是两个,所以猜测需要有两个一样的串,和前面构建字典树的字符的数量也相符不过这里有些 字符串的长度是一样的,不是到哪个先哪个后,这就需要前面提到的 last_check_401B80 函数了, 将对应的字符 的byte 异或一下就可以知道哪个是哪个了
其实自己排列组合爆破一下也是可以的最后得到的flag
2018CMv4.exe: PE32 executable (console) Intel 80386, for MS Windows
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
a1 = [141,180,251,69,81,152,144,139,175,218,207,96,171,100,39,0] # a1 = [0xb4,0xFB,0x45,0x51,0x98,0x90,0x8B,0xAF,0xDA,0xCF,0x60,0xAB,0x64,0x27,0x00] for i in range(0,15): a1[i] ^= i * 34 * i + i * i * 58 * i - 78 * i - 52 result = i + 1 print(a1)