Keith and Dawg 2 Solution

By: Jason Yang

Flag: ywterqtwe

Solution

Basically, brute force it. Calculate every possible password using the letters q, w, e, r, t, and y, and keep going until you find the right hash.

Firstly, we use a built in Java function to calculate md5 hashes:

MessageDigest md = MessageDigest.getInstance("md5");
md.update(s.getBytes(), 0, s.length());
return new BigInteger(1, md.digest()).toString(16);

where s is the string to be hashed.

Then, we need to iterate over every single letter combination of a certain length. If the password isn’t found, then increment the length and repeat until it is found. We can do this by representing each combination with length n and o characters as an integer from 0 to $$o^n-1$$. Using a for loop, each of these integers can be converted to base o, then converted to a string using each digit as the index in the character set array, then hashed. If the loop is completed and the hash is still not found, n is incremented, and the loop repeated.

Of course, this is clearly not the most efficient algorithm. An improvement would be using multithreading. In the example, four threads are created, using the Iterator class to get the integer representing the character combination. The method getNext() is synchronized to prevent multiple threads from accessing the method concurrently and performing the same hash. Because the method is synchronized, it presents a bottleneck, as all thread must block until the method finishes. As a result, as much computation is placed in the thread and not in the getNext() method, which only needs to increment the integer. A CountDownLatch is used to block the main thread until all four hashing threads have completed, either when all combinations of length n have been tested or when the hash has been found. Once the CountDownLatch unblocks, the main thread either moves on and increments n (in the first case), or reports a successfully reversed hash (in the second case).

Full Solution

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.CountDownLatch;

public class Reverse {

    public String check;
    public String[] chars = {"q", "w", "e", "r", "t", "y"}; 

    public int length;
    public int count = 0;
    public boolean found = false;
    public Iterator it;

    public CountDownLatch latch;

    public static void main(String[] args){
        new Reverse().run();
    }

    public void run(){
        int maxLength = 10;
        int threads = 4;

        check = "b81b28baa97b04cf3508394d9a58caae";
        long beginTime = System.nanoTime();
        length = 1;
        while (length <= maxLength && !found){
            latch = new CountDownLatch(threads);
            it = new Iterator(length, chars);
            for (int i = 0; i < threads; i++){
                Thread t = new Thread(new Hash(), "hash");
                t.start();
            }
            try {
                latch.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            length++;
        }
        long endTime = System.nanoTime();
        long time = endTime - beginTime;
        System.out.println(String.format("%f hashes/second", (double) count / time * 1000000000d));
        System.out.println(String.format("%f seconds", time / 1000000000d));
    }

    public static String md5(String s){
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            md.update(s.getBytes(), 0, s.length());
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public class Hash implements Runnable {

        @Override
        public void run() {
            int index = -1;
            while ((index = it.getNext()) >= 0 && !found){
                String s = "";
                for (int i = it.n - 1; i >= 0; i--){
                    int num = (int) Math.floor(index / Math.pow(it.o, i));
                    index -= num * Math.pow(it.o, i);
                    s += chars[num];
                }
                String hash = md5(s);

                count++;
                if (hash.equals(check)){
                    found = true;
                    System.out.println(s);
                    System.out.println(hash);
                }
            }
            latch.countDown();
        }

    }

    public class Iterator {

        public final int n;
        public final int o;
        public int index;

        public Iterator(int size, String[] chars){
            n = size;
            o = chars.length;
            this.index = 0;
        }

        public synchronized int getNext(){
            if (index < (Math.pow(o, n))){
                int tmp = index;
                index++;
                return tmp;
            }
            return -1;
        }

    }

}

results matching ""

    No results matching ""