Support GM61a

This commit is contained in:
Li 2022-07-08 21:57:26 +12:00
parent 11c4b7a3ef
commit 2056d68f44
18 changed files with 97 additions and 31 deletions

View File

@ -18,9 +18,9 @@
<datafile>
<name>UGP.dll</name>
<filename>UGP.dll</filename>
<origname>C:\Users\User\Documents\git\UGP\UGP.gmx\\\datafiles\UGP.dll</origname>
<origname>C:\Users\User\Documents\git\UGP\UGP.gmx\datafiles\UGP.dll</origname>
<exists>-1</exists>
<size>93696</size>
<size>97280</size>
<exportAction>2</exportAction>
<exportDir></exportDir>
<overwrite>0</overwrite>

Binary file not shown.

View File

@ -95,7 +95,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;UNIVERSALGAMEMAKERPATCHERDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>

View File

@ -2,5 +2,12 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommand>C:\Users\User\Desktop\UGP\UGP\UGP.exe</LocalDebuggerCommand>
<LocalDebuggerWorkingDirectory>C:\Users\User\Desktop\UGP\UGP</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommand>C:\Users\User\Desktop\UGP\UGP\UGP.exe</LocalDebuggerCommand>
<LocalDebuggerWorkingDirectory>C:\Users\User\Desktop\UGP\UGP</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@ -24,11 +24,8 @@ GMSTR GetMachineGuid(void)
GMSTR GenerateGM6Key(char* name) {
uint8_t out_key[KEY_LEN];
keygen_gm6(name, out_key);
key_to_string(out_key, gm6key, sizeof(gm6key));
return gm6key;
}

View File

@ -3,9 +3,33 @@
static char key_name[6];
// The Mark Overmas Sequence.
const uint8_t mark_overmars_seq[0x29] = { 0x01, 0x07, 0x11, 0x17, 0x19, 0x1b, 0x24, 0x27, 0x2b, 0x31, 0x33, 0x3d, 0x3f, 0x4d, 0x53, 0x59, 0x5e, 0x63, 0x68, 0x69, 0x76, 0x7f, 0x89, 0x8b, 0x97, 0x9b, 0x9e, 0xA6, 0xB9, 0xBD, 0xBF, 0xC6, 0xC9, 0xD3, 0xD6, 0xDE, 0xE5, 0xEA, 0xEB, 0xF5, 0xF9 };
const uint8_t mark_overmars_seq[0x30] = { 0x01,0x07,0x11,0x17,0x19,0x1b,0x24,0x27,0x2b,0x31,0x33,0x3d,0x3f,0x4d,0x53,0x59,0x5e,0x63,0x68,0x69,0x76,0x7f,0x89,0x8b,0x95,0x97,0x9b,0x9e,0xa6,0xb9,0xbd,0xbf,0xc6,0xc9,0xd3,0xd6,0xde,0xe5,0xea,0xeb,0xf5,0xf9 };
const uint8_t blacklisted_keys[0x6][0x8] = {
{0xFF, 0xDF, 0x0A, 0xFF, 0xD3, 0x05, 0x7F, 0x24},
{0x04, 0x22, 0xDA, 0xEE, 0x19, 0x79, 0xEE, 0x61},
{0x24, 0xB4, 0x48, 0x5C, 0x5B, 0xDB, 0x29, 0x22},
{0xB6, 0x15, 0xEA, 0x32, 0xBC, 0x16, 0xFB, 0xAF},
{0x1E, 0x9E, 0xCE, 0x56, 0x12, 0xAD, 0x9D, 0x48},
{0x9E, 0x6E, 0x3F, 0x8C, 0xD4, 0x36, 0x22, 0xEA}
};
int is_blacklisted(uint8_t* key) {
for (int i = 0; i < 0x6; i++) {
if (memcmp(blacklisted_keys[i], key, 0x8) == 0)
return 1;
}
if (key[0x00] == 0xE3 &&
key[0x05] == 0x7A &&
key[0x06] == 0xD9 &&
key[0x07] == 0xE3 &&
key[0x08] == 0x06) {
return 1;
}
return 0;
}
int add_multiply(uint8_t* key_arr) {
int sum = 0;
@ -65,7 +89,6 @@ void gen_checksum(uint8_t* key_arr) {
int curchk = key_arr[KEY_LEN - 1];
int chksum = add_multiply(key_arr);
if (curchk != chksum) {
//printf("Updating checksum, %x -> %x\n", curchk, chksum);
key_arr[KEY_LEN - 1] = (uint8_t)chksum;
}
@ -202,6 +225,7 @@ char* decode_name(int encoded_name)
void sanitize_name(char* namein, char* nameout) {
memset(nameout, 0, 6);
memcpy(nameout, namein, 5);
if (strlen(namein) != 5) {
int sz = strlen(namein);
@ -232,6 +256,11 @@ void sanitize_name(char* namein, char* nameout) {
}
int get_current_date_delphi() {
double t = (((((double)time(0)) + 0.5) / 86400.0) + 25569.0);
return (int)t;
}
int encode_name(char* name) {
int total = 0;
int multi = 1;
@ -258,13 +287,22 @@ int final_key_check(uint8_t* key_arr, char* name, uint8_t chk2, uint8_t chk1, ui
encoded_time += 0x8EAE;
if (timed) {
if (encoded_time != (exp_date + 0x8EAE)) {
if (encoded_time != exp_date + 0x8EAE) {
return 0;
}
}
if (encoded_time - 0xA > get_current_date_delphi()) {
return 0;
}
int is_timed = key_arr[0x2];
if (!(is_timed >= 0x1 && is_timed <= 0x20)) {
return 0;
}
if (is_timed >= 0xA && is_timed <= 0xF) {
if (!timed) {
return 0;
@ -341,6 +379,11 @@ void obfuscate_key(uint8_t* key_arr, uint8_t* out_key, int chk2, int chk1) {
}
int check_key_6(uint8_t* key_arr, char* name, uint32_t exp_date, uint32_t timed) {
// Did we win the lottery?
if (is_blacklisted(key_arr)) {
return 0;
}
if (check_checksum(key_arr)) {
uint8_t chk1;
@ -355,7 +398,7 @@ int check_key_6(uint8_t* key_arr, char* name, uint32_t exp_date, uint32_t timed)
return 0;
}
void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint32_t exp_date, uint32_t timed, uint8_t* out_key) {
void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint16_t exp_date, uint32_t timed, uint8_t* out_key) {
uint8_t keydata[KEY_LEN];
@ -374,7 +417,7 @@ void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint32_t exp_date, uint32
int encoded_time = exp_date - 0x8EAE;
uint16_t encoded_time = exp_date;
keydata[0x1] = ((uint8_t*)(&encoded_time))[0];
keydata[0x0] = ((uint8_t*)(&encoded_time))[1];
@ -383,9 +426,9 @@ void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint32_t exp_date, uint32
is_timed = (rand() % 0x6) + 0xA;
}
else {
is_timed = rand() % 0x100;
if (is_timed >= 0xA && is_timed <= 0xF)
is_timed += 0x10;
do {
is_timed = (rand() % 0x20) + 1;
} while (is_timed >= 0xA && is_timed <= 0xF);
}
keydata[0x2] = is_timed;
@ -401,40 +444,59 @@ void key_to_string(uint8_t* key, char* out_str, int buffer_sz) {
snprintf(out_str, buffer_sz, "%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", key[0x0], key[0x1], key[0x2], key[0x3], key[0x4], key[0x5], key[0x6], key[0x7], key[0x8], key[0x9], key[0xA], key[0xB]);
}
void bruteforce_mark_seq(void* name) {
char checked_name[6];
sanitize_name(name, checked_name);
uint8_t keybuf[KEY_LEN];
for (int chk1 = 0; chk1 < 0xFF; chk1++) {
int chk1_valid = 0;
for (int chk2 = 0; chk2 < 0xFF; chk2++) {
uint32_t exp_date = (get_current_date_delphi() - 0xA) - 0x8EAE;
gen_key_6(checked_name, chk1, chk2, exp_date, 0, keybuf);
if (check_key_6(keybuf, checked_name, exp_date, 0)) {
chk1_valid++;
}
}
if (chk1_valid == 0xFF)
printf("found part of seq; 0x%x c = 0x%x\n", chk1, chk1_valid);
}
}
void keygen_gm6(char* name, uint8_t* out_key) {
char checked_name[6];
sanitize_name(name, checked_name);
uint8_t keybuf[KEY_LEN];
// the key data must survive the obfuscation step, while placing the chk1 and chk2 into the correct places
// in the obfuscation steps, and the final checksum byte as well,
// for this reason, key generation does not always work
// so i simply retry forever until we find a key that does work.
int chk1 = mark_overmars_seq[rand() % sizeof(mark_overmars_seq)];
int chk2 = rand() % 0xFF;
uint32_t exp_date = (get_current_date_delphi() - 0xA) - 0x8EAE;
while (1) {
int chk1 = mark_overmars_seq[rand() % sizeof(mark_overmars_seq)];
int chk2 = rand() % 0x100;
int exp_date = rand() % 0xFFFF;
gen_key_6(checked_name, chk1, chk2, exp_date, 0, keybuf);
if (check_key_6(keybuf, checked_name, exp_date, 0)) {
break;
}
gen_key_6(checked_name, chk1, chk2, exp_date, 0, keybuf);
// Sanity check ...
if (check_key_6(keybuf, checked_name, exp_date, 0)) {
memcpy(out_key, keybuf, KEY_LEN);
}
else {
keygen_gm6(name, out_key);
}
memcpy(out_key, keybuf, KEY_LEN);
}
#ifdef STANDALONE
int main(int argc, char* argv[]) {
srand(time(0));
char keystr[31];
uint8_t out_key[KEY_LEN];
keygen_gm6(argv[1], out_key);
key_to_string(out_key, keystr, sizeof(keystr));
printf("Key found: %s", keystr);
return 0;
}
}
#endif

View File

@ -10,6 +10,6 @@
int check_key_6(uint8_t* key_arr, char* name, uint32_t exp_date, uint32_t timed);
void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint32_t exp_date, uint32_t timed, uint8_t* out_key);
void gen_key_6(char* name, uint8_t chk1, uint8_t chk2, uint16_t exp_date, uint32_t timed, uint8_t* out_key);
void keygen_gm6(char* name, uint8_t* out_key);
void key_to_string(uint8_t* key, char* out_str, int buffer_sz);