int KeyDecoder::DecodeProductKey(KeyDecoder::Key key, char* pKey) { byte* pEncodedPID = GetRegistryDigitalProductId(key); int keyLen = 0; if(pEncodedPID) { char* pDecodedPID = DecodeProductKey(pEncodedPID); if(pDecodedPID) { keyLen = (int)::strlen(pDecodedPID); if(pKey) { ::strcpy(pKey, pDecodedPID); } delete[] pDecodedPID; } } return keyLen + 1; }
char* KeyDecoder::DecodeProductKey(byte* digitalProductId) { // Offset of first byte of encoded product key in // 'DigitalProductIdxxx" REG_BINARY value. Offset = 34H. const int keyStartIndex = 52; // Offset of last byte of encoded product key in // 'DigitalProductIdxxx" REG_BINARY value. Offset = 43H. const int keyEndIndex = keyStartIndex + 15; // Possible alpha-numeric characters in product key. char digits[] = { 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9', }; // Length of decoded product key const int decodeLength = 29; // Length of decoded product key in byte-form. // Each byte represents 2 chars. const int decodeStringLength = 15; // Array of containing the decoded product key. char* pDecodedChars = new char[decodeLength + 1]; ::memset(pDecodedChars, 0, decodeLength + 1); // Extract byte 52 to 67 inclusive. byte hexPid[keyEndIndex - keyStartIndex + 1]; for (int i = keyStartIndex; i <= keyEndIndex; i++) { hexPid[i - keyStartIndex] = digitalProductId[i]; } for (int i = decodeLength - 1; i >= 0; i--) { // Every sixth char is a separator. if ((i + 1) % 6 == 0) { *(pDecodedChars + i) = '-'; } else { // Do the actual decoding. int digitMapIndex = 0; for (int j = decodeStringLength - 1; j >= 0; j--) { int byteValue = (digitMapIndex << 8) | hexPid[j]; hexPid[j] = (byte)(byteValue / 24); digitMapIndex = byteValue % 24; *(pDecodedChars + i) = digits[digitMapIndex]; } } } return pDecodedChars; }
byte* KeyDecoder::GetRegistryDigitalProductId(KeyDecoder::Key key) { HKEY hKey = 0; LONG lResult = 0L; const char* pPIDName = "DigitalProductId"; byte* pPID = 0; switch(key) { case KeyDecoder::Key::XP: lResult = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE//Microsoft//Windows NT//CurrentVersion", 0, KEY_QUERY_VALUE, &hKey); break; case KeyDecoder::Key::Office10: break; case KeyDecoder::Key::Office11: break; } if(lResult == ERROR_SUCCESS) { DWORD cbData = 0; DWORD dwType = 0; lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &dwType, 0, &cbData); if(lResult == ERROR_SUCCESS) { pPID = new byte[cbData]; lResult = ::RegQueryValueEx(hKey, pPIDName, 0, &dwType, pPID, &cbData); if(lResult != ERROR_SUCCESS) { delete[] pPID; pPID = 0; } } } if(hKey) { ::RegCloseKey(hKey); } return pPID; }