diff --git a/CMakeLists.txt b/CMakeLists.txt index f14a081..b83942e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,14 +25,6 @@ CONFIGURE_FILE(keys.json keys.json COPYONLY) #SET(BUILD_SHARED_LIBS OFF) #SET(CMAKE_EXE_LINKER_FLAGS "-static") -ADD_EXECUTABLE(xpkey src/main.cpp src/xp.cpp src/key.cpp src/util.cpp src/cli.cpp) +ADD_EXECUTABLE(xpkey src/main.cpp src/server.cpp src/xp.cpp src/key.cpp src/util.cpp src/cli.cpp src/confid.cpp) TARGET_INCLUDE_DIRECTORIES(xpkey PUBLIC crypto) -TARGET_LINK_LIBRARIES(xpkey PUBLIC OpenSSL::Crypto nlohmann_json::nlohmann_json fmt) - -ADD_EXECUTABLE(srv2003key src/server.cpp src/key.cpp src/util.cpp src/cli.cpp) -TARGET_INCLUDE_DIRECTORIES(srv2003key PUBLIC crypto) -TARGET_LINK_LIBRARIES(srv2003key PUBLIC OpenSSL::Crypto nlohmann_json::nlohmann_json fmt) - -ADD_EXECUTABLE(xpactivate src/confid.cpp) -TARGET_INCLUDE_DIRECTORIES(xpactivate PUBLIC crypto) -TARGET_LINK_LIBRARIES(xpactivate PUBLIC OpenSSL::Crypto nlohmann_json::nlohmann_json fmt) \ No newline at end of file +TARGET_LINK_LIBRARIES(xpkey PUBLIC OpenSSL::Crypto nlohmann_json::nlohmann_json fmt) \ No newline at end of file diff --git a/README.md b/README.md index d971b35..b9646d6 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ In light of the recent exponential interest in this project I've decided to put * If on **Linux** please clone and compile this repository using `cd build && cmake ../ && make` and run using `./xpkey` to generate a Volume License Key -2. (For retail only): After installation, you will be prompted to activate Windows. Select the *telephone activation* method, then, run `./xpactivate ` using the installation ID that the activation wizard gave you. +2. (For retail only): After installation, you will be prompted to activate Windows. Select the *telephone activation* method, then, run `./xpkey -i ` using the installation ID that the activation wizard gave you. 3. Click "**Next**" @@ -52,6 +52,7 @@ The list of people who have helped to bring the XP generation to where it is now * pottzman * Endermanch * Neo-Desktop +* WitherOrNot (the list will be updated to add more collaborators) diff --git a/keys.json b/keys.json index 202456b..cd28092 100644 --- a/keys.json +++ b/keys.json @@ -48,6 +48,9 @@ "Windows XP Starter Edition": { "BINK": ["32", "33"] }, + "Windows Longhorn (6.0.3683.0 -> 6.0.4029.0)": { + "BINK": ["40", "41"] + }, "Halo: Combat Evolved": { "BINK": ["50", "51"] }, @@ -57,6 +60,9 @@ "Plus! Digital Media Edition for Windows XP": { "BINK": ["52", "53"] }, + "Windows Longhorn (6.0.4033.0)": { + "BINK": ["54", "55"] + }, "Windows Server 2003": { "BINK": ["54", "55", "58", "59"] }, @@ -74,6 +80,9 @@ }, "Windows Server 2003 64 Bit VLK": { "BINK": ["68", "69", "6C", "6D"] + }, + "Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)": { + "BINK": ["74", "75"] } }, "BINK": { @@ -482,6 +491,36 @@ "y": "16927761660112078837951464089861279221188811999337390492625539371026015626584250804363204864186060157462161862017016" } }, + "40": { + "a": "1", + "b": "0", + "g": { + "x": "4059949146365219555765942623881117805902135583342215173483403715338700834444334843734013438929948804356102673557995327491778895286621343661027886194229423", + "y": "2666176389066415236284652473344297039725375670348031203453175504900403049498614310424697925683808910311136608699171612232668547550268382836372320506920106" + }, + "n": "5433982808887507657", + "p": "8593089364081001067462414866654031030011369860377686076521185730682021902004001446804904031667686514463236003668466017626568697473954285995216040950902881", + "priv": "449278429561237525", + "pub": { + "x": "7559615723586709586458106004507017059372166711271777511283228857051909257718309123926479472096584643986638698351587465542509690715985335205369481790178546", + "y": "7080073383749624161526624872543179425900008718862030231798273629479785989924538511939628398505421596500162321954578945975993952938126069166218024480096454" + } + }, + "41": { + "a": "1", + "b": "0", + "g": { + "x": "9791458979524371820932506373340791347147485287286801025025747008476002029861528741424050864358137516255664108423493779065350932029808518858376062167004536", + "y": "9932434466111647561557538581748799870403761251980691823240328064662070366553827221038647353473056891319938111493174855021955908965618290167703383083703662" + }, + "n": "4927638009777311293", + "p": "10165754444795254057389422393400930472583053728543041642319024171930216155078184719345890697917311487018908539453332431395199632756711975301609704092843793", + "priv": "3476326144393184330", + "pub": { + "x": "4462922298422522788711301077640671149487080987386610884077317356313747587278274922553055511229554308642911107087728929458238030390328053305039156712425692", + "y": "4166331361209663080277908775030002767045551689443380649904104094047767422069625957190676222747168197864341871814070164924686453916110248521040648287862677" + } + }, "50": { "a": "1", "b": "0", @@ -690,82 +729,112 @@ "pub": { "x": "4722272800064252767454697391320635537092623053473493936821919057777751250795528775893773028180225310055317957128183947713166125210509990475635070787240674", "y": "1531615552769437372403026851115800774961251901795490190286680044124146107960174759313522242631208697837075037127449543341158979848323485793132900943144563" - }, - "68": { - "a": "1", - "b": "0", - "g": { - "x": "5314815905585889296798694589942539626853861931198694818603038996528084849226860592659970116239143301533686664128842093994835269693920687751688904127888779", - "y": "10414790044180029072298701038447244079242758942849978521692070049764442685692432822170776283556203601227171463278884193414648621672635573015724449767555202" - }, - "n": "5725875683522971721", - "p": "12826772525868542995993863552630880658950068926652633231964092210337092764237251131994848166209877304480048932720132480186262823567355089380901269920285577", - "priv": "1068281577452339154", - "pub": { - "x": "12033418992548426346178523393578748081768559116860151229166249264538780301962627440762898922271298713141461639555947553862212449547395648972547457272406904", - "y": "4032882174174859318365824908716254483866659322383072417928411611598186762680107569672924388718908325415355049452875792560066378636581873850483566463440639" - } - }, - "69": { - "a": "1", - "b": "0", - "g": { - "x": "7173096084863451615574458983860544861871291843691257280899194149874765254047059142205262441857301868057882685920836271904169877920201774602904928493082466", - "y": "3685411334779977585663385448619770855951447093889245910985895498674988632379639227046444801656846750232784910161110782562016802517178353986707750695901040" - }, - "n": "5293859400497927137", - "p": "8380779820034448265154966159054835477696357572828327273565364892590557383123266250688404613890842142510687380806967918444847122708322525769781340041557697", - "priv": "4697401303693971213", - "pub": { - "x": "7654344525783880004912076071251050310876900359019139489057007158425701076455194924956926865732209623315247611882280988142426301468375261779854585638959095", - "y": "2205301557007321522756388509630157773456414780456128615321524979273286030768187976057798339743808057683824812565389382337153729181012589332286276647781278" - } - }, - "6C": { - "a": "1", - "b": "0", - "g": { - "x": "3193924578749149973349715439708853249371533674866738373146929732320027236261541739595179638552708548249437080416228471131201918968064263764697554111530165", - "y": "4888965687615736901315989550371141796747021791887255081237624800145952769028792494595799455118213679617455373330584340380954501271445892269198650215048525" - }, - "n": "5716362938854350473", - "p": "6772644826114336975395521564093976272857924418773374298215345596476892260493496637686700145278269579146144605357425079537260056407908058166728104826706641", - "priv": "2077245658215532950", - "pub": { - "x": "268695446123955264077019637228932681884538989037732941099747311674045562360739358379871180345850032196900336613323005578507597779076899979732110092466639", - "y": "679259663772569453698820219709022062154214038591908789527736008819910024904428464410413122647073108532832895523045487629004791793096766249438993506680831" - } - }, - "6D": { - "a": "1", - "b": "0", - "g": { - "x": "3298099620604059787834899492662174917598027267355370357344802081588599421345170581026563084037203023916968294761623560693756892912943381721305999449177880", - "y": "660070182381517254140291291235766825707865896406148611965367756543311281179754720142572450841218027728395896039015649326406436127710908614699312486011632" - }, - "n": "4729400334442529957", - "p": "10949181517511926903567022348751201958461013848233333337252284131793670496593568885605542253013440341224349881301674089289841680074611115257051662616691737", - "priv": "1917167729222184576", - "pub": { - "x": "6148303559806694802720175134063952680971862197161214387714553406366855716527344657113993997849223962074971349265039287455185887671146559993479377577325902", - "y": "4457002224085552970249907174802329661250245161967874670366390075435589489905320422633893787965164168305287264752277411705970075802880020100425352544173375" - } } }, - "office-xp": { + "68": { "a": "1", "b": "0", "g": { - "x": "12259358487924366608305813282440364085684395756994923636191629847503895994037183295786380452071239418106026509150804", - "y": "14853676372788121804436447106529209167572424731944959299344702242030301728072117127341066233856180747847416655851934" + "x": "5314815905585889296798694589942539626853861931198694818603038996528084849226860592659970116239143301533686664128842093994835269693920687751688904127888779", + "y": "10414790044180029072298701038447244079242758942849978521692070049764442685692432822170776283556203601227171463278884193414648621672635573015724449767555202" }, - "n": "69284057899286401", - "priv": "13576107630579530", - "p": "31648573662208007208411279340972174081655191771220726603117102285639562723584318781472781870749438532939445789762497", + "n": "5725875683522971721", + "p": "12826772525868542995993863552630880658950068926652633231964092210337092764237251131994848166209877304480048932720132480186262823567355089380901269920285577", + "priv": "1068281577452339154", "pub": { - "x": "5871898692465293699950936882527671235864759453647136933264801904900692020319864572178035453433020771524967155028662", - "y": "7797169826989892215278245730061461386927964876868463824394796499325209401088175936040551790551876059967923119137155" + "x": "12033418992548426346178523393578748081768559116860151229166249264538780301962627440762898922271298713141461639555947553862212449547395648972547457272406904", + "y": "4032882174174859318365824908716254483866659322383072417928411611598186762680107569672924388718908325415355049452875792560066378636581873850483566463440639" } + }, + "69": { + "a": "1", + "b": "0", + "g": { + "x": "7173096084863451615574458983860544861871291843691257280899194149874765254047059142205262441857301868057882685920836271904169877920201774602904928493082466", + "y": "3685411334779977585663385448619770855951447093889245910985895498674988632379639227046444801656846750232784910161110782562016802517178353986707750695901040" + }, + "n": "5293859400497927137", + "p": "8380779820034448265154966159054835477696357572828327273565364892590557383123266250688404613890842142510687380806967918444847122708322525769781340041557697", + "priv": "4697401303693971213", + "pub": { + "x": "7654344525783880004912076071251050310876900359019139489057007158425701076455194924956926865732209623315247611882280988142426301468375261779854585638959095", + "y": "2205301557007321522756388509630157773456414780456128615321524979273286030768187976057798339743808057683824812565389382337153729181012589332286276647781278" + } + }, + "6C": { + "a": "1", + "b": "0", + "g": { + "x": "3193924578749149973349715439708853249371533674866738373146929732320027236261541739595179638552708548249437080416228471131201918968064263764697554111530165", + "y": "4888965687615736901315989550371141796747021791887255081237624800145952769028792494595799455118213679617455373330584340380954501271445892269198650215048525" + }, + "n": "5716362938854350473", + "p": "6772644826114336975395521564093976272857924418773374298215345596476892260493496637686700145278269579146144605357425079537260056407908058166728104826706641", + "priv": "2077245658215532950", + "pub": { + "x": "268695446123955264077019637228932681884538989037732941099747311674045562360739358379871180345850032196900336613323005578507597779076899979732110092466639", + "y": "679259663772569453698820219709022062154214038591908789527736008819910024904428464410413122647073108532832895523045487629004791793096766249438993506680831" + } + }, + "6D": { + "a": "1", + "b": "0", + "g": { + "x": "3298099620604059787834899492662174917598027267355370357344802081588599421345170581026563084037203023916968294761623560693756892912943381721305999449177880", + "y": "660070182381517254140291291235766825707865896406148611965367756543311281179754720142572450841218027728395896039015649326406436127710908614699312486011632" + }, + "n": "4729400334442529957", + "p": "10949181517511926903567022348751201958461013848233333337252284131793670496593568885605542253013440341224349881301674089289841680074611115257051662616691737", + "priv": "1917167729222184576", + "pub": { + "x": "6148303559806694802720175134063952680971862197161214387714553406366855716527344657113993997849223962074971349265039287455185887671146559993479377577325902", + "y": "4457002224085552970249907174802329661250245161967874670366390075435589489905320422633893787965164168305287264752277411705970075802880020100425352544173375" + } + }, + "74": { + "a": "1", + "b": "0", + "g": { + "x": "520282615406607935808830413235837609227529008118239433194891765554084261177667142590192616462797266047427714603514505726507565809100858610756034340614180", + "y": "4557046395510954851157569206449480560848332315791566919607580280750304632075435589109908909351625686398512699199297926705742962219032991805095344264722444" + }, + "n": "4633201844252750473", + "p": "7181106593102322766813520532476531209871483588988471009176871145241389568314039093657656718839885029493125387894856821599452867350054864568294961595970889", + "priv": "4329540238250287790", + "pub": { + "x": "1748427561645745685508888890965804844329037567281415535239953290167653001827496844268667372126127464466687812723744919132659150838866693283679107969476861", + "y": "6808711632346399211426562555523956018872055718394662707289722207520029794097689415773036615424757895159410496488301598927496012713658489637493990459415502" + } + }, + "75": { + "a": "1", + "b": "0", + "g": { + "x": "3970421503592305806162067723385709415592786314716896691566248833585082875504539058115488199826473702792925925118152558094421770503793167297677060024718927", + "y": "5554883105100816924956214909142063182467429753687518086358166201697075386873889702658647183787469227480685699761636254567290136343644815706400210445911313" + }, + "n": "4969620768775003333", + "p": "9367329192536614353969825571614784746581688133872824941332015624935819730507282545479782208538086552891932718692035451653750509854673642536729217033200809", + "priv": "1900542198084112697", + "pub": { + "x": "4353876892698321681359683809542869088530852337838122569824839215556706068138042362107206144376439479309074833553075054210218907784959548685449627846808344", + "y": "8262695428675693411183184536456322786716473350154493786858023121139149995844800363332075756178523197170309252869968129569021002560420175757226928859306184" + } + } + }, + "office-xp": { + "a": "1", + "b": "0", + "g": { + "x": "12259358487924366608305813282440364085684395756994923636191629847503895994037183295786380452071239418106026509150804", + "y": "14853676372788121804436447106529209167572424731944959299344702242030301728072117127341066233856180747847416655851934" + }, + "n": "69284057899286401", + "priv": "13576107630579530", + "p": "31648573662208007208411279340972174081655191771220726603117102285639562723584318781472781870749438532939445789762497", + "pub": { + "x": "5871898692465293699950936882527671235864759453647136933264801904900692020319864572178035453433020771524967155028662", + "y": "7797169826989892215278245730061461386927964876868463824394796499325209401088175936040551790551876059967923119137155" } } } \ No newline at end of file diff --git a/src/cli.cpp b/src/cli.cpp index cc15721..927ab99 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -6,12 +6,17 @@ bool loadJSON(const fs::path& filename, json *output) { if (!fs::exists(filename)) { - fmt::print("{} does not exist", filename.string()); + fmt::print("ERROR: File {} does not exist\n", filename.string()); return false; } std::ifstream f(filename); - *output = json::parse(f); + *output = json::parse(f, nullptr, false, false); + + if (output->is_discarded()) { + fmt::print("ERROR: Unable to parse keys from {}\n", filename.string()); + return false; + } return true; } @@ -21,7 +26,9 @@ void showHelp(char *argv[]) { fmt::print("usage: {} \n", argv[0]); fmt::print("\t-h --help\tshow this message\n"); fmt::print("\t-v --verbose\tenable verbose output\n"); + fmt::print("\t-n --number\tnumber of keys to generate (defaults to 1)\n"); fmt::print("\t-f --file\tspecify which keys file to load (defaults to keys.json)\n"); + fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n"); fmt::print("\t-b --binkid\tspecify which BINK identifier to load (defaults to 2E)\n"); fmt::print("\t-l --list\tshow which products/binks can be loaded\n"); fmt::print("\t-c --channelid\tspecify which Channel Identifier to use (defaults to 640)\n"); @@ -34,6 +41,10 @@ int parseCommandLine(int argc, char* argv[], Options* options) { "2E", 640, "keys.json", + 1, + "", + false, + false, false, false, false @@ -46,12 +57,35 @@ int parseCommandLine(int argc, char* argv[], Options* options) { options->verbose = true; } else if (arg == "-h" || arg == "--help") { options->help = true; + } else if (arg == "-n" || arg == "--number") { + if (i == argc - 1) { + options->error = true; + break; + } + + int nKeys; + if (!sscanf(argv[i+1], "%d", &nKeys)) { + options->error = true; + } else { + options->numKeys = nKeys; + } + i++; } else if (arg == "-b" || arg == "--bink") { + if (i == argc - 1) { + options->error = true; + break; + } + options->binkid = argv[i+1]; i++; } else if (arg == "-l" || arg == "--list") { options->list = true; } else if (arg == "-c" || arg == "--channelid") { + if (i == argc - 1) { + options->error = true; + break; + } + int siteID; if (!sscanf(argv[i+1], "%d", &siteID)) { options->error = true; @@ -60,8 +94,21 @@ int parseCommandLine(int argc, char* argv[], Options* options) { } i++; } else if (arg == "-f" || arg == "--file") { + if (i == argc - 1) { + options->error = true; + break; + } + options->keysFilename = argv[i+1]; i++; + } else if (arg == "-i" || arg == "--instid") { + if (i == argc - 1) { + options->error = true; + break; + } + + options->instid = argv[i+1]; + i++; } else { options->error = true; } @@ -71,6 +118,18 @@ int parseCommandLine(int argc, char* argv[], Options* options) { } int validateCommandLine(Options* options, char *argv[], json *keys) { + if (options->verbose) { + fmt::print("Loading keys file {}\n", options->keysFilename); + } + + if (!loadJSON(options->keysFilename, keys)) { + return 2; + } + + if (options->verbose) { + fmt::print("Loaded keys from {} successfully\n",options->keysFilename); + } + if (options->help || options->error) { if (options->error) { fmt::print("error parsing command line options\n"); @@ -79,26 +138,11 @@ int validateCommandLine(Options* options, char *argv[], json *keys) { return 1; } - if (options->verbose) { - fmt::print("loading {}\n", options->keysFilename); - } - - if (!loadJSON(options->keysFilename, keys)) { - return 2; - } - - if (options->verbose) { - fmt::print("loaded {} successfully\n",options->keysFilename); - } - if (options->list) { for (auto el : (*keys)["Products"].items()) { int id; sscanf((el.value()["BINK"][0]).get().c_str(), "%x", &id); - if (id >= 0x50) { - continue; - } - std::cout << el.key() << ": " << el.value()["BINK"] << std::endl; + fmt::print("{}: {}\n", el.key(), el.value()["BINK"]); } fmt::print("\n\n"); @@ -110,13 +154,12 @@ int validateCommandLine(Options* options, char *argv[], json *keys) { 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 (intBinkID >= 0x40) { + options->isBink2002 = true; } if (options->channelID > 999) { - std::cout << "ERROR: refusing to create a key with a siteID greater than 999" << std::endl; + fmt::print("ERROR: refusing to create a key with a siteID greater than 999\n"); return 1; } diff --git a/src/confid.cpp b/src/confid.cpp index 69d7332..f791537 100644 --- a/src/confid.cpp +++ b/src/confid.cpp @@ -629,12 +629,11 @@ static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* ke } } -#define CHARTYPE char -static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirmation_id[49]) +int generateConfId(const char* installation_id_str, char confirmation_id[49]) { unsigned char installation_id[19]; // 10**45 < 256**19 size_t installation_id_len = 0; - const CHARTYPE* p = installation_id_str; + const char* p = installation_id_str; size_t count = 0, totalCount = 0; unsigned check = 0; size_t i; @@ -787,7 +786,7 @@ static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirma decimal[34 - i] = c4; } assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0); - CHARTYPE* q = confirmation_id; + char* q = confirmation_id; for (i = 0; i < 7; i++) { if (i) *q++ = '-'; @@ -802,39 +801,4 @@ static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirma } *q++ = 0; return 0; -} - -int main(int argc, char** argv) { - if (argc < 2) { - std::cout << "usage:" << std::endl; - std::cout << argv[0] << " " << std::endl; - return 1; - } - - char confirmation_id[49]; - int err = generateConfId(argv[1], confirmation_id); - - switch (err) { - case ERR_TOO_SHORT: - std::cout << "ERROR: Installation ID is too short" << std::endl; - return 1; - case ERR_TOO_LARGE: - std::cout << "ERROR: Installation ID is too long" << std::endl; - return 1; - case ERR_INVALID_CHARACTER: - std::cout << "ERROR: Invalid character in installation ID" << std::endl; - return 1; - case ERR_INVALID_CHECK_DIGIT: - std::cout << "ERROR: Installation ID checksum failed. Please check that it is typed correctly" << std::endl; - return 1; - case ERR_UNKNOWN_VERSION: - std::cout << "ERROR: Unknown installation ID version" << std::endl; - return 1; - case ERR_UNLUCKY: - std::cout << "ERROR: Unable to generate valid confirmation ID" << std::endl; - return 1; - case SUCCESS: - std::cout << "Confirmation ID: " << confirmation_id << std::endl; - return 0; - } } \ No newline at end of file diff --git a/src/header.h b/src/header.h index f1689a8..8e410ef 100644 --- a/src/header.h +++ b/src/header.h @@ -104,11 +104,15 @@ struct Options { std::string binkid; int channelID; std::string keysFilename; - bool verbose; + int numKeys; + std::string instid; bool help; bool list; + bool isBink2002; + bool verbose; bool error; }; +extern Options options; int parseCommandLine(int argc, char* argv[], Options* output); int validateCommandLine(Options* options, char* argv[], json* output); @@ -120,7 +124,7 @@ bool verifyXPKey( EC_GROUP *eCurve, EC_POINT *basePoint, EC_POINT *publicKey, - char (&pKey)[25] + char (&pKey)[25] ); void generateXPKey( @@ -129,9 +133,28 @@ void generateXPKey( BIGNUM *genOrder, BIGNUM *privateKey, DWORD pSerial, - char (&cdKey)[25] + char (&pKey)[25] ); // server.cpp +bool verifyServerKey( + EC_GROUP *eCurve, + EC_POINT *basePoint, + EC_POINT *publicKey, + char (&cdKey)[25] +); + +void generateServerKey( + EC_GROUP *eCurve, + EC_POINT *basePoint, + BIGNUM *genOrder, + BIGNUM *privateKey, + DWORD pChannelID, + DWORD pAuthInfo, + char (&pKey)[25] +); + +// confid.cpp +int generateConfId(const char* installation_id_str, char confirmation_id[49]); #endif //WINDOWSXPKG_HEADER_H diff --git a/src/main.cpp b/src/main.cpp index 40df42d..03e9fe5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,18 +5,20 @@ #include "header.h" char pCharset[] = "BCDFGHJKMPQRTVWXY2346789"; +Options options; int main(int argc, char *argv[]) { - Options options; - if (!parseCommandLine(argc, argv, &options)) { - fmt::print("error parsing command line\n"); + fmt::print("error parsing command line options\n"); + showHelp(argv); return !options.error ? 0 : 1; } json keys; - if (validateCommandLine(&options, argv, &keys) < 0) { - return 1; + int status = validateCommandLine(&options, argv, &keys); + + if (status > 0) { + return status; } const char* BINKID = options.binkid.c_str(); @@ -61,8 +63,74 @@ int main(int argc, char *argv[]) { pubPoint ); + if (!options.instid.empty()) { + char confirmation_id[49]; + int err = generateConfId(options.instid.c_str(), confirmation_id); + + switch (err) { + case ERR_TOO_SHORT: + fmt::print("ERROR: Installation ID is too short.\n"); + return 1; + case ERR_TOO_LARGE: + fmt::print("ERROR: Installation ID is too long.\n"); + return 1; + case ERR_INVALID_CHARACTER: + fmt::print("ERROR: Invalid character in installation ID.\n"); + return 1; + case ERR_INVALID_CHECK_DIGIT: + fmt::print("ERROR: Installation ID checksum failed. Please check that it is typed correctly.\n"); + return 1; + case ERR_UNKNOWN_VERSION: + fmt::print("ERROR: Unknown installation ID version.\n"); + return 1; + case ERR_UNLUCKY: + fmt::print("ERROR: Unable to generate valid confirmation ID.\n"); + return 1; + case SUCCESS: + fmt::print("Confirmation ID: {}\n", confirmation_id); + return 0; + + default: + fmt::print("Unknown error occurred during Confirmation ID generation: {}\n", err); + } + return 1; + } + // Calculation char pKey[25]; + int count = 0, total = options.numKeys; + + // BINK2002 Generation + if (options.isBink2002) { + DWORD pChannelID = options.channelID << 1; + + if (options.verbose) { + fmt::print("> Channel ID: {:03d}\n", options.channelID); + } + + // generate a key + for (int i = 0; i < total; i++) { + DWORD pAuthInfo; + RAND_bytes((BYTE *)&pAuthInfo, 4); + pAuthInfo &= 0x3ff; + + if (options.verbose) { + fmt::print("> AuthInfo: {}\n", pAuthInfo); + } + + generateServerKey(eCurve, genPoint, genOrder, privateKey, pChannelID, pAuthInfo, pKey); + print_product_key(pKey); + fmt::print("\n\n"); + + // verify a key + count += verifyServerKey(eCurve, genPoint, pubPoint, pKey); + } + + fmt::print("Success count: {}/{}\n", count, total); + return 0; + } + + // BINK1998 Generation DWORD nRaw = options.channelID * 1000000 ; /* <- change */ @@ -82,7 +150,6 @@ int main(int argc, char *argv[]) { // generate a key BN_sub(privateKey, genOrder, privateKey); nRaw <<= 1; - int count = 0, total = 1000; for (int i = 0; i < total; i++) { generateXPKey(eCurve, genPoint, genOrder, privateKey, nRaw, pKey); @@ -94,6 +161,5 @@ int main(int argc, char *argv[]) { } fmt::print("Success count: {}/{}\n", count, total); - return 0; } diff --git a/src/server.cpp b/src/server.cpp index 917867d..7221d92 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4,11 +4,6 @@ #include "header.h" -char pCharset[] = "BCDFGHJKMPQRTVWXY2346789"; -const std::string filename = "keys.json"; - -using json = nlohmann::json; - /* Unpacks the Windows XP-like Product Key. */ void unpackServer( QWORD (&pRaw)[2], @@ -67,11 +62,14 @@ bool verifyServerKey( // Extract segments from the bytecode and reverse the signature. unpackServer(bKey, pChannelID, pHash, pSignature, pAuthInfo); - std::cout << "Validation results:\n Serial: 0x" << std::hex << std::setw(8) << std::setfill('0') << pChannelID << std::endl - << " Hash: 0x" << std::hex << std::setw(8) << std::setfill('0') << pHash << std::endl - << " Signature: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSignature << std::endl - << " AuthInfo: 0x" << std::hex << std::setw(8) << std::setfill('0') << pAuthInfo << std::endl - << std::endl; + if (options.verbose) { + fmt::print("Validation results:\n"); + fmt::print(" Serial: 0x{:08x}\n", pChannelID); + fmt::print(" Hash: 0x{:08x}\n", pHash); + fmt::print(" Signature: 0x{:08x}\n", pSignature); + fmt::print(" AuthInfo: 0x{:08x}\n", pAuthInfo); + fmt::print("\n"); + } BYTE msgDigest[SHA_DIGEST_LENGTH]{}, msgBuffer[SHA_MSG_LENGTH_2003]{}, @@ -294,19 +292,29 @@ void generateServerKey( // Pack product key. packServer(pRaw, pChannelID, hash, pSignature, pAuthInfo); - std::cout << "Generation results:\n Serial: 0x" << std::hex << std::setw(8) << std::setfill('0') << pChannelID << std::endl - << " Hash: 0x" << std::hex << std::setw(8) << std::setfill('0') << hash << std::endl - << " Signature: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSignature << std::endl - << " AuthInfo: 0x" << std::hex << std::setw(8) << std::setfill('0') << pAuthInfo << std::endl - << std::endl; + if (options.verbose) { + fmt::print("Generation results:\n"); + fmt::print(" Serial: 0x{:08x}\n", pChannelID); + fmt::print(" Hash: 0x{:08x}\n", hash); + fmt::print(" Signature: 0x{:08x}\n", pSignature); + fmt::print(" AuthInfo: 0x{:08x}\n", pAuthInfo); + fmt::print("\n"); + } EC_POINT_free(r); - } while (HIBYTES(pSignature, sizeof(DWORD)) >= 0x40000000); + + DWORD chkChannelID, chkHash, chkAuthInfo; + QWORD chkSignature; + + unpackServer(pRaw, chkChannelID, chkHash, chkSignature, chkAuthInfo); + + if (chkHash != hash || chkSignature != pSignature) { + wrong = true; + } + } while ((HIBYTES(pSignature, sizeof(DWORD)) >= 0x40000000) || wrong); base24(pKey, (BYTE *)pRaw); - std::cout << "attempt pass " << pKey << " key is " << (wrong ? "INVALID" : "VALID") << std::endl; - BN_free(c); BN_free(s); BN_free(x); @@ -314,53 +322,4 @@ void generateServerKey( BN_free(e); BN_CTX_free(numContext); -} - -int main() -{ - const char* BINKID = "5A"; - - // 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). - BIGNUM *privateKey = BN_new(); - - // We can, however, validate any given key using the available public key: {p, a, b, G, K}. - // genOrder the order of the generator G, a value we have to reverse -> Schoof's Algorithm. - BIGNUM *genOrder = BN_new(); - - std::ifstream f(filename); - json keys = json::parse(f); - - EC_POINT *genPoint, *pubPoint; - EC_GROUP *eCurve = initializeEllipticCurve( - 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_dec2bn(&genOrder, keys["BINK"][BINKID]["n"].get().c_str()); - BN_dec2bn(&privateKey, keys["BINK"][BINKID]["priv"].get().c_str()); - - char pKey[25]{}; - DWORD pChannelID = 640 << 1, pAuthInfo; - - RAND_bytes((BYTE *)&pAuthInfo, 4); - pAuthInfo &= 0x3ff; - - printf("AuthInfo: %d\n", pAuthInfo); - - do { - generateServerKey(eCurve, genPoint, genOrder, privateKey, pChannelID, pAuthInfo, pKey); - } while (!verifyServerKey(eCurve, genPoint, pubPoint, pKey)); - - print_product_key(pKey); - std::cout << std::endl << std::endl; - - return 0; -} +} \ No newline at end of file diff --git a/src/xp.cpp b/src/xp.cpp index 61c748b..6279d2d 100644 --- a/src/xp.cpp +++ b/src/xp.cpp @@ -219,10 +219,13 @@ void generateXPKey( // Pack product key. packXP(pRaw, pSerial, pHash, pSignature); - fmt::print(" Serial: 0x{:08x}\n", pSerial); - fmt::print(" Hash: 0x{:08x}\n", pHash); - fmt::print(" Signature: 0x{:08x}\n", pSignature); - fmt::print("\n"); + if (options.verbose) { + fmt::print("Generation results:\n"); + fmt::print(" Serial: 0x{:08x}\n", pSerial); + fmt::print(" Hash: 0x{:08x}\n", pHash); + fmt::print(" Signature: 0x{:08x}\n", pSignature); + fmt::print("\n"); + } EC_POINT_free(r); } while (pRaw[1] > BITMASK(50));