将Python代码注入进程
我想把Python代码注入到一个进程里,但在注入的时候,那个进程似乎崩溃了。我的程序没有报错,但目标进程却停止工作了。调用的那些不受管理的API没有给我任何错误,看起来执行得也挺正常。
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess,IntPtr lpThreadAttributes,uint dwStackSize, IntPtr lpStartAddress,IntPtr lpParameter,uint dwCreationFlags, out uint lpThreadId);
[Flags]
enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000,
VIRTUAL_MEM = (0x1000 | 0x2000)
}
[Flags]
public enum MemoryProtection
{
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
ExecuteWriteCopy = 0x80,
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400,
PAGE_EXECUTE_READWRITE = 0x00000040
}
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint dwFreeType);
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
internal static extern Int32 WaitForSingleObject( IntPtr handle,Int32 milliseconds);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
private void InjectCode(string shellcode = "print('Hello, World!')")
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName == "Toontown")
{
int shellcode_length = shellcode.Length;
IntPtr h_process = OpenProcess(ProcessAccessFlags.All, false, (int)proc.Id);
IntPtr shellcode_address = (IntPtr)VirtualAllocEx(h_process, (IntPtr)0, (uint)shellcode_length, AllocationType.VIRTUAL_MEM, MemoryProtection.PAGE_EXECUTE_READWRITE);
byte[] bytes = new byte[shellcode.Length * sizeof(char)];
Buffer.BlockCopy(shellcode.ToCharArray(), 0, bytes, 0, bytes.Length);
UIntPtr bytesout;
uint t_id;
bool Written = WriteProcessMemory(h_process, shellcode_address, bytes, (uint)shellcode_length, out bytesout);
IntPtr hThread = (IntPtr)CreateRemoteThread(h_process, (IntPtr)null, 0, (IntPtr)shellcode_length, (IntPtr)shellcode_address, 0, out t_id);
int Result = WaitForSingleObject(hThread, 10 * 1000);
if (Result == 0x00000080L || Result == 0x00000102L || Result == 0xFFFFFFFF)
{
if (hThread != null)
{
CloseHandle(hThread);
}
}
Thread.Sleep(1000);
VirtualFreeEx(h_process, shellcode_address, (UIntPtr)0, 0x8000);
if (hThread != null)
{
CloseHandle(hThread);
}
}
}
}
正如你所看到的,我把不受管理的API返回的值保存到了变量里,用来检查它是否正常工作。看起来是没问题的,但目标进程还是崩溃了,日志里也没有记录相关的错误信息。管理程序能否注入到不受管理的进程里?我是不是把变量类型转换错了?或者是shellcode转换成字节数组时出错了?请告诉我,谢谢。
补充:崩溃发生在CreateRemoteThread那里。
2 个回答
看起来你想从 .net 运行一些任意的 Python 代码。现在你正在尝试调用 Python 解释器来实现这个目标。
这样做的缺点有:
- 这很复杂,正如你发现的那样。
- 进程间通信让事情变得更难,因为你需要在不同的程序之间传递数据。
- 然后你需要把从每一方得到的信息解析成有意义的东西(可能需要用到某种 XML 格式)。
- 最后,考虑到以上所有的麻烦,这个过程会很慢。
解决这个问题的一种方法是在 .net 中直接调用 Python 程序。老实说,我自己从来没有这样做过,也没见过真正的 Python(除了那种会嘶嘶叫的)。你可以看看 http://msdn.microsoft.com/en-us/library/ee461504.aspx,不过不幸的是,看起来他们是把 Python 存储在一个文件中并在那里调用它。不过我相信你可以调用存储为字符串的代码。
使用 DLR 实现的 Python 的主要缺点是你依赖第三方来确保 Python 到 CLR 的转换是正确的。不过我认为 IronPython 是一个由微软赞助的开源项目。
想了解更多信息,可以访问:http://ironpython.codeplex.com/
CreateRemoteThread
是一个可以在另一个进程中创建本地线程的功能,但它需要一个有效的机器代码地址,如果这个地址不对,线程就会导致进程崩溃。
你提到的情况有点不同,你想要让另一个进程中的 Python 解释器执行一些代码。这是可以做到的,但方法不同,而且难度更大。
你需要把一个本地库注入到另一个进程中,这个库要完成两个任务:
- 设置 Python 解释器
- 建立进程间通信(IPC)的方法
然后,利用这个 IPC 把你想执行的 Python 代码发送到另一个进程中,注入的库会使用 Python 解释器来执行这些代码。
你可以在这个 Codeproject 文章 中找到如何将 DLL 注入到另一个进程的示例。