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.

Disabling ASLR

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

Spy++ on GetWindowsTextW

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:

  1. Check each field in the LicenseProperties block.
  2. Validate the Signature.
  3. Check the ActId field in the LicenseProperties block.

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:

  1. Implement the serial-validation algorithm as a serial generator; fill the Serial field.
  2. Randomly generate the LicensedUser, Organization, and Email fields.
  3. Take the current date for the Date field.
  4. Read all characters before the <Signature string, run them through 00402FF0() to produce binary signature data, Base64-encode it, and write it into the Value field of the Signature block.

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:

Registration passed

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