mirror of
https://github.com/Neo-Desktop/WindowsXPKg
synced 2024-11-25 15:20:59 +02:00
merge server and confid with xpkey, add LH keys (#18)
* merge server and confid with xpkey, add LH keys * improve error handling * update README.md * fix line endings * reorder products section of keys.json * use options as global variable * rename genServer to isBink2002 * small refactor * handle unknown error codepath on confirmation id remove redundant else for BINK1998 generation * finish conversion from std::cout -> fmt::print(); --------- Co-authored-by: Neo <321592+Neo-Desktop@users.noreply.github.com>
This commit is contained in:
parent
8c295cf973
commit
98c8db7e02
@ -25,14 +25,6 @@ CONFIGURE_FILE(keys.json keys.json COPYONLY)
|
|||||||
|
|
||||||
#SET(BUILD_SHARED_LIBS OFF)
|
#SET(BUILD_SHARED_LIBS OFF)
|
||||||
#SET(CMAKE_EXE_LINKER_FLAGS "-static")
|
#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_INCLUDE_DIRECTORIES(xpkey PUBLIC crypto)
|
||||||
TARGET_LINK_LIBRARIES(xpkey PUBLIC OpenSSL::Crypto nlohmann_json::nlohmann_json fmt)
|
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)
|
|
@ -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
|
* 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 <Installation ID>` 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 <Installation ID>` using the installation ID that the activation wizard gave you.
|
||||||
|
|
||||||
3. Click "**Next**"
|
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
|
* pottzman
|
||||||
* Endermanch
|
* Endermanch
|
||||||
* Neo-Desktop
|
* Neo-Desktop
|
||||||
|
* WitherOrNot
|
||||||
|
|
||||||
(the list will be updated to add more collaborators)
|
(the list will be updated to add more collaborators)
|
||||||
|
|
||||||
|
71
keys.json
71
keys.json
@ -48,6 +48,9 @@
|
|||||||
"Windows XP Starter Edition": {
|
"Windows XP Starter Edition": {
|
||||||
"BINK": ["32", "33"]
|
"BINK": ["32", "33"]
|
||||||
},
|
},
|
||||||
|
"Windows Longhorn (6.0.3683.0 -> 6.0.4029.0)": {
|
||||||
|
"BINK": ["40", "41"]
|
||||||
|
},
|
||||||
"Halo: Combat Evolved": {
|
"Halo: Combat Evolved": {
|
||||||
"BINK": ["50", "51"]
|
"BINK": ["50", "51"]
|
||||||
},
|
},
|
||||||
@ -57,6 +60,9 @@
|
|||||||
"Plus! Digital Media Edition for Windows XP": {
|
"Plus! Digital Media Edition for Windows XP": {
|
||||||
"BINK": ["52", "53"]
|
"BINK": ["52", "53"]
|
||||||
},
|
},
|
||||||
|
"Windows Longhorn (6.0.4033.0)": {
|
||||||
|
"BINK": ["54", "55"]
|
||||||
|
},
|
||||||
"Windows Server 2003": {
|
"Windows Server 2003": {
|
||||||
"BINK": ["54", "55", "58", "59"]
|
"BINK": ["54", "55", "58", "59"]
|
||||||
},
|
},
|
||||||
@ -74,6 +80,9 @@
|
|||||||
},
|
},
|
||||||
"Windows Server 2003 64 Bit VLK": {
|
"Windows Server 2003 64 Bit VLK": {
|
||||||
"BINK": ["68", "69", "6C", "6D"]
|
"BINK": ["68", "69", "6C", "6D"]
|
||||||
|
},
|
||||||
|
"Windows Longhorn (6.0.4039.0 -> Pre PIDGENX)": {
|
||||||
|
"BINK": ["74", "75"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"BINK": {
|
"BINK": {
|
||||||
@ -482,6 +491,36 @@
|
|||||||
"y": "16927761660112078837951464089861279221188811999337390492625539371026015626584250804363204864186060157462161862017016"
|
"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": {
|
"50": {
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "0",
|
"b": "0",
|
||||||
@ -690,6 +729,7 @@
|
|||||||
"pub": {
|
"pub": {
|
||||||
"x": "4722272800064252767454697391320635537092623053473493936821919057777751250795528775893773028180225310055317957128183947713166125210509990475635070787240674",
|
"x": "4722272800064252767454697391320635537092623053473493936821919057777751250795528775893773028180225310055317957128183947713166125210509990475635070787240674",
|
||||||
"y": "1531615552769437372403026851115800774961251901795490190286680044124146107960174759313522242631208697837075037127449543341158979848323485793132900943144563"
|
"y": "1531615552769437372403026851115800774961251901795490190286680044124146107960174759313522242631208697837075037127449543341158979848323485793132900943144563"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"68": {
|
"68": {
|
||||||
"a": "1",
|
"a": "1",
|
||||||
@ -750,6 +790,36 @@
|
|||||||
"x": "6148303559806694802720175134063952680971862197161214387714553406366855716527344657113993997849223962074971349265039287455185887671146559993479377577325902",
|
"x": "6148303559806694802720175134063952680971862197161214387714553406366855716527344657113993997849223962074971349265039287455185887671146559993479377577325902",
|
||||||
"y": "4457002224085552970249907174802329661250245161967874670366390075435589489905320422633893787965164168305287264752277411705970075802880020100425352544173375"
|
"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": {
|
"office-xp": {
|
||||||
@ -767,5 +837,4 @@
|
|||||||
"y": "7797169826989892215278245730061461386927964876868463824394796499325209401088175936040551790551876059967923119137155"
|
"y": "7797169826989892215278245730061461386927964876868463824394796499325209401088175936040551790551876059967923119137155"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
87
src/cli.cpp
87
src/cli.cpp
@ -6,12 +6,17 @@
|
|||||||
|
|
||||||
bool loadJSON(const fs::path& filename, json *output) {
|
bool loadJSON(const fs::path& filename, json *output) {
|
||||||
if (!fs::exists(filename)) {
|
if (!fs::exists(filename)) {
|
||||||
fmt::print("{} does not exist", filename.string());
|
fmt::print("ERROR: File {} does not exist\n", filename.string());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream f(filename);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -21,7 +26,9 @@ void showHelp(char *argv[]) {
|
|||||||
fmt::print("usage: {} \n", argv[0]);
|
fmt::print("usage: {} \n", argv[0]);
|
||||||
fmt::print("\t-h --help\tshow this message\n");
|
fmt::print("\t-h --help\tshow this message\n");
|
||||||
fmt::print("\t-v --verbose\tenable verbose output\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-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-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-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");
|
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",
|
"2E",
|
||||||
640,
|
640,
|
||||||
"keys.json",
|
"keys.json",
|
||||||
|
1,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
@ -46,12 +57,35 @@ int parseCommandLine(int argc, char* argv[], Options* options) {
|
|||||||
options->verbose = true;
|
options->verbose = true;
|
||||||
} else if (arg == "-h" || arg == "--help") {
|
} else if (arg == "-h" || arg == "--help") {
|
||||||
options->help = true;
|
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") {
|
} else if (arg == "-b" || arg == "--bink") {
|
||||||
|
if (i == argc - 1) {
|
||||||
|
options->error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
options->binkid = argv[i+1];
|
options->binkid = argv[i+1];
|
||||||
i++;
|
i++;
|
||||||
} else if (arg == "-l" || arg == "--list") {
|
} else if (arg == "-l" || arg == "--list") {
|
||||||
options->list = true;
|
options->list = true;
|
||||||
} else if (arg == "-c" || arg == "--channelid") {
|
} else if (arg == "-c" || arg == "--channelid") {
|
||||||
|
if (i == argc - 1) {
|
||||||
|
options->error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int siteID;
|
int siteID;
|
||||||
if (!sscanf(argv[i+1], "%d", &siteID)) {
|
if (!sscanf(argv[i+1], "%d", &siteID)) {
|
||||||
options->error = true;
|
options->error = true;
|
||||||
@ -60,8 +94,21 @@ int parseCommandLine(int argc, char* argv[], Options* options) {
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
} else if (arg == "-f" || arg == "--file") {
|
} else if (arg == "-f" || arg == "--file") {
|
||||||
|
if (i == argc - 1) {
|
||||||
|
options->error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
options->keysFilename = argv[i+1];
|
options->keysFilename = argv[i+1];
|
||||||
i++;
|
i++;
|
||||||
|
} else if (arg == "-i" || arg == "--instid") {
|
||||||
|
if (i == argc - 1) {
|
||||||
|
options->error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
options->instid = argv[i+1];
|
||||||
|
i++;
|
||||||
} else {
|
} else {
|
||||||
options->error = true;
|
options->error = true;
|
||||||
}
|
}
|
||||||
@ -71,6 +118,18 @@ int parseCommandLine(int argc, char* argv[], Options* options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int validateCommandLine(Options* options, char *argv[], json *keys) {
|
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->help || options->error) {
|
||||||
if (options->error) {
|
if (options->error) {
|
||||||
fmt::print("error parsing command line options\n");
|
fmt::print("error parsing command line options\n");
|
||||||
@ -79,26 +138,11 @@ int validateCommandLine(Options* options, char *argv[], json *keys) {
|
|||||||
return 1;
|
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) {
|
if (options->list) {
|
||||||
for (auto el : (*keys)["Products"].items()) {
|
for (auto el : (*keys)["Products"].items()) {
|
||||||
int id;
|
int id;
|
||||||
sscanf((el.value()["BINK"][0]).get<std::string>().c_str(), "%x", &id);
|
sscanf((el.value()["BINK"][0]).get<std::string>().c_str(), "%x", &id);
|
||||||
if (id >= 0x50) {
|
fmt::print("{}: {}\n", el.key(), el.value()["BINK"]);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::cout << el.key() << ": " << el.value()["BINK"] << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print("\n\n");
|
fmt::print("\n\n");
|
||||||
@ -110,13 +154,12 @@ int validateCommandLine(Options* options, char *argv[], json *keys) {
|
|||||||
int intBinkID;
|
int intBinkID;
|
||||||
sscanf(options->binkid.c_str(), "%x", &intBinkID);
|
sscanf(options->binkid.c_str(), "%x", &intBinkID);
|
||||||
|
|
||||||
if (intBinkID >= 0x50) {
|
if (intBinkID >= 0x40) {
|
||||||
std::cout << "ERROR: BINK2002 and beyond is not supported in this application at this time" << std::endl;
|
options->isBink2002 = true;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options->channelID > 999) {
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,12 +629,11 @@ static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* ke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHARTYPE char
|
int generateConfId(const char* installation_id_str, char confirmation_id[49])
|
||||||
static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirmation_id[49])
|
|
||||||
{
|
{
|
||||||
unsigned char installation_id[19]; // 10**45 < 256**19
|
unsigned char installation_id[19]; // 10**45 < 256**19
|
||||||
size_t installation_id_len = 0;
|
size_t installation_id_len = 0;
|
||||||
const CHARTYPE* p = installation_id_str;
|
const char* p = installation_id_str;
|
||||||
size_t count = 0, totalCount = 0;
|
size_t count = 0, totalCount = 0;
|
||||||
unsigned check = 0;
|
unsigned check = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -787,7 +786,7 @@ static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirma
|
|||||||
decimal[34 - i] = c4;
|
decimal[34 - i] = c4;
|
||||||
}
|
}
|
||||||
assert(e.encoded[0] == 0 && e.encoded[1] == 0 && e.encoded[2] == 0 && e.encoded[3] == 0);
|
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++) {
|
for (i = 0; i < 7; i++) {
|
||||||
if (i)
|
if (i)
|
||||||
*q++ = '-';
|
*q++ = '-';
|
||||||
@ -803,38 +802,3 @@ static int generateConfId(const CHARTYPE* installation_id_str, CHARTYPE confirma
|
|||||||
*q++ = 0;
|
*q++ = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
if (argc < 2) {
|
|
||||||
std::cout << "usage:" << std::endl;
|
|
||||||
std::cout << argv[0] << " <Installation ID>" << 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;
|
|
||||||
}
|
|
||||||
}
|
|
27
src/header.h
27
src/header.h
@ -104,11 +104,15 @@ struct Options {
|
|||||||
std::string binkid;
|
std::string binkid;
|
||||||
int channelID;
|
int channelID;
|
||||||
std::string keysFilename;
|
std::string keysFilename;
|
||||||
bool verbose;
|
int numKeys;
|
||||||
|
std::string instid;
|
||||||
bool help;
|
bool help;
|
||||||
bool list;
|
bool list;
|
||||||
|
bool isBink2002;
|
||||||
|
bool verbose;
|
||||||
bool error;
|
bool error;
|
||||||
};
|
};
|
||||||
|
extern Options options;
|
||||||
|
|
||||||
int parseCommandLine(int argc, char* argv[], Options* output);
|
int parseCommandLine(int argc, char* argv[], Options* output);
|
||||||
int validateCommandLine(Options* options, char* argv[], json* output);
|
int validateCommandLine(Options* options, char* argv[], json* output);
|
||||||
@ -129,9 +133,28 @@ void generateXPKey(
|
|||||||
BIGNUM *genOrder,
|
BIGNUM *genOrder,
|
||||||
BIGNUM *privateKey,
|
BIGNUM *privateKey,
|
||||||
DWORD pSerial,
|
DWORD pSerial,
|
||||||
char (&cdKey)[25]
|
char (&pKey)[25]
|
||||||
);
|
);
|
||||||
|
|
||||||
// server.cpp
|
// 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
|
#endif //WINDOWSXPKG_HEADER_H
|
||||||
|
80
src/main.cpp
80
src/main.cpp
@ -5,18 +5,20 @@
|
|||||||
#include "header.h"
|
#include "header.h"
|
||||||
|
|
||||||
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
||||||
|
Options options;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
Options options;
|
|
||||||
|
|
||||||
if (!parseCommandLine(argc, argv, &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;
|
return !options.error ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
json keys;
|
json keys;
|
||||||
if (validateCommandLine(&options, argv, &keys) < 0) {
|
int status = validateCommandLine(&options, argv, &keys);
|
||||||
return 1;
|
|
||||||
|
if (status > 0) {
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* BINKID = options.binkid.c_str();
|
const char* BINKID = options.binkid.c_str();
|
||||||
@ -61,8 +63,74 @@ int main(int argc, char *argv[]) {
|
|||||||
pubPoint
|
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
|
// Calculation
|
||||||
char pKey[25];
|
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 */
|
DWORD nRaw = options.channelID * 1000000 ; /* <- change */
|
||||||
|
|
||||||
@ -82,7 +150,6 @@ int main(int argc, char *argv[]) {
|
|||||||
// generate a key
|
// generate a key
|
||||||
BN_sub(privateKey, genOrder, privateKey);
|
BN_sub(privateKey, genOrder, privateKey);
|
||||||
nRaw <<= 1;
|
nRaw <<= 1;
|
||||||
int count = 0, total = 1000;
|
|
||||||
|
|
||||||
for (int i = 0; i < total; i++) {
|
for (int i = 0; i < total; i++) {
|
||||||
generateXPKey(eCurve, genPoint, genOrder, privateKey, nRaw, pKey);
|
generateXPKey(eCurve, genPoint, genOrder, privateKey, nRaw, pKey);
|
||||||
@ -94,6 +161,5 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt::print("Success count: {}/{}\n", count, total);
|
fmt::print("Success count: {}/{}\n", count, total);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,6 @@
|
|||||||
|
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
|
|
||||||
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
|
|
||||||
const std::string filename = "keys.json";
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
/* Unpacks the Windows XP-like Product Key. */
|
/* Unpacks the Windows XP-like Product Key. */
|
||||||
void unpackServer(
|
void unpackServer(
|
||||||
QWORD (&pRaw)[2],
|
QWORD (&pRaw)[2],
|
||||||
@ -67,11 +62,14 @@ bool verifyServerKey(
|
|||||||
// Extract segments from the bytecode and reverse the signature.
|
// Extract segments from the bytecode and reverse the signature.
|
||||||
unpackServer(bKey, pChannelID, pHash, pSignature, pAuthInfo);
|
unpackServer(bKey, pChannelID, pHash, pSignature, pAuthInfo);
|
||||||
|
|
||||||
std::cout << "Validation results:\n Serial: 0x" << std::hex << std::setw(8) << std::setfill('0') << pChannelID << std::endl
|
if (options.verbose) {
|
||||||
<< " Hash: 0x" << std::hex << std::setw(8) << std::setfill('0') << pHash << std::endl
|
fmt::print("Validation results:\n");
|
||||||
<< " Signature: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSignature << std::endl
|
fmt::print(" Serial: 0x{:08x}\n", pChannelID);
|
||||||
<< " AuthInfo: 0x" << std::hex << std::setw(8) << std::setfill('0') << pAuthInfo << std::endl
|
fmt::print(" Hash: 0x{:08x}\n", pHash);
|
||||||
<< std::endl;
|
fmt::print(" Signature: 0x{:08x}\n", pSignature);
|
||||||
|
fmt::print(" AuthInfo: 0x{:08x}\n", pAuthInfo);
|
||||||
|
fmt::print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
BYTE msgDigest[SHA_DIGEST_LENGTH]{},
|
||||||
msgBuffer[SHA_MSG_LENGTH_2003]{},
|
msgBuffer[SHA_MSG_LENGTH_2003]{},
|
||||||
@ -294,19 +292,29 @@ void generateServerKey(
|
|||||||
// Pack product key.
|
// Pack product key.
|
||||||
packServer(pRaw, pChannelID, hash, pSignature, pAuthInfo);
|
packServer(pRaw, pChannelID, hash, pSignature, pAuthInfo);
|
||||||
|
|
||||||
std::cout << "Generation results:\n Serial: 0x" << std::hex << std::setw(8) << std::setfill('0') << pChannelID << std::endl
|
if (options.verbose) {
|
||||||
<< " Hash: 0x" << std::hex << std::setw(8) << std::setfill('0') << hash << std::endl
|
fmt::print("Generation results:\n");
|
||||||
<< " Signature: 0x" << std::hex << std::setw(8) << std::setfill('0') << pSignature << std::endl
|
fmt::print(" Serial: 0x{:08x}\n", pChannelID);
|
||||||
<< " AuthInfo: 0x" << std::hex << std::setw(8) << std::setfill('0') << pAuthInfo << std::endl
|
fmt::print(" Hash: 0x{:08x}\n", hash);
|
||||||
<< std::endl;
|
fmt::print(" Signature: 0x{:08x}\n", pSignature);
|
||||||
|
fmt::print(" AuthInfo: 0x{:08x}\n", pAuthInfo);
|
||||||
|
fmt::print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
EC_POINT_free(r);
|
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);
|
base24(pKey, (BYTE *)pRaw);
|
||||||
|
|
||||||
std::cout << "attempt pass " << pKey << " key is " << (wrong ? "INVALID" : "VALID") << std::endl;
|
|
||||||
|
|
||||||
BN_free(c);
|
BN_free(c);
|
||||||
BN_free(s);
|
BN_free(s);
|
||||||
BN_free(x);
|
BN_free(x);
|
||||||
@ -315,52 +323,3 @@ void generateServerKey(
|
|||||||
|
|
||||||
BN_CTX_free(numContext);
|
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<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["a"].get<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["b"].get<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["g"]["x"].get<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["g"]["y"].get<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["pub"]["x"].get<std::string>(),
|
|
||||||
keys["BINK"][BINKID]["pub"]["y"].get<std::string>(),
|
|
||||||
genPoint,
|
|
||||||
pubPoint
|
|
||||||
);
|
|
||||||
|
|
||||||
BN_dec2bn(&genOrder, keys["BINK"][BINKID]["n"].get<std::string>().c_str());
|
|
||||||
BN_dec2bn(&privateKey, keys["BINK"][BINKID]["priv"].get<std::string>().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;
|
|
||||||
}
|
|
||||||
|
@ -219,10 +219,13 @@ void generateXPKey(
|
|||||||
// Pack product key.
|
// Pack product key.
|
||||||
packXP(pRaw, pSerial, pHash, pSignature);
|
packXP(pRaw, pSerial, pHash, pSignature);
|
||||||
|
|
||||||
|
if (options.verbose) {
|
||||||
|
fmt::print("Generation results:\n");
|
||||||
fmt::print(" Serial: 0x{:08x}\n", pSerial);
|
fmt::print(" Serial: 0x{:08x}\n", pSerial);
|
||||||
fmt::print(" Hash: 0x{:08x}\n", pHash);
|
fmt::print(" Hash: 0x{:08x}\n", pHash);
|
||||||
fmt::print(" Signature: 0x{:08x}\n", pSignature);
|
fmt::print(" Signature: 0x{:08x}\n", pSignature);
|
||||||
fmt::print("\n");
|
fmt::print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
EC_POINT_free(r);
|
EC_POINT_free(r);
|
||||||
} while (pRaw[1] > BITMASK(50));
|
} while (pRaw[1] > BITMASK(50));
|
||||||
|
Loading…
Reference in New Issue
Block a user