c/c++语言开发共享C++ DLL注入工具(完整源码)

先上源码:#include “inject_main.h”#include “resource.h”#include <windows.h>#include <tlhelp32.h&

先上源码:

#include "inject_main.h"  #include "resource.h"  #include <windows.h>  #include <tlhelp32.h>  #include <string>  #include <tchar.h>    using namespace std;      /// <summary>  /// 通过进程名称获取该进程句柄  /// </summary>  /// <param name="processname"></param>  /// <returns>成功返回 dword,失败返回 0</returns>  dword getprocessbyname(const tchar* processname) {      // 获取到整个系统的进程      handle processall = createtoolhelp32snapshot(th32cs_snapprocess, null);        // 定义一个容器,该容器用来接收,进程信息      processentry32w processinfo = { 0 };      processinfo.dwsize = sizeof(processentry32w);        // 根据进程名称,循环判断是否是指定的进程      do      {          if (_tcscmp(processinfo.szexefile, processname) == 0)          {              // 释放进程快照,防止内存泄露              closehandle(processall);              // 如果是返回指定进程句柄              return processinfo.th32processid;          }          // 一个迭代函数      } while (process32next(processall, &processinfo));      // 释放进程快照,防止内存泄露      closehandle(processall);      return 0;  }    /// <summary>  /// 获取指定 dll 的内存地址  /// </summary>  /// <param name="pid"></param>  /// <param name="modulename"></param>  /// <returns></returns>  hmodule getprocessmodulehandle(dword pid, const tchar* modulename) {      moduleentry32 moduleentry;      handle handle = null;      handle = createtoolhelp32snapshot(th32cs_snapmodule, pid);      if (!handle) {          closehandle(handle);          return null;      }      zeromemory(&moduleentry, sizeof(moduleentry32));      moduleentry.dwsize = sizeof(moduleentry32);      if (!module32first(handle, &moduleentry)) {          closehandle(handle);          return null;      }      do {          if (_tcscmp(moduleentry.szmodule, modulename) == 0) {              // 释放进程快照,防止内存泄露              closehandle(handle);              return moduleentry.hmodule;          }      } while (module32next(handle, &moduleentry));      closehandle(handle);      return 0;  }    /// <summary>  /// 把指定dll注入到指定进程中  /// </summary>  /// <param name="processname">processname 进程名称</param>  /// <param name="dllpath">dllpath dll路径</param>  void injectdll(const wchar_t* processname, const char* dllpath) {      // 获取指定进程的句柄      dword dword = getprocessbyname(processname);      if (dword == 0)      {          messagebox(null, text("没有找到指定进程"), text("错误"), 0);          return;      }      // 打开指定进程      handle hprocess = openprocess(process_all_access, false, dword);      if (hprocess == null)      {          messagebox(null, text("指定进程打开失败"), text("错误"), 0);          return;      }      /*          在指定进程的地址,开辟一块内存空间,用来保存 dll的路径信息          lpvoid virtualallocex(          [in]           handle hprocess, 在那个进程中开辟内存          [in, optional] lpvoid lpaddress, 开辟内存的起始地址 (null,不需要控制起始位置)          [in]           size_t dwsize,  开辟内存的大小(当前保存的内容是 dll的路径)          [in]           dword  flallocationtype, 内存分配的类型。(开辟内存)          [in]           dword  flprotect,设置内存的权限 (可读可写)          );       */      lpvoid dlladdress = virtualallocex(hprocess, null, strlen(dllpath), mem_commit, page_readwrite);      /*          把dll的路径,写入到刚开辟出来的内存中          bool writeprocessmemory(          [in]  handle  hprocess, // 指定的进程          [in]  lpvoid  lpbaseaddress, // dll路径字符串,写入的基址          [in]  lpcvoid lpbuffer, // dll路径字符串,的指针          [in]  size_t  nsize, // 需要写入内存的字节长度          [out] size_t  *lpnumberofbyteswritten // [out] 返回一个指针,不需要,null          );      */        if (writeprocessmemory(hprocess, dlladdress, dllpath, strlen(dllpath), null) == 0)      {          messagebox(null, text("路径写入失败"), text("错误"), 0);          return;      }        // 获取 kernel32.dll 这个模块      hmodule k32 = getmodulehandle(text("kernel32.dll"));      // 在 kernel32.dll 模块中找到 loadlibrary 这个函数的内存地址      lpvoid loadadd = getprocaddress(k32, "loadlibrarya");      /*          在指定进程中,创建一个线程          并通过这个线程,调用 loadlibrary 函数          通过 loadlibrary 函数,把 dll 载入到目标进程中          handle createremotethread(          [in]  handle                 hprocess, // 指定进程          [in]  lpsecurity_attributes  lpthreadattributes, // 设置线程安全属性,表示线程是否可以继承,null就够了          [in]  size_t                 dwstacksize, // 堆栈的初始大小,0 表示使用可执行文件的默认大小          [in]  lpthread_start_routine lpstartaddress, // 远程进程中,需要执行的那个函数的指针          [in]  lpvoid                 lpparameter, // 目前进程中 dll路径的指针          [in]  dword                  dwcreationflags, // 0 线程在创建后立即运行。          [out] lpdword                lpthreadid // [out] 当前不需要这个返回值          );      */      handle hthread = createremotethread(hprocess, null, 0, (lpthread_start_routine)loadadd, dlladdress, 0, null);          // 释放指定的模块      closehandle(hthread);      closehandle(hprocess);    }    /// <summary>  /// 把指定进程中的dll卸载掉  /// </summary>  /// <param name="processname"></param>  /// <param name="dllpath"></param>  void uninjectdll(const wchar_t* processname) {      // 通过进程名称获取该进程句柄      dword dword = getprocessbyname(processname);      if (dword == 0)      {          messagebox(null, text("没有找到指定进程"), text("错误"), 0);          return;      }      // 获取指定进程中指定模块的内存地址      hmodule hmodule = getprocessmodulehandle(dword, l"wx_read_write.dll");        // 打开指定进程      handle hprocess = openprocess(process_all_access, false, dword);      if (hprocess == null)      {          messagebox(null, text("指定进程打开失败"), text("错误"), 0);          return;      }        // 获取 kernel32.dll 这个模块      hmodule k32 = getmodulehandle(text("kernel32.dll"));      // 在 kernel32.dll 模块中找到 loadlibrary 这个函数的内存地址      lpvoid loadadd = getprocaddress(k32, "freelibrary");        handle hthread = createremotethread(hprocess, null, 0, (lpthread_start_routine)loadadd, (lpvoid)hmodule, 0, null);        // 释放指定的模块      closehandle(hthread);      closehandle(hprocess);  }      /// <summary>  ///   /// </summary>  /// <param name="hwnddlg"></param>  /// <param name="umsg"></param>  /// <param name="wparam"></param>  /// <param name="lparam"></param>  /// <returns></returns>  int_ptr callback dialogproc(_in_ hwnd hwnddlg, _in_ uint umsg, _in_ wparam wparam, _in_ lparam lparam)  {      wchar_t processname[100] = l"wechat.exe";      char dllpath[400] = { "c://users//qiaoas//documents//visual studio 2015//projects//consoleapplication1//debug//wx_read_write.dll" };      switch (umsg)      {      case wm_initdialog:          break;      case wm_close:          enddialog(hwnddlg, 0); // 关闭窗体          break;      case wm_command:          /*getdlgitemtext(hwnddlg, text_processname, processname, sizeof(processname));          getdlgitemtext(hwnddlg, text_dllpath, (lpwstr)dllpath, sizeof(dllpath));*/            if (wparam == btn_inject_dll)          {              if (sizeof(processname) == 0)              {                  messagebox(null, text("进程名称不能为空"), text("错误"), 0);              }              if (sizeof(dllpath) == 0)              {                  messagebox(null, text("dll路径不能为空"), text("错误"), 0);              }              injectdll(processname, dllpath); // 注入dll          }          if (wparam == btn_uninject_dll)          {              uninjectdll(processname); // 卸载dll          }          break;      default:          break;      }      return false;  }      /// <summary>  /// 初始化  /// </summary>  /// <param name="hinstance"></param>  /// <param name="hprevinstance"></param>  /// <param name="lpcmdline"></param>  /// <param name="ncmdshow"></param>  /// <returns></returns>  int apientry wwinmain(_in_ hinstance hinstance,      _in_opt_ hinstance hprevinstance,      _in_ lpwstr    lpcmdline,      _in_ int       ncmdshow)  {      dialogbox(hinstance, makeintresource(idd_dialog1), null, &dialogproc);      return 0;  }

初学c++,代码可能有些地方写的不够好,但是注入卸载是完全没问题的。

注入逻辑解释:

使用createremotethread 函数可以为目标进程创建一个新的线程。

在一个进程为另一个进程创建的线程就是远程线程。

使用 loadlibrary 函数把指定的dll加载到进程中

因此就可以在创建远程线程的同时调用 loadlibrary 函数,把指定的dll加载到目标进程中。

为什么创建远程线程的时候调用 loadlibrary 函数就能把 dll 注入到目标进程中?

  • loadlibrary  函数是 kernel32.dll 中的一个成员
  • kernel32.dll 这个dll是创建进程必须的一个dll,并且所有进程在内存中指向的 kernel32.dll 是同一个地址
  • 所以只要获取到当前进程中 loadlibrary 函数的地址就够了

为什么要在目标进程中开辟一块内存,再把dll路径写入到块内存中?

  • loadlibrary 函数需要一个参数,就是dll的路径
  • 把当前进程中的一个地址传到另一个进程中,鬼知道另一个进程获取这个地址中的数据时,读取到的是否是我们想要的。
  • 因此需要把dll的路径直接写入到目标进程中。
  • virtualallocex 函数,在目标进程中开辟一块空间,用来存放dll路径
  • writeprocessmemory 函数,把dll的路径写入进去
  • getmodulehandle 获取 kernel32.dll 模块
  • getprocaddress 获取 loadlibrarya 函数在内存中的地址
  • createremotethread 创建远程线程,并调用 loadlibrarya 函数

loadlibraryloadlibraryaloadlibraryw 这三者的区别。

loadlibrary 是一个宏,可以根据字符集的不同,自动决定是使用 loadlibrarya 还是 loadlibraryw

loadlibrary 宏定义的源码:

winbaseapi  _ret_maybenull_  hmodule  winapi  loadlibrarya(      _in_ lpcstr lplibfilename      );    winbaseapi  _ret_maybenull_  hmodule  winapi  loadlibraryw(      _in_ lpcwstr lplibfilename      );    #ifdef unicode  #define loadlibrary  loadlibraryw  #else  #define loadlibrary  loadlibrarya  #endif // !unicode

卸载逻辑:

使用 createremotethread 函数创建一个远程线程

调用 freelibrary 函数,卸载dll

freelibrary 函数在 kernel32.dll 模块中,逻辑同上

freelibrary 函数需要 dll 的内存地址

遍历进程快照可以获取到指定模块的内存地址

卸载和注入的思路都是一样的

确认dll是否注入到目标进程中:

方式一:使用 procexp

C++ DLL注入工具(完整源码)

方式二:cheat engine

C++ DLL注入工具(完整源码)

C++ DLL注入工具(完整源码)

C++ DLL注入工具(完整源码)

确认 kernel32.dll 中的 freelibrary 和 loadlibrarya 在多个进程中是否指向同一块内存地址:

C++ DLL注入工具(完整源码)

 可以通过ce查看多个进程中  kernel32.dll 的内存地址是否相同

再通过  kernel32.dll 中函数的内存地址,确认 freelibrary 和 loadlibrarya 这两个函数

到此这篇关于c++ dll注入工具(完整源码)的文章就介绍到这了,更多相关c++ dll注入工具内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

需要了解更多c/c++开发分享C++ DLL注入工具(完整源码),都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/1045912.html

(0)
上一篇 2022年2月7日
下一篇 2022年2月7日

精彩推荐