<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml page="/?x=&amp;n=&amp;t=keygen"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <tag value="keygen"/>
  <tag value="reverse"/>
  <title>anonymous keygen</title>
  <date>20 Feb 2010</date>
  <p>
  As a 'hobby' I quite like to reverse engineer key verifiers in random programs found on the net. In order to protect the company involved, I won't be naming them or their product.
  </p>
  <p>
  The key system is standard stuff, the program generates an activation code (12 digits) and the user enters a serial (24 digits). Internally it uses three main stages - a transform, a checksum and a different machine check. Additional information is also embedded in the serial - version, expiry date, site licencing and capabilities.
  </p>  
  <p>
  <span class="header">The Transform</span>
  The transform stage walks through the serial and a hardcoded transform key of the same length adding the two together, except in the special case of a zero in the serial which it treats as ten and subtracts the transform key instead:
  </p>
  <pre>
  for(i=0;i&lt;24;i++){
    if(serial[i]==0}{
      key[i] = 10 - xkey[i];
    }else{
      key[i] = serial[i] + xkey[i];
    }    
  }
  </pre>
  <p>
  Once this stage is complete the key has a structure and is broken up into six chunks:
  </p>
  <pre>
ZZZX-XXXX-XXYY-YYYW-WWVV-VVCS
  |        |     |    |   | |
(Z)version |     |    |   | |
(X)diff machine  |    |   | |
(Y)expiry date        |   | |
(W)site licence           | |
(V)capabilities             |
(CS)checksum
  </pre>
  <p>
  <span class="header">The Checksum</span>
  The checksum stage walks the first 22 numbers of the transformed key adding them up as it goes. With the result it takes the right most two digits and compares them to the last two in the transformed key.
  </p>
  <pre>
  for(i=0;i&lt;22;i++){
    cs = cs + key[i];
  }
  return cs % 100;  
  </pre>
  <p>
  <span class="header">The Different Machine Check</span>
  The different machine check takes the first four chars of the computer name and converts them in turn to their decimal representation resulting in an eight digit number. The first seven digits of this number are then compared to the fourth to tenth digits in the transformed key ('X' on the diagram above).
  </p>
  <pre>
  for(i=0;i&lt;4;i++){
    keypart .= ord(pcname[i]);
  }
  return substr(keypart, 0, 7);  
  </pre>
  <p>
  <span class="header">Additional Embedded Information</span>
  </p>
  <ul>
    <li>
    (Z) version - must equal "008" on the tested version
    </li>
    <li>
    (Y) expiry date - number of days since 31-12-1899
    </li>
    <li>
    (W) site licence
    </li>
    <li>
    (V) product capabilities - decimal number treated as a bit field
    </li>    
  </ul>
  <p>
  <span class="header">Activation key</span>
  Strangely the activation key wasn't required to successfully generate keys. I suspect it's an encoding of the computer name, that is then relayed to the vendor for key generation.
  </p>  
</post></xml>
