Translate

Partners

This is a great mission and I really enjoyed doing it. It took me ages to complete and I have learned many things along the way. Big thanks to the guy(s) who created it!!

The brief:
You have 120 seconds to brute force the encrypted text and submit the last of the 5 dummy serial numbers.

The first look:
At first sight the mission is very complex and it looked unmanageable to me. So I have applied the good old method I have learned during completing work projects: you break down a complicated task to smaller chunks and if the smaller chunks are still unmanageable you break them down to even smaller chunks until the subtasks you end up with are very simple and easy to complete. From there it is like a walk in the park. You complete a series of easy tasks and that&#039;s it.

What language?
You need to write a fast program using a smart brute forcing method to complete the mission on time. For this I would suggest using a compiled language because of their efficiency. I used c++ but your favorite compiled language will be just fine. If you don&#039;t have one this is a good time to pick/learn one. First I thought of using php but it is either too slow or my method was not smart enough so I went with c++ instead.

This is the list of easy tasks I ended up with:
gather all the information from the brief

understand the php code used for encrypting the serials
understand the functions
learn about hexadecimal numbers

get the encrypted text
reproduce the functions used by the encryption script(MD5,evalCrossTotal,ord)
start from the beginning

container for your data
loop through all 100 one by one
print out the last serial number and submit it

Now I&#039;ll look at each of the above easy task in detail. If you don&#039;t want me to take away from you all the fun that comes with discovering things yourself then stop reading.

Gather all the information from the brief:
Looking at the encrypted text you can see that there are 100 negative numbers separated by spaces.
Your ultimate goal is to submit the last dummy serial number within 120 seconds.
We actually know a lot about the serial numbers from the example.txt.
Let&#039;s look at the first one: 99Z-KH5-OEM-240-1.1
All of them are 19 character long and some of the characters are constants as in they are the same in every serial number in the example list. This information is really important because it tells you that you don&#039;t need to crack all 19 but only the few which are changing. Based on this we can come up with a template serial number: XXX-XXX-OEM-XXX-1.1 where the characters you need to brute force are represented by X. You can also notice that X is either a capital letter or a number between 0 and 9. This reduces the possible variations significantly. There is also a hint in this file at the bottom: (Don&#039;t forget the UNIX-style line breaks.) This tells you that after each line (read it: after each serial number) there is a unix-style line break. We can google unix-style line breaks and add it to the end of our template. It is now 20 character long. This actually adds up nicely. We already knew that the encrypted text is 100 characters long. From this we can calculate that there are 5 serial numbers hidden in the encrypted text.

So how many variations are there? Awful lot. To be precise there are 9 Xs in our template and we have 5 serial numbers to crack. That is 45 unknowns. Each X could be either a number between 0 and 9 or a capital letter. There are 26 capital letters plus the 10 numerics that comes to 36. There are 36 possible variations for each Xs. The total number of variations for the encrypted text is 36x36x36...x36. In other words 36 raised to the power of 36. That equals to too much. We will need to come up with a smart way to reduce that.

Understand the php code used for encrypting the serials:
This you can not avoid. You need to study the php code used for the encryption and you need to understand it, every bit of it. If you are like me and don&#039;t know much about php I suggest googleing a tutorial. After that stick it on a server and run it with different serial numbers using our template and try to use different passwords too. Really helped me to &#039;echo&#039; the value of different variables during runtime.
To help myself understand it I drew up a mind map with all the functions and variables and included some notes too. It looks crazy so I will not post it here and punish you with it. You can try that or some other way. The main thing is to understand the code. If you don&#039;t then you are not ready yet to move on.

Basically you pass the entire content of the file containing the original serial numbers and the password to
function encryptString($strString, $strPassword)
and it spits out the encrypted text as one long string. A few other function also gets called on the way:
function evalCrossTotal($strMD5)
MD5
ord
Play with them and see what value they return

Each element of the string returned by encryptString() function is calculated by this piece of code:
$arrEncryptedValues[] = ord(substr($strString, $i, 1))

+(&#039;0x0&#039; . substr($strPasswordMD5, $i%32, 1))

-$intMD5Total;

This is what really gives it away. Replace $arrEncryptedValues[] with each element of the encrypted text and bang you almost finished. Now you only need to write a smart code that brute forces the three elements on the other side of the equal sign.

Here is a big spoiler. It is stating the obvious but the value of the hexadecimal representation of the decimal number 2 is still 2 even if it looks different.

It is also worth looking into how a new value is given to $intMD5Total at each instance and how it is calculated and from what.

Now it is time to roll up your sleeves, open a text editor and start writing the code after reading up on md5 hashes.

Get the encrypted text:
This is an easy one. I just copied and pasted it to a text file and my program starts with opening this text file and reading the negative numbers into an array.

Reproduce the functions used by the encryption script:
The next step is again easy. I just wrote the c++ equivalent of the php functions md5 and evalCrossTotal. These two needs to be fast as possible because your program will call them zillion times. If you later need to improve on speed these are two good places to look. Make sure that your md5 function always returns the same hash as the built in php equivalent.

Start from the beginning:
Let&#039;s have a go at the first element of our encrypted text array which is hiding the first character of the first serial number. By studying the php code we know that what we are looking for here is equals to: ord(substr($strString, $i, 1))
plus (&#039;0x0&#039; . substr($strPasswordMD5, $i%32, 1))
less $intMD5Total;

One way to attack this is simple looping through all the possible variations but how many are there?
Let&#039;s look at each of the three elements one by one.

ord(substr($strString, $i, 1))
Inside->out
$strString is the content of the entire original password file
substr() php function returns a substring
ord() php function returns the ascii value of the first character of a string
So this whole thing is just simple the ascii value of the $i-th character of the original serial number file. Quick look at our template and we know that there are 36 possible values for this. Not too bad.

(&#039;0x0&#039; . substr($strPasswordMD5, $i%32, 1))

inside->out
$strPasswordMD5 is the 32 character long md5 hash of the password used for the encryption.
substr() php function returns a substring
&#039;0x0&#039;. Very clever way of converting a char to a hexadecimal number
What we have here is a hexadecimal number(it is still a number) which is the same as the $i-th element of the 32 character long md5 hash of the password. Unfortunately we don&#039;t know the hash or the original password and it would be impossible to brute force.
But and this is a big but we know that what we are looking for is a one digit long hexadecimal number and for this there are only 16 possible variations(0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f)

$intMD5Total is the sum of all 32 digits of the md5 hash of the password
Again brute forcing the md5 hash would be impossible here but there is a but. We know that the md5 is a string of hexadecimal numbers. For each 32 digits there are 16 possible values from 0 to f .
16x32 is 512. That&#039;s the number of possible variations for $intMD5Total.

36 x 16 x 512 = 294912
It is not impossible to loop through all the variations! While doing it you can save the matching results for later reference.

Container for your data:
You will also need to store and access your data. One way of doing it would be using a multidimensional vector. When deciding keep in mind that your container needs to be dynamic because you don&#039;t know how many matches you will find for each letter. You also need to access each element fast.

Now there is nothing left but writing a function that loops through all the remaining 99 elements of the encrypted text. Think of the template! You already know half of the 99. A piece of cake if you ask me now after I have completed it. ;)