这是第一次接触unicorn
的题目,也算是第一次用z3
来解决题目,花了好长时间去熟悉z3
和unicorn
,确实很强大
打开来有个脚本
1 | LD_PRELOAD=./un.so.1 ./babyunic func |
逐个调用,看一下babyunic
1 |
|
输入一个字符串经过处理后和已知字符串进行对比,相同则通过,接下来看看处理的方法
1 |
|
这里用到了unicorn
来模拟其它架构的处理器,查阅unicorn
引用的头文件可以得到以下信息
1 | local_20 = fopen(param_3,"rb"); |
最后这个函数的输出是param_2
也就是最终用来比较的__s1
,所以接下来需要搞清楚func
函数里进行了哪些操作
1 | void UndefinedFunction_00000000(byte *param_1,int *param_2) |
实在是太长了,就不放全了,可以看得出来param_1
是我们的输入,经过一个处理之后用一系列复杂的方程计算出了param_2
这个时候就要用z3
一把梭解决问题了
首先对最终用于比较的字符进行一些处理
1 | from z3 import * |
在babyunic
里是小端序存储,但是在unicorn
里模拟的是32位大端序,需要进行一个转换,先是转换成大端序,然后转换成c
的int32
类型
1 | c = [Int('c%d' % i) for i in range(42)] |
设定好符号,添加约束为ascii
码值,然后添加方程的约束
1 | solver.add(enc[0] == (((((((((((((((((((((((((((((((c[0] + c[1] + c[2]) - c[3]) + c[4]) - c[5]) - c[6]) - c[7]) - c[ |
这一部分可以直接用脚本来写,把所有的param_1
替换并且注意把(uint)
和*param_1
特殊处理一下就好了
然后解出为唯一解
1 | if solver.check() == sat: |
直接输出flag
1 | SUCTF{Un1c0rn_Engin3_Is_@_P0wer7ul_TO0ls!} |
unicorn
和z3
实在是太好用了,之前b01lersCTF
的第一道题我还愚蠢的手解方程,早知道z3
一把梭就完了……
Comments