← Back to Write-Ups

Context

This challenge presents an HTML page with intentionally obfuscated JavaScript. The goal is to analyze the code and find the hidden flag inside, without guessing it.

What is Obfuscation?

Obfuscation is the practice of making code readable by machines but hard to understand for humans. Unlike encryption, the code remains functional and accessible — it's just intentionally obscured.

Note: Obfuscation is not a security measure. The code remains fully accessible to the user and can always be analyzed.

When landing on the page, we are prompted to enter a password — curious, I typed one at random.

Obviously that's wrong — and it's mocking me.

After that, a blank page appears.

Source Code Analysis

By opening the page and inspecting the code (F12 → Sources), we find the following JavaScript:

function dechiffre(pass_enc){
    var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
    var tab  = pass_enc.split(',');
    var tab2 = pass.split(',');
    var i,j,k,l=0,m,n,o,p = "";
    // ... complex logic ...
    p += String.fromCharCode(tab2[17]);
    pass = p; return pass;
}

String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));

h = window.prompt('Entrez le mot de passe / Enter password');
alert( dechiffre(h) );

Key Observation: The Red Herring

The function dechiffre(pass_enc) does receive the user's input as a parameter, but following the execution reveals that it completely ignores it. It always returns the contents of the internal variable pass, a hardcoded sequence of ASCII values.

No matter what you type in the prompt, the function always returns FAUX PASSWORD HAHA. This is intentional — the real challenge lies elsewhere.

Step 1 — Decoding the Hex String

The most interesting line is this one:

String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));

Each \xNN is a character encoded in ASCII hexadecimal. Each \xNN = one character. For example:

We can use this handy ASCII table to convert hex to decimal:

ASCII table
HexDecimalCharacter
\x35535
\x35535
\x2c44,
\x35\x3653 + 545, 6
\x2c44,
.........

Decoding the full string gives us:

55,56,54,79,115,69,114,116,107,49,50

Step 2 — Applying String.fromCharCode

These values are then passed to String.fromCharCode() via dechiffre(). Each number maps to an ASCII character.

I wrote a small Python script to decode the decimal sequence into text:

# Decode decimal values to text
values = "55,56,54,79,115,69,114,116,107,49,50"

flag = ""
for val in values.split(','):
    flag += chr(int(val))

print("Flag:", flag)

Output:

Flag: 786OsErtk12

Conclusion

This challenge highlights two fundamental concepts in web security:

Takeaway: Any JavaScript running on the client side is fully accessible to the user. Never store secrets, passwords, or flags in front-end JS — even if it's obfuscated.

Flag

786OsErtk12

Have a good day! — @Swif2D

← Back to Write-Ups