解析 TEA 加密算法(C语言、python):_tea加密-CSDN博客
CTF-RE 从0到N: TEA_tea加密原理-CSDN博客
1 字节 = 8 位
牢记密文的64位和密钥的128位,最好可以自己独立的写出tea解密代码
相当于密文是传入8个字符类型数据或者是2个整型数据,
密钥是16个字符数据或者4个整型数据,
一.drink_tea
blob:https://ctf.xidian.edu.cn/7ae7c1a9-61a8-4343-be1f-a4ce1fafcf7e
int __fastcall main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // r8
__int64 v6; // rdx
__int64 v7; // r8
int i; // [rsp+20h] [rbp-28h]
__int64 v9; // [rsp+28h] [rbp-20h]
sub_140001070(aPleaseInput, argv, envp);
sub_140001120("%32s", byte_140004700);
v9 = -1i64;
do
++v9;
while ( byte_140004700[v9] );
if ( v9 == dword_140004078 )
{
for ( i = 0; i < dword_140004078; i += 8 )
sub_140001180(&byte_140004700[i], aWelcometonewst);
if ( !memcmp(byte_140004700, &unk_140004080, dword_140004078) )
sub_140001070(aRight, v6, v7);
else
sub_140001070(aWrong_0, v6, v7);
return 0;
}
else
{
sub_140001070(aWrong, v3, v4);
return 0;
}
}
int __fastcall main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdx
__int64 v4; // r8
__int64 v6; // rdx
__int64 v7; // r8
int i; // [rsp+20h] [rbp-28h]
__int64 v9; // [rsp+28h] [rbp-20h]
printf(Format, argv, envp);
scanf("%32s", falg);
v9 = -1i64;
do
++v9;
while ( falg[v9] );
if ( v9 == len )
{
for ( i = 0; i < len; i += 8 )
encrypt(&falg[i], aWelcometonewst);
if ( !memcmp(falg, &miwen, len) )
printf(aRight, v6, v7);
else
printf(aWrong_0, v6, v7);
return 0;
}
else
{
printf(aWrong, v3, v4);
return 0;
}
}
分析了一下修改了函数名,查看密文和长度
查看加密函数
__int64 __fastcall encrypt(unsigned int *a1, _DWORD *a2)
{
__int64 result; // rax
unsigned int v3; // [rsp+0h] [rbp-38h]
unsigned int v4; // [rsp+4h] [rbp-34h]
int v5; // [rsp+8h] [rbp-30h]
unsigned int i; // [rsp+Ch] [rbp-2Ch]
v3 = *a1;
v4 = a1[1];
v5 = 0;
for ( i = 0; i < 0x20; ++i )
{
v5 -= 1640531527;
v3 += (a2[1] + (v4 >> 5)) ^ (v5 + v4) ^ (*a2 + 16 * v4);
v4 += (a2[3] + (v3 >> 5)) ^ (v5 + v3) ^ (a2[2] + 16 * v3);
}
*a1 = v3;
result = 4i64;
a1[1] = v4;
return result;
}
是tea加密,密文是32个字符类型数据,密钥是16个字符类型数据,让后学到了新的代码
uint32_t:32位无符号整数
uint32_t
是一个在 C 语言标准库<stdint.h>
中定义的类型,可以处理特定大小数据,就比如tea中的密文和密钥
写代码
#include<stdio.h>
#include<stdint.h>
void decrypt(uint32_t *a1,uint32_t *a2)
{
uint32_t v3; // [rsp+0h] [rbp-38h]
uint32_t v4; // [rsp+4h] [rbp-34h]
int v5; // [rsp+8h] [rbp-30h]
uint32_t i; // [rsp+Ch] [rbp-2Ch]
v3 = a1[0];
v4 = a1[1];
v5 = -1640531527*32;
for ( i = 0; i < 32; ++i )
{
v4 -= (a2[3] + (v3 >> 5)) ^ (v5 + v3) ^ (a2[2] + 16 * v3);
v3 -= (a2[1] + (v4 >> 5)) ^ (v5 + v4) ^ (a2[0] + 16 * v4);
v5 += 1640531527;
}
a1[0] = v3;
a1[1] = v4;
}
int main()
{
unsigned char a[]={
120, 32, 247, 179, 197, 66, 206, 218, 133, 89,
33, 26, 38, 86, 90, 89, 41, 2, 13, 237,
7, 168, 185, 238, 54, 89, 17, 135, 253, 92,
35, 36};
unsigned char key[]="WelcomeToNewStar";
int i;
uint32_t *v=(uint32_t*)a;
uint32_t *k=(uint32_t*)key;
for(i=0;i<8;i+=2){
decrypt(v+i,k);
}
for(i=0;i<32;i++){
printf("%c",a[i]);
}
}
flag{There_R_TEA_XTEA_and_XXTEA}
二.xtea
int __fastcall main_0(int argc, const char **argv, const char **envp)
{
char *v3; // rdi
__int64 i; // rcx
__int64 v5; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
__int64 v10; // rax
char v11; // [rsp+20h] [rbp+0h] BYREF
unsigned int v12; // [rsp+24h] [rbp+4h]
char Str[48]; // [rsp+48h] [rbp+28h] BYREF
int v14[12]; // [rsp+78h] [rbp+58h] BYREF
char Src[32]; // [rsp+A8h] [rbp+88h] BYREF
char v16[28]; // [rsp+C8h] [rbp+A8h] BYREF
int j; // [rsp+E4h] [rbp+C4h]
v3 = &v11;
for ( i = 58i64; i; --i )
{
*v3 = -858993460;
v3 += 4;
}
j___CheckForDebuggerJustMyCode(&unk_140028066, argv, envp);
v12 = 32;
memset(Str, 0, 0xDui64);
v5 = sub_1400110AA(std::cout, "please input key:");
std::ostream::operator<<(v5, sub_140011046);
sub_14001153C(std::cin, Str);
v14[0] = 2;
v14[1] = 0;
v14[2] = 2;
v14[3] = 4;
v6 = sub_1400110AA(std::cout, "let me check your key");
std::ostream::operator<<(v6, sub_140011046);
v7 = sub_1400110AA(std::cout, "emmm");
std::ostream::operator<<(v7, sub_140011046);
if ( j_strlen(Str) == 12 )
{
memset(v16, 0, 8ui64);
j_memcpy(Src, Str, 8ui64);
sub_14001119F(v12, Src, v14);
j_memcpy(Str, Src, 8ui64);
j_memcpy(v16, &Str[4], 8ui64);
sub_14001119F(v12, v16, v14);
j_memcpy(&Str[4], v16, 8ui64);
for ( j = 0; j < 12; ++j )
{
if ( Str[j] != byte_140022000[j] )
goto LABEL_5;
}
v10 = sub_1400110AA(std::cout, "Correct key! Your flag is moectf{your key}");
std::ostream::operator<<(v10, sub_140011046);
return 0;
}
else
{
LABEL_5:
v8 = sub_1400110AA(std::cout, "XD,wrong!");
std::ostream::operator<<(v8, sub_140011046);
return 0;
}
}
是c++代码,猜测关键地方
进入sub_14001119F函数有xtea加密
__int64 __fastcall sub_1400148C0(unsigned int a1, unsigned int *a2, __int64 a3)
{
__int64 result; // rax
unsigned int i; // [rsp+24h] [rbp+4h]
unsigned int v5; // [rsp+44h] [rbp+24h]
unsigned int v6; // [rsp+64h] [rbp+44h]
unsigned int v7; // [rsp+84h] [rbp+64h]
j___CheckForDebuggerJustMyCode(&unk_140028066, a2, a3);
v5 = *a2;
v6 = a2[1];
v7 = 0;
for ( i = 0; i < a1; ++i )
{
v5 += (*(a3 + 4i64 * (v7 & 3)) + v7) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
v7 -= 855655493;
v6 += (*(a3 + 4i64 * ((v7 >> 11) & 3)) + v7) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
}
*a2 = v5;
result = 4i64;
a2[1] = v6;
return result;
}
写注释来分析,其中
8ui64分析是对“8个无符号的64位整数”的非正式简写。这里的“ui64”通常指的是一个无符号的64位整数,而“8”表示数量。
由于一个无符号的64位整数占用8个字节(因为64位等于8字节),那么“8ui64”就意味着8个这样的64位整数。因此,计算总字节数是64字节
但是密文就只有12个字符是64字节,其中他还分了前后8位进行加密运算,所以合理猜测是表示有误,我们按照一般思路来解题目;
写代码
#include<stdio.h>
#include<stdint.h>
void decrypt( uint32_t *a2, int* a3)
{
int i; // [rsp+24h] [rbp+4h]
uint32_t v5; // [rsp+44h] [rbp+24h]
uint32_t v6; // [rsp+64h] [rbp+44h]
int v7; // [rsp+84h] [rbp+64h]
v5 = *a2;
v6 = a2[1];
v7 = -855655493*32;
for ( i = 0; i < 32; ++i )
{
v6 -= (a3[(v7 >> 11) & 3] + v7) ^ (v5 + ((v5 >> 5) ^ (16 * v5)));
v7 += 855655493;
v5 -= (a3[v7 & 3] + v7) ^ (v6 + ((v6 >> 5) ^ (16 * v6)));
}
*a2 = v5;
a2[1] = v6;
}
int main()
{
unsigned char miwen[] ={
163, 105, 150, 38, 189, 120, 11, 61, 157, 165,
40, 98, };
int key[]={2,0,2,4};
int i;
uint32_t*v=(uint32_t*)miwen;
decrypt(v+1,key);
decrypt(v,key);
for(i=0;i<12;i++){
printf("%c",miwen[i]);
}
}
moectf2024!!
让后结合输出的格式
moectf{moectf2024!!}
之后遇到了有价值的题目再总结于此吧