exchange

这一部分经过动调后发现是将输入的每两个字节转为hex,再转为四字节字符串,每四字节的中间两位交换

跟进,上图可以看到v4 = 8
所以根据判断,只执行这一部分

美化

跟进

这俩函数算一个,都是keyinit
跟进
int64 __fastcall sub_7FF6AE812BD0(__int64 key, __int16 a2)
{
char *v2; // rdi
__int64 i; // rcx
char v4; // al
char v5; // al
char v7[32]; // [rsp+0h] [rbp-20h] BYREF
char v8; // [rsp+20h] [rbp+0h] BYREF
int round; // [rsp+24h] [rbp+4h]
int j; // [rsp+44h] [rbp+24h]
int v11; // [rsp+64h] [rbp+44h]
int v12; // [rsp+84h] [rbp+64h]
int v13; // [rsp+A4h] [rbp+84h]
char v14[168]; // [rsp+C8h] [rbp+A8h]
int v15[81]; // [rsp+170h] [rbp+150h] BYREF
BOOL v16; // [rsp+2B4h] [rbp+294h]
v2 = &v8;
for ( i = 122i64; i; --i )
{
*(_DWORD *)v2 = -858993460;
v2 += 4;
}
sub_7FF6AE8113CA((__int64)&unk_7FF6AE8260A6);
for ( j = 0; j < 56; ++j ) //PC1置换
{
v11 = PC1_Table[j];
v12 = v11 & 7;
v16 = (bytebit[v11 & 7] & *(unsigned __int8 *)(key + (v11 >> 3))) != 0;
v14[j] = v16;
}
for ( round = 0; round < 16; ++round ) //16轮的密钥扩展
{
if ( a2 == 1 )
v12 = 2 * (15 - round);
else
v12 = 2 * round;
v13 = v12 + 1;
v15[v12 + 1] = 0;
v15[v12] = 0; //前半位移
for ( j = 0; j < 28; ++j )
{
v11 = totrot[round] + j;
if ( v11 >= 28 )
v4 = v14[v11 - 28];
else
v4 = v14[v11];
v14[j + 80] = v4;
}
for ( j = 28; j < 56; ++j )
{
v11 = totrot[round] + j;
if ( v11 >= 56 )
v5 = v14[v11 - 28];
else
v5 = v14[v11];
v14[j + 80] = v5;
} //后半位移
for ( j = 0; j < 24; ++j )
{
if ( v14[pc2[j] + 80] )
v15[v12] |= bigbyte[j];
if ( v14[pc2[j + 24] + 80] )
v15[v13] |= bigbyte[j];
}
} //pc2置换
sub_7FF6AE811B80(v15);
return sub_7FF6AE81135C((__int64)v7, (__int64)&unk_7FF6AE81CE80);
}
上面是对key的初始化,每一步已经用注释标出来
再跟进encrypt函数,可以看见交换特征
接着是加密函数
_DWORD *__fastcall sub_7FF6AE812510(unsigned int *a1, _DWORD *a2)
{
_DWORD *result; // rax
int v3; // [rsp+24h] [rbp+4h]
int v4; // [rsp+24h] [rbp+4h]
unsigned int v5; // [rsp+44h] [rbp+24h]
int v6; // [rsp+44h] [rbp+24h]
int v7; // [rsp+44h] [rbp+24h]
int v8; // [rsp+44h] [rbp+24h]
unsigned int v9; // [rsp+44h] [rbp+24h]
unsigned int v10; // [rsp+44h] [rbp+24h]
unsigned int v11; // [rsp+44h] [rbp+24h]
unsigned int v12; // [rsp+44h] [rbp+24h]
unsigned int v13; // [rsp+44h] [rbp+24h]
unsigned int v14; // [rsp+44h] [rbp+24h]
int v15; // [rsp+44h] [rbp+24h]
int v16; // [rsp+44h] [rbp+24h]
int v17; // [rsp+44h] [rbp+24h]
unsigned int v18; // [rsp+64h] [rbp+44h]
int v19; // [rsp+64h] [rbp+44h]
unsigned int v20; // [rsp+64h] [rbp+44h]
unsigned int v21; // [rsp+64h] [rbp+44h]
unsigned int v22; // [rsp+64h] [rbp+44h]
unsigned int v23; // [rsp+64h] [rbp+44h]
int v24; // [rsp+64h] [rbp+44h]
int v25; // [rsp+64h] [rbp+44h]
int v26; // [rsp+64h] [rbp+44h]
int v27; // [rsp+64h] [rbp+44h]
unsigned int v28; // [rsp+64h] [rbp+44h]
unsigned int v29; // [rsp+84h] [rbp+64h]
int v30; // [rsp+84h] [rbp+64h]
int v31; // [rsp+84h] [rbp+64h]
int v32; // [rsp+84h] [rbp+64h]
unsigned int v33; // [rsp+84h] [rbp+64h]
unsigned int v34; // [rsp+84h] [rbp+64h]
unsigned int v35; // [rsp+84h] [rbp+64h]
int v36; // [rsp+84h] [rbp+64h]
int v37; // [rsp+84h] [rbp+64h]
int i; // [rsp+A4h] [rbp+84h]
_DWORD *v41; // [rsp+1A8h] [rbp+188h]
sub_7FF6AE8113CA(byte_7FF6AE8260A6);
v18 = a1[1];
v5 = (v18 ^ (*a1 >> 4)) & 0xF0F0F0F;
v19 = v5 ^ v18;
v29 = (16 * v5) ^ *a1;
v6 = (unsigned __int16)(v19 ^ HIWORD(v29));
v20 = v6 ^ v19;
v30 = (v6 << 16) ^ v29;
v7 = (v30 ^ (v20 >> 2)) & 0x33333333;
v31 = v7 ^ v30;
v21 = (4 * v7) ^ v20;
v8 = (v31 ^ (v21 >> 8)) & 0xFF00FF;
v32 = v8 ^ v31;
v22 = (((v8 << 8) ^ v21) >> 31) | (2 * ((v8 << 8) ^ v21));
v9 = (v22 ^ v32) & 0xAAAAAAAA;
v23 = v9 ^ v22;
v33 = ((v9 ^ v32) >> 31) | (2 * (v9 ^ v32)); //E盒扩展
for ( i = 0; i < 8; ++i )
{
v10 = *a2 ^ ((v23 >> 4) | (v23 << 28));
v41 = a2 + 1;
v3 = dword_7FF6AE820100[HIBYTE(v10) & 0x3F] | dword_7FF6AE820300[HIWORD(v10) & 0x3F] | dword_7FF6AE820500[(v10 >> 8) & 0x3F] | dword_7FF6AE820700[v10 & 0x3F];
v11 = *v41++ ^ v23;
v33 ^= dword_7FF6AE820200[HIBYTE(v11) & 0x3F] | dword_7FF6AE820400[HIWORD(v11) & 0x3F] | dword_7FF6AE820600[(v11 >> 8) & 0x3F] | dword_7FF6AE820800[v11 & 0x3F] | v3;
v12 = *v41++ ^ ((v33 >> 4) | (v33 << 28));
v4 = dword_7FF6AE820100[HIBYTE(v12) & 0x3F] | dword_7FF6AE820300[HIWORD(v12) & 0x3F] | dword_7FF6AE820500[(v12 >> 8) & 0x3F] | dword_7FF6AE820700[v12 & 0x3F];
v13 = *v41 ^ v33;
a2 = v41 + 1;
v23 ^= dword_7FF6AE820200[HIBYTE(v13) & 0x3F] | dword_7FF6AE820400[HIWORD(v13) & 0x3F] | dword_7FF6AE820600[(v13 >> 8) & 0x3F] | dword_7FF6AE820800[v13 & 0x3F] | v4;
} //S盒置换
v24 = (v23 >> 1) | (v23 << 31);
v14 = (v24 ^ v33) & 0xAAAAAAAA;
v25 = v14 ^ v24;
v34 = ((v14 ^ v33) >> 1) | ((v14 ^ v33) << 31);
v15 = (v25 ^ (v34 >> 8)) & 0xFF00FF;
v26 = v15 ^ v25;
v35 = (v15 << 8) ^ v34;
v16 = (v26 ^ (v35 >> 2)) & 0x33333333;
v27 = v16 ^ v26;
v36 = (4 * v16) ^ v35;
v17 = (unsigned __int16)(v36 ^ HIWORD(v27));
v37 = v17 ^ v36;
v28 = (v17 << 16) ^ v27;
*a1 = (16 * ((v37 ^ (v28 >> 4)) & 0xF0F0F0F)) ^ v28;
result = a1 + 1;
a1[1] = (v37 ^ (v28 >> 4)) & 0xF0F0F0F ^ v37; //P盒置换
return result;
}
DES的加密流程画了一个图,助于理解
最后网上脚本是有但是改了太多,这道题连E表和P表都没有
只能用wp的脚本,或者patch调用没删的dec函数
解出333936147332632923d96353321d3345636826d26314621d3349330463126348
写个脚本
得出flag
conforand
这题需要看函数,函数框里寥寥几个函数,rc4,rand
再交叉引用rand,发现再init函数里,并不是用来加密输入的
由此猜想可能有对称性
patch byte,换成output
经过调试发现每次加密结果都不一样,应该是每次的Sbox不同
通过随机加密key生成的随机的Sbox对输入加密,应该爆破种子,动调行不通。。
看了liv的wp,方法实在学不会。。
只能老老实实用D810去部分混淆,写脚本
手搓脚本
#include<stdio.h>
\#include<string.h>
\#include<stdlib.h>
\#include<stdint.h>
\#include<math.h>
int initsbox(unsigned char s[], unsigned char key[], unsigned int randnum) {
int i, j;
char k[256] = {0};
unsigned char tmp;
for (i = 0; i < 257; i++) {
• s[i] = i;
• k[i] = key[i % 9] ^ randnum;
}
for (i = 0; i < 257; i++) {
• j = (j + s[i] + k[i]) % 257;
• tmp = s[i];
• s[i] = s[j];
• s[j] = tmp;
}
return 0;
}
int main() {
for (unsigned int randnum = 0; randnum < 300; randnum++) {
• unsigned char sbox[256];
• unsigned char key[] = "JustDoIt!";
•
• // for (int i = 0; i < 9; i++)
• // {
• // key[i]^=randnum;
• // }
•
• initsbox(sbox, key, randnum);
• unsigned int Data[] = {
• 0x83, 0x1e, 0x9c, 0x48, 0x7a, 0xfa, 0xe8, 0x88, 0x36, 0xd5, 0x0a, 0x08, 0xf6, 0xa7, 0x70, 0x0f,
• 0xfd, 0x67, 0xdd, 0xd4, 0x3c, 0xa7, 0xed, 0x8d, 0x51, 0x10, 0xce, 0x6a, 0x9e, 0x56, 0x57, 0x83,
• 0x56, 0xe7, 0x67, 0x9a, 0x67, 0x22, 0x24, 0x6e, 0xcd, 0x2f
• };
• unsigned long k = 0;
• unsigned char tmp;
• int i = 0, j = 0, t = 0;
• for (k = 0; k < sizeof(Data) / sizeof(Data[0]); k++) {
• i = (i + 1) % 257;
• j = (j + sbox[i]) % 257;
• sbox[i] = sbox[j];
• sbox[j] = sbox[i];
• t = (sbox[i] + sbox[j]) % 257;
• Data[k] ^= sbox[t];
• }
• for (int i = 0; i < sizeof(Data) / sizeof(Data[0]); i++) {
• printf("%c", (unsigned char)Data[i]);
• }
• putchar('\n');
}
return 0;
}
终于出了
RandomSystem
函数分析
开头这两个函数可以静态分析
puts("Welcome to HZNUCTF!!!\n", v4);
puts("Enter something: \n", v5);
sub_9E1037("%64s", v29);
BinaryToHex(v29, v28);
ReverseAndCut(v28[0], v28[1], &v23);
也可以查看TLS回调函数,初始化线程本地存储
输入的内容为str的二进制
动调得seed
![]()
得Str
得key

去除花指令 注释每个加密过程,去除步骤见### 花指令去除
__int64 sub_9E2370()
{
int v0; // edx
int v1; // eax
__int64 v3; // [esp-8h] [ebp-78Ch]
char v4; // [esp+0h] [ebp-784h]
char v5; // [esp+0h] [ebp-784h]
char v6; // [esp+0h] [ebp-784h]
char v7; // [esp+0h] [ebp-784h]
char v8; // [esp+0h] [ebp-784h]
int m; // [esp+250h] [ebp-534h]
int k; // [esp+25Ch] [ebp-528h]
unsigned int v11; // [esp+268h] [ebp-51Ch]
int j; // [esp+274h] [ebp-510h]
char v13; // [esp+283h] [ebp-501h]
int i; // [esp+298h] [ebp-4ECh]
int key[34]; // [esp+2A4h] [ebp-4E0h] BYREF
char Str[20]; // [esp+32Ch] [ebp-458h] BYREF
int v17[66]; // [esp+340h] [ebp-444h] BYREF
int v18[66]; // [esp+448h] [ebp-33Ch] BYREF
int sqr[66]; // [esp+550h] [ebp-234h] BYREF
int Destination[24]; // [esp+658h] [ebp-12Ch] BYREF
char input; // [esp+6B8h] [ebp-CCh] BYREF
char Source[76]; // [esp+6C0h] [ebp-C4h] BYREF
int v23; // [esp+70Ch] [ebp-78h] BYREF
int v24; // [esp+710h] [ebp-74h]
int v25; // [esp+714h] [ebp-70h]
int v26; // [esp+718h] [ebp-6Ch]
char v27; // [esp+71Ch] [ebp-68h]
int v28[4]; // [esp+728h] [ebp-5Ch] BYREF
char v29[72]; // [esp+738h] [ebp-4Ch] BYREF
int savedregs; // [esp+784h] [ebp+0h] BYREF
sub_9E137A(&unk_9EE0A9);
v23 = 0;
v24 = 0;
v25 = 0;
v26 = 0;
v27 = 0;
j_memset(sqr, 0, 256u);
j_memset(v18, 0, 256u);
strcpy(Str, "KeYkEy!!");
v17[0] = 0x178;
v17[1] = 0x164;
v17[2] = 0xA9;
v17[3] = 0x1F5;
v17[4] = 0x115;
v17[5] = 0x149;
v17[6] = 0x8B;
v17[7] = 342;
v17[8] = 380;
v17[9] = 0x16D;
v17[10] = 162;
v17[11] = 258;
v17[12] = 381;
v17[13] = 339;
v17[14] = 347;
v17[15] = 307;
v17[16] = 263;
v17[17] = 359;
v17[18] = 162;
v17[19] = 484;
v17[20] = 310;
v17[21] = 333;
v17[22] = 346;
v17[23] = 339;
v17[24] = 150;
v17[25] = 194;
v17[26] = 175;
v17[27] = 344;
v17[28] = 158;
v17[29] = 250;
v17[30] = 128;
v17[31] = 175;
v17[32] = 158;
v17[33] = 173;
v17[34] = 152;
v17[35] = 379;
v17[36] = 158;
v17[37] = 292;
v17[38] = 130;
v17[39] = 365;
v17[40] = 197;
v17[41] = 20;
v17[42] = 197;
v17[43] = 161;
v17[44] = 198;
v17[45] = 10;
v17[46] = 207;
v17[47] = 244;
v17[48] = 202;
v17[49] = 14;
v17[50] = 204;
v17[51] = 176;
v17[52] = 193;
v17[53] = 255;
v17[54] = 35;
v17[55] = 7;
v17[56] = 158;
v17[57] = 181;
v17[58] = 145;
v17[59] = 353;
v17[60] = 153;
v17[61] = 357;
v17[62] = 0xF6;
v17[63] = 0x97;
puts("Welcome to HZNUCTF!!!\n", v4);
puts("Enter something: \n", v5);
sub_9E1037("%64s", (char)v29);
sub_9E1339(v29, v28);
sub_9E128F(v28[0], v28[1], &v23);
if ( (char)v23 == '5'
&& SBYTE1(v23) == '2'
&& SBYTE2(v23) == '6'
&& SHIBYTE(v23) == '5'
&& (char)v24 == '5'
&& SBYTE1(v24) == '6'
&& SBYTE2(v24) == '6'
&& SHIBYTE(v24) == '5'
&& (char)v25 == '5'
&& SBYTE1(v25) == '2'
&& SBYTE2(v25) == '6'
&& SHIBYTE(v25) == '5'
&& (char)v26 == '5'
&& SBYTE1(v26) == '3'
&& SBYTE2(v26) == '6'
&& SHIBYTE(v26) == '5' )
{
puts("good_job!!!\n", v6);
puts("So, Plz input the flag:\n", v7);
sub_9E1037("%73s", (char)&input);
strncpy_s((char *)Destination, 65u, Source, 64u);
sub_9E127B();
srand(Seed);
sub_9E127B();
j_memset(key, 0, 128u);
for ( i = 0; i < 32; ++i )
{
do
{
rand();
v1 = sub_9E127B() % 32;
v13 = 1;
for ( j = 0; j < i; ++j )
{
if ( key[j] == v1 )
{
v13 = 0;
break;
}
}
}
while ( !v13 );
key[i] = v1;
} // 生成32个随机数
sub_9E105F((char *)Destination, key); // 32次用key对半置换矩阵
//
copy(sqr, Destination);
sub_9E1334((char *)&v23, (int)Str); // 合并生成str ReVeReSe
sub_9E12DA((int *)asc_9EC368, sqr, v18); // 矩阵相乘
v11 = 0;
for ( k = 0; k < 8; ++k )
{
for ( m = 0; m < 8; ++m )
{
v18[8 * k + m] ^= Str[v11 % j_strlen(Str)];// 8
// 用str加密
++v11;
}
}
if ( sqr_cmp(v18, v17) == 1 )
puts("Congratulation!!!\n", v8);
}
else
{
puts("wrong_wrong!!!\n", v6);
}
sub_9E120D(&savedregs, &dword_9E2D48, 0, v0);
return v3;
}
逆向第一步,解密数v18
#include<stdio.h>
int main(){
unsigned int v17[64];
unsigned int res[8][8];
unsigned char str[] = "ReVeReSe";
v17[0] = 376;
v17[1] = 356;
v17[2] = 169;
v17[3] = 501;
v17[4] = 277;
v17[5] = 329;
v17[6] = 139;
v17[7] = 342;
v17[8] = 380;
v17[9] = 365;
v17[10] = 162;
v17[11] = 258;
v17[12] = 381;
v17[13] = 339;
v17[14] = 347;
v17[15] = 307;
v17[16] = 263;
v17[17] = 359;
v17[18] = 162;
v17[19] = 484;
v17[20] = 310;
v17[21] = 333;
v17[22] = 346;
v17[23] = 339;
v17[24] = 150;
v17[25] = 194;
v17[26] = 175;
v17[27] = 344;
v17[28] = 158;
v17[29] = 250;
v17[30] = 128;
v17[31] = 175;
v17[32] = 158;
v17[33] = 173;
v17[34] = 152;
v17[35] = 379;
v17[36] = 158;
v17[37] = 292;
v17[38] = 130;
v17[39] = 365;
v17[40] = 197;
v17[41] = 20;
v17[42] = 197;
v17[43] = 161;
v17[44] = 198;
v17[45] = 10;
v17[46] = 207;
v17[47] = 244;
v17[48] = 202;
v17[49] = 14;
v17[50] = 204;
v17[51] = 176;
v17[52] = 193;
v17[53] = 255;
v17[54] = 35;
v17[55] = 7;
v17[56] = 158;
v17[57] = 181;
v17[58] = 145;
v17[59] = 353;
v17[60] = 153;
v17[61] = 357;
v17[62] = 246;
v17[63] = 151;
int matrix[8][8] = {
{1, 1, 0, 1, 0, 0, 1, 0},
{0, 1, 1, 0, 0, 1, 0, 1},
{0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 0, 1, 0, 1, 0, 1},
{0, 1, 0, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 0, 0, 1}
}; //矩阵1
int k = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
res[i][k%8] = v17[i*8+j];
k++;
}
}
int cnt = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
res[i][j]^=str[cnt%8];
++cnt;
}
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
printf("%d ",res[i][j]);
}
putchar('\n');
} //v18
// int inv_matrix[8][8] = {
// 1 ,-4 ,1 ,-2, 0, 5, -2, 3 ,
// 0, 3, -1, 1 ,0, -3 ,1 ,-2 ,
// 0, -2 ,1 -1, 0, 2 -1, 2 ,
// 0, 0 ,0, 1,0 ,-1, 0, 0 ,
// 0, -4, 1, -1, 1 ,4, -2, 3 ,
// 0, 1 ,0, 0, 0, 0, 0, -1,
// 0, 1, 0 ,0, 0 ,-1, 1,-1 ,
// 0 ,-1 ,0, 0 ,0 ,1, 0 ,1
// };
}

查看asc_9EC368矩阵,256个,因为是每个元素int,32位
求逆矩阵
还原sqr

#include<stdio.h>
int main(){
unsigned char key[] =
{
27,
26,
25,
23,
28,
1,
6,
10,
20,
7,
15,
14,
31,
18,
19,
21,
9,
30,
22,
24,
8,
2,
29,
3,
12,
11,
17,
16,
0,
13,
5,
4,
};
int sqr[64] = {
102, 100 ,49, 49 ,118 ,53 ,54, 100 ,
52 ,53 ,52 ,114 ,54 ,102, 52, 97 ,
99 ,98 ,45 ,49 ,101, 97, 56, 100 ,
45,54 ,102 ,121 ,56 ,48, 55, 57 ,
53 ,97, 102, 56, 51 ,122, 102, 114 ,
98, 56, 45 ,99 ,100, 54, 99 ,100 ,
99, 50, 52 ,116, 99 ,97 ,55, 53 ,
53 ,57 ,102, 97 ,48, 57, 57, 45 ,
};
int tmp;
for (int i = 0; i <32; i++)
{
tmp = sqr[i];
sqr[i] = sqr[64 - key[i] - 1];
sqr[64 - key[i] - 1] = tmp;
}
for (int i = 0; i < 64; i++)
{
printf("%c",sqr[i]);
}
}
解出flag
花指令去除
第一个函数
去除后
第二个:


重新U P 生成函数
第三个:

U P生成函数
第四个:
和第三个一样

index
修改文件头
WASM , 基于二进制格式的可执行文件格式
用ghidra安装wasm反汇编插件,11.2版本
反汇编及美化如下
undefined4 unnamed_function_12(void)
{
int len;
undefined8 *inputflag [4];
undefined8 *inputkey;
int k;
int j;
int i;
byte Str [32];
undefined8 inputkey_;
undefined local_38;
undefined8 inputflag_;
undefined8 local_28;
undefined8 local_20;
undefined8 local_18;
undefined local_10;
undefined4 local_4;
local_4 = 0;
local_10 = 0;
local_18 = 0;
local_20 = 0;
local_28 = 0;
inputflag_ = 0;
local_38 = 0;
inputkey_ = 0;
Str[0x18] = 0;
Str[0x19] = 0;
Str[0x1a] = 0;
Str[0x1b] = 0;
Str[0x1c] = 0;
Str[0x1d] = 0;
Str[0x1e] = 0;
Str[0x1f] = 0;
Str[0x10] = 0;
Str[0x11] = 0;
Str[0x12] = 0;
Str[0x13] = 0;
Str[0x14] = 0;
Str[0x15] = 0;
Str[0x16] = 0;
Str[0x17] = 0;
Str[8] = 0;
Str[9] = 0;
Str[10] = 0;
Str[0xb] = 0;
Str[0xc] = 0;
Str[0xd] = 0;
Str[0xe] = 0;
Str[0xf] = 0;
Str[0] = 0;
Str[1] = 0;
Str[2] = 0;
Str[3] = 0;
Str[4] = 0;
Str[5] = 0;
Str[6] = 0;
Str[7] = 0;
puts(s_Welcome_to_HZNUCTF!!!_ram_000100ae,0);
puts(s_Plz_input_the_key:_ram_00010051,0);
inputkey = &inputkey_;
scanf(0x10026,&inputkey);
/* TGCTF404 */
len = cmp(&inputkey_,0x11020);
if (len == 0) {
xor0x51(&inputkey_);
puts(s_Ok,_let's_go!!!_ram_0001007a,0);
puts(s_Plz_input_the_flag:_ram_00010065,0);
inputflag[0] = &inputflag_;
scanf(0x10026,inputflag);
len = ::len(&inputflag_);
if (len == 0x20) {
randomenc(&inputflag_,Str);
for (i = 0; i < 8; i = i + 1) {
xorenc(Str + i * 4,&inputkey_);
}
for (j = 0; j < 8; j = j + 1) {
for (k = 0; k < 4; k = k + 1) {
if ((uint)Str[k + j * 4] != *(uint *)(j * 0x10 + 0x10fa0 + k * 4)) {
puts(s_wrong_wrong!!!_ram_00010042,0);
return 0;
}
}
}
puts(s_Congratulation!!!_ram_0001008b,0);
}
else {
puts(s_wrong_wrong!!!_ram_00010042,0);
}
}
else {
puts(s_wrong_wrong!!!_ram_0001009e,0);
}
return 0;
}
可以找到key是TGCTF404
主要加密函数有
xor0x51,randomenc,xorenc
跟进xorenc
void xorenc(int input,int key)
{
int high4;
uint low4;
undefined4 i;
byte local_15;
byte local_9;
high4 = (int)*(char *)(key + iRam00011200) >> 4;
low4 = (int)*(char *)(key + iRam00011200) & 0xf;
iRam00011200 = iRam00011200 + 1;
xor(0x10ea0,(int)*(char *)(high4 * 0x10 + 0x10da0 + low4));
for (i = 0; i < 4; i = i + 1) {
*(byte *)(input + i) =
*(byte *)(input + i) ^ *(byte *)(high4 * 0x10 + i * 0x11 + low4 + 0x10ea0);
*(byte *)(input + i) = *(byte *)(input + i) ^ *(byte *)(i + 0x11020);
}
return;
}
在0x10da0和0x10ea0地址发现两个256长度的加密盒
用加密后的key每字节的高四位和第四位作为行和列的索引用来异或
再跟进randomenc
void randomenc(int input,int str)
{
undefined4 j;
undefined4 i;
undefined4 k;
k = 0;
srand(404);
random_exchange(input,0x20);
for (i = 0; i < 8; i = i + 1) {
for (j = 0; j < 4; j = j + 1) {
*(undefined *)(str + i * 4 + j) = *(undefined *)(input + k);
k = k + 1;
}
}
return;
}
跟进random_exchange
void random_exchange(int param1,int param2)
{
undefined uVar1;
int iVar2;
byte local_11;
undefined4 i;
if (1 < param2) {
for (i = 0; i < param2 + -1; i = i + 1) {
iVar2 = rand();
iVar2 = i + iVar2 / (0x7fffffff / (param2 - i) + 1);
uVar1 = *(undefined *)(param1 + iVar2);
*(undefined *)(param1 + iVar2) = *(undefined *)(param1 + i);
*(undefined *)(param1 + i) = uVar1;
}
}
return;
}
用随机数生成索引进行置换
我们可以先把xorenc这个解出来
#include <stdio.h>
#include <stdlib.h>
int main() {
int k = 0;
char key0[] = "TGCTF404";
char flag[33];
char input[] = "TGCTF404";
int m = 0;
srand(404);
unsigned char box1[16][16] = {
{0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76},
{0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0},
{0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15},
{0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75},
{0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84},
{0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF},
{0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8},
{0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2},
{0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73},
{0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB},
{0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79},
{0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08},
{0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A},
{0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E},
{0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF},
{0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}
};
int box2[256] = {
0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
};
int str[8][4] = {
{0x84, 0x1c, 0x6b, 0xf7},
{0x49, 0x22, 0xd6, 0x42},
{0x50, 0x7b, 0x42, 0xf4},
{0x46, 0xa9, 0x83, 0x62},
{0xd1, 0x32, 0x80, 0x42},
{0x6a, 0x10, 0xa3, 0xf2},
{0xe2, 0xb8, 0x0b, 0x76},
{0xb0, 0xdc, 0x02, 0x51}
};
for (int i = 0; i < 8; i++) {
input[i] = (input[i] ^ 0x51) ;
}
for (int i = 0; i < 8; i++) {
char Char = input[k++];
int r = Char >> 4;
int l = (Char & 0x0F);
char tmp = box1[r][l];
for (int j = 0; j < 256; j++) {
box2[j] ^= tmp;
box2[j] &= 0xFF;
}
for (int j = 0; j < 4; j++) {
str[i][j] ^= box2[(r + j) * 16 + (l + j)];
str[i][j] ^= key0[j];
}
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++) {
flag[m++] = str[i][j] & 0xFF;
}
}
printf("%s", flag);
}
解出Z49H539c{--6}d4888bTUCf8NeFe--e9
再解randomenc,根据生成的rand数组进行倒序置换
遇到一个问题,原题是0x7fffffff写到脚本里生成不了随机数组
只有尝试到0x7fff时才可行,猜测时限制随机数位数的
#include<stdio.h>
#include<stdlib.h>
int main(){
srand(404);
for (int i = 0; i < 31; i++) {
int num = i + rand() / (0x7fff / (32 - i) + 1);
printf("%d ",num);
}
}
得出数组
1 24 28 24 16 25 22 29 29 12 17 19 31 13 18 19 30 31 27 25 24 30 29 25 28 27 29 27 30 29 30
置换脚本
#include<stdio.h>
#include<stdlib.h>
int main(){
char tmp;
char flag[] = "Z49H539c{--6}d4888bTUCf8NeFe--e9";
int num[] = {1, 24, 28, 24, 16, 25, 22, 29, 29, 12 ,17 ,19 ,31, 13, 18 ,19,30, 31, 27 ,25, 24 ,30, 29 ,25 ,28,27 ,29 ,27, 30, 29 ,30 };
for (int i = 30; i >=0; i--)
{
tmp = flag[i];
flag[i] = flag[num[i]];
flag[num[i]] = tmp;
}
for (int i = 0; i < 32; i++)
{
printf("%c",flag[i]);
}
}
得出flag HZNUCTF{f898-de85-46e-9e43-b9c8}

1万+

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



