### Discount VMProtect
![6_title](images/6_title.png)
The name speaks for itself. We are dealing with virtual machine :)
``` bashfile challchall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=230e9f987b798e57f5c25421983e3545c715f850, stripped```
entry:
![6_main](images/6_main.png)
This is very simple stack based virtual machine. Here its code:
![6_vm](images/6_vm.png)
Now we have to write our disassembler and reverse engineer the key check algorithm :)
disassembler:
``` pythondef disassemble_vm(state):    i = 0    while True:        if i == len(state):            break        ins = state[i]        i += 1        if ins == 0x30:            print(f'{str(i-1).ljust(10)}exit')        elif ins == 0x31:            print(f'{str(i-1).ljust(10)}push registers[{state[i]}]')            i += 1        elif ins == 0x32:            print(f'{str(i-1).ljust(10)}push stack[sp]')        elif ins == 0x33:            print(f'{str(i-1).ljust(10)}mov stack[sp], input[stack[sp]]')        elif ins == 0x34:            print(f'{str(i-1).ljust(10)}if stack[sp] == 0:')            print(f'{str(i-1).ljust(10)}\t\tjmp {state[i]}\t; {hex(state[state[i]])}')            print(f'{str(i-1).ljust(10)}sub sp, 1')            i += 1        elif ins == 0x35:            print(f'{str(i-1).ljust(10)}stack[sp] = (stack[sp] << 7) | (stack[sp] >> 1)')        elif ins == 0x36:            print(f'{str(i-1).ljust(10)}push {state[i]}')            i += 1        elif ins == 0x37:            print(f'{str(i-1).ljust(10)}stack[sp-1] ^= stack[sp]')            print(f'{str(i-1).ljust(10)}sub sp, 1')        elif ins == 0x38:            print(f'{str(i-1).ljust(10)}stack[sp-1] += stack[sp]')            print(f'{str(i-1).ljust(10)}sub sp, 1')        elif ins == 0x39:            print(f'{str(i-1).ljust(10)}stack[sp-1] -= stack[sp]')            print(f'{str(i-1).ljust(10)}sub sp, 1')        elif ins == 0x61:            print(f'{str(i-1).ljust(10)}stack[sp-1] = ~stack[sp]')            print(f'{str(i-1).ljust(10)}sub sp, 1')        elif ins == 0x62:            print(f'{str(i-1).ljust(10)}check antidebug')        elif ins == 0x63:            print(f'{str(i-1).ljust(10)}registers[0] = 1')            print(f'{str(i-1).ljust(10)}strcpy(dest, &src)')        elif ins == 0x64:            print(f'{str(i-1).ljust(10)}registers[{state[i]}] = stack[sp]')            print(f'{str(i-1).ljust(10)}sub sp, 1')            i += 1        elif ins == 0x65:            print(f'{str(i-1).ljust(10)}stack[sp] = registers[stack[sp]]')        else:            continue```
First bytecode:
``` python0         push registers[128]2         registers[0] = 12         strcpy(dest, &src)
3         push stack[sp]4         push stack[sp]5         registers[128] = stack[sp]5         sub sp, 17         mov stack[sp], input[stack[sp]]8         if stack[sp] == 0:8         		jmp 18	; 0x368         sub sp, 1
10        push 112        stack[sp-1] += stack[sp]12        sub sp, 113        push stack[sp]14        push stack[sp]15        stack[sp-1] -= stack[sp]15        sub sp, 116        if stack[sp] == 0:16        		jmp 3	; 0x3216        sub sp, 1
18        push 3520        stack[sp-1] -= stack[sp]20        sub sp, 121        if stack[sp] == 0:21        		jmp 27	; 0x3621        sub sp, 123        push 025        registers[0] = stack[sp]25        sub sp, 1
27        push 029        registers[128] = stack[sp]29        sub sp, 131        exit```
Its python representation:
``` pythondef check_password_len(password):	if len(password) != 35:        register[0] = 0```
Second bytecode:
``` python0         push registers[128]2         push stack[sp]3         push stack[sp]4         registers[128] = stack[sp]4         sub sp, 16         mov stack[sp], input[stack[sp]]7         push stack[sp]8         if stack[sp] == 0:8         		jmp 40	; 0x308         sub sp, 1
10        stack[sp] = (stack[sp] << 7) | (stack[sp] >> 1)11        push 9913        stack[sp-1] ^= stack[sp]13        sub sp, 114        push 15216        stack[sp-1] += stack[sp]16        sub sp, 117        stack[sp-1] = ~stack[sp]17        sub sp, 118        check antidebug19        push registers[128]21        push 1023        stack[sp-1] += stack[sp]23        sub sp, 124        stack[sp] = registers[stack[sp]]25        stack[sp-1] -= stack[sp]25        sub sp, 126        if stack[sp] == 0:26        		jmp 32	; 0x3626        sub sp, 128        push 030        registers[0] = stack[sp]30        sub sp, 1
32        push 134        stack[sp-1] += stack[sp]34        sub sp, 135        push stack[sp]36        push stack[sp]37        stack[sp-1] ^= stack[sp]37        sub sp, 138        if stack[sp] == 0:38        		jmp 2	; 0x3238        sub sp, 140        exit```
Its python representation:
``` c++def check_password(password):    check = 0    for i in range(35):		t = password[i]        t = (t << 7) | (t >> 1)        t &= 0xff        t ^= 99        t += 152        t &= 0xff        t = ~t        if t != key[i]:            check = 1            break
    if check == 0:        registers[0] = 1    else:        registers[0] = 0```
Solution:
``` pythonkey = [24, 114, 162, 164, 157, 137, 31, 162, 141, 155, 148, 13, 109, 155, 149,236, 236, 18, 155, 148, 35, 22, 155, 108, 19, 14, 109, 13, 150, 141, 14, 144,19, 151, 138]
def encode(t):    t = (t << 7) | (t >> 1)    t &= 0xff    t ^= 99    t += 152    t &= 0xff    t = ~t    return t & 0xff
y = ""for j in range(len(key)):    for i in range(48, 126):    # Bruteforce every printable character        if encode(i) == key[j]:            y += chr(i)print(y)```
```>>> XMAS{VMs_ar3_c00l_aNd_1nt3resting}```