Retrieve your Windows product key with C#

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • PsychoCoder
    Recognized Expert Contributor
    • Jul 2010
    • 465

    Retrieve your Windows product key with C#

    NOTE: Posted this on my blog this morning but also felt the bytes community could benefit from it.

    I've seen this question asked many times on different forums and thought I'd develop a solution for retrieving your Windows product key. It's actually a little mnore indepth than I initially thought due to the fact that the key is encoded as a byte array in the registry, so we will have to decode it to get the actual key.

    First thing we need to do is to declare all local variables needed to decode and hold the decoded product key:

    Code:
    //first byte offset
    const int start = 52;
    //last byte offset
    const int end = start + 15;
    //decoded key length
    const int length = 29;
    //decoded key in byte form
    const int decoded = 15;
    
    //char[] for holding the decoded product key
    var decodedKey = new char[length];
    
    //List<byte> to hold the key bytes
    var keyHex = new List<byte>();
    
    //list to hold possible alpha-numeric characters
    //that may be in the product key
    var charsInKey = new List<char>()
                        {
                            'B', 'C', 'D', 'F', 'G', 'H', 
                            'J', 'K', 'M', 'P', 'Q', 'R', 
                            'T', 'V', 'W', 'X', 'Y', '2', 
                            '3', '4', '6', '7', '8', '9'
                        };
    Next step is to add all the bytes to our List<byte>:

    Code:
    //add all bytes to our list
    for (var i = start; i <= end; i++)
        keyHex.Add(id[i]);
    Next we do the actual heavy listing (decode the byte array) to get the product key:

    Code:
    //now the decoding starts
    for (var i = length - 1; i >= 0; i--)
    
        switch ((i + 1) % 6)
        {
                //if the calculation is 0 (zero) then add the seperator
            case 0:
                decodedKey[i] = '-';
                break;
            default:
                var idx = 0;
    
                for (var j = decoded - 1; j >= 0; j--)
                {
                    var @value = (idx << 8) | keyHex[j];
                    keyHex[j] = (byte) (@value/24);
                    idx = @value%24;
                    decodedKey[i] = charsInKey[idx];
                }
                break;
        }
    And finally convert the byte array to a string containing the product key:

    Code:
    return new string(decodedKey);
    NOTE: We use the new constructor of the string class to convert a char array to a regular string.

    Ok, so now we have a method for decoding the product key, now how to use it. I created a simple WinForm with a TextBox and a Button. Here the first thing I do is to open the following key "SOFTWARE\\Micro soft\\Windows NT\\CurrentVers ion" (in HKEY_LOCAL_MACH INE). I then grab the value for DigitalProductI d and pass the byte array to the decoding function.

    The button click event looks like so:

    Code:
    private void FindProductKeyClick(object sender, EventArgs e)
    {
        byte[] id = null;
        var regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
    
        if (regKey != null) id = regKey.GetValue("DigitalProductId") as byte[];
    
        ProductKeyTextBox.Text = DecodeKeyByteArray(id);
    }
    Now run your application and retrieve the Windows product key. See that wasnt as hard as you thought it would be now is it. I hope you find this helpful and thanks for reading.

    Happy Coding!
  • Frinavale
    Recognized Expert Expert
    • Oct 2006
    • 9749

    #2
    Cool :)

    I've never had a need to do this but I'm glad you've posted a solution if I ever need to retrieve the Windows product key :)

    -Frinny

    Comment

    • michaeldebruin
      New Member
      • Feb 2011
      • 134

      #3
      I've tried your solution, but I think I did something wrong.

      Code:
      //first byte offset
              const int start = 52;
              //last byte offset
              const int end = start + 15;
              //decoded key length
              const int length = 29;
              //decoded key in byte form
              const int decoded = 15;
      
              private void btnGetKey_Click(object sender, EventArgs e)
              {
                  byte[] id = null;
                  var regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
      
                  if (regKey != null) id = regKey.GetValue("DigitalProductId") as byte[];
                  {
                      WindowsProductKey.Text = DecodeKeyByteArray(id);
                  }
      
                  //char[] for holding the decoded product key
                  var decodedKey = new char[length];
      
                  //List<byte> to hold the key bytes
                  var keyHex = new List<byte>();
      
                  //list to hold possible alpha-numeric characters
                  //that may be in the product key
                  var charsInKey = new List<char>()
                          {
                              'B', 'C', 'D', 'F', 'G', 'H', 
                              'J', 'K', 'M', 'P', 'Q', 'R', 
                              'T', 'V', 'W', 'X', 'Y', '2', 
                              '3', '4', '6', '7', '8', '9'
                          };
                  //add all bytes to our list
                  for (var i = start; i <= end; i++)
                  {
                      keyHex.Add(id[i]);
                  }
      
                  //now the decoding starts
                  for (var i = length - 1; i >= 0; i--)
      
                      switch ((i + 1) % 6)
                      {
                          //if the calculation is 0 (zero) then add the seperator
                          case 0:
                              decodedKey[i] = '-';
                              break;
                          default:
                              var idx = 0;
      
                              for (var j = decoded - 1; j >= 0; j--)
                              {
                                  var @value = (idx << 8) | keyHex[j];
                                  keyHex[j] = (byte)(@value / 24);
                                  idx = @value % 24;
                                  decodedKey[i] = charsInKey[idx];
                              }
                              break;
                      }
                  return new string(decodedKey);
              }
      it keep saying that I shouldn't use the return in the end. Which is kinda obvious because my button is a void. But when I try to separate it into a different class like this:
      Code:
              private void btnGetKey_Click(object sender, EventArgs e)
              {
                  byte[] id = null;
                  var regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
      
                  if (regKey != null) id = regKey.GetValue("DigitalProductId") as byte[];
                  {
                      WindowsProductKey.Text = DecodeKeyByteArray(id);
                  }
              }
      Code:
      class getKey
          {
              //first byte offset
              const int start = 52;
              //last byte offset
              const int end = start + 15;
              //decoded key length
              const int length = 29;
              //decoded key in byte form
              const int decoded = 15;
      
              public WindowsKey()
              {
                  //char[] for holding the decoded product key
                  var decodedKey = new char[length];
      
                  //List<byte> to hold the key bytes
                  var keyHex = new List<byte>();
      
                  //list to hold possible alpha-numeric characters
                  //that may be in the product key
                  var charsInKey = new List<char>()
                          {
                              'B', 'C', 'D', 'F', 'G', 'H', 
                              'J', 'K', 'M', 'P', 'Q', 'R', 
                              'T', 'V', 'W', 'X', 'Y', '2', 
                              '3', '4', '6', '7', '8', '9'
                          };
                  //add all bytes to our list
                  for (var i = start; i <= end; i++)
                  {
                      keyHex.Add(id[i]);
                  }
      
                  //now the decoding starts
                  for (var i = length - 1; i >= 0; i--)
                  {
      
                      switch ((i + 1) % 6)
                      {
                          //if the calculation is 0 (zero) then add the seperator
                          case 0:
                              decodedKey[i] = '-';
                              break;
                          default:
                              var idx = 0;
      
                              for (var j = decoded - 1; j >= 0; j--)
                              {
                                  var @value = (idx << 8) | keyHex[j];
                                  keyHex[j] = (byte)(@value / 24);
                                  idx = @value % 24;
                                  decodedKey[i] = charsInKey[idx];
                              }
                              break;
                      }
                  }
                  return new string(decodedKey);
              }
          }
      }
      it also says that I don't have a return method. Any idea what I need to add, to make it working?

      Comment

      Working...