Example #1
0
 static extern bool SetThreadContext(IntPtr thandle, ref WOW64_CONTEXT context);
Example #2
0
        /// <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);
        }