[SCTF2019]creakme

知识点

  • AES加密
  • 反调试

看起来很麻烦,一步步慢慢看吧

主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
HMODULE v3; // eax
int v4; // eax
_DWORD *v5; // eax
unsigned int v6; // edx
_DWORD *v7; // ecx
unsigned int v8; // ebx
char *v9; // edi
unsigned int v10; // esi
unsigned int v11; // esi
bool v12; // cf
unsigned __int8 v13; // al
unsigned __int8 v14; // al
unsigned __int8 v15; // al
int v16; // esi
void *v17; // ecx
void *v18; // ecx
const char *v19; // edx
int v20; // eax
void *Block[5]; // [esp+10h] [ebp-70h] BYREF
unsigned int v23; // [esp+24h] [ebp-5Ch]
void *v24[5]; // [esp+28h] [ebp-58h] BYREF
unsigned int v25; // [esp+3Ch] [ebp-44h]
char Src[48]; // [esp+40h] [ebp-40h] BYREF
int v27; // [esp+7Ch] [ebp-4h]

v3 = GetModuleHandleW(0);
sub_402320(v3); // 判断.SCTF进行SMC操作
sub_4024A0(); // SMC后
v4 = sub_402870(std::cout, "welcome to 2019 sctf");
std::ostream::operator<<(v4, sub_402AC0);
sub_402870(std::cout, "please input your ticket:");
sub_402AF0(std::cin, Src);
v24[4] = 0;
v25 = 15;
LOBYTE(v24[0]) = 0;
sub_401D30(v24, Src, strlen(Src));
v27 = 0;
v5 = sub_4020D0(Block, (int)v24); // AES加密,CBC模式
v6 = strlen(aPvfqyc4ttc2uxr);
v7 = v5;
if ( v5[5] >= 0x10u )
v7 = (_DWORD *)*v5;
v8 = v5[4];
v9 = aPvfqyc4ttc2uxr;
v10 = v8;
if ( v6 < v8 )
v10 = v6;
v12 = v10 < 4;
v11 = v10 - 4;
if ( v12 )
{
LABEL_8:
if ( v11 == -4 )
goto LABEL_17;
}
else
{
while ( *v7 == *(_DWORD *)v9 ) // 输入的加密字符串与字符串aPvfqyc4ttc2uxr作比较
{
++v7;
v9 += 4;
v12 = v11 < 4;
v11 -= 4;
if ( v12 )
goto LABEL_8;
}
}
v12 = *(_BYTE *)v7 < (unsigned __int8)*v9;
if ( *(_BYTE *)v7 != *v9
|| v11 != -3
&& ((v13 = *((_BYTE *)v7 + 1), v12 = v13 < (unsigned __int8)v9[1], v13 != v9[1])
|| v11 != -2
&& ((v14 = *((_BYTE *)v7 + 2), v12 = v14 < (unsigned __int8)v9[2], v14 != v9[2])
|| v11 != -1 && (v15 = *((_BYTE *)v7 + 3), v12 = v15 < (unsigned __int8)v9[3], v15 != v9[3]))) )// if里都为0
{
v16 = v12 ? -1 : 1;
goto LABEL_18;
}
LABEL_17:
v16 = 0;
LABEL_18:
if ( !v16 )
{
if ( v6 <= v8 )
v16 = v6 < v8; // v6=v8
else
v16 = -1;
}
if ( v23 >= 0x10 )
{
v17 = Block[0];
if ( v23 + 1 >= 0x1000 )
{
v17 = (void *)*((_DWORD *)Block[0] - 1);
if ( (unsigned int)(Block[0] - v17 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn();
}
sub_402F05(v17);
}
v27 = -1;
Block[4] = 0;
v23 = 15;
LOBYTE(Block[0]) = 0;
if ( v25 >= 0x10 )
{
v18 = v24[0];
if ( v25 + 1 >= 0x1000 )
{
v18 = (void *)*((_DWORD *)v24[0] - 1);
if ( (unsigned int)(v24[0] - v18 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn();
}
sub_402F05(v18);
}
v19 = "Have fun!";
if ( v16 ) // v16=0
v19 = "A forged ticket!!";
v20 = sub_402870(std::cout, v19);
std::ostream::operator<<(v20, sub_402AC0);
system("pause");
return 0;
}

sub_402320 & sub_4024A0

void __thiscall sub_402320(_DWORD *this)
{
int v1; // eax
__int16 v2; // bx
const char *v3; // esi
int i; // edi
int v5; // eax

v1 = this[15];
v2 = *(_WORD *)((char *)this + v1 + 6);
v3 = (char *)this + v1 + 248;
for ( i = 0; i < v2; ++i )
{
v5 = strcmp(v3, ".SCTF");
if ( v5 )
v5 = v5 < 0 ? -1 : 1;
if ( !v5 )
{
DebugBreak(); // 反调试绕过
return;
}
v3 += 40;
}
}
int sub_4024A0()
{
void *v1; // [esp+10h] [ebp-20h]

v1 = NtCurrentPeb()->UnicodeCaseTableData;
if ( NtCurrentPeb()->BeingDebugged || v1 == (void *)112 )
exit(-5);
return ((int (*)(void))dword_404000[0])(); // smc修改的函数为sub_404000
}

观察到byte_404000为数据,却在函数中return,可以猜测为smc

那么直接进入动调环节,进入sub_402320函数jmp掉DebugBreak,继续执行到call 404000一直按F7,发现\>pvfqYc,4tTc2UxRmlJ,sB{Fh4Ck2:CFOb4ErhtIcoLo变为nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=

sub_4020D0

继续分析加密函数

void *__fastcall sub_4020D0(void *a1, int a2)
{
char *v2; // esi
int v3; // ebx
char *v4; // edx
int v5; // ecx
char v6; // al
int v7; // ecx
char v8; // si
int v9; // eax
char *v10; // edi
unsigned int v11; // ecx
char *v12; // edi
char v13; // bl
signed int v14; // ecx
char *v15; // esi
char *v16; // edx
signed int v17; // eax
int v19; // [esp-10h] [ebp-4B8h]
int v20; // [esp-Ch] [ebp-4B4h]
int v21; // [esp-8h] [ebp-4B0h]
int v22; // [esp-4h] [ebp-4ACh]
unsigned int v24; // [esp+14h] [ebp-494h]
size_t Size; // [esp+18h] [ebp-490h]
size_t Sizea; // [esp+18h] [ebp-490h]
char *Block; // [esp+1Ch] [ebp-48Ch]
unsigned int v28; // [esp+20h] [ebp-488h]
char *v29; // [esp+20h] [ebp-488h]
void **v30; // [esp+24h] [ebp-484h] BYREF
char v31; // [esp+28h] [ebp-480h]
int v32; // [esp+3ECh] [ebp-BCh]
size_t v33; // [esp+3F0h] [ebp-B8h]
int v34; // [esp+3F4h] [ebp-B4h]
char v35[128]; // [esp+418h] [ebp-90h] BYREF
int v36; // [esp+4A4h] [ebp-4h]

v2 = (char *)a2;
v28 = *(_DWORD *)(a2 + 16);
v3 = 16 * ((v28 >> 4) + 1);
v24 = v3;
Size = v3 + 1;
Block = (char *)unknown_libname_1(v3 + 1);
memset(Block, 0, v3 + 1);
if ( *((_DWORD *)v2 + 5) >= 0x10u )
v2 = *(char **)v2;
v4 = Block;
v5 = Block - v2;
do
{
v6 = *v2++;
v2[v5 - 1] = v6;
}
while ( v6 );
v7 = v28 & 0xF;
if ( 16 - v7 > 0 )
{
v8 = 16 - v7;
v9 = 16843009 * (unsigned __int8)(16 - v7);
v10 = &Block[16 * (v28 >> 4) + v7];
v4 = Block;
v11 = (unsigned int)(16 - v7) >> 2;
memset32(v10, v9, v11);
memset(&v10[4 * v11], v9, v8 & 3);
}
v4[v3] = 0;
v12 = (char *)unknown_libname_1(Size);
v29 = v12;
memset(v12, 0, Size);
v30 = &AES::`vftable';
v31 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v36 = 0;
sub_401690((int)&v30, v19, v20, v21, v22);
v13 = v31;
if ( v31 )
{
if ( v24 )
{
v14 = v33;
if ( !(v24 % v33) )
{
v15 = Block;
Sizea = 0;
if ( v24 / v33 )
{
while ( 1 )
{
v16 = v35;
if ( v13 )
{
v17 = 0;
if ( v14 > 0 )
{
do
*v16++ ^= v15[v17++]; // 自身字符串异或判断为CBC模式
while ( v17 < (int)v33 );
}
}
sub_4013E0(v35, v12);
memcpy(v35, v12, v33);
v14 = v33;
v15 += v33;
v12 += v33;
if ( ++Sizea >= v24 / v33 )
break;
v13 = v31;
}
}
v12 = v29;
}
}
}
sub_401A70(a1, v12, v24);
j_j_free(Block);
j_j_free(v12);
return a1;
}

sub_401690

改了一些数据类型

int __thiscall sub_401690(int this, int a2, int a3, int a4, int a5)
{
int *v5; // ebx
int v6; // eax
int v7; // eax
BOOL v8; // eax
int v9; // ecx
int v10; // esi
int v11; // eax
int v12; // ecx
int *v13; // edx
int v14; // edx
int *v15; // esi
unsigned __int8 *v16; // esi
int v17; // kr04_4
int *v18; // edx
int result; // eax
int *v20; // edi
int v21; // ebx
int v22; // eax
int v23; // edx
int v24; // ecx
int v25; // esi
int v26; // edi
int v27; // eax
int v28; // eax
int v29; // et2
int v30; // ecx
int v31; // edx
char *v32; // eax
int v33; // ecx
int *v34; // ecx
int v35; // edx
int v36; // eax
int *v37; // eax
int v38; // edx
int v39; // ecx
int v40; // edx
int *v41; // ecx
int v42; // eax
int *v43; // ecx
__int64 v44; // rax
__int64 v45; // rt2
int v46; // ecx
int *v47; // edx
int *v48; // esi
int v49; // edi
int v50; // edx
int v52; // [esp+Ch] [ebp-18h]
int v53; // [esp+Ch] [ebp-18h]
int v54; // [esp+10h] [ebp-14h]
int *v55; // [esp+10h] [ebp-14h]
int *v56; // [esp+14h] [ebp-10h]
int *v57; // [esp+14h] [ebp-10h]
int *v58; // [esp+18h] [ebp-Ch]
char *v59; // [esp+18h] [ebp-Ch]
int v60; // [esp+1Ch] [ebp-8h]
int v61; // [esp+20h] [ebp-4h]

v5 = (int *)this;
*(_DWORD *)(this + 972) = 16;
*(_DWORD *)(this + 968) = 16;
*(_OWORD *)(this + 980) = xmmword_407360;
memcpy((void *)(this + 1012), &xmmword_407360, *(_DWORD *)(this + 972));
v6 = v5[242];
if ( v6 == 16 )
{
v9 = v5[243];
if ( v9 == 16 )
{
v7 = 10;
goto LABEL_9;
}
v8 = v9 != 24;
}
else
{
if ( v6 != 24 )
{
v7 = 14;
goto LABEL_9;
}
v8 = v5[243] == 32;
}
v7 = 2 * v8 + 12;
LABEL_9:
v5[244] = v7;
v10 = 0;
v11 = v5[244];
v12 = v5[243] / 4;
v61 = v12;
if ( v11 >= 0 )
{
v13 = v5 + 2;
do
{
if ( v12 > 0 )
{
memset(v13, 0, 4 * v12);
v12 = v61;
}
v11 = v5[244];
++v10;
v13 += 8;
}
while ( v10 <= v11 );
}
v14 = 0;
if ( v11 >= 0 )
{
v15 = v5 + 122;
do
{
if ( v12 > 0 )
{
memset(v15, 0, 4 * v12);
v12 = v61;
}
v11 = v5[244];
++v14;
v15 += 8;
}
while ( v14 <= v11 );
}
v16 = "sycloversyclover";
v60 = v12 * (v11 + 1);
v17 = v5[242];
v18 = v5 + 261;
result = v17 / 4;
v20 = v5 + 261;
v54 = v17 / 4;
v56 = v5 + 261;
if ( v17 / 4 > 0 )
{
v21 = v17 / 4;
do
{
v22 = *v16;
v16 += 4;
v22 <<= 24;
*v20++ = v22;
v23 = v22 | (*(v16 - 3) << 16);
*(v20 - 1) = v23;
v24 = v23 | (*(v16 - 2) << 8);
*(v20 - 1) = v24;
result = v24 | *(v16 - 1);
*(v20 - 1) = result;
--v21;
}
while ( v21 );
v5 = (int *)this;
v12 = v61;
v18 = v56;
}
v25 = v17 / 4;
v26 = 0;
if ( v54 > 0 )
{
v58 = v18;
do
{
if ( v26 >= v60 )
goto LABEL_44;
v27 = v26++;
v29 = v27 % v12;
v28 = v27 / v12;
v5[8 * v28 + 2 + v29] = *v58;
v25 = v17 / 4;
v30 = v29 + 8 * (v5[244] - v28);
result = *v58;
v5[v30 + 122] = *v58;
v12 = v61;
++v58;
}
while ( v26 < v54 );
}
if ( v26 < v60 )
{
v59 = (char *)&unk_406B40;
do
{
v31 = v5[v25 + 260];
v32 = v59++;
v33 = (unsigned __int8)byte_405DE0[HIBYTE(v31)] ^ (((unsigned __int8)byte_405DE0[(unsigned __int8)v31] ^ (((unsigned __int8)byte_405DE0[BYTE1(v31)] ^ ((*v32 ^ byte_405DE0[BYTE2(v31)]) << 8)) << 8)) << 8);
result = (int)(v5 + 261);
v5[261] ^= v33;
if ( v25 == 8 )
{
v37 = v5 + 262;
v38 = 3;
do
{
v39 = *(v37++ - 1);
*(v37 - 1) ^= v39;
--v38;
}
while ( v38 );
v40 = 3;
v5[265] ^= (unsigned __int8)byte_405DE0[(unsigned __int8)v5[264]] ^ (((unsigned __int8)byte_405DE0[BYTE1(v5[264])] ^ (((unsigned __int8)byte_405DE0[(unsigned __int8)BYTE2(v5[264])] ^ (byte_405DE0[HIBYTE(v5[264])] << 8)) << 8)) << 8);
v41 = v5 + 266;
do
{
v42 = *(v41++ - 1);
*(v41 - 1) ^= v42;
--v40;
}
while ( v40 );
}
else
{
if ( v25 <= 1 )
goto LABEL_39;
v34 = v5 + 262;
v35 = v25 - 1;
do
{
v36 = *(v34++ - 1);
*(v34 - 1) ^= v36;
--v35;
}
while ( v35 );
}
result = (int)(v5 + 261);
LABEL_39:
v52 = 0;
if ( v25 > 0 )
{
v43 = (int *)result;
v57 = (int *)result;
while ( v26 < v60 )
{
v44 = v26++;
v45 = v44 % v61;
LODWORD(v44) = v44 / v61;
v5[8 * (_DWORD)v44 + 2 + (_DWORD)v45] = *v43;
v25 = v17 / 4;
v5[8 * (v5[244] - (_DWORD)v44) + 122 + (_DWORD)v45] = *v57;
result = v52 + 1;
v43 = v57 + 1;
v52 = result;
++v57;
if ( result >= v54 )
goto LABEL_43;
}
break;
}
LABEL_43:
;
}
while ( v26 < v60 );
}
LABEL_44:
v46 = 1;
v53 = 1;
if ( v5[244] <= 1 )
{
*((_BYTE *)v5 + 4) = 1;
}
else
{
result = v61;
v47 = v5 + 130;
v55 = v5 + 130;
do
{
if ( result > 0 )
{
v48 = v47;
v49 = result;
do
{
v50 = *v48++;
*(v48 - 1) = dword_406B60[(unsigned __int8)v50] ^ dword_4066E0[BYTE1(v50)] ^ dword_405EE0[BYTE2(v50)] ^ dword_406F60[HIBYTE(v50)];
--v49;
}
while ( v49 );
result = v61;
v46 = v53;
v47 = v55;
}
++v46;
v47 += 8;
v53 = v46;
v55 = v47;
}
while ( v46 < v5[244] );
*((_BYTE *)v5 + 4) = 1;
}
return result;
}

get_Flag

通过里面调用的函数名就可知为AES加密,通过以下代码,可知为CBC模式,然后找密码和偏移值

do
*v16++ ^= v15[v17++]; // 自身字符串异或判断为CBC模式
while ( v17 < (int)v33 );

密码为 v16 = “sycloversyclover”;

发现xmmword_407360

v5 = (int *)this;
*(_DWORD *)(this + 972) = 16;
*(_DWORD *)(this + 968) = 16;
*(_OWORD *)(this + 980) = xmmword_407360;
memcpy((void *)(this + 1012), &xmmword_407360, *(_DWORD *)(this + 972));
进入为
xmmword 66746373667463736674637366746373h
转为char,记得小端转大端,
sctfsctfsctfsctf

aes加密算法,CBC模式,密码为sycloversyclover,偏移量为sctfsctfsctfsctf,在线解密

flag{Ae3_C8c_I28_pKcs79ad4}