【发布时间】:2018-06-21 19:46:25
【问题描述】:
所以我最近偶然发现了一个博客,该博客描述了如何从另一个进程运行您的 WinForms 应用程序。 我立刻认为这是一个非常酷的独特的东西,并想自己测试一下。虽然没有代码,但它解释了如何做到这一点,这就是我所做的。
class Program
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
ProcessAccessFlags processAccess,
bool bInheritHandle,
int processId
);
public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
{
return OpenProcess(flags, false, proc.Id);
}
static void Main(string[] args)
{
Process notepad = null;
Process[] processes = Process.GetProcesses();
foreach (var process in processes)
{
if (process.ProcessName.ToLower() == "notepad")
{
notepad = process;
}
}
OpenProcess(notepad, ProcessAccessFlags.All);
byte[] payload = File.ReadAllBytes(@"C:\Users\developer\source\repos\WindowsFormsApp2\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe");
foreach (ProcessThread pt in notepad.Threads)
{
IntPtr openThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pt.Id);
SuspendThread(openThread);
CloseHandle(openThread);
}
WriteProcessMemory(notepad.Handle, notepad.Modules[0].BaseAddress, payload, payload.Length, out IntPtr lpNumberOfBytesWritten);
CreateRemoteThread(notepad.Handle, IntPtr.Zero, 0x0, notepad.Modules[0].BaseAddress, IntPtr.Zero, 0x0, out _);
}
}
这是一件非常简单的事情,应该暂停进程及其所有线程。
然后从我的另一个应用程序中编写字节数组,这是一个简单的 WinForms 应用程序,带有一个按钮,当您单击它时,它会显示一个消息框,上面写着 Hello World
但是一旦我运行代码,记事本就会崩溃并且什么也没有出现,我哪里出错了?
【问题讨论】:
-
您在崩溃、堆栈跟踪等时获得的任何信息?
-
很奇怪,没有,VS 中什么都没有,事件查看器中什么也没有
-
也许它基于受保护的内存访问或类似的东西,但我担心除此之外我没有更多的想法。