$ cat writeup.md…
$ cat writeup.md…
umdctf
Task: a Vulkan-based exchange service on Mesa lavapipe lets the user quote positions through vkUpdateDescriptorSets, but the chosen array element is attacker-controlled despite a single-descriptor binding. Solution: align the resulting out-of-bounds descriptor write onto the settlement clearing buffer descriptor, retarget it to an attacker-owned account buffer, then settle rounds to copy out the flag and read it back with audit_account.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
No original organizer description was preserved in the local workspace files.
English summary: the service exposes a small trading interface backed by Vulkan compute resources. The intended bug is not in the shader itself, but in how the host program updates storage-buffer descriptors for market quotes, which lets us corrupt a neighboring descriptor set and redirect a later GPU copy into memory we control.
The important host helper is update_storage_desc(), which wraps vkUpdateDescriptorSets() with:
.dstBinding = binding, .dstArrayElement = array_elem, .descriptorCount = 1,
For quote_position(), array_elem comes directly from the user-supplied price_index. The program also enforces:
MIN_PRICE_INDEX = 32768descriptorCount = 1So every valid quote writes far beyond the single descriptor that should exist in quote_book binding 0. On lavapipe from Mesa 22.3.6 this becomes exploitable because:
That means a very large dstArrayElement can walk out of the quote_book allocation and start overwriting descriptors in a later descriptor set.
With one market configured as:
outcome_slots = 32768memo_bytes = 0the target settlement_book descriptors are misaligned relative to the oversized quote_book walk. Only partial overlaps at indices 32775 through 32777 are reachable, and those corruptions crash instead of producing a useful retargeted descriptor.
memo_bytes = 8The trick is to create one market with memo_bytes = 8.
That adds a 40-byte shift in lavapipe's descriptor layout:
...
$ grep --similar