↪ Jump to Section → [C++] Project64 Machine ID Generation

project64 nag removal

description
»  while Project64 is free to use, the developers have added a nag dialog, asking for donations.
»  this modification allows any registration code to be accepted, thus disabling the dialog.
»  the trick is to modify two conditional jump instructions; avoiding the rejection of invalid codes.

how to patch it yourself;
»  open primary executable (Project64.exe) in a hex editor
»  search & replace the original values with NOP (90) at these addresses;
—————————
— 00048448 // this block allows acceptance without internet connection
— 00048449
— 0004844A
— 0004844B
— 0004844C
— 0004844D

— 00048455 // this block is required
— 00048456
— 00048457
— 00048458
— 00048459
— 0004845A

— 00048560 // this block is required
— 00048561
—————————

for use of version; Project64 3.0.1-5664-2df3434

Quick How To Instructions;
»  Place "Project64_patched.exe" within the installation directory along side of "Project64.exe".
»  Run the patched executable. If the registration dialog doesn't automatically appear, then click on the tab Help->SupportProject64.
»  On this dialog you'll see a blue clickable link, this opens another dialog to enter in a unique registration code.
»  Enter any text into the box & click OK. If you're using the patched executable, it will accept the code.
»  A registry key is created for future registration validation.
»  You can now exit & continue to use the original unpatched executable.
»  Optionally, you can delete the patched executable, as it is no longer needed.
»  Now when you click the tab Help->SupportProject64, that once blue clickable link is now grey & disabled, meaning it is registered.
»  The support dialog with timer will no longer appear.

other info
»  the "Machine ID" is generated by using the computer's NAME, HDD SERIAL, & MachineGuid registry key combined, seperated by periods & then md5 hashed.

MD5 hashs
»  EC5B993905B89F85BB6A9BB718FDC603 Project64_original.exe
»  1ED2C0349482FE1D2F7A672C084EB299 Project64_patched.exe

executables;  Project64_original.exe  Project64_patched.exe

below is a screenshot with ollydbg for a better reference. ollydbg.png

[C++] Project64 Machine ID Generation

description
»  Here is a source code on how Project64 generates Machine ID in the registration process.

note
»  tested, working under Windows 7. compiled with mingw32.
»  Do not use speed optimization flags with the compiler as it will give inaccurate results.
»  The Machine ID consists of the PCName, HDD Serial, & Guid registry key, then performing a MD5 hash on them -- formatted like this: < PCName.HDDSERIAL.GUIDREG >
/*
*	[C++] Project64 Machine ID Generation
*	Written by Phillip Housden @ https://starwolf.net/
*/

#include <windows.h>
#include <iostream>

int main() {
	HKEY hKey;
	unsigned char dwReturn[64];
	for(int k=0; k<64; k++) dwReturn[k]=0x00;
	unsigned long dwBufSize=sizeof(dwReturn);

	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Cryptography",0,KEY_QUERY_VALUE | KEY_WOW64_64KEY,&hKey) == ERROR_SUCCESS) {
		if(RegQueryValueEx(hKey,"MachineGuid",0,0,dwReturn,&dwBufSize) == ERROR_SUCCESS) {
			//printf("\n%s\n",dwReturn);
		} else {
			printf("RegQueryValueEx Failed");
		}

		RegCloseKey(hKey);
	} else {
		printf("RegOpenKeyEx Failed");
	}

	unsigned long dwPCNAME;
	char szPCNAME[64];
	for(int y=0; y<64; y++) szPCNAME[y]=0x00;

	GetComputerName(szPCNAME,&dwPCNAME);

	char szMachineCode[128];
	for(int q=0; q<128; q++) szMachineCode[q]=0x00;

	unsigned long disk_serialINT;
	GetVolumeInformationA(NULL,NULL,0,&disk_serialINT,NULL,NULL,NULL,0);

	sprintf(szMachineCode,"%s.%lud.%s",szPCNAME,disk_serialINT,dwReturn);
	printf("\nString to MD5 hash: %s\n\n",szMachineCode);

	int iMachineCode=strlen(szMachineCode);

	HCRYPTPROV hProv=0;
	HCRYPTHASH hHash=0;

	unsigned char rgbHash[16];
	char rgbDigits[]="0123456789ABCDEF";
	CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT);
	CryptCreateHash(hProv,CALG_MD5,0,0,&hHash);

	unsigned char byteMachineCode[128];
	for(int q=0; q<128; q++) {
		byteMachineCode[q]=szMachineCode[q];
	}

	CryptHashData(hHash,byteMachineCode,iMachineCode,0);

	unsigned long cbHash=16;
	CryptGetHashParam(hHash,HP_HASHVAL,rgbHash,&cbHash,0);
	printf("Your unique Machine ID is: ");
	for (unsigned long i=0x00; i<cbHash; i++) {
		printf("%c%c",rgbDigits[rgbHash[i]>>4],rgbDigits[rgbHash[i]&0xf]);
	}

	CryptDestroyHash(hHash);
	CryptReleaseContext(hProv,0);

	printf("\n\n");

	system("pause");

	return 0;
}