1.简介

从根本上来说,DLL注入技术要求目标进程中的一个线程调用LoadLibrary来载入我们想要的DLL。由于我们不能轻易地控制别人进程中的线程,因此这种方法要求我们在目标进程中创建一个新的线程,Windows提供了创建远程线程的函数。

HANDLE CreateRemoteThread([in]  HANDLE                 hProcess,[in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,[in]  SIZE_T                 dwStackSize,[in]  LPTHREAD_START_ROUTINE lpStartAddress,[in]  LPVOID                 lpParameter,[in]  DWORD                  dwCreationFlags,[out] LPDWORD                lpThreadId
);
  • hProcess:用于创建线程的进程的句柄。
  • lpThreadAttributes:指向SECURITY_ATTRIBUTES结构的指针,该结构确定返回的句柄是否可以被子进程继承。
  • dwStackSize:堆栈的初始大小,以字节为单位。如果此参数为零,则新线程使用默认大小。
  • lpStartAddress:指向线程要执行的应用程序定义函数的指针。
  • lpParameter:指向要传递给线程的变量的指针。
  • dwCreationFlags:控制线程创建的标志。
  • lpThreadId:指向接收线程标识符的变量的指针。如果该参数为NULL,则不返回线程标识符。

2.步骤

  • 用VirtualAllocEx函数在远程进程的地址空间中分配一块内存。
  • 用WriteProcessMemory函数把DLL的路径名复制到第一步分配的内存中。
  • 用GetProcAddress函数来得到LoadLibraryW或LoadLibraryA函数的实际地址(在Kernel32.dll中)
  • 用CreateRemoteThread函数在远程进程中创建一个线程,让新线程调用正确的LoadLibrary函数并在参数中传入第一步分配的内存地址。这时,DLL已经被注入到远程进程的地址空间中,DLL的DllMain函数会收到DLL_PROCESS_ATTACH通知并且执行我们想要执行的代码。
  • VirtualFreeEx来释放第1步分配的内存。
  • 用GetProcAddress函数来得到FreeLibrary函数的实际地址(在Kernel32.dll中)
  • 用CreateRemoteThread函数在远程进程中创建一个线程,让新线程调用FreeLibrary函数并在参数中传入远程DLL的HMODULE。

步骤1、2、3原理简介:

字符串“D://remoteDll.dll”,位于调用进程的空间地址中,我们把这个地址传给新创建的远程线程,远程线程再把它传给LoadLibrary,当LoadLibrary去访问这个内存地址的时候,DLL的路径字符串并不在那里,远程进程的线程就很可能引发访问违规。为了解决这个问题,我们需要把DLL的字符串存放到远程进程的地址空间中去,所以会使用VirtualAllocEx和WriteProcessMemory方法。

3.示例

3.1先做一个动态库remoteDll.dll

此库的功能是,一旦被注入到进程的地址空间中,就报告该进程正在使用的所有DLL,并将打印信息写入到本地文件D://out.txt中。

const char* filepath = "D://out.txt";BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{FILE* fp = freopen(filepath, "w", stdout);PBYTE pb = NULL;MEMORY_BASIC_INFORMATION mbi;while (VirtualQuery(pb, &mbi, sizeof(mbi)) == sizeof(mbi)){int nlen;char szModName[MAX_PATH];if (mbi.State == MEM_FREE)mbi.AllocationBase = mbi.BaseAddress;if ((mbi.AllocationBase == hModule) || (mbi.AllocationBase != mbi.BaseAddress) || (mbi.AllocationBase == NULL))nlen = 0;else{nlen = GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, szModName, _countof(szModName));}if (nlen > 0){char szBuf[MAX_PATH] = { 0 };wsprintfA(szBuf, "\n%p-%s", mbi.AllocationBase, szModName);printf("%s\n", szBuf);}pb += mbi.RegionSize;} fclose(fp);}break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;
}

3.2写一个测试程序

新建一个带界面的程序

改了一下窗口界面,这里加了一个菜单项注入。

点击注入出现弹窗,如下图所示。

输入进程ID,点击确定即可,下面是注入的回调函数。

// “注入”框的消息处理程序。
INT_PTR CALLBACK Inject(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:{return (INT_PTR)TRUE;}case WM_COMMAND:if (LOWORD(wParam) == IDOK){//获取ID值DWORD processID = GetDlgItemInt(hDlg, IDC_EDIT1, NULL, FALSE);if (processID == 0){processID = GetCurrentProcessId();}if (InjectLib(processID, TEXT("D://remoteDll.dll"))){printf("inject ok");EjectLib(processID, TEXT("D://remoteDll.dll"));}else{printf("inject failed");}EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}else if (LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;
}

InjectLib函数如下:

BOOL WINAPI InjectLib(DWORD processID, PCWSTR pszLibFile)
{BOOL bOk = FALSE;HANDLE hProcess = NULL, hThread = NULL;PWSTR pszLibFileRemote = NULL;__try{hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD |PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, processID);if (hProcess == NULL)__leave;int cch = 1 + lstrlenW(pszLibFile);int cb = cch * sizeof(wchar_t);pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);if (pszLibFileRemote == NULL)__leave;if (!WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, cb, NULL))__leave;FARPROC pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");if (pfnThreadRtn == NULL)__leave;hThread = CreateRemoteThread(hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pfnThreadRtn, pszLibFileRemote, 0, NULL);if (hThread == NULL)__leave;WaitForSingleObject(hThread, INFINITE);bOk = TRUE;}__finally{if (pszLibFileRemote != NULL)VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);if (hThread != NULL)CloseHandle(hThread);if (hProcess != NULL)CloseHandle(hProcess);}return bOk;
}

EjectLib函数如下:

BOOL WINAPI EjectLib(DWORD processID, PCWSTR pszLibFile)
{BOOL bOk = FALSE;HANDLE hthSnapshot = NULL;HANDLE hProcess = NULL, hThread = NULL;PWSTR pszLibFileRemote = NULL;__try{//获取指定进程的快照,以及这些进程使用的堆、模块和线程。hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);if (hthSnapshot == INVALID_HANDLE_VALUE)__leave;MODULEENTRY32W me = { sizeof(me) };BOOL bFound = FALSE;BOOL bMoreMods = Module32FirstW(hthSnapshot, &me);  //检索与进程关联的第一个模块的信息。for (; bMoreMods; bMoreMods = Module32NextW(hthSnapshot, &me)) //检索与进程或线程关联的下一个模块的信息{bFound = (_wcsicmp(me.szModule, pszLibFile) == 0) || (_wcsicmp(me.szExePath, pszLibFile));if (bFound)break;}if (!bFound)__leave;hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD |PROCESS_VM_OPERATION, FALSE, processID);if (hProcess == NULL)__leave;FARPROC pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");if (pfnThreadRtn == NULL)__leave;//me.modBaseAddr 在所属进程的上下文中模块的基地址。hThread = CreateRemoteThread(hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pfnThreadRtn, me.modBaseAddr, 0, NULL);if (hThread == NULL)__leave;WaitForSingleObject(hThread, INFINITE);bOk = TRUE;}__finally{if (hthSnapshot != NULL)CloseHandle(hthSnapshot);if (hThread != NULL)CloseHandle(hThread);if (hProcess != NULL)CloseHandle(hProcess);}return bOk;
}

3.3执行程序

打开一个记事本程序,找到PID,如下图所示,PID = 20752。

运行3.2中的程序,输入这个PID,点击确定注入成功。

3.4运行结果

注入之后,在本地文件out.txt中,可以看见正在该记事本程序正在使用的DLL。

DLL注入——使用远程线程相关推荐

  1. DLL注入_远程线程注入

    什么是线程注入? 线程注入,是通过开启远程线程的方式,将DLL加载到目标宿主进程中的常用方式. 什么是动态链接库? 首先Windows中链接库分为两种:动态链接库DLL.静态链接库LIB. ① 静态链 ...

  2. DLL注入:远程线程注入

    Dll 代码: #include "stdafx.h" #include <iostream> #include <Windows.h> #include ...

  3. 代码注入之远程线程篇

    引子 前些日子由于项目要求,在网上到处找资料,于无意中发现了 CodeProject 上的一篇很老的文章,文章标题为: Three Ways to Inject Your Code into Anot ...

  4. windows-CODE注入(远程线程注入)

    远程线程注入(先简单说,下面会详细说) 今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式 ...

  5. 远程注入利用远程线程直接注入

    利用远程线程无DLL直接注入 (okwary) 小叹的学习园地 注入代码到其他进程地址空间的方法是使用WriteProcessMemory API.这次你不用编写一个独立的DLL而是直接复制你的代码到 ...

  6. 代码注入之远程线程篇 转载自 Zachary.XiaoZhen - 梦想的天空

    引子 前些日子由于项目要求,在网上到处找资料,于无意中发现了 CodeProject 上的一篇很老的文章,文章标题为: Three Ways to Inject Your Code into Anot ...

  7. 实现HOOK其他进程的Messagebox(2) DLL注入工具

    DLL注入工具(远程线程技术和简单的MFC CListCtrl控件知识). DLL文件已经编写好.测试程序也很简单.现在就是解决将DLL注入到目标进程中.. 这里采用远程线程注入技术..本来WIN32 ...

  8. bcb dll返回字符_⑩的游戏修改小课堂4——HOOK、DLL注入与游戏乱码修正

    本文采用 CC-BY-NC 协议进行授权. 本文的涉及代码已上传到GITHUB~ https://github.com/rumia-san/hook_finale​github.com 因为是以< ...

  9. WinAPI【远程注入】利用远程线程注入DLLDelphi版

    { WinAPI[远程注入]利用远程线程注入DLLDelphi版} (okwary) 小叹的学习园地 ( SDK文档里是这样描述的:进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的 ...

  10. 软件安全之代码注入技术 向目标 PE 文件注入 DLL notepad lpk.dll 远程线程函数 提权函数 OpenProcess VirtualAllocEx

    实验 4 代码注入技术 引言 1.实验说明 代码注入是将用户代码注入到其他进程或者可执行文件中,实现拦截目标进程运行过程的关键信息.改变目标进程或可执行文件原本执行流程等目的 2.实验目的 本实验通过 ...

最新文章

  1. cmd与monkey测试
  2. 怎样增加混凝土粘聚性_如何改善中低强度等级混凝土粘聚性? 这篇文章一定要看...
  3. if语句的一个错误记录,多了个“;”号
  4. 揭开互联网公司的神秘面纱,数据解读那些slay整个行业的互联网公司
  5. 萧山职称计算机考试培训,浙江萧山2017年职称计算机考试时间安排
  6. java求二阶微积分方程特解_Scipy:实现微分方程的两种方法:两种不同的解决方案:回答...
  7. html改变游戏速度变慢,游戏不顺畅,卡顿的显卡设置方法
  8. 微信开放平台修改应用名称
  9. python填充三角形颜色_python的pillow用ImageDraw.Draw.polygon如何填充半透明的颜色
  10. 【数学】 海 盗 埋 宝
  11. windows10插入耳机没有反应的问题
  12. 百度文字识别 百度OCR接口申请
  13. 【2023秋招】9月京东校招题目(Js实现)以及满分解析
  14. 制造企业有可能自行开发ERP系统吗?
  15. 六级考研单词之路-五十三
  16. 操作系统(Operation System, OS)
  17. AD-SAL与MD-SAL的比较
  18. porttunnel
  19. 面试官:“说一下从 url 输入到返回请求的过程”
  20. ATEC倒计时17天 | 港版支付宝AlipayHK加持的香港“无现金”生活(赠门票)

热门文章

  1. 北京计算机应用基础考试时间,07年北京市自学考试计算机应用基础课周末开考...
  2. 基于微信会议室预约小程序毕业设计设计与实现 开题报告参考
  3. 9.4SAS软件入门
  4. 人人开源搭建后台管理系统
  5. android mmkv使用_腾讯开源存储框架MMKV
  6. 网上一些《算法(第四版)》习题答案链接
  7. java飞机大战boss素材_java小游戏飞机大战 源代码以及素材
  8. 高斯克吕格投影与墨卡托投影(通用横轴墨卡托、web墨卡托等)
  9. PHP常用函数集合(可做桌面壁纸)
  10. 数据库常见笔试面试题及答案