NewStar re drink_tea wp

无壳, 64 位

image-20241025091202853

主逻辑就是先判断是不是32位长,然后每8位送去加密,关键函数sub_140001180

最后比较是否相等,我们解密就行

sub_140001180:

image-20241025091600355

image-20241025091653776

密文:

image-20241025091741489

写解密代码,这里建议逆向题用c写,因为逆向离不开c语言,方便自己练手,而且有很多比如无符号整数什么的跟c也比较贴切,不建议python,这里保姆级代码讲解,同时复习下C语言:

参考:

drink_tea | WriteUp - NewStar CTF 2024

逆向算法之TEA算法 - Sk2rw - 博客园

tea 加密解密算法(面向ctf-reverse使用,光速学会tea逆向套路)_tea加密 ctf-CSDN博客

#include <stdio.h>
#include <stdint.h>

// unsigned char 表示数组中的每个元素都是 无符号字符,这意味着每个字符的取值范围是 0 到 255。
// 实际上,编译器会根据 "WelcomeToNewStar" 的长度自动推导出数组的大小。长度为 16,再加上终止符 '\0',因此 keys 的大小为 17。
unsigned char keys[] = "WelcomeToNewStar";

// 密文的ascii码,16进制
unsigned char cipher[] = { 0x78,0x20,0xF7,0xB3,0xC5,0x42,0xCE,0xDA,0x85,0x59,0x21,0x1A,0x26,0x56,0x5A,0x59,0x29,0x02,0x0D,0xED,0x07,0xA8,0xB9,0xEE,0x36,0x59,0x11,0x87,0xFD,0x5C,0x23,0x24 };

//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
    // v3是*a1也就是a1的前四个字节,v4是a1[1]也就是后四个字节
    uint32_t v0 = v[0], v1 = v[1];
    // 2654435769怎么来的?ida 中不是1640531527吗?这里可以仔细学学tea的原理,有一个delta,它的值是2654435769
    // 在加密过程中sum通常+=2654435769,但是我们这是-=1640531527可以看作= sum - 1640531527 = sum + (-1640531527)
    // -1640531527的补码就是2654435769了,我们常用的也是2654435769,不建议这里使用1640531527,容易搞混
    uint32_t delta = 2654435769;
    // 加密中也循环了32次
    uint32_t sum = (32) * delta;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    // 这里跟加密反着来就行
    for (uint32_t i = 0; i < 32; i++) {
        v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
        v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        sum -= delta;
    }
    v[0] = v0; v[1] = v1;
}

int main()
{
    // k 为加密解密密钥,为 4 个 32 位无符号整数,即密钥长度为 128 位
    // v3 += (a2[1] + (v4 >> 5)) ^ (v5 + v4) ^ (*a2 + 16 * v4);
    // v4 += (a2[3] + (v3 >> 5)) ^ (v5 + v3) ^ (a2[2] + 16 * v3);    uint32_t* v = (uint32_t*)cipher;
    // 这里的a2[1,2,3,0]就是key,_DWORD类型什么意思?用来表示 32 位无符号整数(即 unsigned int 或 uint32_t)
    // *a2 表示这是一个指针。具体来说,a2 是一个指向 _DWORD 类型 的指针。换句话说,a2 是一个 指向 32 位无符号整数的指针,你可以通过 *a2 来访问或操作它指向的内存位置。
    // 这里经过转化后就可以像伪代码那样去访问了,我们要传入的是指针,因为在函数中要改变其值
    uint32_t* k = (uint32_t*)keys;
    // v 为要加密的数据是 n 个 32 位无符号整数
    // a1其实就是四字节的起始指针,因为传入的是unsigned int类型,也对其进行转化,其实就是两个两个字符传入
    uint32_t* v = (uint32_t*)cipher;

    // ida的伪代码中i+=8,每次处理8个字节,我们这转化成了u类型,4字节,i+=2,循环4次就行了
    for (int i = 0; i < 8; i += 2) {
        decrypt(v + i, k);
        // printf("解密后的数据:%u %u\n", v[i], v[i+1]); //%u是无符号整数类型
    }
    for (int i = 0; i < 32; i++) printf("%c", cipher[i]);

    return 0;
}

image-20241025102522001