PicoCTF 2019 Writeups

26-oct-2019 by AJc0de5

Click here to start from the beginning of the series.

vault-door-7 - Points 400

This vault uses bit shifts to convert a password string into an array of integers. Hurry, agent, we are running out of time to stop Dr. Evil's nefarious plans! The source code for this vault is here:

import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

class VaultDoor7 {
    public static void main(String args[]) {
        VaultDoor7 vaultDoor = new VaultDoor7();
        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!");
        }
    }

    // Each character can be represented as a byte value using its
    // ASCII encoding. Each byte contains 8 bits, and an int contains
    // 32 bits, so we can "pack" 4 bytes into a single int. Here's an
    // example: if the hex string is "01ab", then those can be
    // represented as the bytes {0x30, 0x31, 0x61, 0x62}. When those
    // bytes are represented as binary, they are:
    //
    // 0x30: 00110000
    // 0x31: 00110001
    // 0x61: 01100001
    // 0x62: 01100010
    //
    // If we put those 4 binary numbers end to end, we end up with 32
    // bits that can be interpreted as an int.
    //
    // 00110000001100010110000101100010 -> 808542562
    //
    // Since 4 chars can be represented as 1 int, the 32 character password can
    // be represented as an array of 8 ints.
    //
    // - Minion #7816
    public int[] passwordToIntArray(String hex) {
        int[] x = new int[8];
        byte[] hexBytes = hex.getBytes();
    
        for (int i=0; i<8; i++) {
            x[i] = hexBytes[(i*4)] << 24 | hexBytes[(i*4)+1] << 16 | hexBytes[(i*4)+2] << 8 | hexBytes[(i*4)+3];
      System.out.print(x[i]+ " ");
        }
        return x;
    }

    public boolean checkPassword(String password) {
        if (password.length() != 32) {
            return false;
        }
        int[] x = passwordToIntArray(password);
        return x[0] == 1096770097
            && x[1] == 1952395366
            && x[2] == 1600270708
            && x[3] == 1601398833
            && x[4] == 1716808014
            && x[5] == 1734305335
            && x[6] == 962749284
            && x[7] == 828584245;
    }
}

Solution

This is the Seventh vault door and in this program the checkPassword method uses Bit Shifting <<, >>and an OR | operation for storing the Flag.

First let's see what the checkPassword Method does, it sends the user input Flag to another method passwordToIntArray which has a int array with length 8 and another byte array hexBytes to store the string as Bytes.

Finally the loop which runs 8 times and what it stores on the int array is, takes the byte on the ith index of hexBytes and the next consecutive three indexes and left shiftes their byte value by 24, 16, 8 and stores them in the int array and sends back to the checkPassword method and every index has as value which is compared explicitly and if all of them matches, the method returns true, else false, Let's see the BruteForce code for this program,

Brute Force

import java.util.Arrays;

public class Vault7BruteForce {
    
    private String looping(byte[] hex, int chkValue) {
        for(int j=0;j<hex.length;j++) {
            for(int k=0;k<hex.length;k++) {
                for(int l=0;l<hex.length;l++) {
                    for(int m=0;m<hex.length;m++) {
                        if((hex[j] << 24
                            | hex[k] << 16
                            | hex[l] << 8
                            | hex[m]) == chkValue) {
                            return (char)hex[j]+""+(char)hex[k]+""+(char)hex[l]+""+(char)hex[m];
                        }
                    }
                }
            }
        }
        return "";
    }
    
    private void bruteForce(String hex) {
        int[] value = new int[8];
        value[0] = 1096770097;
        value[1] = 1952395366;
        value[2] = 1600270708;
        value[3] = 1601398833;
        value[4] = 1716808014;
        value[5] = 1734305335;
        value[6] = 962749284;
        value[7] = 828584245;
        byte[] hexBytes = hex.getBytes();
        System.out.print("picoCTF{");
        for(int i=0;i<8;i++) {
            System.out.print(looping(hexBytes, value[i]));
        }
        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 Vault7BruteForce().bruteForce(Arrays.toString(chr));
    }
}

This method is more likely the last Flag BruteForce Problem, We are doing the opposite of what the original code does we are having four loops for each and every combination and then we compare current total value with the value we have in the given int array and when you run the above code you get the Flag as,

picoCTF{A_b1t_0f_b1t_sh1fTiNg_f79bcd1c15}

And just a note here, if you run this code in a much less processing power computer, it will print them as 4 characters at a time, because the loops runs almost (63)4 * 8 times.