-
-
Save srikavin/cce2544f70b8283309ac088d274b3b06 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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