babybc
查看附件,发现是bc文件,经过一番搜索可知是LLVM IR。
在Ubuntu上安装LLVM,使用clang编译成ELF文件,用IDA Pro打开。
main函数:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
可知我们的输入必须是数字0~5 。
继续查看fill_number函数:
1 | __int64 __fastcall fill_number(__int64 a1) |
fill_number根据输入生成map,若map数组中的数字非零,则对应的input应该是字符’0’;否则会把input中的字符减去48,放入map中。
查看docheck函数:
1 | __int64 docheck() |
先看这一部分:
1 | // ... |
已知v29是长度为5的char数组,每次循环会先将v29置零。
v27从0循环到4,那么每次map[5 * v27]、map[5 * v27 + 1]、… 、map[5 * v27 + 4]就是获取一组五个数字,那么我们可以认为map其实是二维数组。
在这里&v29[map[i]]
就相当于(&v29 + map[i])
。每次我们会检查v29[map[i]]
是否为0,然后将v29[map[i]]
置为1 。那么if部分其实就是检测map
这一行五个数字是否各不相同。
这里其实有一种感觉:这是一个数独题。
再看这一部分:
1 | v20 = v26; |
有了上面的经验,这里就不难发现它是在检测每一列的5个数字是否各不相同。
检测完这个二维数组是否满足数独要求后,还会进一步检测:根据row、col数组提供的信息,判断某两个数是否满足指定的大小关系。
1 | v18 = row[4 * v16]; |
这里只截取部分片段,可知若row[i]
、col[i]
为1或2,则需要二维数组中某一行/某一列相邻的两个数字满足大小关系。否则返回错误。
盗一个z3:
1 | rowss = [[0x00, 0x00, 0x00, 0x01],[0x01, 0x00, 0x00, 0x00], [0x02, 0x00, 0x00, 0x01], [0x00, 0x00, 0x00, 0x00], [0x01, 0x00, 0x01, 0x00]] |