风好大,我好冷,考试凉凉
继续学习Tea算法。
整个程序的逻辑功能也不多解释,在上一篇已经比较完整的介绍了功能,我们直接找到输入的字符串以及encrypt
函数。
然后这里的sub_401950
也就是htoi
函数将字符串转化为数字。
在调用sub_400840
函数之前可以观察一下参数
(在调试的过程中IDA crush 了几次,所以有些截图的地址会有不同)
其中rsi
这个参数像是128位的key,同时注意下小端序,不要把自己弄糊涂了。
然后F7跟进,下断。
初始化阶段,其中有一个常量0x9e3779b9
.(一看就是Tea加密)
然后是一个0x20的循环
之后可以来到loc_4009FF
下,可以看到很多敏感的操作。
shl edi, 4
和shr edi, 5
以及一些xor
此时我们的数据在这里。
然后单步跟一遍其中发现了之前识别出来的key
以及最终的数据变化如下:
好吧,这么看根本看不出数据是经过怎样的运算,如果要逆向算法那么只能仔细的去推加密过程,不过我们只要能抽象出该加密过程的特征即可。
继续F9,在次循环,此时的数据变化如下:
此时的数据特征可以做如下总结:
有一个特征量
三个累加量
一个key
每轮运算将中间量进行运算累加到sum
继续往下,去掉断点,运行完整个循环,可以发现,函数最后将其中两个累加量赋值给了我们传入的参数。
那么至此该算法也就分析完毕了,特征如下。
<<4 , >>5 , xor
等操作其实简单点记的话就只要记住特征量,不过我的建议当然是自己去跟一遍。
Tea
系列算法后面还有xTea&xxTea
都在Tea
的基础上进行了改进,数据的特征类似,但是加入了更多的移位和异或运算。
理解思路之后就会发现其实解密很简单,不过这里仅仅是为了学习Tea算法,一般比赛见到的题目不会这么简单。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t k[4]={2,2,3,4};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
//exchange scale
uint32_t flagLong[2];
flagLong[0] = 0x67d7b805;
flagLong[1] = 0x63c174c3;
decrypt(flagLong,k);
printf("flag{%x-%x}\n",flagLong[0],flagLong[1]);
return 0;
}
至此我们又掌握了一种加密方法。开心