Source Insight 4.x: Reversing the License Scheme and Building an Offline Keygen
About the author. I’m Colin Xiao — an independent reverse engineer, mostly working solo on contract jobs. I dig into compiled code of every kind, including but not limited to: Android and iOS apps, x86/x64/ARM native binaries, packers and obfuscators, DRM and license checks, network protocols and APIs, crypto and signature algorithms, malware, game binaries, and embedded/IoT firmware. I also handle large-scale data collection and vulnerability research. If you have any project in mind, I’d be glad to take it on — whatever it is, as long as it’s within my wheelhouse. Just reach out. You can reach me on X at @colinxiao_lab or on Telegram at https://t.me/ColinXiao666.
This research is published for educational and defensive purposes. The target sample is anonymized throughout.
Source Insight 4.x: Reversing the License Scheme and Building an Offline Keygen
Version analyzed: Source Insight 4.00.0128.
1. Serial validation
Disable ASLR to make analysis easier.

Use Spy++ to inspect the properties of the input controls, then set a conditional breakpoint on GetWindowsTextW() by the control handle.

After capturing the typed-in serial, open the binary in IDA. The serial-validation function:
BOOL __cdecl sub_514BA0(char *szSerial, void *ArgcList_608, void *ArgcList_60C, void *ArgcList_604, int n_1)
{
char v5; // al
char v6; // al
char v7; // al
char v8; // al
int v10; // [esp+4h] [ebp-18h] BYREF
char Destination[20]; // [esp+8h] [ebp-14h] BYREF
_strupr(szSerial);
if ( strlen(szSerial) != 19 )
return 0;
if ( szSerial[4] != '-' )
return 0;
if ( szSerial[9] != '-' )
return 0;
if ( szSerial[14] != '-' )
return 0;
if ( *szSerial != 'S' )
return 0;
if ( n_1 )
{
v5 = szSerial[6];
if ( v5 != 'R' && v5 != 'G' && v5 != 'D' && v5 != 'F' )
return 0;
}
v6 = szSerial[1];
if ( v6 < '0' || v6 > '9' )
return 0;
*ArgcList_604 = v6 - '0'; // *ArgcList_604 = szSerial[1] - '0';
v7 = szSerial[2];
switch ( v7 ) // *ArgcList_604 = [1 3 0 0]
{
case 'T':
*ArgcList_60C = 1;
break;
case 'B':
*ArgcList_60C = 3;
break;
case 'S':
*ArgcList_60C = 0;
break;
case 'U':
*ArgcList_60C = 0;
break;
default:
return 0;
}
v8 = szSerial[3];
if ( v8 == 'G' )
{
*ArgcList_608 = 1;
}
else
{
if ( v8 != 'R' )
return 0;
*ArgcList_608 = 0;
}
if ( !n_1 )
return 1;
strcpy(Destination, szSerial);
Destination[15] = 0;
sub_514370(Destination, 15, &unk_604F70, &v10);// generate the last 4 chars from the first 15 chars
return *(szSerial + 15) == v10; // check whether the generated last 4 match the last 4 in the serial
}
The program helpfully shows the serial format: S4XX-XXXX-XXXX-XXXX.
Serial[0] = 'S'
Serial[1] = '4'
Serial[2] = 'T'/'B'/'S'/'U'
Serial[3] = 'G' (must not be 'R')
Serial[6] = 'R'/'G'/'D'/'F'
So a forged serial looks like S4SG-ARCD-EFGH-XXXX, where the last four can be produced by sub_514370().
The last-four algorithm:
int __cdecl sub_514370(_BYTE *szSerial, unsigned int nSerialLength, char *pTable, int nResult)
{
unsigned int i; // esi
unsigned __int8 v5; // cl
unsigned int j; // eax
int result; // eax
for ( i = 0; i < 4; *(i + nResult - 1) = byte_604E50[v5 % 26] )
{
v5 = pTable[(i + *szSerial)];
for ( j = 1; j < nSerialLength; ++j )
v5 = pTable[v5 ^ szSerial[j]];
result = nResult;
++i;
}
return result;
}
Writing the keygen from that:
unsigned char g_szAlphabetTable[] =
{
0x4B, 0x56, 0x39, 0x36, 0x47, 0x4D, 0x4A, 0x59, 0x48, 0x37,
0x51, 0x46, 0x35, 0x54, 0x43, 0x57, 0x34, 0x55, 0x33, 0x58,
0x5A, 0x50, 0x52, 0x53, 0x44, 0x4E, 0x00
};
int __cdecl sub_514370(char* szSerial, unsigned int nSerialLength, char* pTable, char* pLastFourCharacters)
{
unsigned int i; // esi
unsigned __int8 v5; // cl
unsigned int j; // eax
int result; // eax
for (i = 0; i < 4; *(i + pLastFourCharacters - 1) = g_szAlphabetTable[v5 % 26])
{
v5 = pTable[(i + *szSerial)];
for (j = 1; j < nSerialLength; ++j)
v5 = pTable[v5 ^ szSerial[j]];
result = pLastFourCharacters;
++i;
}
return result;
}
int main(int argc, char* argv[])
{
// "S4SG-XRXX-XXXX-XXXX"
char szSerial[20] = { 'S', '4', 'S', 'G', '-', 'A', 'R', 'C', 'D', '-', 'E', 'F', 'G', 'H', '-', 'X', 'X', 'X', 'X' , 0 };
char aryLastFourCharacters[4] = {0};
sub_514370(szSerial, 15, g_aryTable, &aryLastFourCharacters);
*(PULONG)(szSerial + 15) = *(PLONG)aryLastFourCharacters;
printf("Serial: %s", szSerial);
}
The last four come out as 36V6, giving the serial S4SG-ARCD-EFGH-36V6.
2. Online validation
After entering the serial and filling in your info, the program shows “Now activating your license… Please wait…”. Open Fiddler and you’ll see it sends an HTTP request. Set a breakpoint on HttpSendRequestW(), and you’ll see it calls HttpQueryInfo() to read the response status code and checks whether it’s 200. But the server returns 460, so online validation fails. You could patch the instruction right after HttpQueryInfo() and force the comparison variable to 200. I didn’t bother, because the signature file gives us offline registration.
int __usercall sub_425860@<eax>(
char *Str,
int a3,
const CHAR *lpMultiByteStr,
char *lpOptional,
_BYTE *lpBuffer,
int a7)
{
int v6; // ebp MAPDST
DWORD v7; // edi
DWORD v8; // ebx
INTERNET_PORT v9; // si
void *v10; // eax
void *v12; // eax
void *v13; // ebp
void *v14; // eax
void *v15; // esi
int LastError; // eax
int v18; // [esp+0h] [ebp-11Ch]
int result; // [esp+Ch] [ebp-110h] BYREF
DWORD dwNumberOfBytesRead; // [esp+10h] [ebp-10Ch] BYREF
DWORD dwBufferLength; // [esp+14h] [ebp-108h] BYREF
HINTERNET hInternet; // [esp+18h] [ebp-104h]
char v23[256]; // [esp+1Ch] [ebp-100h] BYREF
v7 = strlen(lpOptional);
result = 0x3E8;
dwBufferLength = 4;
v8 = 67420928;
if ( a3 )
{
v8 = 75817728;
v9 = 443;
}
else
{
v9 = 80;
}
v10 = sub_455BE0("Source Insight", 0, 0, 0, 0);
hInternet = v10;
if ( v10 )
{
v12 = sub_455D90(v10, Str, v9, 0, 0, 3u, 0, 0);
v13 = v12;
if ( v12 )
{
v14 = sub_455F60(v12, "POST", lpMultiByteStr, 0, 0, 0, v8, 0);
v15 = v14;
if ( v14 )
{
sub_456190(v14, "Content-Type: application/x-www-form-urlencoded", 0xFFFFFFFF, 0x20000000u);
sub_456190(v15, "Accept: text/plain", 0xFFFFFFFF, 0x20000000u);
sprintf(v23, "Content-length: %d\n", v7);
sub_456190(v15, v23, 0xFFFFFFFF, 0x20000000u);
if ( HttpSendRequestW(v15, 0, 0, lpOptional, v7) )
{
HttpQueryInfoW(v15, 0x20000013u, &result, &dwBufferLength, 0);
if ( result == 0xC8 ) // check the returned status code
{
if ( InternetReadFile(v15, lpBuffer, a7 - 1, &dwNumberOfBytesRead) )
{
lpBuffer[dwNumberOfBytesRead] = 0;
result = 0xC8;
}
else
{
lpBuffer[dwNumberOfBytesRead] = 0;
sub_413440(0, 0, "InternetReadFile Error", v6);
result = 1007;
}
}
}
else
{
LastError = GetLastError();
result = (LastError == 12045) + 1004;
sub_413440(0, 0, "HttpSendRequest Error %d", LastError);
}
InternetCloseHandle(v15);
}
else
{
sub_413440(0, 0, "HttpOpenRequest failed.", v6);
result = 1006;
}
InternetCloseHandle(v13);
}
else
{
sub_413440(0, 0, "InternetConnect failed.", v6);
result = 0x3EA;
}
InternetCloseHandle(hInternet);
return result;
}
else
{
sub_413440(0, 0, "InternetOpen failed.", v18);
return 0x3E9;
}
}
After web validation passes, the program writes the registry and C:\ProgramData\Source Insight\4.0\si4.lic.
int __thiscall sub_5171D0(const CHAR *this, int a2)
{
int result; // eax
int v4; // [esp+4h] [ebp-3FA4h] BYREF
int v5[2024]; // [esp+8h] [ebp-3FA0h] BYREF
char Str[8192]; // [esp+1FA8h] [ebp-2000h] BYREF
memset(Str, 0, sizeof(Str));
result = sub_515290(this, v5, 0x1FA0); // send the HTTP packet for online validation
if ( result == 0xC8 )
{
if ( a2 )
{
if ( sub_514610(this + 0x75C, &v4, 0x1FA0) == 0xC8 )
sub_516FF0(this, &v4);
return 0xC8;
}
else
{ // after web validation, this branch is taken
sub_412990(); // check whether online validation passed
if ( sub_425C80(&v4, &v5[2023], 0x2000u) && strlen(&v5[2023]) >= 8 ) // check the online validation info
{
sub_516FF0(this, &Str[4]); // write registry
return sub_5148C0(this + 0x75C, &Str[4]); // write the si4.lic file
}
else
{
return 0x1D0;
}
}
}
return result;
}
3. The si.lic file
Validating si.lic has three parts:
- Check each field in the
LicensePropertiesblock. - Validate the
Signature. - Check the
ActIdfield in theLicensePropertiesblock.
The main function:
00518160 | 81EC 00010000 | sub esp,100 |
00518166 | 56 | push esi |
00518167 | 8BF1 | mov esi,ecx |
00518169 | E8 A2CFFFFF | call sourceinsight4.515110 |
0051816E | 68 D0706000 | push sourceinsight4.6070D0 | 6070D0:"Loading license file"
00518173 | E8 18A8EFFF | call sourceinsight4.412990 |
00518178 | 83C4 04 | add esp,4 |
0051817B | 8BCE | mov ecx,esi |
0051817D | E8 4EE6FFFF | call sourceinsight4.5167D0 | 1. check the data in the file
00518182 | 3D C8000000 | cmp eax,C8 |
00518187 | 74 2A | je sourceinsight4.5181B3 |
00518189 | 83BC24 08010000 00 | cmp dword ptr ss:[esp+108],0 |
00518191 | 74 0D | je sourceinsight4.5181A0 |
00518193 | 50 | push eax |
00518194 | 8BCE | mov ecx,esi |
00518196 | E8 35CCFFFF | call sourceinsight4.514DD0 |
0051819B | E8 F0AAEFFF | call sourceinsight4.412C90 |
005181A0 | 8BCE | mov ecx,esi |
005181A2 | E8 69CFFFFF | call sourceinsight4.515110 |
005181A7 | 33C0 | xor eax,eax |
005181A9 | 5E | pop esi |
005181AA | 81C4 00010000 | add esp,100 |
005181B0 | C2 0400 | ret 4 |
005181B3 | 8B06 | mov eax,dword ptr ds:[esi] |
005181B5 | 83F8 02 | cmp eax,2 |
005181B8 | 75 1F | jne sourceinsight4.5181D9 |
005181BA | 68 A4706000 | push sourceinsight4.6070A4 | 6070A4:"Deferred Activation license file loaded."
005181BF | E8 CCA7EFFF | call sourceinsight4.412990 |
005181C4 | 83C4 04 | add esp,4 |
005181C7 | C706 00000000 | mov dword ptr ds:[esi],0 |
005181CD | 33C0 | xor eax,eax |
005181CF | 5E | pop esi |
005181D0 | 81C4 00010000 | add esp,100 |
005181D6 | C2 0400 | ret 4 |
005181D9 | 83F8 03 | cmp eax,3 |
005181DC | 75 2F | jne sourceinsight4.51820D |
005181DE | 8D86 3A070000 | lea eax,dword ptr ds:[esi+73A] |
005181E4 | 50 | push eax |
005181E5 | 8D8E 5C070000 | lea ecx,dword ptr ds:[esi+75C] | esi+75C:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
005181EB | 51 | push ecx |
005181EC | E8 9FDDFFFF | call sourceinsight4.515F90 | 2. check the Signature
005181F1 | 83C4 08 | add esp,8 |
005181F4 | 3D C8000000 | cmp eax,C8 |
005181F9 | 75 2F | jne sourceinsight4.51822A |
005181FB | 8BCE | mov ecx,esi |
005181FD | E8 1EF7FFFF | call sourceinsight4.517920 | 3. check ActId
00518202 | 85C0 | test eax,eax |
00518204 | 75 4E | jne sourceinsight4.518254 |
00518206 | B8 EB010000 | mov eax,1EB |
0051820B | EB 1D | jmp sourceinsight4.51822A |
0051820D | 8D96 3A070000 | lea edx,dword ptr ds:[esi+73A] |
00518213 | 52 | push edx |
00518214 | 8D86 5C070000 | lea eax,dword ptr ds:[esi+75C] | esi+75C:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051821A | 50 | push eax |
0051821B | E8 80EBFFFF | call sourceinsight4.516DA0 |
00518220 | 83C4 08 | add esp,8 |
00518223 | 3D C8000000 | cmp eax,C8 |
00518228 | 74 2A | je sourceinsight4.518254 |
0051822A | 83BC24 08010000 00 | cmp dword ptr ss:[esp+108],0 |
00518232 | 74 0D | je sourceinsight4.518241 |
00518234 | 50 | push eax |
00518235 | 8BCE | mov ecx,esi |
00518237 | E8 94CBFFFF | call sourceinsight4.514DD0 |
0051823C | E8 4FAAEFFF | call sourceinsight4.412C90 |
00518241 | 8BCE | mov ecx,esi |
00518243 | E8 C8CEFFFF | call sourceinsight4.515110 |
00518248 | 33C0 | xor eax,eax |
0051824A | 5E | pop esi |
0051824B | 81C4 00010000 | add esp,100 |
00518251 | C2 0400 | ret 4 |
00518254 | 83BE 0C060000 01 | cmp dword ptr ds:[esi+60C],1 |
0051825B | 57 | push edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051825C | BF DCA25F00 | mov edi,sourceinsight4.5FA2DC | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic", 5FA2DC:"Trial"
00518261 | 74 05 | je sourceinsight4.518268 |
00518263 | BF 80616000 | mov edi,sourceinsight4.606180 | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic", 606180:"Standard"
00518268 | 8D4C24 08 | lea ecx,dword ptr ss:[esp+8] |
0051826C | 51 | push ecx |
0051826D | 8D8E 1C060000 | lea ecx,dword ptr ds:[esi+61C] |
00518273 | E8 F869F3FF | call sourceinsight4.44EC70 | generates a date string
00518278 | 8D5424 08 | lea edx,dword ptr ss:[esp+8] |
0051827C | 52 | push edx |
0051827D | 57 | push edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051827E | 68 7C706000 | push sourceinsight4.60707C | 60707C:"License OK: %s License activated %s UTC"
00518283 | E8 08A7EFFF | call sourceinsight4.412990 | generate registration info
00518288 | 83C4 0C | add esp,C |
0051828B | 5F | pop edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051828C | B8 01000000 | mov eax,1 |
00518291 | 5E | pop esi |
00518292 | 81C4 00010000 | add esp,100 |
00518298 | C2 0400 | ret 4 |
3.1 Checking the LicenseProperties fields
This function returns 0xC8 to signal a pass.
005167D0 | 64:A1 00000000 | mov eax,dword ptr fs:[0] | eax:&"ActId"
005167D6 | 6A FF | push FFFFFFFF |
005167D8 | 68 FB365D00 | push sourceinsight4.5D36FB |
005167DD | 50 | push eax | eax:&"ActId"
005167DE | 64:8925 00000000 | mov dword ptr fs:[0],esp |
005167E5 | 81EC 10040000 | sub esp,410 |
005167EB | 53 | push ebx |
005167EC | 56 | push esi |
005167ED | 33DB | xor ebx,ebx |
005167EF | 57 | push edi |
005167F0 | 8BF1 | mov esi,ecx |
005167F2 | 33C0 | xor eax,eax | eax:&"ActId"
005167F4 | 895C84 1C | mov dword ptr ss:[esp+eax*4+1C],ebx |
005167F8 | 899C84 1C020000 | mov dword ptr ss:[esp+eax*4+21C],ebx |
005167FF | 40 | inc eax | eax:&"ActId"
00516800 | 3D 80000000 | cmp eax,80 | eax:&"ActId"
00516805 | 72 ED | jb sourceinsight4.5167F4 |
00516807 | 899C24 24040000 | mov dword ptr ss:[esp+424],ebx |
0051680E | 8D4424 1C | lea eax,dword ptr ss:[esp+1C] |
00516812 | 50 | push eax | eax:&"ActId"
00516813 | 8D8E 5C070000 | lea ecx,dword ptr ds:[esi+75C] | esi+75C:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00516819 | 51 | push ecx |
0051681A | E8 71E9FFFF | call sourceinsight4.515190 | parse the file data and save it
0051681F | 83C4 08 | add esp,8 |
00516822 | 8D5424 0C | lea edx,dword ptr ss:[esp+C] |
00516826 | 52 | push edx |
00516827 | 68 CCD05E00 | push sourceinsight4.5ED0CC | 5ED0CC:"Type"
0051682C | 8D4C24 24 | lea ecx,dword ptr ss:[esp+24] | [esp+24]:"ActId"
00516830 | 899E 0C060000 | mov dword ptr ds:[esi+60C],ebx |
00516836 | E8 85DDFFFF | call sourceinsight4.5145C0 | read the Type field value
0051683B | 85C0 | test eax,eax | eax:&"ActId"
0051683D | 74 58 | je sourceinsight4.516897 |
0051683F | 8B7C24 0C | mov edi,dword ptr ss:[esp+C] |
00516843 | 68 DCA25F00 | push sourceinsight4.5FA2DC | 5FA2DC:"Trial"
00516848 | 57 | push edi |
00516849 | E8 DCA50B00 | call sourceinsight4.5D0E2A | stricmp(["Type"], "Trial")
0051684E | 83C4 08 | add esp,8 |
00516851 | 85C0 | test eax,eax | eax:&"ActId"
00516853 | 75 0C | jne sourceinsight4.516861 |
00516855 | C786 0C060000 01000000 | mov dword ptr ds:[esi+60C],1 |
0051685F | EB 36 | jmp sourceinsight4.516897 |
00516861 | 68 8C616000 | push sourceinsight4.60618C | 60618C:"Beta"
00516866 | 57 | push edi |
00516867 | E8 BEA50B00 | call sourceinsight4.5D0E2A |
0051686C | 83C4 08 | add esp,8 |
0051686F | 85C0 | test eax,eax | eax:&"ActId"
00516871 | 75 0C | jne sourceinsight4.51687F |
00516873 | C786 0C060000 03000000 | mov dword ptr ds:[esi+60C],3 |
0051687D | EB 18 | jmp sourceinsight4.516897 |
0051687F | 68 80616000 | push sourceinsight4.606180 | 606180:"Standard"
00516884 | 57 | push edi |
00516885 | E8 A0A50B00 | call sourceinsight4.5D0E2A |
0051688A | 83C4 08 | add esp,8 |
0051688D | 85C0 | test eax,eax | eax:&"ActId"
0051688F | 75 06 | jne sourceinsight4.516897 |
00516891 | 899E 0C060000 | mov dword ptr ds:[esi+60C],ebx |
00516897 | 8D4424 0C | lea eax,dword ptr ss:[esp+C] |
0051689B | 50 | push eax | eax:&"ActId"
0051689C | 68 D0656000 | push sourceinsight4.6065D0 | 6065D0:"LicensedUser"
005168A1 | 8D4C24 24 | lea ecx,dword ptr ss:[esp+24] | [esp+24]:"ActId"
005168A5 | E8 16DDFFFF | call sourceinsight4.5145C0 | read the ["LicensedUser"] value
005168AA | 85C0 | test eax,eax | eax:&"ActId"
005168AC | 0F84 36030000 | je sourceinsight4.516BE8 |
005168B2 | 8B4C24 0C | mov ecx,dword ptr ss:[esp+C] |
005168B6 | 51 | push ecx |
005168B7 | 8D96 04010000 | lea edx,dword ptr ds:[esi+104] |
005168BD | 52 | push edx |
005168BE | E8 BD4E0A00 | call sourceinsight4.5BB780 | strcpy(edx, ["LicensedUser"])
005168C3 | 83C4 08 | add esp,8 |
005168C6 | 8D4424 0C | lea eax,dword ptr ss:[esp+C] |
005168CA | 50 | push eax | eax:&"ActId"
005168CB | 68 C0656000 | push sourceinsight4.6065C0 | 6065C0:"Organization"
005168D0 | 8D4C24 24 | lea ecx,dword ptr ss:[esp+24] | [esp+24]:"ActId"
005168D4 | E8 E7DCFFFF | call sourceinsight4.5145C0 | read the ["Organization"] value
005168D9 | 85C0 | test eax,eax | eax:&"ActId"
005168DB | 74 14 | je sourceinsight4.5168F1 |
005168DD | 8B4C24 0C | mov ecx,dword ptr ss:[esp+C] |
005168E1 | 51 | push ecx |
005168E2 | 8D96 04020000 | lea edx,dword ptr ds:[esi+204] |
005168E8 | 52 | push edx |
005168E9 | E8 924E0A00 | call sourceinsight4.5BB780 | strcpy(edx, ["Organization"])
005168EE | 83C4 08 | add esp,8 |
005168F1 | 8D4424 0C | lea eax,dword ptr ss:[esp+C] |
005168F5 | 50 | push eax | eax:&"ActId"
005168F6 | 68 B8656000 | push sourceinsight4.6065B8 | 6065B8:"Email"
005168FB | 8D4C24 24 | lea ecx,dword ptr ss:[esp+24] | [esp+24]:"ActId"
005168FF | E8 BCDCFFFF | call sourceinsight4.5145C0 | read the ["Email"] value
00516904 | 85C0 | test eax,eax | eax:&"ActId"
00516906 | 74 14 | je sourceinsight4.51691C |
00516908 | 8B4C24 0C | mov ecx,dword ptr ss:[esp+C] |
0051690C | 51 | push ecx |
0051690D | 8D96 04030000 | lea edx,dword ptr ds:[esi+304] |
00516913 | 52 | push edx |
00516914 | E8 674E0A00 | call sourceinsight4.5BB780 | strcpy(edx, ["Email"])
00516919 | 83C4 08 | add esp,8 |
0051691C | 8D4424 0C | lea eax,dword ptr ss:[esp+C] |
00516920 | 50 | push eax | eax:&"ActId"
00516921 | 68 B0656000 | push sourceinsight4.6065B0 | 6065B0:"Serial"
00516926 | 8D4C24 24 | lea ecx,dword ptr ss:[esp+24] | [esp+24]:"ActId"
0051692A | E8 91DCFFFF | call sourceinsight4.5145C0 | read the ["Serial"] value
0051692F | 85C0 | test eax,eax | eax:&"ActId"
00516931 | 0F84 B1020000 | je sourceinsight4.516BE8 |
00516937 | 8B4C24 0C | mov ecx,dword ptr ss:[esp+C] |
0051693B | 55 | push ebp |
0051693C | 51 | push ecx |
0051693D | 8D6E 04 | lea ebp,dword ptr ds:[esi+4] |
00516940 | 55 | push ebp |
00516941 | E8 3A4E0A00 | call sourceinsight4.5BB780 | strcpy(edx, ["Serial"])
00516946 | 83C4 08 | add esp,8 |
00516949 | 8D5424 10 | lea edx,dword ptr ss:[esp+10] |
0051694D | 52 | push edx |
0051694E | 68 A8656000 | push sourceinsight4.6065A8 | 6065A8:"ActId"
00516953 | 8D4C24 28 | lea ecx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
00516957 | E8 64DCFFFF | call sourceinsight4.5145C0 | read the ["ActId"] value
0051695C | 85C0 | test eax,eax | eax:&"ActId"
0051695E | 0F84 66020000 | je sourceinsight4.516BCA |
00516964 | 8B4424 10 | mov eax,dword ptr ss:[esp+10] |
00516968 | 50 | push eax | eax:&"ActId"
00516969 | 8DBE 3A060000 | lea edi,dword ptr ds:[esi+63A] |
0051696F | 57 | push edi |
00516970 | E8 0B4E0A00 | call sourceinsight4.5BB780 | strcpy(edx, ["ActId"])
00516975 | 68 7F1B0000 | push 1B7F |
0051697A | 6A 32 | push 32 |
0051697C | 6A 04 | push 4 |
0051697E | 68 701A6500 | push sourceinsight4.651A70 |
00516983 | 57 | push edi |
00516984 | E8 E7CBEEFF | call sourceinsight4.403570 | check the ["ActId"] value
00516989 | 33C9 | xor ecx,ecx |
0051698B | 3BC3 | cmp eax,ebx | eax:&"ActId"
0051698D | 0F9FC1 | setg cl |
00516990 | 68 9C656000 | push sourceinsight4.60659C | 60659C:"Deferred"
00516995 | 57 | push edi |
00516996 | 8BD9 | mov ebx,ecx |
00516998 | E8 8DA40B00 | call sourceinsight4.5D0E2A | stricmp(["ActId"], "Deferred")
0051699D | 83C4 24 | add esp,24 |
005169A0 | 85C0 | test eax,eax | eax:&"ActId"
005169A2 | 75 38 | jne sourceinsight4.5169DC |
005169A4 | C706 02000000 | mov dword ptr ds:[esi],2 |
005169AA | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
005169B5 | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
005169B9 | E8 22DBFFFF | call sourceinsight4.5144E0 | free the saved file data
005169BE | B8 C8000000 | mov eax,C8 | returns 0xC8 = pass
005169C3 | 5D | pop ebp |
005169C4 | 5F | pop edi |
005169C5 | 5E | pop esi |
005169C6 | 5B | pop ebx |
005169C7 | 8B8C24 10040000 | mov ecx,dword ptr ss:[esp+410] |
005169CE | 64:890D 00000000 | mov dword ptr fs:[0],ecx |
005169D5 | 81C4 1C040000 | add esp,41C |
005169DB | C3 | ret |
005169DC | 33D2 | xor edx,edx |
005169DE | 85DB | test ebx,ebx |
005169E0 | 0F94C2 | sete dl |
005169E3 | 8D4424 14 | lea eax,dword ptr ss:[esp+14] |
005169E7 | 8D4C24 18 | lea ecx,dword ptr ss:[esp+18] |
005169EB | 52 | push edx |
005169EC | 50 | push eax | eax:&"ActId"
005169ED | 51 | push ecx |
005169EE | 8D5424 28 | lea edx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
005169F2 | 52 | push edx |
005169F3 | 55 | push ebp |
005169F4 | E8 A7E1FFFF | call sourceinsight4.514BA0 | check ["Serial"]
005169F9 | 83C4 14 | add esp,14 |
005169FC | 85C0 | test eax,eax | eax:&"ActId"
005169FE | 74 0C | je sourceinsight4.516A0C |
00516A00 | 8B4424 18 | mov eax,dword ptr ss:[esp+18] |
00516A04 | 3B86 0C060000 | cmp eax,dword ptr ds:[esi+60C] | eax:&"ActId"
00516A0A | 74 1B | je sourceinsight4.516A27 |
00516A0C | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
00516A17 | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516A1B | E8 C0DAFFFF | call sourceinsight4.5144E0 |
00516A20 | B8 EF010000 | mov eax,1EF | eax:&"ActId"
00516A25 | EB 9C | jmp sourceinsight4.5169C3 |
00516A27 | 0FB60D 13956500 | movzx ecx,byte ptr ds:[659513] |
00516A2E | 8B7C24 14 | mov edi,dword ptr ss:[esp+14] |
00516A32 | 3BF9 | cmp edi,ecx |
00516A34 | 0F85 BA000000 | jne sourceinsight4.516AF4 |
00516A3A | 55 | push ebp |
00516A3B | B9 40846600 | mov ecx,sourceinsight4.668440 |
00516A40 | E8 CB6FF4FF | call sourceinsight4.45DA10 |
00516A45 | 85C0 | test eax,eax | eax:&"ActId"
00516A47 | 74 1E | je sourceinsight4.516A67 |
00516A49 | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
00516A54 | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516A58 | E8 83DAFFFF | call sourceinsight4.5144E0 |
00516A5D | B8 CC010000 | mov eax,1CC | eax:&"ActId"
00516A62 | E9 5CFFFFFF | jmp sourceinsight4.5169C3 |
00516A67 | 85DB | test ebx,ebx |
00516A69 | 75 37 | jne sourceinsight4.516AA2 |
00516A6B | 8D5424 10 | lea edx,dword ptr ss:[esp+10] |
00516A6F | 52 | push edx |
00516A70 | 68 94656000 | push sourceinsight4.606594 | 606594:"HWID"
00516A75 | 8D4C24 28 | lea ecx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
00516A79 | C706 01000000 | mov dword ptr ds:[esi],1 |
00516A7F | E8 3CDBFFFF | call sourceinsight4.5145C0 |
00516A84 | 85C0 | test eax,eax | eax:&"ActId"
00516A86 | 0F84 3E010000 | je sourceinsight4.516BCA |
00516A8C | 8B4424 10 | mov eax,dword ptr ss:[esp+10] |
00516A90 | 50 | push eax | eax:&"ActId"
00516A91 | 8D8E 28060000 | lea ecx,dword ptr ds:[esi+628] |
00516A97 | 51 | push ecx |
00516A98 | E8 E34C0A00 | call sourceinsight4.5BB780 |
00516A9D | 83C4 08 | add esp,8 |
00516AA0 | EB 06 | jmp sourceinsight4.516AA8 |
00516AA2 | C706 03000000 | mov dword ptr ds:[esi],3 |
00516AA8 | 8D5424 10 | lea edx,dword ptr ss:[esp+10] |
00516AAC | 52 | push edx |
00516AAD | 68 10AC5D00 | push sourceinsight4.5DAC10 | 5DAC10:"Version"
00516AB2 | 8D4C24 28 | lea ecx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
00516AB6 | E8 05DBFFFF | call sourceinsight4.5145C0 | read the ["Version"] value
00516ABB | 85C0 | test eax,eax | eax:&"ActId"
00516ABD | 0F84 07010000 | je sourceinsight4.516BCA |
00516AC3 | 8B4424 10 | mov eax,dword ptr ss:[esp+10] |
00516AC7 | 8A00 | mov al,byte ptr ds:[eax] | eax:&"ActId"
00516AC9 | 3C 30 | cmp al,30 | 30:'0'
00516ACB | 0F8C F9000000 | jl sourceinsight4.516BCA |
00516AD1 | 3C 39 | cmp al,39 | 39:'9'
00516AD3 | 0F8F F1000000 | jg sourceinsight4.516BCA |
00516AD9 | 0FBEC0 | movsx eax,al | eax:&"ActId"
00516ADC | 83C0 D0 | add eax,FFFFFFD0 | eax:&"ActId"
00516ADF | 8986 04060000 | mov dword ptr ds:[esi+604],eax | eax:&"ActId"
00516AE5 | 0FB60D 13956500 | movzx ecx,byte ptr ds:[659513] |
00516AEC | 3BC1 | cmp eax,ecx | eax:&"ActId"
00516AEE | 75 04 | jne sourceinsight4.516AF4 |
00516AF0 | 3BC7 | cmp eax,edi | eax:&"ActId"
00516AF2 | 74 1E | je sourceinsight4.516B12 |
00516AF4 | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
00516AFF | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516B03 | E8 D8D9FFFF | call sourceinsight4.5144E0 |
00516B08 | B8 EA010000 | mov eax,1EA | eax:&"ActId"
00516B0D | E9 B1FEFFFF | jmp sourceinsight4.5169C3 |
00516B12 | 8D5424 10 | lea edx,dword ptr ss:[esp+10] |
00516B16 | 33DB | xor ebx,ebx |
00516B18 | 52 | push edx |
00516B19 | 68 88656000 | push sourceinsight4.606588 | 606588:"Expiration"
00516B1E | 8D4C24 28 | lea ecx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
00516B22 | 899E 18060000 | mov dword ptr ds:[esi+618],ebx |
00516B28 | 899E 14060000 | mov dword ptr ds:[esi+614],ebx |
00516B2E | 899E 10060000 | mov dword ptr ds:[esi+610],ebx |
00516B34 | E8 87DAFFFF | call sourceinsight4.5145C0 | read the ["Expiration"] value
00516B39 | 85C0 | test eax,eax | eax:&"ActId"
00516B3B | 74 1F | je sourceinsight4.516B5C |
00516B3D | 8B4424 10 | mov eax,dword ptr ss:[esp+10] |
00516B41 | 50 | push eax | eax:&"ActId"
00516B42 | 8D8E 10060000 | lea ecx,dword ptr ds:[esi+610] |
00516B48 | E8 E394F3FF | call sourceinsight4.450030 |
00516B4D | 8D8E 10060000 | lea ecx,dword ptr ds:[esi+610] |
00516B53 | E8 8881F3FF | call sourceinsight4.44ECE0 |
00516B58 | 85C0 | test eax,eax | eax:&"ActId"
00516B5A | 74 50 | je sourceinsight4.516BAC |
00516B5C | 8D4C24 10 | lea ecx,dword ptr ss:[esp+10] |
00516B60 | 51 | push ecx |
00516B61 | 68 D8A65E00 | push sourceinsight4.5EA6D8 | 5EA6D8:"Date"
00516B66 | 8D4C24 28 | lea ecx,dword ptr ss:[esp+28] | [esp+28]:"Serial"
00516B6A | 899E 24060000 | mov dword ptr ds:[esi+624],ebx |
00516B70 | 899E 20060000 | mov dword ptr ds:[esi+620],ebx |
00516B76 | 899E 1C060000 | mov dword ptr ds:[esi+61C],ebx |
00516B7C | E8 3FDAFFFF | call sourceinsight4.5145C0 | read the ["Date"] value
00516B81 | 85C0 | test eax,eax | eax:&"ActId"
00516B83 | 0F84 21FEFFFF | je sourceinsight4.5169AA |
00516B89 | 8B5424 10 | mov edx,dword ptr ss:[esp+10] |
00516B8D | 52 | push edx |
00516B8E | 8D8E 1C060000 | lea ecx,dword ptr ds:[esi+61C] |
00516B94 | E8 9794F3FF | call sourceinsight4.450030 | check the date validity
00516B99 | 8D8E 1C060000 | lea ecx,dword ptr ds:[esi+61C] |
00516B9F | E8 3C81F3FF | call sourceinsight4.44ECE0 |
00516BA4 | 85C0 | test eax,eax | check year/month/day validity
00516BA6 | 0F85 FEFDFFFF | jne sourceinsight4.5169AA |
00516BAC | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
00516BB7 | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516BBB | E8 20D9FFFF | call sourceinsight4.5144E0 |
00516BC0 | B8 E3010000 | mov eax,1E3 | eax:&"ActId"
00516BC5 | E9 F9FDFFFF | jmp sourceinsight4.5169C3 |
00516BCA | C78424 28040000 FFFFFF | mov dword ptr ss:[esp+428],FFFFFFFF |
00516BD5 | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516BD9 | E8 02D9FFFF | call sourceinsight4.5144E0 |
00516BDE | B8 D5010000 | mov eax,1D5 | eax:&"ActId"
00516BE3 | E9 DBFDFFFF | jmp sourceinsight4.5169C3 |
00516BE8 | C78424 24040000 FFFFFF | mov dword ptr ss:[esp+424],FFFFFFFF |
00516BF3 | 8D4C24 1C | lea ecx,dword ptr ss:[esp+1C] |
00516BF7 | E8 E4D8FFFF | call sourceinsight4.5144E0 |
00516BFC | 8B8C24 1C040000 | mov ecx,dword ptr ss:[esp+41C] |
00516C03 | 5F | pop edi |
00516C04 | 5E | pop esi |
00516C05 | B8 D5010000 | mov eax,1D5 | eax:&"ActId"
00516C0A | 5B | pop ebx |
00516C0B | 64:890D 00000000 | mov dword ptr fs:[0],ecx |
00516C12 | 81C4 1C040000 | add esp,41C |
00516C18 | C3 | ret |
3.2 Validating the Signature
Validating the Signature field means: read all characters before the Signature block in si.lic, strip spaces and newlines, run them through 00402FF0() to produce binary signature data, Base64-decode the Value string inside the Signature block into binary, and compare the two. Equal → return 0xC8.
00515F90 | B8 24210000 | mov eax,2124 |
00515F95 | E8 36850A00 | call sourceinsight4.5BE4D0 |
00515F9A | 56 | push esi |
00515F9B | 8BB424 2C210000 | mov esi,dword ptr ss:[esp+212C] |
00515FA2 | 68 A01F0000 | push 1FA0 |
00515FA7 | 8D8424 8C010000 | lea eax,dword ptr ss:[esp+18C] |
00515FAE | 50 | push eax |
00515FAF | 56 | push esi |
00515FB0 | E8 5BE6FFFF | call sourceinsight4.514610 | open the file and read its contents
00515FB5 | 83C4 0C | add esp,C |
00515FB8 | 3D C8000000 | cmp eax,C8 |
00515FBD | 0F85 49010000 | jne sourceinsight4.51610C |
00515FC3 | 8B8C24 30210000 | mov ecx,dword ptr ss:[esp+2130] |
00515FCA | 51 | push ecx | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00515FCB | 8D9424 8C010000 | lea edx,dword ptr ss:[esp+18C] |
00515FD2 | 52 | push edx |
00515FD3 | E8 88F8FFFF | call sourceinsight4.515860 |
00515FD8 | 56 | push esi |
00515FD9 | E8 0257F4FF | call sourceinsight4.45B6E0 | convert the file contents to XML
00515FDE | 83C4 0C | add esp,C |
00515FE1 | 85C0 | test eax,eax |
00515FE3 | 75 0D | jne sourceinsight4.515FF2 |
00515FE5 | B8 CC010000 | mov eax,1CC |
00515FEA | 5E | pop esi |
00515FEB | 81C4 24210000 | add esp,2124 |
00515FF1 | C3 | ret |
00515FF2 | 68 085E6000 | push sourceinsight4.605E08 | 605E08:"Signature"
00515FF7 | 8BC8 | mov ecx,eax | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00515FF9 | E8 722AF4FF | call sourceinsight4.458A70 | check whether the "Signature" field exists
00515FFE | 8BF0 | mov esi,eax |
00516000 | 85F6 | test esi,esi |
00516002 | 74 E1 | je sourceinsight4.515FE5 |
00516004 | 68 889D5E00 | push sourceinsight4.5E9D88 | 5E9D88:"Value"
00516009 | 8BCE | mov ecx,esi | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051600B | E8 4032F4FF | call sourceinsight4.459250 | check whether "Value" exists
00516010 | 85C0 | test eax,eax |
00516012 | 74 D1 | je sourceinsight4.515FE5 |
00516014 | 55 | push ebp |
00516015 | 57 | push edi |
00516016 | 8B78 18 | mov edi,dword ptr ds:[eax+18] |
00516019 | 8B46 20 | mov eax,dword ptr ds:[esi+20] |
0051601C | 8D8C24 90010000 | lea ecx,dword ptr ss:[esp+190] |
00516023 | 51 | push ecx | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00516024 | C68404 94010000 00 | mov byte ptr ss:[esp+eax+194],0 |
0051602C | E8 AFE8F2FF | call sourceinsight4.4448E0 |
00516031 | 8BE8 | mov ebp,eax |
00516033 | 83C4 04 | add esp,4 |
00516036 | 85ED | test ebp,ebp |
00516038 | 75 0F | jne sourceinsight4.516049 |
0051603A | 5F | pop edi |
0051603B | 5D | pop ebp |
0051603C | B8 EC010000 | mov eax,1EC |
00516041 | 5E | pop esi |
00516042 | 81C4 24210000 | add esp,2124 |
00516048 | C3 | ret |
00516049 | 55 | push ebp |
0051604A | 8D9424 94010000 | lea edx,dword ptr ss:[esp+194] |
00516051 | 68 0C606000 | push sourceinsight4.60600C | 60600C:"\n\r\t "
00516056 | 52 | push edx |
00516057 | E8 14EAF2FF | call sourceinsight4.444A70 | strip whitespace and newlines from the file data
0051605C | 83C4 0C | add esp,C |
0051605F | 8D4424 10 | lea eax,dword ptr ss:[esp+10] |
00516063 | 50 | push eax |
00516064 | 68 80000000 | push 80 |
00516069 | 68 B0070000 | push 7B0 |
0051606E | 55 | push ebp |
0051606F | E8 6C4E0A00 | call sourceinsight4.5BAEE0 | compute the length
00516074 | 83C4 04 | add esp,4 |
00516077 | 40 | inc eax |
00516078 | 50 | push eax |
00516079 | 55 | push ebp |
0051607A | E8 91D1EEFF | call sourceinsight4.403210 | 1.
0051607F | 8D4C24 20 | lea ecx,dword ptr ss:[esp+20] |
00516083 | 51 | push ecx | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00516084 | 8D9424 A8000000 | lea edx,dword ptr ss:[esp+A8] |
0051608B | 52 | push edx |
0051608C | 57 | push edi |
0051608D | E8 6ECEEEFF | call sourceinsight4.402F00 | 2. Base64-decode the Value string in the Signature block
00516092 | 83C4 20 | add esp,20 |
00516095 | 817C24 0C 80000000 | cmp dword ptr ss:[esp+C],80 |
0051609D | 75 50 | jne sourceinsight4.5160EF |
0051609F | B8 80000000 | mov eax,80 |
005160A4 | 8D4C24 10 | lea ecx,dword ptr ss:[esp+10] |
005160A8 | 8DB424 90000000 | lea esi,dword ptr ss:[esp+90] | esi:EntryPoint
005160AF | 90 | nop |
005160B0 | 8B16 | mov edx,dword ptr ds:[esi] | edx:EntryPoint, esi:EntryPoint
005160B2 | 3B11 | cmp edx,dword ptr ds:[ecx] | edx:EntryPoint, ecx:EntryPoint
005160B4 | 75 39 | jne sourceinsight4_original.5160EF |
005160B6 | 83E8 04 | sub eax,4 |
005160B9 | 83C1 04 | add ecx,4 | ecx:EntryPoint
005160BC | 83C6 04 | add esi,4 | esi:EntryPoint
005160BF | 83F8 04 | cmp eax,4 |
005160C2 | 73 EC | jae sourceinsight4.5160B0 |
005160C4 | 85C0 | test eax,eax |
005160C6 | 74 20 | je sourceinsight4.5160E8 |
005160C8 | 8A11 | mov dl,byte ptr ds:[ecx] | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
005160CA | 3A16 | cmp dl,byte ptr ds:[esi] |
005160CC | 75 21 | jne sourceinsight4.5160EF |
005160CE | 83F8 01 | cmp eax,1 |
005160D1 | 76 15 | jbe sourceinsight4.5160E8 |
005160D3 | 8A51 01 | mov dl,byte ptr ds:[ecx+1] | ecx+1:":\\ProgramData\\Source Insight\\4.0\\si4.lic"
005160D6 | 3A56 01 | cmp dl,byte ptr ds:[esi+1] |
005160D9 | 75 14 | jne sourceinsight4.5160EF |
005160DB | 83F8 02 | cmp eax,2 |
005160DE | 76 08 | jbe sourceinsight4.5160E8 |
005160E0 | 8A41 02 | mov al,byte ptr ds:[ecx+2] | ecx+2:"\\ProgramData\\Source Insight\\4.0\\si4.lic"
005160E3 | 3A46 02 | cmp al,byte ptr ds:[esi+2] |
005160E6 | 75 07 | jne sourceinsight4.5160EF |
005160E8 | BE 01000000 | mov esi,1 |
005160ED | EB 02 | jmp sourceinsight4.5160F1 |
005160EF | 33F6 | xor esi,esi |
005160F1 | 55 | push ebp |
005160F2 | E8 39EDF0FF | call sourceinsight4.424E30 |
005160F7 | 83C4 04 | add esp,4 |
005160FA | 8BC6 | mov eax,esi |
005160FC | F7D8 | neg eax |
005160FE | 1BC0 | sbb eax,eax |
00516100 | 25 FAFEFFFF | and eax,FFFFFEFA |
00516105 | 5F | pop edi |
00516106 | 05 CE010000 | add eax,1CE |
0051610B | 5D | pop ebp |
0051610C | 5E | pop esi |
0051610D | 81C4 24210000 | add esp,2124 |
00516113 | C3 | ret |
The function that produces the binary signature data:
00402FF0 | 53 | push ebx |
00402FF1 | 33DB | xor ebx,ebx |
00402FF3 | 395C24 14 | cmp dword ptr ss:[esp+14],ebx |
00402FF7 | 7E 5C | jle sourceinsight4.403055 |
00402FF9 | 8B5424 1C | mov edx,dword ptr ss:[esp+1C] |
00402FFD | 55 | push ebp |
00402FFE | 56 | push esi |
00402FFF | 8B7424 14 | mov esi,dword ptr ss:[esp+14] |
00403003 | 57 | push edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00403004 | 8B7C24 14 | mov edi,dword ptr ss:[esp+14] |
00403008 | EB 06 | jmp sourceinsight4.403010 |
0040300A | 8D9B 00000000 | lea ebx,dword ptr ds:[ebx] |
00403010 | 0FB607 | movzx eax,byte ptr ds:[edi] | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00403013 | 03C3 | add eax,ebx |
00403015 | 034424 1C | add eax,dword ptr ss:[esp+1C] |
00403019 | 25 FF000080 | and eax,800000FF |
0040301E | 79 07 | jns sourceinsight4.403027 |
00403020 | 48 | dec eax |
00403021 | 0D 00FFFFFF | or eax,FFFFFF00 |
00403026 | 40 | inc eax |
00403027 | 8A0C10 | mov cl,byte ptr ds:[eax+edx] |
0040302A | B8 01000000 | mov eax,1 |
0040302F | 3BF0 | cmp esi,eax |
00403031 | 7E 11 | jle sourceinsight4.403044 |
00403033 | 0FB62C38 | movzx ebp,byte ptr ds:[eax+edi] |
00403037 | 0FB6C9 | movzx ecx,cl | ecx:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0040303A | 33E9 | xor ebp,ecx |
0040303C | 8A0C2A | mov cl,byte ptr ds:[edx+ebp] |
0040303F | 40 | inc eax |
00403040 | 3BC6 | cmp eax,esi |
00403042 | 7C EF | jl sourceinsight4.403033 |
00403044 | 8B4424 24 | mov eax,dword ptr ss:[esp+24] |
00403048 | 880C03 | mov byte ptr ds:[ebx+eax],cl |
0040304B | 43 | inc ebx |
0040304C | 3B5C24 20 | cmp ebx,dword ptr ss:[esp+20] |
00403050 | 7C BE | jl sourceinsight4.403010 |
00403052 | 5F | pop edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00403053 | 5E | pop esi |
00403054 | 5D | pop ebp |
00403055 | 5B | pop ebx |
00403056 | C3 | ret |
3.3 Checking ActId
The first four characters of the ActId field are compared against each ActId in the ActId table — only the first 4 characters are compared.
int __cdecl sub_403570(char *pData, int a2, size_t Size_4, int n_x32, int n_1B7F)
{
int v5; // esi
void *ppTable; // ebp
int v7; // edi
v5 = 0;
ppTable = sub_403240(a2, Size_4, n_x32, n_1B7F);// returns the table containing many ActIds
if ( n_x32 <= 0 )
{
LABEL_4:
sub_425090(ppTable);
ReleaseBlock(ppTable);
return 0;
}
else
{
while ( 1 )
{
v7 = CheckActIdHeaderFourCharacter(*(ppTable + v5), Size_4, pData);
if ( v7 == Size_4 ) // only compare the first 4 chars
break;
if ( ++v5 >= n_x32 )
goto LABEL_4;
}
sub_425090(ppTable);
ReleaseBlock(ppTable);
return v7;
}
}
The ActId table:
"673A44D35B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"44D35B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"5B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"08E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"16F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"55E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"00D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"4B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"18E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"3E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"87A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"68E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"13DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"61B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"76B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"3BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"49F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"4F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"52A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"03A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"74E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"1EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"83A6F5090AD61F3F365D1C67DA22A478FA17",
"F5090AD61F3F365D1C67DA22A478FA17",
"0AD61F3F365D1C67DA22A478FA17",
"1F3F365D1C67DA22A478FA17",
"365D1C67DA22A478FA17",
"1C67DA22A478FA17",
"DA22A478FA17",
"A478FA17"
The remaining characters of ActId are produced by concatenating the C: volume ID, the process token SID, and the computer name, then running that through 00402FF0() to produce a 4-byte checksum, then converting it to a decimal string.
00517920 | 81EC 00010000 | sub esp,100 |
00517926 | 56 | push esi |
00517927 | 57 | push edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00517928 | 68 7F1B0000 | push 1B7F |
0051792D | 6A 32 | push 32 |
0051792F | 8BF1 | mov esi,ecx |
00517931 | 6A 04 | push 4 |
00517933 | 8D86 3A060000 | lea eax,dword ptr ds:[esi+63A] | eax:"673A2434362875", esi+63A:"673A2434362875"
00517939 | 68 701A6500 | push sourceinsight4.651A70 |
0051793E | 50 | push eax | eax:"673A2434362875"
0051793F | E8 2CBCEEFF | call sourceinsight4.403570 | 1. check the first 4 chars of ActId
00517944 | 8BF8 | mov edi,eax | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic", eax:"673A2434362875"
00517946 | 83C4 14 | add esp,14 |
00517949 | 85FF | test edi,edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051794B | 75 0B | jne sourceinsight4.517958 |
0051794D | 5F | pop edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
0051794E | 33C0 | xor eax,eax | eax:"673A2434362875"
00517950 | 5E | pop esi |
00517951 | 81C4 00010000 | add esp,100 |
00517957 | C3 | ret |
00517958 | 8D4C24 08 | lea ecx,dword ptr ss:[esp+8] |
0051795C | 6A 00 | push 0 |
0051795E | 51 | push ecx |
0051795F | E8 7CF5FFFF | call sourceinsight4.516EE0 | 2. generate a checksum string from the C: volume ID, process token SID, and computer name
00517964 | 83C4 08 | add esp,8 |
00517967 | 85C0 | test eax,eax | eax:"673A2434362875"
00517969 | 74 E2 | je sourceinsight4.51794D |
0051796B | 8D5424 08 | lea edx,dword ptr ss:[esp+8] |
0051796F | 52 | push edx |
00517970 | 8D8437 3A060000 | lea eax,dword ptr ds:[edi+esi+63A] | eax:"673A2434362875"
00517977 | 50 | push eax | eax:"673A2434362875"
00517978 | E8 83400A00 | call sourceinsight4.5BBA00 | compare the rest of ActId with the checksum string
0051797D | 83C4 08 | add esp,8 |
00517980 | F7D8 | neg eax | eax:"673A2434362875"
00517982 | 1BC0 | sbb eax,eax | eax:"673A2434362875"
00517984 | 5F | pop edi | edi:"C:\\ProgramData\\Source Insight\\4.0\\si4.lic"
00517985 | 40 | inc eax | eax:"673A2434362875"
00517986 | 5E | pop esi |
00517987 | 81C4 00010000 | add esp,100 |
0051798D | C3 | ret |
int __cdecl sub_516EE0(char *Buffer, int a2)
{
int v3; // [esp+0h] [ebp-314h] BYREF
char v4[784]; // [esp+4h] [ebp-310h] BYREF
sub_515050(v4);
if ( sub_515220(v4) ) // get the disk ID, token, computer name
{
sub_514810(v4, 4, &v3, a2); // generate the checksum from disk ID + token + computer name
sprintf(Buffer, "%u", v3); // convert the checksum to a decimal string
return 1;
}
else
{
*Buffer = 0;
return 0;
}
}
Getting the C: volume ID:
int __cdecl sub_44F2A0(void *a1)
{
unsigned int v1; // eax
char *v2; // eax
const WCHAR *v3; // eax
size_t v4; // eax
signed int v5; // eax
size_t v6; // esi
CHAR Str[256]; // [esp+4h] [ebp-51Ch] BYREF
char Buf2[11]; // [esp+104h] [ebp-41Ch] BYREF
char Src[245]; // [esp+10Fh] [ebp-411h] BYREF
char v11[272]; // [esp+204h] [ebp-31Ch] BYREF
WCHAR szVolumeName[256]; // [esp+314h] [ebp-20Ch] BYREF
int v13; // [esp+51Ch] [ebp-4h]
*(_BYTE *)a1 = 0;
v1 = sub_4573D0("SystemDrive", Str, 0x100u);
if ( v1 < 0x100 && v1 )
{
Str[v1] = 0;
if ( Str[0] )
goto LABEL_5;
}
else
{
Str[0] = 0;
}
strcpy(Str, "C:\\");
LABEL_5:
v2 = &Str[strlen(Str)];
if ( v2 != Str )
--v2;
if ( *v2 != 92 )
strcat(Str, "\\");
sub_4534A0(Str);
v13 = 0;
v3 = (const WCHAR *)sub_453B10(v11);
if ( GetVolumeNameForVolumeMountPointW(v3, szVolumeName, 0xFFu)
&& (sub_447330(szVolumeName, Buf2, 255), strlen(Buf2) >= 0x30)
&& (v4 = strlen("\\\\?\\Volume{"), !memcmp("\\\\?\\Volume{", Buf2, v4)) )
{
v5 = strlen(Src);
v6 = 36;
if ( v5 <= 36 )
v6 = v5;
memcpy(a1, Src, v6);
*((_BYTE *)a1 + v6) = 0;
v13 = -1;
sub_453360(v11);
return 1;
}
else
{
v13 = -1;
sub_453360(v11);
return 0;
}
}
Getting the process token SID:
int __cdecl sub_44F490(HANDLE TokenHandle)
{
CHAR *v1; // ebx
HANDLE CurrentProcess; // eax
PSID *v4; // esi
DWORD ReturnLength; // [esp+4h] [ebp-8h] BYREF
LPWSTR StringSid; // [esp+8h] [ebp-4h] BYREF
v1 = (CHAR *)TokenHandle;
*(_BYTE *)TokenHandle = 0;
CurrentProcess = GetCurrentProcess();
if ( !CurrentProcess )
return 0;
TokenHandle = 0;
if ( !OpenProcessToken(CurrentProcess, 8u, &TokenHandle) )
return 0;
if ( (GetTokenInformation(TokenHandle, TokenUser, 0, 0, &ReturnLength) || GetLastError() == 122)
&& (v4 = (PSID *)sub_425300(ReturnLength, 1),
GetTokenInformation(TokenHandle, TokenUser, v4, ReturnLength, &ReturnLength))
&& ConvertSidToStringSidW(*v4, &StringSid) )
{
sub_447330(StringSid, v1, 255);
LocalFree(StringSid);
sub_424E30(v4);
CloseHandle(TokenHandle);
return 1;
}
else
{
CloseHandle(TokenHandle);
return 0;
}
}
Getting the computer name:
BOOL __cdecl sub_44D730(LPSTR lpMultiByteStr)
{
BOOL result; // eax
DWORD nSize; // [esp+4h] [ebp-204h] BYREF
WCHAR Buffer[256]; // [esp+8h] [ebp-200h] BYREF
*lpMultiByteStr = 0;
nSize = 256;
result = GetComputerNameW(Buffer, &nSize);
if ( result )
{
Buffer[nSize] = 0;
sub_447330(Buffer, lpMultiByteStr, 255);
return 1;
}
return result;
}
Concatenating the volume ID, token, and computer name, then producing the checksum:
int __cdecl sub_514810(const char *a1)
{
int v1; // eax
char Str[512]; // [esp+0h] [ebp-200h] BYREF
sprintf(Str, "%s%s%s", a1, a1 + 256, a1 + 512);// concatenate the C: volume ID, token, computer name
v1 = strlen(Str);
return sub_403210((int)Str, v1); // generate the checksum
}
int __cdecl sub_403210(int a1, int a2)
{
int v3; // [esp+Ch] [ebp+Ch]
int v4; // [esp+10h] [ebp+10h]
int v5; // [esp+14h] [ebp+14h]
return sub_402FF0(a1, a2, v3, v4, v5, &byte_5D6B98);
}
4. The keygen
Now that we know how si.lic is produced, we can write a keygen that emits a valid si.lic for offline registration:
- Implement the serial-validation algorithm as a serial generator; fill the
Serialfield. - Randomly generate the
LicensedUser,Organization, andEmailfields. - Take the current date for the
Datefield. - Read all characters before the
<Signaturestring, run them through00402FF0()to produce binary signature data, Base64-encode it, and write it into theValuefield of theSignatureblock.
The implementation:
#include "pch.h"
#include "CSourceInsightTool.h"
#include "Base64.h"
#include "Sddl.h"
unsigned char byte_6060F0[] =
{
0x4B, 0x56, 0x39, 0x36, 0x47, 0x4D, 0x4A, 0x59, 0x48, 0x37,
0x51, 0x46, 0x35, 0x54, 0x43, 0x57, 0x34, 0x55, 0x33, 0x58,
0x5A, 0x50, 0x52, 0x53, 0x44, 0x4E, 0x00
};
unsigned char unk_606210[] =
{
0x23, 0xDD, 0x78, 0xB5, 0x33, 0x6F, 0xD4, 0xF9, 0xA6, 0xE8,
0xCC, 0x7C, 0x9F, 0xB3, 0x22, 0xDA, 0x32, 0xDF, 0x71, 0xB7,
0x61, 0x3D, 0x6B, 0x57, 0xD7, 0xA1, 0x34, 0x38, 0xF2, 0xE1,
0xF3, 0xB8, 0x1A, 0x80, 0xF5, 0xFE, 0x91, 0x01, 0x3C, 0x73,
0x93, 0x48, 0xA0, 0xE0, 0x94, 0xAA, 0x39, 0x8F, 0x58, 0xE2,
0x31, 0x0B, 0xBB, 0xCE, 0x4C, 0xD2, 0x56, 0xC2, 0x5E, 0x27,
0xB6, 0xFB, 0x65, 0xAE, 0x55, 0x60, 0xBD, 0x10, 0x86, 0xF7,
0xC1, 0x88, 0x12, 0xED, 0x67, 0xC4, 0x74, 0x30, 0x1B, 0xBC,
0x9A, 0xB0, 0xEF, 0x36, 0xC5, 0x72, 0x5B, 0x7E, 0x54, 0x2C,
0x0F, 0xF6, 0xA9, 0x85, 0x2A, 0xB1, 0x37, 0xF1, 0x2F, 0x4E,
0xE7, 0x6A, 0x75, 0xA8, 0x26, 0xEB, 0x3F, 0x6C, 0x69, 0x20,
0x87, 0x62, 0x8D, 0x68, 0xA5, 0xFA, 0x3A, 0x04, 0x21, 0x1F,
0xAC, 0x05, 0xA4, 0x76, 0x11, 0x70, 0x9E, 0x46, 0x24, 0x5D,
0xC6, 0xE4, 0x95, 0x82, 0x1C, 0xBA, 0x59, 0x09, 0xD9, 0x44,
0x98, 0x92, 0x07, 0xAF, 0xA7, 0x41, 0x96, 0x90, 0xB4, 0x42,
0x63, 0x99, 0xD0, 0x4D, 0x97, 0xBE, 0x40, 0xCF, 0x84, 0xE5,
0x1D, 0x5A, 0x0C, 0x7F, 0xC7, 0xEA, 0xEE, 0xEC, 0x00, 0xD5,
0x49, 0x2D, 0x51, 0xAD, 0xB9, 0x89, 0x77, 0x52, 0x3E, 0x8C,
0xE6, 0xFF, 0x15, 0xDE, 0x6D, 0x14, 0xA2, 0xCD, 0xA3, 0xD6,
0x17, 0x81, 0xC8, 0x45, 0x4B, 0x35, 0x0A, 0x0D, 0xFC, 0x9D,
0x16, 0x3B, 0xD3, 0x7D, 0xD1, 0xF4, 0xFD, 0xCA, 0x25, 0x06,
0x6E, 0xF8, 0x5F, 0xBF, 0x8A, 0x7B, 0x50, 0xD8, 0x79, 0x9C,
0xAB, 0x43, 0x53, 0xCB, 0x8E, 0x4F, 0xE3, 0xC9, 0x8B, 0xDC,
0x5C, 0xC0, 0x1E, 0x9B, 0x18, 0x02, 0x47, 0x03, 0x2B, 0x0E,
0x66, 0x4A, 0xB2, 0xF0, 0xE9, 0x19, 0x29, 0x7A, 0xC3, 0x08,
0x83, 0xDB, 0x64, 0x13, 0x2E, 0x28
};
int *__cdecl sub_5153C0(BYTE *pSerial, unsigned int nLength, BYTE *pData, int *pResult)
{
unsigned int i; // esi
BYTE v5; // cl
unsigned int j; // eax
int *result; // eax
for (i = 0; i < 4; *((BYTE *)pResult + i - 1) = byte_6060F0[v5 % 26])
{
v5 = pData[(unsigned __int8)(i + *pSerial)];
for (j = 1; j < nLength; ++j)
v5 = pData[v5 ^ (char)pSerial[j]];
result = pResult;
++i;
}
return result;
}
void CSourceInsightTool::GenerateSerial(char szSerial[20])
{
int nResult = 0;
sub_5153C0((BYTE *)szSerial, 15, unk_606210, &nResult);
*(UINT32 *)&szSerial[15] = nResult;
szSerial[19] = 0;
}
const char *gActIdTable[49] = {
"673A44D35B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"44D35B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"5B3608E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"08E5C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"C603D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D775C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"C76216F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"16F555E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"55E000D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"00D04B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"4B6718E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"18E33E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"3E93F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F35887A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"87A8A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"A360D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D2F468E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"68E313DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"13DC7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"7B3E047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"047E08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"08F10A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0A51B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"B75561B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"61B5L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"L55576B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"76B63BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"3BF2D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"D7750F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0F09557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"557AF661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F661F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"F14849F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"49F94F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"4F2652A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"52A903A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"03A10E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"0E9074E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"74E61EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"1EA4FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"FE7E83A6F5090AD61F3F365D1C67DA22A478FA17",
"83A6F5090AD61F3F365D1C67DA22A478FA17",
"F5090AD61F3F365D1C67DA22A478FA17",
"0AD61F3F365D1C67DA22A478FA17",
"1F3F365D1C67DA22A478FA17",
"365D1C67DA22A478FA17",
"1C67DA22A478FA17",
"DA22A478FA17",
"A478FA17"
};
unsigned char unk_5D6B98[] =
{
0x32, 0xDF, 0x71, 0xB7, 0x61, 0x3D, 0x6B, 0x57, 0xD7, 0xA1,
0x34, 0x38, 0xF2, 0xE1, 0xF3, 0xB8, 0x23, 0xDD, 0x78, 0xB5,
0x33, 0x6F, 0xD4, 0xF9, 0xA6, 0xE8, 0xCC, 0x7C, 0x9F, 0xB3,
0x22, 0xDA, 0x37, 0xF1, 0x2F, 0x4E, 0xE7, 0x6A, 0x75, 0xA8,
0x26, 0xEB, 0x3F, 0x6C, 0x69, 0x20, 0x87, 0x62, 0xA7, 0x41,
0x96, 0x90, 0xB4, 0x42, 0x63, 0x99, 0xD0, 0x4D, 0x97, 0xBE,
0x40, 0xCF, 0x84, 0xE5, 0x1D, 0x5A, 0x0C, 0x7F, 0xC7, 0xEA,
0xEE, 0xEC, 0x00, 0xD5, 0x49, 0x2D, 0x51, 0xAD, 0xB9, 0x89,
0x1A, 0x80, 0xF5, 0xFE, 0x91, 0x01, 0x3C, 0x73, 0x93, 0x48,
0xA0, 0xE0, 0x94, 0xAA, 0x39, 0x8F, 0x58, 0xE2, 0x31, 0x0B,
0xBB, 0xCE, 0x4C, 0xD2, 0x56, 0xC2, 0x5E, 0x27, 0xB6, 0xFB,
0x65, 0xAE, 0x9A, 0xB0, 0xEF, 0x36, 0xC5, 0x72, 0x5B, 0x7E,
0x54, 0x2C, 0x0F, 0xF6, 0xA9, 0x85, 0x2A, 0xB1, 0x55, 0x60,
0xBD, 0x10, 0x86, 0xF7, 0xC1, 0x88, 0x12, 0xED, 0x67, 0xC4,
0x74, 0x30, 0x1B, 0xBC, 0x77, 0x52, 0x3E, 0x8C, 0xE6, 0xFF,
0x15, 0xDE, 0x6D, 0x14, 0xA2, 0xCD, 0xA3, 0xD6, 0x17, 0x81,
0x8D, 0x68, 0xA5, 0xFA, 0x3A, 0x04, 0x21, 0x1F, 0xAC, 0x05,
0xA4, 0x76, 0x11, 0x70, 0x9E, 0x46, 0x24, 0x5D, 0xC6, 0xE4,
0x95, 0x82, 0x1C, 0xBA, 0x59, 0x09, 0xD9, 0x44, 0x98, 0x92,
0x07, 0xAF, 0xC8, 0x45, 0x4B, 0x35, 0x0A, 0x0D, 0xFC, 0x9D,
0x16, 0x3B, 0xD3, 0x7D, 0xD1, 0xF4, 0xFD, 0xCA, 0x8E, 0x4F,
0xE3, 0xC9, 0x8B, 0xDC, 0x5C, 0xC0, 0x1E, 0x9B, 0x18, 0x02,
0x47, 0x03, 0x2B, 0x0E, 0x25, 0x06, 0x6E, 0xF8, 0x5F, 0xBF,
0x8A, 0x7B, 0x50, 0xD8, 0x79, 0x9C, 0xAB, 0x43, 0x53, 0xCB,
0x66, 0x4A, 0xB2, 0xF0, 0xE9, 0x19, 0x29, 0x7A, 0xC3, 0x08,
0x83, 0xDB, 0x64, 0x13, 0x2E, 0x28
};
void __declspec(naked) __cdecl sub_402FF0_ASM(unsigned __int8 *Info, int InfoLen, int a3, int Size, unsigned __int8 *buff, unsigned __int8 **a6)
{
__asm {
push ebx
xor ebx, ebx
cmp[esp + 0x14], ebx
jle short loc_403055
mov edx, [esp + 1Ch]
push ebp
push esi
mov esi, [esp + 14h]
push edi
mov edi, [esp + 14h]
jmp short loc_403010
loc_403010 :
movzx eax, byte ptr[edi]
add eax, ebx
add eax, [esp + 1Ch]
and eax, 800000FFh
jns short loc_403027
dec eax
or eax, 0FFFFFF00h
inc eax
loc_403027 :
mov cl, [eax + edx]
mov eax, 1
cmp esi, eax
jle short loc_403044
loc_403033 :
movzx ebp, byte ptr[eax + edi]
movzx ecx, cl
xor ebp, ecx
mov cl, [edx + ebp]
inc eax
cmp eax, esi
jl short loc_403033
loc_403044 :
mov eax, [esp + 24h]
mov [ebx + eax], cl
inc ebx
cmp ebx, [esp + 20h]
jl short loc_403010
pop edi
pop esi
pop ebp
loc_403055 :
pop ebx
retn
}
}
bool CSourceInsightTool::GenerateActId(char szActId[16])
{
bool bIsFail = FALSE;
int nActIdIndex = 0;
srand((unsigned int)time(NULL));
nActIdIndex = rand() / sizeof(gActIdTable);
//nActIdIndex = 0;
for (int i = 0; i < 4; ++i)
{
szActId[i] = gActIdTable[nActIdIndex][i];
}
// get the disk ID
char szVolumeMountPoint[0xFF] = "C:\\";
char szVolumeName[0xFF] = { 0 };
char szVolumeId[0xFF] = { 0 };
char *pVolumeIdEnd = NULL;
if (!GetVolumeNameForVolumeMountPoint(szVolumeMountPoint, szVolumeName, sizeof(szVolumeName)))
{
return false;
}
sscanf_s(szVolumeName, "\\\\?\\Volume{%s}\\", szVolumeId, _countof(szVolumeId));
pVolumeIdEnd = strchr(szVolumeId, '}');
if (pVolumeIdEnd)
{
*pVolumeIdEnd = 0;
}
// get the token
HWND hWindow = NULL;
DWORD dwProcessId = 0;
HANDLE hProcess = NULL;
HANDLE hToken = NULL;
DWORD dwReturnLength = 0;
PVOID TokenInformation = NULL;
DWORD TokenInformationLength = 0;
LPTSTR StringSid = NULL;
do
{
//hWindow = FindWindowA("si4_Frame", "(No Project) - Source Insight 4.0");
hWindow = FindWindowA("si4_Frame", NULL);
if (!hWindow)
{
bIsFail = true;
break;
}
GetWindowThreadProcessId(hWindow, &dwProcessId);
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (!hProcess)
{
bIsFail = true;
break;
}
OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
if (!hToken)
{
return false;
}
if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwReturnLength))
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
return false;
}
}
TokenInformationLength = dwReturnLength;
TokenInformation = calloc(TokenInformationLength, 1);
if (!GetTokenInformation(hToken, TokenUser, TokenInformation, TokenInformationLength, &dwReturnLength))
{
return false;
}
ConvertSidToStringSid(*(PSID *)TokenInformation, &StringSid);
} while (false);
if (!TokenInformation)
{
free(TokenInformation);
TokenInformation = NULL;
}
if (hToken)
{
CloseHandle(hToken);
hToken = NULL;
}
if (hProcess)
{
CloseHandle(hProcess);
hProcess = NULL;
}
//if (hWindow)
//{
// CloseHandle(hWindow);
// hWindow = NULL;
//}
if (bIsFail)
{
return !bIsFail;
}
// get the computer name
char szComputerName[256] = { 0 };
DWORD dwSize = sizeof(szComputerName);
if (!GetComputerName(szComputerName, &dwSize))
{
return false;
}
// generate the checksum
int nLength = 0;
char *pBuffer = NULL;
UINT8 result[4] = { 0 };
char szResult[12] = { 0 };
do
{
nLength = strlen(szVolumeId) + strlen(StringSid) + strlen(szComputerName) + sizeof('\0');
pBuffer = (char *)calloc(nLength, 1);
if (!pBuffer)
{
bIsFail = true;
break;
}
sprintf_s(pBuffer, nLength, "%s%s%s", szVolumeId, StringSid, szComputerName);
sub_402FF0_ASM((unsigned char *)pBuffer, strlen(pBuffer), 0x7A9, sizeof(result), result, (unsigned char **)&unk_5D6B98);
sprintf_s(szResult, sizeof(szResult), "%u", *(PDWORD)result);
strcat_s(szActId, 16, szResult);
} while (false);
if (pBuffer)
{
free(pBuffer);
pBuffer = NULL;
}
return !bIsFail;
}
bool CSourceInsightTool::GenerateSignatureFile(const char *sFilePath,
const char *sActId,
const char *sSerial,
const char *sLicensedUser,
const char *sOrganization,
const char *sEmail,
const char *sDate
)
{
//char sRegisterInformation[] = "<!--SourceInsight4.xLicenseFileDONOTEDITTHISFILE.Doingsowillrenderitunusable.Thislicensewascreatedfor:userMicrosoftuser@user.com--><SourceInsightLicense><LicensePropertiesActId=\"673A2434362875\"Serial=\"S4SG-ARCD-EFGH-36V6\"LicensedUser=\"user\"Organization=\"Microsoft\"Email=\"user@user.com\"Type=\"Standard\"Version=\"4\"MinorVersion=\"0\"Date=\"2023-04-06\"/>\x00";
char sRegisterInformationFormat[] = "<!--SourceInsight4.xLicenseFileDONOTEDITTHISFILE.Doingsowillrenderitunusable.Thislicensewascreatedfor:%s%s%s--><SourceInsightLicense><LicensePropertiesActId=\"%s\"Serial=\"%s\"LicensedUser=\"%s\"Organization=\"%s\"Email=\"%s\"Type=\"Standard\"Version=\"4\"MinorVersion=\"0\"Date=\"%s\"/>";
char szRegisterInforamtion[512] = { 0 };
unsigned char szBinarySignature[0x80] = { 0 };
int nSignatureLength = 0;
char szSignature[0xFF] = { 0 };
sprintf_s(szRegisterInforamtion, sizeof(szRegisterInforamtion), sRegisterInformationFormat,
sLicensedUser,
sOrganization,
sEmail,
sActId,
sSerial,
sLicensedUser,
sOrganization,
sEmail,
sDate
);
sub_402FF0_ASM((unsigned char *)szRegisterInforamtion,
strlen(szRegisterInforamtion) + 1,
0x7B0,
sizeof(szBinarySignature),
szBinarySignature,
(unsigned char **)&unk_5D6B98
);
nSignatureLength = ::base64_encode(szBinarySignature, sizeof(szBinarySignature), szSignature);
// write the file
const char* sSignatureFileFormat = "<!--\r\n\tSource Insight 4.x License File\r\n\r\n\tDO NOT EDIT THIS FILE. Doing so will render it unusable.\r\n\r\n\tThis license was created for:\r\n\r\n\t\t%s\r\n\t\t%s\r\n\t\t%s\r\n\r\n-->\r\n<SourceInsightLicense>\r\n\t<LicenseProperties\r\n\t\tActId=\"%s\"\r\n\t\tSerial=\"%s\"\r\n\t\tLicensedUser=\"%s\"\r\n\t\tOrganization=\"%s\"\r\n\t\tEmail=\"%s\"\r\n\t\tType=\"Standard\"\r\n\t\tVersion=\"4\"\r\n\t\tMinorVersion=\"0\"\r\n\t\tDate=\"%s\"\r\n\t/>\r\n\t<Signature\r\n\t\tValue=\"%s\"\r\n\t/>\r\n</SourceInsightLicense>\r\n";
HANDLE hFile = NULL;
char szBuffer[1024] = { 0 };
DWORD dwNumberOfBytesWritten = 0;
sprintf_s(szBuffer, sizeof(szBuffer), sSignatureFileFormat,
sLicensedUser,
sOrganization,
sEmail,
sActId,
sSerial,
sLicensedUser,
sOrganization,
sEmail,
sDate,
szSignature
);
hFile = CreateFileA(sFilePath,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
dwNumberOfBytesWritten = strlen(szBuffer);
WriteFile(hFile, szBuffer, dwNumberOfBytesWritten, &dwNumberOfBytesWritten, NULL);
if (hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
return true;
}
5. Verification
Registration passes:

The generated si.lic:
<!--
Source Insight 4.x License File
DO NOT EDIT THIS FILE. Doing so will render it unusable.
This license was created for:
YGF4XNO
KAX9H5L
QG783WA7@gmail.com
-->
<SourceInsightLicense>
<LicenseProperties
ActId="047E1691621634"
Serial="S4SG-WRBO-LGQC-VQTF"
LicensedUser="YGF4XNO"
Organization="KAX9H5L"
Email="QG783WA7@gmail.com"
Type="Standard"
Version="4"
MinorVersion="0"
Date="2023-06-13"
/>
<Signature
Value="t+YYiaGMUOtoTqC7GfnD6PY/GrW0c+PdH26TEsqqT6TLC6iYpwRFAUD9Db3B6az6qx45JhXhriFl5GwkWTTI/8SPMs1t5xtNM4v83D7tn+D42HuDJerClkIsnsCXVDhEN7EKPI5nB9G42VGbtrNBVVyCS32I35IvBeKwOytmWEY="
/>
</SourceInsightLicense>
The reference code and tool are available on the author’s Gitee repo (SourceInsight4 · Boaster/Crack).
Colin Xiao — I take on contract reverse-engineering work, and writeups like this are how I show what I can do. If you need help with anything in this space — including but not limited to the areas I cover above — I’m available. No project is too big or too small — if it’s reverse engineering and I can do it, I’ll take it. DM me on X (@colinxiao_lab) or Telegram (@ColinXiao666).
Get in touch