[英]Passing multiple parameters using CreateRemoteThread in C#
我的目标是在 C# (CreateRemoteThread) 中使用 P/Invoke 调用远程进程中的函数。 问题是该函数需要多个参数。 有没有办法将多个参数传递给函数?
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[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, IntPtr lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
[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
}
[StructLayout(LayoutKind.Sequential, Pack=1]
public struct RemoteThreadParams
{
[MarshalAs(UnmanagedType.U1)]
public byte Param1;
[MarshalAs(UnmanagedType.I4)]
public int Param2;
...
}
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
out uint lpThreadId
);
RemoteThreadParams params = new RemoteThreadParams();
parms.Param1 = 10;
parms.Param2 = 200;
// Allocate some native heap memory in your process big enough to store the
// parameter data
IntPtr iptrtoparams = Marshal.AllocHGlobal(Marshal.SizeOf(RemoteThreadParams));
// Copies the data in your structure into the native heap memory just allocated
Marshal.StructureToPtr(params, iptrtoparams, false);
// Use to get a handle to the process you intend to create a thread in.
OpenProcess(...,...,...);
// Use to alloc "committed" memory that is addressable by other process
IntPtr iptrremoteallocatedmemory = VirtualAllocEx()...
// Copy from your process memory to the memory the remoteprocess will be accessing
WriteProcessMemory(...,iptrremoteallocatedmemory,iptrtoparams,...,...);
Marshal.FreeHGlobal(iptrtoparams); // safe to free, as you have done the copy
CreateRemoteThread(...,...,...,...,iptrremoteallocatedmemory,...,...);
// Free the memory that was allocated for the other process...but be
// careful of its lifetime.
//
// Only free when the thread will no longer be accessing the allocated native
// memory i.e. when it's finished.
VirtualFreeEx(...,...,...,...);
在您的 C/C++ 代码中有:
#pragma pack(push,1)
struct tagRemoteThreadParams
{
BYTE Param1;
int Param2;
} RemoteThreadParams, *PRemoteThreadParams;
#pragma pack(pop)
将线程函数接收到的LPVOID
为PRemoteThreadParams
(即*RemoteThreadParams
)。
如果您有一些“字符串”想要作为参数之一,那么您将需要做更多的工作来将它们编组。 如需更多帮助,请参阅:
其他一些参考:
如果函数有多个参数,不使用 shellcode 就不可能将它们传递给CreateRemoteThread()
调用的函数。
传递指向结构或参数数组的指针将不起作用。
第一个参数将被正确传递,其他参数也将存在于您编写它们的内存中,但它们不会被放置到调用约定正确访问它们所需的寄存器或堆栈中。
如果函数接受 2 个参数并且您传递一个指向结构的指针(正如我在其他答案中看到的那样),第一个参数将正确放置在堆栈或寄存器中,但是当函数尝试访问后续参数时,它只会提取之前堆栈中或寄存器中的任何数据。
本质上,它会将这些垃圾数据视为参数。
正确获取参数的唯一方法是将 shellcode 写入进程,该进程在执行对目标函数的调用或 jmp 之前将参数加载到适当的寄存器和堆栈中。
您可以通过尝试使用 CreateRemoteThread 执行以下任一操作来轻松测试:
MessageBoxA(0,0,0,0);
Beep(500, 500);
您可以自己跟踪程序集并轻松查看问题,程序集绝不会尝试触及第一个参数之后的地址。 相反,它只是在参数应该位于的位置(在堆栈和寄存器中,而不是在您写入内存的结构中)接触数据。
如果您的函数采用指向结构的指针,则其他答案中提供的方法将起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.