campctf2023-chall-tis256

Zachtronics TIS100-inspired reversing challenge for CampCTF 2023
git clone https://git.sinitax.com/sinitax/campctf2023-chall-tis256
Log | Files | Refs | Submodules | README | sfeed.txt

memory.py (3625B)


      1import sys
      2
      3memory_block_start = """
      4    mov UP, LEFT
      5
      6    mov UP, ACC
      7    mov UP, LEFT
      8
      9    jnz is_write
     10    mov LEFT, DOWN
     11    mov 0, DOWN
     12    mov UP, DOWN
     13    mov LEFT, NIL
     14    jmp wrap
     15
     16is_write:
     17    mov LEFT, DOWN
     18    mov 1, DOWN
     19    mov UP, ACC
     20    xor LEFT
     21    mov ACC, DOWN
     22    swp
     23
     24wrap:
     25    mov DOWN, ACC
     26    xor LEFT
     27    mov LEFT, RIGHT
     28    mov ${{addr}}, RIGHT
     29    mov ${OP_ACK}, RIGHT
     30    mov ACC, RIGHT
     31    mov ${OP_NIL}, RIGHT
     32"""
     33
     34memory_block_start_left = """
     35    mov RIGHT, ACC
     36    swp
     37    mov RIGHT, ACC
     38    mov ACC, RIGHT
     39    mov ACC, RIGHT
     40    mov ACC, RIGHT
     41    swp
     42    mov ACC, RIGHT
     43"""
     44
     45memory_block_start_right = """
     46    mov LEFT, UP
     47"""
     48
     49code_memory_split = """
     50    mov UP, ACC
     51    mov ACC, LEFT
     52    mov ACC, RIGHT
     53
     54    mov UP, ACC
     55    mov ACC, LEFT
     56    mov ACC, RIGHT
     57
     58    mov UP, ACC
     59    mov ACC, LEFT
     60    mov ACC, RIGHT
     61
     62    mov ANY, ACC
     63    add ANY
     64    mov ACC, UP
     65"""
     66
     67code_memory_split_rev = """
     68    mov UP, ACC
     69    mov ACC, RIGHT
     70    mov ACC, LEFT
     71
     72    mov UP, ACC
     73    mov ACC, RIGHT
     74    mov ACC, LEFT
     75
     76    mov UP, ACC
     77    mov ACC, RIGHT
     78    mov ACC, LEFT
     79
     80    mov ANY, ACC
     81    add ANY
     82    mov ACC, UP
     83"""
     84
     85code_memory_cell = """
     86    mov 0x{val:02x}, ACC
     87    sav
     88start:
     89    mov UP, ACC
     90    xor {idx}
     91    jnz skip
     92    mov UP, ACC
     93    jnz WRITE
     94    mov UP, NIL
     95    swp
     96    mov ACC, UP
     97    sav
     98    jmp start
     99write:
    100    mov UP, ACC
    101    swp
    102    mov ACC, UP
    103    jmp start
    104skip:
    105    mov UP, NIL
    106    mov UP, NIL
    107    mov 0, UP
    108    jmp start
    109"""
    110
    111code_memory_right = """
    112mov LEFT, RIGHT
    113mov LEFT, RIGHT
    114mov LEFT, RIGHT
    115mov RIGHT, LEFT
    116"""
    117
    118code_memory_right_corner = """
    119mov LEFT, DOWN
    120mov LEFT, DOWN
    121mov LEFT, DOWN
    122mov DOWN, LEFT
    123"""
    124
    125code_memory_left = """
    126mov RIGHT, LEFT
    127mov RIGHT, LEFT
    128mov RIGHT, LEFT
    129mov LEFT, RIGHT
    130"""
    131
    132code_memory_left_corner = """
    133mov RIGHT, DOWN
    134mov RIGHT, DOWN
    135mov RIGHT, DOWN
    136mov DOWN, RIGHT
    137"""
    138
    139class BlockMap(dict):
    140    def __setattr__(self, key, value):
    141        if key in self.__dict__:
    142            raise ValueError("Already exists")
    143        super().__setattr__(key, value)
    144
    145def gen_memory(blocks, start, idx_offset, idx, depth, contents):
    146    if depth <= 0:
    147        addr = idx_offset + idx
    148        blocks[start] = code_memory_cell.format(idx=addr,val=addr^contents[idx])
    149        return
    150    sx, sy = start
    151    blocks[start] = code_memory_split_rev if depth % 2 else code_memory_split
    152    sidelen = int(2**(depth-1))
    153    for i in range(1, sidelen):
    154        blocks[(sx + i, sy)] = code_memory_right
    155        blocks[(sx - i, sy)] = code_memory_left
    156    blocks[(sx + sidelen, sy)] = code_memory_right_corner
    157    blocks[(sx - sidelen, sy)] = code_memory_left_corner
    158    gen_memory(blocks, (start[0] + sidelen, start[1] + 1),
    159        idx_offset, idx + 2**(depth-1), depth - 1, contents)
    160    gen_memory(blocks, (start[0] - sidelen, start[1] + 1),
    161        idx_offset, idx, depth - 1, contents)
    162
    163def write_blocks(blocks, filepath, addr_tmpl):
    164    with open(filepath, "w+") as f:
    165        for i,(x,y) in enumerate(blocks):
    166            f.write(f"tpu X{x} Y{y}\n")
    167            if i == 0:
    168                f.write("\t## ${" + addr_tmpl + "}\n")
    169            for l in blocks[(x,y)].strip("\n").split("\n"):
    170                f.write(f"{l}\n")
    171            f.write(f"end\n")
    172            f.write("\n")
    173
    174if __name__ == "__main__":
    175    blocks = {}
    176    blocks[(0, 0)] = memory_block_start.replace("{addr}", sys.argv[5])
    177    blocks[(-1, 0)] = memory_block_start_left
    178    blocks[(1, 0)] = memory_block_start_right
    179    gen_memory(blocks, (0, 1), int(sys.argv[2]), 0, int(sys.argv[3]),
    180        open(sys.argv[4], "rb").read().ljust(256, b"\x00"))
    181    write_blocks(blocks, sys.argv[1], sys.argv[5])