2026-05-29 23:32:05 +02:00
2024-09-13 23:21:32 +10:00
2024-09-13 23:21:32 +10:00
2024-01-05 17:51:01 +01:00
2024-02-05 18:22:36 +01:00
2024-09-13 23:21:32 +10:00
2024-09-13 23:21:32 +10:00
2024-01-05 17:01:10 +01:00
2024-01-10 16:02:51 +01:00
2026-05-29 23:32:05 +02:00
2024-01-29 17:37:10 +01:00

CoPaaS — Compiler-oriented Programming as a Service

A startup offers an emulation service with a JIT engine for a custom instruction set. The ISA is small and has no jumps, branches, or function calls — so it is really just a glorified pocket calculator. You hand it a program, it compiles that program to native x86-64 at runtime, runs it, and tells you the result.

In the free tier, every program runs inside a sandbox. Pay for the premium tier and the sandbox comes off — the startup trusts its paying customers.

How it works

On connect you may activate premium mode, then you enter a loop: submit a program, the service JIT-compiles and runs it, and prints the result. Repeat as often as you like.

Each round:

  1. You are asked for a program length n (1 ≤ n ≤ 0x1000).
  2. You send n instructions as raw fixed-size records (see format below).
  3. The service validates the program, compiles it to x86-64, and executes it.
  4. It prints Your program exited with <code>!, where <code> is the result.

The machine

  • Registers (14): named AN. All registers are zeroed before your program runs.
  • Result: the program's exit code is the low 8 bits of register A.
  • No control flow: there are no jumps, branches, or calls.

Instructions

Each instruction is a fixed-size record with the fields:

opcode | reg1 | (padding) | reg2_or_immediate

reg2_or_immediate is interpreted as a second register for register-form instructions, or as a 32-bit immediate for immediate-form instructions.

Opcode Form Effect
LOADI reg1, imm reg1 = imm
ADDI reg1, imm reg1 += imm
ADD reg1, reg2 reg1 += reg2
SUB reg1, reg2 reg1 -= reg2
COPY reg1, reg2 reg1 = reg2

Programs are validated before compilation: any out-of-range opcode or register is rejected and the round is discarded. The compiler also applies small optimizations — consecutive ADDIs to the same register are folded together, redundant consecutive LOADIs collapse to one, and a COPY of a register onto itself is dropped.

Execution model

  • Free / demo tier: the compiled code runs in a forked child under a seccomp-BPF sandbox that permits only read, write, execve, and exit_group. The child runs on a fresh stack at a randomized address, and stdin, stdout, and stderr are all closed first — so the only information that leaves the child is its exit code (the low byte of A).
  • Premium tier: unlocked by supplying the correct activation key. Compiled code then runs in-process with no sandbox.

Mitigations

Full RELRO · Stack Canary · NX · PIE

Goal

Break out of the calculator and run code of your choosing — capture the flag via /bin/get_flag (or a shell). The interesting surface is the JIT: what the code generator emits for your instructions is not always what you'd expect.

Description
Challenge for the practical course binary exploitation at TUM in WS 23/24.
Readme MIT 4.6 MiB
Languages
TeX 30.1%
Python 29.9%
C 27.3%
Dockerfile 8.4%
Shell 2.4%
Other 1.9%