原理

核心函数

CreateRemoteThread:让在其他进程中创建一个线程变成可能

核心思想

HANDLE WINAPI 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
);
HMODULE
WINAPI
LoadLibraryW(
_In_ LPCWSTR lpLibFileName
);

CreateRemoteThread函数的第四个参数是线程函数,我们可以用LoadLibrary的函数地址作为线程函数地址。

CreateRemoteThread函数的第五个参数是线程函数参数。用要加载的dll路径作为线程函数的参数。

相当于用这个线程函数(LoadLibrary)把参数(dll路径)Load到“被注入的进程”里。

设计的巧合才出现了这一注入方式

代码实现

获取pid

OpenProcess这个函数有个参数是pid,获取pid的方式多种多样,我这里使用的是快照

 1 //根据进程名找对应的pid(快照方式)
2 DWORD _getProcessHandle(LPCTSTR lpProcessName)
3 {
4 DWORD dwRet = 0;
5 HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
6 if (hSnapShot == INVALID_HANDLE_VALUE)
7 {
8 printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
9 return dwRet;
10 }
11
12 PROCESSENTRY32 pe32;
13 pe32.dwSize = sizeof(PROCESSENTRY32);
14 ::Process32First(hSnapShot, &pe32);
15 do
16 {
17 if (!lstrcmp(pe32.szExeFile, lpProcessName))
18 {
19 dwRet = pe32.th32ProcessID;
20 break;
21 }
22 } while (::Process32Next(hSnapShot, &pe32));
23 ::CloseHandle(hSnapShot);
24 return dwRet;
25 }

打开进程

hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);

在注入进程里申请空间

pAlloc = ::VirtualAllocEx(hprocess,NULL, _SIZE, MEM_COMMIT,PAGE_READWRITE);

因为我们需要找到那个参数(dll路径),在我本来的进程中,dll路径存放的地方和注入进程中dll路径存放的地方不是同一个地方,我们需要跨进程将dll路径写在注入进程中,下面起线程的时候才能找到存放dll路径的字符串

在申请的空间中写入数据

::WriteProcessMemory(hprocess, pAlloc, psDllFillName, _SIZE, NULL);

获得LoadLibraryW的地址

pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");

由于Windows引入了基址随机化ASLR安全机制,所以导致每次开机启动时系统DLL加载基址都不一样,有些系统dll(kernel,ntdll)的加载地址,允许每次启动基址可以改变,但是启动之后必须固定,也就是说两个不同进程在相互的虚拟内存中,这样的系统dll地址总是一样的。

创建线程在注入进程中

hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc,0,NULL);

让这个线程loadlibrary

所有代码

 1 #include <iostream>
2 #include <windows.h>
3 #include <TlHelp32.h>
4 #include "tchar.h"
5
6 //根据进程名找对应的pid(快照方式)
7 DWORD _getProcessHandle(LPCTSTR lpProcessName)
8 {
9 DWORD dwRet = 0;
10 HANDLE hSnapShot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
11 if (hSnapShot == INVALID_HANDLE_VALUE)
12 {
13 printf("\n获得进程快照失败,返回的GetLastError():%d", ::GetLastError());
14 return dwRet;
15 }
16
17 PROCESSENTRY32 pe32;
18 pe32.dwSize = sizeof(PROCESSENTRY32);
19 ::Process32First(hSnapShot, &pe32);
20 do
21 {
22 if (!lstrcmp(pe32.szExeFile, lpProcessName))
23 {
24 dwRet = pe32.th32ProcessID;
25 break;
26 }
27 } while (::Process32Next(hSnapShot, &pe32));
28 ::CloseHandle(hSnapShot);
29 return dwRet;
30 }
31
32
33 //打开一个进程并为其创建一个线程
34 DWORD _InjectThread(DWORD _Pid, LPCWSTR psDllFillName)
35 {
36 //打开进程
37 HANDLE hprocess;
38 HANDLE hThread;
39 DWORD _SIZE = 0;
40 LPVOID pAlloc = NULL;
41 DWORD psDllAddr = 0;
42 FARPROC pThreadFunction;
43 hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);
44 //在注入进程中写入Loadlibrary名称
45 _SIZE = (_tcslen(psDllFillName) + 1)* sizeof(TCHAR);
46 pAlloc = ::VirtualAllocEx(hprocess,NULL, _SIZE, MEM_COMMIT,PAGE_READWRITE);
47 if (pAlloc == NULL)
48 {
49 printf("VirtualAllocExERROR");
50 return FALSE;
51 }
52 BOOL x = ::WriteProcessMemory(hprocess, pAlloc, psDllFillName, _SIZE, NULL);
53 if (FALSE == x)
54 {
55 printf("WriteProcessMemoryERROR");
56 return FALSE;
57 }
58 //获得Loadlibrary的地址
59 pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
60 //在另一个进程创建一个线程
61 hThread = ::CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc,0,NULL);
62 if (hThread == NULL)
63 {
64 printf("CreateRemoteThreadError");
65 return FALSE;
66 }
67 WaitForSingleObject(hThread,-1);
68 GetExitCodeThread(hThread, &psDllAddr);
69 VirtualFreeEx(hprocess, pAlloc, _SIZE, MEM_DECOMMIT);
70 ::CloseHandle(hprocess);
71 return TRUE;
72 }
73 int main()
74 {
75 DWORD PID = _getProcessHandle(L"Test.exe");
76 _InjectThread(PID,L"MessageBox.dll");
77 }

实际上整个过程就是等效于在注入进程中自己LoadLibrary,只不过我们是在其他进程load这个dll

Dll文件

 1 #include "pch.h"
2
3 BOOL APIENTRY DllMain( HMODULE hModule,
4 DWORD ul_reason_for_call,
5 LPVOID lpReserved
6 )
7 {
8 switch (ul_reason_for_call)
9 {
10 case DLL_PROCESS_ATTACH:
11 MessageBox(NULL, L"sucess!!!", L"注入", MB_OK);
12 case DLL_THREAD_ATTACH:
13 MessageBox(NULL, L"sucess!!!", L"注入", MB_OK);
14 case DLL_THREAD_DETACH:
15 case DLL_PROCESS_DETACH:
16 break;
17 }
18 return TRUE;
19 }

测试

一开始没有这个dll

注入后

说明注入成功

dll远线程注入的更多相关文章

  1. 恶意软件开发——突破SESSION 0 隔离的远线程注入

    一.前言 在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能 ...

  2. 动态加载dll的实现+远线程注入

    1.在目标进程中申请内存 2.向目标进程内存中写入shellcode(没有特征,编码比较麻烦) 3.创建远线程执行shellcode 之前可以看到shellcode很难编写还要去依赖库,去字符串区等等 ...

  3. VB.NET实现32位、64位远线程运行ASM,注入非托管、托管DLL

    这是一个老话题,远线程函数给我们提供了机会在其他进程中启动一个新线程,所以我们可以做很多事情.但事情远远没有结束,如果我们要做的事情非常复杂,那么将面临编写大量的ASM代码,虽然我们可以用VC之类的工 ...

  4. Dll注入技术之远程线程注入

    DLL注入技术之远线程注入 DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EX ...

  5. 远程线程注入dll,突破session 0

    前言 之前已经提到过,远线程注入和内存写入隐藏模块,今天介绍突破session 0的dll注入 其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可 ...

  6. 远程线程注入DLL突破session 0 隔离

    远程线程注入DLL突破session 0 隔离 0x00 前言 补充上篇的远程线程注入,突破系统SESSION 0 隔离,向系统服务进程中注入DLL. 0x01 介绍 通过CreateRemoteTh ...

  7. 远程线程注入突破SESSION 0

    远程线程注入突破SESSION 0 SESSION 0 隔离 在Windows XP.Windows Server 2003,以及更老版本的Windows操作系统中,服务和应用程序使用相同的会话(Se ...

  8. 安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程

    简介        大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...

  9. 安全之路 —— 无DLL文件实现远程线程注入

    简介         在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着 ...

随机推荐

  1. node.js & ORM & ODM

    node.js & ORM & ODM ODM & NoSQL Object Data Modeling 对象数据模型 Object Document Mapping 对象文档 ...

  2. 为什么说USDN是一种应用型稳定币?

    USDN是由NGK Global出品的一种新型稳定币系统,里面是涵盖了包括货币供需.Bancor.抵押借贷等在内的一整套算法.该稳定币构想一经提出,便在社区引发了不小的热度. 官方对于USDN的定位是 ...

  3. npm与package.json快速入门

    本文转载自npm与package.json快速入门 导语 npm 是前端开发广泛使用的包管理工具,之前使用 Weex 时看了阮一峰前辈的文章了解了一些,这次结合官方文章总结一下,加深下理解吧! 读完本 ...

  4. canal数据同步的环境配置

    canal数据同步的环境配置:(适用于mysql) 前提:在linux和windows系统的mysql数据库中创建相同结构的数据库和表,我的linux中mysql是用docker实现的(5.7版本), ...

  5. C# 使用 Index 和 Range 简化集合操作

    C# 使用 Index 和 Range 简化集合操作 Intro 有的语言数组的索引值是支持负数的,表示从后向前索引,比如:arr[-1] 从 C# 8 开始,C# 支持了数组的反向 Index,和 ...

  6. JS语法-ES6

    1.介绍 ECMAScript 6简称ES6,是JavaScript语言的下一代标准. 2.常用属性及方法 2.1常量与变量的定义 在JavaScript中,我们一般使用var来定义变量,实际上它是有 ...

  7. 从HashMap面试聊聊互联网内卷

    微信公众号:大黄奔跑 关注我,可了解更多有趣的面试相关问题. 写在之前 毫无疑问,回想2020年有什么词出现在眼前最多的,无疑是"996"和"内卷",从马老师的 ...

  8. DRF 外键字段深度查询优化、ListSerializer辅助完成群改

    目录 一.Response封装 二.外键字段深度查询 1.序列化配置exclude.depth 2.模型层函数.插拔式字段查询 三.listserializer辅助类 一.Response封装 用de ...

  9. Go的switch

    目录 go的switch 一.语法 二.默认情况 三.多表达式判断 四.无表达式 五.Fallthrough go的switch switch 是一个条件语句,用于多条件匹配,可以替换多个if els ...

  10. python:虚拟环境与pip

    原生pip镜像下载速度较慢,配置使用国内镜像.这里选择清华镜像,文档地址:https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ pip 镜像配置 临时使用: ...