vault-door-6 - Points 350
This vault uses an XOR encryption scheme. The source code for this vault is here:
import java.util.*; class VaultDoor6 { public static void main(String args[]) { VaultDoor6 vaultDoor = new VaultDoor6(); Scanner scanner = new Scanner(System.in); System.out.print("Enter vault password: "); String userInput = scanner.next(); String input = userInput.substring("picoCTF{".length(),userInput.length()-1); if (vaultDoor.checkPassword(input)) { System.out.println("Access granted."); } else { System.out.println("Access denied!"); } } // Dr. Evil gave me a book called Applied Cryptography by Bruce Schneier, // and I learned this really cool encryption system. This will be the // strongest vault door in Dr. Evil's entire evil volcano compound for sure! // Well, I didn't exactly read the *whole* book, but I'm sure there's // nothing important in the last 750 pages. // // -Minion #3091 public boolean checkPassword(String password) { if (password.length() != 32) { return false; } byte[] passBytes = password.getBytes(); byte[] myBytes = { 0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d, 0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa , 0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27, 0xa , 0x67, 0x6d, 0x33, 0x34, 0x6c, 0x60, 0x33, }; for (int i=0; i<32; i++) { if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) { return false; } } return true; } }
Solution
This is the Sixth vault door and for first time in the series it uses a Encryption technique which is XOR (^) it outputs true only when the inputs are not same, else false. To learn more about XOR.
First let's see what the checkPassword Method does,
public boolean checkPassword(String password) { if (password.length() != 32) { return false; } byte[] passBytes = password.getBytes(); byte[] myBytes = { 0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d, 0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa , 0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27, 0xa , 0x67, 0x6d, 0x33, 0x34, 0x6c, 0x60, 0x33, }; for (int i=0; i<32; i++) { if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) { return false; } } return true; }
This Method gets the user input and stores them as byte array using getBytes(), this method encodes the given string into UTF-8 encoded array of characters, and then we have a byte array initialization with 32 characters of HexaDecimals, you guessed it this array must be our way to the Flag and then we have a loop which run 32 times which is exactly our Flag length, then let's see what this loop does,
for (int i=0; i<32; i++) { if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) { return false; } } return true;
First this loop run 32 times as you already know, then it compares a condition which first takes the user given passBytes
array one by one and then XOR that character with a constant Hexadecimal 0x55
value after that it subracts that value with the myBytes
array then finally it compares a condition which is, the obtained value should not be equal to 0
, if it does the loop gets terminated by passing return value as false
so we need to give the input as Flag where each and every character should not produce a 0
when the calculation in the loop happens,
If you already know that this is the perfect situation to use a Brute Force technique, if you didn't, Brute Force is just a technique which try all the combinations for the Flag or any other set of characters we are trying to obtain.
BruteForce Code:
Let me provide the code first and then I will explain about the Program,
public Vault6BruteForce { public void bruteForce(String str) { byte[] passBytes = str.getBytes(); byte[] myBytes = { 0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d, 0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa , 0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27, 0xa , 0x67, 0x6d, 0x33, 0x34, 0x6c, 0x60, 0x33, }; System.out.print("picoCTF{"); for(int i=0;i<myBytes.length;i++) { for(int j=0;j<passBytes.length;j++) { if((passBytes[j] ^ 0x55) - myBytes[i] == 0) { System.out.print((char)passBytes[j]); } } } System.out.println("}"); } public static void main(String[] args) { char[] chr = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', '1','2','3','4','5','6','7','8','9','0','_'}; new Vault6BruteForce().bruteForce(Arrays.toString(chr)); } }
Like I said about trying all the combinations in the Brute Force we need all the characters and numbers and symbols as characters which are used in the Flag, and that would be a-z
,A-Z
,0-9
, and the symbol _
.
After that, we are sending the chr
array as String
to the bruteForce method, and it just does the opposite of the encryption.
The First loop takes the HexaDecimal myBytes
and the Inner loop takes our passBytes
array and then does the exact same calculation only to check if it equals to 0
, then you can say that is one of the character in the Flag, when completion of each iteration a single character is printed to the output.
If you run the above given Brute Force Program, you get the output as Flag
picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_28fa95f}