找回密码
 立即注册
首页 业界区 业界 伪造令牌提权Windows ring3 最高权限

伪造令牌提权Windows ring3 最高权限

湄圳啸 6 天前
伪造令牌提权Windows ring3 最高权限

起因是我想在搞一些操作windows进程的事情时,老是需要右键以管理员身份运行,感觉很麻烦。就研究了一下怎么提权,顺手瞄了一眼Windows下用户态权限分配,然后也是感谢《深入解析Windows操作系统》这本书给我偷令牌的灵感吧,写了两三天,成功获取了用户态下所有特权+用户组。
一、windows的权限

在 Windows 操作系统中,“你是谁”以及“你能做什么”完全由一个核心内核对象决定。无论是用户登录、服务启动,还是进程创建,Windows 安全引用监视器(SRM)都会为每个进程分配一个令牌。Windows 的权限机制并不是一个单点功能,而是一整套围绕“对象”“身份”“能力”展开的安全体系。它的核心目标只有一个:在多用户、多进程、多权限级别共存的环境中,让系统既能安全运行,又能灵活扩展。
这套机制的关键在于三个概念:安全主体、访问令牌、受保护对象。Windows 不关心你写了什么代码,只关心你的线程当前挂着哪一张令牌,以及你试图触碰的对象设置了怎样的门禁。
在 Windows 中,真正参与权限判断的不是“用户”这个抽象概念,而是 Security Principal。它可以是本地用户、域用户、系统账户,甚至是服务账户。每一个 Security Principal 在系统中都有一个唯一的 SID,这个 SID 就像身份证号码一样,贯穿其一生。
当你登录系统时,无论是交互式登录、服务启动,还是计划任务触发,LSASS 都会负责认证你的身份,并为你生成一个访问令牌。这个令牌不是简单的“你是谁”,而是一个完整的能力集合快照。
这个快照在登录完成后通常是静态的,除非显式进行特权调整或令牌复制。也正因为如此,Windows 的提权行为,本质上不是“获得新能力”,而是“获得另一张令牌”。
1.令牌的结构

令牌中包含用户 SID 和所属的所有组 SID。这些组并不只是显示在“用户属于 Administrators”那么简单,还包括诸如 INTERACTIVE、SERVICE、AUTHENTICATED USERS 等隐式组。每一个组都可以被启用、禁用,或者标记为仅用于拒绝访问。
令牌中还包含一组特权,也就是 Privileges,例如 SeDebugPrivilege、SeLoadDriverPrivilege、SeImpersonatePrivilege 等。这些特权并不是默认全部启用的,大多数处于 Disabled 状态,需要显式调整。
此外,令牌还携带完整性级别。自 Windows Vista 起,引入了强制完整性控制机制,低完整性进程即便拥有访问控制列表允许的权限,也可能被完整性策略直接拦截。
最后,令牌还记录了是否为主令牌还是模拟令牌,这个细节直接决定了它能否被用于创建新进程。
二、申请UAC和调试权限

1.强制管理员运行

函数 IsRunAsAdmin() 通过检查当前令牌是否含有 DOMAIN_ALIAS_RID_ADMINS(管理员组 SID)来判断权限。 如果不是管理员,SelfElevate() 函数利用了一个经典技巧:ShellExecuteExW 配合 runas 动词。
原理:runas 会触发 Windows 的用户账户控制(UAC)机制。如果当前用户在管理员组但以中等完整性级别(Medium Integrity Level)运行,这会弹窗请求提升。这是本程序中唯一一处需要用户给权的代码。(uac似乎也能绕过,更改环境变量+劫持dll)
[code]BOOL IsRunAsAdmin() {    BOOL fIsRunAsAdmin = FALSE;    PSID pAdminSID = NULL;    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;    if (AllocateAndInitializeSid(            &NtAuthority,            2,            SECURITY_BUILTIN_DOMAIN_RID,            DOMAIN_ALIAS_RID_ADMINS,            0,            0,            0,            0,            0,            0,            &pAdminSID)) {        if (!CheckTokenMembership(NULL, pAdminSID, &fIsRunAsAdmin)) {            fIsRunAsAdmin = FALSE;        }        FreeSid(pAdminSID);    }    return fIsRunAsAdmin;}void SelfElevate() {    WCHAR szPath[MAX_PATH];    if (GetModuleFileNameW(            NULL,            szPath,            ARRAYSIZE(szPath))) {        SHELLEXECUTEINFOW sei = {sizeof(sei)};        sei.cbSize = sizeof(sei);        sei.lpVerb = L"runas";        sei.lpFile = szPath;        sei.hwnd = NULL;        sei.nShow = SW_NORMAL;        if (!ShellExecuteExW(&sei)) {            std::wcout

相关推荐

19 小时前

举报

您需要登录后才可以回帖 登录 | 立即注册