首页
社区
课程
招聘
[原创]使用未文档化的函数 NtCreateToken 提升进程的访问权限
发表于: 2020-5-10 17:53 7112

[原创]使用未文档化的函数 NtCreateToken 提升进程的访问权限

2020-5-10 17:53
7112

网上这方面的资料比较少,很多都是自己总结出来的。目前使用此技术可以在一定程度上挑战现有的安全策略,如给线程添加任意特权,添加任意用户组。请大家理智使用,不要用在危害网络安全的事情上。

由于本人水平有限,文中难免会出现错误,欢迎批评指正。

访问令牌(Access Token)是描述进程或线程安全上下文的对象。令牌中的信息包括与进程或线程关联的用户帐户SID和特权。当用户成功登录后,系统会为用户创建一个访问令牌,用户创建的所有进程都包含了这个令牌的副本(copy)。[本段内容翻译自MSDN]
当线程尝试访问一个对象或执行一个需要特定的特权的系统任务时,系统会检查线程关联的令牌中的信息。具体来说,如果是访问一个对象,内核中的服务例程会根据对象的访问控制列表和访问令牌的用户组决定是否授予访问权限;如果是执行需要特权的系统任务,服务例程则会检查令牌中是否包含并启用所需的特权。
每个进程都有一个主令牌,并且在默认情况下系统在进行访问检查时使用的就是主令牌。线程可以设置一个模拟令牌。

令牌中这些结构大小是固定的。
可以分别使用TokenUser、TokenPrimaryGroup、TokenOwner信息类调用GetTokenInformation函数获取这些信息。
结构定义如下:

用户组是令牌的重要信息之一。调整用户组信息可以调用AdjustTokenGroups函数。用户组在创建令牌时指定,创建后不能添加或删除成员,也不能修改属性包含 SE_GROUP_USE_FOR_DENY_ONLY 位的成员。服务例程进行访问检查用的就是用户组结构。
可以使用TokenGroups信息类调用GetTokenInformation函数来获取此信息。
结构定义如下:

特权列表是令牌的又一重要信息。调整特权信息可以调用AdjustTokenPrivileges函数。特权列表也是在创建令牌时指定,创建后不能添加新的特权,但是可以移除特权。服务例程就是根据特权列表判断是否具有特权的。
可以使用TokenPrivileges信息类调用GetTokenInformation函数来获取此信息。
结构定义如下:

令牌对象的默认访问控制列表,完全可以在创建后修改,因此DACL暂时对我们意义不大。相关内容请参阅MSDN文档。
结构定义如下:

令牌来源用来表示令牌创建者,只读的,定长的。
名称成员可以为用户定义的任意8字节字符,id成员可以调用AllocateLocallyUniqueId函数分配一个全局唯一的LUID。
结构定义如下:

令牌类型只有两种(目前)。
令牌类型可以使用DuplicateTokenEx函数相互转换。
令牌类型在1.8的统计信息中定义。
定义如下:

如果线程有模拟令牌,那么系统在进行访问检查时会根据模拟令牌中的模拟级别决定线程是否允许具有令牌中的特权。值越大表示级别越高,允许的就越多。
模拟级别在1.8的统计信息中定义。
定义如下:

统计信息包含很多令牌的多种数据。
使用TokenStatistics信息类调用GetTokenInformation函数获取此信息。
结构定义如下:

令牌会话ID,类型为DWORD,与会话隔离中的会话是一个概念。
会话ID可以更改,前提是没有使用这个令牌创建进程/模拟线程,或者创建的进程或线程已经终止。

具有访问令牌的对象只有进程和线程。
访问令牌也是一种内核对象,因此它也有访问控制列表,限制其他对象对访问令牌的访问。
打开进程的令牌,进程句柄必须具有PROCESS_QUERY_INFORMATION权限;
打开线程的令牌,线程句柄必须具有THREAD_QUERY_INFORMATION权限。
要打开进程或线程,需使用进程或者线程的ID调用OpenProcess或OpenThread函数。

打开进程令牌的函数原型:

打开线程令牌的函数原型:

令牌中包含的信息非常多,仅信息类就有40+,并且在MSDN上都有详尽的记录。
直接上函数原型:

对于令牌中的用户组和特权列表,需要使用AdjustTokenGroups和AdjustTokenPrivileges函数修改。

一旦进程对象在内核中创建完成便无法替换关联的令牌。因此分配给进程需要在进程创建的边界上进行。即在创建进程时指定要分配的访问令牌。
可以实现这个过程的WIN32API函数:

除了上述方法外,还可以使用本地api,如NtCreateProcessEx、NtCreateUserProcess等。

默认情况下线程是没有模拟令牌的,但是可以手动为线程分配一个模拟令牌。

SE_CREATE_TOKEN_NAME是调用NtCreateToken例程所必需的的特权。根据MSDN文档,用户不能使用“创建令牌对象”策略将此特权添加到用户帐户;也不能使用Windows API将此特权添加到拥有的进程。使用ProcessHacker工具可以确定,正常情况下,系统中具有此特权的进程只有lsass.exe,并且目前lsass.exe并没有受到轻型保护,能够在用户态访问。

获取 SE_CREATE_TOKEN_NAME 特权:

使用lsass.exe的令牌创建一个进程,新进程将具有 SE_CREATE_TOKEN_NAME 特权。

对于NtCreateToken例程,如果调用线程的有效令牌是主令牌,会检查是否具有SE_CREATE_TOKEN_NAME特权;

如果是模拟令牌,则会先检查令牌的模拟级别,如果小于SecurityDelegation则会认为不具有特权;然后检查模拟令牌中是否具有SE_CREATE_TOKEN_NAME特权。
调用OpenProcessToken得到的模拟令牌小于等于SecurityImpersonation,因此需要用SecurityDelegation级别调用DuplicateTokenEx复制一个令牌,然后模拟这个新令牌。

显然,这个方法是最佳选择,它可以让我们执行代码像真实获得了SE_CREATE_TOKEN_NAME特权一样。

认证ID可以通过令牌统计信息获取,也可以使用下面的常量:
如果使用AllocateLocallyUniqueId函数生成一个不存在的ID可能会发生异常情况。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 4
支持
分享
最新回复 (5)
雪    币: 3190
活跃值: (1816)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
"目前lsass.exe并没有受到轻型保护,能够在用户态访问",目标系统是Win7?
2020-5-11 09:45
0
雪    币: 4154
活跃值: (1535)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
MsScotch "目前lsass.exe并没有受到轻型保护,能够在用户态访问",目标系统是Win7?
最新的win10也可以,在注册表里可以设置启用保护
2020-5-11 12:03
0
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
4
感谢分享~
2020-5-11 15:12
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
感谢分享!
2020-5-13 11:08
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
感谢分享~!
2020-5-13 23:24
0
游客
登录 | 注册 方可回帖
返回
//