深入理解MSF之Getsystem
本文首发于先知社区 : https://xz.aliyun.com/news/12747 在渗透测试中,我们输入getsystem命令轻松就获得了一个system权限的shell,本文将解析幕后发生的工作流程和原理,了解了这些之后我们将以更加灵活的方式实现权限提升定制出我们需要的工具,并且更好的规避安全监测,在正式阅读之前,让我们简单学习一下几个概念辅助我们理解源码中的内容。 认识Windows访问控制模型 Window的访问控制模型如此复杂,以至于完全理解Windows权限是非常困难的,不过我们可以从宏观上做一个简单的理解: 当windows完成了身份认证(例如开启输入密码、rdp登录、匿名登录等等)会生成一份主的访问令牌(access token) 我们所有通过用户启动的进程都会有一份此访问令牌的副本,默认情况下,当进程的线程与安全对象(几乎所有的windows对象都是安全对象:文件、进程、服务等等)交互时,系统会使用主令牌 进程的线程可以模拟客户端帐户,模拟允许线程使用客户端的Access Token与安全对象交互,拿到的令牌称之为模拟令牌。 模拟客户端的线程同时具有主令牌和模拟令牌 你可能好奇Access Token到底是什么,我们可以简单理解为一个windows内核对象,里面包含着各种信息: 用户标识符(User Identifier):通常是一个唯一的账户安全标识符(SID),用于识别用户账户。 组标识符(Group Identifiers):用户所属的一组或多组的SIDs,它反映了用户在不同的组中的成员资格。 权限(Privileges):一个或多个权限,指明了线程所能执行的特定系统级操作(例如关机、改变系统时间、模拟客户端权限等)。 所有者(Owner):该令牌指定的默认所有者SID。在创建对象时,通常会被用作对象的所有者。 访问控制列表(DACL):指定哪些用户或组可以对对象执行何种操作。 登录会话(Logon Session):一个标识符,指关联到此访问令牌的登录会话。 这些信息在c++里面都有对应的数据结构类型,我们要操控获取Access Token的信息是非常容易的,举一个简单的例子,下面是微软官方文档用户标识的TOKEN_USER结构: typedef struct _TOKEN_USER { SID_AND_ATTRIBUTES User; } TOKEN_USER, *PTOKEN_USER; SID_AND_ATTRIBUTES类型的User里面包含着sid typedef struct _SID_AND_ATTRIBUTES { #if ... PISID Sid; #else PSID Sid; #endif DWORD Attributes; } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; 实现获取当下进程的用户的sid信息,同理其他信息也是一样的: // token.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <Windows.h> #include <processthreadsapi.h> #include <sddl.h> int main() { HANDLE hToken = NULL; BOOL bSuccess = FALSE; DWORD dwSize = 0; PTOKEN_USER pTokenUser = NULL; LPWSTR szSID = NULL; using namespace std; bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); if (!...