使用C#调用系统API实现内存注入的代码

时间:2021-12-01 00:25:59 


//首先导入命名空间
using System.Runtime.InteropServices;
/// <summary>
/// 在指定进程的虚拟地址空间中保留或开辟一段区域..除非MEM_RESET被使用,否则将该内存区域初始化为0.
/// </summary>
/// <param name="process">需要在其中分配空间的进程的句柄.这个句柄必须拥有PROCESS_VM_OPERATION访问权限</param>
/// <param name="pAddress">想要获取的地址区域.一般用NULL自动分配</param>
/// <param name="size">要分配的内存大小.字节单位.注意实际分 配的内存大小是页内存大小的整数倍</param>
/// <param name="type">内存分配的类型</param>
/// <param name="protect">内存页保护</param>
/// <returns>执行成功就返回分配内存的首地址,失败返回0。</returns>
[DllImport("kernel32.dll")] //声明API函数
public static extern int VirtualAllocEx(IntPtr process, int pAddress, int size, int type, int protect);
/// <summary>
/// 写入某一进程的内存区域。入口区必须可以访问,否则操作将失败
/// </summary>
/// <param name="process">进程句柄</param>
/// <param name="baseAddress">要写的内存首地址</param>
/// <param name="buffer">指向要写的数据的指针(数据当前存放地址)。</param>
/// <param name="nSize">要写入的字节数。</param>
/// <param name="lpNumberOfBytesWritten">实际数据的长度</param>
/// <returns>非零表示成功,零表示失败</returns>
[DllImport("kernel32.dll")]
public static extern int WriteProcessMemory(IntPtr process, int baseAddress, string buffer, int nSize, int lpNumberOfBytesWritten);
/// <summary>
/// 检索指定的动态链接库(DLL)中的输出库函数地址
/// </summary>
/// <param name="hModule"> DLL模块句柄 包含此函数的DLL模块的句柄。LoadLibrary或者GetModuleHandle函数可以返回此句柄。</param>
/// <param name="lpProcName">函数名 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。</param>
/// <returns>调用成功,返回DLL中的输出函数地址,调用失败,返回0。得到进一步的错误信息,调用函数GetLastError。</returns>
[DllImport("kernel32.dll")]
public static extern int GetProcAddress(int hModule, string lpProcName);
/// <summary>
/// 获取一个应用程序或动态链接库的模块句柄
/// </summary>
/// <param name="moduleName">指定模块名,这通常是与模块的文件名相同的一个名字</param>
/// <returns>如执行成功成功,则返回模块句柄。零表示失败</returns>
[DllImport("kernel32.dll")]
public static extern int GetModuleHandleA(string moduleName);
/// <summary>
/// 创建一个在其它进程地址空间中运行的线程(也称:创建远程线程).
/// </summary>
/// <param name="process">目标进程的句柄</param>
/// <param name="threadAttributes">指向线程的安全描述结构体的指针,一般设置为0,表示使用默认的安全级别</param>
/// <param name="stackSize">线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M</param>
/// <param name="startAddress">线程函数的地址</param>
/// <param name="parameter">传给线程函数的参数</param>
/// <param name="creationFlags">线程的创建方式(0表示线程创建后立即运行 CREATE_SUSPENDED 0x00000004以挂起方式创建 创建不会运行,直到调用 ResumeThread函数)</param>
/// <param name="threadid">指向所创建线程句柄的指针,如果创建失败,该参数为0</param>
/// <returns>如果调用成功,返回新线程句柄,失败返回0</returns>
[DllImport("kernel32.dll")]
public static extern int CreateRemoteThread(IntPtr process, int threadAttributes, int stackSize, int startAddress, int parameter, int creationFlags, int threadid);



/// <summary>
/// 根据进程名称获取进程
/// </summary>
/// <param name="ProcessName">进程名称</param>
/// <returns></returns>
public Process GetProcessByName(string ProcessName)
{
//取得所有进程
Process[] pname = Process.GetProcesses();
//遍历进程
foreach (Process name in pname)
{
//如果查找到进程名称 返回
if (name.ProcessName.ToLower().IndexOf(ProcessName) != -1)
return name;
}
return null;
}



public void killDll()
{
string dllName = "c:\\text.dll";
int dlllength = dllName.Length + 1;
//这里以记事本为例
Process processName = GetProcessByName("notepad");
//如果查找到记事本进程,那么下面开始注入
if (processName != null)
{
//申请内存空间,执行成功就返回分配内存的首地址,不成功就是0。
int baseaddress = VirtualAllocEx(processName.Handle, 0, dlllength, 4096, 4);
if (baseaddress == 0)
{
MessageBox.Show("申请内存空间失败!");
return;
}
//写内存
int result = WriteProcessMemory(processName.Handle, baseaddress, dllName, dlllength, 0);
if (result == 0)
{
MessageBox.Show("写内存失败!");
return;
}
//取得loadlibarary在kernek32.dll地址
int procAddress = GetProcAddress(GetModuleHandleA("Kernel32"), "LoadLibraryA");
if (procAddress == 0)
{
MessageBox.Show("无法取得函数的入口点!");
return;
}
//创建远程线程。
result = CreateRemoteThread(processName.Handle, 0, 0, 0, baseaddress, 0, 0);
if (result == 0)
{
MessageBox.Show("创建远程线程失败!");
return;
}
else
MessageBox.Show("已成功注入dll!");
}
}
标签:C#,API
0
投稿

猜你喜欢

  • java如何获得redis所有的key-value

    2022-03-13 12:22:14
  • 一文带你掌握Spring Security框架的使用

    2021-12-02 09:41:00
  • 流式图表拒绝增删改查之kafka核心消费逻辑上篇

    2023-04-19 03:32:11
  • 利用C#实现最基本的小说爬虫示例代码

    2023-09-25 15:48:17
  • java 输入一个数字组成的数组(输出该数组的最大值和最小值)

    2023-11-24 21:41:58
  • 自定义类加载器以及打破双亲委派模型解析

    2023-06-22 22:03:59
  • SpringBoot整合java诊断工具Arthas解读

    2023-08-07 10:39:03
  • Java数据结构之优先级队列(堆)图文详解

    2021-06-25 13:47:58
  • JavaWeb开发之使用jQuery与Ajax实现动态联级菜单效果

    2023-11-28 19:46:08
  • 解决mybatis-plus自动配置的mapper.xml与java接口映射问题

    2023-08-25 04:16:02
  • 详解Java中NullPointerException异常的原因详解以及解决方法

    2023-01-22 20:13:28
  • Java命令设计模式详解

    2022-07-14 04:38:31
  • Java使用条件语句和循环结构确定控制流(实例)

    2022-07-04 04:52:35
  • 如何用C#找出数组中只出现了一次的数字

    2021-06-15 15:42:56
  • spring mvc+localResizeIMG实现HTML5端图片压缩上传

    2023-07-11 15:31:51
  • Java修饰符 abstract,static,final 的区别详解

    2023-12-19 22:11:25
  • Java实战之敏感词过滤器

    2022-01-18 10:32:03
  • Java 方法签名详解及实例代码

    2022-02-04 05:56:06
  • Unity实现俄罗斯方块(二)

    2022-01-15 06:57:56
  • Android kotlin使用注解实现防按钮连点功能的示例

    2023-07-02 11:58:06
  • asp之家 软件编程 m.aspxhome.com