
先看下文件信息:没有加壳、64位程序

看别人wp时候发现个好东东,就是这个findcrypt插件,可以看加密算法的,具体安装可以看这个IDA7.5安装findcrypt3插件

可以看到这是tea加密

先一点点分析代码,输入flag,flag的长度必须为19
sub_7FF7A98718C0(std::cin, argv, flag); // 输入flagv3 = -1i64;v4 = -1i64;do++v4;while ( *((_BYTE *)flag + v4) );if ( v4 != 19 ) // 长度为19{sub_7FF7A9871620(std::cout, "error\n");_exit((int)flag);
这里给v6赋值为qwertyuiopasdfghjklzxcvbnm1234567890
这行代码看上去挺麻烦的,一眼唬住,但是仔细看下,前面有个v9 = v5,后面又减去了个v5,所以这行代码就变成了v10 = *flag
v10 = *((_BYTE *)v9 + (char *)flag - (char *)v5);
这段代码比较的是输入的flag的前四个字符是否在qwertyuiopasdfghjklzxcvbnm1234567890之间,顺便把flag的前四个字符赋值给v5
v5 = (__int128 *)operator new(5ui64);v6 = *(_QWORD *)&Code;v7 = v5;v8 = 0;v9 = v5;do{v10 = *((_BYTE *)v9 + (char *)flag - (char *)v5);v11 = 0;*(_BYTE *)v9 = v10;v12 = 0i64;v13 = -1i64;do++v13;while ( *(_BYTE *)(v6 + v13) );if ( v13 ){do{if ( v10 == *(_BYTE *)(v6 + v12) )break;++v11;++v12;}while ( v11 < v13 );}v14 = -1i64;do++v14;while ( *(_BYTE *)(v6 + v14) );if ( v11 == v14 )_exit(v6);v9 = (__int128 *)((char *)v9 + 1);}while ( (char *)v9 - (char *)v5 < 4 );
将v5扩展成16位,不足补0,前四位应该是 ‘flag’,补完后就是 ‘flag000000000000’
v30 = *v7;while ( *((_BYTE *)&v30 + v15) ){if ( !*((_BYTE *)&v30 + v15 + 1) ){++v15;break;}if ( !*((_BYTE *)&v30 + v15 + 2) ){v15 += 2i64;break;}if ( !*((_BYTE *)&v30 + v15 + 3) ){v15 += 3i64;break;}v15 += 4i64;if ( v15 >= 0x10 )break;}for ( i = v15 + 1; i < 0x10; ++i )*((_BYTE *)&v30 + i) = 0;
这一段就是给输入的flag进行xxtea加密,前面扩展的v5就是它的秘钥,然后再变换位置
v17 = sub_7FF7A9871AB0((__int64)flag, v3, (unsigned __int8 *)&v30, &Size);// tea加密v18 = Size;v19 = v17;v20 = operator new(Size);v21 = 1;*v20 = v19[2];v22 = v20 + 1;v20[1] = *v19;v20[2] = v19[3];v20[3] = v19[1];v20[4] = v19[6];v20[5] = v19[4];v20[6] = v19[7];v20[7] = v19[5];v20[8] = v19[10];v20[9] = v19[8];v20[10] = v19[11];v20[11] = v19[9];v20[12] = v19[14];v20[13] = v19[12];v20[14] = v19[15];v20[15] = v19[13];v20[16] = v19[18];v20[17] = v19[16];v20[18] = v19[19];v20[19] = v19[17];v20[20] = v19[22];v20[21] = v19[20];v20[22] = v19[23];
xxtea里面还有一段拆分的代码,将32位的数拆分成4个8位的数
if ( v40 ){do{v42[v13] = v11[v13 >> 2] >> (8 * (v13 & 3));++v13;}while ( v13 < v40 );}
异或
for ( v20[23] = v19[21]; v21 < v18; ++v22 ){v23 = 0i64;if ( v21 / 3 > 0 ){v24 = *v22;do{v24 ^= v20[v23++]; // 与前面的数异或*v22 = v24;}while ( v23 < v21 / 3 );}++v21;}
变换后的字符串要等于v30中的字符串
*(_QWORD *)&v30 = 0xC0953A7C6B40BCCEui64;v25 = v20 - (_BYTE *)&v30;*((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;v26 = 0i64;v31 = 0xC8021823;v32 = 0xFA5656E7;do{if ( *((_BYTE *)&v30 + v26) != *((_BYTE *)&v30 + v26 + v25) )_exit(v8 * v8);++v8;++v26;}while ( v26 < 24 );
梳理下:
输入flag->取前四位扩展成16位作秘钥-> xxtea加密->拆分 ->移位 ->异或
然后写脚本挨个逆就行,先异或
int v20[] = { 0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,0xE7, 0x56, 0x56, 0xFA};for(int v22 = 23,v21 = 23; v21 >= 1; v22--){int v23 = 0;if( v21 / 3 > 0){//int v24 = v20[v22];do{//v24 ^= v20[v23 ++];//v20[v22] = v24;v20[v22] ^= v20[v23++];}while(v23 < v21 / 3);}--v21;}
移位
int v19[25] = {0};v19[0] = v20[1];v19[2] = v20[0];v19[3] = v20[2];v19[1] = v20[3];v19[6] = v20[4];v19[4] = v20[5];v19[7] = v20[6];v19[5] = v20[7];v19[10] = v20[8];v19[8] = v20[9];v19[11] = v20[10];v19[9] = v20[11];v19[14] = v20[12];v19[12] = v20[13];v19[15] = v20[14];v19[13] = v20[15];v19[18] = v20[16];v19[16] = v20[17];v19[19] = v20[18];v19[17] = v20[19];v19[22] = v20[20];v19[20] = v20[21];v19[23] = v20[22];v19[21] = v20[23];
合并
unsigned int flag[10] = {0};for(int i = 0 ; i < 0x18 ; i++){//printf("%d, %d\n",i , 4 * (i / 4 + 1) - (i % 4) - 1);flag[i >>2] <<= 8;flag[i >> 2] += v19[4 * (i / 4 + 1) - i % 4 - 1];}
xxtea解密
xxtea秘钥是4个32位数,小端排序
#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647int key[5] = {0x67616c66,0x00,0x00,0x00};unsigned int sum = 0 , n = 6;int rounds = 52 / n + 6;int i,j,k;unsigned int z,y,e,p;rounds = 6 + 52/n;sum = rounds * DELTA * (-1);y = flag[0];do{// if(rounds < 0) break;e = (sum >> 2) & 3;for (p=n-1; p>0; p--){z = flag[p-1];//y = v2[p] -= ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));y = flag[p] -= MX;printf("p = %d\n",p);}z = flag[n-1];//y = v2[0] -= ((v2[0] ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * v2[0]) ^ (z >> 5)) + ((v2[0] >> 3) ^ (16 * z)));y = flag[0] -= MX;sum += DELTA;printf("rounds = %d\n",rounds);}while(--rounds);
总代码
#include
#include
#include
#include
#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647int main()
{int v20[] = { 0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,0xE7, 0x56, 0x56, 0xFA};int key[5] = {0x67616c66,0x00,0x00,0x00};for(int v22 = 23,v21 = 23; v21 >= 1; v22--){int v23 = 0;if( v21 / 3 > 0){do{v20[v22] ^= v20[v23++];}while(v23 < v21 / 3);}--v21;}int v19[25] = {0};v19[0] = v20[1];v19[2] = v20[0];v19[3] = v20[2];v19[1] = v20[3];v19[6] = v20[4];v19[4] = v20[5];v19[7] = v20[6];v19[5] = v20[7];v19[10] = v20[8];v19[8] = v20[9];v19[11] = v20[10];v19[9] = v20[11];v19[14] = v20[12];v19[12] = v20[13];v19[15] = v20[14];v19[13] = v20[15];v19[18] = v20[16];v19[16] = v20[17];v19[19] = v20[18];v19[17] = v20[19];v19[22] = v20[20];v19[20] = v20[21];v19[23] = v20[22];v19[21] = v20[23];unsigned int flag[10] = {0};for(int i = 0 ; i < 0x18 ; i++){//printf("%d, %d\n",i , 4 * (i / 4 + 1) - (i % 4) - 1);flag[i >>2] <<= 8;flag[i >> 2] += v19[4 * (i / 4 + 1) - i % 4 - 1];}unsigned int sum = 0 , n = 6;int rounds = 52 / n + 6;int i,j,k;unsigned int z,y,e,p;//xxtearounds = 6 + 52/n;sum = rounds * DELTA * (-1);y = flag[0];do{// if(rounds < 0) break;e = (sum >> 2) & 3;for (p=n-1; p>0; p--){z = flag[p-1];y = flag[p] -= MX;}z = flag[n-1];y = flag[0] -= MX;sum += DELTA;}while(--rounds);//输出char *tmp = flag;for(int i = 0 ; i < 19 ; i++){printf("%c",*tmp++);}return 0;
}
输出

最终flag:flag{CXX_and_++tea}