找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 148|回复: 0

[工具类] 使用C#调用系统API实现内存注入

[复制链接] IP属地:广东省广州市
发表于 2022-12-28 09:52:50 | 显示全部楼层 |阅读模式
本帖最后由 shiy720 于 2022-12-28 09:53 编辑

  1. //首先导入命名空间
  2. using System.Runtime.InteropServices;
  3. /// <summary>
  4. /// 在指定进程的虚拟地址空间中保留或开辟一段区域..除非MEM_RESET被使用,否则将该内存区域初始化为0.
  5. /// </summary>
  6. /// <param name="process">需要在其中分配空间的进程的句柄.这个句柄必须拥有PROCESS_VM_OPERATION访问权限</param>
  7. /// <param name="pAddress">想要获取的地址区域.一般用NULL自动分配</param>
  8. /// <param name="size">要分配的内存大小.字节单位.注意实际分 配的内存大小是页内存大小的整数倍</param>
  9. /// <param name="type">内存分配的类型</param>
  10. /// <param name="protect">内存页保护</param>
  11. /// <returns>执行成功就返回分配内存的首地址,失败返回0。</returns>
  12. [DllImport("kernel32.dll")] //声明API函数
  13. public static extern int VirtualAllocEx(IntPtr process, int pAddress, int size, int type, int protect);
  14. /// <summary>
  15. /// 写入某一进程的内存区域。入口区必须可以访问,否则操作将失败
  16. /// </summary>
  17. /// <param name="process">进程句柄</param>
  18. /// <param name="baseAddress">要写的内存首地址</param>
  19. /// <param name="buffer">指向要写的数据的指针(数据当前存放地址)。</param>
  20. /// <param name="nSize">要写入的字节数。</param>
  21. /// <param name="lpNumberOfBytesWritten">实际数据的长度</param>
  22. /// <returns>非零表示成功,零表示失败</returns>
  23. [DllImport("kernel32.dll")]
  24. public static extern int WriteProcessMemory(IntPtr process, int baseAddress, string buffer, int nSize, int lpNumberOfBytesWritten);
  25. /// <summary>
  26. /// 检索指定的动态链接库(DLL)中的输出库函数地址
  27. /// </summary>
  28. /// <param name="hModule"> DLL模块句柄 包含此函数的DLL模块的句柄。LoadLibrary或者GetModuleHandle函数可以返回此句柄。</param>
  29. /// <param name="lpProcName">函数名 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。</param>
  30. /// <returns>调用成功,返回DLL中的输出函数地址,调用失败,返回0。得到进一步的错误信息,调用函数GetLastError。</returns>
  31. [DllImport("kernel32.dll")]
  32. public static extern int GetProcAddress(int hModule, string lpProcName);
  33. /// <summary>
  34. /// 获取一个应用程序或动态链接库的模块句柄
  35. /// </summary>
  36. /// <param name="moduleName">指定模块名,这通常是与模块的文件名相同的一个名字</param>
  37. /// <returns>如执行成功成功,则返回模块句柄。零表示失败</returns>
  38. [DllImport("kernel32.dll")]
  39. public static extern int GetModuleHandleA(string moduleName);
  40. /// <summary>
  41. /// 创建一个在其它进程地址空间中运行的线程(也称:创建远程线程).
  42. /// </summary>
  43. /// <param name="process">目标进程的句柄</param>
  44. /// <param name="threadAttributes">指向线程的安全描述结构体的指针,一般设置为0,表示使用默认的安全级别</param>
  45. /// <param name="stackSize">线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M</param>
  46. /// <param name="startAddress">线程函数的地址</param>
  47. /// <param name="parameter">传给线程函数的参数</param>
  48. /// <param name="creationFlags">线程的创建方式(0表示线程创建后立即运行 CREATE_SUSPENDED 0x00000004以挂起方式创建 创建不会运行,直到调用 ResumeThread函数)</param>
  49. /// <param name="threadid">指向所创建线程句柄的指针,如果创建失败,该参数为0</param>
  50. /// <returns>如果调用成功,返回新线程句柄,失败返回0</returns>
  51. [DllImport("kernel32.dll")]
  52. public static extern int CreateRemoteThread(IntPtr process, int threadAttributes, int stackSize, int startAddress, int parameter, int creationFlags, int threadid);
复制代码
  1. /// <summary>
  2. /// 根据进程名称获取进程
  3. /// </summary>
  4. /// <param name="ProcessName">进程名称</param>
  5. /// <returns></returns>
  6. public Process GetProcessByName(string ProcessName)
  7. {
  8.      //取得所有进程
  9.      Process[] pname = Process.GetProcesses();
  10.      //遍历进程
  11.      foreach (Process name in pname)
  12.      {
  13.           //如果查找到进程名称 返回
复制代码
这里以记事本为例
  1. public void killDll()
  2. {
  3.      string dllName = "c:\\text.dll";
  4.      int dlllength = dllName.Length + 1;
  5.      //这里以记事本为例
  6.      Process processName = GetProcessByName("notepad");
  7.      //如果查找到记事本进程,那么下面开始注入
  8.      if (processName != null)
  9.      {
  10.      //申请内存空间,执行成功就返回分配内存的首地址,不成功就是0。
  11.      int baseaddress = VirtualAllocEx(processName.Handle, 0, dlllength, 4096, 4);
  12.      if (baseaddress == 0)
  13.      {
  14.      MessageBox.Show("申请内存空间失败!");
  15.      return;
  16.      }
  17.      //写内存
  18.      int result = WriteProcessMemory(processName.Handle, baseaddress, dllName, dlllength, 0);
  19.      if (result == 0)
  20.      {
  21.      MessageBox.Show("写内存失败!");
  22.      return;
  23.      }
  24.      //取得loadlibarary在kernek32.dll地址
  25.      int procAddress = GetProcAddress(GetModuleHandleA("Kernel32"), "LoadLibraryA");
  26.      if (procAddress == 0)
  27.      {
  28.           MessageBox.Show("无法取得函数的入口点!");
复制代码


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|西兴社区 ( 蜀ICP备2022005627号 )|网站地图

GMT+8, 2024-12-27 12:30 , Processed in 1.016155 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表