AIS CTF Series – 2.2. – Code Breaker

Spexeah Community

Break the alpha-numeric code like in spy movies. Each guess returns a score. The higher the score the more characters you have correct and in the correct position.

Hackerman

This challenge follows on quite nicely from the Brutal Force challenge, however, this time we’re not given the hash of the key instead & if we open up our console we see the following:

Well that’s handy…

So just like last time, the challenge has given us a way to send in our code, but instead of a fail or pass, a promise is returned that will resolve to the score of our submission.

Initially, we thought the score returned would be the Hamming Distance of the input from the code, however, upon testing it became clear that we were being scored out of 100, so for every correct character in the 7 character input, the score would be increased by 1/7th or 14.285714285 – this can be seen below:

This can still roughly be described as a (non-bitwise) inverse hamming distance as a percentage like so:

Score = ((Length(Code)-HammingDistance(Input,Code))/Length(Code))*100)

The above would mean that if with a HammingDistance of 6 (six bytes/chars of the Input would need to change for Input & Code to match), and Code being 7 characters long, our Score would be 14.285714285.

With the above information in mind, much like last time, we need to construct a loop that will continuously guess until we’ve got all a score of 100, and once again, we’ll keep to js.

We’ll begin by defining some variables to be used:

//Our current score
let currentScore = 0
//Our current best input
let currentNearest = "0000000"
//The set of characters to test with
let validChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split('')

Next we’ll need a function that will take which character we’re looking to modify as an index i:

let guessDigits = async i => {
    
}

We’ll then iterate through each character in validChars, replace the character at index: i with our current character from validChars and then store the result in guess:

let guessDigits = async i => {
    for(let j = 0; j < validChars.length; j++) {
        let guess = currentNearest.substring(0, i) + validChars[j] + currentNearest.substring(i + 1)
    }
}

This should mean after 2 iterations of this loop, our string (guess) should equal “1000000”.

We can now implement the CodeBreaker_submit(guess) function, and return to caller if our score has increased:

let guessDigits = async i => {
    for(let j = 0; j < validChars.length; j++) {
        let guess = currentNearest.substring(0, i) + validChars[j] + currentNearest.substring(i + 1)
        let score = await CodeBreaker_submit(guess)
        console.log("Guess: " + guess + " Score: " + score)
        if(score > currentScore) {
            console.log("New best guess: " + guess + " with score " + score)
            currentScore = score
            currentNearest = guess
            break
        }
    }
}

Finally, we just need a loop that calls this function for each index in our currentNearest string “0000000”:

let guessAll = async () => {
    for(let i = 0; i < currentNearest.length; i++) {
		await guessDigits(i)
	}
	console.log("Solved: " + currentNearest + " with score " + currentScore)
}

Pasting all of that into our console and then calling guessAll()….

and after a little while….

We’re in. 😎

Another 150 points bagged and one step closer to finishing the programming section! Hopefully you’ve enjoyed following along, feel free to reach out with any comments/questions or even better solutions!

Leave a Reply