reg_hash Can have Capitals letters as you can see
private_key and private_key2 can only hold 0..9 and a..f (non-capitals)
Pretty nice start isn't it? Later you will find the use for this.
License Structure
This the main estructure
CODE
struct t_WL_License_File
{
DWORD unk0; // 0 :: DWORDs reg_hash[8] + reg_hash[C]
BYTE unk4; // 4 :: expiration_days Value if 0 then RDTSC
BYTE unk5; // 5 :: executions Value if 0 then RDTSC
DWORD unk6; // 6 :: expire_date Value if 0 then RDTSC
DWORD unkA; // A :: global_time Value if 0 then RDTSC
DWORD unkE; // E :: country Value if 0 then RDTSC
DWORD unk12; // 12 :: run_time | expiration_days Value if 0 then RDTSC
DWORD unk16; // 16 :: DWORDs reg_hash[10] + reg_hash[14]
BYTE unk1A; // 1A :: CheckSum HWID
WORD unk1B; // 1B :: CheckSum HWID
WORD unk1D; // 1D :: CheckSum HWID
WORD unk1F; // 1F :: CheckSum HWID
WORD unk21; // 21 :: CheckSum HWID
WORD unk23; // 23 :: RDTSC
WORD unk25; // 25 :: Flags
DWORD unk27; // 27 :: RDTSC
WORD unk2B; // 2B :: CheckSum User
WORD unk2D; // 2D :: CheckSum from 0..2D
DWORD unk2F; // 2F :: RDTSC
WORD unk33; // 33 :: WORDs reg_hash[18] + (DWORDs reg_hash[18] >> 0x10);
WORD unk35; // 35 :: CheckSum User
WORD unk37; // 2D :: CheckSum from 0..37
DWORD unk39; // 39 :: Always is 0xFFFFFFFF
DWORD unk3D; // 3D :: Always is 0xFFFFFFFF
BYTE unk41[0x2000 - 0x41]; // Empty Slots for other purposes
};
RDTSC is Time Stamp Counter ( an asm instruction) return its values in eax:edx, is like a rand() function
Unk0
is the result of the next operation = *(DWORD *)((LPBYTE)hash_key + 0x08) + *(DWORD *)((LPBYTE)hash_key + 0x0C);
Hey! so this value is checked if the License belong to that program!, nice start to avoid corrupt license message!, but is not as easy as i said xd, but for example look, reg_hash has this feautres, can hold from '0' (0x30) to 'z' (0x7A), so theoperation and the result will be between 0x60 to 0xF4, for eaxmple
0x5456886D - you would bever find this value on unk0 position! why? 0x54 does not belong to the range as well as 0x56
0xF5A6E89D - the same 0xF5 does not belong to the range!
0xCCA6E89D - ... Yes you can find it
Well, nice to see, but why do i need this?, simple, with this limitations you can discard values from Virtual Machine when comapring this values.
Unk4
Will hold the expirations days from the License, ONLY if the value is below 255!
Unk5
Contains the number of executions before license expires
Unk6
Contains the expire date in this format year - month - day
day is a byte value, is on the 0..7 bit
month is a byte value, is on 8..15 bit
year is a word value, is on a 16-32 bit
For example 07D70204 says that will license will expire on 2007-March-04
UnkA
Contains the Global Time before license expires
UnkE
Contains the locked country
Unk12
Well, i think here is a bug, coz on generated license one value destroys another, maybe i reversed i little bad
Unk1A
Take for example this HWID
105A-DF45-3533-AACC-328D-DEDF-6789-ABCD
Conatins Checksum of HarwareID, is the result of the addition between Orange and purple (0x6A)
Unk1B
Take for example this HWID
105A-DF45-3533-AACC-328D-DEDF-6789-ABCD
Conatins Checksum of HarwareID, is the result of the addition between Orange and purple
Unk1D
Take for example this HWID
105A-DF45-3533-AACC-328D-DEDF-6789-ABCD
Conatins Checksum of HarwareID, is the result of the addition between Orange and purple
Unk1F
Take for example this HWID
105A-DF45-3533-AACC-328D-DEDF-6789-ABCD
Conatins Checksum of HarwareID, is the result of the addition between Orange and purple
Unk21
Take for example this HWID
105A-DF45-3533-AACC-328D-DEDF-6789-ABCD
Conatins Checksum of HarwareID, is the result of the next operation
So unk2B is CreateCheckSumStr(user) + CreateCheckSumStr(company) + CreateCheckSumStr(CustomData) + CreateCheckSumStr(HWID)
Caution.- If in you application is enabled the Network instances you will see that CustomData Is a Little different, take for example this custom data
Without Network instances : 'This is Custom Data'
With Network instances : '*NL*0003This is Custom Data' <- in this case You got network instances ( is 3 ), *NL* is like a 'flag', that tells WL that Application have Network Instances, now, The CreateCheckSumStr in this case is only the purple data (not the *NL*)
CreateCheckSumStr(CustomData + 0x08);
Unk2D
Is the Result of a Checksum of the generated license from 0..2C
Unk41 to the end
This part contains the user, company, customdata (including *NL* part) and HWID, remember, this are NULL terminatedStrings, adn the separation between then are the 0xFFFFFFFF. Here you got an example
Howevber you will find this is not the end, you will find 0x100 more bytes after this Checksum Value, this vlues are a rsa sign, made from LicenseUnique Hash
This is the structure, but it not all, in the process, some parts are encrypted, many times, that i will complete later
Tracing License Building
The text above is just for say what you would find on a decrypted License File, but first it is necesary to decrypt it
So Here is the values set before the first encrypt (in order )
Now, after this encryption, another is made (what i call Method 2), take a look, this time hash_key is NOT altered, so you can find the original one in the encrypted application, like an null terminate string
void __declspec(naked) SubVarian_Method_02()
{
__asm
{
PUSH ECX
PUSH ESI
PUSH EDX
XOR EDX,EDX
DEC ESI
label2: INC ESI
XOR AH,BYTE PTR DS:[ESI]
label1: XOR AL,DL
ADD EAX,0x7034616B
MOV CL,AL
ROR EAX,CL
XOR EAX,0x8372A5A7
DEC DX
JNZ SHORT label1
CMP BYTE PTR DS:[ESI],0
JNZ SHORT label2
POP EDX
POP ESI
POP ECX
RETN
}
}
Now, the next values are set
CODE
WinLicenseFile->unk37 -- Checksum
WinLicenseFile->unk39
WinLicenseFile->unk3D
WinLicenseFile User, Company and Custom Data and HWID
After this, again the License File is encrypted using unk0, thi part Crypts the Usser, Company and Custom Data and HWID
Finally after the 0xFFFFFFFE 0xFFFFFFFE (after HWID ) is created the last Checksum according to the algorithm i put above
Now, we finish with the first stage of protection, here comes the second one
WinLicense Creates a 'sign', according to the License Unique Hash, beetween the fffefffe and the end (i mean private_key), it is always 0x100 bytes
- Using LibTomCrypt lib should be
This part is more difficult, since it uses rsa, but is pretty interesting once you got it
Licenses on 2.0.5.0
Here is and update to 2.0.5.0, the changes are that HWID is Wchar null termitated strings, Net instances are no longer stored on CustomData String, and there is some new params, Like dwLocalTime (Strores year, month and day, format similar to ExpirationDate), InstallDate
WinLicense Updated 2.0.5.0 License Structure Reversed
First how WL make unique Licenses for each program?, easy, as you can ses on the pic above, there is an 'hash', specific for each program, now this hash have three hashes insid, but how WL recognize them?, easy. Take for example my hash
/* C/C++ Format */