Showing posts with label Keygenning. Show all posts
Showing posts with label Keygenning. Show all posts

Sunday, June 26, 2016

Bypassing Protections: Exploiting Activation to Access Sensitive Data

Welcome to part 2 of the Bypassing Protections series. In this part, we will be looking at an application which uses online activation to verify a license key and activate the software. After activation, the server allows the user to upload their sensitive data to the server, using their registration information as authentication. In this tutorial, we will look into creating an activator which will allow us to bypass the online activation and access the sensitive data that other users have uploaded. Before we begin, I am obligated to say that this tutorial is provided for informational purposes only. By reading this tutorial, you agree not to use the information in this tutorial to hack the server or pirate the application of the software author. As last time, I will not mention the name of the software in this post, but will include pictures which will allow you to determine which software this tutorial was based upon.


To begin this tutorial, we will first try to find the license verification routine. Let's start the target up in ollydbg and attempt to register it with a random name and serial. In this example, I will be using the author's name and '123456' as a license key.

After clicking okay and the nag appears, let's pause ollydbg and follow the call stack back into the application code. After a few steps, we will arrive here:

It appears that this is the verification routine at first glance. Let's set a breakpoint on Function labeled "GenerujKluczProdukti..." and attempt to register again. After the breakpoint, we can step inside and look around. Inside this routine, we notice there is a loop that appears to be replacing the characters in our name which are greater than >=$80 with their numerical/ordinal value in a &#ordinal; format.

We can recreate this function in delphi like this:

After this routine, the application takes an MD5 hash of our name, extracts every other character from the hash, and inserts dashes every 5 characters.

We can generate a key in delphi like this:


I will publish the getMD5 code later which uses the CryptoAPI.

Now that we can generate a valid serial, we can look into the online activation. Following the jump past the nag routine, we begin preparing the url to verify our key with the server. At this point, I advise disconnecting the internet or blocking the application with the firewall. After scrolling down, we can see a string which says [RETURN:OK]. Below this, there is JLE. If we bypass this jump by setting EAX=0, our application will believe the server verified our serial as legitimate.
 Let's toggle a breakpoint on CMP EAX, -1 and allow the program to attempt to activate. Once we break here, immediately set EAX to 0. Now, we will begin storing our information in the registry. The activation data is stored in HKEY_CURRENT_USER\Software\Classes\.p k c d o c 2(remove spaces) in the following string values:
o1= encrypted name
k1= encrypted serial
v1= encrypted version
wk= server result (0)
Each value with the exception of wk(sever result) is encrypted with with the following algorithm.
This routine encrypts each individual character of the name, key, and version number. It then converts the encrypted character, which is a WORD(16 bits unsigned) to a number string(inttostr) and adds it to a numerical string separated by a space. We can recreate the routine in this fashion:
 

The result of this routine is then added to the registry. We can do this in delphi using the TRegistry unit.


Now, we can use this activator to activate the application with any name we please, without having to verify it online. Now that the application is registered to the author of the software, we can now access any tournament data he has stored on the server.

This is due to the fact that the server grants access to information stored on the server by using the username and license key for authentication.

Since there is only one possible license key for each licensed user, and the name of each user is published with their tournament results, we can simply activate the software with their name to gain access to their data. This is a serious flaw which I tried to bring to the attention of the author, but he ignored every email I attempted to send him.

A way that this authentication flaw could be fixed is to remove the md5 license scheme and make the serial number for each user generated at random. That way, there are trillions, if not an infinite number of possible serial numbers for each user. This way, if I activated the application in the manner above, using a serial I generated at random, it would be next to impossible for me to generate the exact key issued by the author, thus, causing the authentication to fail. The author could also add a second layer of authentication for accessing the online data which required the user to create an account on the server with their email and password.

I want to thank you for reading and following along with this tutorial. If you have any questions, feel free to ask them below. Until next time, happy reversing.

Monday, December 29, 2014

Keygenning With Delphi: Useful Delphi Functions and Tips

Hello and welcome to this short tutorial for keygenning in Delphi. A lot of beginners who are trying to learn keygenning often get stuck with questions about how to implement certain things or manipulate strings or characters in certain ways. In this tutorial, I will try to cover many of the things that were confusing to me and give you some tips on how to accomplish some of these tasks in a simple and effective manner.




Question 1: How do I get the numerical value of a character and a character value of a number?

A lot of licensing algorithms like to manipulate the numerical value of each character in a name individually in a mathematical operation. In order to do this in delphi, we can use the ord() function. Ord is short for ordinal. When a character is passed to this function, it will return the numerical value of the character. In this case we can implement myByte:=ord('A'); This sets myByte to 65 or $41 in hex. If you want to loop through an entire string and add all of the characters together we can do this:

var
I: Byte;
math: integer;
name: String;
Begin
name:='George';
math:=0;

For I := 1 to length(name) do
math:=math+ord(name[I]);

End;


In this example, we loop through the entire string and use 'name[I]' to get the character of the name at the current loop value. In Delphi, the first character is always character '1' unlike C++ where the first character is '0';
In order to get a character value of a number, we will use the chr() function. This allows us to pass a byte value to the function and get the character representation of it. If we execute myChar:=chr($41); this will set myChar = 'A'; Here is a code example.

CONST myVals: Array[0..3] of byte=($41,$42,$43,$44);
VAR
myStr: String;
I:byte;
Begin
myStr:=''; //Clears the Strings

for I := 0 to 3 do
myStr:=myStr+chr(myVals[I]); //Loops through myVals and converts the bytes to characters.
End; //In the end, myStr='ABCD'

Question 2: How do I work with hexadecimal values? How do I convert HexToInt? How do I convert an integer to a hex string?

Working with hexadecimal values in delphi is quite simple once you know how to do it. You are able to easily embed hexadecimal values in your code by simply adding a '$' sign before the value. With that said I:=$51; would be a simple way to put a hex numerical value in your code without having to convert it to decimal. If you are working with a hex string and you want to convert it to an integer, it is quite simple. The built-in delphi function strToInt can do it if you tell it that the string is a hex value. If you have the hex string value
of '5A223B4A', to convert it to hex, all you need to do is place a '$' at the beginning and pass it to the strToInt function. The '$' informs the function that this is a hex value. Therefore, the code I:=strToInt('$'+'5A223B4A') will convert the hex string to a numerical/integer value. If you have to do this with multiple values, you can simply create a small function such as this:

function hexToInt(hexStr: string): Integer;
begin
Result:=strToInt('$'; + hexStr);
end;

To convert an integer to a hex string, we need to use the built in intToHex function. This function takes two parameters. The first value is our numerical value or variable while the second is the length format. The length format tells the function what the minimum length you want the string to return. For example, if you wanted the length of the hex value to always be 8 or the equivalent of a 32 bit hex value, we will add a parameter of 8. This means that if the converted value is less than 8 characters, it will pad the value with zeros to get the desired length. However, if the converted value is greater than the length value, it will still output the correct value. That is because the length parameter only sets the minimum length, not the maximum. Therefore, if your code is intToHex($ffffffff, 4), it will output 'FFFFFFFF' where intToHex($ff, 4) will output '00FF'. Note that this function always returns uppercase hex strings.

Question 3: How do I generate a random letter/character from A-Z or a random hex value?

To generate a random letter or character between A-Z or a-z, we can do this numerically using the random function without needing to embed all 26 characters as a string. The characters A-Z have the numerical values of $41 to $5A while a-z have the numerical values of $61 to $7A. To generate a random uppercase character, we can do this:

VAR
myChar, myHexChar: Char;

Begin
myChar:= chr(byte(random(26)+$41)); //This generates a random Uppercase letter.
myChar:= chr(byte(random(26)+$61)); //This generates a random Lowercase letter.


For a random hex character, we can simply do this:

myHexChar:= intToHex(random($10), 1);//Creates a single hex character from '0-F'.
End;

Question 4: How do I work with Unicode String bytes?

Working with each each individual byte of a unicode string can be a little tricky in delphi, but can be accomplished with the use of pointers. In this code, we will create a byte pointer to our unicode string and use that pointer to read each byte individually. Since a unicode string represents each character with 2 bytes, we will need to get the length of our string and multiply it by 2 in order to get the length of the bytes. It this example, we will convert a unicode string to hex, byte by byte.

var
i,i2:integer;
pntr:pointer;
str2:string;

strU:unicodeString;
begin


str2:='';

strU:='ABCDEFG';
pntr:=(@strU[1]);
//This creates a pointer to our string.
   
I2:=length(strU)*2;
//doubles the length to equal the length of its bytes.
for I := 1 to I2 do begin
str2:=str2+inttohex(byte(pntr^),2);
//This tells delphi to read the byte at the address of which our pointer points to. In this case, it is the address of our string.

inc(pbyte(pntr),1); // This will increment our pointer address to go to the next value in our string.
end;
//End loop

In the end, str2 will equal '4100420043004400450046004700'.


Question 5: How do I manipulate or obtain the individual bytes in an integer or cardinal?

As you may know, an integer value consists of 4 bytes. Some mathematical operations require us to manipulate an individual byte from this or extract it. Here are a few operations you can use to get the data you need.
If you are looking to access an individual byte other than the first, it is easiest to use the SHR function to move the bytes to the one that you need. The SHR function works at a binary level. A byte consists of 8 binary digits. In order to get to the next byte in the value, you would need to SHR by 8. Here are some examples of how to do so. We will use the hex value AABBCCDD to show you how to obtain each portion as a byte.

VAR
MyHex: Integer;
MyByte: Byte;
Begin
 myHex:=$AABBCCDD;

//let's get the $CC portion.
MyByte:=Byte(myHex SHR 8);// this moves the integer over by 8 binary digits and discards them from the right.
//In memory $AABBCCDD becomes $00AABBCC after the shift.


//let's get the $BB portion.
MyByte:=Byte(myHex SHR 16);// this moves the integer over by 16 binary digits and discards them.
//In memory $AABBCCDD becomes $0000AABB after the shift.
//let's get the $BB portion.
MyByte:=Byte(myHex SHR 24);// this moves the integer over by 24 binary digits and discards them.
//In memory $AABBCCDD becomes $000000AA after the shift.


In this next example, lets pretend we need to convert a value such as AABBCCDD to AA000000. While we could accomplish this with 2 shifts, it is easiest to use the and instruction. By doing $AABBCCDD and $FF000000, the result. The location of the F hex values will be the only portions remaining in the integer where the 0 values will be eliminated. Here are a few examples.

Var
int1,int2:Integer;
Begin
int1:=$AABBCCDD;
Int2:=int1 and $f0f0f0f0; //Int2=$A0B0C0D0
Int2:=int1 and $ff00;       //Int2=$0000CC00
End;

Question 6: How do I convert a float to hexadecimal?

 A very easy way to get the hexadecimal value of a float is to create a pointer to it and read it as a int64 value and use the format command to convert it to hexadecimal. Here is the approach I use:

VAR
flt: double;
I64: int64;
s:string;
Begin
flt:=12.45443563350
I64:=PInt64(@f1)^; //We get the address and read the value it contains as a int64 value.
s:=Format('%X', [I64]);//converts int64 to hex string;


This concludes this short entry on keygenning with delphi. If you have questions you would like to have answered, post them below and I will try to include them in my next tutorial. Until next time, happy reversing.