Example #1
0
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_RPC_MESSAGE)
            {
                byte[] messageData = null;
                UInt32 messageID   = 0;
                if ((m.WParam != IntPtr.Zero) && (m.LParam != IntPtr.Zero))
                {
                    using (var region = RemoteMemoryRegion.Existing(_Process, m.WParam, (uint)m.LParam.ToInt64()))
                        messageData = ReadRemoteData(region, out messageID);
                }

                Future <byte[]> fResult;
                Monitor.Enter(_AwaitingResponses);
                if (_AwaitingResponses.TryGetValue(messageID, out fResult))
                {
                    _AwaitingResponses.Remove(messageID);
                    Monitor.Exit(_AwaitingResponses);
                    fResult.SetResult(messageData, null);
                }
                else
                {
                    Debug.Assert(messageID == 0);

                    Monitor.Exit(_AwaitingResponses);
                    _Messages.Enqueue(messageData);
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }
Example #2
0
        protected RemoteMemoryRegion GetFunctionRegion(string moduleName, string functionName, byte[] replacementBytes)
        {
            var address = GetFunctionAddress(moduleName, functionName);

            return(RemoteMemoryRegion.Existing(
                       Process, address, (uint)replacementBytes.Length
                       ));
        }
Example #3
0
        protected unsafe byte[] ReadRemoteData(RemoteMemoryRegion region, out UInt32 messageId)
        {
            using (var handle = region.OpenHandle(ProcessAccessFlags.VMRead)) {
                messageId = BitConverter.ToUInt32(
                    region.ReadBytes(handle, 0, 4), 0
                    );

                return(region.ReadBytes(handle, 4, region.Size - 4));
            }
        }
Example #4
0
 public static RemoteMemoryRegion Allocate(Process process, SafeProcessHandle handle, UInt32 size)
 {
     var result = new RemoteMemoryRegion {
         Process = process,
         Size = size
     };
     result.Address = Win32.VirtualAllocEx(
         handle.DangerousGetHandle(), IntPtr.Zero,
         size, AllocationType.Commit | AllocationType.Reserve,
         MemoryProtection.ReadWrite
     );
     if (result.Address == IntPtr.Zero) {
         var error = Win32.GetLastError();
         throw new Exception(String.Format("Allocation failed: Error {0:x8}", error));
     }
     return result;
 }
Example #5
0
        public static RemoteMemoryRegion Allocate(Process process, SafeProcessHandle handle, UInt32 size)
        {
            var result = new RemoteMemoryRegion {
                Process = process,
                Size    = size
            };

            result.Address = Win32.VirtualAllocEx(
                handle.DangerousGetHandle(), IntPtr.Zero,
                size, AllocationType.Commit | AllocationType.Reserve,
                MemoryProtection.ReadWrite
                );
            if (result.Address == IntPtr.Zero)
            {
                var error = Win32.GetLastError();
                throw new Exception(String.Format("Allocation failed: Error {0:x8}", error));
            }
            return(result);
        }
Example #6
0
        public unsafe void Send(byte[] message)
        {
            if (_Process == null)
            {
                throw new Exception("No remote process");
            }
            if (RemoteThreadId == 0)
            {
                throw new Exception("No remote thread");
            }

            using (var handle = Win32.OpenProcessHandle(ProcessAccessFlags.VMWrite | ProcessAccessFlags.VMOperation, false, _Process.Id)) {
                RemoteMemoryRegion region;
                UInt32             regionSize = (UInt32)message.Length;

                // leaked on purpose
                region = RemoteMemoryRegion.Allocate(
                    _Process, handle, regionSize
                    );

                fixed(byte *pData = message)
                {
                    try {
                        region.Write(handle, 0, regionSize, pData);
                    } catch {
                        try {
                            region.Dispose();
                        } catch {
                        }
                        throw;
                    }
                }

                if (!Win32.PostThreadMessage(RemoteThreadId, WM_RPC_MESSAGE, region.Address, region.Size))
                {
                    var error = Win32.GetLastError();
                    region.Dispose();
                    throw new Exception(String.Format("Error posting thread message: {0:x8}", error));
                }
            }
        }
Example #7
0
        public static unsafe RemoteMemoryRegion Inject(
            Process process, PortableExecutable executable, IntPtr payloadArgument,
            Future <Int32> threadResultFuture, Future <UInt32> threadIdFuture
            )
        {
            RemoteMemoryRegion region = null;

            using (var handle = Win32.OpenProcessHandle(
                       ProcessAccessFlags.VMRead | ProcessAccessFlags.VMWrite |
                       ProcessAccessFlags.VMOperation | ProcessAccessFlags.CreateThread |
                       ProcessAccessFlags.QueryInformation,
                       false, process.Id
                       ))
                try {
                    region = RemoteMemoryRegion.Allocate(
                        process, handle, executable.OptionalHeader.SizeOfImage
                        );
                    region.Protect(handle, 0, region.Size, MemoryProtection.ReadWrite);

                    var baseAddress = (UInt32)region.Address.ToInt64();

                    executable.Rebase(baseAddress);
                    executable.ResolveImports();

                    foreach (var section in executable.Sections.Values)
                    {
                        // 0-byte remote memory read/write/protect operations will fail with an error.
                        if (section.Size <= 0)
                        {
                            continue;

                            fixed(byte *data = section.RawData)
                            {
                                region.Write(
                                    handle, section.VirtualAddress, section.Size, data
                                    );

                                // Why the f**k isn't this a flags-style enumeration? Sigh, classic windows.
                                MemoryProtection protection = MemoryProtection.ReadOnly;

                                if ((section.Characteristics & PortableExecutable.SectionCharacteristics.MemExecute) == PortableExecutable.SectionCharacteristics.MemExecute)
                                {
                                    protection = MemoryProtection.ExecuteRead;
                                }
                                else if ((section.Characteristics & PortableExecutable.SectionCharacteristics.MemWrite) == PortableExecutable.SectionCharacteristics.MemWrite)
                                {
                                    protection = MemoryProtection.ReadWrite;
                                }

                                region.Protect(
                                    handle, section.VirtualAddress, section.Size, protection
                                    );
                            }
                    }

                    UInt32 threadId           = 0;
                    UInt32 creationFlags      = 0x0;
                    IntPtr remoteThreadHandle = Win32.CreateRemoteThread(
                        handle.DangerousGetHandle(), IntPtr.Zero, 0,
                        baseAddress + executable.OptionalHeader.AddressOfEntryPoint,
                        payloadArgument,
                        creationFlags, out threadId
                        );
                    if (remoteThreadHandle == IntPtr.Zero)
                    {
                        var error = Win32.GetLastError();
                        throw new Exception(String.Format("Thread start failed: Error {0:x8}", error));
                    }

                    threadIdFuture.Complete(threadId);
                    var threadHandle = new ThreadWaitHandle(new SafeWaitHandle(remoteThreadHandle, true));
                    ThreadPool.RegisterWaitForSingleObject(threadHandle, (s, e) => {
                        Int32 exitCode;
                        Win32.GetExitCodeThread(handle.DangerousGetHandle(), out exitCode);
                        threadResultFuture.Complete(exitCode);
                        threadHandle.Close();
                    }, null, -1, true);

                    var theResult = region;
                    region = null;
                    return(theResult);
                } finally {
                    if (region != null)
                    {
                        bool exited = true;
                        try {
                            exited = process.HasExited;
                        } catch {
                        }

                        if (!exited)
                            region.Dispose(); }
                    }
                }
Example #8
0
        protected unsafe byte[] ReadRemoteData(RemoteMemoryRegion region, out UInt32 messageId)
        {
            using (var handle = region.OpenHandle(ProcessAccessFlags.VMRead)) {
                messageId = BitConverter.ToUInt32(
                    region.ReadBytes(handle, 0, 4), 0
                );

                return region.ReadBytes(handle, 4, region.Size - 4);
            }
        }