前言

风好大,我好冷,考试凉凉

继续学习Tea算法。

解题

整个程序的逻辑功能也不多解释,在上一篇已经比较完整的介绍了功能,我们直接找到输入的字符串以及encrypt函数。

然后这里的sub_401950也就是htoi函数将字符串转化为数字。
在调用sub_400840函数之前可以观察一下参数
(在调试的过程中IDA crush 了几次,所以有些截图的地址会有不同)

其中rsi这个参数像是128位的key,同时注意下小端序,不要把自己弄糊涂了。

然后F7跟进,下断。

初始化阶段,其中有一个常量0x9e3779b9.(一看就是Tea加密)

然后是一个0x20的循环

之后可以来到loc_4009FF下,可以看到很多敏感的操作。

shl edi, 4shr edi, 5以及一些xor

此时我们的数据在这里。

然后单步跟一遍其中发现了之前识别出来的key

以及最终的数据变化如下:

好吧,这么看根本看不出数据是经过怎样的运算,如果要逆向算法那么只能仔细的去推加密过程,不过我们只要能抽象出该加密过程的特征即可。

继续F9,在次循环,此时的数据变化如下:

此时的数据特征可以做如下总结:

有一个特征量
三个累加量
一个key
每轮运算将中间量进行运算累加到sum

继续往下,去掉断点,运行完整个循环,可以发现,函数最后将其中两个累加量赋值给了我们传入的参数。

那么至此该算法也就分析完毕了,特征如下。

  1. 特征量:0x9e3779b9
  2. key 128 bit {2,2,3,4}
  3. 传入两个32位无符号整数
  4. 三个累加量,其中最后赋值给传入的参数
  5. 存在<<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;
}

总结

至此我们又掌握了一种加密方法。开心

源链接

Hacking more

...