Solution to leyer`s @Lycrackme

Disclaimer

The ByteBuddy api can give us a different solution.

Well gentlemen that talc testing bored I found this crackME of Leyer is about 10 years old hahahaha first time I peek into this issue crackMEs, before just used them and ready without much passion, but really let’s say, I was a little bored, so vacilen.

Tools and Environment

The first thing we must do is to decompile our .jar with the decompiler of preference for example this web javadecompilers.com there we must upload the .jar, there are other offline options such as the use of Krakatau programmed in python by console, also recaf bytecode reader and includes cfr internal decompiler.

I also have the option with the default IntelliJ IDEA decompiler version that I used for this:

  • (Community Edition) 2017.2 EAP

  • Build #IC-172.2656.10, built on May 30, 2017

Here in this link is the crackME of leyer, well I don’t know if he has others, I’m sure he does XD Ly-CrackME.jar to decompile we do like this, we create a java project and add our .jar from File/project Structure and in the Libraries menu we click on + to import the jar

subirJAr

Now we can see all the source code, in the External Libraries menu the first line if I click on the + will say Source code recreated from a .class file by IntelliJ IDEA ..blalba by Fernflower, now we should create a new class and copy the content of all the code below, or use krakatau to convert this .class (Bytecode) to .java source code.

crackeJar

Directly in silver platter this almost everything, it does not have any wrapper with some application type Jar2Exe, so we do not have to complain so much XD, another thing in its Web has a source code that is like a new version of the crackME that is almost the same, but if it has some differences and it is the code that we will use it looks like this:

crackME2 Original

We see that the variables are written with $ that are missing in Vzla, to give it a more intense touch hahahaha yes or no ? And obfuscation something the code, in java can be written this way, although by convention its use is avoided, but this is another case.

Here it is important to note that String obfuscation is not as hard as some other obfuscators like Allatori( ofuscator, the _$as_OIsl method that receives a String as a parameter and then passes it through a digest algorithm using the MessageDisgest() class with SHA1 which we cannot decrypt, unless you are an employee of google and you can achieve a collision with 100 VGA XD or even masss, well enough of so much blabber and let’s start by parts as the popular jack.

Execute the crackme SHIFT + F10

runBarraHerramientasSuperior

It should appear as follows

crakcMeee

We introduce any value, throwing error clearly, but that already gives a clue that the validate button may perform the validation or invoke a method that does it, let’s go for more, if I press control + F CONTROL + F that is to search and I introduce the word validate like this:

busquedaValidar

Now with the option to press control + click right on the name of the instance of the button _$b$hsqqso line 85 should appear as the image, indicating that on line 108 is the listener of the button, let’s see how it works.

botonListener

In line 112, we obtain an array of characters that comes from the JPasswordField that is the field where we introduce the serial that must be valid, we use a for to concatenate all the values in a String this _$I_pos123 see line 115

JPasswordFiel

line 117 is the conditional that compares whether $I_pos123 equals $I_pos123.

<em>%2524%2524r easte $r_easte pero quien rayos es el puto _$r_easte ? vamos a buscarlo:

line 105 we see that the value of $r_easte is actually assigned from another String plus $c_Cor_ ok we are doing well

Debugging with IntelliJ basic

In line 105 just where the red circle is, it is to place a BreakPoint and to know what value has that String variable _$r_easte.

breakPoint

Now to run the debugger we can press Shift + F9 or in the upper left corner press where we have the bug icon.

Many times we don’t have a configuration ready and our app doesn’t run, see I have my configuration of the file to run/debug which is CrackME2_ORIGINAL that tells the IDE which class to run

INIT DEBUG

If for some reason you have that list of items _empty create a previous configuration with EDIT CONFIGURATION…​ and select the project to run/debug, which I hope will not happen to you.

editConfiguration

When doing everything right the debug should appear like this:

initDebug

we go to the Variables tab observing that the String $c_Cor contains this value

cacaba0dff27b124ae5bc688b77c14f136b989118

HASH EASTER EGGS

that is the random key that was generated at the time of running the crackME, I could get it with control + c, and we can get more information with right click on it.

This listener presented here is in the main method, as we do not have instance variables and the scope of the variables are local because we will work within the main, otherwise, I can create instance variables and work cleaner as a good developer (XD) or good practice to not get wet, but at the time of cracking we will find ourselves in much worse environments or scenarios hahahaha I’ll show you a lot worse later XD

_$b__$hsqqso_.addActionListener(e -> {
   final String $faHA_$oPL = __gXb$.getText();
   if ($faHA_$oPL == null || "".equals($faHA_$oPL.trim())) { (1)
     return;
   }
   if (!$faHA_$oPL.matches("[0-9]{0,9}") ) {
     JOptionPane.showMessageDialog(null, "Invalid value");
   } else {
     final int shitDesireMyEX = $$1(_$Y_sy76, Integer.valueOf($faHA_$oPL.trim())); (2)
     if(shitDesireMyEX != -1) {
        String _$c_Cor_ = "";
        final int _$_foP = shitDesireMyEX; (3)
        for (int _$i_INDEX_ = 0; _$i_INDEX_ < _$Y_sy76.length; ++_$i_INDEX_) { (4)
           if (_$Y_sy76[_$i_INDEX_] == _$Y_sy76[_$_foP]) { (5)
             for (int index = 0; index < _$i_INDEX_; ++index) {
                 _$c_Cor_ = _$c_Cor_ + String.valueOf((byte) _$Y_sy76[index]);
             }
      //here the method is the one that encrypts the String _$c_Cor_ and concatenates it
      _$c_Cor_ = _$as_OIsl(_$c_Cor_) + String.valueOf(Math.pow((double) _$2341s, 2.0D) / 6.0D - 36.0D);
           }
        }//for externo XP
       _$lH$j$.setText("");
       _$lH$j$.setText(_$c_Cor_);(6)
       _$c_Cor_ = "";
     }else {
        JOptionPane.showMessageDialog(null, "Invalid value"); (7)
     }
  }
});
1 To validate the user input we use conditionals like in line 3 and 6 just in line 6 there is a regular expression (max 9, and range 0 to 9 inclusive) that each index contains that long 9 numbers, like the following: matches("[0-9]{0,9}").
2 Line 9 of the above code invokes the $$1 method shown below this returns the index, where is the value of the crackME variable X, for each static array index of hexadecimal values example 0x7031101 is equal to the decimal 117641473, each one has a unique hash which is what we want otherwise it would be -1 in case it is not there.
3 With this index which we will call shitDesireMyEX my fucking EX, in case it exists we will set it to $_foP.
4 there is a for that goes through the array and in each iteration it queries the following conditional
5 When the value of the counter $i_INDEX is equal to $_foP that is to say my _fuckEX that made my life impossible with so much drama for 3 months, we will enter in the most internal for to cast explicitly the values of the counter of the for to bytes, + another casting to String and concatenate it to $c_Cor, at the end of this internal for we invoke _$ as_OIsl encrypting it with the SHA1 hashing algorithm returning again to the line 13 for external, this condition of the line 14 will always be fulfilled only once, that is to say if the X is 7414755 index 0, this for will iterate 71 times in vain, our array has 72 positions.
6 The String value will be set in the JTextField here, or see line 23.
7 Here from point <2> notifying with Invalid Value in case it returns -1.
private static int $$1(final int $_23DeSh$T[], final int $Bul$) {
        return IntStream.range(0, $_23DeSh$T.length)
                .filter($__Fkl -> $_23DeSh$T[$__Fkl] == $Bul$)
                .findFirst()
                .orElse(-1);
}

keygenPoCBug

Well, before anyone else complains, I’m going to complain.

errorPoC


FIXME EASTER EGG

ex

Debugging that line, giving to the arrow as in the image to see the result of the operation that, here the variable _$2341s will be assigned 18, other times when our PoC goes to shit-""$ is because it has this value 268435465 and incidentally is constant.

 122318Ex

268435465

So if _$2341s can present a constant value that is sometimes given, we can create a method and another button that sets that value back to the JTextField or not? I continue several more times and I run into the very big easter egg again, but I came up with the idea then to apply the acid to it.

eggsProtein

fixmeEASTER EGGS

to execute it in linux we open the console we move in the directory where the jar is and we write,

java -jar KeyGenPoC.jar

In guindo$ you will already know, it has a nice _music, another thing JDK 8 XD