Skip to content

ClaudeMaxUser/speak-the-creed

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

speak-the-creed

JavaScript Node.js License Category Difficulty Theme

"A Mandalorian never removes their helmet. But some doors demand a creed."

A beginner CrackMe written in JavaScript — a focused runtime-obfuscation exercise themed around The Mandalorian. The project demonstrates how to serialize a self-contained validator, encrypt it at build-time, and reconstruct it at runtime so the validation logic isn't plainly visible in the distributable.

The challenge: figure out what to say when the program asks you to Speak the Creed.


The Challenge

node MandoCrackme.js
  ██╗    ██╗██╗  ██╗ ██████╗     ██╗███████╗
  ██║    ██║██║  ██║██╔═══██╗    ██║██╔════╝
  ██║ █╗ ██║███████║██║   ██║    ██║███████╗
  ██║███╗██║██╔══██║██║   ██║    ██║╚════██║
  ╚███╔███╔╝██║  ██║╚██████╔╝    ██║███████║
   ╚══╝╚══╝ ╚═╝  ╚═╝ ╚═════╝     ╚═╝╚══════╝
        ████████╗██╗  ██╗███████╗
           ██╔══╝██║  ██║██╔════╝
           ██║   ███████║█████╗
           ██║   ██╔══██║██╔══╝
           ██║   ██║  ██║███████╗
           ╚═╝   ╚═╝  ╚═╝╚══════╝
                W A Y

  ┌─────────────────────────────────────────┐
  │  A Mandalorian never removes their       │
  │  helmet. But some doors demand a creed.  │
  └─────────────────────────────────────────┘

  Speak the Creed, Foundling: _

If you speak truly, the Covert welcomes you. If not — I have spoken.


Prerequisites

Just Node.js. No dependencies, no npm install.

node --version  # anything v14+ works

How It Works

This project is an exercise in runtime code obfuscation — the validation logic is not present in plaintext inside the distributable. Instead the validator is serialized and encrypted at build-time, then rebuilt and executed at runtime.

The Big Picture

[Encrypt.js]                      (build time, run once)
        │
        │  1. serialize validate() to a string
        │  2. XOR-encrypt it with key 0x1337
        │  3. output: encrypted byte array
        │
        ▼
[MandoCrackme.js]                (ships to the user)
        │
        │  at runtime:
        │  4. XOR-decrypt the byte array → JS source string
        │  5. eval() the string → live function
        │  6. call it with the user's input
        │
        ▼
   Correct / Wrong

Concept Map (build-time → runtime)

A concise mapping of the project's build-time and runtime steps (all in JavaScript):

  • Build-time serialization: Function.prototype.toString() turns the validate() function into source text.
  • Build-time encryption: Encrypt.js XOR-encodes the serialized source into a numeric byte array (ENCRYPTED_PAYLOAD).
  • Embedded payload: the runtime script ships the encrypted numeric array; the validator's source isn't present in plain text.
  • Runtime reconstruction: xorDecrypt() converts the byte array back to the original source string, and eval("(" + funcSource + ")") recreates the callable function.
  • Execution: call the reconstructed validate(input) to check user input.
  • Purpose: keep validation logic out of plaintext to raise the bar for casual static analysis.

File Breakdown

MandoCrackme.js — the CrackMe runtime

This is the file the player runs. It contains:

  • ENCRYPTED_PAYLOAD — the serialized validate() source, XOR-encrypted and stored as a numeric array.
  • xorDecrypt() — decrypts the payload at runtime using key 0x1337.
  • Reconstruction & execution — the decrypted source is parsed (via eval) into a function and executed with the user's input.
  • The flag comparison is case-sensitive.
// Runtime flow (simplified)
const funcSource = xorDecrypt(ENCRYPTED_PAYLOAD, 0x1337);
const validateFn = eval("(" + funcSource + ")");
return validateFn(input);

Encrypt.js — build-time encryption tool

You don't need this to play the crackme. Run it when you want to generate or update the encrypted payload embedded in MandoCrackme.js.

It does three things:

  1. Defines a self-contained validate() function (store any secret data inside the function so it does not rely on outer scope).
  2. Serializes it to a source string via Function.prototype.toString().
  3. XOR-encrypts the serialized source using key 0x1337 and prints the numeric array for embedding.

Run it to re-generate the payload:

node Encrypt.js
# outputs the new ENCRYPTED_PAYLOAD array → paste into Mando crackme.js

RodataBugDemo.js — closure-severing demo

This demo shows a common pitfall in JavaScript: if a validator depends on outer-scope variables (a closure), serializing it and re-evaluating it in a new, isolated scope severs that closure and those outer variables are no longer available.

The demo uses new Function(src) to simulate evaluating serialized code in an isolated context. It contrasts a broken validator that references an outer variable with a fixed, self-contained validator that keeps the secret data inside a local array.

node RodataBugDemo.js

What You Learn

  • How to serialize and reconstruct live functions at runtime in JS
  • XOR encryption/decryption with a multi-byte key
  • Why self-contained code matters when it's relocated (closure-severing)
  • How runtime reconstruction raises the bar for static analysis

License

MIT — do whatever you want with it. This is the Way.

About

A Mandalorian-themed CrackMe in JavaScript — XOR-encrypted validation logic reconstructed at runtime via eval(). Speak the Creed, Foundling.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors