25.9.2_NSSCTF-[HNCTF 2022 WEEK2]TTTTTTTTTea_WP
NSSCTF-[HNCTF 2022 WEEK2]TTTTTTTTTea_WP
1.分析题目
拖入ida中,详细分析见注释:
int __fastcall main(int argc, const char **argv, const char **envp)
{_DWORD v4[16]; // [rsp+20h] [rbp-80h] BYREF_BYTE v5[44]; // [rsp+60h] [rbp-40h] BYREFint k; // [rsp+8Ch] [rbp-14h]int j; // [rsp+90h] [rbp-10h]int i; // [rsp+94h] [rbp-Ch]_DWORD *v9; // [rsp+98h] [rbp-8h]_main();puts("please input your flag");scanf("%s", v5);v9 = v5;for ( i = 0; i <= 5; ++i )v4[i + 8] = *v9++; // 就是复制for ( j = 0; j <= 2; ++j )tea_encrypt(&v4[2 * j + 8], &key); // 这里加密,逆向就用密文传进去v4[0] = 0xC11EE75A;v4[1] = 0xA4AD0973;v4[2] = 0xF61C9018;v4[3] = 0x32E37BCD;v4[4] = 0x2DCC1F26;v4[5] = 0x344380CC; // 给了v4[0-5],相当于给了密文for ( k = 0; k <= 5; ++k ){if ( v4[k] != v4[k + 8] ) // 0-5与8-13{printf("ERROR!");exit(9);}}printf("you are right!");return 0;
}
本质就是一个清晰的xtea加密,重点看看key值:
shift+e
提取,注意改为dword,这样提取出来key值才是4个
__int64 __fastcall tea_encrypt(unsigned int *a1, __int64 a2)
{__int64 result; // raxunsigned __int64 i; // [rsp+8h] [rbp-18h]unsigned int sum; // [rsp+14h] [rbp-Ch]unsigned int v5; // [rsp+18h] [rbp-8h]unsigned int v6; // [rsp+1Ch] [rbp-4h]v6 = *a1;v5 = a1[1];sum = 0;for ( i = 0LL; i <= 31; ++i ){v6 += (((v5 >> 5) ^ (16 * v5)) + v5) ^ (*(_DWORD *)(4LL * (sum & 3) + a2) + sum);sum -= 0x61C88647; // 这里的sum逆向时需要转化为-32*delta// delta=0x61C88647v5 += (((v6 >> 5) ^ (16 * v6)) + v6) ^ (*(_DWORD *)(4LL * ((sum >> 11) & 3) + a2) + sum);}*a1 = v6;result = v5;a1[1] = v5;return result;
}
这里就是常规的tea加密,但是注意sum逆向时的初始值
还是一样的*(_DWORD *)(4LL * (sum & 3) + a2)就是a2[(sum & 3)](a2就是key值),然后写脚本
2.EXP
这里重点注意输出部分,因为得到的明文是一串16进制字符串,但是是以小端序存储的(应该是因为密文就是以小端序存储的),所以这里输出采用unsigned char *p = (unsigned char*)output;
,这样p输出时就是正常的顺序了
#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1];uint32_t delta = 0x61C88647;uint32_t sum=-32*delta; for (int i = 0; i < 32; i++) {v1 -= (((v0 >> 5) ^ (16 * v0)) + v0) ^ (k[(sum >> 11) & 3] + sum);sum += 0x61C88647;v0 -= (((v1 >> 5) ^ (16 * v1)) + v1) ^ (k[(sum & 3)] + sum);} v[0] = v0;v[1] = v1;
}int main() {uint32_t k[4] = {0x10203,0x4050607,0x8090A0B,0xC0D0E0F};uint32_t output[] = {0xC11EE75A,0xA4AD0973,0xF61C9018,0x32E37BCD,0x2DCC1F26,0x344380CC}; for(int i=0;i<=2;i++){//循环次数需要具体找,比如这道题是每次传两个,一共传三次,所以就是i<=2 decrypt(&output[i*2],k);}
// for(int i=0;i<6;i++){//输出格式具体改变
// printf("%X",output[i]);
// }//这里输出的是小端序 unsigned char *p = (unsigned char*)output;for(int i=0;i<24;i++){printf("%c", p[i]);//用这种输出方式能够避免大小端序问题
}return 0;
}