The VM exposes a capability environment (caps) that restricts filesystem reads to /data/public via key 0x0a. A stale inline cache in opcode 0x21 (lookup) can be abused after opcode 0x70 (freeze/reorder) to remap the cached slot for key 0x0a to slot 0, which holds the absolute read function (key 0x00). Using this, the program reads /flag.txt.
The program input is a hex string that decodes to:
nr (1 byte): number of registersconst_count (1 byte)String constant format:
0x02 [u16 length little-endian] [bytes...]
0x02 (op b): load capability object by name0x20 (op c): get property from env by key0x21 (op d): lookup in env chain with inline cache0x70 (op k): freeze env (convert to dictionary, reorder slots)0x60 (op h): relative jump (signed 16-bit)0x30 (op e): call function0x31 (op f): returnop d caches the slot index of a key in an environment. op k converts a slot-based env to a dictionary and reorders keys by numeric sort, but it does not bump the cache version. The cached slot index is then stale and can point to a different key after reordering.
In the root env:
0x0a => relative read (/data/public)0x00 => absolute read (normally unreachable)If the cache was created for key 0x0a and then the env is reordered, the cached slot can resolve to key 0x00.
caps and fetch caps[3] (io env).op d on key 0x0a once to populate the inline cache.op k on the same receiver/key to reorder slots.op d to retrieve key 0x00 (absolute read)."/flag.txt" and return.Hex input (paste into nc):
0703020400636170730209002f666c61672e7478740201003102000020010003210203010a6104090070010a01040260eeff0105013006020301053106
uoftctf{c4ch3_m3_1n11n3_h0w_80u7_d4h??}