Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   Help with generating serial (https://forum.exetools.com/showthread.php?t=20016)

foil 12-15-2021 06:47

Help with generating serial
 
Hi guys,

I'm currently working on a piece of software and it is driving me crazy. I am able to 'register/activate' it by fudging all of the jumps at the serial key checker. However, I cannot for the life of me figure out the routine that actually creates the serial numbers..

Would any of you like to check this out and possibly give me an idea of how to do it?

I don't really want the company looking this direction by mentioning the name of it, but here is the link to the installer. (It's used for Nissan cars)

Link to the software:
Code:

https://nisscan.com/NDSI/index.php?content=download
It is written in VB6, and here is the "unlock" function that it performs:

Code:

Private Sub btnUnlock_Click() '53DC71
  Dim var_10C As Variant
  Dim var_114 As TextBox
  loc_0053DCC6: On Error GoTo loc_0053E93B
  loc_0053DCFB: var_40 = frmActivate.txtActivKey.Text
  loc_0053DD03: var_110 = var_40
  loc_0053DD70: If (var_40 = global_00425534) + 1 Then
  loc_0053DD7E:  var_40 = "Please enter Activation Key"
  loc_0053DDA1:  var_44 = Proc_15_1_52D634(&HCB)
  loc_0053DE08:  MsgBox(var_44, 0, 10, var_80, 10)
  loc_0053DE41: Else
  loc_0053DEE3:  var_8020 = GetVolumeInformation("C:\", String$(256, False), 255, global_005C507C, global_005C5084, global_005C5080, String$(256, False), 255)
  loc_0053DEFB:  var_8028 = var_44
  loc_0053DF08:  var_802C = var_48
  loc_0053DF13:  global_005C5088 = var_8020
  loc_0053DF46:  var_114 = frmActivate.txtActivKey
  loc_0053DF7C:  var_40 = frmActivate.txtActivKey.Text
  loc_0053DF84:  var_110 = var_40
  loc_0053E003:  var_114.Text = CStr(Trim(var_40))
  loc_0053E00B:  var_118 = var_114
  loc_0053E0A0:  var_40 = frmActivate.txtActivKey.Text
  loc_0053E0A8:  var_110 = var_40
  loc_0053E13E:  var_3C = Proc_23_0_565AB7(Proc_24_1_56681B("Tomasz", "Tomasz", 1), "Tomasz", Me)
  loc_0053E212:  var_2C = Proc_23_0_565AB7(Mid(var_3C, 17, Len(var_3C)), Mid(var_3C, 1, 16), 0)
  loc_0053E2A7:  var_8050 = Proc_23_0_565AB7(Proc_24_1_56681B(GetSetting("NDataScan", "Activation", "RegCode", 10), var_CC, 80020004h), "Lilys", var_C4)
  loc_0053E2B1:  var_3C = var_8050
  loc_0053E37A:  var_34 = Proc_23_0_565AB7(Mid(var_3C, 17, Len(var_3C)), Mid(var_3C, 1, 16), 0)
  loc_0053E3DC:  var_34 = Left(var_34, Len(var_34)(-1))
  loc_0053E42C:  var_34 = Right(var_34, Len(var_34)(-1))
  loc_0053E530:  If CBool((var_2C = var_34) And (var_2C = Str(global_005C507C)) And (var_34 = Str(global_005C507C))) Then
  loc_0053E53E:    var_40 = "NDSI has been sucessfully activated. Please restart NDSI."
  loc_0053E5C8:    MsgBox(Proc_15_1_52D634(&HCC), 0, 10, var_80, 10)
  loc_0053E614:    var_10C = frmActivate.btnUnlock
  loc_0053E62A:    var_10C.Enabled = False
  loc_0053E632:    var_110 = var_10C
  loc_0053E68B:    var_10C = frmActivate.txtRegCode
  loc_0053E6A1:    var_10C.Enabled = False
  loc_0053E6A9:    var_110 = var_10C
  loc_0053E702:    var_10C = frmActivate.txtActivKey
  loc_0053E718:    var_10C.Enabled = False
  loc_0053E720:    var_110 = var_10C
  loc_0053E779:    var_10C = frmActivate.lblNotice
  loc_0053E78F:    var_10C.Enabled = False
  loc_0053E797:    var_110 = var_10C
  loc_0053E808:    var_40 = frmActivate.txtActivKey.Text
  loc_0053E810:    var_110 = var_40
  loc_0053E85B:    SaveSetting("NDataScan", "Activation", "ActivKey", var_40)
  loc_0053E875:  Else
  loc_0053E87D:    var_40 = "You have entered wrong activation details. Please try again."
  loc_0053E907:    MsgBox(Proc_15_1_52D634(&HCD), 0, 10, 10, 10)
  loc_0053E93B:  End If
  loc_0053E93B: End If
  loc_0053E93B: Exit Sub
  loc_0053E945: GoTo loc_0053E9A2
  loc_0053E9A1: Exit Sub
  loc_0053E9A2: ' Referenced from: 0053E945
End Sub

I have found that it appends or prepends the string "*-91511383#" to the key, I think.. lol someone please help me. :)

xobor 12-15-2021 22:46

Hello,

try to look at loc_0052cf95

maybe this is what you looking for

foil 12-16-2021 01:00

Hi Xobor,

I appreciate your help with this!

What made you look at that address?
It's almost the very first thing that's done right after the entry point - I don't see anything about activation or registration?

Sorry, I'm not the greatest with this stuff yet, but am learning!

xobor 12-16-2021 16:54

Hello

in this function application reads ActivKey from registry and does some checks
it came interesting to me

best regards

QuakeGamer 12-17-2021 23:57

It seems Proc_23_0_565AB7 is calculating something relevant. What does the decompilation show for that part?

T-rad 12-18-2021 08:28

Quote:

Originally Posted by foil (Post 124194)

I have found that it appends or prepends the string "*-91511383#" to the key, I think.. lol someone please help me. :)

not quite. And that string is unique to your computer. so you have to find out how it is generated.

TempoMat 12-20-2021 04:20

Hi,

The procedure to generate the RegistrationCode aka RegCode in the version 1.63 with modified date 13.05.2013 is as follows:
Code:

1. Generate 16 radom numbers of base 256=Res1
2. SignedDec(VolumeInfoA("C:\"))=Res2
3. ConcatSeveralStrings("*",Res1,"#")=Res3
4. RC4_Encrypt(Key=Res1,Res3)=Res4
5. Concat(Res1,Res4)=Res5
6. RC4_Encrypt(Key="Lilys", Res5)=Res6
7. byteArrayToBase64(Res6)= RegCode

Hardcoding the drive "C:\" for the VolumeInfo will eg fail on some of my systems, which don't have a partition "C:\". That is just my thoughts.

From my investigation so far, I could not find the RegName and Email(no syntax check) been used or referenced anywhere during the check of the activation key.
They are however mandatory and the user will be promted to fill the corresponding empty field(s) before the RegistrationCode will be generated.

Anyways, the ActivationKey does the same thing but with Key="Tomasz" instead of "Lilys".

It should be noted however that both the initial 16 RadomNumbers(Res1) and the VolumeID (Res2) are in the resulted Regcode and are thus used to generate the ActivationKey, so that the 3 compares it does after decoding and decrypting the ActivationKey will match the original values.

Regards,
TemPoMat

PS: If I have time I will try to write a Keygen for it

T-rad 12-20-2021 14:33

Quote:

Originally Posted by TempoMat (Post 124233)
Hi,
1. Generate 16 radom numbers of base 256=Res1
2. SignedDec(VolumeInfoA("C:\"))=Res2
3. ConcatSeveralStrings("*",Res1,"#")=Res3

should be
3. ConcatSeveralStrings("*",Res2,"#")=Res3

just a note, the volume serial number is in number format, not hex format

TempoMat 12-21-2021 03:17

Quote:

Originally Posted by T-rad (Post 124239)
should be
3. ConcatSeveralStrings("*",Res2,"#")=Res3

just a note, the volume serial number is in number format, not hex format

Your are right.
and for the 2.Step it would have been clearer if I had written it as:
2. Hex2SignedDec(VolumeInfoA("C:\"))=Res2

TempoMat 12-21-2021 08:00

1 Attachment(s)
The Activation Key is calculated as follows:
Code:

1. AK1 = the 16 RandomBytes from Res1
2. AK2 = the Hex2SignedDec(VolumeInfoA("C:\")) from Res2
3. AK3 = RC4_Encrypt(Key=AK1, Data=AK2)
4. AK4 = ConCat(AK1,AK3)
5. AK5 = RC4_Encrypt(Key="Tomasz", Data=AK4)
6. ActivKey = byteArrayToBase64(AK5)

The only step missing here is the step
3. ConcatSeveralStrings("*", Res2 ,"#")=Res3

Cheers

raduga_fb 12-21-2021 16:15

Actually, "#" and "*" to be removed to create Activation Code.

Code:

string pass_1 = "?????";
byte[] pass_1_b = Encoding.ASCII.GetBytes(pass_1);

string pass_2 = "??????";
byte[] pass_2_b = Encoding.ASCII.GetBytes(pass_2);


byte[] hexData = Convert.FromBase64String(Registratin_Code);

byte[] z1 = RC4.Decrypt(pass_1_b, hexData);

byte[] pass_3_b = new byte[16];
Buffer.BlockCopy(z1, 0, pass_3_b, 0, 16);

byte[] z5 = new byte[z1.Length - 16];
Buffer.BlockCopy(z1, 16, z5, 0, z1.Length - 16);

byte[] z3 = RC4.Decrypt(pass_3_b, z5);

string z3_str = BitConverter.ToString(z3).Replace("-", "");

string z4 = Encoding.ASCII.GetString(z3);

//************************************************************

string girdi = z4.Replace("#", "").Replace("*", "");

byte[] girdi_b = Encoding.ASCII.GetBytes(girdi);

byte[] x1 = RC4.Encrypt(pass_3_b, girdi_b);

byte[] x2 = new byte[x1.Length + 16];
Buffer.BlockCopy(pass_3_b, 0, x2, 0, 16);

Buffer.BlockCopy(x1, 0, x2, 16, x1.Length);

byte[] x3 = RC4.Encrypt(pass_2_b, x2);


//************************************************************

string Activation_Code = Convert.ToBase64String(x3);


foil 12-22-2021 04:00

Thank you, everyone, for helping me out with this.
I will have some free time on Thursday night to check it out again, with all of your notes by my side!

I appreciate all of you :)

@raduga_fb - is there a certain module that you used when using RC4? Visual Studio only has RC2 by default, from what I can remember.

raduga_fb 12-23-2021 01:31

RC4
 
Code:

public class RC4
    {
        public static byte[] Encrypt(byte[] pwd, byte[] data)
        {
            int a, i, j, k, tmp;
            int[] key, box;
            byte[] cipher;

            key = new int[256];
            box = new int[256];
            cipher = new byte[data.Length];

            for (i = 0; i < 256; i++)
            {
                key[i] = pwd[i % pwd.Length];
                box[i] = i;
            }
            for (j = i = 0; i < 256; i++)
            {
                j = (j + box[i] + key[i]) % 256;
                tmp = box[i];
                box[i] = box[j];
                box[j] = tmp;
            }
            for (a = j = i = 0; i < data.Length; i++)
            {
                a++;
                a %= 256;
                j += box[a];
                j %= 256;
                tmp = box[a];
                box[a] = box[j];
                box[j] = tmp;
                k = box[((box[a] + box[j]) % 256)];
                cipher[i] = (byte)(data[i] ^ k);
            }
            return cipher;
        }

        public static byte[] Decrypt(byte[] pwd, byte[] data)
        {
            return Encrypt(pwd, data);
        }

    }


foil 12-24-2021 03:15

Hi @raduga_fb

I really appreciate all of the help you've given me!

I compiled the code that you have given me, but am still receiving an error message stating that the activation key is incorrect.

Here is a screenshot of the source, the activation code generated and the error on activation: https://f0il.com/datascan.png

Am I doing something wrong in all of that? I'm still trying to wrap my head around how you figured all of this out in the first place lol sorry for my ignorance!

raduga_fb 12-24-2021 04:12

:) You need to eat much more bread.

Who said that pass_1 & pass_2 should be name & email? They are already mentioned above.

string pass_1 = "?????" <- 5 digits = Li***

string pass_2 = "??????" <- 6 digits = To****

TempoMat 12-24-2021 06:03

I did some tests on step 2 with different values for the VolumInfoA
2. AK2 = the Hex2SignedDec(VolumeInfoA("C:\")) from Res2
and found out that if the value of the VolumeSerialNumber is positive i.e. below 0x80000000 then the converted value has a space(0x20) instead of "+" before it.

Final thing to note is that the RegCode should always be generated on the target computer. Then the 3 checks the program does are all related to the result from Step2

First it gets the Hex2SignedDec(VoluemInfoA("C:\")=>VolumeSerialNum then decrypts the RegCode and the ActivKey and final does the following comparisons:

Is VolumeSerialNum=Res2 from decrypted RegCode?
Is VolumeSerialNum=AK2 from the decrypted ActivKey?
Is Res2=AK2?

foil 12-24-2021 06:39

Quote:

Originally Posted by raduga_fb (Post 124279)
:) You need to eat much more bread.

Who said that pass_1 & pass_2 should be name & email? They are already mentioned above.

string pass_1 = "?????" <- 5 digits = Li***

string pass_2 = "??????" <- 6 digits = To****

Hi @raduga_fb
Ahhh, okay, that worked! I do need much more knowledge with encryption and decryption. I am reading lots of material about the subjects, and am rewriting your code by hand on paper to try to understand the flow a little better :)

I did receive an error on a second test machine about the Registration Code not being a valid Base64 string, but I'll cross that bridge later.

Thank you again for all of your help, I haven't ever put much effort into reversing keys! :)

Quote:

Originally Posted by TempoMat (Post 124281)
I did some tests on step 2 with different values for the VolumInfoA
2. AK2 = the Hex2SignedDec(VolumeInfoA("C:\")) from Res2
and found out that if the value of the VolumeSerialNumber is positive i.e. below 0x80000000 then the converted value has a space(0x20) instead of "+" before it.

Final thing to note is that the RegCode should always be generated on the target computer. Then the 3 checks the program does are all related to the result from Step2

First it gets the Hex2SignedDec(VoluemInfoA("C:\")=>VolumeSerialNum then decrypts the RegCode and the ActivKey and final does the following comparisons:

Is VolumeSerialNum=Res2 from decrypted RegCode?
Is VolumeSerialNum=AK2 from the decrypted ActivKey?
Is Res2=AK2?

I appreciate all of your help as well, @TempoMat ! :)
I am studying over everything that everyone has told me and am not going to give up on it! Thank you so much

T-rad 12-25-2021 15:47

Actually the RegCode is useless for generating a working key. also check 3 is redundant. is only checking if the VolumeSerialNum from RES2 is the same VolumeSerialNum from AK2. If check 1 & 2 pass, 3 has no choice but to pass

TempoMat 12-26-2021 21:30

Quote:

Originally Posted by T-rad (Post 124294)
... also check 3 is redundant. is only checking if the VolumeSerialNum from RES2 is the same VolumeSerialNum from AK2. If check 1 & 2 pass, 3 has no choice but to pass

I agree with you. Maybe the programmer/vendor is paranoid.

Quote:

Originally Posted by T-rad (Post 124294)
Actually the RegCode is useless for generating a working key....

Not for the programmer/vendor, then he will need the RegCode in order to extract from it the RandomBytes and the VolumeSerialNum to generate the corresponding correct key for the registrant.

A Keygen can for instance have the option for the user to enter a Regcode (Registation code) from a different machine and generate the corresponding ActivKey (Activation Key).
Also just for a gemmick, it could include options to decode the RegCode and ActiveKey to compare the RandomBytes and the VolumeSerialNum.

T-rad 12-27-2021 04:36

Quote:

Not for the programmer/vendor, then he will need the RegCode in order to extract from it the RandomBytes and the VolumeSerialNum to generate the corresponding correct key for the registrant.
not exactly, the vendor just requires the VolumeSerialNumber, the rest is just for show.
Any random bytes will work so they do not need to be extracted as the program decrypts the decoded bytes using the first 16 bytes as the key.

Code:

var_2C = Proc_23_0_565AB7(Mid(var_3C, 17, Len(var_3C)), Mid(var_3C, 1, 16), 0)
= RC4(data, key)

for example... using 0123456789ABCDEFFEDCBA9876543210 as the random bytes / key and using *-91511383# from the first post, this key should work for that computer

ts3Huirg1Olt00VIn78ZgsVes7y8VZqw1Q==

TempoMat 12-27-2021 21:11

Quote:

Originally Posted by T-rad (Post 124322)
for example... using 0123456789ABCDEFFEDCBA9876543210 as the random bytes / key and using *-91511383# from the first post, this key should work for that computer

ts3Huirg1Olt00VIn78ZgsVes7y8VZqw1Q==

Your key in itself is correct but it will only be accepted if the same random bytes are used for the generation of the RegCode as well.
Meaning that the key is valid if and only if the Regcode is replaced with a newly generated one with your sample random bytes.

The VolumeSerialNum is for sure the only part that is always the same on a target machine but every newly generated RegCode will have a different random bytes which are used in the ActivKey generation as well.

Therefore using different random bytes as in your key with the initial RegCode from post #1 will fail.

As a prove, deleting the string value for RegCode in the registry location: example
Code:

[HKEY_CURRENT_USER\Software\VB and VBA Program Settings\NDataScan\Activation]
"Name"="TemPoMat"
"Email"="TemPoMat"
"RegCode"="GIv/lhuqYNCUTPZfPgYG3rM5EtzvsurmsyLeOB0"
"ActivKey"="mP1y4G/RxxQvtIPpV8ZAI/yGoab2NnDSgZWT"

will result in a new RegCode been generated with the same VolumeSerialNum but different random bytes upon re-registration.

I assume this is one of the reasons it is doing the 3 checks.

T-rad 12-27-2021 23:22

It will work regardless. I've tried it, using my own volume serial of course.

There is does no check against the random bytes.

Code:

var_8020 = GetVolumeInformation("C:\", String$(256, False), 255, global_005C507C, global_005C5084, global_005C5080, String$(256, False), 255)
global_005C507C = VolumeSerial#


Code:

var_2C = Proc_23_0_565AB7(Mid(var_3C, 17, Len(var_3C)), Mid(var_3C, 1, 16), 0)
var_2C = decoded VolumeSerial# from our input



Code:

var_8050 = Proc_23_0_565AB7(Proc_24_1_56681B(GetSetting("NDataScan", "Activation", "RegCode", 10), var_CC, 80020004h), "Lilys", var_C4)
var_3C = var_8050
var_34 = Proc_23_0_565AB7(Mid(var_3C, 17, Len(var_3C)), Mid(var_3C, 1, 16), 0)
var_34 = Left(var_34, Len(var_34)(-1))
var_34 = Right(var_34, Len(var_34)(-1))

var_34 = decoded VolumeSerial# from registry, less the left and right chars

Code:

If CBool((var_2C = var_34) And (var_2C = Str(global_005C507C)) And (var_34 = Str(global_005C507C))) Then
var_40 = "NDSI has been sucessfully activated. Please restart NDSI."

check 1. -> var_2C = var_34
compare the decoded VolumeSerial# from our input with the decoded VolumeSerial# from registry, less the left and right chars.

check 2 -> var_2C = Str(global_005C507C)
compare the decoded VolumeSerial# from our input with the GetVolumeInformation VolumeSerial#

check 3 -> var_34 = Str(global_005C507C)
decoded VolumeSerial# from registry, less the left and right chars with the GetVolumeInformation VolumeSerial#


as i said before, check 3 is redundant. It will always pass as the program generated it .

TempoMat 12-29-2021 20:37

Quote:

Originally Posted by T-rad (Post 124329)
It will work regardless. I've tried it, using my own volume serial of course.

There is does no check against the random bytes.

Correct.
That is because the random bytes used to encrypt the VolumeSerialNum in the 1.encryption are in themselves included in each case in the 2.encryption leading to the final RegCode and the ActivKey respectively.

Therefore an ActivKey generated with the same VolumeSerialNum of a target machine will work regardless of the RegCode.

Quote:

Originally Posted by T-rad (Post 124329)
as i said before, check 3 is redundant. It will always pass as the program generated it .

This is a valid point.


All times are GMT +8. The time now is 06:50.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX