# Confiant CrackMe Report For this CrackMe, I was tasked with interacting with and manipulating the given page in such a way that would reveal the "hidden treasure". I used my browser's native tools such as the inspect tool, the JavaScript console, and viewing the page source in order to reverse-engineer the conditions required to reveal the treasure and crack the puzzle. A documentation of the solution as well as my problem-solving process and methodology follows. ## Solution :::info This crack depends on manipulating your browser's `userAgent` string and is thus best performed in Firefox, where the `userAgent` can be manipulated freely and persistently (in Chrome and Chromium-based browsers it can only be changed temporarily while the developer tools are active) ::: ### Modifying the browser's UserAgent The browser's `userAgent` string must first be set such that the string `'BLACKSEA'` is at index 9 (10th character). This can be done in Firefox by navigating to `about:config` and adding a string for the `general.useragent.override` setting, such as `'aaaaaaaaaBLACKSEA'`. An example is shown below: ![](https://hackmd.io/_uploads/SJAgAvtC2.png) ### Moving the "X" to the correct locations to acquire runes The `X` on the page is interactible and can be dragged and dropped. Furthermore, once it is moved, a byte-encoded string representing the `X`'s location will appear and update continually. Once a valid `userAgent` has been set, the `X` must be moved sequentially to three precise locations to acquire "runes" corresponding to each location. The following locations are given as numbers in the format `[y,x]` and then their byte-encoded representations, which is what is displayed by the webpage (with some minor alternations). #### alpha This rune is located at `[82,73]`, or `['ODI=','NzM=']` ![](https://hackmd.io/_uploads/rkZzRwtAn.png) #### beta This rune is located at `[80,76]`, or `['ODA=','NzY=']`. ![](https://hackmd.io/_uploads/SyaQ0wt0h.png) #### gamma This rune is located at `[69,89]`, or `['Njk=','ODk=']`. The treasure is revealed immediately after passing over this location, so the displayed coordinates in the screenshot are slightly off. ![](https://hackmd.io/_uploads/r1Gr0vY03.png) ## Methodology I didn't really use any special tools for this challenge, just the normal developer tools (inspect tool, etc.) available through my browser, as well as some Googling for fields or functions I wasn't immediately/intimately familiar with. Overall, my problem-solving process had roughly 5 phases, which are documented below. ### Phase 1: Getting my bearings I approached this challenge by first looking at the DOM structure to understand the layout of the page. Upon opening the inspect tool, I was immediately taken to the page sources view and presented with a suspended JavaScript debugger and script for the page source. I extrapolated that this debugger was suspending the underlying loop that checked for the proper conditions for revealing the treasure. After looking at the script for a while without much luck understanding it, I closed the dev tools and tried interacting with the page. At this point, I found out that **the `X` could be moved by dragging/dropping, and also that the `gps` div filled with a string that changed as the `X` was moved**. A little more experimentation confirmed that the string likely represented a coordinate system. With this in mind, I returned to examining the script to try and understand how these strings were encoded. ### Phase 2: Finding a clue Scanning the script with fresh eyes, I noticed that there were a lot of strings being combined that seemed to have a similar format to the string in the `gps` div. Examining how these were being used, I noticed that the variable `b`, which was aliasing the native function `atob`, was being called on many of these strings. **When I tried using the console to call `atob` on one of the `gps` strings, it returned a string representing a coordinate!** I spent a few minutes tinkering with the DOM in the inspect tool to try to render the "translation" of the `gps` strings, but after a few unsuccessful attempts I returned to examining the script, recognizing that this endeavor was not critical to unlocking the puzzle. ### Phase 3: Translation I spent the next quarter hour or so using the console to "translate" and recording the meanings of various parts of the script. This also helped me gain a more in-depth understanding of what various parts of the script were doing. Some key pieces of information I recorded during this time were: * **The contents of the `spikes` array:** `['navigator', 'userAgent', 'indexOf', 'LAMBERT', 'RIPLEY', 'ALDERSON', 'BLACKSEA', 'dir', 'clear', 'clue', 'canary', 'alpha', 'beta', 'gamma']`, obtained by mapping a composition of the `b` and `tY` functions to each value of the array. * The value of `ee` - just the native `eval()` function * Line 67 - `eval('debugger')`, which I presume to be the line that triggered the debugger Most critically, I ran **the code on line 75 - `eval('alert("Congratulations Oh 1337 One! You have found my treasure!")')`**, which manually triggered the alert representing the puzzle's solution. I now had identified the line I wanted the script's execution to reach. ### Phase 4: `clue` validation and `userAgent` manipulation Lines 69-74 contain the conditions that need to be met for the final line to be triggered. A cursory glance at the `IChing` function both confirmed that the `X`'s coordinates were being encoded via `btoa` and displayed in the `gps` div, and that **the first condition (`runes.length > 2`) could be fulfilled by moving the `X` to a series of 3 locations**, each of which would `push` another word (`alpha`, `beta`, then `gamma` from the `spikes` array) onto `runes`. Leaving the decoding of the location aside for the time being, I decided to focus on the second condition, which was that the sum of the character codes for each letter in the `clue` variable would sum up to 469. The three possible values of `clue` were `'LAMBERT'` (the default), `'RIPLEY'`, and `'ANDERSON'`. The following simple one-liner added up the sum of the character code values for a given clue: ```javascript [...'LAMBERT'].map((x) => x.charCodeAt(0)).reduce((a, v) => a + v) ``` Which gave the following sums: * `'LAMBERT'` --> 519 * **`'RIPLEY'` --> 469** * `'ALDERSON'` --> 600 The condition for setting `clue` to `'RIPLEY'`, translated from line 47, was that `window['navigator']['userAgent'].indexOf('BLACKSEA') == 9`, or that **the string `'BLACKSEA'` appeared at index 9 of the browser's `userAgent` string**. A quick Google search later and I had found a way to manipulate the `userAgent` on the browser I was using (Vivaldi, a Chromium-based browser). However, the changes did not persist after I closed the developer tools, and I was unable to interact with the `X` while the developer tools were open, so I decided to switch to Firefox, which had a much simpler way to modify the `userAgent` persistently, as outlined [above](##Modifying-the-browser%E2%80%99s-UserAgent). After making this change, I could confirm that the value of `clue` had changed from `'LAMBERT'` to `'RIPLEY'` as desired. ### Phase 5: Decoding locations The final phase consisted of decoding the appropriate locations to move the `X` to in order to add to the `runes` array. The `IChing` function, which performs location validation, **checks the location against the character code of each letter in `clue`**. Thus, I extracted an array of character codes for each letter in `'RIPLEY'` as well as byte-encoding them using `btoa`, which would give me the same representation used by the `gps`: ```javascript [...'RIPLEY'].map((x) => x.charCodeAt(0)) --> [ 82, 73, 80, 76, 69, 89 ] .map(btoa) --> [ "ODI=", "NzM=", "ODA=", "NzY=", "Njk=", "ODk=" ] ``` Giving me the (`y,x`) coordinates: * `82,73`, or `'ODI=','NzM='` * `80,76`, or `'ODA=','NzY='` * `69,89`, or `'Njk=','ODk='` After this, I just needed to move the `X` sequentially to each location (a feat of no small mouse precision) and the alert on line 75 was triggered, solving the puzzle!