Follow my PATH!
Attachments:
We are given a small VM.
void __fastcall main(int a1, char **a2, char **a3)
{
cpu *cpu; // [rsp+18h] [rbp-878h]
char v4[2137]; // [rsp+20h] [rbp-870h] BYREF
unsigned __int64 v5; // [rsp+888h] [rbp-8h]
v5 = __readfsqword(0x28u);
qmemcpy(v4, &unk_1040, sizeof(v4));
cpu = (cpu *)malloc(0x38uLL);
cpu->code_data = v4;
init_cpu(cpu);
runvm(cpu);
}
init_cpu
initializes the registers
void __fastcall init_cpu(cpu *cpu)
{
cpu->R3 = 0;
cpu->R2 = cpu->R3;
cpu->R1 = cpu->R2;
cpu->R0 = cpu->R1;
cpu->R[0] = &cpu->R0;
cpu->R[1] = &cpu->R1;
cpu->R[2] = &cpu->R2;
cpu->R[3] = &cpu->R3;
cpu->X = cpu->code_data + 2048;
}
runvm
executes the VM
void __fastcall runvm(cpu *cpu)
{
do
{
v2 = cpu->code_data[cpu->InsPointer + 1];
v3 = cpu->code_data[cpu->InsPointer + 2];
v1 = 0;
switch ( cpu->code_data[cpu->InsPointer] )
{
case 1:
v11 = cpu->R[v2];
*v11 *= v3;
break;
case 2:
v10 = cpu->R[v2];
*v10 -= v3;
break;
case 3:
v9 = cpu->R[v2];
*v9 = ~*v9;
break;
case 4:
v8 = cpu->R[v2];
*v8 ^= cpu->X[v3];
break;
case 5:
*cpu->R[v2] = *cpu->R[v3];
break;
case 6:
*cpu->R[v2] = cpu->X[v3];
break;
case 7:
if ( cpu->R0 )
{
cpu->InsPointer += v2;
v1 = 1;
}
break;
case 8:
putc(cpu->R0, stdout);
break;
case 9:
exit(cpu->R0);
case 10:
cpu->R0 = getc(stdin);
break;
case 11:
v7 = cpu->R[v2];
*v7 = *v7 << v3;
break;
case 12:
v6 = cpu->R[v2];
*v6 &= cpu->X[v3];
break;
case 13:
v5 = cpu->R[v2];
*v5 |= cpu->X[v3];
break;
case 14:
v4 = cpu->R[v2];
*v4 += *cpu->R[v3];
break;
default:
break;
}
if ( v1 != 1 )
cpu->InsPointer += 3;
}
while ( cpu->code_data[cpu->InsPointer] != 101 );
}
I wrote a disassembler to parse the opcodes. Script here, Output here
After printing some stuff it takes a character and checks them
0x0ba R0 = getc
0x0bd R0 ^= 0x63
0x0c0 R3 += R0
0x0c3 R0 = getc
0x0c6 ~R0
0x0c9 R0 ^= 0x8b
0x0cc R3 += R0
0x0cf R0 = getc
0x0d2 R1 = R0
0x0d5 R0 ^= 0x8a
0x0d8 R1 &= 0x8a
0x0db R1 << 1
0x0de R2 = R1
0x0e1 R1 += R0
0x0e4 R2 += R0
0x0e7 R1 &= 0x10
0x0ea R2 |= 0x10
0x0ed R1 += R2
0x0f0 R0 = R1
0x0f3 R3 = R1
0x0f6 R0 = getc
0x0f9 R1 = R0
0x0fc R1 ^= 0x85
0x0ff R0 &= 0x85
0x102 R0 *= 2
0x105 R0 += R1
0x108 R3 += R0
Instead of reversing the check, I just bruteforced the characters with this python script
ctf{v1rtu4l_m4chine_pr0tection_is_soo_2010_xD}