diff --git a/.idea/vcs.xml b/.idea/vcs.xml index b65c2e5..c8397c9 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/src/BINK1998.cpp b/src/BINK1998.cpp index 45f2a5a..6f55073 100644 --- a/src/BINK1998.cpp +++ b/src/BINK1998.cpp @@ -7,6 +7,7 @@ /* Unpacks the Windows XP-like Product Key. */ void BINK1998::Unpack( QWORD (&pRaw)[2], + BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature @@ -14,8 +15,11 @@ void BINK1998::Unpack( // We're assuming that the quantity of information within the product key is at most 114 bits. // log2(24^25) = 114. - // Serial = Bits [0..30] -> 31 bits - pSerial = FIRSTNBITS(pRaw[0], 31); + // Upgrade = Bit 0 + pUpgrade = FIRSTNBITS(pRaw[0], 1); + + // Serial = Bits [1..30] -> 30 bits + pSerial = NEXTSNBITS(pRaw[0], 30, 1); // Hash = Bits [31..58] -> 28 bits pHash = NEXTSNBITS(pRaw[0], 28, 31); @@ -27,6 +31,7 @@ void BINK1998::Unpack( /* Packs the Windows XP-like Product Key. */ void BINK1998::Pack( QWORD (&pRaw)[2], + BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature @@ -36,7 +41,7 @@ void BINK1998::Pack( // 64 * 2 = 128 // Signature [114..59] <- Hash [58..31] <- Serial [30..1] <- Upgrade [0] - pRaw[0] = FIRSTNBITS(pSignature, 5) << 59 | FIRSTNBITS(pHash, 28) << 31 | pSerial; + pRaw[0] = FIRSTNBITS(pSignature, 5) << 59 | FIRSTNBITS(pHash, 28) << 31 | pSerial << 1 | pUpgrade; pRaw[1] = NEXTSNBITS(pSignature, 51, 5); } @@ -50,16 +55,21 @@ bool BINK1998::Verify( BN_CTX *numContext = BN_CTX_new(); QWORD pRaw[2]{}, - pSignature = 0; + pSignature; - DWORD pSerial = 0, - pHash = 0; + DWORD pData, + pSerial, + pHash; + + BOOL pUpgrade; // Convert Base24 CD-key to bytecode. unbase24((BYTE *)pRaw, pKey); // Extract RPK, hash and signature from bytecode. - Unpack(pRaw, pSerial, pHash, pSignature); + Unpack(pRaw, pUpgrade, pSerial, pHash, pSignature); + + pData = pSerial << 1 | pUpgrade; /* * @@ -107,7 +117,7 @@ bool BINK1998::Verify( BN_bn2lebin(y, yBin, FIELD_BYTES); // Assemble the SHA message. - memcpy((void *)&msgBuffer[0], (void *)&pSerial, 4); + memcpy((void *)&msgBuffer[0], (void *)&pData, 4); memcpy((void *)&msgBuffer[4], (void *)xBin, FIELD_BYTES); memcpy((void *)&msgBuffer[4 + FIELD_BYTES], (void *)yBin, FIELD_BYTES); @@ -139,6 +149,7 @@ void BINK1998::Generate( BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, + BOOL pUpgrade, char (&pKey)[25] ) { BN_CTX *numContext = BN_CTX_new(); @@ -151,6 +162,9 @@ void BINK1998::Generate( QWORD pRaw[2]{}, pSignature = 0; + // Data segment of the RPK. + DWORD pData = pSerial << 1 | pUpgrade; + do { EC_POINT *r = EC_POINT_new(eCurve); @@ -175,7 +189,7 @@ void BINK1998::Generate( BN_bn2lebin(y, yBin, FIELD_BYTES); // Assemble the SHA message. - memcpy((void *)&msgBuffer[0], (void *)&pSerial, 4); + memcpy((void *)&msgBuffer[0], (void *)&pData, 4); memcpy((void *)&msgBuffer[4], (void *)xBin, FIELD_BYTES); memcpy((void *)&msgBuffer[4 + FIELD_BYTES], (void *)yBin, FIELD_BYTES); @@ -216,10 +230,11 @@ void BINK1998::Generate( BN_bn2lebinpad(s, (BYTE *)&pSignature, BN_num_bytes(s)); // Pack product key. - Pack(pRaw, pSerial, pHash, pSignature); + Pack(pRaw, pUpgrade, pSerial, pHash, pSignature); if (options.verbose) { fmt::print("Generation results:\n"); + fmt::print(" Upgrade: 0x{:08x}\n", pUpgrade); fmt::print(" Serial: 0x{:08x}\n", pSerial); fmt::print(" Hash: 0x{:08x}\n", pHash); fmt::print(" Signature: 0x{:08x}\n", pSignature); diff --git a/src/BINK1998.h b/src/BINK1998.h index 0af8bda..82c9361 100644 --- a/src/BINK1998.h +++ b/src/BINK1998.h @@ -10,12 +10,14 @@ class BINK1998 { static void Unpack( QWORD (&pRaw)[2], + BOOL &pUpgrade, DWORD &pSerial, DWORD &pHash, QWORD &pSignature ); static void Pack( QWORD (&pRaw)[2], + BOOL pUpgrade, DWORD pSerial, DWORD pHash, QWORD pSignature @@ -34,6 +36,7 @@ public: BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, + BOOL pUpgrade, char (&pKey)[25] ); }; diff --git a/src/cli.cpp b/src/cli.cpp index af54098..714fc19 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -270,7 +270,7 @@ int CLI::BINK1998() { char *cRaw = BN_bn2dec(bnrand); sscanf(cRaw, "%d", &oRaw); - nRaw += (oRaw &= 0xF423F); // ensure our serial is less than 999999 + nRaw += (oRaw % 999999); // ensure our serial is less than 999999 if (options.verbose) { fmt::print("> PID: {:09d}\n", nRaw); @@ -278,10 +278,12 @@ int CLI::BINK1998() { // generate a key BN_sub(privateKey, genOrder, privateKey); - nRaw <<= 1; + + // Specify whether an upgrade version or not + bool bUpgrade = false; for (int i = 0; i < total; i++) { - BINK1998::Generate(eCurve, genPoint, genOrder, privateKey, nRaw, pKey); + BINK1998::Generate(eCurve, genPoint, genOrder, privateKey, nRaw, bUpgrade, pKey); CLI::print_product_key(pKey); fmt::print("\n\n"); @@ -304,7 +306,7 @@ int CLI::BINK2002() { for (int i = 0; i < total; i++) { DWORD pAuthInfo; RAND_bytes((BYTE *)&pAuthInfo, 4); - pAuthInfo &= 0x3ff; + pAuthInfo &= BITMASK(10); if (options.verbose) { fmt::print("> AuthInfo: {}\n", pAuthInfo); diff --git a/src/header.h b/src/header.h index 206736a..d654a3e 100644 --- a/src/header.h +++ b/src/header.h @@ -77,10 +77,8 @@ struct Options { MODE applicationMode; }; -extern Options options; - // Type definitions -typedef bool BOOL; +typedef uint32_t BOOL; typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; @@ -91,6 +89,7 @@ typedef unsigned __int128 OWORD; #endif // Global variables +extern Options options; // util.cpp int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen); // Hello OpenSSL developers, please tell me, where is this function at?