当前位置: 首页 > article >正文

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;
    }
}

http://www.kler.cn/a/392374.html

相关文章:

  • css:盒子模型
  • 设计模式之责任链模式(Chain Of Responsibility)
  • 【数据结构】交换排序——冒泡排序 和 快速排序
  • DeBiFormer实战:使用DeBiFormer实现图像分类任务(二)
  • 带你掌握springboot集成SpringSecurity安全框架
  • Linux第四讲:Git gdb
  • 生成任意3D和4D场景!GenXD:通用3D-4D联合生成框架 | 新加坡国立微软
  • 【C#设计模式(2)——工厂模式】
  • 推荐一款游戏玩家性能优化工具:Razer Cortex
  • C#的6种常用集合类
  • MySQL 中的集群部署方案
  • 使用Python实现音频降噪
  • ubuntu-desktop-24.04上手指南(更新阿里源、安装ssh、安装chrome、设置固定IP、安装搜狗输入法)
  • Windows快速部署并使用GitHub上Swift项目
  • 三 Spring的入门程序
  • 【MySQL】零碎知识点(易忘 / 易错)总结回顾
  • 【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-跳绳
  • el-table 行列文字悬浮超出屏幕宽度不换行的问题
  • 微信小程序+JAVA实现微信支付
  • JS爬虫实战之TikTok_Shop验证码
  • 【基础】类中的继承
  • 工程认证导向的Spring Boot计算机课程管理平台
  • 微服务架构面试内容整理-SpringCloud Netflix‌与Spring Cloud Alibaba比较
  • spring cloud实战总结(优雅下线、灰度发布)
  • AI问答-base64:概念、原理、使用
  • 安卓全屏实现