PicoCTF: Vault Door Writeups
(De-obfuscating Java code)
The Following writeups are my documentation of my own methods at solving this set of challenges from PicoCTF in the Reverse Engineering category. I will not be providing the flags (with the exception of Vault-Door-Training due to the flag being in plain-text) at the end of each challenge description because I know (from experience) that the more the answers to challenges like these are available online, the more likely it is that people will take the easy way out and look up the answer, and I feel it is much more beneficial to try things like this out for yourself.
Vault Door Training:
Upon downloading and opening the given java file, there are two methods that we will be dealing with: a main method and a method called checkPassword. The main method in this program takes in a password entered by the user and takes the substring of it, removing the “PicoCTF{“ and the trailing curly brace. Next, the modified user-entered password is passed into the checkPassword method which checks to see if it is the same as the password written in plain-text inside the method. This password, proceeded by “PicoCTF{“ and ending with “}”, is the flag. There really isn’t much to this challenge other than familiarizing the user with the style of this challenge set.
Vault Door 1:
After opening the source code to this new Vault Door challenge, notice the checkPassword method has changed quite a bit. Instead of having the password written out nicely in plain-text, the method checks the password that is passed to the method for its characters at every index to see if they match the flag’s characters. This function explicitly checks each letter of the password with the letter it should be, meaning that the password’s characters are written in plain-text but shuffled. If the lines containing the password.charAt() function calls are reordered in numeric order, the flag can be found looking from top to bottom at the characters within single quotes. This can be done by manually copying and pasting them in order yourself, writing a quick python script to parse the characters in order, or even passing the text to something like ChatGPT to re-order.
Vault Door 3:
This challenge is similar to the last in the sense that all it requires is the reordering of the plain-text characters. It is not quite as straight-forward, however, as the for loops that iterate through the passed password variable do not do so in a friendly way. It is important to have either a pen and paper or a separate tab open to step through this challenge as writing the characters being added to the array is the easiest way to visualize the flag as it is being built.
Towards the beginning of the method, a new char array is created with a length that is equal to the compared string at the end. The string being created and compared to the string literal at the end of the method will use the same characters, but the characters will be in a different order. In the first for loop, the first 8 characters of the string are added to the first 8 indices of the new char array, in order. Write down the first 8 characters from the string literal at the end of the method as they will be the first 8 characters of the flag. The second for loop starts with i being set to 8 from the previous loop. While iterating normally through the array (going up by 1 index for every iteration), the character the char array is being assigned from the string literal is starting from the 15th index and going down to the 8th index. This is essentially adding the next 8 characters to the array in reverse order. Similar to the last loop, write out the characters from index 8 to 15 in the string literal in reverse after the first 8 that have already been written down. In the third for loop, i is set to 16 from the end condition in the previous loop. Instead of continuing to increment by 1 through the array’s indices, this loop will step through the indices by 2, filling in the remaining even indices (from 16 to 30) within the array with the characters at the [ 46 - i ] index in the string. Finally, in the last for loop, the remaining odd indices are filled in by iterating from 31 to 17. This loop is simpler than the last as the characters being added at each index in the array are the characters at the same index within the starting string.
After performing all of the above operations on the string given at the end of the method, the flag has been built.
Vault Door 4:
This challenge is surprisingly simple for those that are familiar with the different bases that numbers can be represented in. In the byte array that is being initialized, there are four lines made up of 8 separate bytes. In the first row, these individual bytes are the ascii values of characters. In order to convert them back to characters, there are ascii tables available online that can easily be used to figure out the characters that they represent. In the second row the bytes are written in hexadecimal (base 16). These, similar to the last row, can be converted either by hand or with an online converter. The bytes in the third row are represented in octal (base 8). Again, these bytes can be converted to their respective character either by hand or by using an online converter. Finally, the last line is simply plain-text which should be appended to the end of the characters that have been found so far to give the final flag.
Vault Door 5:
For this challenge, the password is URL encoded and then Base64 encoded. The resulting string after concatenating the strings at the end of the checkPassword method are the encoded flag. In order to solve this challenge, this string should be decoded from Base64 and then decoded from its URL encoding. This can be done with a quick script in any language, or, the much quicker way, putting the text into an online Base64 and URL decoder. The resulting flag should be wrapped in “PicoCTF{“ and “}”.
Vault Door 6:
For the sixth challenge in this series, the password is being broken into a byte array. These bytes are being XORed with 0x55 in the hope that they will be equivalent to the value at the same index of the explicitly created byte array. Something to note about the XOR operation is the rule stating that if A ^ B = C, then C ^ B = A. Since the XORed value of the bytes from the password and 0x55 are supposed to be equal to the bytes from myBytes, the bytes from myBytes can be XORed with 0x55 to return the flag. To generate the flag, it is easiest to write a quick java program to do the XOR operations and generate the flag. Below is how I wrote the program to solve the challenge, though there is probably a more concise way.
Vault Door 7:
This challenge is where the difficulty begins to scale upwards. The entered password is parsed into an int array, where the resulting integers are compared with the integer values of the flag. In order to solve this challenge, the passwordToIntArray method needs to be reversed to generate the flag from the given integers. To start, create a new java file and, in it, initialize an int array with the integers that are explicitly typed at the end of the checkPassword method. Each of these integers represents a 32 bit binary string containing four characters each. In order to generate the flag, each of these binary strings needs to be broken into 4 substrings, each of length 8, representing their own respective character. To do this, parse the integer from the 8 bit binary substring and then cast it to a char. My solution is below for reference:
Vault Door 8:
In Vault Door 8, not only is there code to decipher, but the code itself is obfuscated with terrible formatting to make it harder to understand. The format of the code is the first issue to fix and can be done by either manually spacing out lines and their respective scopes, or by copying and pasting this text into an online code beautifier. Once this is done, the challenge becomes a bit easier to visualize.
Looking at the formatted code, the entered password is shuffled by switching the bits at specific positions. Once shuffled, the resulting char array is compared to the bytes defined in the expected char array. In order to get the flag in this challenge, the ‘expected’ char array needs to have the bits that were switched put back into their original positions. To begin solving the challenge, make a new Java file. The switchBits() method can remain the same and be directly copied and pasted into the program. Similarly, the ‘expected’ char array can be copied and pasted into the new file. In order to reorder the scramble() method, reverse the order that the switchBits(c,_,_) are called in. Once this is done, add a print statement to display the resulting char array represented as a string.