51 Commits

Author SHA1 Message Date
49fefca596 Fix DOS compilation (Attempt 2) 2023-09-02 13:44:35 -04:00
178c9e0689 Fix DOS compilation (Attempt 1) 2023-09-02 13:43:03 -04:00
214d2d38a5 Merge pull request #68 from UMSKT/newline-fix 2023-09-02 13:16:56 -04:00
3ae078e3c5 update arg from nonewline to nonewlines 2023-09-02 11:53:09 -04:00
12e511b3a5 Update cli.cpp 2023-09-02 11:39:22 -04:00
21bac3b66c Update cli.cpp 2023-09-02 11:37:41 -04:00
09842ace12 Update cli.h 2023-09-02 11:37:38 -04:00
0d016b8872 Update cli.cpp 2023-09-02 11:31:25 -04:00
b1743f4bff fix name for FreeBSD 2023-09-02 11:17:52 -04:00
cc765edb4f Merge pull request #61 from UMSKT/workflow-update 2023-09-02 11:11:47 -04:00
4d1b5d6681 Update README.md 2023-09-02 11:11:16 -04:00
f59d77bdd1 Merge branch 'master' into workflow-update 2023-09-02 10:43:12 -04:00
71cbd19017 Add universal Confirmation ID 2023-09-02 10:42:26 -04:00
974f400cfc Revert "TEMP -- use -v" 2023-09-02 09:56:36 -04:00
a2d521c230 Update CMakeLists.txt 2023-09-02 09:55:20 -04:00
d53409f5bd TEMP -- use -v 2023-09-02 09:51:35 -04:00
2703e17f69 Update cli.cpp 2023-09-02 23:51:08 +10:00
680239bdb7 Merge branch 'cmake-fix' into master 2023-09-02 09:44:57 -04:00
104bdb19e3 Update confid.cpp 2023-09-02 23:33:47 +10:00
f2f859faeb Update confid.h 2023-09-02 23:27:02 +10:00
a2d9c46a4b Update libumskt.cpp 2023-09-02 23:25:14 +10:00
f65533bbb3 macOS build is not static 2023-09-02 09:24:04 -04:00
90e31b667a Update cli.h 2023-09-02 23:23:59 +10:00
492d245f86 Update cli.cpp
added CLI options for confirmation ID generation
2023-09-02 23:22:53 +10:00
361a39e204 Fix macOS compilation (Attempt 1) 2023-09-02 09:20:54 -04:00
31993afb62 Merge pull request #3 from UMSKT/master
FE and FF BINK exclusions
2023-09-02 23:03:17 +10:00
b3f64e6330 fix typo 2023-09-02 00:59:34 -04:00
ccf93a0089 Merge pull request #51 from UMSKT/fe-ff-fix
Add exclusions for FE and FF BINKs
2023-09-01 23:17:58 -04:00
ae391a5e50 Update cli.cpp 2023-09-01 22:43:32 -04:00
3620cf5af6 Update README.md 2023-09-01 19:54:08 -04:00
b7965f19e8 Delete test.md 2023-08-14 22:20:59 -04:00
52c9a57ea2 Create test.md 2023-08-14 22:16:07 -04:00
283df1c1fe Update linux.yml 2023-08-14 22:01:07 -04:00
c1eb81490b Update freebsd.yml 2023-08-14 22:01:01 -04:00
2ee6a99acd Update macos.yml 2023-08-14 22:00:58 -04:00
1370a6ecff Update windows.yml 2023-08-14 22:00:56 -04:00
e3a6b78407 Update dos-djgpp.yml 2023-08-14 21:59:25 -04:00
6ae5c9e435 Update windows.yml 2023-08-14 15:12:24 -04:00
a6bfaed6e8 Update macos.yml 2023-08-14 15:12:13 -04:00
f7b41a9810 Update linux.yml 2023-08-14 15:11:53 -04:00
e76eb7ac33 Update freebsd.yml 2023-08-14 15:11:35 -04:00
c91bbad69a Update dos-djgpp.yml 2023-08-14 15:11:17 -04:00
75e81e7049 Update dos-djgpp.yml 2023-08-14 15:09:41 -04:00
e9131e45c8 Update freebsd.yml 2023-08-14 15:09:16 -04:00
c664ea7f9c Update linux.yml 2023-08-14 15:08:52 -04:00
f95501b789 Update macos.yml 2023-08-14 15:08:24 -04:00
444f8c45c7 Allow manual workflows and auto workflows on all branches
This lets workflows work on all branches without changing anything, and allows workflows to be activated manually.
2023-08-14 15:07:24 -04:00
Neo
45004623be Why does the Github web editor commit tabs??? 2023-07-28 16:17:57 -07:00
Neo
a4cb524fed re-add removed comment 2023-07-28 16:16:31 -07:00
Neo
03ae90163a cleaner cli.cpp fix 2023-07-28 16:15:37 -07:00
c1e9a0f021 add exclusions for FE and FF 2023-07-28 18:10:25 -05:00
13 changed files with 382 additions and 90 deletions

View File

@ -22,9 +22,9 @@ name: C/C++ CI (DOS DJGPP)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
env:
CC: ${{ github.workspace }}/djgpp/bin/i586-pc-msdosdjgpp-gcc

View File

@ -22,9 +22,9 @@
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:

View File

@ -22,9 +22,9 @@ name: C/C++ CI (Linux)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build:

View File

@ -22,9 +22,9 @@ name: C/C++ CI (macOS)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build-x86:
@ -56,5 +56,5 @@ jobs:
- name: Upload build artifact
uses: actions/upload-artifact@v3.1.2
with:
name: UMSKT-macOS-${{ matrix.arch }}-static
name: UMSKT-macOS-${{ matrix.arch }}
path: build/actions_upload

View File

@ -22,9 +22,9 @@ name: C/C++ CI (Windows)
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches: [ "*" ]
paths-ignore: [ '**.md', 'doc/**', '.idea/**'] # If only these files are edited, skip
workflow_dispatch:
jobs:
build-32bit:

View File

@ -31,6 +31,16 @@ OPTION(MSVC_MSDOS_STUB "Specify a custom MS-DOS stub for a 32-bit MSVC compilati
SET(UMSKT_LINK_LIBS ${UMSKT_LINK_LIBS})
SET(UMSKT_LINK_DIRS ${UMSKT_LINK_DIRS})
# macOS does not support static build
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(UMSKT_USE_SHARED_OPENSSL ON)
endif()
# neither does dos idk i'm trying random stuff
if (DJGPP_WATT32)
SET(UMSKT_USE_SHARED_OPENSSL ON)
endif()
IF(UMSKT_USE_SHARED_OPENSSL)
SET(OPENSSL_USE_STATIC_LIBS FALSE)
SET(OPENSSL_MSVC_STATIC_RT FALSE)
@ -40,6 +50,8 @@ ELSE()
SET(OPENSSL_MSVC_STATIC_RT TRUE)
ENDIF()
IF(DJGPP_WATT32)
SET(CMAKE_SYSTEM_NAME MSDOS)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
@ -68,6 +80,16 @@ ELSE()
MESSAGE(STATUS "[UMSKT] Detected Static Library version of OpenSSL")
ENDIF()
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET(BUILD_SHARED_LIBS ON)
MESSAGE(STATUS "[UMSKT] macOS has no static library - Shared library forced on")
endif()
if (DJGPP_WATT32)
SET(BUILD_SHARED_LIBS ON)
MESSAGE(STATUS "[UMSKT] DOS has no static library - Shared library forced on")
endif()
# if we're compiling with MSVC, respect the DEBUG compile option
IF(MSVC)
SET(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

View File

@ -13,9 +13,9 @@
[![C/C++ CI (Linux)](https://github.com/UMSKT/UMSKT/actions/workflows/linux.yml/badge.svg)](../../actions/workflows/linux.yml)
[![C/C++ CI (FreeBSD)](https://github.com/UMSKT/UMSKT/actions/workflows/freebsd.yml/badge.svg)](../../actions/workflows/dos-djgpp.yml)
[![C/C++ CI (FreeBSD)](https://github.com/UMSKT/UMSKT/actions/workflows/freebsd.yml/badge.svg)](../../actions/workflows/freebsd.yml)
[![C/C++ CI (DOS DJGPP)](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/freebsd.yml)
[![C/C++ CI (DOS DJGPP)](https://github.com/UMSKT/UMSKT/actions/workflows/dos-djgpp.yml/badge.svg)](../../actions/workflows/dos-djgpp.yml)
------
@ -56,9 +56,13 @@ In light of the recent exponential interest in this project I've decided to put
* **Note:** Before continuing, please ensure you have the `umskt` executable extracted and on UNIX-like systems, have execution permissions (`chmod +x umskt`).
#### 2. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
#### 2. Install OpenSSL 3.1.2.
For Windows, click [here](https://slproweb.com/products/Win32OpenSSL.html) and choose the right version. For other operating systems, consult your package manager.
*Note: This only applies if the build you download has OpenSSL embedded (static library) or not. You can usually tell if the download size is measured in KB or MB. If it's MB, you don't need this.*
#### 3. *(Activation step for `Retail` and `OEM` only)*
#### 3. Run `umskt` to generate a key, or add `--help` or `-h` to see more options.
#### 4. *(Activation step for `Retail` and `OEM` only)*
* After installation, you will be prompted to activate Windows.

View File

@ -1531,7 +1531,7 @@
}
},
"Activation": {
"Windowws XP": {
"Windows XP": {
"p": "102011604035381881",
"x": {
"0": "0",

View File

@ -53,12 +53,15 @@ void CLI::showHelp(char *argv[]) {
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\n");
fmt::print("\t-i --instid\tinstallation ID used to generate confirmation ID\n");
fmt::print("\t-m --mode\tproduct family to activate.\n\t\t\tvalid options are \"WINDOWS\", \"OFFICEXP\", \"OFFICE2K3\", \"OFFICE2K7\" or \"PLUSDME\"\n\t\t\t(defaults to \"WINDOWS\")\n");
fmt::print("\t-p --productid\tthe product ID of the Program to activate. only required for Office 2K3 and Office 2K7 programs\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");
fmt::print("\t-s --serial\tspecifies a serial to use in the product ID (defaults to random, BINK1998 only)\n");
fmt::print("\t-u --upgrade\tspecifies the Product Key will be an \"Upgrade\" version\n");
fmt::print("\t-V --validate\tproduct key to validate signature\n");
fmt::print("\t-N --nonewlines\tdisables newlines (for easier embedding in other apps)\n");
fmt::print("\n");
}
@ -69,6 +72,7 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
"",
"",
"",
"",
640,
0,
1,
@ -78,12 +82,13 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
false,
false,
false,
MODE_BINK1998_GENERATE
false,
MODE_BINK1998_GENERATE,
WINDOWS
};
for (int i = 1; i < argc; i++) {
std::string arg = argv[i];
if (arg == "-v" || arg == "--verbose") {
options->verbose = true;
UMSKT::setDebugOutput(stderr);
@ -158,6 +163,28 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
options->instid = argv[i+1];
options->applicationMode = MODE_CONFIRMATION_ID;
i++;
} else if (arg == "-m" || arg == "--mode") {
std::string mode = argv[i+1];
char *p = &mode[0];
for (; *p; p++) {
*p = toupper((unsigned char)*p);
}
p = &mode[0];
if (strcmp(p, "WINDOWS") == 0) {
options->activationMode = WINDOWS;
} else if (strcmp(p, "OFFICEXP") == 0) {
options->activationMode = OFFICE_XP;
} else if (strcmp(p, "OFFICE2K3") == 0) {
options->activationMode = OFFICE_2K3;
} else if (strcmp(p, "OFFICE2K7") == 0) {
options->activationMode = OFFICE_2K7;
} else if (strcmp(p, "PLUSDME") == 0) {
options->activationMode = PLUS_DME;
}
i++;
} else if (arg == "-p" || arg == "--productid") {
options->productid = argv[i+1];
i++;
} else if (arg == "-V" || arg == "--validate") {
if (i == argc - 1) {
options->error = true;
@ -167,11 +194,19 @@ int CLI::parseCommandLine(int argc, char* argv[], Options* options) {
options->keyToCheck = argv[i+1];
options->applicationMode = MODE_BINK1998_VALIDATE;
i++;
} else if (arg == "-N" || arg == "--nonewlines") {
options->nonewlines = true;
} else {
options->error = true;
}
}
// make sure that a product id is entered for OFFICE_2K3 or OFFICE_2K7 IIDs
if ((options->activationMode == OFFICE_2K3 || options->activationMode == OFFICE_2K7) && options->productid == "") {
return options->error = true;
}
return !options->error;
}
@ -220,6 +255,12 @@ int CLI::validateCommandLine(Options* options, char *argv[], json *keys) {
int intBinkID;
sscanf(options->binkid.c_str(), "%x", &intBinkID);
// FE and FF are BINK 1998, but do not generate valid keys, so we throw an error
if (intBinkID >= 0xFE) {
fmt::print("ERROR: Terminal Services BINKs (FE and FF) are unsupported at this time\n");
return 1;
}
if (intBinkID >= 0x40) {
// set bink2002 validate mode if in bink1998 validate mode, else set bink2002 generate mode
options->applicationMode = (options->applicationMode == MODE_BINK1998_VALIDATE) ? MODE_BINK2002_VALIDATE : MODE_BINK2002_GENERATE;
@ -383,13 +424,8 @@ int CLI::BINK1998Generate() {
// generate a key
BN_sub(this->privateKey, this->genOrder, this->privateKey);
// Specify whether an upgrade version or not
bool bUpgrade = false;
if (options.upgrade == true)
bUpgrade = true;
for (int i = 0; i < this->total; i++) {
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, bUpgrade, this->pKey);
PIDGEN3::BINK1998::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, nRaw, options.upgrade, this->pKey);
bool isValid = PIDGEN3::BINK1998::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
if (isValid) {
@ -414,10 +450,9 @@ int CLI::BINK1998Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
}
@ -438,12 +473,7 @@ int CLI::BINK2002Generate() {
fmt::print("> AuthInfo: {}\n", pAuthInfo);
}
// Specify whether an upgrade version or not
bool bUpgrade = false;
if (options.upgrade == true)
bUpgrade = true;
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, bUpgrade, this->pKey);
PIDGEN3::BINK2002::Generate(this->eCurve, this->genPoint, this->genOrder, this->privateKey, pChannelID, pAuthInfo, options.upgrade, this->pKey);
bool isValid = PIDGEN3::BINK2002::Verify(this->eCurve, this->genPoint, this->pubPoint, this->pKey);
if (isValid) {
@ -468,9 +498,9 @@ int CLI::BINK2002Generate() {
if (this->options.verbose) {
fmt::print("\nSuccess count: {}/{}", this->count, this->total);
}
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
}
@ -515,7 +545,7 @@ int CLI::BINK2002Validate() {
int CLI::ConfirmationID() {
char confirmation_id[49];
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id);
int err = ConfirmationID::Generate(this->options.instid.c_str(), confirmation_id, options.activationMode, options.productid);
switch (err) {
case ERR_TOO_SHORT:
@ -544,9 +574,9 @@ int CLI::ConfirmationID() {
case SUCCESS:
fmt::print(confirmation_id);
#ifndef _WIN32
if (this->options.nonewlines == false) {
fmt::print("\n");
#endif
}
return 0;
default:

View File

@ -36,6 +36,14 @@
CMRC_DECLARE(umskt);
enum ACTIVATION_ALGORITHM {
WINDOWS = 0,
OFFICE_XP = 1,
OFFICE_2K3 = 2,
OFFICE_2K7 = 3,
PLUS_DME = 4,
};
enum MODE {
MODE_BINK1998_GENERATE = 0,
MODE_BINK2002_GENERATE = 1,
@ -49,6 +57,7 @@ struct Options {
std::string keysFilename;
std::string instid;
std::string keyToCheck;
std::string productid;
int channelID;
int serial;
int numKeys;
@ -58,8 +67,10 @@ struct Options {
bool help;
bool error;
bool list;
bool nonewlines;
MODE applicationMode;
ACTIVATION_ALGORITHM activationMode;
};
class CLI {

View File

@ -29,9 +29,25 @@
#include "confid.h"
#define MOD 0x16A6B036D7F2A79ULL
#define NON_RESIDUE 43
static const QWORD f[6] = {0, 0x21840136C85381ULL, 0x44197B83892AD0ULL, 0x1400606322B3B04ULL, 0x1400606322B3B04ULL, 1};
QWORD MOD = 0;
QWORD NON_RESIDUE = 0;
QWORD f[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
int productID1;
int productID2;
int productID3;
int productID4;
int activationMode;
int ConfirmationID::calculateCheckDigit(int pid)
{
unsigned int i = 0, j = 0, k = 0;
for (j = pid; j; i += k)
{
k = j % 10;
j /= 10;
}
return ((10 * pid) - (i % 7)) + 7;
}
QWORD ConfirmationID::residue_add(QWORD x, QWORD y)
{
@ -95,18 +111,65 @@ QWORD ConfirmationID::ui128_quotient_mod(QWORD lo, QWORD hi)
{
// hi:lo * ceil(2**170/MOD) >> (64 + 64 + 42)
QWORD prod1;
__umul128(lo, 0x604fa6a1c6346a87, &prod1);
switch (activationMode) {
case 0:
__umul128(lo, 0x604FA6A1C6346A87, &prod1);
break;
case 1:
case 2:
case 3:
__umul128(lo, 0x4FA8E4A40CDAE44A, &prod1);
break;
case 4:
__umul128(lo, 0x2C5C4D3654A594F0, &prod1);
}
QWORD part1hi;
QWORD part1lo = __umul128(lo, 0x2d351c6d04f8b, &part1hi);
QWORD part1lo;
switch (activationMode) {
case 0:
part1lo = __umul128(lo, 0x2D351C6D04F8B, &part1hi);
break;
case 1:
case 2:
case 3:
part1lo = __umul128(lo, 0x2CBAF12A59BBE, &part1hi);
break;
case 4:
part1lo = __umul128(lo, 0x2D36C691A4EA5, &part1hi);
}
QWORD part2hi;
QWORD part2lo = __umul128(hi, 0x604fa6a1c6346a87, &part2hi);
QWORD part2lo;
switch (activationMode) {
case 0:
part2lo = __umul128(hi, 0x604FA6A1C6346A87, &part2hi);
break;
case 1:
case 2:
case 3:
part2lo = __umul128(hi, 0x4FA8E4A40CDAE44A, &part2hi);
break;
case 4:
part2lo = __umul128(hi, 0x2C5C4D3654A594F0, &part2hi);
}
QWORD sum1 = part1lo + part2lo;
unsigned sum1carry = (sum1 < part1lo);
sum1 += prod1;
sum1carry += (sum1 < prod1);
QWORD prod2 = part1hi + part2hi + sum1carry;
QWORD prod3hi;
QWORD prod3lo = __umul128(hi, 0x2d351c6d04f8b, &prod3hi);
QWORD prod3lo;
switch (activationMode) {
case 0:
prod3lo = __umul128(hi, 0x2D351C6D04F8B, &prod3hi);
break;
case 1:
case 2:
case 3:
prod3lo = __umul128(hi, 0x2CBAF12A59BBE, &prod3hi);
break;
case 4:
prod3lo = __umul128(hi, 0x2D36C691A4EA5, &prod3hi);
}
prod3lo += prod2;
prod3hi += (prod3lo < prod2);
return (prod3lo >> 42) | (prod3hi << 22);
@ -619,6 +682,20 @@ void ConfirmationID::sha1_single_block(unsigned char input[64], unsigned char ou
output[16] = e >> 24; output[17] = e >> 16; output[18] = e >> 8; output[19] = e;
}
void ConfirmationID::decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version)
{
QWORD buffer[5];
int i;
for (i = 0; i < 5; i++)
memcpy(&buffer[i], (iid + (4 * i)), 4);
DWORD v1 = (buffer[3] & 0xFFFFFFF8) | 2;
DWORD v2 = ((buffer[3] & 7) << 29) | (buffer[2] >> 3);
QWORD hardwareIDVal = ((QWORD)v1 << 32) | v2;
for (i = 0; i < 8; ++i)
hwid[i] = (hardwareIDVal >> (8 * i)) & 0xFF;
*version = buffer[0] & 7;
}
void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize)
{
unsigned char sha1_input[64];
@ -628,11 +705,25 @@ void ConfirmationID::Mix(unsigned char* buffer, size_t bufSize, const unsigned c
int external_counter;
for (external_counter = 0; external_counter < 4; external_counter++) {
memset(sha1_input, 0, sizeof(sha1_input));
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(sha1_input, buffer + half, half);
memcpy(sha1_input + half, key, keySize);
sha1_input[half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100;
break;
case 2:
case 3:
sha1_input[0] = 0x79;
memcpy(sha1_input + 1, buffer + half, half);
memcpy(sha1_input + 1 + half, key, keySize);
sha1_input[1 + half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
}
sha1_single_block(sha1_input, sha1_result);
size_t i;
for (i = half & ~3; i < half; i++)
@ -654,11 +745,25 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
int external_counter;
for (external_counter = 0; external_counter < 4; external_counter++) {
memset(sha1_input, 0, sizeof(sha1_input));
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(sha1_input, buffer, half);
memcpy(sha1_input + half, key, keySize);
sha1_input[half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (half + keySize) * 8 / 0x100;
break;
case 2:
case 3:
sha1_input[0] = 0x79;
memcpy(sha1_input + 1, buffer, half);
memcpy(sha1_input + 1 + half, key, keySize);
sha1_input[1 + half + keySize] = 0x80;
sha1_input[sizeof(sha1_input) - 1] = (1 + half + keySize) * 8;
sha1_input[sizeof(sha1_input) - 2] = (1 + half + keySize) * 8 / 0x100;
}
sha1_single_block(sha1_input, sha1_result);
size_t i;
for (i = half & ~3; i < half; i++)
@ -671,8 +776,44 @@ void ConfirmationID::Unmix(unsigned char* buffer, size_t bufSize, const unsigned
}
}
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49])
int ConfirmationID::Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid)
{
int version;
unsigned char hardwareID[8];
activationMode = mode;
switch (activationMode) {
case 0:
MOD = 0x16A6B036D7F2A79;
NON_RESIDUE = 43;
f[0] = 0x0;
f[1] = 0x21840136C85381;
f[2] = 0x44197B83892AD0;
f[3] = 0x1400606322B3B04;
f[4] = 0x1400606322B3B04;
f[5] = 0x1;
break;
case 1:
case 2:
case 3:
MOD = 0x16E48DD18451FE9;
NON_RESIDUE = 3;
f[0] = 0x0;
f[1] = 0xE5F5ECD95C8FD2;
f[2] = 0xFF28276F11F61;
f[3] = 0xFB2BD9132627E6;
f[4] = 0xE5F5ECD95C8FD2;
f[5] = 0x1;
break;
case 4:
MOD = 0x16A5DABA0605983;
NON_RESIDUE = 2;
f[0] = 0x334F24F75CAA0E;
f[1] = 0x1392FF62889BD7B;
f[2] = 0x135131863BA2DB8;
f[3] = 0x153208E78006010;
f[4] = 0x163694F26056DB;
f[5] = 0x1;
}
unsigned char installation_id[19]; // 10**45 < 256**19
size_t installation_id_len = 0;
const char* p = installation_id_str;
@ -714,7 +855,23 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
return ERR_TOO_SHORT;
for (; installation_id_len < sizeof(installation_id); installation_id_len++)
installation_id[installation_id_len] = 0;
static const unsigned char iid_key[4] = {0x6A, 0xC8, 0x5E, 0xD4};
unsigned char iid_key[4] = { 0x0, 0x0, 0x0, 0x0 };
switch (activationMode) {
case 0:
case 4:
iid_key[0] = 0x6A;
iid_key[1] = 0xC8;
iid_key[2] = 0x5E;
iid_key[3] = 0xD4;
break;
case 1:
case 2:
case 3:
iid_key[0] = 0x5A;
iid_key[1] = 0x30;
iid_key[2] = 0xB9;
iid_key[3] = 0xF3;
}
Unmix(installation_id, totalCount == 41 ? 17 : 19, iid_key, 4);
if (installation_id[18] >= 0x10)
return ERR_UNKNOWN_VERSION;
@ -727,19 +884,65 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
unsigned short KeySHA1;
} parsed;
#pragma pack(pop)
switch (activationMode) {
case 0:
case 1:
case 4:
memcpy(&parsed, installation_id, sizeof(parsed));
unsigned productId1 = parsed.ProductIDLow & ((1 << 17) - 1);
unsigned productId2 = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1);
unsigned productId3 = (parsed.ProductIDLow >> 27) & ((1 << 25) - 1);
unsigned version = (parsed.ProductIDLow >> 52) & 7;
unsigned productId4 = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
if (version != (totalCount == 41 ? 4 : 5))
productID1 = parsed.ProductIDLow & ((1 << 17) - 1);
productID2 = (parsed.ProductIDLow >> 17) & ((1 << 10) - 1);
productID3 = (parsed.ProductIDLow >> 27) & ((1 << 24) - 1);
version = (parsed.ProductIDLow >> 51) & 15;
productID4 = (parsed.ProductIDLow >> 55) | (parsed.ProductIDHigh << 9);
switch (activationMode) {
case 0:
if (version != (totalCount == 41 ? 9 : 10))
return ERR_UNKNOWN_VERSION;
break;
case 1:
if (version != 1)
return ERR_UNKNOWN_VERSION;
break;
case 3:
if (version != 4)
return ERR_UNKNOWN_VERSION;
}
break;
case 2:
case 3:
decode_iid_new_version(installation_id, hardwareID, &version);
productID1 = stoi(productid.substr(0,5));
std::string channelid = productid.substr(6,3);
char *p = &channelid[0];
for (; *p; p++) {
*p = toupper((unsigned char)*p);
}
if (strcmp(&channelid[0], "OEM") == 0) {
productID2 = stoi(productid.substr(12,3));
productID3 = calculateCheckDigit((stoi(productid.substr(15,1)) * 100000) + (stoi(productid.substr(18,5))));
productID4 = (stoi((productid.substr(10,2))) / 100000) * 1000;
} else {
productID2 = stoi(productid.substr(6,3));
productID3 = stoi(productid.substr(10,7));
productID4 = stoi(productid.substr(18,5));
}
switch (activationMode) {
case 2:
if (version != 3)
return ERR_UNKNOWN_VERSION;
break;
case 3:
if (version != 4)
return ERR_UNKNOWN_VERSION;
}
memcpy(&parsed, hardwareID, 8);
break;
}
//printf("Product ID: %05u-%03u-%07u-%05u\n", productId1, productId2, productId3, productId4);
unsigned char keybuf[16];
memcpy(keybuf, &parsed.HardwareID, 8);
QWORD productIdMixed = (QWORD)productId1 << 41 | (QWORD)productId2 << 58 | (QWORD)productId3 << 17 | productId4;
QWORD productIdMixed = (QWORD)productID1 << 41 | (QWORD)productID2 << 58 | (QWORD)productID3 << 17 | productID4;
memcpy(keybuf + 8, &productIdMixed, 8);
TDivisor d;
@ -754,7 +957,16 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
} u;
u.lo = 0;
u.hi = 0;
switch (activationMode) {
case 0:
case 1:
case 4:
u.buffer[7] = attempt;
break;
case 2:
case 3:
u.buffer[6] = attempt;
}
Mix(u.buffer, 14, keybuf, 16);
QWORD x2 = ui128_quotient_mod(u.lo, u.hi);
QWORD x1 = u.lo - x2 * MOD;
@ -766,7 +978,18 @@ int ConfirmationID::Generate(const char* installation_id_str, char confirmation_
}
if (attempt > 0x80)
return ERR_UNLUCKY;
divisor_mul128(&d, 0x04e21b9d10f127c1, 0x40da7c36d44c, &d);
switch (activationMode) {
case 0:
divisor_mul128(&d, 0x04E21B9D10F127C1, 0x40DA7C36D44C, &d);
break;
case 1:
case 2:
case 3:
divisor_mul128(&d, 0xEFE0302A1F7A5341, 0x01FB8CF48A70DF, &d);
break;
case 4:
divisor_mul128(&d, 0x7C4254C43A5D1181, 0x01C61212ECE610, &d);
}
union {
struct {
QWORD encoded_lo, encoded_hi;

View File

@ -41,6 +41,7 @@ typedef struct {
} TDivisor;
EXPORT class ConfirmationID {
static int calculateCheckDigit(int pid);
static QWORD residue_add(QWORD x, QWORD y);
static QWORD residue_sub(QWORD x, QWORD y);
static QWORD __umul128(QWORD a, QWORD b, QWORD* hi);
@ -60,11 +61,12 @@ EXPORT class ConfirmationID {
static void divisor_mul128(const TDivisor* src, QWORD mult_lo, QWORD mult_hi, TDivisor* dst);
static unsigned rol(unsigned x, int shift);
static void sha1_single_block(unsigned char input[64], unsigned char output[20]);
static void decode_iid_new_version(unsigned char* iid, unsigned char* hwid, int* version);
static void Mix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
static void Unmix(unsigned char* buffer, size_t bufSize, const unsigned char* key, size_t keySize);
public:
static int Generate(const char* installation_id_str, char confirmation_id[49]);
static int Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid);
//EXPORT static int CLIRun();
};

View File

@ -27,8 +27,8 @@
#include "pidgen3/BINK2002.h"
#include "pidgen2/PIDGEN2.h"
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49]) {
return ConfirmationID::Generate(installation_id_str, confirmation_id);
FNEXPORT int ConfirmationID_Generate(const char* installation_id_str, char confirmation_id[49], int mode, std::string productid) {
return ConfirmationID::Generate(installation_id_str, confirmation_id, mode, productid);
}
FNEXPORT EC_GROUP* PIDGEN3_initializeEllipticCurve(char* pSel, char* aSel, char* bSel, char* generatorXSel, char* generatorYSel, char* publicKeyXSel, char* publicKeyYSel, EC_POINT *&genPoint, EC_POINT *&pubPoint) {