模拟时无法设置所有权
Trouble setting ownership when impersonating
这是我的代码:
logonSuccess = LogonUserW(userPartW, domainPartW, pwdW,
LOGON32_LOGON_BATCH,
LOGON32_PROVIDER_DEFAULT, &token);
Int result1 = SetNamedSecurityInfo("C:\file.crt", SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, yveri, NULL, NULL, NULL);
fprintf(stderr, "result -> %d.\n", result1); //which gives me 0
if (ImpersonateLoggedOnUser(token) == FALSE)
{
printf("Imperesonating failed.\n");
return -1;
}
Int result2 = SetNamedSecurityInfo("C:\Users\nx\.nx\config\authorized.crt", SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, yveri, NULL, NULL, NULL);
fprintf(stderr, "result -> %d.\n", result2); //which gives me 5
第一次调用 SetNamedSecurityInfo 有效,但第二次调用(模拟到位后)returns 错误代码 5。
基于我们在评论中得出的结论:
当您调用任何模拟函数(ImpersonateLoggedOnUser
、ImpersonateNamedPipeClient
、RpcImpersonateClient
等)时,您基本上是在调用 SetThreadToken(GetCurrentThread(), __GetInterestingToken())
(其中 GetInterestingToken()
是一个占位符,用于为每个函数获取相关标记。
当您执行任何针对 current 安全上下文1 进行安全检查的操作时,它会针对当前线程的令牌进行检查- 无论它是什么 - 如果它存在。否则它会根据进程令牌进行检查。
当线程附加了令牌时,从进程的安全上下文到线程的安全上下文没有任何类型的 "inheritance"。您要么获取进程的安全上下文(全部,仅此而已),要么获取线程的特定安全上下文(仅此而已!)。
这实际上就是模仿背后的全部要点,它是 存在的理由2。
您在模仿之前所做的任何成功与您在模仿之后执行相同操作的能力完全无关3。由于您尚未启用允许您更改内核对象所有者的权限(SeTakeOwnershipPrivilege
使您自己成为所有者,正如 Harry Johnston 正确所说 - SeRestorePrivilege
将其他人设置为所有者)您更改它的尝试被拒绝。
启用必要的权限(假设令牌具有)以便能够更改所有者。
1 与故意对另一个安全上下文进行检查的代码相反,例如将 OpenAsSelf = TRUE
传递给 OpenThreadToken
.
2 解释客户端模拟时给出的经典示例是文件服务器 运行 作为 LOCAL_SYSTEM
在请求服务期间模拟客户端以确保它不会不要意外(或故意...)访问不允许客户端访问的文件。如果在模拟期间对模拟线程的任何能力(权限或特权)"leaked" 几乎会破坏模拟客户端的目的。
3 除了 ImpersonateSelf
的特殊情况,在这种情况下显然你应该能够做任何你在模仿之前可以做的事情。
这是我的代码:
logonSuccess = LogonUserW(userPartW, domainPartW, pwdW,
LOGON32_LOGON_BATCH,
LOGON32_PROVIDER_DEFAULT, &token);
Int result1 = SetNamedSecurityInfo("C:\file.crt", SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, yveri, NULL, NULL, NULL);
fprintf(stderr, "result -> %d.\n", result1); //which gives me 0
if (ImpersonateLoggedOnUser(token) == FALSE)
{
printf("Imperesonating failed.\n");
return -1;
}
Int result2 = SetNamedSecurityInfo("C:\Users\nx\.nx\config\authorized.crt", SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, yveri, NULL, NULL, NULL);
fprintf(stderr, "result -> %d.\n", result2); //which gives me 5
第一次调用 SetNamedSecurityInfo 有效,但第二次调用(模拟到位后)returns 错误代码 5。
基于我们在评论中得出的结论:
当您调用任何模拟函数(ImpersonateLoggedOnUser
、ImpersonateNamedPipeClient
、RpcImpersonateClient
等)时,您基本上是在调用 SetThreadToken(GetCurrentThread(), __GetInterestingToken())
(其中 GetInterestingToken()
是一个占位符,用于为每个函数获取相关标记。
当您执行任何针对 current 安全上下文1 进行安全检查的操作时,它会针对当前线程的令牌进行检查- 无论它是什么 - 如果它存在。否则它会根据进程令牌进行检查。
当线程附加了令牌时,从进程的安全上下文到线程的安全上下文没有任何类型的 "inheritance"。您要么获取进程的安全上下文(全部,仅此而已),要么获取线程的特定安全上下文(仅此而已!)。
这实际上就是模仿背后的全部要点,它是 存在的理由2。
您在模仿之前所做的任何成功与您在模仿之后执行相同操作的能力完全无关3。由于您尚未启用允许您更改内核对象所有者的权限(SeTakeOwnershipPrivilege
使您自己成为所有者,正如 Harry Johnston 正确所说 - SeRestorePrivilege
将其他人设置为所有者)您更改它的尝试被拒绝。
启用必要的权限(假设令牌具有)以便能够更改所有者。
1 与故意对另一个安全上下文进行检查的代码相反,例如将 OpenAsSelf = TRUE
传递给 OpenThreadToken
.
2 解释客户端模拟时给出的经典示例是文件服务器 运行 作为 LOCAL_SYSTEM
在请求服务期间模拟客户端以确保它不会不要意外(或故意...)访问不允许客户端访问的文件。如果在模拟期间对模拟线程的任何能力(权限或特权)"leaked" 几乎会破坏模拟客户端的目的。
3 除了 ImpersonateSelf
的特殊情况,在这种情况下显然你应该能够做任何你在模仿之前可以做的事情。