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 1
View the page sourceObservationI noticed the challenge description explicitly says 'Check the HTML source,' which suggested the password validation logic, including the correct password, is embedded in a client-side script tag that can be read directly by viewing 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 already run, which can differ from the original source. Inline script tags may appear collapsed or reformatted. Ctrl+U (View Source) gives you the raw server-delivered HTML, which is what you want when hunting for the embedded 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 2
Deobfuscate the JavaScriptObservationI noticed the validation script used a lookup function (such as _0x4b5b) with numeric indices and substring position checks rather than plain string comparisons, which suggested the password was assembled from encoded fragments that needed to be resolved individually in the browser console before they could be read.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 full logic mentally without resolving those lookups first leads to confusion. Instead, paste the lookup function and its arguments into the browser console to decode each fragment individually, 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 3
Extract the flag from the JSObservationI noticed the deobfuscated expressions resolved to several string fragments that, when assembled in the order the validation equality check used them, formed a complete picoCTF{...} flag, which suggested manually or console-evaluating the final assembled expression to produce the submittable 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 validation script may check only the inner portion of the flag (the part between the braces), and concatenate the picoCTF{} wrapper separately in the source. If you only extract the inner value, the submission will fail. Look for any string in the JS that assembles the full picoCTF{...} format.
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 string pieces out of sequence and then assemble them using index references or array positioning. Reading top-to-bottom gives the wrong order. Evaluate the final expression the validation function uses (often an equality check against a constructed string) in the console to get the correctly ordered result.
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.