这里是我试图模拟一个用户然后创build一个互斥体的代码。 互斥体没有被创build。 我得到了ERROR_ACCESS_DENIED错误。
void Impersonate() { DWORD logonType = LOGON32_LOGON_INTERACTIVE; DWORD logonProvider = LOGON32_PROVIDER_DEFAULT; HANDLE userToken; HANDLE hMutex; DWORD err; LPSTR user = "zoom"; // the user I created myself on my machine. // It has Administrator privileges, and my account, // from which I start the app, is Admin too LPSTR password = "zoom"; LPSTR domain = "."; hMutex = NULL; LogonUserA(user, domain, password, logonType, logonProvider,&userToken); // just to make sure that mutexes are created fine before impersonation hMutex = CreateMutexA( NULL, FALSE, "mutex_good" ); ImpersonateLoggedOnUser(userToken); hMutex = CreateMutexA( NULL, FALSE, "mutex_797" ); // I can set any // random name, no difference if( hMutex == NULL ) { err = GetLastError(); // here err is ERROR_ACCESS_DENIED } CloseHandle(userToken); }
我发现了几个类似的主题,但是他们都在讨论从两个不同的用户上下文创build同名互斥体,即在模仿之前已经创build了一个互斥体“MUTEX_1”,并且尝试使用相同的名称调用CreateMutex,用户由于缺乏权限而失败。
这里不是这种情况,因为我确信在这个代码之前没有创build具有相同名称的互斥体(或任何互斥体)。
我想我应该传递一些非null到CreateMutex,但究竟是什么?
我的Windows安全性不是很好。 我明白传递NULL作为CreateMutex的第一个参数意味着将使用“默认”安全属性。 在这种情况下,它将是与线程相关的安全参数,即模拟用户。
我的假设是否正确?
首先你需要了解NT命名空间并使用WinObj工具。
这就像内存中带有文件夹和不同“文件”的小文件系统(这里“文件”是指不同的对象类型 – Event
, Mutant
(互斥体), Section
, Device
…)。 每一次当你创建命名对象 – 它放置在NT命名空间中的某个文件夹。 这里的文件夹(如NTFS中的文件夹)具有安全描述符。 结果不是每个人都可以在任何文件夹下创建对象。
来解释你在文件系统语言上做了什么(可能会更清楚):
我( John
)尝试创建%USERPROFILE%\Documents
下的文件“mutex_good”,这是可以的。 因为这是我的个人文件夹,我有写权限。
然后我登录(impersonate)作为zoom
并尝试再次创建文件“mutex_797”在%USERPROFILE%\Documents
( %USERPROFILE%
在两种情况下展开到相同的路径,说c:\Users\John
模仿不影响这一点)
和zoom
无法创建文件。 为什么? 只是他没有权利这样做。 只有John
, Administartors
, SYSTEM
才能对c:\Users\John
进行写入访问,但不能zoom
。
现在让我们回到NT命名空间 。 当我们调用CreateMutexA( NULL, FALSE, "mutex_797" );
"mutex_797"
在哪里?
如果你不是appcontainer
而不是在系统session 0
运行 – 你运行在某个用户session <N>
,你的命名对象将被放置在\Sessions\<N>\BaseNamedObjects
目录中,其中N = 1,2 ..
所以调用CreateMutexA( NULL, FALSE, "mutex_797" );
尝试在\Sessions\<N>\BaseNamedObjects\mutex_797
创建互斥体
然而在\Sessions\<N>\BaseNamedObjects
存在SymbolicLinks(这和NTFS文件系统一样):
Global -> \BaseNamedObjects Local -> \Sessions\<N>\BaseNamedObjects Session -> \Sessions\BNOLINKS
所以说如果你调用CreateMutexA( NULL, FALSE, "Global\\mutex_797" );
对象管理器尝试将您的互斥锁放在\BaseNamedObjects\mutex_797
有关此更多信息读取内核对象命名空间
当然,我们必须了解AccessCheck如何工作
对于定义下一个访问权限的目录对象:
// // Object Manager Directory Specific Access Rights. // #define DIRECTORY_QUERY (0x0001) #define DIRECTORY_TRAVERSE (0x0002) #define DIRECTORY_CREATE_OBJECT (0x0004) #define DIRECTORY_CREATE_SUBDIRECTORY (0x0008)
也可以在DirectoryObject DesiredAccess标志中阅读更多
我们需要DIRECTORY_CREATE_OBJECT
访问( 目录对象的名称创建访问)来在目录中创建互斥体(或事件或任何对象)
现在理解为什么您可以在\Sessions\<N>\BaseNamedObjects
创建互斥,但zoom
无法 – 需要查找此文件夹的Security Descriptor
。 我倾倒它:
T FL AcessMsK Sid 0 00 000F000F S-1-5-90-0-1 DWM-1 0 00 000F000F S-1-5-18 SYSTEM 0 0B 10000000 S-1-5-18 SYSTEM 0 0B 10000000 S-1-3-0 CREATOR OWNER 0 00 000F000F S-1-5-21-4026734978-3280735129-2412320105-1001 John 0 0B 10000000 S-1-5-5-0-294807 LogonSessionId_0_294807 0 00 0002000F S-1-5-5-0-294807 LogonSessionId_0_294807 0 00 0002000F S-1-5-32-544 Administrators 0 02 00000003 S-1-1-0 Everyone 0 00 00000002 S-1-5-12 RESTRICTED 17 00 00000001 S-1-16-4096 Low Mandatory Level
那么谁在这里有DIRECTORY_CREATE_OBJECT
(4)? DWM-1
, SYSTEM
, Administrators
,当前登录会话用户( LogonSessionId_0_294807
),当前用户( John
)以及全部。 zoom
没有这个访问。
例如, Everyone
都有(3) – DIRECTORY_QUERY|DIRECTORY_TRAVERSE
– Name lookup
和Query
但不Name creation
你可以问在这种情况下,我可以在模拟后创建互斥体? 需要使用\BaseNamedObjects
( 全局命名空间 )OR \BaseNamedObjects\Restricted
目录 – 我测试它的安全描述符和结果:
为\BaseNamedObjects
T FL AcessMsK Sid 0 00 0002000F S-1-1-0 Everyone 0 00 00000002 S-1-5-12 RESTRICTED 0 00 000F000F S-1-5-90-0-0 0 00 000F000F S-1-5-18 SYSTEM 17 00 00000001 S-1-16-4096 Low Mandatory Level
对于\BaseNamedObjects\Restricted
T FL AcessMsK Sid 0 00 0002000F S-1-1-0 Everyone 0 00 0002000F S-1-5-12 RESTRICTED 0 00 000F000F S-1-5-90-0-0 0 00 000F000F S-1-5-18 SYSTEM 17 00 00000001 S-1-16-4096 Low Mandatory Level
所以如何查看Everyone
在这里有2000F – 所有需要访问。 希望zoom
是Everyone
成员? 接下来的代码我肯定会工作
CreateMutexA(0, 0, "Global\\mutex_797");
对于\BaseNamedObjects
( 全局命名空间 )存在一个例外:
通过使用CreateFileMapping从全局命名空间中的会话零以外的会话中创建文件映射对象是一项特权操作。 因此,在任意远程桌面会话主机(RD会话主机)服务器会话中运行的应用程序必须启用SeCreateGlobalPrivilege才能成功在全局名称空间中创建文件映射对象。 特权检查仅限于创建文件映射对象,并不适用于打开现有文件。 例如,如果服务或系统创建文件映射对象,则在任何会话中运行的任何进程都可以访问该文件映射对象,前提是用户具有必要的访问权限。
但对于互斥或说事件 – 不需要启用SeCreateGlobalPrivilege
你也可以说,但zoom
是管理员帐户和Administrator
有权访问\Sessions\<N>\BaseNamedObjects
– 为什么这不起作用? 因为用LOGON32_LOGON_INTERACTIVE
和UAC
系统分配来zoom
过滤的令牌。 Administrator
组( S-1-5-32-544
)存在于令牌中, 但仅具有SE_GROUP_USE_FOR_DENY_ONLY
属性 – 因此,它将忽略SID的允许访问的ACE。 并zoom
另一个LogonSessionId_0_XXX
SID – 作为结果和ERROR_ACCESS_DENIED
如上所述@Harry Johnston – 如果我们将使用LOGON32_LOGON_BATCH
而不是LOGON32_LOGON_INTERACTIVE
– 我们得到了提升的令牌 – 这里Administrator
组将具有SE_GROUP_ENABLED
属性 – 对访问允许的ACE启用访问检查
或者我如何提供 – 在名称前使用Global\
prefix – 将对象放置到Everyone
都有完全访问权限的\BaseNamedObjects
中
我明白传递NULL作为
CreateMutex
的第一个参数意味着将使用“默认”安全属性。 在这种情况下,它将是与线程相关的安全参数,即模拟用户。
第一个参数 – 指向SECURITY_ATTRIBUTES
指针可以覆盖新对象的默认安全描述符。 这是控制谁将有权访问它。 但是这不会给你更多或更少的访问目录,你尝试的地方对象 – 你必须有DIRECTORY_CREATE_OBJECT
访问授予,我们不能通过SECURITY_ATTRIBUTES
影响这个 – 这影响新的对象,但不是现有的目录
最后是NT命名空间的一些可视化