void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
__int64 v3[2]; // [rsp+10h] [rbp-10h] BYREF
v3[1] = __readfsqword(0x28u);
v3[0] = 0LL;
puts("Please input something:");
sub_CD1(v3);
sub_E0B(v3);
sub_F83(v3);
puts("And the flag is GWHT{true flag}");
exit(0);
}
unsigned __int64 __fastcall sub_CD1(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
*(_DWORD *)a1 = 0;
*(_DWORD *)(a1 + 4) = 18;
*(_DWORD *)(a1 + 8) = 0;
*(_DWORD *)(a1 + 12) = 0;
*(_QWORD *)(a1 + 16) = &unk_202060;
*(_BYTE *)(a1 + 24) = -15;
*(_QWORD *)(a1 + 32) = sub_B5F;
*(_BYTE *)(a1 + 40) = -14;
*(_QWORD *)(a1 + 48) = sub_A64;
*(_BYTE *)(a1 + 56) = -11;
*(_QWORD *)(a1 + 64) = sub_AC5;
*(_BYTE *)(a1 + 72) = -12;
*(_QWORD *)(a1 + 80) = sub_956;
*(_BYTE *)(a1 + 88) = -9;
*(_QWORD *)(a1 + 96) = sub_A08;
*(_BYTE *)(a1 + 104) = -8;
*(_QWORD *)(a1 + 112) = sub_8F0;
*(_BYTE *)(a1 + 120) = -10;
*(_QWORD *)(a1 + 128) = sub_99C;
qword_2022A8 = malloc(0x512uLL);
memset(qword_2022A8, 0, 0x512uLL);
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 __fastcall sub_E0B(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
*(_QWORD *)(a1 + 16) = &unk_202060;
while ( **(_BYTE **)(a1 + 16) != 0xF4 )
sub_E6E(a1);
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 sub_F83()
{
int i; // [rsp+Ch] [rbp-14h]
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
for ( i = 0; dword_2022A4 - 1 > i; ++i )
{
if ( *((_BYTE *)qword_2022A8 + i + 32) != aFzAmAmFmtSum[i] )
{
puts("WRONG!");
exit(0);
}
}
puts("Congratulation?");
puts("tips: input is the start");
return __readfsqword(0x28u) ^ v2;
}
sub_CD1
是自定义的VM, 先逆出所有指令
mov: E1, E2, E3, E4, E5, E7
unsigned __int64 __fastcall sub_B5F(__int64 a1)
{
int *v2; // [rsp+28h] [rbp-18h]
unsigned __int64 v3; // [rsp+38h] [rbp-8h]
v3 = __readfsqword(0x28u);
v2 = (int *)(*(_QWORD *)(a1 + 16) + 2LL);
switch ( *(_BYTE *)(*(_QWORD *)(a1 + 16) + 1LL) )
{
case 0xE1:
*(_DWORD *)a1 = *((char *)qword_2022A8 + *v2);
break;
case 0xE2:
*(_DWORD *)(a1 + 4) = *((char *)qword_2022A8 + *v2);
break;
case 0xE3:
*(_DWORD *)(a1 + 8) = *((char *)qword_2022A8 + *v2);
break;
case 0xE4:
*((_BYTE *)qword_2022A8 + *v2) = *(_DWORD *)a1;
break;
case 0xE5:
*(_DWORD *)(a1 + 12) = *((char *)qword_2022A8 + *v2);
break;
case 0xE7:
*((_BYTE *)qword_2022A8 + *v2) = *(_DWORD *)(a1 + 4);
break;
default:
break;
}
*(_QWORD *)(a1 + 16) += 6LL;
return __readfsqword(0x28u) ^ v3;
}
xor
unsigned __int64 __fastcall sub_A64(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
*(_DWORD *)a1 ^= *(_DWORD *)(a1 + 4);
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v2;
}
length check
unsigned __int64 __fastcall sub_AC5(__int64 a1)
{
const char *buf; // [rsp+10h] [rbp-10h]
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
buf = (const char *)qword_2022A8;
read(0, qword_2022A8, 0x20uLL);
length = strlen(buf);
if ( length != 21 )
{
puts("WRONG!");
exit(0);
}
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v3;
}
nop
unsigned __int64 __fastcall sub_956(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v2;
}
mul
unsigned __int64 __fastcall sub_A08(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
*(_DWORD *)a1 *= *(_DWORD *)(a1 + 12);
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v2;
}
swap
unsigned __int64 __fastcall sub_8F0(int *a1)
{
int v2; // [rsp+14h] [rbp-Ch]
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
v2 = *a1;
*a1 = a1[1];
a1[1] = v2;
++*((_QWORD *)a1 + 2);
return __readfsqword(0x28u) ^ v3;
}
special calculation
unsigned __int64 __fastcall sub_99C(__int64 a1)
{
unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readfsqword(0x28u);
*(_DWORD *)a1 = *(_DWORD *)(a1 + 8) + 2 * *(_DWORD *)(a1 + 4) + 3 * *(_DWORD *)a1;
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v2;
}
unk_202060
是操作码, 提取出来, 按照刚刚逆向分析出来的指令, 写脚本解析VM代码
这里a1
是eax, a1+4
是ebx, a1+8
是ecx, a1+12
是edx, a1+16
是eip
opcode = [
0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2D,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0F, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2F, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x10, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x30, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x13, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x33, 0x00, 0x00,
0x00, 0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF1,
0xE1, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x01, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x01, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x02, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x01, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x03, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x02, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x03, 0x00,
0x00, 0x00, 0xF1, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x03, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x05, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x04, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x05,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF1,
0xE2, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x08, 0x00, 0x00,
0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6, 0xF7, 0xF1,
0xE4, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00,
0x00, 0xF1, 0xE2, 0x08, 0x00, 0x00, 0x00, 0xF1, 0xE3, 0x09,
0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00, 0x00, 0xF6,
0xF7, 0xF1, 0xE4, 0x07, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08,
0x00, 0x00, 0x00, 0xF1, 0xE2, 0x09, 0x00, 0x00, 0x00, 0xF1,
0xE3, 0x0A, 0x00, 0x00, 0x00, 0xF1, 0xE5, 0x0C, 0x00, 0x00,
0x00, 0xF6, 0xF7, 0xF1, 0xE4, 0x08, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x13, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x13, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00,
0xF1, 0xE2, 0x12, 0x00, 0x00, 0x00, 0xF8, 0xF1, 0xE4, 0x0E,
0x00, 0x00, 0x00, 0xF1, 0xE7, 0x12, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE2, 0x11, 0x00, 0x00,
0x00, 0xF8, 0xF1, 0xE4, 0x0F, 0x00, 0x00, 0x00, 0xF1, 0xE7,
0x11, 0x00, 0x00, 0x00, 0xF4
]
i = 0
while i < len(opcode):
if (opcode[i] == 0xF1):
print('mov ', end='')
if (opcode[i + 1] == 0xE1):
print('eax ' + 'flag[' + str(opcode[i + 2]) + ']')
elif (opcode[i + 1] == 0xE2):
print('ebx ' + 'flag[' + str(opcode[i + 2]) + ']')
elif (opcode[i + 1] == 0xE3):
print('ecx ' + 'flag[' + str(opcode[i + 2]) + ']')
elif (opcode[i + 1] == 0xE4):
print('flag[' + str(opcode[i + 2]) + '] ' + 'eax')
elif (opcode[i + 1] == 0xE5):
print('edx ' + 'flag[' + str(opcode[i + 2]) + ']')
elif (opcode[i + 1] == 0xE7):
print('flag[' + str(opcode[i + 2]) + '] ' + 'ebx')
i += 6
elif (opcode[i] == 0xF2):
print('xor eax, ebx')
i += 1
elif (opcode[i] == 0xF5):
print('check length')
i += 1
elif (opcode[i] == 0xF4):
print('nop')
i += 1
elif (opcode[i] == 0xF7):
print('mul eax, edx')
i += 1
elif (opcode[i] == 0xF8):
print('swap eax, ebx')
i += 1
elif (opcode[i] == 0xF6):
print('mov eax, 3*eax + 2*ebx + ecx')
i += 1
else:
i += 1
得到vm指令序列, 第一段因为flag长度大于21, 所以不合法. 主要逻辑是第二段
# invalid code
check length
mov eax flag[0]
xor eax, ebx
mov flag[32] eax
mov eax flag[1]
xor eax, ebx
mov flag[33] eax
mov eax flag[2]
xor eax, ebx
mov flag[34] eax
mov eax flag[3]
xor eax, ebx
mov flag[35] eax
mov eax flag[4]
xor eax, ebx
mov flag[36] eax
mov eax flag[5]
xor eax, ebx
mov flag[37] eax
mov eax flag[6]
xor eax, ebx
mov flag[38] eax
mov eax flag[7]
xor eax, ebx
mov flag[39] eax
mov eax flag[8]
xor eax, ebx
mov flag[40] eax
mov eax flag[9]
xor eax, ebx
mov flag[41] eax
mov eax flag[10]
xor eax, ebx
mov flag[42] eax
mov eax flag[11]
xor eax, ebx
mov flag[43] eax
mov eax flag[12]
xor eax, ebx
mov flag[44] eax
mov eax flag[13]
xor eax, ebx
mov flag[45] eax
mov eax flag[14]
xor eax, ebx
mov flag[46] eax
mov eax flag[15]
xor eax, ebx
mov flag[47] eax
mov eax flag[16]
xor eax, ebx
mov flag[48] eax
mov eax flag[17]
xor eax, ebx
mov flag[49] eax
mov eax flag[18]
xor eax, ebx
mov flag[50] eax
mov eax flag[19]
xor eax, ebx
mov flag[51] eax
nop
# real code
check length
mov eax flag[0]
mov ebx flag[1]
xor eax, ebx
mov flag[0] eax
mov eax flag[1]
mov ebx flag[2]
xor eax, ebx
mov flag[1] eax
mov eax flag[2]
mov ebx flag[3]
xor eax, ebx
mov flag[2] eax
mov eax flag[3]
mov ebx flag[4]
xor eax, ebx
mov flag[3] eax
mov eax flag[4]
mov ebx flag[5]
xor eax, ebx
mov flag[4] eax
mov eax flag[5]
mov ebx flag[6]
xor eax, ebx
mov flag[5] eax
mov eax flag[6]
mov ebx flag[7]
mov ecx flag[8]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[6] eax
mov eax flag[7]
mov ebx flag[8]
mov ecx flag[9]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[7] eax
mov eax flag[8]
mov ebx flag[9]
mov ecx flag[10]
mov edx flag[12]
mov eax, 3*eax + 2*ebx + ecx
mul eax, edx
mov flag[8] eax
mov eax flag[13]
mov ebx flag[19]
swap eax, ebx
mov flag[13] eax
mov flag[19] ebx
mov eax flag[14]
mov ebx flag[18]
swap eax, ebx
mov flag[14] eax
mov flag[18] ebx
mov eax flag[15]
mov ebx flag[17]
swap eax, ebx
mov flag[15] eax
mov flag[17] ebx
nop
人工转等价python代码
flag = ''
for i in range(6)::
flag[i] = flag[i] ^ flag[i + 1]
flag[6] = (flag[8] + 2 * flag[7] + 3 * flag[6]) * flag[12]
flag[7] = (flag[9] + 2 * flag[8] + 3 * flag[7]) * flag[12]
flag[8] = (flag[10] + 2 * flag[9] + 3 * flag[8]) * flag[12]
swap(flag[13], flag[19])
swap(flag[14], flag[18])
swap(flag[15], flag[17])
拿到checklist, 然后逆回去, 注意这里伪代码有点问题, 看汇编来确认
checkval = [
0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72
]
checkval[13], checkval[19] = checkval[19], checkval[13]
checkval[14], checkval[18] = checkval[18], checkval[14]
checkval[15], checkval[17] = checkval[17], checkval[15]
check12 = checkval[12]
for i in range(128):
if checkval[8] == ((checkval[10] + 2 * checkval[9] + 3 * i) * check12) & 0xFF:
checkval[8] = i
for j in range(128):
if checkval[7] == ((checkval[9] + 2 * checkval[8] + 3 * j) * check12) & 0xFF:
checkval[7] = j
for k in range(128):
if checkval[6] == ((checkval[8] + 2 * checkval[7] + 3 * k) * check12) & 0xFF:
checkval[6] = k
for i in range(6)[::-1]:
checkval[i] ^= checkval[i + 1]
flag = ''
for i in range(len(checkval)):
flag += chr(checkval[i])
print('flag{{{}}}'.format(flag))
脱壳脚本 https://github.com/hluwa/FRIDA-DEXDump
脱壳之后拖进JEB打开, flag是明文形式存储…
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
char *v3; // rdi
__int64 i; // rcx
char v6; // [rsp+0h] [rbp-20h] BYREF
char v7[32]; // [rsp+30h] [rbp+10h]
char v8[184]; // [rsp+50h] [rbp+30h] BYREF
char v9[60]; // [rsp+108h] [rbp+E8h] BYREF
unsigned int v10[8]; // [rsp+144h] [rbp+124h] BYREF
int j; // [rsp+164h] [rbp+144h]
int v12; // [rsp+234h] [rbp+214h]
int v13; // [rsp+238h] [rbp+218h]
v3 = &v6;
for ( i = 150i64; i; --i )
{
*(_DWORD *)v3 = -858993460;
v3 += 4;
}
j___CheckForDebuggerJustMyCode(&unk_140023035, argv, envp);
v7[0] = 2;
v7[1] = 3;
v7[2] = 2;
v7[3] = 1;
v7[4] = 4;
v7[5] = 7;
v7[6] = 4;
v7[7] = 5;
v7[8] = 10;
v7[9] = 11;
v7[10] = 10;
v7[11] = 9;
v7[12] = 14;
v7[13] = 15;
v7[14] = 12;
v7[15] = 13;
v7[16] = 16;
v7[17] = 19;
v7[18] = 16;
v7[19] = 17;
v7[20] = 20;
v7[21] = 23;
v7[22] = 22;
v7[23] = 19;
v7[24] = 28;
v7[25] = 25;
v7[26] = 30;
v7[27] = 31;
v7[28] = 28;
v7[29] = 25;
v7[30] = 26;
v7[31] = 31;
qmemcpy(v8, "$!\"'$!\"#().+$-&/81:;4=>7092;<567HIBBDDFGHIJJMMONPPRSUTVWYYZ[\\]^^``ccdeggiikklmnnpprstuwwxy{{}}", 94);
v8[94] = 127;
v8[95] = 127;
v8[96] = -127;
v8[97] = -127;
v8[98] = -125;
v8[99] = -125;
v8[100] = -116;
v8[101] = -115;
v8[102] = -114;
v8[103] = -113;
v8[104] = -120;
v8[105] = -119;
v8[106] = -118;
v8[107] = -117;
v8[108] = -116;
v8[109] = -115;
v8[110] = -114;
v8[111] = -121;
v8[112] = -104;
v8[113] = -111;
v8[114] = -110;
v8[115] = -109;
v8[116] = -108;
v8[117] = -107;
v8[118] = -106;
v8[119] = -105;
v8[120] = -104;
v8[121] = -103;
v8[122] = -102;
v8[123] = -102;
v8[124] = -100;
v8[125] = -100;
v8[126] = -98;
v8[127] = -98;
v8[128] = -96;
v8[129] = -96;
v8[130] = -94;
v8[131] = -94;
v8[132] = -92;
v8[133] = -92;
v8[134] = -90;
v8[135] = -90;
v8[136] = -88;
v8[137] = -88;
v8[138] = -86;
v8[139] = -86;
v8[140] = -84;
v8[141] = -84;
v8[142] = -82;
v8[143] = -82;
v8[144] = -80;
v8[145] = -79;
v8[146] = -78;
v8[147] = -77;
memset(v9, 0, 0x1Fui64);
sub_140011159(std::cout, "flag format: SUCTF{xxxxxxxxxxxxxxx}\n");
sub_140011159(std::cout, "Please Input Key:");
std::istream::operator>>(std::cin, v10);
v10[0] %= 0x10000u;
v9[30] = 8;
while ( v9[30] )
{
--v9[30];
for ( j = 22; j; v9[j] |= v13 << v9[30] )
{
v12 = v7[22 * v9[30] + --j];
v13 = (v12 >> ((v10[0] >> (2 * v9[30])) & 3)) & 1;
}
}
sub_140011159(std::cout, v9);
system("pause");
return 0;
}
输入flag, 范围在0x10000之内, 直接爆破
/*
v186 %= 0x10000u;
v185 = 8;
while ( v185 )
{
--v185;
for ( j = 22; j; v184[j] |= v189 << v185 )
{
v188 = *(&v4 + 22 * v185 + --j);
v189 = (v188 >> ((v186 >> 2 * v185) & 3)) & 1;
}
}
*/
#include
#include
int v[500];
int v184[100];
int v188,v189;
void init();
int main() {
init();
for(int v186 = 0;v186 < 0x10000;v186++)
{
memset(v184,0,sizeof(v184));
int v185 = 8;
while ( v185 ) {
--v185;
for (int j = 22; j; v184[j] |= v189 << v185 ) {
v188 = v[22 * v185 + --j + 4];
v189 = (v188 >> ((v186 >> 2 * v185) & 3)) & 1;
}
}
// SUCTF{xxxxxxxxxxxxxxx}
if (v184[0] == 'S' &&
v184[1] == 'U' &&
v184[2] == 'C' &&
v184[3] == 'T' &&
v184[4] == 'F' &&
v184[5] == '{' &&
v184[21] == '}') {
printf("key : %d\n",v186);
for(int i = 0;i < 22;i++) {
printf("%c",v184[i]);
}
printf("\n");
}
}
return 0;
}
void init() {
v[4]= 2;
v[5]= 3;
v[6]= 2;
v[7]= 1;
v[8]= 4;
v[9]= 7;
v[10]= 4;
v[11]= 5;
v[12]= 10;
v[13]= 11;
v[14]= 10;
v[15]= 9;
v[16]= 14;
v[17]= 15;
v[18]= 12;
v[19]= 13;
v[20]= 16;
v[21]= 19;
v[22]= 16;
v[23]= 17;
v[24]= 20;
v[25]= 23;
v[26]= 22;
v[27]= 19;
v[28]= 28;
v[29]= 25;
v[30]= 30;
v[31]= 31;
v[32]= 28;
v[33]= 25;
v[34]= 26;
v[35]= 31;
v[36]= 36;
v[37]= 33;
v[38]= 34;
v[39]= 39;
v[40]= 36;
v[41]= 33;
v[42]= 34;
v[43]= 35;
v[44]= 40;
v[45]= 41;
v[46]= 46;
v[47]= 43;
v[48]= 36;
v[49]= 45;
v[50]= 38;
v[51]= 47;
v[52]= 56;
v[53]= 49;
v[54]= 58;
v[55]= 59;
v[56]= 52;
v[57]= 61;
v[58]= 62;
v[59]= 55;
v[60]= 48;
v[61]= 57;
v[62]= 50;
v[63]= 59;
v[64]= 60;
v[65]= 53;
v[66]= 54;
v[67]= 55;
v[68]= 72;
v[69]= 73;
v[70]= 66;
v[71]= 66;
v[72]= 68;
v[73]= 68;
v[74]= 70;
v[75]= 71;
v[76]= 72;
v[77]= 73;
v[78]= 74;
v[79]= 74;
v[80]= 77;
v[81]= 77;
v[82]= 79;
v[83]= 78;
v[84]= 80;
v[85]= 80;
v[86]= 82;
v[87]= 83;
v[88]= 85;
v[89]= 84;
v[90]= 86;
v[91]= 87;
v[92]= 89;
v[93]= 89;
v[94]= 90;
v[95]= 91;
v[96]= 92;
v[97]= 93;
v[98]= 94;
v[99]= 94;
v[100]= 96;
v[101]= 96;
v[102]= 99;
v[103]= 99;
v[104]= 100;
v[105]= 101;
v[106]= 103;
v[107]= 103;
v[108]= 105;
v[109]= 105;
v[110]= 107;
v[111]= 107;
v[112]= 108;
v[113]= 109;
v[114]= 110;
v[115]= 110;
v[116]= 112;
v[117]= 112;
v[118]= 114;
v[119]= 115;
v[120]= 116;
v[121]= 117;
v[122]= 119;
v[123]= 119;
v[124]= 120;
v[125]= 121;
v[126]= 123;
v[127]= 123;
v[128]= 125;
v[129]= 125;
v[130]= 127;
v[131]= 127;
v[132]= -127;
v[133]= -127;
v[134]= -125;
v[135]= -125;
v[136]= -116;
v[137]= -115;
v[138]= -114;
v[139]= -113;
v[140]= -120;
v[141]= -119;
v[142]= -118;
v[143]= -117;
v[144]= -116;
v[145]= -115;
v[146]= -114;
v[147]= -121;
v[148]= -104;
v[149]= -111;
v[150]= -110;
v[151]= -109;
v[152]= -108;
v[153]= -107;
v[154]= -106;
v[155]= -105;
v[156]= -104;
v[157]= -103;
v[158]= -102;
v[159]= -102;
v[160]= -100;
v[161]= -100;
v[162]= -98;
v[163]= -98;
v[164]= -96;
v[165]= -96;
v[166]= -94;
v[167]= -94;
v[168]= -92;
v[169]= -92;
v[170]= -90;
v[171]= -90;
v[172]= -88;
v[173]= -88;
v[174]= -86;
v[175]= -86;
v[176]= -84;
v[177]= -84;
v[178]= -82;
v[179]= -82;
v[180]= -80;
v[181]= -79;
v[182]= -78;
v[183]= -77;
}
VMP, 瞳孔地震(bushi
MFC逆向使用xspy
, 去52下一个
Windows编程, 给API发消息触发key控件
#include "stdafx.h"
#include
#include
int _tmain(int argc, _TCHAR* argv[])
{
HWND h = FindWindowA(NULL, "Flag就在控件里");
SendMessage(h, 0x0464, 0, 0);
return 0;
}
HWND: 944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b
DES解密就是flag
int __cdecl main(int argc, const char **argv, const char **envp)
{
HMODULE ModuleHandleW; // eax
int v4; // eax
_DWORD *v5; // eax
unsigned int v6; // edx
_DWORD *v7; // ecx
char *v8; // edi
unsigned int v9; // esi
bool v10; // cf
unsigned int i; // esi
_BYTE *v12; // ecx
void *v13; // ecx
int v14; // eax
int v16; // [esp-4h] [ebp-84h]
int v17; // [esp-4h] [ebp-84h]
int v18; // [esp+0h] [ebp-80h]
int v19; // [esp+0h] [ebp-80h]
int v20; // [esp+0h] [ebp-80h]
_BYTE *Block; // [esp+10h] [ebp-70h]
unsigned int v22; // [esp+24h] [ebp-5Ch]
void *v23[5]; // [esp+28h] [ebp-58h] BYREF
unsigned int v24; // [esp+3Ch] [ebp-44h]
char Src[48]; // [esp+40h] [ebp-40h] BYREF
int v26; // [esp+7Ch] [ebp-4h]
ModuleHandleW = GetModuleHandleW(0);
sub_402320(ModuleHandleW);
sub_4024A0();
v4 = sub_402870(sub_402AC0);
std::ostream::operator<<(v4, v16);
sub_402870(v18);
sub_402AF0(v19);
v23[4] = 0;
v24 = 15;
LOBYTE(v23[0]) = 0;
sub_401D30(v23, Src, strlen(Src));
v26 = 0;
v5 = (_DWORD *)sub_4020D0(v20);
v6 = strlen(aPvfqyc4ttc2uxr);
v7 = v5;
if ( v5[5] >= 0x10u )
v7 = (_DWORD *)*v5;
v8 = aPvfqyc4ttc2uxr;
v9 = v5[4];
if ( v6 < v9 )
v9 = v6;
v10 = v9 < 4;
for ( i = v9 - 4; !v10; i -= 4 )
{
if ( *v7 != *(_DWORD *)v8 )
break;
++v7;
v8 += 4;
v10 = i < 4;
}
if ( v22 >= 0x10 )
{
v12 = Block;
if ( v22 + 1 >= 0x1000 )
{
v12 = (_BYTE *)*((_DWORD *)Block - 1);
if ( (unsigned int)(Block - v12 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn();
}
sub_402F05(v12);
}
v26 = -1;
if ( v24 >= 0x10 )
{
v13 = v23[0];
if ( v24 + 1 >= 0x1000 )
{
v13 = (void *)*((_DWORD *)v23[0] - 1);
if ( (unsigned int)(v23[0] - v13 - 4) > 0x1F )
invalid_parameter_noinfo_noreturn();
}
sub_402F05(v13);
}
v14 = sub_402870(sub_402AC0);
std::ostream::operator<<(v14, v17);
system("pause");
return 0;
}
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()
{
unsigned int NtGlobalFlag; // [esp+10h] [ebp-20h]
NtGlobalFlag = NtCurrentPeb()->NtGlobalFlag;
if ( NtCurrentPeb()->BeingDebugged || NtGlobalFlag == 112 )
exit(-5);
return ((int (*)(void))dword_404000[0])();
}
dword_404000
应该是SMC, sub_402320
这个函数原来是通过调试器附加的方式来进行SMC修改, 静态分析遇到阻碍, 直接动调, 这里有个反调试, 修改EIP绕过反调, 或者nop
动调过程中可以拿到base64编码之后的check字符串nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=
通过findcrypt
可以发现程序存在AES加密, 定位到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
char *v13; // edx
int v14; // edx
char *v15; // esi
const char *key; // esi
int v17; // kr04_4
_DWORD *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
_DWORD *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]
_DWORD *v57; // [esp+14h] [ebp-10h]
_DWORD *v58; // [esp+18h] [ebp-Ch]
char *v59; // [esp+18h] [ebp-Ch]
int v60; // [esp+1Ch] [ebp-8h]
int v61; // [esp+20h] [ebp-4h]
v5 = this;
*(_DWORD *)(this + 972) = 16;
*(_DWORD *)(this + 968) = 16;
*(_OWORD *)(this + 980) = xmmword_407360;
memcpy((void *)(this + 1012), &xmmword_407360, *(_DWORD *)(this + 972));
v6 = *(_DWORD *)(v5 + 968);
if ( v6 == 16 )
{
v9 = *(_DWORD *)(v5 + 972);
if ( v9 == 16 )
{
v7 = 10;
goto LABEL_9;
}
v8 = v9 != 24;
}
else
{
if ( v6 != 24 )
{
v7 = 14;
goto LABEL_9;
}
v8 = *(_DWORD *)(v5 + 972) == 32;
}
v7 = 2 * v8 + 12;
LABEL_9:
*(_DWORD *)(v5 + 976) = v7;
v10 = 0;
v11 = *(_DWORD *)(v5 + 976);
v12 = *(_DWORD *)(v5 + 972) / 4;
v61 = v12;
if ( v11 >= 0 )
{
v13 = (char *)(v5 + 8);
do
{
if ( v12 > 0 )
{
memset(v13, 0, 4 * v12);
v12 = v61;
}
v11 = *(_DWORD *)(v5 + 976);
++v10;
v13 += 32;
}
while ( v10 <= v11 );
}
v14 = 0;
if ( v11 >= 0 )
{
v15 = (char *)(v5 + 488);
do
{
if ( v12 > 0 )
{
memset(v15, 0, 4 * v12);
v12 = v61;
}
v11 = *(_DWORD *)(v5 + 976);
++v14;
v15 += 32;
}
while ( v14 <= v11 );
}
key = "sycloversyclover";
v60 = v12 * (v11 + 1);
v17 = *(_DWORD *)(v5 + 968);
v18 = (_DWORD *)(v5 + 1044);
result = v17 / 4;
v20 = v5 + 1044;
v54 = v17 / 4;
v56 = v5 + 1044;
if ( v17 / 4 > 0 )
{
v21 = v17 / 4;
do
{
v22 = *(unsigned __int8 *)key;
key += 4;
v22 <<= 24;
v20 += 4;
*(_DWORD *)(v20 - 4) = v22;
v23 = v22 | (*((unsigned __int8 *)key - 3) << 16);
*(_DWORD *)(v20 - 4) = v23;
v24 = v23 | (*((unsigned __int8 *)key - 2) << 8);
*(_DWORD *)(v20 - 4) = v24;
result = v24 | *((unsigned __int8 *)key - 1);
*(_DWORD *)(v20 - 4) = result;
--v21;
}
while ( v21 );
v5 = this;
v12 = v61;
v18 = (_DWORD *)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;
*(_DWORD *)(v5 + 4 * (v29 + 8 * v28) + 8) = *v58;
v25 = v17 / 4;
v30 = v29 + 8 * (*(_DWORD *)(v5 + 976) - v28);
result = *v58;
*(_DWORD *)(v5 + 4 * v30 + 488) = *v58;
v12 = v61;
++v58;
}
while ( v26 < v54 );
}
if ( v26 < v60 )
{
v59 = (char *)&unk_406B40;
do
{
v31 = *(_DWORD *)(v5 + 4 * v25 + 1040);
v32 = v59++;
v33 = (unsigned __int8)RijnDael_AES_LONG_405DE0[HIBYTE(v31)] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)v31] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[BYTE1(v31)] ^ ((*v32 ^ RijnDael_AES_LONG_405DE0[BYTE2(v31)]) << 8)) << 8)) << 8);
result = v5 + 1044;
*(_DWORD *)(v5 + 1044) ^= v33;
if ( v25 == 8 )
{
v37 = v5 + 1048;
v38 = 3;
do
{
v39 = *(_DWORD *)(v37 - 4);
v37 += 4;
*(_DWORD *)(v37 - 4) ^= v39;
--v38;
}
while ( v38 );
v40 = 3;
*(_DWORD *)(v5 + 1060) ^= (unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)*(_DWORD *)(v5 + 1056)] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[BYTE1(*(_DWORD *)(v5 + 1056))] ^ (((unsigned __int8)RijnDael_AES_LONG_405DE0[(unsigned __int8)BYTE2(*(_DWORD *)(v5 + 1056))] ^ (RijnDael_AES_LONG_405DE0[HIBYTE(*(_DWORD *)(v5 + 1056))] << 8)) << 8)) << 8);
v41 = v5 + 1064;
do
{
v42 = *(_DWORD *)(v41 - 4);
v41 += 4;
*(_DWORD *)(v41 - 4) ^= v42;
--v40;
}
while ( v40 );
}
else
{
if ( v25 <= 1 )
goto LABEL_39;
v34 = v5 + 1048;
v35 = v25 - 1;
do
{
v36 = *(_DWORD *)(v34 - 4);
v34 += 4;
*(_DWORD *)(v34 - 4) ^= v36;
--v35;
}
while ( v35 );
}
result = v5 + 1044;
LABEL_39:
v52 = 0;
if ( v25 > 0 )
{
v43 = (_DWORD *)result;
v57 = (_DWORD *)result;
while ( v26 < v60 )
{
v44 = v26++;
v45 = v44 % v61;
LODWORD(v44) = v44 / v61;
*(_DWORD *)(v5 + 4 * (v45 + 8 * v44) + 8) = *v43;
v25 = v17 / 4;
*(_DWORD *)(v5 + 4 * (v45 + 8 * (*(_DWORD *)(v5 + 976) - v44)) + 488) = *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 ( *(int *)(v5 + 976) <= 1 )
{
*(_BYTE *)(v5 + 4) = 1;
}
else
{
result = v61;
v47 = (int *)(v5 + 520);
v55 = v5 + 520;
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 = (int *)v55;
}
++v46;
v47 += 8;
v53 = v46;
v55 = (int)v47;
}
while ( v46 < *(_DWORD *)(v5 + 976) );
*(_BYTE *)(v5 + 4) = 1;
}
return result;
}
分析可以得知密钥为sycloversyclover
, 偏移量为sctfsctfsctfsctf
, CBC模式
逆
from Crypto.Cipher import AES
from base64 import b64decode, b64encode
BLOCK_SIZE = AES.block_size
pad = lambda s: s + (BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s.encode()) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
class AESCipher:
def __init__(self):
self.key = 'sycloversyclover'
self.iv = 'sctfsctfsctfsctf'
def encrypt(self, text):
text = pad(text).encode()
cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
encrypted_text = cipher.encrypt(text)
return b64encode(encrypted_text).decode('utf-8')
def decrypt(self, encrypted_text):
encrypted_text = b64decode(encrypted_text)
cipher = AES.new(key=self.key.encode(), mode=AES.MODE_CBC, IV=self.iv.encode())
decrypted_text = cipher.decrypt(encrypted_text)
return unpad(decrypted_text).decode('utf-8')
if __name__ == '__main__':
AESobj = AESCipher()
flag = AESobj.decrypt('nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=')
print(flag)