去除平坦化
给了elf文件,一开始缺libc库,先下载下来apt-file search libc1++.so
sudo apt-get install libc1++.so
然后运行程序,输入flag然后没了
载入ida,发现主函数比较复杂,查看控制流程图(cfg)
根据流程图发现是控制流平坦化混淆技术,利用符号执行来去除平坦化:https://security.tencent.com/index.php/blog/msg/112
在ida中找到main函数地址,然后deflat.py一把梭
拿到去除平坦化后的文件,载入ida,舒服了
算法分析
发现主函数一堆分支围绕x和y来展开
x和y都是bss段上的变量,整个函数中也没有对齐赋值,所以都是没啥用的代码
真正有用的代码逻辑在后面的while循环中
这些函数我都给重新命名了,其中的一些函数很简单,另外一些函数做了混淆处理,我们进入一个比较复杂的函数来查看
很混乱,不知道是干啥的
仔细分析一下就会发现我们只关心局部变量v16的值
所以大胆推测这个函数虽然这么多代码,但是有效的代码就执行了一个逻辑,将传入的两个参数相加并返回,保险起见我们可以动态调试验证一下,下断点为0x400EBF
函数调用前:
调用后:
发现执行完这个函数后rax的值果然变为了0x38
后面几个函数大概也是这个逻辑
解密
main函数执行完这一系列函数后,和enc这个表中的字符作对比,要保证我们输入的21个字符都和表中相等,通过这一连串的处理函数,我们总结表达式如下(前面记录了两个时间差,预期肯定是让时间差是0):enc[i-1] = (0 ^ flag[i] + flag[i-1] % 7) ^ (s2 ^ 18 * 3 + 2)
注意,一开始程序给了一串md5作为flag[0],是”#”
所以这个表达式中惟一的未知量就是flag[i]
两边做变形处理,得flag[i] = ((enc[i-1] ^ ((flag[i - 1] ^ 18) * 3 + 2)) - flag[i - 1] % 7) ^ 0;
最终decode代码如下:
unsigned char enc[] =
{
0xF3, 0x2E, 0x18, 0x36, 0xE1, 0x4C, 0x22, 0xD1, 0xF9, 0x8C,
0x40, 0x76, 0xF4, 0x0E, 0x00, 0x05, 0xA3, 0x90, 0x0E, 0xA5
};
int main()
{
char flag[21] = {0x23};
for (int i = 1; i < 21; i++)
{
flag[i] = ( (enc[i-1] ^ ((flag[i - 1] ^ 18) * 3 + 2)) - flag[i - 1] % 7) ^ 0;
}
puts(flag);
return 0;
}
得到flag