Description
Try to find the password again. Check the HTML source.
Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1View the page source
ObservationThe description says to check the HTML source. So the password validation, correct password included, sits in a client-side script tag you can read straight from the raw page source.Open the challenge URL and view source (Ctrl+U). Find the JavaScript that validates the password. The logic will be obfuscated - variables may have random names and strings may be split into pieces.What didn't work first
Tried: Opening DevTools and looking at the Elements panel instead of View Source.
The Elements panel shows the live DOM after JavaScript has run, which can differ from the original source, and inline scripts may appear collapsed or reformatted. Ctrl+U gives you the raw server-delivered HTML, which is what you want when hunting for the validation script.
Tried: Looking only at the visible page content for the password, rather than the JS.
Client-side validation challenges embed the comparison logic inside a script tag, not in any visible element. The password will not appear in the page text - it is buried inside JavaScript string operations that only show up when you read the source.
Learn more
Client-side password validation is fundamentally insecure because the browser must have the complete validation logic (including the correct password) to check your input. Obfuscation only adds friction, not real security.
Common obfuscation techniques include: splitting strings into parts and joining them, using character codes instead of string literals, renaming variables to meaningless names, and reversing strings.
Step 2Deobfuscate the JavaScript
ObservationThe validation script uses a lookup function such as _0x4b5b, with numeric indices and substring position checks instead of plain comparisons. The password is assembled from encoded fragments, so each one needs resolving in the browser console before the logic is readable.Paste the obfuscated JavaScript into an online beautifier (like beautifier.io) or use browser DevTools. Trace the string operations - look for concatenation, split, reverse, join, or charAt calls that reconstruct the password.What didn't work first
Tried: Trying to read the obfuscated code top-to-bottom without evaluating subexpressions first.
Obfuscated JS uses lookup tables, functions like _0x4b5b, where each call returns a string fragment. Tracing the logic in your head without resolving those first just gets confusing. Paste the lookup function and its arguments into the console to decode each fragment, then trace the assembly.
Tried: Running a generic JS deobfuscator tool and expecting a clean, readable password to appear.
Automated deobfuscators reformat control flow and rename variables, but they rarely evaluate runtime expressions. The password fragments are still encoded inside array entries or function return values. You still need to manually evaluate the validation expression in the console after beautifying.
Learn more
A useful trick: open the browser console and type the name of any variable you see in the obfuscated JS. The console will show you its current value. You can also call the validation function directly with test values to observe its behavior.
If the password is assembled from parts (e.g.,
var a = 'pic'; var b = 'oCTF';), just concatenate them mentally. Check for array operations too - sometimes the flag is stored as a reversed or shuffled array of characters.In client-side-again specifically, the obfuscation uses a lookup function (e.g.
_0x4b5b) that maps numeric indices to string fragments, and validates the password through overlappingsubstring()position checks rather than plain concatenation. Evaluate the lookup function in the browser console to decode each argument, then assemble the substrings in positional order.Step 3Extract the flag from the JS
ObservationThe deobfuscated expressions resolve to several string fragments. Assembled in the order the equality check uses them, they form a complete picoCTF{...} flag, so evaluating that final expression gives the answer.Once you understand the string operations, manually execute them (in your head, on paper, or in the browser console) to reconstruct the final password/flag string.What didn't work first
Tried: Submitting the reconstructed string without the picoCTF{} wrapper.
The script may check only the part between the braces and concatenate the picoCTF{} wrapper elsewhere in the source. Extract just the inner value and the submission fails. Look for whatever string in the JS assembles the full picoCTF{...} form.
Tried: Concatenating the string fragments in the order they appear in the source file rather than the order the code assembles them.
Obfuscated scripts often define their string pieces out of sequence and assemble them by index reference, so reading top to bottom gives the wrong order. Evaluate the final expression the validation function uses, usually an equality check against a constructed string, in the console.
Learn more
The flag will either be in the standard picoCTF format directly, or it will be the input that passes the validation check. If the JS checks your input against a transformed version, reverse the transformation.
Interactive tools
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
- Regex TesterTest regular expressions against a string with live match highlighting, flag toggles, and common CTF pattern shortcuts.
Flag
Reveal flag
picoCTF{not_this_again_...}
The flag is assembled from split string parts in the JavaScript source - concatenate them in the correct order.