/// <summary> /// Inject x86 assembly into the target process and execute it /// </summary> /// <param name="asm">Assembly code to inject</param> /// <returns>true if the code was injected. Otherwise false.</returns> /// <exception cref="HookNotAppliedException">Thrown when the required hook has not been applied</exception> private static void InjectAndExecute(IEnumerable <string> asm) { lock (LockObject) { if (!_isApplied) { throw new HookNotAppliedException("Tried to inject code when the Hook was not applied"); } //Lets Inject the passed ASM Inject(asm, _allocatedMemory["codeCavePtr"]); _allocatedMemory.Write("addressInjection", _allocatedMemory["codeCavePtr"]); Stopwatch timer = Stopwatch.StartNew(); while (_allocatedMemory.Read <int>("addressInjection") > 0) { Thread.Sleep(1); if (timer.ElapsedMilliseconds >= 10000) { throw new CodeInjectionFailedException("Failed to inject code after 10 seconds. Last Error: " + Marshal.GetLastWin32Error()); } } // Wait to launch code _allocatedMemory.WriteBytes("codeCavePtr", Eraser); } }
/// <summary> /// 在游戏进程中执行给出的指令 /// </summary> /// <param name="command">需要执行的指令</param> private void DoTextCommand(string command) { if (FFXIV == null) { PluginUI.Log("执行错误:接收到指令,但是没有对应的游戏进程"); throw new Exception("没有对应的游戏进程"); } PluginUI.Log(command); if (command == "") { throw new Exception("指令为空"); } var assemblyLock = Memory.Executor.AssemblyLock; var flag = false; try { Monitor.Enter(assemblyLock, ref flag); var array = Encoding.UTF8.GetBytes(command); using (AllocatedMemory allocatedMemory = Memory.CreateAllocatedMemory(400), allocatedMemory2 = Memory.CreateAllocatedMemory(array.Length + 30)) { allocatedMemory2.AllocateOfChunk("cmd", array.Length); allocatedMemory2.WriteBytes("cmd", array); allocatedMemory.AllocateOfChunk <IntPtr>("cmdAddress"); allocatedMemory.AllocateOfChunk <long>("t1"); allocatedMemory.AllocateOfChunk <long>("tLength"); allocatedMemory.AllocateOfChunk <long>("t3"); allocatedMemory.Write("cmdAddress", allocatedMemory2.Address); allocatedMemory.Write("t1", 0x40); allocatedMemory.Write("tLength", array.Length + 1); allocatedMemory.Write("t3", 0x00); _ = Memory.CallInjected64 <int>(Offsets.ProcessChatBoxPtr, Offsets.RaptureModule, allocatedMemory.Address, Offsets.UiModule); } } finally { if (flag) { Monitor.Exit(assemblyLock); } } }
/// <summary> /// Inject x86 assembly into the target process and execute it /// </summary> /// <param name="asm">Assembly code to inject</param> /// <returns>true if the code was injected. Otherwise false.</returns> private void InjectAndExecute(IEnumerable <string> asm) { lock (_injectLock) { //Lets Inject the passed ASM Inject(asm, _allocatedMemory["codeCavePtr"]); _allocatedMemory.Write("addressInjection", _allocatedMemory["codeCavePtr"]); while (_allocatedMemory.Read <int>("addressInjection") > 0) { Thread.Sleep(1); } // Wait to launch code _allocatedMemory.WriteBytes("codeCavePtr", _eraser); } }
/// <summary> /// Inject x86 assembly into the target process and execute it /// </summary> /// <param name="asm">Assembly code to inject</param> /// <returns>true if the code was injected. Otherwise false.</returns> /// <exception cref="HookNotAppliedException">Thrown when the required hook has not been applied</exception> private static void InjectAndExecute(IEnumerable <string> asm) { lock (LockObject) { if (!_isApplied) { throw new HookNotAppliedException("Tried to inject code when the Hook was not applied"); } //Lets Inject the passed ASM Inject(asm, _allocatedMemory["codeCavePtr"]); _allocatedMemory.Write("addressInjection", _allocatedMemory["codeCavePtr"]); Stopwatch timer = Stopwatch.StartNew(); while (_allocatedMemory.Read <int>("addressInjection") > 0) { Thread.Sleep(1); if (timer.ElapsedMilliseconds >= 3000) { var window = BotManager.Memory.Process.MainWindowHandle; if (NativeImports.isWindowMinimized(window)) { Logger.Warn("CoolFish can not run when WoW is minimized. Please keep the window in background only."); NativeImports.ShowWindow(window); timer.Restart(); } else { throw new CodeInjectionFailedException("Failed to inject code after 3 seconds. Last Error: " + Marshal.GetLastWin32Error()); } } } // Wait to launch code _allocatedMemory.WriteBytes("codeCavePtr", Eraser); } }
internal IntPtr method_28(string string_0) { IntPtr result; using (AllocatedMemory allocatedMemory = this.externalProcessMemory_0.CreateAllocatedMemory((string_0.Length + 1) * 2)) { if (string_0.Length > 0) { allocatedMemory.WriteString(0, string_0, Encoding.UTF8); } else { allocatedMemory.Write <ushort>(0, 0); } IntPtr intPtr = this.method_27(); //mono_domain_get result = this.method_17 <IntPtr>(this.intptr_25, //mono_string_new new object[] { intPtr, allocatedMemory.Address }); } return(result); }
/// <summary> /// Apply the DirectX function hook to the WoW process /// </summary> /// <returns>true if it applied correctly. Otherwise, false</returns> internal static bool Apply() { lock (LockObject) { try { //Lets check if we are already hooked. if (_isApplied) { return true; } if (BotManager.Memory == null || BotManager.Memory.Process.HasExited) { return false; } _allocatedMemory = BotManager.Memory.CreateAllocatedMemory(CODECAVESIZE + 0x1000 + 0x4 + 0x4); var detourFunctionPointer = Offsets.Addresses["CGWorldFrame__Render"]; // store original bytes _originalBytes = BotManager.Memory.ReadBytes(detourFunctionPointer, 8); if (_originalBytes[0] == 0xE9) { MessageBox.Show( "It seems CoolFish might have crashed before it could clean up after itself. Please restart WoW and reattach the bot."); return false; } _allocatedMemory.WriteBytes("codeCavePtr", Eraser); _allocatedMemory.WriteBytes("injectedCode", Eraser); _allocatedMemory.Write("addressInjection", 0); _allocatedMemory.Write("returnInjectionAsm", 0); var asm = new List<string> { "pushad", // save registers to the stack "pushfd", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "test eax, eax", // Test if you need launch injected code "je .leave", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "call eax", // Launch Function "mov [" + _allocatedMemory["returnInjectionAsm"] + "], eax", // Copy pointer return value "mov edx, " + _allocatedMemory["addressInjection"], // Enter value 0 of so we know we are done "mov ecx, 0", "mov [edx], ecx", ".leave:", // Close function "popfd", "popad" }; asm = AddRandomAsm(asm); // injected code int sizeAsm = Inject(asm, _allocatedMemory["injectedCode"]); // copy and save original instructions BotManager.Memory.WriteBytes(_allocatedMemory["injectedCode"] + sizeAsm, _originalBytes); asm.Clear(); asm.Add("jmp " + (detourFunctionPointer + _originalBytes.Length)); // create jump back stub Inject(asm, _allocatedMemory["injectedCode"] + sizeAsm + _originalBytes.Length); // create hook jump asm.Clear(); asm.Add("jmp " + _allocatedMemory["injectedCode"]); asm.Add("nop"); asm.Add("nop"); asm.Add("nop"); Inject(asm, detourFunctionPointer); _isApplied = true; } catch { _isApplied = false; if (_allocatedMemory != null) { _allocatedMemory.Dispose(); } throw; } return true; } }
internal IntPtr method_43(IntPtr intptr_37, IntPtr intptr_38, params object[] object_0) { if (object_0 != null && object_0.Length != 0) { IntPtr result; using (AllocatedMemory allocatedMemory = this.externalProcessMemory_0.CreateAllocatedMemory(2048)) { allocatedMemory.AllocateOfChunk("ArrayPtrs", 512); allocatedMemory.AllocateOfChunk("Args", 512); int num = 0; int num2 = 0; foreach (object obj in object_0) { object obj2 = obj; IntPtr intPtr; if (MonoClass.IsOutParam(num, out intPtr)) { obj2 = intPtr; } MonoClass monoClass = obj as MonoClass; if (monoClass != null) { obj2 = monoClass.GetClassInstance(); } else if (obj != null) { string text = obj as string; if (text != null) { obj2 = this.method_28(text); } else if (obj.GetType().IsEnum) { obj2 = Convert.ChangeType(obj2, ((Enum)obj2).GetTypeCode()); } } else { obj2 = IntPtr.Zero; } int num3 = 4; if (!(obj2 is IntPtr)) { if (obj2 is long) { allocatedMemory.Write <long>("Args", num2, (long)obj2); num3 = 8; } else if (obj2 is ulong) { allocatedMemory.Write <ulong>("Args", num2, (ulong)obj2); num3 = 8; } else if (obj2 is uint) { allocatedMemory.Write <uint>("Args", num2, (uint)obj2); } else if (obj2 is int) { allocatedMemory.Write <int>("Args", num2, (int)obj2); } else if (obj2 is bool) { allocatedMemory.Write <int>("Args", num2, ((bool)obj2) ? 1 : 0); } else if (obj2 is double) { allocatedMemory.Write <double>("Args", num2, (double)obj2); num3 = 8; } else if (obj2 is float) { allocatedMemory.Write <float>("Args", num2, (float)obj2); } else if (obj2 is Vector3) { Vector3 vector = (Vector3)obj2; allocatedMemory.Write <float>("Args", num2 + 0, vector.X); allocatedMemory.Write <float>("Args", num2 + 4, vector.Y); allocatedMemory.Write <float>("Args", num2 + 8, vector.Z); num3 = 12; } else { if (!(obj2 is RaycastHit)) { throw new Exception("Unknown type passed as argument: " + obj2.GetType()); } RaycastHit raycastHit = (RaycastHit)obj2; allocatedMemory.Write <float>("Args", num2 + 0, raycastHit.Point.X); allocatedMemory.Write <float>("Args", num2 + 4, raycastHit.Point.Y); allocatedMemory.Write <float>("Args", num2 + 8, raycastHit.Point.Z); allocatedMemory.Write <float>("Args", num2 + 12, raycastHit.Normal.X); allocatedMemory.Write <float>("Args", num2 + 16, raycastHit.Normal.Y); allocatedMemory.Write <float>("Args", num2 + 20, raycastHit.Normal.Z); allocatedMemory.Write <int>("Args", num2 + 24, raycastHit.FaceID); allocatedMemory.Write <float>("Args", num2 + 28, raycastHit.Distance); allocatedMemory.Write <float>("Args", num2 + 32, raycastHit.UV.X); allocatedMemory.Write <float>("Args", num2 + 36, raycastHit.UV.Y); num3 = 40; } } if (obj2 is IntPtr) { allocatedMemory.Write <IntPtr>("ArrayPtrs", 4 * num, (IntPtr)obj2); } else { allocatedMemory.Write <IntPtr>("ArrayPtrs", 4 * num, allocatedMemory["Args"] + num2); } num++; num2 += num3; } result = this.method_17 <IntPtr>(this.intptr_26,//mono_runtime_invoke new object[] { intptr_37, intptr_38, allocatedMemory["ArrayPtrs"], IntPtr.Zero }); } return(result); } IntPtr temp = this.method_17 <IntPtr>(this.intptr_26,//mono_runtime_invoke new object[] { intptr_37, intptr_38, IntPtr.Zero, IntPtr.Zero }); return(temp); }
/// <summary> /// Apply the DirectX function hook to the WoW process /// </summary> /// <returns>true if it applied correctly. Otherwise, false</returns> internal static bool Apply() { lock (LockObject) { try { //Lets check if we are already hooked. if (_isApplied) { return(true); } if (BotManager.Memory == null || BotManager.Memory.Process.HasExited) { return(false); } _allocatedMemory = BotManager.Memory.CreateAllocatedMemory(CODECAVESIZE + 0x1000 + 0x4 + 0x4); var detourFunctionPointer = Offsets.Addresses["CGWorldFrame__Render"]; // store original bytes _originalBytes = BotManager.Memory.ReadBytes(detourFunctionPointer, 6); if (_originalBytes[0] == 0xE9) { MessageBox.Show( "It seems CoolFish might have crashed before it could clean up after itself. Please restart WoW and reattach the bot."); return(false); } _allocatedMemory.WriteBytes("codeCavePtr", Eraser); _allocatedMemory.WriteBytes("injectedCode", Eraser); _allocatedMemory.Write("addressInjection", 0); _allocatedMemory.Write("returnInjectionAsm", 0); var asm = new List <string> { "pushad", // save registers to the stack "pushfd", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "test eax, eax", // Test if you need launch injected code "je @out", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "call eax", // Launch Function "mov [" + _allocatedMemory["returnInjectionAsm"] + "], eax", // Copy pointer return value "mov edx, " + _allocatedMemory["addressInjection"], // Enter value 0 of so we know we are done "mov ecx, 0", "mov [edx], ecx", "@out:", // Close function "popfd", // load reg "popad" }; asm = AddRandomAsm(asm); // injected code int sizeAsm = Inject(asm, _allocatedMemory["injectedCode"]); // copy and save original instructions BotManager.Memory.WriteBytes(_allocatedMemory["injectedCode"] + sizeAsm, _originalBytes); asm.Clear(); asm.Add("jmp " + (detourFunctionPointer + _originalBytes.Length)); // create jump back stub Inject(asm, _allocatedMemory["injectedCode"] + sizeAsm + _originalBytes.Length); // create hook jump asm.Clear(); asm.Add("jmp " + _allocatedMemory["injectedCode"]); asm.Add("nop"); Inject(asm, detourFunctionPointer); _isApplied = true; } catch { _isApplied = false; if (_allocatedMemory != null) { _allocatedMemory.Dispose(); } throw; } return(true); } }
/// <summary> /// Retrieve global LUA variables from the WoW process /// </summary> /// <param name="commands">String names of variables to retrieve</param> /// <returns>values of the variables to retrieve</returns> /// <exception cref="HookNotAppliedException">Thrown when the required hook has not been applied</exception> public static Dictionary <string, string> GetLocalizedText(IEnumerable <string> commands) { var returnDict = new Dictionary <string, string>(); if (commands == null) { throw new ArgumentNullException("commands"); } List <string> enumerable = commands.ToList(); if (!enumerable.Any()) { return(returnDict); } var builder = new StringBuilder(enumerable.Count); foreach (string s in enumerable.Where(s => !string.IsNullOrWhiteSpace(s))) { builder.Append(s); builder.Append('\0'); returnDict[s] = string.Empty; } int commandSpace = Encoding.UTF8.GetBytes(builder.ToString()).Length; commandSpace += commandSpace % 4; int returnAddressSpace = enumerable.Count == 0 ? 0x4 : enumerable.Count * 0x4; AllocatedMemory mem = BotManager.Memory.CreateAllocatedMemory(commandSpace + returnAddressSpace + 0x4); try { mem.WriteBytes("command", Encoding.UTF8.GetBytes(builder.ToString())); mem.WriteBytes("returnVarsPtr", new byte[enumerable.Count * 0x4]); mem.Write("returnVarsNamesPtr", mem["command"]); InternalExecute(IntPtr.Zero, mem["returnVarsNamesPtr"], enumerable.Count, mem["returnVarsPtr"]); if (enumerable.Any()) { byte[] address = BotManager.Memory.ReadBytes(mem["returnVarsPtr"], enumerable.Count * 4); Parallel.ForEach(enumerable, // source collection () => 0, // method to initialize the local variable (value, loop, offset) => // method invoked by the loop on each iteration { var retnByte = new List <byte>(); var dwAddress = new IntPtr(BitConverter.ToInt32(address, offset)); if (dwAddress != IntPtr.Zero) { var buf = BotManager.Memory.Read <byte>(dwAddress); while (buf != 0) { retnByte.Add(buf); dwAddress = dwAddress + 1; buf = BotManager.Memory.Read <byte>(dwAddress); } } returnDict[value] = Encoding.UTF8.GetString(retnByte.ToArray()); offset += 0x4; //modify local variable return(offset); // value to be passed to next iteration }, finalResult => { } ); } } finally { mem.Dispose(); } return(returnDict); }
/// <summary> /// Retrieve global LUA variables from the WoW process /// </summary> /// <param name="commands">String names of variables to retrieve</param> /// <returns>values of the variables to retrieve</returns> /// <exception cref="Exception">Throws generic exception if the function hook we need is not applied</exception> public Dictionary <string, string> GetLocalizedText(IEnumerable <string> commands) { if (LocalSettings.Settings["DoDebugging"].As <bool>()) { var stackTrace = new StackTrace(); Logging.Log("[DEBUG] GetLocalizedText (enumerable) Lua from " + stackTrace.GetFrame(1).GetMethod().ReflectedType.Name + "." + stackTrace.GetFrame(1).GetMethod().Name); } if (!IsApplied) { throw new Exception( "Tried to Execute Lua Code when our hook wasn't applied. You should check Hook.IsApplied First!"); } var returnDict = new Dictionary <string, string>(); if (commands == null) { return(returnDict); } var enumerable = commands.ToList(); if (!enumerable.Any()) { return(returnDict); } var builder = new StringBuilder(enumerable.Count); enumerable.RemoveAll(string.IsNullOrWhiteSpace); foreach (var s in enumerable) { builder.Append(s); builder.Append('\0'); returnDict[s] = string.Empty; } int commandSpace = Encoding.UTF8.GetBytes(builder.ToString()).Length; commandSpace += commandSpace % 4; int returnAddressSpace = enumerable.Count == 0 ? 0x4 : enumerable.Count * 0x4; AllocatedMemory mem = BotManager.Memory.CreateAllocatedMemory(commandSpace + returnAddressSpace + 0x4 + 0x4); mem.WriteBytes("command", Encoding.UTF8.GetBytes(builder.ToString())); mem.WriteBytes("returnVarsPtr", new byte[enumerable.Count * 0x4]); mem.Write("numberOfReturnVarsAddress", 0); mem.Write("returnVarsNamesPtr", mem["command"]); try { lock (_lockObject) { InternalExecute(IntPtr.Zero, mem["returnVarsNamesPtr"], enumerable.Count, mem["returnVarsPtr"], mem["numberOfReturnVarsAddress"]); } byte[] address = BotManager.Memory.ReadBytes(mem["returnVarsPtr"], enumerable.Count * 4); Parallel.ForEach(enumerable, // source collection () => 0, // method to initialize the local variable (value, loop, offset) => // method invoked by the loop on each iteration { var retnByte = new List <byte>(); var dwAddress = new IntPtr(BitConverter.ToInt32(address, offset)); if (dwAddress != IntPtr.Zero) { var buf = BotManager.Memory.Read <byte>(dwAddress); while (buf != 0) { retnByte.Add(buf); dwAddress = dwAddress + 1; buf = BotManager.Memory.Read <byte>(dwAddress); } } returnDict[value] = Encoding.UTF8.GetString(retnByte.ToArray()); offset += 0x4; //modify local variable return(offset); // value to be passed to next iteration }, finalResult => {} ); } catch (Exception ex) { Logging.Log(ex); } finally { mem.Dispose(); } return(returnDict); }
/// <summary> /// Apply the DirectX function hook to the WoW process /// </summary> /// <returns>true if it applied correctly. Otherwise, false</returns> public bool Apply() { //Lets check if we are already hooked. if (IsApplied) { //Were already hooked. //So lets restore the original bytes. Restore(); } _allocatedMemory = BotManager.Memory.CreateAllocatedMemory(CODECAVESIZE + 0x1000 + 0x4 + 0x4); _dxAddress = new Dirext3D(BotManager.Memory.Process); // store original bytes _endSceneOriginalBytes = BotManager.Memory.ReadBytes(_dxAddress.HookPtr - 5, 10); int jumpLoc = 0; if (_endSceneOriginalBytes[5] == 0xE9) { DialogResult result = MessageBox.Show(LocalSettings.Translations["Hook Found"], LocalSettings.Translations["Warning"], MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.No) { return(false); } Logging.Log("Detected Another hook. Trying to hook anyway."); var offset = BotManager.Memory.Read <int>(_dxAddress.HookPtr + 1); jumpLoc = _dxAddress.HookPtr.ToInt32() + offset + 5; } foreach (int b in _endSceneOriginalBytes.Where(b => b == 0xE9).Select((b, i) => i)) { Logging.Log("E9 byte Detected at index: " + b); } if (_endSceneOriginalBytes[0] == 0xE9) { MessageBox.Show(LocalSettings.Translations["Reattach"]); return(false); } try { _allocatedMemory.WriteBytes("codeCavePtr", _eraser); _allocatedMemory.WriteBytes("injectedCode", _eraser); _allocatedMemory.Write("addressInjection", 0); _allocatedMemory.Write("returnInjectionAsm", 0); var asm = new List <string> { "pushad", // save registers to the stack "pushfd", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "test eax, eax", // Test if you need launch injected code "je @out", "mov eax, [" + _allocatedMemory["addressInjection"] + "]", "call eax", // Launch Function "mov [" + _allocatedMemory["returnInjectionAsm"] + "], eax", // Copy pointer return value "mov edx, " + _allocatedMemory["addressInjection"], // Enter value 0 of so we know we are done "mov ecx, 0", "mov [edx], ecx", "@out:", // Close function "popfd", // load reg "popad" }; asm = AddRandomAsm(asm); // injected code int sizeAsm = Inject(asm, _allocatedMemory["injectedCode"]); // Size asm jumpback int sizeJumpBack; // copy and save original instructions if (jumpLoc != 0) { asm.Clear(); asm.Add("jmp " + (uint)jumpLoc); Inject(asm, IntPtr.Add(_allocatedMemory["injectedCode"], sizeAsm)); sizeJumpBack = 5; } else { BotManager.Memory.WriteBytes(IntPtr.Add(_allocatedMemory["injectedCode"], sizeAsm), new[] { _endSceneOriginalBytes[5], _endSceneOriginalBytes[6] }); sizeJumpBack = 2; } asm.Clear(); asm.Add("jmp " + ((uint)_dxAddress.HookPtr + sizeJumpBack)); // short jump takes 2 bytes. // create jump back stub Inject(asm, _allocatedMemory["injectedCode"] + sizeAsm + sizeJumpBack); // create hook jump asm.Clear(); asm.Add("@top:"); asm.Add("jmp " + _allocatedMemory["injectedCode"]); asm.Add("jmp @top"); Inject(asm, _dxAddress.HookPtr - 5); IsApplied = true; } catch (Exception ex) { Logging.Log(ex); return(false); } return(true); }