Visual Workflow Summary
Summary
Identifying hidden functions generated dynamically was at the core of this challenge. While the giveFlag parameter commented out in main.js seemed like a red herring at first, it was later conjoined with the hidden function "superSecretFunction" as a called parameter . However to seal the deal, the functions were dynamic, and had to be selected from the console prompt in my experience.
Technical Workflow Summary
Web application enumeration
Identify and pass JS functions to console
Red herring & pivot
Examine .wasm file and identify secret function
Research Web Assembly
Call dynamic function "superSecretFunction" with giveFlag parameter
Retrieve Flag
References
Web application enumeration
Initially browsing to the website provides a simple web application requiring us to ring the bell 9000 times. There is also a comment about untold secrets within the bell. So initially we are being given two paths forwards, ring the bell, or look inside the bell. This is an operational idea we will constantly by mimicking as we work through this challenge.
The page source reveals several scripts, the location of image assets, and the ding function. While nothing here is overtly revealing, it wouldn't be uncommon to attempt local overrides of the counter variable on the page element or within a script. However in a competitive CTF this is highly unlikely.
Identify and pass JS functions to console
Reviewing main.js we find a considerable amount of relevant information, that is somewhat fragmented leaving us to do the detective work.
Occam's Razor tells us that the simplest path is the likely one. We have to try the obvious of passing the giveFlag() function in the console. Sure enough when we pass the giveFlag() function we are met with a funny mp3 sound, and message suggesting we need to find a secret hidden function.
While we are not finished with passing functions to the console, I press forwards and try the winner() function which simply triggers the on page animations for winning.
Lastly, I tried to call the giveFlag function as a parameter to the winner function. This resulted in some error based output, but it was not helpful.
Red herring & pivot
At this point it was clear we had to find this hidden function. The ding.wasm was the next best place to start. The reason we wouldn't look at wasm_exec.js, this is just the framework operating as a loader for web assembly loading and execution.
Initially viewing the ding.wasm file from within the browser dev tools it was not practical. So instead we download the file for offline review.
Examine .wasm file and identify secret function
Looking through the wasm file was the next step as we pursued the secret hidden function. While my first pass through of the file did not yield anything, my second attempt involved adjusting my searches for upper case characters and that is when I found the superSecretFunction.
cat ding.wasm | grep Function
The next step seemed obvious, to call the superSecretFunction in the console. However, we were prompted with what I later learned was a dynamic function identifier. Calling this superSecretFunction with its identifier did now work. It simply provided a response
The response in the image below provided nothing that assist me directly in solving the challenge.
Research web assembly
From the article above, what I understood is that we are working with a dynamically generated function with a unique identifier appended to its name. This practice is often used in environments where multiple instances of the same function might be created, such as in certain frameworks or libraries. It helps ensure that each instance of the function has a distinct name to prevent conflicts.
The random string appended to the function name could be a hash, timestamp, or some other unique identifier generated by the environment. This technique is commonly used to maintain the integrity and isolation of functions within a system.
In our case, superSecretFunction_51366166 seems to be one instance of the superSecretFunction, and it's likely that there are others with different appended identifiers. When you see this, you can generally use any of the available instances interchangeably, as they likely perform the same functionality but in different contexts or instances.
Call dynamic function "superSecretFunction" with giveFlag parameter
When you read this blog, it will seem simple and the solution is quite quick once you know what to for. However for the purposes of not spreading imposter syndrome I do want to state that this took me quite a long time in actuality. I had explored several other paths and tried to actually convert the .wasm file to C and wabt files in an attempt to identify data that appeared unstructured, through decompilers and disassemblers like Ghidra and Binary Ninja.
Comments