static extern bool SetThreadContext(IntPtr thandle, ref WOW64_CONTEXT context);
/// <summary> /// Выполняет функцию по указанному адрессу с указанным списком аргуметов. /// </summary> /// <param name="injAddress">Адрес в памяти куда записывается исполнимый байткод.</param> /// <param name="callAddress">Относительный адресс выполняемой функции.</param> /// <param name="funcArgs"> /// Параметры функции. /// Параметрами могут выступать как и значения так и указатели на значения. /// </param> public void Call_x32(IntPtr injAddress, IntPtr callAddress, params int[] funcArgs) { var tHandle = OpenThread(ThreadAccess.All, false, Process.Threads[0].Id); if (SuspendThread(tHandle) == 0xFFFFFFFF) { throw new Win32Exception(); } var context = new WOW64_CONTEXT { ContextFlags = 0x10001 /*CONTROL*/ }; if (!GetThreadContext(tHandle, ref context)) { throw new Win32Exception(); } var retaddr = Write <uint>(0xDEAD); var bytes = new List <byte>(); #region ASM // push eip (stored refernse to next inctruction) bytes.Add(0x68); bytes.AddRange(BitConverter.GetBytes(context.Eip)); // pushad (stored general registers) bytes.Add(0x60); // pushfd (stored flags) bytes.Add(0x9C); // pushed to the stack function arguments for (int i = funcArgs.Length - 1; i >= 0; --i) { // push param address bytes.Add(0x68); bytes.AddRange(BitConverter.GetBytes(funcArgs[i])); } // mov eax, callAddress bytes.Add(0xB8); bytes.AddRange(BitConverter.GetBytes(callAddress.ToInt32())); // call eax bytes.Add(0xFF); bytes.Add(0xD0); // add esp, arg_count * pointersize (__cdecl correct stack) bytes.Add(0x83); bytes.Add(0xC4); bytes.Add((byte)(funcArgs.Length * IntPtr.Size)); // mov [retaddr], eax bytes.Add(0xA3); bytes.AddRange(BitConverter.GetBytes(retaddr.ToInt32())); // popfd (restore flags) bytes.Add(0x9D); // popad (restore general registers) bytes.Add(0x61); // retn bytes.Add(0xC3); #endregion var oldProtect = MemoryProtection.ReadOnly; // Save original code and disable protect var oldCode = ReadBytes(injAddress, bytes.Count); if (!VirtualProtectEx(Process.Handle, injAddress, bytes.Count, MemoryProtection.ExecuteReadWrite, out oldProtect)) { throw new Win32Exception(); } Write(injAddress, bytes.ToArray()); context.Eip = (uint)injAddress.ToInt32(); if (!SetThreadContext(tHandle, ref context) || ResumeThread(tHandle) == 0xFFFFFFFF) { throw new Win32Exception(); } for (int i = 0; i < 0x100; ++i) { System.Threading.Thread.Sleep(15); if (Read <uint>(retaddr) != 0xDEAD) { break; } } // restore protection and original code Write(injAddress, oldCode); if (!FlushInstructionCache(Process.Handle, injAddress, bytes.Count)) { throw new Win32Exception(); } if (!VirtualProtectEx(Process.Handle, injAddress, bytes.Count, oldProtect, out oldProtect)) { throw new Win32Exception(); } Free(retaddr); }