mirror of
https://silica.codes/BedrockReverse/MCEELoginSkip.git
synced 2025-04-06 05:05:47 +12:00
Doesn't actually change anything, just fixes some warnings. and adds more to the resource file
438 lines
12 KiB
C
438 lines
12 KiB
C
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#include <psapi.h>
|
|
#include <wchar.h>
|
|
#include <string.h>
|
|
#include <TlHelp32.h>
|
|
|
|
int* pointer_path;
|
|
int num_ptr;
|
|
|
|
/*
|
|
* Gets the base address of the main module for any process id
|
|
* I totally didnt steal this from StackOverflow.
|
|
*/
|
|
uintptr_t GetProcessBaseAddress(DWORD processId)
|
|
{
|
|
/*
|
|
* Open the process
|
|
*/
|
|
uintptr_t baseAddress = 0;
|
|
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processId);
|
|
HMODULE* moduleArray;
|
|
LPBYTE moduleArrayBytes;
|
|
DWORD bytesRequired;
|
|
|
|
if (processHandle)
|
|
{
|
|
// Enumarate through all process modules
|
|
if (EnumProcessModules(processHandle, NULL, 0, &bytesRequired))
|
|
{
|
|
if (bytesRequired)
|
|
{
|
|
moduleArrayBytes = (LPBYTE)LocalAlloc(LPTR, bytesRequired);
|
|
|
|
if (moduleArrayBytes)
|
|
{
|
|
int moduleCount;
|
|
|
|
moduleCount = bytesRequired / sizeof(HMODULE);
|
|
moduleArray = (HMODULE*)moduleArrayBytes;
|
|
|
|
|
|
// Get the first module in the process (main exe)
|
|
if (EnumProcessModules(processHandle, moduleArray, bytesRequired, &bytesRequired))
|
|
{
|
|
baseAddress = (uintptr_t)(moduleArray[0]);
|
|
}
|
|
|
|
LocalFree(moduleArrayBytes);
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle(processHandle);
|
|
}
|
|
|
|
return baseAddress;
|
|
}
|
|
|
|
/*
|
|
* Obtains a process id from
|
|
* a given executable name
|
|
* (eg, Minecraft.Windows.exe)
|
|
* Returns NULL if not found.
|
|
*/
|
|
DWORD GetProcId(WCHAR* name)
|
|
{
|
|
PROCESSENTRY32 entry;
|
|
entry.dwSize = sizeof(PROCESSENTRY32);
|
|
|
|
// Save a snapshot of all open processes
|
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
|
// Get the first process
|
|
if (Process32First(snapshot, &entry) == TRUE)
|
|
{
|
|
// Enumerate through all processes
|
|
while (Process32Next(snapshot, &entry) == TRUE)
|
|
{
|
|
// Check if the file name matches
|
|
if (wcscmp(entry.szExeFile, name) == 0)
|
|
{
|
|
return entry.th32ProcessID;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove the snapshot.
|
|
CloseHandle(snapshot);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Entry Point - Runs when the program starts
|
|
*/
|
|
int main(int argc, char* argv[])
|
|
{
|
|
FILE* ptr_file;
|
|
char MEE_POINTER_FILE[0x2048];
|
|
int LOGIN_STEP_VALUE = -1;
|
|
|
|
char* tmp;
|
|
#ifdef _WIN64
|
|
printf_s("!!! x64 Version can ONLY be used for the 64 Bit Versions of the game!\n");
|
|
#else
|
|
printf_s("!!! x86 Version can ONLY be used for the 32 Bit Versions of the game!\n");
|
|
#endif
|
|
|
|
/*
|
|
* Check for command line arguments:
|
|
*
|
|
* --help - Shows list of commands
|
|
* --ptr - Sets the filename to read pointer paths from
|
|
* --lstep - What to set the login step value to.
|
|
*/
|
|
|
|
strncpy_s(MEE_POINTER_FILE, 0x2048, "mee.ptr", 0x2048);
|
|
if(argc > 1)
|
|
{
|
|
for (int i = 0; i < argc; i++)
|
|
{
|
|
|
|
if (strcmp(argv[i], "--help") == 0)
|
|
{
|
|
printf_s("--ptr <mee.ptr file>\n");
|
|
printf_s("--lstep <custom login step value>\n");
|
|
return;
|
|
}
|
|
|
|
if(strcmp(argv[i],"--ptr") == 0)
|
|
strncpy_s(MEE_POINTER_FILE, 0x2048, argv[i+1], 0x2048);
|
|
|
|
if (strcmp(argv[i], "--lstep") == 0)
|
|
LOGIN_STEP_VALUE = strtol(argv[i + 1], &tmp, 10);
|
|
|
|
}
|
|
|
|
printf_s("MEE.PTR FILE : %s\nLOGIN STEP VALUE: %i\n", MEE_POINTER_FILE, LOGIN_STEP_VALUE);
|
|
}
|
|
|
|
/*
|
|
* Parse Pointer Path File (mee.ptr)
|
|
* ASCII Hex Numbers, seperated by " > "
|
|
* And converts it to a array of intergers.
|
|
*/
|
|
printf_s("Loading %s\n", MEE_POINTER_FILE);
|
|
if ((_access(MEE_POINTER_FILE, 0)) != -1) // If the mee.ptr file exists AND the process has permission to read it..
|
|
{
|
|
// Open the pointer file
|
|
fopen_s(&ptr_file, MEE_POINTER_FILE, "r");
|
|
|
|
/*
|
|
* This next part just gets the size
|
|
* of mee.ptr file
|
|
*/
|
|
|
|
// Seek to the end of the file
|
|
fseek(ptr_file, 0, SEEK_END);
|
|
// Get the current position
|
|
int sz = ftell(ptr_file)+1;
|
|
// Seek to the start of the file
|
|
fseek(ptr_file, 0, SEEK_SET);
|
|
|
|
/*
|
|
* Allocate a buffer the size of mee.ptr
|
|
* then read the contents of the mee.ptr file
|
|
* into that buffer
|
|
*/
|
|
|
|
// Allocate (sz) bytes of memory for the buffer.
|
|
char* file_contents = (char*)malloc(sz);
|
|
// Set the newly allocated buffer to all 0x00
|
|
memset(file_contents, 0x00, sz);
|
|
// Read the contents of mee.ptr into the buffer.
|
|
fread(file_contents, sz, 1, ptr_file);
|
|
|
|
/*
|
|
* Create a copy of the pointer path file buffer
|
|
* This is so we can scan through and mess with the pointers to it
|
|
* Without messing up the our original copy
|
|
*/
|
|
|
|
// Allocate (sz) bytes of memory for the buffer
|
|
char* work_buf = (char*)malloc(sz);
|
|
// Copy contents of previously read file into the new buffer
|
|
memcpy_s(work_buf, sz, file_contents, sz);
|
|
|
|
/*
|
|
* Count the total number of elements
|
|
* From mee.ptr file.
|
|
*/
|
|
|
|
// Set the total number of elements in the pointer path to 0
|
|
num_ptr = 0;
|
|
|
|
// Pointer to the next element, NULL for now.
|
|
char* next_token1 = NULL;
|
|
|
|
// Get a pointer to the first occurance of " > "
|
|
char* token = strtok_s(work_buf, " > ", &next_token1);
|
|
|
|
// Repeat this until there is no more " > " left
|
|
while (token != NULL) {
|
|
// Get the pointer to the next " > ".
|
|
token = strtok_s(NULL, " > ",&next_token1);
|
|
// Add 1 to the total number of elements
|
|
num_ptr ++;
|
|
}
|
|
|
|
// Free up memory used for counting the list of elements
|
|
free(work_buf);
|
|
|
|
/*
|
|
* Create a new 2nd copy of the pointer path file buffer
|
|
*/
|
|
|
|
// Allocate buffer the size of the mee.ptr file
|
|
work_buf = (char*)malloc(sz);
|
|
// Copy contents of mee.ptr file into new buffer
|
|
memcpy_s(work_buf, sz, file_contents, sz);
|
|
|
|
/*
|
|
* Allocate the memory required for the interger array
|
|
* Then convert each ASCII Hex Code to an int
|
|
* And store it in the pointer paths array.
|
|
*/
|
|
|
|
// Allocate memory buffer the size of the required int array
|
|
pointer_path = (int*)malloc(num_ptr * sizeof(int));
|
|
|
|
// Pointer to the next element, NULL for now.
|
|
char* next_token2 = NULL;
|
|
// Get the pointer to the first element (seperated by " > ")
|
|
char* ptrs = strtok_s(work_buf, " > ",&next_token2);
|
|
// Convert the ascii string to a int value, and put it into the int array
|
|
pointer_path[0] = (int)strtol(ptrs, &tmp, 16);
|
|
|
|
// Repeat until read all pointers
|
|
for(int i = 1; i < num_ptr; i++){
|
|
// Read the next element (seperated by " > ")
|
|
ptrs = strtok_s(NULL, " > ", &next_token2);
|
|
// Convert the ascii string to a int value, and put it into the int array
|
|
pointer_path[i] = (int)strtol(ptrs, &tmp, 16);
|
|
}
|
|
|
|
// Finally close the mee.ptr file
|
|
fclose(ptr_file);
|
|
|
|
// Free up memory used for reading the list of elements
|
|
free(work_buf);
|
|
// Free up memory used for the file contents
|
|
free(file_contents);
|
|
|
|
printf_s("Loaded %s!\n", MEE_POINTER_FILE);
|
|
}
|
|
else // If no mee.ptr file is found ... OR the process dont have permission to read it
|
|
{
|
|
// Set number of elements to a default number
|
|
num_ptr = 8;
|
|
// Allocate enough space for an int array of that size
|
|
pointer_path = (int*)malloc(num_ptr * sizeof(int));
|
|
#ifdef _WIN64 // This code is only included if the project is built as win64 version
|
|
printf_s("Failed, using default pointer path (MCEE 1.17.30 UWP x64)\n");
|
|
// Use a default pointer path.
|
|
pointer_path[0] = 0x3607D48;
|
|
pointer_path[1] = 0x0;
|
|
pointer_path[2] = 0x50;
|
|
pointer_path[3] = 0xA8;
|
|
pointer_path[4] = 0xE8;
|
|
pointer_path[5] = 0x0;
|
|
pointer_path[6] = 0x630;
|
|
pointer_path[7] = 0x10;
|
|
#else // if its NOT the win64 version..
|
|
printf_s("Failed, using default pointer path (MCEE 1.17.30 Win32 x86)\n");
|
|
// Use a default pointer path.
|
|
pointer_path[0] = 0x2CBF0FC;
|
|
pointer_path[1] = 0x0;
|
|
pointer_path[2] = 0x7C;
|
|
pointer_path[3] = 0x0;
|
|
pointer_path[4] = 0x68;
|
|
pointer_path[5] = 0xC;
|
|
pointer_path[6] = 0x2E4;
|
|
pointer_path[7] = 0x8;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Print the currently in use
|
|
* pointer path to the output of the terminal
|
|
*/
|
|
|
|
// Print "Pointer Path: "
|
|
printf_s("\nPointer Path: ");
|
|
for (int i = 0; i < num_ptr; i++) // Repeat for all elements in the path
|
|
{
|
|
// Print the hex encoding of the current element
|
|
printf_s("%x", pointer_path[i]);
|
|
if (i != num_ptr - 1) // if its not the last element
|
|
{
|
|
// Print " > "
|
|
printf_s(" > ");
|
|
}
|
|
}
|
|
// Print a newline
|
|
printf_s("\n");
|
|
|
|
/*
|
|
* This part is the part that actually patches
|
|
* Education edition's memory space
|
|
*/
|
|
|
|
// Process ID of minecraft educattion ediion application, (currently 0)
|
|
DWORD proc_id = 0;
|
|
printf_s("\nPlease open Minecraft Education Edition\n");
|
|
|
|
/*
|
|
* Repeatidly check if "Minecraft.Windows.exe" or "Minecraft.Win10.DX11.exe" is open
|
|
*/
|
|
while (proc_id == 0)
|
|
{
|
|
proc_id = GetProcId(L"Minecraft.Windows.exe"); // Try to get the process ID for "Minecraft.Windows"
|
|
if (proc_id == 0) // If the process ID is NULL (process not found)
|
|
proc_id = GetProcId(L"Minecraft.Win10.DX11.exe"); // Try to get the process ID for "Minecrat.Win10.DX11.exe"
|
|
}
|
|
// Print the process ID
|
|
printf_s("MCEE Process ID: %x\n", proc_id);
|
|
// Try to open the process.
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, proc_id);
|
|
// Print the process handle
|
|
printf_s("MCEE Process Handle: 0x%p\n", hProcess);
|
|
|
|
if (!hProcess) // If failed to open the process (eg no permission)
|
|
{
|
|
// Display a message box saying to try with admin rights
|
|
MessageBox(NULL, L"Cannot open process!\r\nTry \"Run as administrator\"", L"Error!", MB_OK + MB_ICONERROR);
|
|
}
|
|
else
|
|
{
|
|
// Base Address of the minecraft education edition process (NULL for now)
|
|
uintptr_t baseAddress = 0;
|
|
while(baseAddress == 0) // Repeat until the base address is not NULL.
|
|
// Try to get the base address of the Minecraft Education Edition Process
|
|
baseAddress = GetProcessBaseAddress(proc_id);
|
|
|
|
printf_s("MCEE Base Addr: 0x%p\n", (void*)baseAddress);
|
|
printf_s("Waiting for game to initalize....\n");
|
|
|
|
read_ptr_path:
|
|
|
|
// recalculate base address idk why but this seems to be required.
|
|
baseAddress = GetProcessBaseAddress(proc_id);
|
|
|
|
|
|
// Read first element
|
|
uintptr_t first_ptr = pointer_path[0];
|
|
uintptr_t cur_ptr = baseAddress + first_ptr;
|
|
uintptr_t ptr = 0;
|
|
uintptr_t new_ptr = 0;
|
|
|
|
// Read first element from the games memory
|
|
ReadProcessMemory(hProcess, (LPCVOID)cur_ptr, &ptr, sizeof(uintptr_t), 0);
|
|
if (ptr == 0)
|
|
goto read_ptr_path;
|
|
|
|
|
|
/*
|
|
* Follow all elements
|
|
* in the path, until you reach
|
|
* the pointer to the login step value.
|
|
*/
|
|
for (int i = 1; i < num_ptr-1; i++)
|
|
{
|
|
cur_ptr = ptr + pointer_path[i];
|
|
ReadProcessMemory(hProcess, (LPCVOID)cur_ptr, &new_ptr, sizeof(uintptr_t), 0);
|
|
if (new_ptr == 0) {
|
|
i -= 1;
|
|
goto read_ptr_path;
|
|
}
|
|
else
|
|
{
|
|
ptr = new_ptr;
|
|
|
|
}
|
|
}
|
|
|
|
// final addition
|
|
ptr += pointer_path[num_ptr-1];
|
|
|
|
// Wait for Welcome Screen.
|
|
int login_step_value = 0;
|
|
ReadProcessMemory(hProcess, (LPCVOID)ptr, &login_step_value, sizeof(int), 0);
|
|
|
|
if (login_step_value != 0x0)
|
|
{
|
|
|
|
printf_s("Final Ptr: 0x%p\n", (void*)ptr);
|
|
|
|
printf_s("Current Login Step: %i\n", login_step_value);
|
|
if (LOGIN_STEP_VALUE != -1)
|
|
{
|
|
printf_s("Trying login stage %i", LOGIN_STEP_VALUE);
|
|
WriteProcessMemory(hProcess, (LPVOID)ptr, &LOGIN_STEP_VALUE, sizeof(int), 0);
|
|
goto finish;
|
|
}
|
|
|
|
printf_s("Trying login stage 5...\n"); // Backwards Comp (0.xx)
|
|
int login_step_value = 5;
|
|
WriteProcessMemory(hProcess, (LPVOID)ptr, &login_step_value, sizeof(int), 0);
|
|
|
|
Sleep(1 * 200);
|
|
|
|
printf_s("Trying login stage 6...\n"); // Backwards Comp (1.9 and lower)
|
|
login_step_value = 6;
|
|
WriteProcessMemory(hProcess, (LPVOID)ptr, &login_step_value, sizeof(int), 0);
|
|
|
|
Sleep(1 * 200);
|
|
|
|
printf_s("Trying login stage 8...\n");
|
|
login_step_value = 8;
|
|
WriteProcessMemory(hProcess, (LPVOID)ptr, &login_step_value, sizeof(int), 0);
|
|
|
|
}
|
|
else
|
|
goto read_ptr_path;
|
|
|
|
finish:
|
|
|
|
|
|
CloseHandle(hProcess);
|
|
|
|
printf_s("\nBlessed Be!\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|