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

25.9.2_CTF_reverse_TEA算法

CTF_reverse_TEA算法

0x00

主要借鉴了这位大佬的博文tea 加密解密算法(面向ctf-reverse使用,光速学会tea逆向套路)_tea加密-CSDN博客

做了几道题,我觉得tea算法就是一个异或,在原代码上修改就成了解密脚本

一般tea算法加密都是:

for (int i = 0; i < 32; i++) {sum += delta;v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);}

delta的值,右移5左移4,加密32轮都可以作为识别tea算法的特征

解密也很简单就是从下往上写,加换减,异或看作一个整体

for (int i = 0; i < 32; i++) {v1 -= ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);v0 -= ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);sum -= delta;

0x01 [MoeCTF 2022]ezTea

pdf文件里面找到输出output={0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e, 0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99, 0xec, 0xb1, 0xe1, 0x7d}

分析源码,具体分析放在注释里了

#include <stdio.h>
#include <stdint.h>void encrypt (uint32_t* v, uint32_t* k) {                       // 主要加密函数,试着搞定它uint32_t v0 = v[0], v1 = v[1], sum = 0;uint32_t delta = 0xd33b470;for (int i = 0; i < 32; i++) {sum += delta;v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);}                              //这里就是具体加密过程 v[0] = v0;v[1] = v1;
}int main() {uint32_t k[4] = {1, 2, 3, 4};int8_t input[33] = {0};      //注意这里的输入是int8_t类型的,就是一个字节,比如0x12 scanf("%32s", input);for (int i = 0; i < 32; i+=8) {uint32_t v[2] = {*(uint32_t *)&input[i], *(uint32_t *)&input[i+4]};        //这里需要C语言知识,解读一下*(uint32_t *)&input[i],对input[i]取地址,然后转化为uint32_t*的指针,然后解引用,举例来说就是比如input={0x12,0x34,0x56,0x78},然后先是取input[0]也就是0x12的地址,然后转化为uint32_t类型的指针,这时候指针指的就是4个字节了,解引用后就是{0x12,0x34,0x56,0x78} encrypt(v, k);                        //假设我们输入8个字节,0x12算是一个字节,v[0]就是前4个字节,v[1]就是后4个字节,但是注意小端序存储,所以v[0]=0x78563412,就是顺序倒过来 for (int j = 0; j < 2; j++) {                           // 这一段主要是把 v 按单字节输出,另外可以了解一下 “大小端序” 在这题是如何体现的for (int k = 0; k < 4; k++) {printf("%#x, ", v[j] & 0xff);            //进行输出,我们改成%c输出的就是字符了 v[j] >>= 8;}}}return 0;
}

解密脚本:

#include <stdio.h>
#include <stdint.h>void encrypt (uint32_t* v, uint32_t* k) {                       // 主要加密函数,试着搞定它uint32_t v0 = v[0], v1 = v[1], sum = 0;uint32_t delta = 0xd33b470;for (int i = 0; i < 32; i++) {sum += delta;v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);}v[0] = v0;v[1] = v1;
}
void decrypt (uint32_t* v, uint32_t* k) {                       // 主要加密函数,试着搞定它uint32_t v0 = v[0], v1 = v[1];uint32_t delta = 0xd33b470;uint32_t sum=32*delta;for (int i = 0; i < 32; i++) {v1 -= ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);v0 -= ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);sum -= delta;}v[0] = v0;v[1] = v1;
}int main() {uint32_t k[4] = {1, 2, 3, 4};
//    int8_t input[33] = {0};int8_t output[]={0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e, 
0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99, 
0xec, 0xb1, 0xe1, 0x7d};   
//    scanf("%32s", input);for (int i = 0; i < 32; i+=8) {uint32_t v[2] = {*(uint32_t *)&output[i], *(uint32_t *)&output[i+4]};     //比如{0x12,0x34,0x56,0x78}就转化成0x78563412,因为0x12是一个字节,input是int8类型,转化后的是in32类型,所以需要4字节,又因为大小端序存储,所以是0x78563412 
//        encrypt(v, k);decrypt(v,k);for (int j = 0; j < 2; j++) {                           // 这一段主要是把 v 按单字节输出,另外可以了解一下 “大小端序” 在这题是如何体现的for (int k = 0; k < 4; k++) {printf("%c", v[j] & 0xff);v[j] >>= 8;}}}return 0;
}

Get_flag:moectf{Th3_TEA_!S_s0_t4s7y~~!!!}

0x02 [GWCTF 2019]xxor

1.分析题目

先分析main函数,详见注释:

__int64 __fastcall main(int a1, char **a2, char **a3)
{int i; // [rsp+8h] [rbp-68h]int j; // [rsp+Ch] [rbp-64h]_QWORD v6[6]; // [rsp+10h] [rbp-60h] BYREF_QWORD v7[6]; // [rsp+40h] [rbp-30h] BYREFv7[5] = __readfsqword(0x28u);puts("Let us play a game?");puts("you have six chances to input");puts("Come on!");memset(v6, 0, 40);for ( i = 0; i <= 5; ++i ){printf("%s", "input: ");__isoc99_scanf("%d", (char *)v6 + 4 * i);   // 输入的是32位整数,如0x12345678// 这里只有v[0],v[1],v[2]存入了输入的元素// 相当于我输入6个4字节的数,然后存成3个8字节的数}memset(v7, 0, 40);for ( j = 0; j <= 2; ++j ){dword_601078 = v6[j];dword_60107C = HIDWORD(v6[j]);sub_400686(&dword_601078, &key);            // 通过tea算法加密// 这里看似是只加密低位的,其实低位的和高位的都加密了,所以j只取了0,1,2三个值LODWORD(v7[j]) = dword_601078;HIDWORD(v7[j]) = dword_60107C;              // 这里再合起来得到v7}if ( (unsigned int)sub_400770(v7) != 1 )      // 可以由这个函数求得v7{puts("NO NO NO~ ");exit(0);}puts("Congratulation!\n");puts("You seccess half\n");puts("Do not forget to change input to hex and combine~\n");puts("ByeBye");return 0LL;
}

我觉得最主要是要搞懂qword和dword,以及地址的解引用与取地址的理解

然后找一下key值,双击,shift+e提取:

image-20250901221757002

image-20250901221839843

再分析sub_400686函数,也就是tea算法加密:

// 其实低位高位都加密了
__int64 __fastcall sub_400686(unsigned int *v, _DWORD *a2)
{__int64 result; // raxunsigned int v0; // [rsp+1Ch] [rbp-24h]unsigned int v1; // [rsp+20h] [rbp-20h]int sum; // [rsp+24h] [rbp-1Ch]unsigned int i; // [rsp+28h] [rbp-18h]v0 = *v;                                      // 低位的4字节v1 = v[1];                                    // 高位的4字节sum = 0;for ( i = 0; i <= 63; ++i ){sum += 1166789954;v0 += (v1 + sum + 11) ^ ((v1 << 6) + *a2) ^ ((v1 >> 9) + a2[1]) ^ 0x20;v1 += (v0 + sum + 20) ^ ((v0 << 6) + a2[2]) ^ ((v0 >> 9) + a2[3]) ^ 0x10;}                                             // 正常的tea算法*v = v0;result = v1;v[1] = v1;return result;
}

这道题也是常规的tea算法,可以直接编写脚本

2.EXP

#include <stdio.h>
#include <stdint.h>
void encrypt (uint32_t* v, uint32_t* k) {                       uint32_t v0 = v[0], v1 = v[1];uint32_t delta = 0x458BCD42;uint32_t sum=delta*64;for (int i = 0; i < 64; i++) {v1-=(v0 + sum + 20) ^ ((v0 << 6) + k[2]) ^ ((v0 >> 9) + k[3]) ^ 0x10;v0-=(v1 + sum + 11) ^ ((v1 << 6) + k[0]) ^ ((v1 >> 9) + k[1]) ^ 0x20;sum-=delta;}                               v[0] = v0;v[1] = v1;
}int main() {uint32_t k[4] = {2, 2, 3, 4};uint32_t input[] = {3746099070,550153460,3774025685,1548802262,2652626477,2230518816};      for(int i=0;i<=2;i++){//循环次数需要具体找,比如这道题是每次传两个,一共传三次,所以就是i<=2 encrypt(&input[i*2],k);}for(int i=0;i<6;i++){//输出格式具体改变 printf("%X",input[i]);}return 0;
}

得到一串16进制字符666C61677B72655F69735F6772656174217D,在在线网站上转化为字符串,得到flag

Get_flag:flag{re_is_great!}

0x03 [GDOUCTF 2023]Tea

1.分析题目

64位,ida打开,定位到main函数,详细分析见注释:

int __fastcall main_0(int argc, const char **argv, const char **envp)
{char *v3; // rdi__int64 i; // rcxchar v6; // [rsp+20h] [rbp+0h] BYREFint n32; // [rsp+24h] [rbp+4h]int v8; // [rsp+44h] [rbp+24h]_DWORD key[12]; // [rsp+68h] [rbp+48h] BYREF_DWORD input[16]; // [rsp+98h] [rbp+78h] BYREF_DWORD v11[31]; // [rsp+D8h] [rbp+B8h] BYREFint j; // [rsp+154h] [rbp+134h]int k; // [rsp+174h] [rbp+154h]int m; // [rsp+194h] [rbp+174h]v3 = &v6;for ( i = 102LL; i; --i ){*(_DWORD *)v3 = -858993460;v3 += 4;}j___CheckForDebuggerJustMyCode(&unk_140023009, argv, envp);n32 = 32;v8 = 0;key[0] = 1234;key[1] = 5678;key[2] = 9012;key[3] = 3456;memset(input, 0, 0x28uLL);v11[15] = 0;v11[23] = 0;                                  // 以上都是初始化sub_1400113E8();                              // 打印初始信息for ( j = 0; j < 10; ++j )scanf("%x", &input[j]);                     // 这里调试后发现是scanf函数sub_140011339(key);                           // 这里修改了keysub_140011145(input, v11);                    // 就是把input复制给了v11sub_1400112B7(input, key);                    // tea加密v8 = sub_140011352(input);                    // 这里可以求得加密后的值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)(v11[k] >> (8 * m)));}}else{sub_140011195("fault!\nYou can go online and learn the tea algorithm!");}return 0;
}

双击跟进sub_140011339(key)函数可以发现key值:key={2233,4455,6677,8899}

image-20250902101644878

sub_140011145(input, v11)不必多说

先看v8 = sub_140011352(input),双击跟进后找到加密后的值:

image-20250902101753326

output[]={0x1A800BDA,0xF7A6219B,0x491811D8,0xF2013328,0x156C365B,0x3C6EAAD8,0x84D4BF28,0xF11A7EE7,0x3313B252,0xDD9FE279}

这里重点分析tea算法,也就是sub_1400112B7函数

__int64 __fastcall sub_140011900(__int64 a1, __int64 a2, __int64 a3)
{__int64 result; // raxint v4; // [rsp+44h] [rbp+24h]int i; // [rsp+64h] [rbp+44h]unsigned int j; // [rsp+84h] [rbp+64h]unsigned int sum; // [rsp+C4h] [rbp+A4h]result = j___CheckForDebuggerJustMyCode(&unk_140023009, a2, a3);for ( i = 0; i <= 8; ++i ){j = 0;sum = 256256256 * i;v4 = i + 1;do{++j;*(_DWORD *)(a1 + 4LL * i) += sum ^ (*(_DWORD *)(a1 + 4LL * v4)+ ((*(_DWORD *)(a1 + 4LL * v4) >> 5) ^ (16 * *(_DWORD *)(a1 + 4LL * v4)))) ^ (sum + *(_DWORD *)(a2 + 4LL * (sum & 3)));*(_DWORD *)(a1 + 4LL * v4) += (sum + *(_DWORD *)(a2 + 4LL * ((sum >> 11) & 3))) ^ (*(_DWORD *)(a1 + 4LL * i)+ ((*(_DWORD *)(a1 + 4LL * i) >> 5) ^ (16 * *(_DWORD *)(a1 + 4LL * i))));sum += 256256256;}while ( j <= 0x20 );result = (unsigned int)(i + 1);}return result;
}

这里需要特别注意的是两层循环分别循环多少次,另一个就是后面的括号一定要分清楚,特别是’+‘优先级大于’^',这里我写脚本的时候就栽了跟斗

简单来说就是第一个for循环0-8,共9次,第二个do-while循环j从1到33共33次(这里注意j进循环就加1了,所以不是从0开始的)

所以逆向思路就是for循环从8-0,然后do-while从33到1

2.EXP

这里需要注意的是,有的师傅得到16进制串就让直接16进制转字符串了,这是不对的,需要按照题中的输出方式copy一遍出来的才对

#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {                       uint32_t delta = 0xF462900,sum=0,j=33;for(int i=8;i>=0;i--){j=33;//这里注意每个for循环开始,j都要初始化为33 sum=delta*(i+j);do{j--;sum-=delta;v[i+1] -= (sum + k[((sum >> 11) & 3)]) ^ (v[i] + ((v[i] >> 5) ^ (16 * v[i])));v[i] -= sum ^ (v[i+1] + ((v[i+1] >> 5) ^ (16 * v[i+1]))) ^ (sum + k[(sum & 3)]);}while(j>0);}
}int main() {uint32_t k[4] = {2233,4455,6677,8899};uint32_t output[] = {0x1A800BDA,0xF7A6219B,0x491811D8,0xF2013328,0x156C365B,0x3C6EAAD8,0x84D4BF28,0xF11A7EE7,0x3313B252,0xDD9FE279};      decrypt(output,k);//这道题是直接传入的,所以不用循环 
//	for(int i=0;i<10;i++){
//		printf("%X",output[i]);
//	}//output求出来是'485A4354467B687A4374665F39345F726536363666696E676372793536343171717D0',很多师傅直接说16进制转字符串,这是不对的for(int m=0;m<10;m++){//这里的输出要按照题中的输出来copy for(int n=3;n>=0;n--){printf("%c",output[m]>>(8 * n));}}return 0;
}

Get_flag:HZCTF{hzCtf_94_re666fingcry5641qq}

0x04 写在最后的

本次刷了几道比较简单的TEA算法的题目,脚本都是手搓的,最好用C语言写,因为指针就是破解tea最强大的利器。简单来说就是如下几点:

1.找key值,一般都是4个整数

2.找密文

3.找加密算法,这里想成一个异或这样的对称加密就好了,但是delta,sum值,循环(特别是循环次数!!!)一定要找清楚

4.输出的时候严格按照题中的输出方法来写

TEA算法还在持续做题ing……

r(int m=0;m<10;m++){//这里的输出要按照题中的输出来copy
for(int n=3;n>=0;n–){
printf(“%c”,output[m]>>(8 * n));
}
}
return 0;
}


Get_flag:HZCTF{hzCtf_94_re666fingcry5641qq}## 0x04 写在最后的本次刷了几道比较简单的TEA算法的题目,脚本都是手搓的,最好用C语言写,因为指针就是破解tea最强大的利器。简单来说就是如下几点:1.找key值,一般都是4个整数2.找密文3.找加密算法,这里想成一个异或这样的对称加密就好了,但是delta,sum值,循环(特别是循环次数!!!)一定要找清楚4.输出的时候严格按照题中的输出方法来写TEA算法还在持续做题ing……

文章转载自:

http://nxZq4mci.rgtst.cn
http://6JydYZwS.rgtst.cn
http://2prRhCja.rgtst.cn
http://T1epYohN.rgtst.cn
http://njPERx44.rgtst.cn
http://jMUXzW5N.rgtst.cn
http://q38kHL2f.rgtst.cn
http://8ifBd45Q.rgtst.cn
http://Mjs2LiPY.rgtst.cn
http://Bbbh9Jjv.rgtst.cn
http://w9zcZknZ.rgtst.cn
http://z6wFCQFC.rgtst.cn
http://07dSFuka.rgtst.cn
http://uNPSS3bf.rgtst.cn
http://6dxhNqnF.rgtst.cn
http://qotY3166.rgtst.cn
http://OE68HtCE.rgtst.cn
http://LXvBbZPF.rgtst.cn
http://kou7Pm67.rgtst.cn
http://dpH4XtLz.rgtst.cn
http://WsW6qgcj.rgtst.cn
http://g6wmN300.rgtst.cn
http://3iXMnXX7.rgtst.cn
http://p4tv9JCd.rgtst.cn
http://jl3DH83J.rgtst.cn
http://qytQ7dzt.rgtst.cn
http://Jt9rgLLr.rgtst.cn
http://7ZEkTHwF.rgtst.cn
http://ROgpS0hf.rgtst.cn
http://0sKeh70C.rgtst.cn
http://www.dtcms.com/a/363612.html

相关文章:

  • 项目解析:技术实现与面试高频问题
  • 交叉熵损失函数
  • 一文读懂 Python 【循环语句】:从基础到实战,效率提升指南
  • 零构建的快感!dagger.js 与 React Hooks 实现对比,谁更优雅?
  • 餐饮、跑腿、零售多场景下的同城外卖系统源码扩展方案
  • 基于高德地图实现后端传来两点坐标计算两点距离并显示
  • JDK16安装步骤及下载(附小白详细教程)
  • 【Spring Cloud微服务】9.一站式掌握 Seata:架构设计与 AT、TCC、Saga、XA 模式选型指南
  • Javascript》》JS》》ES6》 Map、Set、WeakSet、WeakMap
  • Java 技术支撑 AI 系统落地:从模型部署到安全合规的企业级解决方案(一)
  • SQL分类详解:掌握DQL、DML、DDL等数据库语言类型
  • Java-Spring入门指南(二)利用IDEA手把手教你如何创建第一个Spring系统
  • Python学习-day4
  • win32diskimager强行缩减TF卡镜像制作尺寸的方法
  • Zynq中级开发七项必修课-第四课:S_AXI_HP0 高速端口访问 DDR
  • 整理期初数据用到的EXCEL里面的函数操作
  • 2026届长亭科技秋招正式开始
  • 炫酷JavaScript鼠标跟随特效
  • Nano Banana 新玩法超惊艳!附教程案例提示词!
  • CMake构建学习笔记23-SQLite库的构建
  • SQL Server 数据库创建与用户权限绑定
  • 构建下一代智能金融基础设施
  • 网络编程 05:UDP 连接,UDP 与 TCP 的区别,实现 UDP 消息发送和接收,通过 URL 下载资源
  • 网络传输的实际收发情况及tcp、udp的区别
  • python 创建websocket教程
  • 异常处理小妙招——1.别把“数据库黑话”抛给用户:论异常封装的重要性
  • GitHub每日最火火火项目(9.2)
  • 使用谷歌ai models/gemini-2.5-flash-image-preview 生成图片
  • Python/JS/Go/Java同步学习(第一篇)格式化/隐藏参数一锅端 四语言输出流参数宇宙(附源码/截图/参数表/避坑指南/老板沉默术)
  • 下载速度爆表,全平台通用,免费拿走!