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

memory2.py (3745B)


      1import sys
      2
      3memory_block_start = """
      4    mov UP, LEFT
      5
      6    mov UP, ACC
      7    mov UP, LEFT
      8
      9    jne 0, 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_cell = """
     50    mov 0x{val:02x}, ACC
     51    sav
     52start:
     53    mov {inp}, ACC
     54    jne {idx}, fwd
     55    mov {inp}, ACC
     56    jne 0, WRITE
     57    mov {inp}, NIL
     58    swp
     59    mov ACC, {inp}
     60    sav
     61    jmp start
     62write:
     63    mov {inp}, ACC
     64    swp
     65    mov ACC, {inp}
     66    jmp start
     67fwd:
     68    mov ACC, {outp}
     69    mov {inp}, {outp}
     70    mov {inp}, {outp}
     71    mov {outp}, {inp}
     72    jmp start
     73"""
     74
     75pattern = """
     76#                   
     77#                   
     78# ##################
     79# #                #
     80# ################ #
     81#                  #
     82####################
     83
     84"""
     85assert(pattern.count("#") == 64)
     86pattern = pattern.strip("\n").split("\n")
     87
     88dirs = ((1, 0), (0, 1), (-1, 0), (0, -1))
     89
     90x,y = (0, 0)
     91seen = set()
     92seen.add((x,y))
     93path = [(x,y),]
     94while True:
     95    npos = None
     96    for dx,dy in dirs:
     97        nx,ny = x+dx,y+dy
     98        if nx < 0 or nx >= len(pattern[0]): continue
     99        if ny < 0 or ny >= len(pattern): continue
    100        if pattern[ny][nx] == "#" and (nx,ny) not in seen:
    101            npos = (nx,ny)
    102            break
    103    if npos is None:
    104        break
    105    x,y = npos
    106    seen.add((x,y))
    107    path.append((x,y))
    108
    109class BlockMap(dict):
    110    def __setattr__(self, key, value):
    111        if key in self.__dict__:
    112            raise ValueError("Already exists")
    113        super().__setattr__(key, value)
    114
    115def gen_memory(blocks, start, idx_offset, depth, contents, dtype):
    116    opposite = { "UP": "DOWN", "LEFT": "RIGHT", "RIGHT": "LEFT", "DOWN": "UP" }
    117    ports = { (-1, 0): "LEFT", (0, 1): "DOWN", (1, 0): "RIGHT", (0, -1): "UP" }
    118    sx,sy = start
    119    maxi = 2**depth-1
    120    for i in range(2**depth):
    121        fix = lambda x,y: (-x,y) if dtype == "left" else (x,y)
    122        x,y = fix(*path[i])
    123        px,py = (0,0) if i == 0 else fix(*path[i-1])
    124        nx,ny = (0,0) if i == maxi else fix(*path[i+1])
    125        pd = x-px,y-py
    126        nd = nx-x,ny-y
    127        inp = "UP" if i == 0 else opposite[ports[pd]]
    128        outp = opposite[inp] if i == maxi else ports[nd]
    129        addr = idx_offset + i
    130        cell = code_memory_cell.format(idx=addr,val=addr^contents[i],inp=inp,outp=outp)
    131        if dtype == "left":
    132            blocks[(sx+x,sy+y)] = cell
    133        elif dtype == "right":
    134            blocks[(sx+x,sy+y)] = cell
    135        else:
    136            assert(dtype == "straight")
    137            blocks[(sx,sy+i)] = cell
    138
    139def write_blocks(blocks, filepath, addr_tmpl):
    140    with open(filepath, "w+") as f:
    141        for i,(x,y) in enumerate(blocks):
    142            f.write(f"tpu X{x} Y{y}\n")
    143            if i == 0:
    144                f.write("\t## ${" + addr_tmpl + "}\n")
    145            for l in blocks[(x,y)].strip("\n").split("\n"):
    146                f.write(f"{l}\n")
    147            f.write(f"end\n")
    148            f.write("\n")
    149
    150if __name__ == "__main__":
    151    blocks = {}
    152    blocks[(0, 0)] = memory_block_start.replace("{addr}", sys.argv[5])
    153    blocks[(-1, 0)] = memory_block_start_left
    154    blocks[(1, 0)] = memory_block_start_right
    155    gen_memory(blocks, (0, 1), int(sys.argv[2]), int(sys.argv[3]),
    156        open(sys.argv[4], "rb").read().ljust(256, b"\x00"), sys.argv[6])
    157    write_blocks(blocks, sys.argv[1], sys.argv[5])