nssctf_Tea 📅 发布时间:2026/8/31 11:20:56 👁 浏览次数: 下载、查壳、64位、IDA打开、f5查看伪代码代码分析这是 IDA 反编译出的MSVC Debug 版 x64 程序主函数核心逻辑是「输入明文 → TEA 加密 → 与内置密文比对 → 正确则输出明文」。下面逐行拆解1. 函数入口与变量声明int __fastcall main_0(int argc, const char **argv, const char **envp) { char *v3; // rdi __int64 i; // rcx char v6; // [rsp20h] [rbp0h] BYREF int v7; // [rsp24h] [rbp4h] int v8; // [rsp28h] [rbp8h] int v9[12]; // [rsp68h] [rbp48h] BYREF int v10[31]; // [rsp98h] [rbp78h] BYREF int v11[31]; // [rsp114h] [rbpF4h] int j; // [rsp154h] [rbp134h] int k; // [rsp158h] [rbp138h] int m; // [rsp15Ch] [rbp13Ch]__fastcallx64 下的调用约定前 4 个参数通过寄存器传递这里argc/argv/envp是标准 C 程序 main 函数的入参。后续行是局部变量声明注释里的rspxxx是栈偏移rdi/rcx是变量使用的寄存器。v3栈操作指针用于初始化栈内存。v6栈缓冲区起始标记。v7临时计数变量初始值 32。v8校验结果标记存加密后密文是否匹配内置正确值。v9[12]TEA 加密密钥数组实际只用前 4 个元素组成 128 位标准 TEA 密钥。v10[31]输入缓冲区存用户输入的明文加密后被密文覆盖。v11[31]明文备份数组校验成功后输出它的内容。j/k/m循环计数器。2. 栈内存初始化Debug 版特征v3 v6; for ( i 102164; i; --i ) { *(_DWORD *)v3 -858993460; v3 4; }这是MSVC Debug 编译模式的栈初始化操作把栈上局部变量的内存空间全部填充为0xCCCCCCCC十进制就是 - 858993460。作用① 未初始化的变量会是0xCC调试时容易识别② 栈溢出时会覆盖成0xCC触发栈检查机制属于安全编译选项。循环次数对应栈缓冲区总大小和核心算法逻辑无关属于编译器自动生成的代码。3. 反调试检测__CheckForDebuggerJustMyCode(unk_140023009, argv, envp);微软 Visual Studio 自带的Just My Code 调试器检测函数属于反调试手段。功能检查当前程序是否被调试器附加并且验证是否只调试了程序自身代码而非系统库。如果检测到调试器程序会直接中断或异常退出阻碍动态调试。逆向时可以通过 patch 二进制、使用反调试插件绕过。4. 变量与密钥初始化v7 32; v8 0; v9[0] 1234; v9[1] 5678; v9[2] 9012; v9[3] 3456;v732、v80临时变量初始化v8作为校验标记初始化为 0代表不匹配。v9[0]~v9[3]TEA 加密的 128 位密钥4 个 32 位整数对应十六进制0x4D2、0x162E、0x2334、0xD80。标准 TEA 算法固定使用 4 个 32 位整数作为密钥这里是硬编码在程序里的固定密钥。5. 输入缓冲区清零memset(v10, 0, 0x28ui64); v11[15] 0;memset(v10, 0, 0x28)把v10数组前 40 字节0x2840清零v10用来存放用户输入的 10 个 32 位整数10×440 字节。v11[15] 0给备份数组设置字符串结束标记防止输出时越界。6. 前置子函数调用sub_1400113E8();调用地址为0x1400113E8的子函数从上下文看属于程序初始化逻辑不涉及核心加密算法一般是环境初始化、控制台设置等操作。7. 读取用户输入for ( j 0; j 10; j ) sub_1400111FE(%x, v10[j]);循环 10 次每次调用格式化输入函数类似scanf以十六进制整数的格式读取用户输入依次存入v10[0]~v10[9]。也就是说程序要求用户输入 10 个十六进制数作为待加密的明文。8. 加密前预处理sub_14001139(v9); sub_140011145(v10, v11);sub_14001139(v9)密钥预处理函数对密钥数组做前置处理标准 TEA 不需要密钥扩展这个函数大概率是简单校验或干扰也可能是魔改 TEA 的密钥变换。sub_140011145(v10, v11)把v10里的输入明文备份到v11数组后面校验成功后输出的就是备份的这份明文。9. 核心加密sub_1400112B7(v10, v9);整个程序的核心加密函数参数是「明文缓冲区 v10 密钥 v9」。结合后面错误提示里的tea algorithm可以确定这个函数实现了TEA 加密算法用密钥v9加密v10里的明文加密后的密文直接覆盖v10。TEA 是分组密码每组 64 位2 个 32 位 int这里 10 个 int 共 5 组会循环加密 5 组数据。10. 密文校验v8 sub_140011352(v10);校验函数把加密后的v10密文和程序内置的正确密文做逐位对比。返回值v8非 0 代表密文匹配输入正确0 代表不匹配输入错误。内置的正确密文就硬编码在这个函数里是解题的关键数据之一。11. 结果分支校验成功if ( v8 ) { sub_140011195(you are right!\n); for ( k 0; k 10; k ) { for ( m 3; m 0; --m ) sub_140011195(%c, (unsigned __int8)((unsigned int)v11[k] (8 * m))); } }校验通过时先输出you are right!提示。然后两层循环遍历 10 个 int每个 int 按从高字节到低字节的顺序逐字节以字符形式输出备份的明文v11。也就是把用户输入的正确明文按字节还原成字符串输出这个字符串就是 flag。12. 结果分支校验失败else { sub_140011195(fault!\nYou can go online and learn the tea algorithm!); }校验失败时输出错误提示同时直接点明加密算法是 TEA降低了逆向难度。13. 函数返回return 0; }程序正常退出返回值 0。TEATiny Encryption Algorithm微型加密算法是剑桥大学 David Wheeler 与 Roger Needham 设计的轻量级分组密码核心特点是代码极简、实现体积小、运算速度快非常适合嵌入式、资源受限设备也是 CTF 逆向题中最常考的经典算法之一。核心参数分组长度64 位加密时拆成 2 个 32 位整数v0、v1并行运算密钥长度128 位拆成 4 个 32 位整数k0、k1、k2、k3标准轮数32 轮标准轮常数delta0x9E3779B9取自黄金分割比的小数部分用于每轮混淆扩散2. 标准 TEA 加密逻辑TEA 采用类 Feistel 迭代结构每轮通过移位、异或、加法操作对左右两半数据做非线性混淆重复 32 轮后得到密文。标准单轮加密公式// 每轮先累加轮常数 sum delta; // 更新左半部分v0 v0 ((v1 4) k0) ^ (v1 sum) ^ ((v1 5) k1); // 更新右半部分v1 v1 ((v0 4) k2) ^ (v0 sum) ^ ((v0 5) k3);运算逻辑拆解移位扩散对另一半数据做左移 4 位、右移 5 位把单个比特的影响扩散到整个整数。密钥混合移位结果分别和两个密钥子项相加引入密钥信息。轮常数混淆和累加后的sum做异或让每轮的运算特征都不同提升抗攻击能力。结果累加最终结果累加到原数据上完成一轮更新。3. XTEA改进版 TEAXTEAeXtended TEA是 TEA 的增强版本修正了原 TEA 的弱密钥缺陷调整了密钥调度和运算顺序也是 CTF 中更常见的版本密钥选取改为sum 3和(sum11) 3每轮动态从 4 个密钥里选 2 个。移位和异或的组合更复杂进一步提升非线性程度。标准 XTEA 单轮加密sum delta; v0 ((v1 4 ^ v1 5) v1) ^ (sum key[sum 3]); v1 ((v0 4 ^ v0 5) v0) ^ (sum key[(sum11) 3]);写解密脚本由代码解析可知核心加密算法是这个解密脚本#include stdio.h#include stdint.hint j;int round;int i;void decrypt(uint32_t* v, const uint32_t* key) {const uint32_t delta 256256256;for (j 8; j 0; --j) { uint32_t v4 j 1; uint32_t v7 delta * (32 j); for (round 0; round 33; round) { v[v4] - ((key[(v7 11) 3] v7) ^ (((v[j] 4) ^ (v[j] 5)) v[j])); v[j] - (((key[v7 3] v7) ^ (((v[v4] 4) ^ (v[v4] 5)) v[v4])) ^ v7); v7 - delta; } }}int main() {uint32_t Key[4] { 2233,4455,6677,8899 };uint32_t v8[10];v8[0] 444599258;v8[1] -140107365;v8[2] 1226314200;v8[3] -234802392;v8[4] 359413339;v8[5] 1013885656;v8[6] -2066432216;v8[7] -249921817;v8[8] 856928850;v8[9] -576724359;decrypt(v8, Key);for (i 0; i 10; i) { for (j 3; j 0; j--) putchar((v8[i] (j * 8))); }}得到flag本题知识点1、tea算法2、会追数据