XTEA

XTEA加密算法

本篇文章面向有TEA基础的读者,如果你不了解TEA,也可以从我的博客中学习TEA加密算法

XTEA 与 TEA 的关系

XTEA(eXtended Tiny Encryption Algorithm)是在 TEA(Tiny Encryption Algorithm)的基础上改进得到的一种对称分组密码算法,两者具有相同的整体框架,均采用 64 位分组、128 位密钥,并使用 Feistel 网络结构,通过加法(Addition)、异或(XOR)和移位(Shift)等简单运算完成加解密。

代码实现

#include <cstdint>

void xtea_encrypt(uint32_t v[2], const uint32_t key[4])
{
    uint32_t v0 = v[0], v1 = v[1];
    uint32_t sum = 0;
    const uint32_t delta = 0x9E3779B9;

    for (int i = 0; i < 32; ++i)
    {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1)
              ^ (sum + key[sum & 3]);

        sum += delta;

        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0)
              ^ (sum + key[(sum >> 11) & 3]);
    }

    v[0] = v0;
    v[1] = v1;
}

我们直接通过阅读代码来找到在TEA上进行改动的痕迹

其中改动最明显的莫过于

(sum + key[sum & 3]);
(sum + key[(sum >> 11) & 3])

key的索引受到了sum的影响,依旧是单元运算异或

然后是sum在轮运算中的处理,先处理完一轮后再对sum进行累加运算,在这里逆向的顺序就发生了改变

可以发现整体的改动不算太大,我们直接结合题目进行逆向工程的教学

逆向工程部分

题目名称:[Harukaze]NSSCTF2025入门题目-XTea

题目来源:NSSCTF

下载题目附件,拖入IDA

image-20260804212430850

直接查看check逻辑

image-20260804212453359

看看xtea_encrypt函数

image-20260804212540855

XTEA加密,略微进行了修改

值得注意的是,这里的sum并不是真的-= 1640531527

这里利用了无符号整数的mod 2^32运算

反编译得到的是

sum -= 1640531527;

其中

1640531527 = 0x61C88647

与标志delta值的关系

0x9E3779B9 + 0x61C88647 = 0x100000000 = 2^32

因此有0x61C88647≡−0x9E3779B9(mod232)

也就是说

sum -= 0x61C88647;

在uint32_t下,等价于

sum += 0x9E3779B9;

这与uint32_t类型整数的运算息息相关

而其他的代码片段,多是确保校验位置,以及校验数据的正确性,不影响算法,我们查看密文和key后就能写出解密脚本

image-20260804213231391

以上密钥部分,记得取128位,16字节数据即可

以下密文部分,ciphertext数组,刚好是8字节的整数倍

image-20260804213307800

完整EXP

#include <iostream>
#include <cstdint>
#include <windows.h>
using namespace std;
 
void decrypt(uint32_t *v,uint32_t *key)
{
    uint32_t v0=*v;
    uint32_t v1=v[1];
    uint32_t sum=0;
    uint32_t delta=0x414554;
    for(int i=0;i<32;i++)
    {
        sum+=delta;
    };
    for(int i=0;i<32;i++)
    {
        v1-= (v0 + sum) ^ (16 * v0 + key[2]) ^ ((v0 >> 5) + key[3]);
        v0 -= (v1 + sum) ^ (16 * v1 + *key) ^ ((v1 >> 5) + key[1]);
        sum -= delta;
    }
    v[0]=v0; v[1]=v1;
}


int main()
{
     SetConsoleOutputCP(CP_UTF8); 
     SetConsoleCP(CP_UTF8);
    uint8_t enc[] =
{
  0xE4, 0x6E, 0x00, 0xF0, 0x91, 0x73, 0x9A, 0xBE, 0xCA, 0xF1, 
  0x2A, 0x60, 0x0E, 0x8F, 0x74, 0x83, 0xE0, 0x8E, 0x6C, 0x34, 
  0xD7, 0x99, 0xDE, 0x36, 0x8B, 0x86, 0xC4, 0x90, 0xC2, 0x0B, 
  0xC4, 0x59
};
   uint8_t key[] =
{
  0xEF, 0xBE, 0xAD, 0xDE, 0x0D, 0xF0, 0xAD, 0xBA, 0xDE, 0xC0, 
  0xAD, 0xDE, 0xCC, 0x10, 0xAD, 0xDE
};
    for (int i = 0; i < sizeof(enc); i+=8)
    {
        decrypt((uint32_t*)(enc + i), (uint32_t*)key);
    }
    cout<<(char*)enc;
    system("pause");
}

结果就请自己运行试试看啦,如果你觉得本篇文章对你有帮助不妨点个赞,如果觉得存在问题欢迎在评论区以及私信作者

posted @ 2026-08-04 21:44  DrD1Di  阅读(2)  评论(0)    收藏  举报