/// <summary> /// Initializes the in-game objects so they can be managed using the API. /// </summary> protected void Initialize() { try { active = true; memoryManager = new MemoryManager(process); while (!initialized && active) { if (GetCurrentMenu() != 0 && GetCurrentMenu() != Menu.Loading && GetCurrentMenu() != Menu.Initializing) { initialized = true; // Core functionality is now initialized InitializedType = InitializedType.Core; Initialized(InitializedType.Core); while (active && !IsRaceRunning) { // Wait until a race has been started so the drivers can be initialized Thread.Sleep((int)Settings.RefreshRate); } if (!active) // When the client closes before a race has been started return; // Stop initializing do { // Reset the player to a null value to prevent a memory overflow Player = null; // There is a small time between the starting of a race and the actual start, // so the thread will continue to run for a small time until the local players X-coordinate // is actually filled with correct data, which is a good way to test if the race has actually been started. Player = new Player(memoryManager, DRIVER_BASE, PLAYER_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); Thread.Sleep((int)Settings.RefreshRate); } while (active && (Player == null || Player.X == 0)); Opponents = new Opponent[5]; Opponents[0] = new Opponent(memoryManager, DRIVER_BASE, ENEMY_1_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); Opponents[1] = new Opponent(memoryManager, DRIVER_BASE, ENEMY_2_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); Opponents[2] = new Opponent(memoryManager, DRIVER_BASE, ENEMY_3_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); Opponents[3] = new Opponent(memoryManager, DRIVER_BASE, ENEMY_4_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); Opponents[4] = new Opponent(memoryManager, DRIVER_BASE, ENEMY_5_BASE_OFFSETS, DRIVER_OFFSET_COORDINATE_X, DRIVER_OFFSET_COORDINATE_Y, DRIVER_OFFSET_COORDINATE_Z, DRIVER_OFFSET_SPEED_X, DRIVER_OFFSET_SPEED_Y, DRIVER_OFFSET_SPEED_Z, DRIVER_OFFSET_VECTOR_X1, DRIVER_OFFSET_VECTOR_Y1, DRIVER_OFFSET_VECTOR_Z1, DRIVER_OFFSET_VECTOR_X2, DRIVER_OFFSET_VECTOR_Y2, DRIVER_OFFSET_VECTOR_Z2, DRIVER_OFFSET_BRICK, DRIVER_OFFSET_WHITEBRICKS, POWERUP_RED_ADDRESS, POWERUP_BLUE_ADDRESS, POWERUP_GREEN_ADDRESS, POWERUP_YELLOW_ADDRESS); InitializedType = InitializedType.Both; Initialized(InitializedType.Drivers); } Thread.Sleep((int)Settings.RefreshRate); } } catch (Exception exc) { Console.WriteLine(exc); } }
private void ClientForm_Load(object sender, EventArgs e) { try { engineInitialized = false; sentLastUsedPowerUp = true; powerUpsUsed = new int[5]; for (int i = 0; i < 5; i++) { powerUpsUsed[i] = 0; } gameClient = GameClientFactory.GetGameClient(gameProcess); gameClient.Initialized += gameClient_Initialized; participants = new List<Participant>(); // Set the amount of players to zero playerCount = 0; // Create a new Player object that is going to hold the local Player information participant = new Participant() { Nickname = "Player" }; if (!Toolbox.IsAdministrator()) { throw new Win32Exception(); } for (int i = 0; i < dataGridPlayers.Columns.Count; i++) { dataGridPlayers.Columns[i].Visible = false; } mainModule = gameProcess.MainModule; memoryManager = new MemoryManager(gameProcess); //codeInjector = new CodeInjector(memoryManager); SetStatus("Not Connected"); clientState = ClientState.Disconnected; // Creates and starts a new thread that will be responsible for updating the client thread = new Thread(UpdateClient); thread.Start(); } catch (Win32Exception) { // The Client was (probably) not started with Administrator rights MessageBox.Show("Error while finding LEGO Racers process. Please restart the application with Administrator rights.", "Error"); Close(); } catch (Exception exc) { // An unknown error occured ErrorHandler.ShowDialog("Failed to initialize", "The Client failed to initialize.", exc); Close(); } }
private UInt32 GetMenuStringsAddress(int line) { // code from 0x0044E500 uint ecx = MemoryManager.ReadUInt(MemoryManager.ReadUInt(MemoryManager.ReadUInt(MemoryManager.ReadUInt(0x004c4918) + 0x4dc8) + 0x354) + 0x4d00); short offset = MemoryManager.ReadShort((UInt32)(ecx + line * 2)); int filestart = MemoryManager.ReadInt(MemoryManager.ReadUInt(MemoryManager.ReadUInt(MemoryManager.ReadUInt(0x004c4918) + 0x4dc8) + 0x354) + 0x4cfc); return((UInt32)(filestart + offset * 2)); }
/// <summary> /// Selects a race. /// </summary> /// <param name="circuit">The race circuit number to select.</param> /// <param name="race">The race number to select.</param> public void SelectRace(int circuit, int race) { if (initialized) { MemoryManager.WriteInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, SELECTED_CIRCUIT_OFFSETS), MemoryManager.ReadInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, CIRCUIT_BASE_OFFSETS)) + 100 * circuit); MemoryManager.WriteInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, SELECTED_RACE_OFFSETS), race); } }
/// <summary> /// Navigates to a given menu. /// </summary> /// <param name="targetmenu">The menu to navigate to.</param> public void GotoMenu(Menu targetmenu) { if (initialized) { Menu currentMenu = GetCurrentMenu(); Console.WriteLine(currentMenu + " -> " + targetmenu); int offset = 0; int ECXbase = MemoryManager.ReadInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, TARGETMENU_ECX_OFFSET)); int ESIbase = MemoryManager.ReadInt(MemoryManager.CalculatePointer(MENU_BASEADDRESS, TARGETMENU_ESI_OFFSET)); if (ECXbase != ESIbase) // if a prompt is open { switch (currentMenu) { case Menu.Options: if (targetmenu == Menu.DisplayOptions) { offset = 0x549C; } break; case Menu.Build: // delete racer if (targetmenu == Menu.PromptYes) { offset = 0x5B38; } else if (targetmenu == Menu.PromptNo) { offset = 0x5E28; } break; case Menu.CreateDriver: // cancel if (targetmenu == Menu.PromptYes) { offset = 0x3FD0; } else if (targetmenu == Menu.PromptNo) { offset = 0x42C0; } break; default: return; } } else { switch (currentMenu) { case Menu.MainMenu: if (targetmenu == Menu.Build) { offset = 0x1058; } else if (targetmenu == Menu.SingleRace) { offset = 0x498; } else if (targetmenu == Menu.Options) { offset = 0x1348; } else if (targetmenu == Menu.TimeAttack) { offset = 0xD68; } else if (targetmenu == Menu.Circuit) { offset = 0x788; } else { return; } break; case Menu.Build: if (targetmenu == Menu.MainMenu) { offset = 0x5848; } else if (targetmenu == Menu.CreateDriver) { offset = 0x40C8; } else if (targetmenu == Menu.DeleteRacer) // opens a prompt { offset = 0x4999; } else if (targetmenu == Menu.EditRacer) // Not finished { offset = 0x43B8; } else if (targetmenu == Menu.CopyRacer) { offset = 0x46A8; } else { return; } break; case Menu.Options: if (targetmenu == Menu.MainMenu) { offset = 0x18D8; } else if (targetmenu == Menu.ControlsP1) { offset = 0xA28; } else if (targetmenu == Menu.ControlsP2) { offset = 0xD18; } else if (targetmenu == Menu.GameOptions) { offset = 0x448; } else if (targetmenu == Menu.PromptDisplayOptions) // opens a prompt { offset = 0x51AC; } else if (targetmenu == Menu.Options) // currentmenu==DisplayOptions or GameOptions { offset = 0x18D8; } else { return; } break; case Menu.Controls: if (targetmenu == Menu.Options) { offset = 0x47C; } else { return; } break; case Menu.SingleRace: if (targetmenu == Menu.MainMenu) { offset = 0x1CCC; } else if (targetmenu == Menu.ChooseRacer) { offset = 0x19DC; } else { return; } break; case Menu.TimeAttack: if (targetmenu == Menu.MainMenu) { offset = 0x1CC; } else { return; } break; case Menu.Circuit: if (targetmenu == Menu.MainMenu) { offset = 0x1c34; } else if (targetmenu == Menu.ChooseRacer) { offset = 0x1F24; } else { return; } break; case Menu.CreateDriver: if (targetmenu == Menu.CancelDriver) // opens a prompt { offset = 0x39F0; } else if (targetmenu == Menu.CreateLicense) { offset = 0x3CE0; } else { return; } break; case Menu.CreateLicense: if (targetmenu == Menu.CreateDriver) { offset = 0xA88; } else if (targetmenu == Menu.BuildCar) { offset = 0xD78; } else { return; } break; case Menu.BuildCar: if (targetmenu == Menu.Build) { offset = 0x11E4; } else if (targetmenu == Menu.CreateLicense) { offset = 0x14D4; } else { return; } break; case Menu.ChooseRacer: if (targetmenu == Menu.Circuit || targetmenu == Menu.SingleRace || targetmenu == Menu.TimeAttack) { offset = 0x4998; } else if (targetmenu == Menu.StartRace) { offset = 0x40C8; } else { return; } break; default: return; } } List <byte> codeToInject = new List <byte>(); codeToInject.Add(0xB9); codeToInject.AddRange(BitConverter.GetBytes(ECXbase)); // mov ecx,neededECX codeToInject.Add(0xBE); codeToInject.AddRange(BitConverter.GetBytes(ESIbase + offset)); // mov esi,neededESI codeToInject.AddRange(new byte[] { 0x8B, 0x11, 0x56, 0xFF, 0x52, 0x38, 0xC3 }); // mov edx,[ecx] | push esi | call dword ptr [edx+38] | ret // Write code to the assigned memory and execute it MemoryManager.WriteBytes(MemoryManager.NewMemory, codeToInject.ToArray()); MemoryManager.CreateThread(MemoryManager.NewMemory); } }
/// <summary> /// Safely unloads the API. /// </summary> public void Unload() { this.active = false; Thread.Sleep((int)Settings.RefreshRate); MemoryManager.Unload(); }