(54)[GDOUCTF 2023]Tea
nss:3688
关于这个题,看题目我们就知道很什么有关系。
那我们拖进IDA观察一下

我们发现这个题里面有好多函数,说明这个题没有我们想的那么简单,不仅仅是一个加密哦。
我们一步步来看吧(我把函数名字重新赋一个名字,便于打字)

我们先进入step1看看这个函数
__int64 __fastcall sub_1400117D0(_DWORD *a1, __int64 a2, __int64 a3)
{
char *v3; // rdi
__int64 i; // rcx
__int64 result; // rax
char v6; // [rsp+20h] [rbp+0h] BYREF
int v7; // [rsp+2Ch] [rbp+Ch]
int v8; // [rsp+30h] [rbp+10h]
unsigned int v9; // [rsp+34h] [rbp+14h]
v3 = &v6;
for ( i = 14i64; i; --i )
{
*(_DWORD *)v3 = -858993460;
v3 += 4;
}
j___CheckForDebuggerJustMyCode((__int64)&unk_140023009, a2, a3);
v7 = 4455;
v8 = 6677;
v9 = 8899;
*a1 = 2233;
a1[1] = v7;
a1[2] = v8;
result = v9;
a1[3] = v9;
return result;
}
它传入v9然后将v9的值给变更。
所以v9经过改变后的值变成了
unsinged int v9[4]={2233,4455,6677,8899};
我们接着往后看step2,我们发现后面就没有用到v11,并且我们进入函数,这个函数也是一个没起到作用的函数。

然后我们进入step3,它传入的v9和flag

这个有点类似于tea了对不对,但跟我们标准的tea加密还不一样,但是解密我们仿照它写就对了。
通过观察,我们发现deault是v7
key是v9
我们就把这个代码逆过来就是以下代码:
#include <stdio.h>
#include <stdint.h>
int main() {
uint32_t key[4] = { 2233, 4455, 6677, 8899 };
uint32_t enc[10] = { 444599258, 4154859931, 1226314200, 4060164904, 359413339, 1013885656,
2228535080, 4045045479, 856928850, 3718242937
};
for (int i = 8; i >= 0; i--) {
unsigned int v6 = 33;
unsigned int v7 = 256256256 * (i + v6);
do {
v7 -= 256256256 ;
enc[i + 1] -= (v7 + key[(v7 >> 11) & 3]) ^ (enc[i] + ((enc[i] >> 5) ^ (16 * enc[i])));
enc[i] -= v7 ^ (enc[i + 1] + ((enc[i + 1] >> 5) ^ (16 * enc[i + 1]))) ^ (v7 + key[v7 & 3]);
--v6;
} while (v6 > 0);
}
for (int i = 0; i < 10; i++) {
printf("%x", enc[i]);
}
printf("\n");
//下面是将小端序搞出来
for (int i = 0; i < 10; i++) {
uint32_t val = enc[i];
putchar((val >> 24) & 0xFF);
putchar((val >> 16) & 0xFF);
putchar((val >> 8) & 0xFF);
putchar(val & 0xFF);
}
// for (int i = 0; i < 40; i++) {
// printf("%c", *(((char *)enc) + i));
// }
}
485a4354467b687a4374665f39345f726536363666696e676372793536343171717d0 HZCTF{hzCtf_94_re666fingcry5641qq}

最后讲一下这里,关于大小端序的问题。
我们知道我们电脑基本都是小端序,当我用我注释的这几行错误代码,我们将enc转化为一个char*类型,原本是4字节,char之后是一字节,便于我们去转换字符。然后我这里错在这里。
当我们强制转换类型之后,enc是小端存储,他原本的首地址,存储的
所以我们如果按我这个写的就不对了
我们可以这样改一下哦
// for (int i = 0; i < 40; i++) {
// // 计算当前字节所在的大端序位置
// int block = i / 4; // 当前是第几个 4 字节块
// int offset = i % 4; // 当前块内的偏移
// int adjusted_i = block * 4 + (3 - offset); // 大端序调整后的偏移
// printf("%c", *(((char *)enc) + adjusted_i));
// }
然后我们运行之后,就是正确答案了
GDOUCTF 2023 Tea题解题分析
6244

被折叠的 条评论
为什么被折叠?



