【问题标题】:Controlling child process Windows [closed]控制子进程 Windows [关闭]
【发布时间】:2016-02-04 13:22:49
【问题描述】:

是否可以完全控制子进程?我没有子进程的来源。我需要查看并更改它的变量。如果是,我该如何通过 C#/C++ 来实现?

【问题讨论】:

  • 类似于作弊引擎的东西?
  • 我需要“即时”替换原始路径和其他一些数据
  • 我不知道它使用了哪些地址。应用程序必须自动执行此操作,无需用户输入。
  • 在文件系统中创建快捷方式不是更容易吗?

标签: c# c++ windows child-process


【解决方案1】:

如果是内存操作 - 例如:读取和写入字节数据到另一个进程的内存空间,那么是的 - 你可以这样做,假设父进程以足够的权限启动。 例如:作为管理员。

对于更复杂的事情,例如调用子进程代码,您需要执行 DLL 注入之类的操作。作为开发中的一种安全措施,程序旨在完全控制自己的代码空间,其他应用程序并不意味着能够访问或调用外部应用程序中的方法。 保存供外部应用程序使用的公开 API。

为了在外部应用程序中读取和写入内存位置,您可以在 C# 中执行以下操作

使用下面的

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace MemoryManagement
{
    public class Memory : IDisposable
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwProcessId);
        [DllImport("kernel32.dll")]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        byte[] lpBuffer, UIntPtr nSize, uint lpNumberOfBytesWritten);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);


        public IntPtr Handle;
        public Process ProcessHeld = null;
        public Memory(string sprocess)
        {
            Process[] Processes = Process.GetProcessesByName(sprocess);
            Process nProcess = Processes[0];

            Handle = OpenProcess(0x10, false, (uint)nProcess.Id);
            if (Handle != IntPtr.Zero)
            {
                ProcessLoaded = true;
                ProcessHeld = nProcess;
            }
            else
            {
                ProcessLoaded = false;
            }
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Free other state (managed objects).

            }
            // Free your own state (unmanaged objects).
            // Set large fields to null.
        }

        // Use C# destructor syntax for finalization code.

        ~Memory()
        {
            Dispose(false);
        }



        //Would use this method below - for the actual writing of the Disable Patch Code 
        public UIntPtr WriteByteArray(IntPtr hProcess, IntPtr BaseAddress, byte[] NewVal)
        {
            try
            {
                // Return Value 
                bool ReturnVal;
                UIntPtr BytesWritten;
                // Write Memory Byte Array 
                ReturnVal = WriteProcessMemory(hProcess, BaseAddress, NewVal, (uint)NewVal.Length, out BytesWritten);

                return BytesWritten;
            }
            catch (Exception e)
            {

                return (UIntPtr)0x0;
            }
        } 


        public bool ProcessLoaded = false;

        public string ReadString(uint pointer)
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)24, 0);
            return Encoding.UTF8.GetString(bytes);
        }

        public string ReadString(uint pointer, int length)
        {
            byte[] bytes = new byte[length];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)length, 0);
            return Encoding.UTF8.GetString(bytes);
        }

        public int ReadOffset(uint pointer, uint offset)
        {
            byte[] bytes = new byte[24];

            uint adress = (uint)ReadPointer(pointer) + offset;
            ReadProcessMemory(Handle, (IntPtr)adress, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }

        public int ReadPointer(uint pointer)
        {
            byte[] bytes = new byte[24];

            ReadProcessMemory(Handle, (IntPtr)pointer, bytes, (UIntPtr)sizeof(int), 0);
            return BitConverter.ToInt32(bytes, 0);
        }

    }

}

然后你可以使用

Memory mem = new Memory(Process.GetProcessByName("proc"));
string strVal = mem.ReadString(0x04443);

注意 - 我使用这个类从一个名为 Neverwinter Nights 的游戏中读取一些记忆。如果可以找到指向内存位置的指针,则可以将指针与 ReadPointer 方法一起使用。

对于更复杂的 DLL 注入任务,我建议查找这些库之一。

WhiteMagic、BlackMagic 或 GreyMagic

http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/259362-release-c-whitemagic-injected-net-helper-library.html

https://forum.tuts4you.com/topic/23764-blackmagic-managed-memory-manipulation/

http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/379821-greymagic-best-of-both-worlds-then-some-print.html

DLL 注入更复杂,因为您需要对子进程中的结构有一个大致的了解。您需要使用 IDA 之类的工具来检查程序方法调用和跳转等。

在另一位开发人员的帮助下,我能够使用 IDA 和 Whitemagic 创建一个 DLL 注入负载,使我能够从子进程内的新端口上打开一个新的 TCPClient。基本上允许我将自己的“onCommand”功能添加到子进程中。

我特意尝试这样做,以便我的 GameServer 可以触发 GameClient 截取屏幕截图,然后自动将其上传到游戏服务器的 facebook 页面。 最后搞定了,不过有点复杂。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    • 2013-07-19
    • 2011-12-30
    • 1970-01-01
    相关资源
    最近更新 更多