麻了,之前写的博客全是收藏,没人点赞,来点赞行不行!
GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review
公众号:URLeisure 的复习仓库
公众号二维码见文末
以下是本篇文章正文内容,下面案例可供参考。
写在开头:感谢好友 ‘樱桃破’ 的不懈讲解!
个人水平有限,如有错误还请各位不吝赐教,在评论区指出错误或私信错误,感谢。
DLL 注入(英语:DLL injection)是一种涉及计算机信息安全的特殊编程技术。
它可以强行使一个 进程 加载某个 动态链接库 以在其私有地址空间内运行指定 代码(往往是恶意代码)。
DLL 注入 的常见手段是用外部 DLL 库覆盖一个程序原先的 DLL 库,目的是实现该程序的作者未预期的结果。
比如,注入的代码可以 挂钩(Hook) 系统消息或系统调用,以达到读取密码框的内容等危险目的,而一般编程手段无法达成这些目的。
能将任意代码注入任意进程的程序被称为 DLL 注入器(DLL injector)。
Windows 操作系统中,每个进程都有自己 独立的 4G 虚拟内存空间 (保护模式),当程序真正使用时,操作系统才会分配对应的物理内存。
也就是 不同进程 有着自己 独立的地址空间。
例如,对进程 A 中地址 0x1000000 处的数据进行修改,并不会改变进程 B 中地址 0x1000000 处的数据,甚至进程 B 中可能不存在此地址。
由于不同进程的地址空间相互独立(保护模式),我们很难编写能够与其它进程通信或控制其它进程的程序。
DLL 注入即是,存在进程 A、B,使进程 A 中的 dll 文件强行在进程 B 中加载,此时进程 A 的 dll 文件就进入了进程 B 的地址空间,并使进程 B 执行 dll 文件中的代码。
由于 dll 文件由恶意程序开发者设计,因此程序开发者可对程序 B(目标进程)进行自定义修改。






// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "stdlib.h"
#include using namespace std;BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved
){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: {// 当DLL被进程 <<第一次>> 调用时,导致DllMain函数被调用,HWND hwnd = GetActiveWindow();MessageBox(hwnd, L"DLL已进入目标进程。", L"信息", MB_ICONINFORMATION); //弹出一个模态对话框}}return TRUE;
}
//我们注入记事本
system("start %windir%\\system32\\notepad.exe");//打开
/**
*info ---> 存放快照进程信息的一个结构体
*processName ---> 进程名
* 通过获取系统快照,得到进程列表,通过进程名,遍历进程列表得到 pid
*/
BOOL getProcess32Info(PROCESSENTRY32* info, const TCHAR processName[]){HANDLE handle; handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得系统快照句柄info->dwSize = sizeof(PROCESSENTRY32);Process32First(handle, info);//从快照中获取进程列表while (Process32Next(handle, info) != FALSE){if (wcscmp(processName, info->szExeFile) == 0){return TRUE;//找到了}}return FALSE;
}
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);//返回指定进程的打开句柄,并获得此进程最高权限
if (hProc == 0) return -1;int pathSize = (wcslen(DllFullPath) + 1) * sizeof(wchar_t);//DllFullPath ---> dll 文件路径 计算所需空间大小LPVOID buffer = VirtualAllocEx(hProc, 0, pathSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);//申请内存
if (buffer == 0) return -2;
if (!WriteProcessMemory(hProc, buffer, DllFullPath, pathSize, NULL)) return -3;//并判断是否成功
//调用Kernel32.dll中的LoadLibraryW方法用以加载DLL文件
LPVOID pFunc = GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryW");//创建一个在另一个进程的虚拟地址空间中运行的线程
CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)pFunc, buffer, 0, 0);
dllmain.cpp(示例):
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "stdlib.h"
#include using namespace std;BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved
){switch (ul_reason_for_call) {case DLL_PROCESS_ATTACH: {// 当DLL被进程 <<第一次>> 调用时,导致DllMain函数被调用,HWND hwnd = GetActiveWindow();MessageBox(hwnd, L"DLL已进入目标进程。", L"信息", MB_ICONINFORMATION); //弹出一个模态对话框}}return TRUE;
}
注入器代码(示例):
#include
#include
#include
#include
#include using namespace std;BOOL getProcess32Info(PROCESSENTRY32 *info, const TCHAR processName[]) {HANDLE handle;handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);info->dwSize = sizeof(PROCESSENTRY32);Process32First(handle, info);while (Process32Next(handle, info) != FALSE) {if (wcscmp(processName, info->szExeFile) == 0) {return TRUE;}}return FALSE;
}int InjectDLL(const wchar_t *DllFullPath, const DWORD pid) {HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);if (hProc == 0) return -1;int pathSize = (wcslen(DllFullPath) + 1) * sizeof(wchar_t);LPVOID buffer = VirtualAllocEx(hProc, 0, pathSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (buffer == 0) return -2;if (!WriteProcessMemory(hProc, buffer, DllFullPath, pathSize, NULL)) return -3;LPVOID pFunc = GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryW");CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE) pFunc, buffer, 0, 0);
}int main() {system("start %windir%\\system32\\notepad.exe");PROCESSENTRY32 info;if (getProcess32Info(&info, L"notepad.exe")) {InjectDLL(L"E:\\Dll1.dll", info.th32ProcessID);} else {cout << "查找失败" << endl;}return 0;
}

本次 DLL 注入取巧用了 LoadLibrary
一些安全软件对 LoadLibrary 这样的 API 十分敏感,且 DLL 文件本身也容易被检测并被删除
要解决这些问题,就需要用到 反射型 DLL 注入(没做)。

下期预告: 基于数据报套接字的并发服务器的设计与实现