Windows Via C/C++ note 4_2

Windows 安全相关知识下半节,这一章主要讲一下除了SID,DACL这类,还有哪些安全对象也在 Windows 安全中发挥着重要的作用


Windows 安全相关(下)

这一段会尝试介绍一下 Windows 整个操作系统中,参与了安全保护的各个部件。

Access Token 访问令牌

当用户登录操作系统的时候,操作系统会要求用户输入密码,输入的密码会与Windows的安全数据库(security database)的信息进行比较。当密码得到验证(authenticated)之后,系统将会产生一个Access Token,代表了当前登录用户的权限。
每一个 Access Token 都是描述了一个进程或者线程的安全上下文,包括身份以及特权(privilege)。

Access Token 使用场合

当一个线程尝试进行如下操作的时候,操作系统会使用 Access Token 来识别一个用户

  • 与安全对象(Secure Object)进行交互
  • 执行一些需要系统权限的任务(例如对进程进行调试)

Access Token 包含内容

一个Access Token中实际上包含了如下的内容:

  • 用户账户的SID
  • 用户从属组的SID
  • 当前登录会话(logon session)的SID
  • 用户以及从属组所持有的特权
  • token 从属者的SID
  • 主从属组(primary Group)的SID
  • 当创建安全对象的时候,如果不指定安全描述符时系统会赋予的默认DACL
  • Access Token 的源
  • 当前 token 是 primary(主token)还是 impersonation(模仿token)
  • 一系列可选的限制Token (Restricted Token)
  • 当前的模仿等级(impersonation level)
  • 一些其他的东西

Primary/Impersonation Token 主Token/模仿token

从逻辑上讲,线程从属进程,而用户直接创建的是进程,所以进程中会持有象征着创建者的Token,这个Token就被称为主token (primary token)。一个主token中会记录当前用户与进程相关联的有效的安全上下文(secure context)。而实际上与安全对象交互的往往是线程,所以默认情况下主token是由线程携带与安全对象进行交互。

不过特殊情况下(例如在一些RPC场合,或者在一些CS架构的软件,server端限制client端权限的时候等),可能会出现某些线程需要以创建当前进程不同的,其他用户的身份访问安全对象的时候,这个时候会给线程一个特殊的token,被称为模仿token(impersonation token)。此时的线程使用属于自己的token,并且有不同于进程的权限。

相关API

此时可以使用

1
2
OpenProcessToken 
OpenThreadToken

来检查当前进程/线程的使用token

Windbg 查看方式

windbg中可以方便的查看一个进程的token

user mode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
!token
0:000> !token
Thread is not impersonating. Using process token...
TS Session ID: 0x1
User: S-1-5-21-3132730683-2216882805-422503560-1001
User Groups:
00 S-1-16-8192
Attributes - GroupIntegrity GroupIntegrityEnabled
01 S-1-1-0
Attributes - Mandatory Default Enabled
02 S-1-5-114
Attributes - DenyOnly
03 S-1-5-32-544
Attributes - DenyOnly
04 S-1-5-32-545
Attributes - Mandatory Default Enabled
05 S-1-5-32-559
Attributes - Mandatory Default Enabled
06 S-1-5-4
Attributes - Mandatory Default Enabled
07 S-1-2-1
Attributes - Mandatory Default Enabled
08 S-1-5-11
Attributes - Mandatory Default Enabled
09 S-1-5-15
Attributes - Mandatory Default Enabled
10 S-1-11-96-3623454863-58364-18864-2661722203-1597581903-544001092-2724467026-4283684584-2191855628-1410562263
Attributes - Mandatory Default Enabled
11 S-1-5-113
Attributes - Mandatory Default Enabled
12 S-1-5-5-0-5228497
Attributes - Mandatory Default Enabled LogonId
13 S-1-2-0
Attributes - Mandatory Default Enabled
14 S-1-5-64-36
Attributes - Mandatory Default Enabled
Primary Group: S-1-5-21-3132730683-2216882805-422503560-1001
Privs:
00 0x000000013 SeShutdownPrivilege Attributes -
01 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default
02 0x000000019 SeUndockPrivilege Attributes -
03 0x000000021 SeIncreaseWorkingSetPrivilege Attributes -
04 0x000000022 SeTimeZonePrivilege Attributes -
Auth ID: 0:4fea7c
Impersonation Level: Anonymous
TokenType: Primary
Is restricted token: no.
SandBoxInert: 0
Elevation Type: 3 (Limited)
Mandatory Policy: TOKEN_MANDATORY_POLICY_VALID_MASK
Integrity Level: S-1-16-8192
Attributes - GroupIntegrity GroupIntegrityEnabled
Process Trust Level: LocalDumpSid failed to dump Sid at addr 000000ee876fabb8, 0xC0000078; try own SID dump.
s-1-0
Attributes -
Token Virtualized: Disabled
UIAccess: 0
IsAppContainer: 0
Security Attributes Information:
00 Attribute Name: TSA://ProcUnique
Value Type : TOKEN_SECURITY_ATTRIBUTE_TYPE_UINT64
Value[0] : 283
Value[1] : 428746286
Device Groups:

kernel mode

1
2
3
!process 0 0 // 找到对应的进程
!process PROCESS //查看具体的进程,找到其中的TOKEN
!token TOKEN // 查看token信息

实例:获取Token句柄

通常情况下,我们的程序拿到的token都是伪token(pseudo token)。这种方式主要是为了托管我们对内核句柄的操作:

1
HANDLE hToken = GetCurrentProcessToken();

如上,虽然从API可知我们尝试获取了当前进程中的token(也就是primary token)但是此时的token值为:0xfffffffffffffffc(64位下),显然不是一个真正的handle值。在某些场合下(需要知道确切句柄值的API的时候)会无法正常使用。如果需要知道此时真正的token的时候,需要使用OpenProcessToken这个API:

1
OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);

这里注意,不可以使用DuplicateHandle这个API!因为这个API在MSDN上写的其实是:

If hSourceHandle is a pseudo handle returned by GetCurrentProcess or GetCurrentThread, DuplicateHandle converts it to a real handle to a process or thread, respectively.

也就是说只有进程和线程的伪句柄才生效。对于token的伪句柄是不生效的。

Restricted Token 限制令牌

限制令牌是由APICreateRestrictedToken创建的一种主/模仿token。一个跑在限制token的安全上下文的进程或者模仿线程将会收到访问安全对象的限制,以及一些特权操作的限制。具体来说,会以如下的方式来限制一个token

  • 移除token中的特权
  • 对 token 中的 SIDs 应用 deny-only 的属性,从而让其无法访问到安全对象。(详情看后面的访问令牌中的SID属性
  • 显示指定一系列的限制SID来限制安全对象访问

当系统检查一个token是对访问安全对象的访问权限的时候,系统通常会使用一系列的限制SIDs。当一个被限制的进程/线程尝试访问一个安全对象的时候,系统会进行两种检查:

  • 检查token中被启用的SIDs
  • 检查一系列的限制SIDs

只有当两种权限都被允许的时候,才能够访问这个对象。

API CreateProcessAsUser 拥有创建一个有指定token权限的进程,但是一般情况下需要有特权SE_ASSIGNPRIMARYTOKEN_NAME。然而,当指定的进程token为限制token的时候,创建的父进程可以不具有特权也可创建。

SID Attributes in an Access Token

每一个用户组拥有的访问token都有一系列的属性来说明操作系统要如何使用这个访问检查,一般来说有如下两种检查方式:

Attribute Description
SE_GROUP_ENABLED 启用了这个属性的SID能够被进行访问检查。当系统尝试进行访问检查的时候,当检查当前的SID对应的ACE中状态为allowed\deny的时候,能够被检查到。与此同时,未设置这个属性的(除了SE_GROUP_USE_FOR_DENY_ONLY)的SID将会被忽略检查
SE_GROUP_USE_FOR_DENY_ONLY 启用这个属性的SID被称为deny-only的SID,当系统进行访问检查的时候,只会检查对当前SID中deny的权限,而忽略所有allow的权限,也就是只关注这个SID被显示的拒绝了什么权限,而不关注其被允许的权限。一旦这个属性被设置的话,SE_GROUP_ENABLED将无法被设置,并且SID不能被enable。

对访问Token的访问权限控制

一个应用只有在获得相应权限的时候才能够去修改一个ACL。这些权限被记录在访问Token中的安全描述符中。
如果才想要设置一个访问Token的安全描述符的时候,需要调用GetKernelObjectSecurity/SetKernelObjectSecurity等相关API。
当需要使用OpenProcessToken/OpenThreadToken获取的Token的时候,系统就会检查请求的权限和记录在token的安全描述符中的DACL中的差异。一般来说一个有效的访问权限token有以下的权限:

  • 标准权限中,不支持SYNCHRONIZE,其余的DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER 都有
  • 拥有 ACCESS_SYSTEM_SECURITY的SACL的权限
  • 其中Token还有一些只属于自己的权限。可以参考MSDN官方文档

特权 privilege

特权privilege(例如一般的用户账号或者组账号——在本地计算机中执行的各种与系统相关的操作(例如开关闭系统,加载驱动,更改系统事件等等)的权利。特权(privilege)和之前提到过的访问权限(access right)有两个不同的地方:

  • 特权控制的是对系统资源以及系统相关任务的访问权限,然而访问权限控制的是对安全对象的访问权限。
  • 只有系统管理员才能够将权限赋予用户/组(相当于提前给予的),然而系统可以基于一个对象的DCAL中的某一个ACE赋予/拒绝其对于某一个安全对象的访问权限。(相当于根据某个设定动态设定)

每一个系统都有一个用户数据库(account database),里面存储了每一个用户/组的特权信息。当用户尝试登录系统的时候,系统将会提供一个包含了当前用户所有特权的访问token,以及授予用户这个访问token中的用户/组的特权。不过,这个特权只适用于本地计算机,在域中并不适用。当用户尝试进行一个特权操作的时候,系统将会检查访问token中的特权位,检查其是否包含对应的特权权限,如果有的话,才会允许执行。这里大致展示一下:

TOKEN与Privilege
TOKEN的结构体大致长这个样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
typedef struct _TOKEN
{
TOKEN_SOURCE TokenSource;
LUID TokenId;
LUID AuthenticationId;
LUID ParentTokenId;
LARGE_INTEGER ExpirationTime;
PERESOURCE TokenLock;
LUID ModifiedId;
SEP_TOKEN_PRIVILEGES Privileges;
SEP_AUDIT_POLICY AuditPolicy;
ULONG SessionId;
ULONG UserAndGroupCount;
ULONG RestrictedSidCount;
ULONG VariableLength;
ULONG DynamicCharged;
ULONG DynamicAvailable;
ULONG DefaultOwnerIndex;
PSID_AND_ATTRIBUTES UserAndGroups;
PSID_AND_ATTRIBUTES RestrictedSids;
PVOID PrimaryGroup;
ULONG * DynamicPart;
PACL DefaultDacl;
TOKEN_TYPE TokenType;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
ULONG TokenFlags;
UCHAR TokenInUse;
ULONG IntegrityLevelIndex;
ULONG MandatoryPolicy;
PSECURITY_TOKEN_PROXY_DATA ProxyData;
PSECURITY_TOKEN_AUDIT_DATA AuditData;
PSEP_LOGON_SESSION_REFERENCES LogonSession;
LUID OriginatingLogonSession;
SID_AND_ATTRIBUTES_HASH SidHash;
SID_AND_ATTRIBUTES_HASH RestrictedSidHash;
ULONG VariablePart;
} TOKEN, *PTOKEN;

其中SEP_TOKEN_PRIVILEGES表示的就是当前TOKEN的特权:

1
2
3
4
nt!_SEP_TOKEN_PRIVILEGES
+0x000 Present : Uint8B
+0x008 Enabled : Uint8B
+0x010 EnabledByDefault : Uint8B

这个_SEP_TOKEN_PRIVILEGES.Enabled中的每一个bit就表示一种特权。前文提到的当用户尝试进行一个特权操作的时候,系统将会检查访问token中的特权位,实际上就是检查SEP_TOKEN_PRIVILEGES.Enabled中的bit位是否为1.

实践:在windbg(kernel debug)下检查当前进程 token 的特权

用之前提过的技巧,首先找到当前进程的TOKEN地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
: kd> !process aed07600 1
PROCESS aed07600 SessionId: 1 Cid: 1b90 Peb: 00451000 ParentCid: 0d24
DirBase: 3ffd35c0 ObjectTable: af3f4540 HandleCount: 38.
Image: Exploit.exe
VadRoot a6f684a0 Vads 31 Clone 0 Private 105. Modified 0. Locked 0.
DeviceMap 9cf61548
Token 8bfd18a0 <--------------注意这里
ElapsedTime 00:04:57.845
UserTime 00:00:00.000
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 25664
QuotaPoolUsage[NonPagedPool] 2540
Working Set Sizes (now,min,max) (650, 50, 345) (2600KB, 200KB, 1380KB)
PeakWorkingSetSize 784
VirtualSize 16 Mb
PeakVirtualSize 17 Mb
PageFaultCount 810
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 131

然后这里我们找到了对应token的地址,我们使用dt去检查一下其内存中的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
1: kd> dt nt!_TOKEN  8bfd18a0
+0x000 TokenSource : _TOKEN_SOURCE
+0x010 TokenId : _LUID
+0x018 AuthenticationId : _LUID
+0x020 ParentTokenId : _LUID
+0x028 ExpirationTime : _LARGE_INTEGER 0x7fffffff`ffffffff
+0x030 TokenLock : 0xaedba148 _ERESOURCE
+0x034 ModifiedId : _LUID
+0x040 Privileges : _SEP_TOKEN_PRIVILEGES
+0x058 AuditPolicy : _SEP_AUDIT_POLICY
+0x078 SessionId : 1
+0x07c UserAndGroupCount : 0xf
+0x080 RestrictedSidCount : 0
+0x084 VariableLength : 0x78
+0x088 DynamicCharged : 0x1000
+0x08c DynamicAvailable : 0
+0x090 DefaultOwnerIndex : 4
+0x094 UserAndGroups : 0x8bfd1b40 _SID_AND_ATTRIBUTES
+0x098 RestrictedSids : (null)
+0x09c PrimaryGroup : 0xa3379658 Void
+0x0a0 DynamicPart : 0xa3379658 -> 0x501
+0x0a4 DefaultDacl : 0xa3379674 _ACL
+0x0a8 TokenType : 1 ( TokenPrimary )
+0x0ac ImpersonationLevel : 0 ( SecurityAnonymous )
+0x0b0 TokenFlags : 0x2000
+0x0b4 TokenInUse : 0x1 ''
+0x0b8 IntegrityLevelIndex : 0xe
+0x0bc MandatoryPolicy : 1
+0x0c0 LogonSession : 0x9e7756c8 _SEP_LOGON_SESSION_REFERENCES
+0x0c4 OriginatingLogonSession : _LUID
+0x0cc SidHash : _SID_AND_ATTRIBUTES_HASH
+0x154 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH
+0x1dc pSecurityAttributes : 0xaf366428 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION
+0x1e0 Package : (null)
+0x1e4 Capabilities : (null)
+0x1e8 CapabilityCount : 0
+0x1ec CapabilitiesHash : _SID_AND_ATTRIBUTES_HASH
+0x274 LowboxNumberEntry : (null)
+0x278 LowboxHandlesEntry : (null)
+0x27c pClaimAttributes : (null)
+0x280 TrustLevelSid : (null)
+0x284 TrustLinkedToken : (null)
+0x288 IntegrityLevelSidValue : 0xae8aa528 Void
+0x28c TokenSidValues : 0x9e748038 _SEP_SID_VALUES_BLOCK
+0x290 IndexEntry : 0xb53e5b20 _SEP_LUID_TO_INDEX_MAP_ENTRY
+0x294 DiagnosticInfo : (null)
+0x298 BnoIsolationHandlesEntry : (null)
+0x29c SessionObject : 0x8e0eb6f8 Void
+0x2a0 VariablePart : 0x9e748044
1: kd> dx -id 0,0,aed07600 -r1 (*((ntkrpamp!_SEP_TOKEN_PRIVILEGES *)0x8bfd18e0))
(*((ntkrpamp!_SEP_TOKEN_PRIVILEGES *)0x8bfd18e0)) [Type: _SEP_TOKEN_PRIVILEGES]
[+0x000] Present : 0x1e73deff20 [Type: unsigned __int64]
[+0x008] Enabled : 0x60800000 [Type: unsigned __int64]
[+0x010] EnabledByDefault : 0x60800000 [Type: unsigned __int64]

可以看到,_SEP_TOKEN_PRIVILEGES.Enabled的值为0x60800000,写成bit的形式就是:

1
1100000100000000000000000000000

此时直接查看token 的内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
_EPROCESS 0xffffffffaed07600, _TOKEN 0x0000000000000000
TS Session ID: 0x1
User: S-1-5-21-3717723882-702046769-3252787667-1000
User Groups:
00 S-1-5-21-3717723882-702046769-3252787667-513
Attributes - Mandatory Default Enabled
01 S-1-1-0
Attributes - Mandatory Default Enabled
02 S-1-5-114
Attributes - Mandatory Default Enabled
03 S-1-5-32-544
Attributes - Mandatory Default Enabled Owner
04 S-1-5-32-545
Attributes - Mandatory Default Enabled
05 S-1-5-4
Attributes - Mandatory Default Enabled
06 S-1-2-1
Attributes - Mandatory Default Enabled
07 S-1-5-11
Attributes - Mandatory Default Enabled
08 S-1-5-15
Attributes - Mandatory Default Enabled
09 S-1-5-113
Attributes - Mandatory Default Enabled
10 S-1-5-5-0-141477
Attributes - Mandatory Default Enabled LogonId
11 S-1-2-0
Attributes - Mandatory Default Enabled
12 S-1-5-64-10
Attributes - Mandatory Default Enabled
13 S-1-16-12288
Attributes - GroupIntegrity GroupIntegrityEnabled
Primary Group: S-1-5-21-3717723882-702046769-3252787667-513
Privs:
05 0x000000005 SeIncreaseQuotaPrivilege Attributes -
08 0x000000008 SeSecurityPrivilege Attributes -
09 0x000000009 SeTakeOwnershipPrivilege Attributes -
10 0x00000000a SeLoadDriverPrivilege Attributes -
11 0x00000000b SeSystemProfilePrivilege Attributes -
12 0x00000000c SeSystemtimePrivilege Attributes -
13 0x00000000d SeProfileSingleProcessPrivilege Attributes -
14 0x00000000e SeIncreaseBasePriorityPrivilege Attributes -
15 0x00000000f SeCreatePagefilePrivilege Attributes -
17 0x000000011 SeBackupPrivilege Attributes -
18 0x000000012 SeRestorePrivilege Attributes -
19 0x000000013 SeShutdownPrivilege Attributes -
20 0x000000014 SeDebugPrivilege Attributes -
22 0x000000016 SeSystemEnvironmentPrivilege Attributes -
23 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default
24 0x000000018 SeRemoteShutdownPrivilege Attributes -
25 0x000000019 SeUndockPrivilege Attributes -
28 0x00000001c SeManageVolumePrivilege Attributes -
29 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default
30 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default
33 0x000000021 SeIncreaseWorkingSetPrivilege Attributes -
34 0x000000022 SeTimeZonePrivilege Attributes -
35 0x000000023 SeCreateSymbolicLinkPrivilege Attributes -
36 0x000000024 SeDelegateSessionUserImpersonatePrivilege Attributes -
Authentication ID: (0,23098)
Impersonation Level: Anonymous
TokenType: Primary
Source: User32 TokenFlags: 0x2000 ( Token in use )
Token ID: 181366 ParentToken ID: 0
Modified ID: (0, de5e9)
RestrictedSidCount: 0 RestrictedSids: 0x0000000000000000
OriginatingLogonSession: 3e7
PackageSid: (null)
CapabilityCount: 0 Capabilities: 0x0000000000000000
LowboxNumberEntry: 0x0000000000000000
Security Attributes:
Unable to get the offset of nt!_AUTHZBASEP_SECURITY_ATTRIBUTE.ListLink
Process Token TrustLevelSid: (null)

注意特权那一栏:
特权的第23,29,30 bit正好都是1,对应在bit的形式就是(注意存在第0位):

1
1100000100000000000000000000000

正好和我们之前和内存中存在的形式看的一致。于是我们就能够知道当前进程中的token拥有的特权有:

  • SeChangeNotifyPrivilege:这类用户能够绕过NTFS文件系统/注册表中的访问权限的check,也就是对文件有特殊的访问特权就是了。
  • SeImpersonatePrivilege:这类用户可以模拟已有的token,但是不能创建新的token,也就是模仿token的创建特权。
  • SeCreateGlobalPrivilege:这类用户可以创建全局的安全对象。(也就是那种跨session的global object的创建权限)

LUID local identifier

之前提到过,每一个安全对象都有一个唯一的SID,那么特权对象有没有对应的唯一标识符呢?其实是有的,就叫做LUID,本地唯一标识符(因为特权只对当前机器生效,所以不需要GUID)。LUID可以在每台机器之间都不同,甚至每次重启之后都不同。为了确认当前LUID和特权的对应关系,可以使用API

1
2
LookupPrivilegeValue
LookupPrivilegeName

进行切换。

一些杂项

Security system components

Windows下有很多实现了相关安全防护的组件(其中大部分都在%SystemRoot%\System32这个目录下)

win00.png

Security reference monitor(SRM)

存在ntoskrnl.exe这个文件中,定义了acces token的数据结构,并且会对security access进行checks,以及对不同token分发权限,并且产生安全审计日志。

Local Security Authority Subsystem Service(Lsass)

常见的user-mode进程,主要用于本地操作系统安全策略管理(登陆用户管理,密码策略,用户(组)权限管理等等),用户权限,并且负责发送安全事件的日志。其中主要功能由Local Security Authority service(Lsasrv.dll)进行实现。

LSAIso.exe

Lsass使用,或者叫做Credential Guard,用于存放用户token的hash值,而不是直接在Lsas的内存中存放。由于Lsaiso.exe是Trustlet进程(与普通用户空间隔离),所以当需要与Lsass.exe通信的时候,只能使用ALPC

Lsass policy database

数据库中存储了了本地系统安全策略的设置。这个模块被存储在又ACL保护下的HKLM\SECURITY下的注册表中。其中包含的信息有:

  • 哪个域被授权登入
  • 哪个用户对系统有哪些操控权限
  • 用户被分发的权限
  • 启用的安全审计等级

其中还存储了一些和登陆信息有关的秘密

Security Accounts manager(SAM)

这个服务用于管理定义在当前机器中用户名的组的数据库。这个模块由samsrv.dll实现,并且会被load到进程lsass.

SAM database

之前提到的被管理的数据库。里面存储了本地用户(组)以及对应密码和其他相关的属性。对于域控制者来说,SAM·中并不会存放域定义者的用户信息,但是会存放系统管理员恢复的账号和密码。这些数据存放在:HKLM\SAM

Active Directory(活动目录)

这是一个目录服务,包含一个存储域中对象的数据库。一个域由许多的计算机组成,这些计算机会被组织成一个安全组,并且作为一个实体进行管理。AD会将这些对象的信息存放在域中,包括用户,组以及计算机。域用户和组的密码信息以及权限都会被存储在一个在所有计算机中,被设计为域管理员的AD中。AD server 由Ntdsa.dll实现,同样运行在lsass.exe进程中。

Authentication packages

这个模块其实是指的哪些运行在lsass 以及其他实现了windows 客户验证的dlls。一个验证dll将会验证一个用户的用户名和密码是否匹配(或者当前机器会不会提供身份认证)。如果匹配,则返回给Lsass用户的安全身份,lsass用此来产生验证用的token。

Interactive logon manager(WinLogon)

这个就是Winlogon.exe,是第一个用户态的程序,用来进行SAS(Shared Access Signature),并且对登陆的会话进行管理。当用户登陆成功后,winlogon.exe将会创建第一个用户程序。

Login user inerface(LogonUI)

一个用户态的进程LogonUI.exe可以让用户对自己的身份进行验证。

Credential providers(CPs)

这个是一个COM对象,运行在进程LogonUI中,用来获取用户的用户名和密码,smartcard PIN 码,生物信息(指纹等等),或者其他的身份认证信息。完整的CPsauthui.dllSmartcardCredentialProvider.dllBioCredProv.dll以及FaceCredentialProvider.dll实现(有些特性win10才加入)

Network logon service(Netlogon)

这个是由Netlogon.dll(由svchost启动)模块实现的一个功能。用于设置对域控制的安全通道,以及安全请求。例如交互式登陆(如果域是在WIndows NT 4)或者LAN Manager以及NT LAN Manager(V1/V2)的身份认证,这个模块同样也会作为AD的登陆模块使用。

Kernel Security Device Driver(KsecDD)

一个内核态的模块(%SystemRoot%\System32\Drivers\Kescdd.sys),实现了APLC(Advanced local procedure call的结构。让其他的内核态安全模块(包括Encryption File System(EFS))能与Lsass进行通信

AppLocker

这个功能运行管理员能够指定哪个exe,dll,scripts能被指定的用户执行。这个模块由内核驱动(%SystemRoot%\System32\Drivers\Appld.sys)和服务(AppidSvc.dll)两部分组成

Credential Guard

Crediential Guard给系统中的不同元素提供了安全边界与保护。不过为了实现这个过程,首先需要知道程序是怎么实现身份验证的

  • Password:登陆验证,这个是最常见的身份验证方法。
  • NT one-way function(NT OWF):通常在用户用password登陆成功后,使用NT LAN用于对传统模块的身份验证。不过在现在的网络系统验证已经不使用这部分内容了
  • Ticket-granting ticket(TGT):这就是现代的远程网络验证常用的一个验证方式:Kerberos.这也是通常Windows AD域下常做的验证方式。在登陆成功之后,TGT以及相应的密钥将会被提供给本地机器。