# Crackme
Follow my PATH!
Attachments:* [crackme](./crackme)
## SolutionWe are given a small VM.
```cvoid __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```cvoid __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```cvoid __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](./disasm.py), Output [here](./disasm.txt)
After printing some stuff it takes a character and checks them```0x0ba R0 = getc0x0bd R0 ^= 0x630x0c0 R3 += R0
0x0c3 R0 = getc0x0c6 ~R00x0c9 R0 ^= 0x8b0x0cc R3 += R0
0x0cf R0 = getc0x0d2 R1 = R00x0d5 R0 ^= 0x8a0x0d8 R1 &= 0x8a0x0db R1 << 10x0de R2 = R10x0e1 R1 += R00x0e4 R2 += R00x0e7 R1 &= 0x100x0ea R2 |= 0x100x0ed R1 += R20x0f0 R0 = R10x0f3 R3 = R1
0x0f6 R0 = getc0x0f9 R1 = R00x0fc R1 ^= 0x850x0ff R0 &= 0x850x102 R0 *= 20x105 R0 += R10x108 R3 += R0```
Instead of reversing the check, I just bruteforced the characters with this python [script](./solve.py)
## Flag>  ctf{v1rtu4l_m4chine_pr0tection_is_soo_2010_xD}