真正的Babyre
ida开始直接搜索字符串,找到关键函数,简单修复一下栈指针,直接F5。
开始总感觉自己看到的是假的流程,把程序翻了个遍,没发现其它的流程,但是发现了几个反调试,但是调试发现程序都没有使用。。。其中二个:
然后确定这就是一个虚拟机逆向。静态分析一下后直接让程序跑起来。
这里我做的时候和复现的时候,ida识别的竟然不一样,复现分析的更简洁。记得做的时候,每次赋值操作码与数据的时候是使用一个四字节数据来保存的,其中L0BYTE,Byte1,Byte2,HIByte都是不同的含义:
做的时候的一些笔记:
1 | //测试flag。 |
然后程序中使用了的一个反调试(时钟检测):简单patch了即可。
乍一看程序流程有点复杂,感觉输入的数据会应该下一步操作码,这个其实就是一个加密操作。
总结一下程序的加密操作(对所有字符串的加密都是这个操作):首先从操作码中取出一个数据op_data ,然后temp = input[i]^op_data,再让op_data &= input[i],input[i] = temp,一直这个循环直到op_data == 0,最后取出input[i+1]进行input[i] ^= input[i+1]。一直这样对所有的input加密2遍,就是使用op_data不同。
使用ida_python导出我们要用的op_data。
按照程序的算法,逆二次即可:第一次解密过程我进行了注释。
1 |
|
ctfvm
从题目名字可知道是虚拟机逆向。在linux中运行一下,看见字符串信息。
ida中搜索一圈并没有发现任何相关字符串,那就是程序运行时解密出相关字符串。从入口点找到main函数,可以看到464行的代码,分支极其多。。
静态分析是不可能了,直接动调。
开始慢慢的调试看哪里解密字符串的,但实在是冗长,直接在while循环下断,然后F9一直跑,直到程序等待我们输入。
随便输入后,开始慢慢跟进熟悉一些函数的功能,发现开始就是在以此取我们输入的字符存入一个大数组中
继续跟踪,分析到我们输入的字符长度要是38,虽然读取了最后的回车符,但是没有使用的。
其中程序中这个内存区域类似就是vm使用的寄存器。
接下来判断我们输入最后一位是不是 ‘}‘ 字符,再把除了flag{ }中的内容复制到与程序最后做比较的字符串的下面,
接着判断我们开始的5位是不是 flag{。
最后就是以此取出我们flag{}中每一位,(0xFB*input[i])&0xff
,然后以此与上面的比较字符串比较。解密:
1 |
|