From 72d441b53922fca5afa3a123e950bccad78fa9fe Mon Sep 17 00:00:00 2001 From: Neo <321592+Neo-Desktop@users.noreply.github.com> Date: Thu, 1 Jun 2023 21:25:43 -0700 Subject: [PATCH] Fix datatypes to use platform independent values, Add command line switch scaffolding Allow users to chose which bink/channelid they'd like to generate with Add rudimentary help system, Sanitize user input --- src/cli.cpp | 51 +++++++++++++++++- src/header.h | 41 +++++++++------ src/key.cpp | 12 ++--- src/main.cpp | 137 ++++++++++++++++++++++++++++++++----------------- src/server.cpp | 81 ++++++++++++++--------------- src/util.cpp | 36 ++++++------- src/xp.cpp | 36 +++++++------ 7 files changed, 250 insertions(+), 144 deletions(-) diff --git a/src/cli.cpp b/src/cli.cpp index 808dbbf..d567ea6 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -4,14 +4,61 @@ #include "header.h" -void print_product_id(ul32 *pid) +void showHelp(char *argv[]) { + std::cout << "usage: " << argv[0] << std::endl << std::endl + << "\t-h --help\tshow this message" << std::endl + << "\t-v --verbose\tenable verbose output" << std::endl + << "\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)" << std::endl + << "\t-l --list\tshow which products/binks can be loaded" << std::endl + << "\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)" << std::endl + << std::endl << std::endl; +} + +Options parseCommandLine(int argc, char* argv[]) { + Options options = { + "2E", + 640, + false, + false, + false + }; + + for (int i = 1; i < argc; i++) { + std::string arg = argv[i]; + + if (arg == "-v" || arg == "--verbose") { + options.verbose = true; + } else if (arg == "-h" || arg == "--help") { + options.help = true; + } else if (arg == "-b" || arg == "--bink") { + options.binkid = argv[i+1]; + i++; + } else if (arg == "-l" || arg == "--list") { + options.list = true; + } else if (arg == "-c" || arg == "--channelid") { + int siteID; + if (!sscanf(argv[i+1], "%d", &siteID)) { + options.error = true; + } else { + options.channelID = siteID; + } + i++; + } else { + options.error = true; + } + } + + return options; +} + +void print_product_id(uint32_t *pid) { char raw[12]; char b[6], c[8]; int i, digit = 0; // Cut a away last bit of pid and convert it to an accii-number (=raw) - sprintf(raw, "%lu", pid[0] >> 1); + sprintf(raw, "%iu", pid[0] >> 1); // Make b-part {640-....} strncpy(b, raw, 3); diff --git a/src/header.h b/src/header.h index ec361d5..df09489 100644 --- a/src/header.h +++ b/src/header.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -31,39 +32,49 @@ #define FIELD_BITS_2003 512 #define FIELD_BYTES_2003 64 -typedef unsigned char byte; -typedef unsigned int ul32; extern char charset[]; // util.cpp -void endian(byte *data, int length); +void endian(uint8_t *data, int length); EC_GROUP *initializeEllipticCurve( - const char *pSel, - const char *aSel, - const char *bSel, - const char *generatorXSel, - const char *generatorYSel, - const char *publicKeyXSel, - const char *publicKeyYSel, + const std::string pSel, + const std::string aSel, + const std::string bSel, + const std::string generatorXSel, + const std::string generatorYSel, + const std::string publicKeyXSel, + const std::string publicKeyYSel, EC_POINT **genPoint, EC_POINT **pubPoint ); // key.cpp -void unbase24(ul32 *byteSeq, const char *cdKey); -void base24(char *cdKey, ul32 *byteSeq); +void unbase24(uint32_t *byteSeq, const char *cdKey); +void base24(char *cdKey, uint32_t *byteSeq); // cli.cpp void print_product_key(char *pk); -void print_product_id(ul32 *pid); +void print_product_id(uint32_t *pid); + +struct Options { + std::string binkid; + int channelID; + bool verbose; + bool help; + bool list; + bool error; +}; + +Options parseCommandLine(int argc, char* argv[]); +void showHelp(char *argv[]); // xp.cpp bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, char *cdKey); -void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *order, BIGNUM *privateKey, ul32 *pRaw); +void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *order, BIGNUM *privateKey, uint32_t *pRaw); // server.cpp int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cdkey); -void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, BIGNUM *priv, ul32 *osfamily, ul32 *prefix); +void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, BIGNUM *priv, uint32_t *osfamily, uint32_t *prefix); #endif //WINDOWSXPKG_HEADER_H diff --git a/src/key.cpp b/src/key.cpp index fb2b83c..c689f15 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -5,8 +5,8 @@ #include "header.h" /* Converts from CD-key to a byte sequence. */ -void unbase24(ul32 *byteSeq, const char *cdKey) { - byte pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{}; +void unbase24(uint32_t *byteSeq, const char *cdKey) { + uint8_t pDecodedKey[PK_LENGTH + NULL_TERMINATOR]{}; BIGNUM *y = BN_new(); BN_zero(y); @@ -34,16 +34,16 @@ void unbase24(ul32 *byteSeq, const char *cdKey) { int n = BN_num_bytes(y); // Place the generated code into the byte sequence. - BN_bn2bin(y, (byte *)byteSeq); + BN_bn2bin(y, (uint8_t *)byteSeq); BN_free(y); // Reverse the byte sequence. - endian((byte *) byteSeq, n); + endian((uint8_t *)byteSeq, n); } /* Converts from byte sequence to the CD-key. */ -void base24(char *cdKey, ul32 *byteSeq) { - byte rbyteSeq[16]; +void base24(char *cdKey, uint32_t *byteSeq) { + uint8_t rbyteSeq[16]; BIGNUM *z; // Copy byte sequence to the reversed byte sequence. diff --git a/src/main.cpp b/src/main.cpp index 0a76a48..88b052a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,21 +3,64 @@ // #include "header.h" -#include char charset[] = "BCDFGHJKMPQRTVWXY2346789"; +const std::string filename = "keys.json"; using json = nlohmann::json; -int main() { - char* BINKID = "2E"; +int main(int argc, char *argv[]) { + Options options = parseCommandLine(argc, argv); - std::ifstream f("keys.json"); + if (options.help || options.error) { + if (options.error) { + std::cout << "error parsing command line options" << std::endl; + } + showHelp(argv); + return 0; + } + + if (options.verbose) { + std::cout << "loading " << filename << std::endl; + } + + std::ifstream f(filename); json keys = json::parse(f); - rand(); - srand(time(nullptr)); - rand(); + if (options.verbose) { + std::cout << "loaded " << filename << " successfully" << std::endl; + } + + if (options.list) { + for (auto el : keys["Products"].items()) { + int id; + sscanf((el.value()[0]).get().c_str(), "%x", &id); + if (id >= 0x50) { + continue; + } + std::cout << el.key() << ": " << el.value() << std::endl; + } + + std::cout << std::endl << std::endl + << "** Please note: any BINK ID other than 2E is considered experimental at this time **" + << std::endl; + return 0; + } + + int intBinkID; + sscanf(options.binkid.c_str(), "%x", &intBinkID); + + if (intBinkID >= 0x50) { + std::cout << "ERROR: BINK2002 and beyond is not supported in this application at this time" << std::endl; + return 1; + } + + if (options.channelID > 999) { + std::cout << "ERROR: refusing to create a key with a siteID greater than 999" << std::endl; + return 1; + } + + const char* BINKID = options.binkid.c_str(); // We cannot produce a valid key without knowing the private key k. The reason for this is that // we need the result of the function K(x; y) = kG(x; y). @@ -31,56 +74,52 @@ int main() { BN_dec2bn(&genOrder, keys["BINK"][BINKID]["n"].get().c_str()); BN_dec2bn(&privateKey, keys["BINK"][BINKID]["priv"].get().c_str()); - std::cout << keys["BINK"][BINKID]["p"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["a"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["b"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["g"]["x"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["g"]["y"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["pub"]["x"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["pub"]["y"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["n"].get().c_str() << std::endl; - std::cout << keys["BINK"][BINKID]["priv"].get().c_str() << std::endl; + if (options.verbose) { + std::cout << "-----------------------------------------------------------" << std::endl + << "Loaded the following curve constraints: BINK[" << BINKID << "]" << std::endl + << "-----------------------------------------------------------" << std::endl + << " P: " << keys["BINK"][BINKID]["p"].get() << std::endl + << " a: " << keys["BINK"][BINKID]["a"].get() << std::endl + << " b: " << keys["BINK"][BINKID]["b"].get() << std::endl + << "Gx: " << keys["BINK"][BINKID]["g"]["x"].get() << std::endl + << "Gy: " << keys["BINK"][BINKID]["g"]["y"].get() << std::endl + << "Kx: " << keys["BINK"][BINKID]["pub"]["x"].get() << std::endl + << "Ky: " << keys["BINK"][BINKID]["pub"]["y"].get() << std::endl + << " n: " << keys["BINK"][BINKID]["n"].get() << std::endl + << " k: " << keys["BINK"][BINKID]["priv"].get() << std::endl + << std::endl << std::endl; + } EC_POINT *genPoint, *pubPoint; EC_GROUP *eCurve = initializeEllipticCurve( - keys["BINK"][BINKID]["p"].get().c_str(), - keys["BINK"][BINKID]["a"].get().c_str(), - keys["BINK"][BINKID]["b"].get().c_str(), - keys["BINK"][BINKID]["g"]["x"].get().c_str(), - keys["BINK"][BINKID]["g"]["y"].get().c_str(), - keys["BINK"][BINKID]["pub"]["x"].get().c_str(), - keys["BINK"][BINKID]["pub"]["y"].get().c_str(), + keys["BINK"][BINKID]["p"].get(), + keys["BINK"][BINKID]["a"].get(), + keys["BINK"][BINKID]["b"].get(), + keys["BINK"][BINKID]["g"]["x"].get(), + keys["BINK"][BINKID]["g"]["y"].get(), + keys["BINK"][BINKID]["pub"]["x"].get(), + keys["BINK"][BINKID]["pub"]["y"].get(), &genPoint, &pubPoint ); - /*BN_print_fp(stdout, p); - std::cout << std::endl; - BN_print_fp(stdout, a); - std::cout << std::endl; - BN_print_fp(stdout, b); - std::cout << std::endl; - BN_print_fp(stdout, gx); - std::cout << std::endl; - BN_print_fp(stdout, gy); - std::cout << std::endl; - BN_print_fp(stdout, pubx); - std::cout << std::endl; - BN_print_fp(stdout, puby); - std::cout << std::endl; - BN_print_fp(stdout, n); - std::cout << std::endl; - BN_print_fp(stdout, priv); - std::cout << std::endl;*/ // Calculation - - char pKey[25]; - ul32 nRaw = 640 * 1000000 ; /* <- change */ - //nRaw += rand() & 999999; + uint32_t nRaw = options.channelID * 1000000 ; /* <- change */ - printf("> PID: %u\n", nRaw); + BIGNUM *bnrand = BN_new(); + BN_rand(bnrand, 19, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY); + + int oRaw; + char *cRaw = BN_bn2dec(bnrand); + + sscanf(cRaw, "%d", &oRaw); + nRaw += (oRaw &= 0xF423F); // ensure our serial is less than 999999 + + if (options.verbose) { + std::cout << "> PID: " << std::setw(9) << std::setfill('0') << nRaw << std::endl; + } // generate a key BN_sub(privateKey, genOrder, privateKey); @@ -88,10 +127,12 @@ int main() { generateXPKey(pKey, eCurve, genPoint, genOrder, privateKey, &nRaw); print_product_key(pKey); - printf("\n\n"); + std::cout << std::endl << std::endl; // verify the key - if (!verifyXPKey(eCurve, genPoint, pubPoint, pKey)) printf("Fail! Key is invalid.\n"); + if (!verifyXPKey(eCurve, genPoint, pubPoint, pKey)) { + std::cout << "Fail! Key is invalid." << std::endl; + } return 0; } \ No newline at end of file diff --git a/src/server.cpp b/src/server.cpp index 3ad4b14..006dde1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2,7 +2,7 @@ char charset[] = "BCDFGHJKMPQRTVWXY2346789"; -void unpack2003(ul32 *osfamily, ul32 *hash, ul32 *sig, ul32 *prefix, ul32 *raw) +void unpack2003(uint32_t *osfamily, uint32_t *hash, uint32_t *sig, uint32_t *prefix, uint32_t *raw) { osfamily[0] = raw[0] & 0x7ff; hash[0] = ((raw[0] >> 11) | (raw[1] << 21)) & 0x7fffffff; @@ -11,7 +11,7 @@ void unpack2003(ul32 *osfamily, ul32 *hash, ul32 *sig, ul32 *prefix, ul32 *raw) prefix[0] = (raw[3] >> 8) & 0x3ff; } -void pack2003(ul32 *raw, ul32 *osfamily, ul32 *hash, ul32 *sig, ul32 *prefix) +void pack2003(uint32_t *raw, uint32_t *osfamily, uint32_t *hash, uint32_t *sig, uint32_t *prefix) { raw[0] = osfamily[0] | (hash[0] << 11); raw[1] = (hash[0] >> 21) | (sig[0] << 10); @@ -34,19 +34,19 @@ int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cd } if (k >= 25) break; } - - ul32 bkey[4] = {0}; - ul32 osfamily[1], hash[1], sig[2], prefix[1]; + + uint32_t bkey[4] = {0}; + uint32_t osfamily[1], hash[1], sig[2], prefix[1]; unbase24(bkey, key); - printf("%.8lx %.8lx %.8lx %.8lx\n", bkey[3], bkey[2], bkey[1], bkey[0]); + printf("%.8ix %.8ix %.8ix %.8ix\n", bkey[3], bkey[2], bkey[1], bkey[0]); unpack2003(osfamily, hash, sig, prefix, bkey); - printf("OS Family: %lu\nHash: %.8lx\nSig: %.8lx %.8lx\nPrefix: %.8lx\n", osfamily[0], hash[0], sig[1], sig[0], prefix[0]); - - byte buf[FIELD_BYTES_2003], md[20]; - ul32 h1[2]; + printf("OS Family: %iu\nHash: %.8ix\nSig: %.8ix %.8ix\nPrefix: %.8ix\n", osfamily[0], hash[0], sig[1], sig[0], prefix[0]); + + uint8_t buf[FIELD_BYTES_2003], md[20]; + uint32_t h1[2]; SHA_CTX h_ctx; /* h1 = SHA-1(5D || OS Family || Hash || Prefix || 00 00) */ @@ -66,15 +66,15 @@ int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cd h1[0] = md[0] | (md[1] << 8) | (md[2] << 16) | (md[3] << 24); h1[1] = (md[4] | (md[5] << 8) | (md[6] << 16) | (md[7] << 24)) >> 2; h1[1] &= 0x3FFFFFFF; - printf("h1: %.8lx %.8lx\n", h1[1], h1[0]); + printf("h1: %.8ix %.8ix\n", h1[1], h1[0]); BIGNUM *s, *h, *x, *y; x = BN_new(); y = BN_new(); - endian((byte *)sig, 8); - endian((byte *)h1, 8); - s = BN_bin2bn((byte *)sig, 8, nullptr); - h = BN_bin2bn((byte *)h1, 8, nullptr); + endian((uint8_t *)sig, 8); + endian((uint8_t *)h1, 8); + s = BN_bin2bn((uint8_t *)sig, 8, nullptr); + h = BN_bin2bn((uint8_t *)h1, 8, nullptr); EC_POINT *r = EC_POINT_new(ec); EC_POINT *t = EC_POINT_new(ec); @@ -84,8 +84,8 @@ int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cd EC_POINT_add(ec, r, r, t, ctx); EC_POINT_mul(ec, r, nullptr, r, s, ctx); EC_POINT_get_affine_coordinates(ec, r, x, y, ctx); - - ul32 h2[1]; + + uint32_t h2[1]; /* h2 = SHA-1(79 || OS Family || r.x || r.y) */ SHA1_Init(&h_ctx); buf[0] = 0x79; @@ -95,17 +95,17 @@ int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cd memset(buf, 0, FIELD_BYTES_2003); BN_bn2bin(x, buf); - endian((byte *)buf, FIELD_BYTES_2003); + endian((uint8_t *)buf, FIELD_BYTES_2003); SHA1_Update(&h_ctx, buf, FIELD_BYTES_2003); memset(buf, 0, FIELD_BYTES_2003); BN_bn2bin(y, buf); - endian((byte *)buf, FIELD_BYTES_2003); + endian((uint8_t *)buf, FIELD_BYTES_2003); SHA1_Update(&h_ctx, buf, FIELD_BYTES_2003); SHA1_Final(md, &h_ctx); h2[0] = (md[0] | (md[1] << 8) | (md[2] << 16) | (md[3] << 24)) & 0x7fffffff; - printf("Calculated hash: %.8lx\n", h2[0]); + printf("Calculated hash: %.8ix\n", h2[0]); BN_free(s); BN_free(h); @@ -125,7 +125,7 @@ int verify2003(EC_GROUP *ec, EC_POINT *generator, EC_POINT *public_key, char *cd } } -void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, BIGNUM *priv, ul32 *osfamily, ul32 *prefix) +void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, BIGNUM *priv, uint32_t *osfamily, uint32_t *prefix) { BN_CTX *ctx = BN_CTX_new(); @@ -136,10 +136,10 @@ void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, BIGNUM *b = BN_new(); EC_POINT *r = EC_POINT_new(ec); - ul32 bkey[4]; - byte buf[FIELD_BYTES_2003], md[20]; - ul32 h1[2]; - ul32 hash[1], sig[2]; + uint32_t bkey[4]; + uint8_t buf[FIELD_BYTES_2003], md[20]; + uint32_t h1[2]; + uint32_t hash[1], sig[2]; SHA_CTX h_ctx; @@ -158,12 +158,12 @@ void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, memset(buf, 0, FIELD_BYTES_2003); BN_bn2bin(x, buf); - endian((byte *)buf, FIELD_BYTES_2003); + endian((uint8_t *)buf, FIELD_BYTES_2003); SHA1_Update(&h_ctx, buf, FIELD_BYTES_2003); memset(buf, 0, FIELD_BYTES_2003); BN_bn2bin(y, buf); - endian((byte *)buf, FIELD_BYTES_2003); + endian((uint8_t *)buf, FIELD_BYTES_2003); SHA1_Update(&h_ctx, buf, FIELD_BYTES_2003); SHA1_Final(md, &h_ctx); @@ -186,11 +186,11 @@ void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, h1[0] = md[0] | (md[1] << 8) | (md[2] << 16) | (md[3] << 24); h1[1] = (md[4] | (md[5] << 8) | (md[6] << 16) | (md[7] << 24)) >> 2; h1[1] &= 0x3FFFFFFF; - printf("h1: %.8lx %.8lx\n", h1[1], h1[0]); + printf("h1: %.8ix %.8ix\n", h1[1], h1[0]); /* s = ( -h1*priv + sqrt( (h1*priv)^2 + 4k ) ) / 2 */ - endian((byte *)h1, 8); - BN_bin2bn((byte *)h1, 8, b); + endian((uint8_t *)h1, 8); + BN_bin2bn((uint8_t *)h1, 8, b); BN_mod_mul(b, b, priv, order, ctx); BN_copy(s, b); BN_mod_sqr(s, s, order, ctx); @@ -203,13 +203,13 @@ void generate2003(char *pkey, EC_GROUP *ec, EC_POINT *generator, BIGNUM *order, } BN_rshift1(s, s); sig[0] = sig[1] = 0; - BN_bn2bin(s, (byte *)sig); - endian((byte *)sig, BN_num_bytes(s)); + BN_bn2bin(s, (uint8_t *)sig); + endian((uint8_t *)sig, BN_num_bytes(s)); if (sig[1] < 0x40000000) break; } pack2003(bkey, osfamily, hash, sig, prefix); - printf("OS family: %lu\nHash: %.8lx\nSig: %.8lx %.8lx\nPrefix: %.8lx\n", osfamily[0], hash[0], sig[1], sig[0], prefix[0]); - printf("%.8lx %.8lx %.8lx %.8lx\n", bkey[3], bkey[2], bkey[1], bkey[0]); + printf("OS family: %iu\nHash: %.8ix\nSig: %.8ix %.8ix\nPrefix: %.8ix\n", osfamily[0], hash[0], sig[1], sig[0], prefix[0]); + printf("%.8ix %.8ix %.8ix %.8ix\n", bkey[3], bkey[2], bkey[1], bkey[0]); base24(pkey, bkey); @@ -259,19 +259,20 @@ int main() assert(EC_POINT_is_on_curve(ec, g, ctx) == 1); assert(EC_POINT_is_on_curve(ec, pub, ctx) == 1); - - char pkey[25]; - ul32 osfamily[1], prefix[1]; + + char pkey[25]; + uint32_t osfamily[1], prefix[1]; osfamily[0] = 1280; - RAND_pseudo_bytes((byte *)prefix, 4); + RAND_pseudo_bytes((uint8_t *)prefix, 4); prefix[0] &= 0x3ff; do { generate2003(pkey, ec, g, n, priv, osfamily, prefix); - } while (!verify2003(ec, g, pub, (char*)pkey)); + } while (!verify2003(ec, g, pub, pkey)); - print_product_key(pkey); printf("\n\n"); + print_product_key(pkey); + std::cout << std::endl << std::endl; BN_CTX_free(ctx); diff --git a/src/util.cpp b/src/util.cpp index f378c63..c015a6c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5,14 +5,14 @@ #include "header.h" int randomRange() { - - + return 4; // chosen by fair dice roll + // guaranteed to be random } /* Convert data between endianness types. */ -void endian(byte *data, int length) { +void endian(uint8_t *data, int length) { for (int i = 0; i < length / 2; i++) { - byte temp = data[i]; + uint8_t temp = data[i]; data[i] = data[length - i - 1]; data[length - i - 1] = temp; } @@ -20,13 +20,13 @@ void endian(byte *data, int length) { /* Initializes the elliptic curve. */ EC_GROUP *initializeEllipticCurve( - const char *pSel, - const char *aSel, - const char *bSel, - const char *generatorXSel, - const char *generatorYSel, - const char *publicKeyXSel, - const char *publicKeyYSel, + const std::string pSel, + const std::string aSel, + const std::string bSel, + const std::string generatorXSel, + const std::string generatorYSel, + const std::string publicKeyXSel, + const std::string publicKeyYSel, EC_POINT **genPoint, EC_POINT **pubPoint ) { @@ -54,14 +54,14 @@ EC_GROUP *initializeEllipticCurve( context = BN_CTX_new(); /* Public data */ - BN_dec2bn(&p, pSel); - BN_dec2bn(&a, aSel); - BN_dec2bn(&b, bSel); - BN_dec2bn(&generatorX, generatorXSel); - BN_dec2bn(&generatorY, generatorYSel); + BN_dec2bn(&p, pSel.c_str()); + BN_dec2bn(&a, aSel.c_str()); + BN_dec2bn(&b, bSel.c_str()); + BN_dec2bn(&generatorX, generatorXSel.c_str()); + BN_dec2bn(&generatorY, generatorYSel.c_str()); - BN_dec2bn(&publicKeyX, publicKeyXSel); - BN_dec2bn(&publicKeyY, publicKeyYSel); + BN_dec2bn(&publicKeyX, publicKeyXSel.c_str()); + BN_dec2bn(&publicKeyY, publicKeyYSel.c_str()); /* Elliptic Curve calculations. */ // The group is defined via Fp = all integers [0; p - 1], where p is prime. diff --git a/src/xp.cpp b/src/xp.cpp index f29d488..db64fae 100644 --- a/src/xp.cpp +++ b/src/xp.cpp @@ -18,7 +18,7 @@ #include "header.h" /* Unpacks the Windows XP Product Key. */ -void unpackXP(ul32 *serial, ul32 *hash, ul32 *sig, ul32 *raw) { +void unpackXP(uint32_t *serial, uint32_t *hash, uint32_t *sig, uint32_t *raw) { // We're assuming that the quantity of information within the product key is at most 114 bits. // log2(24^25) = 114. @@ -39,7 +39,7 @@ void unpackXP(ul32 *serial, ul32 *hash, ul32 *sig, ul32 *raw) { } /* Packs the Windows XP Product Key. */ -void packXP(ul32 *raw, const ul32 *serial, const ul32 *hash, const ul32 *sig) { +void packXP(uint32_t *raw, const uint32_t *serial, const uint32_t *hash, const uint32_t *sig) { raw[0] = serial[0] | ((hash[0] & 1) << 31); raw[1] = (hash[0] >> 1) | ((sig[0] & 0x1f) << 27); raw[2] = (sig[0] >> 5) | (sig[1] << 27); @@ -51,8 +51,8 @@ bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, cha BN_CTX *context = BN_CTX_new(); // Convert Base24 CD-key to bytecode. - ul32 bKey[4]{}; - ul32 pID, checkHash, sig[2]; + uint32_t bKey[4]{}; + uint32_t pID, checkHash, sig[2]; unbase24(bKey, cdKey); @@ -68,8 +68,8 @@ bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, cha BN_set_word(e, checkHash); // Reverse signature and create a new BigNum s. - endian((byte *)sig, sizeof(sig)); - s = BN_bin2bn((byte *)sig, sizeof(sig), nullptr); + endian((uint8_t *)sig, sizeof(sig)); + s = BN_bin2bn((uint8_t *)sig, sizeof(sig), nullptr); // Create x and y. BIGNUM *x = BN_new(); @@ -95,8 +95,8 @@ bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, cha // x = v.x; y = v.y; EC_POINT_get_affine_coordinates(eCurve, v, x, y, context); - byte buf[FIELD_BYTES], md[SHA_DIGEST_LENGTH], t[4]; - ul32 newHash; + uint8_t buf[FIELD_BYTES], md[SHA_DIGEST_LENGTH], t[4]; + uint32_t newHash; SHA_CTX hContext; @@ -150,7 +150,7 @@ bool verifyXPKey(EC_GROUP *eCurve, EC_POINT *generator, EC_POINT *publicKey, cha } /* Generate a valid Product Key. */ -void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *order, BIGNUM *privateKey, ul32 *pRaw) { +void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *order, BIGNUM *privateKey, uint32_t *pRaw) { EC_POINT *r = EC_POINT_new(eCurve); BN_CTX *ctx = BN_CTX_new(); @@ -159,10 +159,10 @@ void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *or BIGNUM *x = BN_new(); BIGNUM *y = BN_new(); - ul32 bKey[4]{}; + uint32_t bKey[4]{}; do { - ul32 hash = 0, sig[2]{}; + uint32_t hash = 0, sig[2]{}; memset(bKey, 0, 4); @@ -176,7 +176,7 @@ void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *or EC_POINT_get_affine_coordinates(eCurve, r, x, y, ctx); SHA_CTX hContext; - byte md[SHA_DIGEST_LENGTH]{}, buf[FIELD_BYTES]{}, t[4]{}; + uint8_t md[SHA_DIGEST_LENGTH]{}, buf[FIELD_BYTES]{}, t[4]{}; // h = (First-32(SHA1(pRaw, r.x, r.y)) >> 4 SHA1_Init(&hContext); @@ -225,13 +225,19 @@ void generateXPKey(char *pKey, EC_GROUP *eCurve, EC_POINT *generator, BIGNUM *or BN_mod_add(s, s, c, order, ctx); // Convert s from BigNum back to bytecode and reverse the endianness. - BN_bn2bin(s, (byte *)sig); - endian((byte *)sig, BN_num_bytes(s)); + BN_bn2bin(s, (uint8_t *)sig); + endian((uint8_t *)sig, BN_num_bytes(s)); // Pack product key. packXP(bKey, pRaw, &hash, sig); - printf("PID: %.8X\nHash: %.8X\nSig: %.8X %.8X\n", pRaw[0], hash, sig[1], sig[0]); + //printf("PID: %.8X\nHash: %.8X\nSig: %.8X %.8X\n", pRaw[0], hash, sig[1], sig[0]); + std::cout << " PID: " << std::hex << std::setw(8) << std::setfill('0') << pRaw[0] << std::endl + << "Hash: " << std::hex << std::setw(8) << std::setfill('0') << hash << std::endl + << " Sig: " << std::hex << std::setw(8) << std::setfill('0') << sig[1] << " " + << std::hex << std::setw(8) << std::setfill('0') << sig[2] << std::endl + << std::endl; + } while (bKey[3] >= 0x40000); // ↑ ↑ ↑ // bKey[3] can't be longer than 18 bits, else the signature part will make