CTF-RE: TEA系列解密脚本
//
// Created by A5rZ on 2024/10/26.
//
#ifndef WORK_TEA_H
#define WORK_TEA_H
#endif //WORK_TEA_H
#include <cstdint>
#include <cstdio>
// 定义TEA加密算法的轮次,一般建议为32轮
#define TEA_ROUNDS 32
#define DELTA 0x9e3779b9
// TEA加密函数
void TEA_encrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = 0;
for (int i = 0; i < TEA_ROUNDS; i++) {
sum += DELTA;
v0 += ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
v1 += ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);
}
v[0] = v0;
v[1] = v1;
}
/*
void TEA_decrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = DELTA * TEA_ROUNDS;
for (int i = 0; i < TEA_ROUNDS; i++) {
v1 -= ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);
v0 -= ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
sum -= DELTA;
}
v[0] = v0;
v[1] = v1;
}
*/
// TEA解密函数
void TEA_decrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = DELTA * TEA_ROUNDS;
for (int i = 0; i < TEA_ROUNDS; i++) {
v1 -= ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3]);
v0 -= ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1]);
sum -= DELTA;
}
v[0] = v0;
v[1] = v1;
}
void TEA_fast_decrypt(uint32_t* data, int data_length, const uint32_t* key) {
// 假设数组长度是偶数
if (data_length % 2 != 0) {
printf("error1输入数组的长度必须是偶数。\n");
return;
}
for (int i = 0; i < data_length; i += 2) {
// 取出两个元素进行解密
uint32_t v[2] = { data[i], data[i + 1] };
// 使用XTEA解密
TEA_decrypt(v, key);
// 打印解密后的结果
printf("%08x %08x\n", v[0], v[1]);
}
}
#define XTEA_ROUNDS 64 // XTEA一般使用64轮加密
#define XTEA_DELTA 0x9E3778B9
// XTEA加密函数
void XTEA_encrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = 0;
for (int i = 0; i < XTEA_ROUNDS; i++) {
v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + key[sum & 3]);
sum += XTEA_DELTA;
v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0;
v[1] = v1;
}
/*
void XTEA_decrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = XTEA_DELTA * XTEA_ROUNDS;
for (int i = 0; i < XTEA_ROUNDS; i++) {
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= XTEA_DELTA;
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
*/
// XTEA解密函数
void XTEA_decrypt(uint32_t* v, const uint32_t* key) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = XTEA_DELTA * XTEA_ROUNDS;
for (int i = 0; i < XTEA_ROUNDS; i++) {
v1 -= (((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + key[(sum >> 11) & 3])) ^ v0;
sum -= XTEA_DELTA;
v0 -= (((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + key[sum & 3])) ^ v1;
}
v[0] = v1;
v[1] = v0;
}
void XTEA_fast_decrypt(uint32_t* data, int data_length, const uint32_t* key) {
// 假设数组长度是偶数
if (data_length % 2 != 0) {
printf("error1输入数组的长度必须是偶数。\n");
return;
}
for (int i = 0; i < data_length; i += 2) {
// 取出两个元素进行解密
uint32_t v[2] = { data[i], data[i + 1] };
// 使用XTEA解密
XTEA_decrypt(v, key);
// 打印解密后的结果
printf("%08x %08x\n", v[0], v[1]);
}
}
// 定义常量 DELTA,用于加密和解密操作中的累加器增量
#define XXTEA_DELTA 0x9E3779B9
// XXTEA 加密函数
void XXTEA_encrypt(uint32_t *v, int n, const uint32_t k[4]) {
// 如果数组大小 n 小于 2,不进行加密,直接返回
if (n < 2) return;
// 初始化 z 和 y,z 为数组最后一个元素,y 为第一个元素
uint32_t z = v[n - 1], y = v[0], sum = 0;
// 计算加密轮数,XXTEA 的轮数依赖于数据块的个数 n
uint32_t rounds = 6 + 52 / n;
// 外层循环执行轮数次
for (uint32_t i = 0; i < rounds; i++) {
// 累加器 sum 增加 DELTA,每轮都递增
sum += XXTEA_DELTA;
// 计算 e,用于密钥选择
uint32_t e = (sum >> 2) & 3;
// 内层循环处理 n-1 个数据块
for (uint32_t p = 0; p < n - 1; p++) {
y = v[p + 1]; // 下一个块的值
// 更新当前块的值,使用 z 和 y 进行加密操作,结合移位、异或和密钥
v[p] += ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z);
z = v[p]; // 更新 z 为当前块
}
// 最后一个数据块的加密操作
y = v[0]; // 第一个块的值
v[n - 1] += ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[((n - 1) & 3) ^ e] ^ z);
z = v[n - 1]; // 更新 z 为最后一个块
}
}
/*
void XXTEA_decrypt(uint32_t *v, int n, const uint32_t k[4]) {
// 如果数组大小 n 小于 2,不进行解密,直接返回
if (n < 2) return;
// 初始化 z 和 y,z 为数组最后一个元素,y 为第一个元素
uint32_t z = v[n - 1], y = v[0];
// 初始化累加器 sum,为加密的总和,解密时从最大值开始递减
uint32_t sum = XXTEA_DELTA * (6 + 52 / n);
// 外层循环执行轮数次,与加密时的轮数相同
for (uint32_t i = 0; i < 6 + 52 / n; i++) {
// 计算 e,用于密钥选择
uint32_t e = (sum >> 2) & 3;
// 内层循环处理 n-1 个数据块,从数组末尾往前遍历
for (uint32_t p = n - 1; p > 0; p--) {
z = v[p - 1]; // 前一个块的值
// 更新当前块的值,使用 z 和 y 进行解密操作,结合移位、异或和密钥
v[p] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z);
y = v[p]; // 更新 y 为当前块
}
// 第一个数据块的解密操作
z = v[n - 1]; // 最后一个块的值
v[0] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(0 & 3) ^ e] ^ z);
y = v[0]; // 更新 y 为第一个块
// 累加器 sum 减少 DELTA 值,与加密时相反
sum -= XXTEA_DELTA;
}
}
*/
void XXTEA_decrypt(uint32_t *v, int n, const uint32_t k[4]) {
/*
* - `v` 是要加密/解密的数据块,类型为 `uint32_t*`,表示数据的多个 32 位块。
* - `n` 是数据块的个数,即数据中包含的 32 位块的数量。
* - `k[4]` 是 128 位的密钥,分成四个 32 位的无符号整数。
*/
// 如果数组大小 n 小于 2,不进行解密,直接返回
if (n < 2) return;
// 初始化 z 和 y,z 为数组最后一个元素,y 为第一个元素
uint32_t z = v[n - 1], y = v[0];
// 初始化累加器 sum,为加密的总和,解密时从最大值开始递减
uint32_t sum = XXTEA_DELTA * (6 + 52 / n);
// 外层循环执行轮数次,与加密时的轮数相同
for (uint32_t i = 0; i < 6 + 52 / n; i++) {
// 计算 e,用于密钥选择
uint32_t e = (sum >> 2) & 3;
// 内层循环处理 n-1 个数据块,从数组末尾往前遍历
for (uint32_t p = n - 1; p > 0; p--) {
z = v[p - 1]; // 前一个块的值
// 更新当前块的值,使用 z 和 y 进行解密操作,结合移位、异或和密钥
v[p] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(p & 3) ^ e] ^ z);
y = v[p]; // 更新 y 为当前块
}
// 第一个数据块的解密操作
z = v[n - 1]; // 最后一个块的值
v[0] -= ((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4)) ^ (sum ^ y) + (k[(0 & 3) ^ e] ^ z);
y = v[0]; // 更新 y 为第一个块
// 累加器 sum 减少 DELTA 值,与加密时相反
sum -= XXTEA_DELTA;
}
}