Exemplo n.º 1
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(); }
                    }
                }
Exemplo n.º 2
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();
                }
            }
        }