Support GM61a
This commit is contained in:
parent
11c4b7a3ef
commit
2056d68f44
|
@ -18,9 +18,9 @@
|
||||||
<datafile>
|
<datafile>
|
||||||
<name>UGP.dll</name>
|
<name>UGP.dll</name>
|
||||||
<filename>UGP.dll</filename>
|
<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>
|
<exists>-1</exists>
|
||||||
<size>93696</size>
|
<size>97280</size>
|
||||||
<exportAction>2</exportAction>
|
<exportAction>2</exportAction>
|
||||||
<exportDir></exportDir>
|
<exportDir></exportDir>
|
||||||
<overwrite>0</overwrite>
|
<overwrite>0</overwrite>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -95,7 +95,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;UNIVERSALGAMEMAKERPATCHERDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;UNIVERSALGAMEMAKERPATCHERDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -2,5 +2,12 @@
|
||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<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>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -24,11 +24,8 @@ GMSTR GetMachineGuid(void)
|
||||||
|
|
||||||
GMSTR GenerateGM6Key(char* name) {
|
GMSTR GenerateGM6Key(char* name) {
|
||||||
uint8_t out_key[KEY_LEN];
|
uint8_t out_key[KEY_LEN];
|
||||||
|
|
||||||
keygen_gm6(name, out_key);
|
keygen_gm6(name, out_key);
|
||||||
|
|
||||||
key_to_string(out_key, gm6key, sizeof(gm6key));
|
key_to_string(out_key, gm6key, sizeof(gm6key));
|
||||||
|
|
||||||
return gm6key;
|
return gm6key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,33 @@
|
||||||
static char key_name[6];
|
static char key_name[6];
|
||||||
|
|
||||||
// The Mark Overmas Sequence.
|
// 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 add_multiply(uint8_t* key_arr) {
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
@ -65,7 +89,6 @@ void gen_checksum(uint8_t* key_arr) {
|
||||||
int curchk = key_arr[KEY_LEN - 1];
|
int curchk = key_arr[KEY_LEN - 1];
|
||||||
int chksum = add_multiply(key_arr);
|
int chksum = add_multiply(key_arr);
|
||||||
if (curchk != chksum) {
|
if (curchk != chksum) {
|
||||||
//printf("Updating checksum, %x -> %x\n", curchk, chksum);
|
|
||||||
key_arr[KEY_LEN - 1] = (uint8_t)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) {
|
void sanitize_name(char* namein, char* nameout) {
|
||||||
memset(nameout, 0, 6);
|
memset(nameout, 0, 6);
|
||||||
|
memcpy(nameout, namein, 5);
|
||||||
|
|
||||||
if (strlen(namein) != 5) {
|
if (strlen(namein) != 5) {
|
||||||
int sz = strlen(namein);
|
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 encode_name(char* name) {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
int multi = 1;
|
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;
|
encoded_time += 0x8EAE;
|
||||||
|
|
||||||
if (timed) {
|
if (timed) {
|
||||||
if (encoded_time != (exp_date + 0x8EAE)) {
|
if (encoded_time != exp_date + 0x8EAE) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (encoded_time - 0xA > get_current_date_delphi()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int is_timed = key_arr[0x2];
|
int is_timed = key_arr[0x2];
|
||||||
|
|
||||||
|
if (!(is_timed >= 0x1 && is_timed <= 0x20)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_timed >= 0xA && is_timed <= 0xF) {
|
if (is_timed >= 0xA && is_timed <= 0xF) {
|
||||||
if (!timed) {
|
if (!timed) {
|
||||||
return 0;
|
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) {
|
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)) {
|
if (check_checksum(key_arr)) {
|
||||||
|
|
||||||
uint8_t chk1;
|
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;
|
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];
|
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[0x1] = ((uint8_t*)(&encoded_time))[0];
|
||||||
keydata[0x0] = ((uint8_t*)(&encoded_time))[1];
|
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;
|
is_timed = (rand() % 0x6) + 0xA;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
is_timed = rand() % 0x100;
|
do {
|
||||||
if (is_timed >= 0xA && is_timed <= 0xF)
|
is_timed = (rand() % 0x20) + 1;
|
||||||
is_timed += 0x10;
|
} while (is_timed >= 0xA && is_timed <= 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
keydata[0x2] = is_timed;
|
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]);
|
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) {
|
void keygen_gm6(char* name, uint8_t* out_key) {
|
||||||
char checked_name[6];
|
char checked_name[6];
|
||||||
sanitize_name(name, checked_name);
|
sanitize_name(name, checked_name);
|
||||||
uint8_t keybuf[KEY_LEN];
|
uint8_t keybuf[KEY_LEN];
|
||||||
|
|
||||||
// the key data must survive the obfuscation step, while placing the chk1 and chk2 into the correct places
|
int chk1 = mark_overmars_seq[rand() % sizeof(mark_overmars_seq)];
|
||||||
// in the obfuscation steps, and the final checksum byte as well,
|
int chk2 = rand() % 0xFF;
|
||||||
// for this reason, key generation does not always work
|
uint32_t exp_date = (get_current_date_delphi() - 0xA) - 0x8EAE;
|
||||||
// so i simply retry forever until we find a key that does work.
|
|
||||||
|
|
||||||
while (1) {
|
gen_key_6(checked_name, chk1, chk2, exp_date, 0, keybuf);
|
||||||
int chk1 = mark_overmars_seq[rand() % sizeof(mark_overmars_seq)];
|
|
||||||
int chk2 = rand() % 0x100;
|
// Sanity check ...
|
||||||
int exp_date = rand() % 0xFFFF;
|
if (check_key_6(keybuf, checked_name, exp_date, 0)) {
|
||||||
|
memcpy(out_key, keybuf, KEY_LEN);
|
||||||
gen_key_6(checked_name, chk1, chk2, exp_date, 0, keybuf);
|
}
|
||||||
if (check_key_6(keybuf, checked_name, exp_date, 0)) {
|
else {
|
||||||
break;
|
keygen_gm6(name, out_key);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(out_key, keybuf, KEY_LEN);
|
|
||||||
}
|
}
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
srand(time(0));
|
srand(time(0));
|
||||||
|
|
||||||
char keystr[31];
|
char keystr[31];
|
||||||
uint8_t out_key[KEY_LEN];
|
uint8_t out_key[KEY_LEN];
|
||||||
keygen_gm6(argv[1], out_key);
|
keygen_gm6(argv[1], out_key);
|
||||||
key_to_string(out_key, keystr, sizeof(keystr));
|
key_to_string(out_key, keystr, sizeof(keystr));
|
||||||
printf("Key found: %s", keystr);
|
printf("Key found: %s", keystr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
|
|
||||||
|
|
||||||
int check_key_6(uint8_t* key_arr, char* name, uint32_t exp_date, uint32_t timed);
|
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 keygen_gm6(char* name, uint8_t* out_key);
|
||||||
void key_to_string(uint8_t* key, char* out_str, int buffer_sz);
|
void key_to_string(uint8_t* key, char* out_str, int buffer_sz);
|
Loading…
Reference in New Issue