Session

我们平常所说的Session是指一次终端登录, 这里的终端登录是指要有自己的显示器和鼠标键盘等, 它包括本地登录和远程登录。在XP时代每次终端登录才会创建一个Session,但是在Vista后所有的服务程序都运行在Session 0, 其他终端会依次运行在session 1, session 2...

Logon Session

登录Session是指不同帐号的登录,它包括System登录, 网络登录及活动交互登录等。 我们在任务管理器里可以看到各种进程运行在不同的帐号下,比如System, Local Service, xxx Account等, 这些帐号有不同的权限。这里要注意区分上面的终端登录Session, 每个终端登录Session内有好几个Logon Session.

Window Station

按MSDN的说法,一个Window Station管理一个剪贴板(Clipboard),一个原子表(Atom Table)和一组桌面(Desktop)。为什么要有Window Station这个概念? 实际上每个Window Station对应一个Logon Session, 也就是说通过Window Station, 把不同的帐号进行隔离,防止他们相互影响, 试想其他人在你机器上执行一个DCOM对象,如果没有Window Station隔离,他可以直接操作你的桌面了。一个终端登录Session可以有多个Window Station,但只能有一个可交互的活动Window Station, 也就是Winsta0.

Desktop

每个Window Station可以创建多个Desktop, 我们平时和3个Desktop打交道比较多(WinLogon, Disconnect, Default), 他们分别代表登录桌面,屏保桌面和我们工作的桌面。我们也可以自己通过CreateDesktop创建桌面, 并通过SwitchDesktop进行切换。

Sid

Sid表示Security Identifier, 它是一串唯一标志符, 它可以表示代表一个帐号, 一个用户组或是一次用户登录等, 具体可以参考这里

Token

Token和进程相关联, 每个进程创建时都会根据Logon Session权限由LSA(Local Security Authority)分配一个Token(如果CreaeProcess时自己指定了Token,  LSA会用该Token, 否则就用父进程Token的一份拷贝,由大部分进程是由Explorer.exe创建, 所以我们大部分时候都复制了explorer.exe的Token), 里面含有该进程的安全信息,包括用户帐号, 组信息, 权限信息和默认安全描述符(Security Descriptor)等, 我们可以通过GetTokenInformation查询某个Token的详细情况。具体可以参考这里

DACL和SACL

DACL(discretionary access control list)用来标志某个安全对象允许被哪些对象访问。SACL(system access control list )用来记录某个安全对象被访问的情况。具体可以参考这里

Security Descriptor

每个安全对象在创建时都可以指定一个安全描述符(Security Descriptor), 如果没有指定就用进程默认的, 该描述符指定了哪些对象可以访问该安全对象。大部分情况下我们都是传NULL, 也就是用该进程Token中默认的。具体可以参考这里

Integrity level

这是UAC提供的新特性, 强制完整性控制(Mandatory Integrity Control), 它标志某进程的安全性级别, 安全级别的高低很大程度和该标志相关联。

下面的图表示了Session, Window Station和Desktop的关系:

下面的图表示当某程序试图访问某个安全对象时, 系统是如何检测的:系统会检测Object的DACL列表, 根据当前进程的Token,判断当前进程(线程)是否允许访问该Object。

我们用Process Explorer查看某个进程的属性时, Security页的信息如何理解?

User和SID项表示创建该进程的用户情况,可以通过GetTokenInformation, 将第二个参数指定成TokenInformationClass来查询。

Session项上面提到过了,表示终端登录session ID,可以通过GetTokenInformation, 将第二个参数指定成TokenSessionId来查询, 也可以通过 API ProcessIDToSessionID来获取

Logon Session表示Logon Session的authority id, 可以通过GetTokenInformation, 将第二个参数指定成TokenStatistics来查询。系统登录的Logon Session id是999(0x3E7), 这里要区分还有一个概念是Logon Session SID, 他们是不同的概念, 前者某种程度上反映了Logon Session的类型, 后则是某次登陆的标志(SID)。

Virtualized是Vista之后才有的概念,表示该程序是否启用了UAC virtualization, 对于没有指定manifest的老程序会使用数据重定向机制。可以通过GetTokenInformation的TokenVirtualizationAllowed/TokenVirtualizationEnabled来查询。

Group是指该用户所在的用户组。我们可以看到尽管我们的用户在Administrators组里,但是上面却显示是Deny的,为什么?因为在Vista之后, UAC打开时, 除非我们显式的Run As Admin, 否则我们的程序都默认运行在标准用户权限下。同时我们注意到上面还有Mandatory label\Medium Mandatory Level项,表示该程序运行的完整性级别, 它包括Untrust, Low, Medium, Hight, System等, 级别越低,权限也就越低。我们可以通过GetTokenInformation的TokenIntegrityLevel来进行查询。

Privilege表示该进程的权限, 我们可以看到好多权限默认是Disabled, 实际上我们可以通过AdjustTokenPrivileges进行提升。 我们可以通过GetTokenInformation的TokenPrivileges进行查询。

Kernel Object, User Object, GDI Object的使用范围?

Kernel Object可以跨进程使用, 如果指定成Global, 还可以跨session.  XP时代即使不指定成Global, 服务程序和普通应用程序也可以通过Kernel Object通讯,但是Vista之后就不行了, 因为他们在不同的Session了。
User Object可以跨进程使用, 但是User Object的使用范围是Window Station, 它不能垮Window Station, 更别说跨session了。我们看不到服务程序弹出的界面, 那是因为服务程序和我们的桌面运行在不同的Window Station, 除非你指定“允许服务程序与桌面交互”, 显式让服务程序运行在活动桌面的Window Station (WinStat0) 。
GDI Object只有在创建它的进程里有效。

怎样以管理员的身份运行某个程序?

其实就是右键Run as Admin, UAC打开时会有确认窗口。
::ShellExecute(0, L"runas",L"C:\\Windows\\Notepad.exe",0,0,SW_SHOWNORMAL);

如何判断当前进程是否运行在管理员账号下?

这里包含2个概念 一个是运行程序的账号是管理员账号, 另外一个是当前运行的环境是管理员环境。
我们下面的Am_I_In_Admin_Group(TRUE)相当于Windows API IsUserAnAdmin()

//如果bCheckAdminMode是TRUE, 则除了检测Admin账号外,还检测是真的运行在Admin环境, 否则只是检测Admin账号。

BOOL Am_I_In_Admin_Group(BOOL bCheckAdminMode /*= FALSE*/)
{
 BOOL   fAdmin;
 HANDLE  hThread;
 TOKEN_GROUPS *ptg = NULL;
 DWORD  cbTokenGroups;
 DWORD  dwGroup;
 PSID   psidAdmin;

SID_IDENTIFIER_AUTHORITY SystemSidAuthority= SECURITY_NT_AUTHORITY;

if ( !OpenThreadToken ( GetCurrentThread(), TOKEN_QUERY, FALSE, &hThread))
 {
  if ( GetLastError() == ERROR_NO_TOKEN)
  {
   if (! OpenProcessToken ( GetCurrentProcess(), TOKEN_QUERY, 
    &hThread))
    return ( FALSE);
  }
  else 
   return ( FALSE);
 }

if ( GetTokenInformation ( hThread, TokenGroups, NULL, 0, &cbTokenGroups))
  return ( FALSE);

if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  return ( FALSE);

if ( ! ( ptg= (TOKEN_GROUPS*)_alloca ( cbTokenGroups))) 
  return ( FALSE);

if ( !GetTokenInformation ( hThread, TokenGroups, ptg, cbTokenGroups,
  &cbTokenGroups) )
  return ( FALSE);

if ( ! AllocateAndInitializeSid ( &SystemSidAuthority, 2, 
  SECURITY_BUILTIN_DOMAIN_RID, 
  DOMAIN_ALIAS_RID_ADMINS,
  0, 0, 0, 0, 0, 0, &psidAdmin) )
  return ( FALSE);

fAdmin= FALSE;

for ( dwGroup= 0; dwGroup < ptg->GroupCount; dwGroup++)
 {
  if ( EqualSid ( ptg->Groups[dwGroup].Sid, psidAdmin))
  {
   if(bCheckAdminMode)
   {
    if((ptg->Groups[dwGroup].Attributes) & SE_GROUP_ENABLED)
    {
     fAdmin = TRUE;
    }
   }
   else
   {
    fAdmin = TRUE;
   }
   break;
  }
 }

FreeSid ( psidAdmin);

return ( fAdmin);
}


如何提升权限?

注意只有原来是Disable的权限才可以提成Enable, 如果原来就没有这个权限, 是提不上去的。

BOOL EnablePrivilege(HANDLE hToken, LPCTSTR lpszPrivilegeName)
{
    TOKEN_PRIVILEGES tkp = {0};
    BOOL bRet = LookupPrivilegeValue( NULL, lpszPrivilegeName, &tkp.Privileges[0].Luid );
    if(!bRet) return FALSE;

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    bRet = AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL );

    return bRet;
}

如何判断用户的进程完整性级别?

该信息包含在Integrity  Level的SID里,通过GetTokenInformation, 第二个参数设置成TokenIntegrityLevel,大概代码如下, 详细可以参考后面下载的源代码。

void CIntegrityLevel::Print(std::wostream& os) const
{
    SID* pSid = (SID*)m_pIntegrity->Label.Sid;
    DWORD rid = pSid->SubAuthority[0];

    LPCTSTR lpszIntegrity = L"Unknown";
    switch (rid)
    {
    case SECURITY_MANDATORY_UNTRUSTED_RID:
        {
            lpszIntegrity = L"Untrusted";
            break;
        }
    case SECURITY_MANDATORY_LOW_RID:
        {
            lpszIntegrity = L"Low";
            break;
        }
    case SECURITY_MANDATORY_MEDIUM_RID:
        {
            lpszIntegrity = L"Medium";
            break;
        }

    case SECURITY_MANDATORY_MEDIUM_PLUS_RID:
        {
            lpszIntegrity = L"Medium +";
            break;
        }
    case SECURITY_MANDATORY_HIGH_RID:
        {
            lpszIntegrity = L"High";
            break;
        }
    case SECURITY_MANDATORY_SYSTEM_RID:
        {
            lpszIntegrity = L"System";
            break;
        }
    default:
        {
            lpszIntegrity = L"XXXXX";
        }
    }

    os << L"Integrity: " << lpszIntegrity << endl;
}

如何指定程序默认启动运行的级别?

在VC里配置Manifest文件。
asInvoker:默认选项,新的进程将简单地继承其父进程的访问令牌
highestAvailable:应用程序会选择该用户允许范围内尽可能高的权限。对于标准用户来说,该选项与asInvoker一样,而对于管理员来说,这就意味着请求Admin令牌。
requireAdministrator:应用程序需要Admin令牌。运行该程序时,标准用户将要输入管理员的用户名和密码,而管理员则要在弹出的确认对话框中进行确认。

上面只是我自己的一些理解和总结, 由于不是专门搞安全相关的, 如果有不正确的地方, 欢迎指正。

注,这是部分测试代码:MySecurityTest

浅析Windows安全相关的一些概念的更多相关文章

  1. [转载]浅析Windows安全相关的一些概念

    Session 我们平常所说的Session是指一次终端登录, 这里的终端登录是指要有自己的显示器和鼠标键盘等, 它包括本地登录和远程登录.在XP时代每次终端登录才会创建一个Session,但是在Vi ...

  2. 转:浅析windows下字符集和文件编码存储/utf8/gbk

    最近老猿在学习文件操作及网络爬虫相关知识,发现字符集及编码的处理非常重要,而老猿原来对此了解并不多,因此找了几篇文章看了一下,将老猿认为比较的相关文章转载一下.感谢各位原创大神! 1,字符集 这里主要 ...

  3. 深入解析Windows操作系统笔记——CH1概念和术语

    1.概念和工具 本章主要介绍Windows操作系统的关键概念和术语 1.概念和工具 1.1操作系统版本 1.2基础概念和术语 1.2.1Windows API 1.2.2 服务.函数和例程 1.2.3 ...

  4. windows域与工作组概念

    局域网上的资源需要管理,“域”和“工作组”就是两种不同的网络资源管理模式.那么二者有何区别呢? 工作组 Work Group 在一个网络内,可能有成百上千台电脑,如果这些电脑不进行分组,都列在“网上邻 ...

  5. 用于所有Windows驱动程序开发者的概念

    用户模式和内核模式 虚拟地址空间 设备节点和设备堆栈 I/O 请求数据包 驱动程序堆栈 微型驱动程序和驱动程序对 Windows 驱动程序工具包中的头文件 为不同版本的 Windows 编写驱动程序

  6. 【转】浅析Windows编程的剪贴板

    摘要: 本文对Windows剪贴板机制作了深入.全面的阐述,具体内容包括:文本.位图.DSP.自定义格式剪贴板的使用和多数据项和延迟提交技术. 关键词: VC++6.0: 剪贴板机制:数据格式:延迟提 ...

  7. windows server域的概念以及wmic(centos上命令)

    wmic访问在域中的计算机.其中ops\administrator为域用户名,也可以写作ops.com\administrator.ops是域名ops.com的简写,是MS的NetBIOS一套吗? . ...

  8. 浅析Windows系统调用——2种切换到内核模式的方法

    http://shayi1983.blog.51cto.com/4681835/1710861/

  9. [转]Windows Azure安全概述

    本文转自:http://blogs.msdn.com/b/azchina/archive/2011/03/06/windows_5f00_azure_5f00_security_5f00_overvi ...

随机推荐

  1. 格式化HRESULT获取对应文本

    CString CXXUtil::FormatMessageFor(HRESULT hr) { CString strMsg; LPVOID pvMsgBuf = NULL; LPCTSTR pszM ...

  2. freeCodeCamp:Where do I belong

    我身在何处? 先给数组排序,然后找到指定的值在数组的位置,最后返回位置对应的索引. 举例:where([1,2,3,4], 1.5) 应该返回 1.因为1.5插入到数组[1,2,3,4]后变成[1,1 ...

  3. js 常见混乱

    slice(begin.end) 复制出一个新的数组或是一个新的字符串,其中end 不包括end本身 splice(begin,howmany,item1....itemn) 更改原先的array 会 ...

  4. 怎么计算Oracle的表一条记录占用空间的大小

    如何计算Oracle的表一条记录占用空间的大小? 如何计算Oracle的表记录占用空间的大小? 是把所有字段的大小都加起来吗?varchar(256),char,number算几个字节? ------ ...

  5. Python回调函数用法实例详解

    本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...

  6. Openlayers+Geoserver(一):项目介绍以及地图加载

           项目验收完,趁着事情不是很多,对这个项目进行梳理.我主要负责地图模块,网站其他模块主要有两个,一个是报表,主要是100多张报表,技术没有难度,主要是工作量的问题.另一个是数据的校验,就是 ...

  7. 我与solr(三)--solr后台相关介绍

    1.DashBoard: 介绍了当前solr的相关信息,运行时间,版本信息,java虚拟机的配置信息. 注意我们的solr与lucence的版本号是保持一致的,而不同的lucence版本也需要对应的j ...

  8. css中怎么设置透明度的问题

    小伙伴们是不是在找怎么样去设置页面的透明度的方法呢...别找了,我这儿就有,而且肯定够用了. 我自己会用到的就有两种,可以和大家分享一下. 1.用opcity的方法去设置透明度.代码如下: .div ...

  9. mysql 函数(二)

    1.space(N) 输出空格 SELECT SPACE(5); -> '     ' 2.replace(str,from_str,to_str) 讲str中的from_str 替换成to_s ...

  10. 创建GitHub技术博客全攻略

    http://blog.csdn.net/renfufei/article/details/37725057 http://www.pchou.info/web-build/2014/07/04/bu ...