The Bytecode Club - Reverse Engineering Forum
TBC Crackme Cracking Tutorial - Printable Version

+- The Bytecode Club - Reverse Engineering Forum (https://the.bytecode.club)
+-- Forum: Lobby (https://the.bytecode.club/forumdisplay.php?fid=1)
+--- Forum: Programming (https://the.bytecode.club/forumdisplay.php?fid=86)
+--- Thread: TBC Crackme Cracking Tutorial (/showthread.php?tid=846)



TBC Crackme Cracking Tutorial - Botnet - 02-16-2015

PLEASE NOTE THAT ALL MY TUTORIALS ARE FOR EDUCATIONAL PURPOSES ONLY
USE THEM TO CRACK SOFTWARE YOU DO NOT OWN AT YOUR OWN RISK
I WILL NOT BE RESPONSIBLE IF YOU GET SUED BY A BROGRAMMER


This tutorial will be focused on the CrackMe by Konloch release here.

Level 1:

Code:
java -cp crackmes_b1.0.jar the.bytecode.club.crackme.level1.Main crackmes_b1.0.jar passw0rd


You can use any variant of passw0rd as long as it contains the Zero due to the case insensitive checking. The way this password was obtained was using The Bytecode Viewer. Simplest to crack of all the challenges contained within.

Code:
if (password.equalsIgnoreCase("passw0rd")) {


Level 2:

Code:
java -cp crackmes_b1.0.jar the.bytecode.club.crackme.level2.Main p4$$w0rd

The way the password was found was through a md5 rainbow table service such as [Gromweb]

Code:
if (md5(password).equalsIgnoreCase(Main.password)) {
    System.out.println("Cracked");
}

You can easily defeat this by use a online md5 generator such as miraclesalad and replacing the MD5 in the source code and recompiling.

So lets say we want to change this from "p4$$w0rd" to "Cracked", we change the MD5 from "b3ea2220280ec43c31c7f6723f85904c" to "cc8b1415557f58abf2e2fa83c2ea6c91" like this:

Code:
Main.password = "b3ea2220280ec43c31c7f6723f85904c";

Will now become this:

Code:
Main.password = "cc8b1415557f58abf2e2fa83c2ea6c91";

Now when recompiled it will print out "Cracked" when the password "Cracked" is used.

Level 3:


Code:
java -cp crackmes_b1.0.jar the.bytecode.club.crackme.level2.Main p4$$w0rd

Level 3 uses the same password and method in Level 2 however the checking method is different. The password check is contained within a bunch of try statements. When the correct password is entered it throws a WebServiceException then procedes to catch it and print "Cracked".

Code:
if (md5(password).equalsIgnoreCase(Main.password)) {
    throw new WebServiceException();
}
catch (WebServiceException e2) {
    System.out.println("Cracked");
}

However if the incorrect password is entered it throws BindException and captures it printing "Try again".

Code:
if (md5(password).equalsIgnoreCase(Main.password)) {
    throw new WebServiceException();
}
    throw new BindException();
}
    catch (BindException e2) {
    System.out.println("Try again.");
}

You might now be wondering why exceptions are thrown and the same password is used. This is a programming trick to throw reverse engineers off the right track. It's a red herring that can often be quite effective in confusing people and getting incorrect results. It's very simple and effective to implement in your own software, but be warned; some obfustocators remove error handling such as throwing and catching to make any fuzzed output useless.

Level 4:

Code:
java -cp crackmes_b1.0.jar the.bytecode.club.crackme.level4.Main

In this one there is no hints as to what the password might be in the file. It makes a call to a file hosted on "the.bytecode.club" instead of checking an internal variable. We could easily spend all day and night trying to brute force what the password might be, or we could simply patch the file and recompile, a much more logical solution.

So inspecting the file we have this:

Code:
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
    connection = (HttpURLConnection)new URL("http://the.bytecode.club/havingfunquestionmark.php?level=4&password=" + args[0]).openConnection();
    connection.setUseCaches(false);
    connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0");
    reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    final String page = reader.readLine();
    
    if (page.equals("authorized")) {
        System.out.println("Cracked");
    }
    else {
        System.out.println("Try again.");
    }
}
catch (IOException e) {
    System.out.println("Unable to connect to http://the.bytecode.club, please try again later.");
}

Since we can see the word that is is looking for this time is "authorized", we can simply change the variable "page" from "reader.readLine()" to "authorized". So it will look like this:

Code:
final String page = "authorized"

Please note that it is a "final", you must change it when it is initialized as changing it after will throw an error stating that you are trying to edit a final.

Now you can run the command at the beginning of this section with any word at the end and it will always print out "Cracked". Simple enough, it's a step into web based authorization systems.


Level 5:

Code:
java -cp crackmes_b1.0.jar the.bytecode.club.crackme.level5.Main

Since Level 5 and 4 are practically the same I wont go into as much detail on everything. But note this key difference:

Code:
final String page = reader.readLine();
if (page.split(" ")[1].equals("got")) {
    System.out.println("Try again.");
}

And this one:

Code:
catch (Exception e2) {
    System.out.println("Cracked");
}


This is where the challenge begins, the code is a bit of trickery. You see that it is simply sending a request to a file on the.bytecode.club that merely echo's what it got. If it finds the word "got" you failed. Simply enter no password to bypass this. This can also be used as trickery to make it look like you need a key and have to enter one but it's never actually validated. This is possibly the worst form of security you could get but it can trick people quite well.


Level 6:

Level 6 is just like 5 and 4. This is the only real difference:

Code:
if (Integer.parseInt(page.split(" ")[3]) >= 9001) {
    System.out.println("Cracked");
}

In this case you can simply patch the if to be if(true){" and it will spit out "Cracked". This is also a horrible method of security. Still not as bad as trying to trick users...

That's it for this tutorial. I hope you all enjoyed.


RE: TBC Crackme Cracking Tutorial - Konloch - 02-16-2015

Very good write up! I've added some improvements you've mentioned, such as the issue with no password entered working.

beta 2.0 is released with a seventh level and obfuscation!


RE: TBC Crackme Cracking Tutorial - Botnet - 02-18-2015

(02-16-2015, 04:26 PM)Konloch Wrote:  Very good write up! I've added some improvements you've mentioned, such as the issue with no password entered working.

beta 2.0 is released with a seventh level and obfuscation!

For anyone trying beta 2.0, be forewarned this obfustocator is not like proguard. It breaks all the decompilers that spit out Java. You will be going into bytecode land for this nightmare.