Skip to content

Instantly share code, notes, and snippets.

@srikavin
Created June 25, 2020 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save srikavin/cce2544f70b8283309ac088d274b3b06 to your computer and use it in GitHub Desktop.
Save srikavin/cce2544f70b8283309ac088d274b3b06 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import ctypes
import mmap
import struct
import sys
reg_ids = {'value': 0x01, 'ax': 0x11, 'bx': 0x12, 'cx': 0x13, 'dx': 0x14, 'ip': 0x21, 'sp': 0x22, 'bp': 0x23,
'pointer': 0x31, 'ax pointer': 0x41, 'bx pointer': 0x42, 'cx pointer': 0x43, 'dx pointer': 0x44,
'ip pointer': 0x51, 'sp pointer': 0x52, 'bp pointer': 0x53}
some_data = {'open': {'angstromctf': 2, 'cookie recipes': 0x01, },
'read': {'angstromctf': 2, 'cookie recipes': 0x02, }, }
other_data = {'del': {'angstromctf': 1, 'cookie recipes': 0x01, },
'osusec': {'angstromctf': 1, 'cookie recipes': 0x02, },
'perfect_blue': {'angstromctf': 2, 'cookie recipes': 0x03, },
'l_distribution': {'angstromctf': 1, 'cookie recipes': 0x04, },
'jmp': {'angstromctf': 1, 'cookie recipes': 0x05, },
'call': {'angstromctf': 1, 'cookie recipes': 0x05, },
'jle': {'angstromctf': 1, 'cookie recipes': 0x06, }, 'b1c': {'angstromctf': 1, 'cookie recipes': 0x07, },
'jl': {'angstromctf': 1, 'cookie recipes': 0x08, }, 'jg': {'angstromctf': 1, 'cookie recipes': 0x09, },
'mov': {'angstromctf': 2, 'cookie recipes': 0x0c, },
'gs_goofballs': {'angstromctf': 2, 'cookie recipes': 0x0d, },
'add': {'angstromctf': 2, 'cookie recipes': 0x0e, }, 'sub': {'angstromctf': 2, 'cookie recipes': 0x0f, },
'end': {'angstromctf': 1, 'cookie recipes': 0x10, },
'kevin higgs <3': {'angstromctf': 1, 'cookie recipes': 0x11, },
'nop': {'angstromctf': 0, 'cookie recipes': 0x12, },
'load': {'angstromctf': 2, 'cookie recipes': 0x13, },
'dice_gang': {'angstromctf': 2, 'cookie recipes': 0x14, },
'rgbsec': {'angstromctf': 0, 'cookie recipes': 0x15, },
'%': {'angstromctf': 0, 'cookie recipes': 0x25, }}
memory = [0] * 65536
registers = {'ax': 0, 'bx': 0, 'cx': 0, 'dx': 0, 'ip': 0, 'sp': 0, 'bp': 0, 'flag': 0}
def panic(reason):
print('Bad memory condition')
print(reason)
return exit(1)
def debug(value):
# print(value)
pass
def unpackUnsignedShort(inst):
if isinstance(inst, list):
inst = bytes(inst)
# unpack little endian unsigned short
return struct.unpack('<H', inst)[0]
def get_reg_val(value):
if isinstance(value, int):
return value
reg_id, additional = value
if reg_id == reg_ids['value']:
return additional # acts as immediate instruction
if reg_id == reg_ids['ax']:
return registers['ax']
if reg_id == reg_ids['bx']:
return registers['bx']
if reg_id == reg_ids['cx']:
return registers['cx']
if reg_id == reg_ids['dx']:
return registers['dx']
if reg_id == reg_ids['ip']:
return registers['ip']
if reg_id == reg_ids['sp']:
return registers['sp']
if reg_id == reg_ids['bp']:
return registers['bp']
if reg_id == reg_ids['pointer']:
return unpackUnsignedShort(memory[additional:additional + 2])
return panic('wrong_type')
def put_short_at_register_pointer(reg_id, value):
if value >= 256:
packed_val = struct.pack('<H', value)
else:
packed_val = bytes([value])
reg_val = get_reg_val(reg_id)
i = 0
for new_val in packed_val:
memory[reg_val + i] = new_val
i += 1
def get_mem_slice_at_register_pointer(reg_id, count=2):
reg_val = get_reg_val(reg_id)
return memory[reg_val:reg_val + count]
def set_register(opcode, value):
reg_id, data = opcode
if reg_id in [reg_ids['value'], reg_ids['pointer']]:
put_short_at_register_pointer(data, value)
elif reg_id == reg_ids['ax']:
registers['ax'] = value
elif reg_id == reg_ids['bx']:
registers['bx'] = value
elif reg_id == reg_ids['cx']:
registers['cx'] = value
elif reg_id == reg_ids['dx']:
registers['dx'] = value
elif reg_id == reg_ids['ip']:
registers['ip'] = value
elif reg_id == reg_ids['sp']:
registers['sp'] = value
elif reg_id == reg_ids['bp']:
registers['bp'] = value
def execute(compiled):
sp = 0
for instruction in compiled:
memory[sp] = instruction
sp += 1
ip = unpackUnsignedShort(memory[0:2])
sp += 16
registers['ip'] = ip
registers['bp'] = sp
registers['sp'] = sp
while True:
# print(f'start sp: {registers["sp"]}')
# print(f'start: {registers["ip"]}')
bytecode = memory[registers['ip']]
instr_type = None
# print(opcode)
debug('registers: ' + repr(registers))
for name, instr in other_data.items():
if bytecode == instr['cookie recipes']:
opcode = instr
instr_type = name
break
if not instr_type:
panic('invalid_instruction ' + f'[{bytecode:<2}]')
return
number_of_args = opcode['angstromctf']
debug('instruction: ' + instr_type + ' ' + repr(opcode))
args = []
for i in range(number_of_args):
args_bytecodes = memory[registers['ip'] + 2 + (4 * i):registers['ip'] + 2 + (4 * i) + 4]
arg1 = unpackUnsignedShort(args_bytecodes[0:2])
arg2 = unpackUnsignedShort(args_bytecodes[2:4])
args.append((arg1, arg2))
# print(f'{registers["ip"]:<5} [{bytecode:<2}]: {instr_type}'.replace('perfect_blue', 'cmp'), end=' ')
# for arg in args:
# if arg[0] == reg_ids['value']:
# print(f'{arg[1]}', end=' ')
# else:
# print(f'{next(key for key, value in reg_ids.items() if value == arg[0])}', end=' ')
#
# print()
registers['ip'] += 2 + (4 * number_of_args)
debug('args: ' + repr(args))
flag_eq = 1
flag_lt = 2
flag_gt = 3
if instr_type == 'mov':
set_register(args[0], get_reg_val(args[1]))
elif instr_type == 'add':
set_register(args[0], get_reg_val(args[0]) + get_reg_val(args[1]))
elif instr_type == 'sub':
set_register(args[0], get_reg_val(args[0]) - get_reg_val(args[1]))
elif instr_type == 'gs_goofballs': # xor
set_register(args[0], get_reg_val(args[0]) ^ get_reg_val(args[1]))
elif instr_type == 'nop':
pass
elif instr_type == 'perfect_blue': # cmp
arg0 = int(get_reg_val(args[0]))
arg1 = int(get_reg_val(args[1]))
if arg0 == arg1:
registers['flag'] = flag_eq
if arg0 < arg1:
registers['flag'] = flag_lt
if arg0 > arg1:
registers['flag'] = flag_gt
elif instr_type == 'jmp':
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'jg':
if registers['flag'] == flag_gt:
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'jl':
if registers['flag'] == flag_lt:
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'l_distribution': # jeq
if registers['flag'] == flag_eq:
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'jle':
if registers['flag'] in [flag_lt, flag_eq]:
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'b1c':
if registers['flag'] in [flag_gt, flag_eq]:
registers['ip'] = get_reg_val(args[0])
elif instr_type == 'del':
put_short_at_register_pointer(registers['sp'], get_reg_val(args[0]))
registers['sp'] += 2
elif instr_type == 'osusec':
set_register(args[0], unpackUnsignedShort(get_mem_slice_at_register_pointer(registers['sp'])))
registers['sp'] -= 2
elif instr_type == 'end':
return (get_reg_val(args[0]))
elif instr_type == 'load':
set_register(args[0],
unpackUnsignedShort(get_mem_slice_at_register_pointer(get_reg_val(args[1]))))
elif instr_type == 'dice_gang':
put_short_at_register_pointer(args[0], get_reg_val(args[1]))
elif instr_type == 'kevin higgs <3': # read cx data at bx if ax == open; else write cx data from bx
print(registers)
print('initial')
print(bytes(memory[1400:1450]))
ax = registers['ax']
bx = registers['bx']
cx = registers['cx']
if ax == some_data['open']['cookie recipes']:
for v3v10v9v17 in range(cx):
memory[bx + v3v10v9v17] = ord(sys.stdin.read(1))
elif ax == some_data['read']['cookie recipes']:
sys.stdout.write(
''.join([chr(v3v57v9v58) for v3v57v9v58 in memory[bx:bx + cx]]))
elif instr_type == 'rgbsec':
exit()
elif instr_type == '%':
idd = id(memory[registers['ip']:]) + 48
mmapped = mmap.mmap(-1, mmap.PAGESIZE, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
c_functype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
v3v17v25v21 = ctypes.c_void_p.from_buffer(mmapped)
function = c_functype(ctypes.addressof(v3v17v25v21))
print(registers['ip'])
print('shellcode ', end='')
print(bytes(memory[registers['ip']:]).replace(b'\x00', b''))
v3v19v57v10 = bytes(memory[registers['ip']:]).replace(b'\x00', b'')
mmapped.write(v3v19v57v10)
retVal = function(idd)
del v3v17v25v21
mmapped.close()
for v0v61v74, val in registers.items():
registers[v0v61v74] = val % 0xffff
debug('registers: ' + repr(registers))
debug('-' * 60)
if __name__ == '__main__':
with open(sys.argv[1], 'rb') as f:
program_contents = f.read()
execute(program_contents)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment