tea代码很短,经常被直接复制为源码(而不是像标准算法那样调库)。在ctf逆向中也算比较常见,复杂度适中。
例题是一道go逆向,经go parser处理后,核心代码如下图。
panic算是go的专有名词,类似异常。
panicIndex是编译过后形成的检查下标的代码,如果有数组越界就会报runtime error。因此可以忽略。
经过动态调试,发现0ff_4c6180[4][8]的作用分别是从内存取和往内存存。
tea的特征之一就是这个四移位和五移位。类似这个0x14285714的设定也很特别。其实这种32轮的算法多半是现成的。老赛棍可能会套tea的模板快速做出这题。
但如果不是标准的tea家族呢?从学习的角度出发,还是讨论一下写逆算法的一般过程。
以前我主张避免写逆算法,原因就是很容易写错,题目简单的时候(flag可分的时候)正向穷举会更快。这种逃避也导致我一直不太会写逆算法。
本题需要注意的几个地方:
- z3不提供bitvec的异或运算。类tea,或者很多其它题目,都会有异或运算。用z3写恐怕不会很快。
- 位运算的运算优先级低于加减乘除。
我觉得画出数据流图会很有帮助。即使不简化原始算法,也可以写出逆算法。以上图的题目为例:
从数据流图中可以看出逆算法应按如下顺序计算:
- 用新前4倒推v17;
- 用v17倒推v18;
- 用v18和新后4倒推v12;
- 用v12倒推后4;
- 用后4推v13;
- 用v17和v13倒推前4。
从而最终实现了“从当前轮次倒推出上一轮次”的目的。