[笔记]Windows安全之《二》Session0隔离及相关启动技术

简介: [笔记]Windows安全之《二》Session0隔离及相关启动技术

穿透Session 0 隔离(一)

创建用户桌面进程(突破Session 0隔离)

《Windows 黑客编程》

前言

Session0会话:在Windows XP、Windows Server 2003,以及更老版本的Windows操作系统中,第一个登录到控制台的用户来启动服务和应用程序,该会话被认为是服务会话,它包含了宿纳系统的服务的进程,该会话就称为SESSION 0。

例如第一个登录的用户创建 Session 1,第二个登录的用户创建Session 2,以此类推,如下图所示。

而将服务和用户应用程序一起在SESSION0中运行会导致安全风险,因为服务会使用提升后的权限来运行,而用户应用程序使用用户特权(大部分都是非管理员用户)运行,这会使得恶意软件把某个服务作为攻击目标,通过“劫持”该服务以达到提升自己权限级别的目的。

Session0隔离

Session0隔离:位于Session0会话的服务程序在Win7及以上(通常是内核6.0以上)是无法进行与UI进行通信的.

从Windows VISTA开始,只有服务可以托管到SESSION0中,用户应用程序和服务之间会进行隔离,并需要运行在用户登录系统时创建的后续会话中。

如第一个登录用户创建Session1,第二个登录用户创建Session2,以此类推。

使用不同会话运行的实体(应用程序或服务)如果不将自己明确标注为全局命名空间,并提供相应的访问控制设置,那么将无法互相发送消息,共享UI元素或共享内核对象。

场景

有些服务可能需要在用户界面上显示对话框,或需要与用户的应用程序通讯,这种类型的功能“通常”属于Windows XP服务,因为在Windows XP中,这样做很容易。如果服务恰好需要显示某些用户界面对象,例如对话框,或者需要与应用程序通讯,则在Windows 7下运行可能会遇到问题。

原因

由于SESSION0的隔离,使得在系统服务进程内不能直接调用CreateProcess等函数创建进程,而只能通过CreateProcessAsUser函数来创建。这样,创建的进程才会显示UI界面,与用户进行交互。

解决方案

在SESSION0中创建用户桌面进程具体的实现流程:

  1. 调用WTSGetActiveConsoleSessionId函数来获取当前程序的会话ID,即Session Id。
  2. 根据Session Id继续调用WTSQueryUser Token函数来检索用户令牌,并获取对应的用户令牌句柄。在不需要使用用户令牌句柄时,可以调用CloseHandle函数来释放句柄。
  3. 使用DuplicateTokenEx函数创建一个新令牌,并复制上面获取的用户令牌。设置新令牌的访问权限为MAXIMUM ALLOWED,这表示获取所有令牌权限。新访问令牌的模拟级别为SecurityIdentification,而且令牌类型为TokenPrimary,这表示新令牌是可以在CreateProcessAsUser函数中使用的主令牌。
  4. 根据新令牌调用CreateEnvironmentBlock函数创建一个环境块,用来传递给CreateProcessAsUser使用。在不需要使用进程环境块时,可以通过调用DestroyEnvironmentBlock函数进行释放。获取环境块后,就可以调用CreateProcessAsUser来创建用户桌面进程。CreateProcessAsUser函数的用法以及参数含义与CreateProcess函数的用法和参数含义类似。新令牌句柄作为用户主令牌的句柄,指定创建进程的路径,设置优先级和创建标志,设置STARTUPINFO结构信自,获取PROCESS
    INFORMATION结构信息

代码实现

参考windows黑客编程技术详解之4.2 突破SESSION 0隔离创建用户进程

// 突破SESSION 0隔离创建用户进程
BOOL CreateUserProcess(char *lpszFileName)
{
  BOOL bRet = TRUE;
  DWORD dwSessionID = 0;
  HANDLE hToken = NULL;
  HANDLE hDuplicatedToken = NULL;
  LPVOID lpEnvironment = NULL;
  STARTUPINFO si = { 0 };
  PROCESS_INFORMATION pi = { 0 };
  si.cb = sizeof(si);
  do
  {
    // 获得当前Session ID
    dwSessionID = ::WTSGetActiveConsoleSessionId();
    // 获得当前Session的用户令牌
    if (FALSE == ::WTSQueryUserToken(dwSessionID, &hToken))
    {
      ShowMessage("WTSQueryUserToken", "ERROR");
      bRet = FALSE;
      break;
    }
    // 复制令牌
    if (FALSE == ::DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
      SecurityIdentification, TokenPrimary, &hDuplicatedToken))
    {
      ShowMessage("DuplicateTokenEx", "ERROR");
      bRet = FALSE;
      break;
    }
    // 创建用户Session环境
    if (FALSE == ::CreateEnvironmentBlock(&lpEnvironment,
      hDuplicatedToken, FALSE))
    {
      ShowMessage("CreateEnvironmentBlock", "ERROR");
      bRet = FALSE;
      break;
    }
    // 在复制的用户Session下执行应用程序,创建进程
    if (FALSE == ::CreateProcessAsUser(hDuplicatedToken,
      lpszFileName, NULL, NULL, NULL, FALSE,
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
      lpEnvironment, NULL, &si, &pi))
    {
      ShowMessage("CreateProcessAsUser", "ERROR");
      bRet = FALSE;
      break;
    }
  } while (FALSE);
  // 关闭句柄, 释放资源
  if (lpEnvironment)
  {
    ::DestroyEnvironmentBlock(lpEnvironment);
  }
  if (hDuplicatedToken)
  {
    ::CloseHandle(hDuplicatedToken);
  }
  if (hToken)
  {
    ::CloseHandle(hToken);
  }
  return bRet;
}

启动技术

创建进程API

可参考博文 Windows几种常见运行命令行方式

内存直接加载执行

原理

将exe/dll等PE文件载入到进程内存中,找到并执行目标exe/dll的入口点。

基本实现步骤

基本实现步骤:

  1. 首先,在DLL文件中,根据PE结构获取其加载映像的大小SizeOflmage,并根据SizeOflmage在自己的程序中申请可读、可写、可执行的内存,那么这块内存的首地址就是DLL的加载基址。
  2. 其次,根据DLL中的PE结构获取其映像对齐大小SectionAlignment,然后把DLL文件数据按照SectionAlignment复制到上述申请的可读、可写、可执行的内存中。
  3. 接下来,根据PE结构的重定位表,重新对重定位表进行修正。
  4. 然后,根据PE结构的导入表,加载所需的DLL,并获取导入函数的地址并写入导入表中。
  5. 接着,修改DLL的加载基址ImageBase.
  6. 最后,根据PE结构获取DLL的入口地址,然后构造并调用DllMain函数,实现DLL加载。

而exe文件相对于DLL文件实现原理唯一的区别就在于构造入口函数的差别,exe不需要构造DlIMain函数,而是根据PE结构获取exe的人口地址偏移AddressOfEntryPoint并计算出入姚后直接跳转到入口地朴外执行即可。

要特别注意的是,对于exe文件来说,重定位表不是必需的,即使没有重定位表,exe也可正常运行。因为对于exe进程来说,进程最早加载的模块是exe模块,所以它可以按照默认的加载基址加载到内存。对于那些没有重定位表的程序,只能把它加载到默认的加载基址上。如果默认加载基址已被占用,则直接内存加载运行会失败。

总结

  • Session0隔离机制是比较容易绕过的
相关文章
|
1月前
|
安全 数据安全/隐私保护 Windows
解锁安全之门,Windows Server 2019密码修改攻略大揭秘
解锁安全之门,Windows Server 2019密码修改攻略大揭秘
|
3月前
|
缓存 网络协议 数据安全/隐私保护
[运维笔记] - (命令).Windows server常用网络相关命令总结
[运维笔记] - (命令).Windows server常用网络相关命令总结
191 0
|
4月前
|
存储 安全 Apache
2023-10 适用于基于 x64 的系统的 Windows Server 2012 R2 月度安全质量汇总(KB5031419)
2023-10 适用于基于 x64 的系统的 Windows Server 2012 R2 月度安全质量汇总(KB5031419)
290 2
|
1月前
|
弹性计算 安全 数据安全/隐私保护
远程桌面连接Windows实例,提示“为安全考虑,已锁定该用户账户,原因是登录尝试或密码更改尝试过多”错误解决方案
远程桌面连接Windows实例,提示“为安全考虑,已锁定该用户账户,原因是登录尝试或密码更改尝试过多”错误解决方案
212 0
|
1月前
|
安全 数据安全/隐私保护 Windows
Windows 命令提示符(CDM)操作(六):安全和权限
Windows 命令提示符(CDM)操作(六):安全和权限
30 0
|
6月前
|
网络协议 程序员 API
[笔记] Microsoft Windows网络编程《一》WinSock简介(四)
[笔记] Microsoft Windows网络编程《一》WinSock简介(四)
|
3月前
|
存储 网络协议 安全
Windows Server 2022 安全功能重大更新
这篇文将介绍 Windows Server 2022 中的一些新增的安全功能,在 Windows Server 2019 的强大基础之上引入了许多创新功能。
60 0
|
3月前
|
存储 Ubuntu 开发工具
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
|
3月前
|
安全 虚拟化 数据安全/隐私保护
Windows 安全
Windows 安全
43 0
|
4月前
|
Linux API C++
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
音视频windows安装ffmpeg6.0并使用vs调试源码笔记
117 0