Skip to content

Instantly share code, notes, and snippets.

@yeuchimse
Last active May 23, 2018 11:58
Show Gist options
  • Select an option

  • Save yeuchimse/8823e935721038850cff to your computer and use it in GitHub Desktop.

Select an option

Save yeuchimse/8823e935721038850cff to your computer and use it in GitHub Desktop.

Revisions

  1. yeuchimse revised this gist Oct 2, 2015. 1 changed file with 13 additions and 13 deletions.
    26 changes: 13 additions & 13 deletions matesctf.092015.re500.py
    Original file line number Diff line number Diff line change
    @@ -346,7 +346,7 @@ def call(vm):
    vm.stack[vm.esp] = vm.eip
    vm.eip += target

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def call_absolute(vm):
    @@ -363,10 +363,10 @@ def call_absolute(vm):
    param = vm.regs[a & 0x3F]

    vm.esp -= 1
    vm.stack[vm.esp] = vm.eip + 1
    vm.stack[vm.esp] = vm.eip
    vm.eip = param

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def ret(vm):
    @@ -379,7 +379,7 @@ def jump(vm):
    print 'jmp',
    vm.eip += vm.read_word(vm.eip) + 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def jump_if_zero(vm):
    @@ -389,7 +389,7 @@ def jump_if_zero(vm):
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def jump_if_not_zero(vm):
    @@ -399,7 +399,7 @@ def jump_if_not_zero(vm):
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def jump_if_error(vm):
    @@ -409,7 +409,7 @@ def jump_if_error(vm):
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def jump_if_not_error(vm):
    @@ -419,7 +419,7 @@ def jump_if_not_error(vm):
    else:
    vm.eip = vm.eip + 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def loop(vm):
    @@ -430,7 +430,7 @@ def loop(vm):
    else:
    vm.eip = vm.eip + 2

    print format_value(uint16(vm.eip + 1))
    print format_value(uint16(vm.eip))


    def read_from(vm):
    @@ -456,7 +456,7 @@ def write_to(vm):


    def push(vm):
    print 'push', vm.one_params(),
    print 'push', vm.one_param(),
    a = vm.code[vm.eip]

    type = a >> 6
    @@ -475,7 +475,7 @@ def push(vm):


    def pop(vm):
    print 'pop', vm.one_params(),
    print 'pop', vm.one_param(),
    value = vm.stack[vm.esp]
    vm.esp += 1

    @@ -696,7 +696,7 @@ def two_params(self):
    except:
    return '%s' % src

    def one_params(self):
    def one_param(self):
    param1 = self.code[vm.eip]

    type1 = param1 >> 6
    @@ -761,7 +761,7 @@ def run(self):
    print 'regs : ', self.registers()
    print 'stack: ', map(hex, vm.stack[-5:][::-1])
    print 'flag : %s (zero flag: %d | error_flag: %d)' % (bin(vm.flags), vm.zero_flag, vm.error_flag)
    print '0x%04x ' % self.eip,
    print '0x%04x ' % (self.eip - 1), # because now eip already points to next instruction
    self.functions[function_index](self)
    print ''

  2. yeuchimse created this gist Oct 2, 2015.
    781 changes: 781 additions & 0 deletions matesctf.092015.re500.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,781 @@
    __author__ = 'yeuchimse'

    import struct

    FileMode = ['rb', 'wb', 'ab', 'r+b', 'w+b', 'a+b']
    Registers = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'esp', 'ebp']


    # region ...
    def format_code(v):
    return '[0x%04x]' % v


    def format_reg(v):
    return Registers[v]


    def format_code_reg(v):
    return '[%s]' % format_reg(v)


    def format_value(v):
    return '0x%04x' % v


    def uint16(n):
    return n & 0xFFFF


    # endregion

    # region xtea
    def up(s):
    sa = []
    for i in xrange(0, len(s), 4):
    sa.append(struct.unpack('>I', s[i:i + 4])[0])

    return sa


    def p(sa):
    s = ''
    for n in sa:
    s += struct.pack('>I', n)

    return s


    def xtea_block(c, k):
    v0, v1 = up(c)
    key = up(k)

    delta = 0x9E3779B9
    sum = (delta * 32) & 0xFFFFFFFF
    for i in xrange(32):
    v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3])
    v1 &= 0xFFFFFFFF
    sum -= delta
    sum &= 0xFFFFFFFF
    v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3])
    v0 &= 0xFFFFFFFF

    return p([v0, v1])


    # endregion


    # region functions
    def execute_function_2_params(vm, func):
    print vm.two_params(),

    a, b = vm.code[vm.eip], vm.code[vm.eip + 1]

    type = a >> 6
    if type:
    if type == 1:
    param1 = vm.read_word(a & 0x3F)
    elif type == 2:
    param1 = vm.read_word(vm.regs[a & 0x3F])
    else:
    param1 = vm.regs[a & 0x3F]

    type = b >> 6
    if type:
    if type == 1:
    param2 = vm.read_word(b & 0x3F)
    elif type == 2:
    param2 = vm.read_word(vm.regs[b & 0x3F])
    elif type == 3:
    param2 = b & 0x3F
    else:
    param2 = vm.regs[b & 0x3F]

    result = func(param1, param2)

    type = a >> 6
    if type:
    if type == 1:
    vm.write_word(a & 0x3F, result)
    elif type == 2:
    vm.write_word(vm.regs[a & 0x3F], result)

    else:
    vm.regs[a & 0x3F] = result

    vm.eip += 2


    def execute_function_1_param(vm, func):
    print vm.two_params(),
    a = vm.code[vm.eip]

    type = a >> 6
    if type:
    if type == 1:
    param = vm.read_word([a & 0x3F])
    result = func(param)
    vm.write_word(a & 0x3F, result)
    elif type == 2:
    param = vm.read_word([vm.regs[a & 0x3F]])
    result = func(param)
    vm.write_word(vm.regs[a & 0x3F], result)

    else:
    param = vm.regs[a & 0x3F]
    result = func(param)
    vm.regs[a & 0x3F] = result

    if result == 0:
    vm.zero_flag = 1
    else:
    vm.zero_flag = 0

    vm.eip += 1


    def add(vm):
    print 'add',
    execute_function_2_params(vm, lambda a, b: a + b)


    def sub(vm):
    print 'sub',
    execute_function_2_params(vm, lambda a, b: a - b)


    def inc(vm):
    print 'inc',
    execute_function_1_param(vm, lambda a: a + 1)


    def dec(vm):
    print 'dec',
    execute_function_1_param(vm, lambda a: a - 1)


    def and_(vm):
    print 'and',
    execute_function_2_params(vm, lambda a, b: a & b)


    def or_(vm):
    print 'or',
    return execute_function_2_params(vm, lambda a, b: a | b)


    def xor(vm):
    print 'xor',
    return execute_function_2_params(vm, lambda a, b: a ^ b)


    def not_(vm):
    print 'not',
    execute_function_1_param(vm, lambda a: ~a)


    def shl(vm):
    print 'shl',
    return execute_function_2_params(vm, lambda a, b: a << b)


    def shr(vm):
    print 'shr',
    return execute_function_2_params(vm, lambda a, b: a >> b)


    def rol(vm):
    print 'rol',
    execute_function_2_params(vm, lambda a, b: a << b | a >> (16 - b))


    def ror(vm):
    print 'ror',
    execute_function_2_params(vm, lambda a, b: a >> b | a << (16 - b))


    def ror8(vm):
    print 'ror8',
    execute_function_1_param(vm, lambda a: a >> 8 | a << 8)


    def mov(vm):
    print 'mov',
    execute_function_2_params(vm, lambda a, b: b)


    def xtea(vm):
    print 'call xtea'
    num_of_block = vm.code[vm.eip]
    addr = vm.eip + 2

    key = vm.read_bytes(vm.regs[2], 16)
    for i in xrange(num_of_block):
    cipher = vm.read_bytes(addr, 8)
    plain = xtea_block(cipher, key)
    vm.write_bytes(addr, plain)

    addr += 8

    vm.eip += 2


    def cmp(vm):
    print 'cmp', vm.two_params(),
    a, b = vm.code[vm.eip], vm.code[vm.eip + 1]

    type = a >> 6
    if type:
    if type == 1:
    param1 = vm.read_word(a & 0x3F)
    elif type == 2:
    param1 = vm.read_word(vm.regs[a & 0x3F])
    else:
    param1 = vm.regs[a & 0x3F]

    type = b >> 6
    if type:
    if type == 1:
    param2 = vm.read_word(b & 0x3F)
    elif type == 2:
    param2 = vm.read_word(vm.regs[b & 0x3F])
    elif type == 3:
    param2 = b & 0x3F
    else:
    param2 = vm.regs[b & 0x3F]

    if param1 - param2 == 0:
    vm.zero_flag = 1
    else:
    vm.zero_flag = 0

    vm.eip += 2


    def mul(vm):
    print 'mul',
    a = vm.code[vm.eip]

    type = a >> 6
    if type:
    if type == 1:
    param1 = vm.read_word(a & 0x3F)
    elif type == 2:
    param1 = vm.read_word(vm.regs[a & 0x3F])
    else:
    param1 = vm.regs[a & 0x3F]

    result = vm.regs[0] * param1

    vm.regs[0] = result & 0xFFFF
    vm.regs[3] = (result & 0xFFFF0000) >> 16

    vm.eip += 1


    def div(vm):
    print 'div',
    a = vm.code[vm.eip]

    type = a >> 6
    if type:
    if type == 1:
    param = vm.read_word(a & 0x3F)
    elif type == 2:
    param = vm.read_word(vm.regs[a & 0x3F])
    else:
    param = vm.regs[a & 0x3F]

    n = vm.regs[0] | (vm.regs[3] << 16)
    vm.regs[0] = n / param
    vm.regs[3] = n % param

    if vm.regs[0] == 0:
    vm.zero_flag = 1
    else:
    vm.zero_flag = 0

    vm.eip += 1


    def xchg(vm):
    print 'xchg', vm.two_params()
    a, b = vm.code[vm.eip], vm.code[vm.eip + 1]

    type2 = b >> 6
    if type2:
    if type2 == 1:
    param2 = vm.read_word(b & 0x3F)
    elif type2 == 2:
    param2 = vm.read_word(vm.regs[b & 0x3F])
    else:
    param2 = vm.regs[b & 0x3F]

    # write dst to src
    type = a >> 6
    if type:
    if type == 1:
    param1 = vm.read_word(a & 0x3F)
    vm.write_word(a & 0x3F, param2)
    elif type == 2:
    param1 = vm.read_word(vm.regs[a & 0x3F])
    vm.write_word(vm.regs[a & 0x3F], param2)
    else:
    param1 = vm.regs[a & 0x3F]
    vm.regs[a & 0x3F] = param2

    # write src to dst
    if type2:
    if type2 == 1:
    vm.write_word(b & 0x3F, param1)
    elif type2 == 2:
    vm.write_word(vm.regs[b & 0x3F], param1)
    else:
    vm.regs[b & 0x3F] = param1

    vm.eip += 2


    def call(vm):
    print 'call',
    target = vm.read_word(vm.eip)

    vm.esp -= 1
    vm.eip += 2
    vm.stack[vm.esp] = vm.eip
    vm.eip += target

    print format_value(uint16(vm.eip + 1))


    def call_absolute(vm):
    print 'call',
    a = vm.code[vm.eip]

    type = a >> 6
    if type:
    if type == 1:
    param = vm.read_word(a & 0x3F)
    else:
    raise 'Error'
    else:
    param = vm.regs[a & 0x3F]

    vm.esp -= 1
    vm.stack[vm.esp] = vm.eip + 1
    vm.eip = param

    print format_value(uint16(vm.eip + 1))


    def ret(vm):
    print 'ret',
    vm.eip = vm.stack[vm.esp]
    vm.esp += 1


    def jump(vm):
    print 'jmp',
    vm.eip += vm.read_word(vm.eip) + 2

    print format_value(uint16(vm.eip + 1))


    def jump_if_zero(vm):
    print 'jz',
    if vm.zero_flag:
    vm.eip = vm.eip + 2 + vm.read_word(vm.eip)
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))


    def jump_if_not_zero(vm):
    print 'jnz',
    if not vm.zero_flag:
    vm.eip = vm.eip + 2 + vm.read_word(vm.eip)
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))


    def jump_if_error(vm):
    print 'js',
    if vm.error_flag:
    vm.eip = vm.eip + 2 + vm.read_word(vm.eip)
    else:
    vm.eip += 2

    print format_value(uint16(vm.eip + 1))


    def jump_if_not_error(vm):
    print 'jns',
    if not vm.error_flag:
    vm.eip = vm.eip + 2 + vm.read_word(vm.eip)
    else:
    vm.eip = vm.eip + 2

    print format_value(uint16(vm.eip + 1))


    def loop(vm):
    print 'loop',
    vm.regs[2] -= 1
    if vm.regs[2]:
    vm.eip = vm.eip + 2 + vm.read_word(vm.eip)
    else:
    vm.eip = vm.eip + 2

    print format_value(uint16(vm.eip + 1))


    def read_from(vm):
    print 'mov %s, %s' % (format_reg(0), format_code_reg(4))
    print ' inc %s' % (format_reg(4)),

    vm.regs[0] = vm.code[vm.regs[4]]
    if vm.flags & 0b1000000 == 0:
    vm.regs[4] += 1
    else:
    vm.regs[4] -= 1


    def write_to(vm):
    print 'mov %s, %s' % (format_code_reg(5), format_reg(0))
    print ' inc %s' % (format_reg(5)),

    vm.code[vm.regs[5]] = vm.regs[0]
    if vm.flags & 0b1000000:
    vm.regs[5] -= 1
    else:
    vm.regs[5] += 1


    def push(vm):
    print 'push', vm.one_params(),
    a = vm.code[vm.eip]

    type = a >> 6
    if type:
    if type == 1:
    param = vm.read_word(a & 0x3F)
    elif type == 2:
    param = vm.read_word(vm.regs[a & 0x3F])

    else:
    param = vm.regs[a & 0x3F]

    vm.esp -= 1
    vm.stack[vm.esp] = param
    vm.eip += 1


    def pop(vm):
    print 'pop', vm.one_params(),
    value = vm.stack[vm.esp]
    vm.esp += 1

    a = vm.code[vm.eip]
    type = a >> 6
    if type:
    if type == 1:
    vm.write_word(a & 0x3F, value)
    elif type == 2:
    vm.write_word(vm.regs[a & 0x3F], value)

    else:
    vm.regs[a & 0x3F] = value

    vm.eip += 1


    def open_file(vm):
    filename = vm.read_str(vm.regs[3])
    filemode = FileMode[vm.regs[2]]

    print 'open(%r, %r)' % (filename, filemode),

    try:
    vm.files[0] = open(filename, filemode)
    vm.error_flag = 0
    except:
    vm.error_flag = 1


    def close_file(vm):
    print 'close',
    vm.error_flag = 0


    def read_char(vm):
    print 'fgetc',
    vm.flags &= 0b11111110
    vm.regs[0] = ord(vm.files[0].read(1))


    def print_char(vm):
    print 'print %r' % chr(vm.regs[2] & 0xFF),

    vm.stdout += chr(vm.regs[2] & 0xFF)


    def finish():
    print 'finish'
    pass


    def clear_flags_6(vm):
    vm.flags &= 0b10111111


    def set_flags_6(vm):
    vm.flags |= 0b01000000


    def null(vm):
    print 'nop',


    def exit(vm):
    print 'exit',
    vm.finish = 1


    def process_first_block(vm):
    print 'call process_first_block'
    a = vm.code[vm.eip]
    print ' div %s, 0x%x' % (format_reg(a % 0x3F), 11)

    v = vm.regs[a % 0x3F]
    vm.regs[0] = v / 11
    vm.regs[3] = v % 11
    if v:
    vm.zero_flag = 0
    else:
    vm.zero_flag = 1

    vm.eip += 1


    def process_second_block(vm):
    print 'call process_second_block'
    a = vm.code[vm.eip]
    print ' div %s, 0x%x' % (format_reg(a % 0x3F), 9)

    v = vm.regs[a % 0x3F]
    vm.regs[0] = v / 9
    vm.regs[3] = v % 9
    if v:
    vm.zero_flag = 0
    else:
    vm.zero_flag = 1

    vm.eip += 1


    # endregion


    # region VM
    class VM(object):
    def __init__(self):
    self.regs = [0] * 8
    self.esp = 256
    self.flags = 0
    self.eip = 0
    self.files = [None] * 20
    self.error_code = 0
    self.functions = [None] * 43
    self.instrutions = {}
    self.finish = 0
    self.stdout = ''

    self.code = open('code.hex', 'rb').read().decode('hex')
    self.code = map(ord, self.code)

    self.code_word = []
    for i in xrange(0, len(self.code), 2):
    a, b = self.code[i], self.code[i + 1]
    self.code_word.append(a | (b << 16))

    self.stack = [0] * 256
    self.code_size = 980
    self.buf_size = 2004

    self.functions[0] = add
    self.functions[1] = sub
    self.functions[2] = cmp
    self.functions[3] = mul
    self.functions[4] = div
    self.functions[5] = inc
    self.functions[6] = dec
    self.functions[7] = and_
    self.functions[8] = or_
    self.functions[9] = xor
    self.functions[10] = not_
    self.functions[11] = mov
    self.functions[12] = xchg
    self.functions[13] = ror8
    self.functions[14] = shl
    self.functions[15] = shr
    self.functions[16] = rol
    self.functions[17] = ror
    self.functions[18] = loop
    self.functions[19] = read_from
    self.functions[20] = write_to
    self.functions[21] = push
    self.functions[22] = pop
    self.functions[23] = xtea
    self.functions[24] = call
    self.functions[25] = call_absolute
    self.functions[26] = ret
    self.functions[27] = jump
    self.functions[28] = jump_if_zero
    self.functions[29] = jump_if_not_zero
    self.functions[30] = jump_if_error
    self.functions[31] = jump_if_not_error
    self.functions[32] = open_file
    self.functions[33] = close_file
    self.functions[34] = read_char
    self.functions[35] = print_char
    self.functions[36] = exit
    self.functions[37] = exit
    self.functions[38] = clear_flags_6
    self.functions[39] = set_flags_6
    self.functions[40] = null
    self.functions[41] = process_first_block
    self.functions[42] = process_second_block

    def read_word(self, i):
    return self.code[i] | (self.code[i + 1] << 8)

    def write_word(self, i, value):
    self.code[i] = value & 0xFF
    self.code[i + 1] = (value & 0xFF00) >> 8

    def read_str(self, i):
    return ''.join(map(chr, self.code[i:])).split('\x00')[0]

    def read_bytes(self, i, n):
    return ''.join(map(chr, self.code[i:]))[:n]

    def write_bytes(self, i, s):
    s = map(ord, s)
    for j in xrange(len(s)):
    self.code[i + j] = s[j]

    def two_params(self):
    param1, param2 = self.code[vm.eip], self.code[vm.eip + 1]

    type1 = param1 >> 6
    if type1:
    if type1 == 1:
    src = format_code(param1 & 0x3F)
    elif type1 == 2:
    src = format_code_reg(param1 & 0x3F)
    else:
    src = format_reg(param1 & 0x3F)

    try:
    type2 = param2 >> 6
    if type2:
    if type2 == 1:
    dst = format_code(param2 & 0x3F)
    elif type2 == 2:
    dst = format_code_reg(param2 & 0x3F)
    elif type2 == 3:
    dst = format_value(param2 & 0x3F)
    else:
    dst = format_reg(param2 & 0x3F)

    return '%s, %s' % (src, dst)
    except:
    return '%s' % src

    def one_params(self):
    param1 = self.code[vm.eip]

    type1 = param1 >> 6
    if type1:
    if type1 == 1:
    src = format_code(param1 & 0x3F)
    elif type1 == 2:
    src = format_code_reg(param1 & 0x3F)
    else:
    src = format_reg(param1 & 0x3F)

    return '%s' % src

    def registers(self):
    return 'eax: 0x%04x | ebx: 0x%04x | ecx: 0x%04x | edx: 0x%04x \n' \
    ' esi: 0x%04x | edi: 0x%04x | esp: 0x%04x | ebp: 0x%04x' % tuple(
    self.regs)

    @property
    def error_flag(self):
    return self.flags & 1

    @error_flag.setter
    def error_flag(self, v):
    if v:
    self.flags |= 1
    else:
    self.flags &= 0b11111110

    @property
    def zero_flag(self):
    return (self.flags & 0b1000) >> 3

    @zero_flag.setter
    def zero_flag(self, v):
    if v:
    self.flags |= 0b1000
    else:
    self.flags &= 0b11110111

    @property
    def esp(self):
    return self.regs[6]

    @esp.setter
    def esp(self, v):
    self.regs[6] = v

    def run(self):
    while self.eip < self.code_size:
    print ''

    function_index = self.code[self.eip]
    if function_index > 43:
    return

    self.eip += 1

    if self.eip not in self.instrutions:
    self.instrutions[self.eip] = True

    print 'regs : ', self.registers()
    print 'stack: ', map(hex, vm.stack[-5:][::-1])
    print 'flag : %s (zero flag: %d | error_flag: %d)' % (bin(vm.flags), vm.zero_flag, vm.error_flag)
    print '0x%04x ' % self.eip,
    self.functions[function_index](self)
    print ''

    self.eip = uint16(self.eip)
    self.regs = map(uint16, self.regs)

    if vm.finish:
    break

    print vm.stdout


    # endregion


    vm = VM()
    vm.run()