[GWCTF 2019]babyvm

知识点

  • 虚拟机逆向

主函数

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((__int64)v3);
sub_E0B((__int64)v3);
sub_F83();
puts("And the flag is GWHT{true flag}");
exit(0);
}

subCD1

opcode

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) = byte_202060; // opcode
*(_BYTE *)(a1 + 24) = 0xF1;
*(_QWORD *)(a1 + 32) = sub_B5F; // mov
*(_BYTE *)(a1 + 40) = 0xF2;
*(_QWORD *)(a1 + 48) = sub_A64; // xor
*(_BYTE *)(a1 + 56) = 0xF5;
*(_QWORD *)(a1 + 64) = sub_AC5; // push
*(_BYTE *)(a1 + 72) = 0xF4;
*(_QWORD *)(a1 + 80) = sub_956; // add
*(_BYTE *)(a1 + 88) = 0xF7;
*(_QWORD *)(a1 + 96) = sub_A08; // mul
*(_BYTE *)(a1 + 104) = 0xF8;
*(_QWORD *)(a1 + 112) = sub_8F0; // swap
*(_BYTE *)(a1 + 120) = 0xF6;
*(_QWORD *)(a1 + 128) = sub_99C; // mul 1+2+3
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) = byte_202060; // opcode
while ( **(_BYTE **)(a1 + 16) != 0xF4 )
sub_E6E(a1);
return __readfsqword(0x28u) ^ v2;
}

unsigned char 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
};

vm指令分析

mov 代表0xF1

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;
}

E1 寄存器 R1

E2 寄存器R2

E3 寄存器R3

E4 flag

E5 寄存器R4

xor 代表0xF2

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;
}

push 代表0xF5

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);
dword_2022A4 = strlen(buf);
if ( dword_2022A4 != 21 )
{
puts("WRONG!");
exit(0);
}
++*(_QWORD *)(a1 + 16);
return __readfsqword(0x28u) ^ v3;
}

nop F4

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 F7

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 F8

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;
}

mul2 F6

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;
}

opcode分析

使用脚本进行替换

code = [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]
Reg_table = {0xe1: 'eax', 0xe2: 'ebx', 0xe3: 'ecx', 0xe4: 'edx'}
instructions = {
0xF1: 'mov',
0xF2: 'xor',
0xF4: 'nop',
0xF5: 'push',
0xF6: 'func',
0xF7: 'mul',
0xF8: 'swap'}
i = 0
for j in range(len(code)):
if(code[i] == 0xF1):
print('mov ', end='')
if (code[i+1] == 0xe1):
print('eax ' + 'flag[' + str(code[i + 2]) + ']')
elif(code[i+1] == 0xe2):
print('ebx ' + 'flag[' + str(code[i + 2]) + ']')
elif (code[i + 1] == 0xe3):
print('ecx ' + 'flag[' + str(code[i + 2]) + ']')
elif (code[i + 1] == 0xe4):
print('flag[' + str(code[i + 2]) + '] ' + 'eax')
elif(code[i+1] == 0xe5):
print('edx ' + 'flag[' + str(code[i + 2]) + ']')
elif (code[i + 1] == 0xe7):
print('flag[' + str(code[i + 2]) + '] ' + 'ebx')
i += 6
elif(code[i] == 0xF2):
print('xor eax ebx')
i += 1
elif (code[i] == 0xF4):
print('nop')
i += 1
elif (code[i] == 0xF5):
print('push')
i += 1
elif (code[i] == 0xF6):
print('func eax=ecx + 2 * ebx + 3 * eax')
i += 1
elif (code[i] == 0xF7):
print('mul eax edx')
i += 1
elif (code[i] == 0xF8):
print('swap eax ebx')
i += 1
else:
i += 1

运行结果
push
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

结果二

push
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]
func eax=ecx + 2 * ebx + 3 * eax
mul eax edx
mov flag[6] eax
mov eax flag[7]
mov ebx flag[8]
mov ecx flag[9]
mov edx flag[12]
func eax=ecx + 2 * ebx + 3 * eax
mul eax edx
mov flag[7] eax
mov eax flag[8]
mov ebx flag[9]
mov ecx flag[10]
mov edx flag[12]
func eax=ecx + 2 * ebx + 3 * eax
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

经过分析第一段为假,分析第二段

# 加密过程
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])

脚本

from z3 import *
code = [0x69, 0x45, 0x2A, 0x37, 0x09, 0x17, 0xC5, 0x0B, 0x5C, 0x72,
0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5F, 0x33, 0x73, 0x72]

(code[13], code[19]) = (code[19], code[13])
(code[14], code[18]) = (code[18], code[14])
(code[15], code[17]) = (code[17], code[15])
a = BitVec('a', 8) # 6
b = BitVec('b', 8) # 7
c = BitVec('c', 8) # 95
s = Solver()
s.add(c == 95)
s.add(b == 51)
s.add((c+2*b+3*a)*0x33 == 0xC5)
s.add((0x72+2*c+3*b)*0x33 == 0x0b)
s.add((0x33+2*0x72+3*c)*0x33 == 0x5c)
if s.check() == sat:
m = s.model()
print(m)
else:
print('failure')
code[6] = 118
code[7] = 51
code[8] = 95
for i in range(5, -1, -1):
code[i] = code[i] ^ code[i+1]
for i in range(20):
print(chr(code[i]), end='')

# output
[a = 118, b = 51, c = 95]
Y0u_hav3_r3v3rs3_1t!