Winapi 模拟时设置所有权时出现问题

Winapi 模拟时设置所有权时出现问题,winapi,permissions,impersonation,Winapi,Permissions,Impersonation,这是我的密码: logonSuccess = LogonUserW(userPartW, domainPartW, pwdW, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &token); Int result1 = SetNamedSecurityInfo("C:\\file.crt", SE_FILE_OBJECT

这是我的密码:

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的第一次调用有效,但第二次调用(一旦模拟到位)返回错误代码5。

基于我们在注释中得出的结论:

当您调用任何模拟函数(
ImpersonateLoggedOnUser
ImpersonateNamedPipeClient
RpcImpersonateClient
)时,您基本上是在调用
SetThreadToken(GetCurrentThread(),u GetInterestingToken())
(其中
GetInterestingToken()
是一个占位符,用于获取每个函数的相关令牌)

当您执行任何针对当前安全上下文1进行安全检查的操作时,它会针对当前线程的令牌进行检查-无论它是什么-,如果它存在的话。否则,它将根据进程令牌进行检查

当线程附加了一个令牌时,从进程的安全上下文到线程的安全上下文没有任何形式的“继承”。您可以获取进程的安全上下文(全部安全上下文,没有其他内容)或线程的特定安全上下文(没有其他内容!)

这实际上是模仿背后的全部要点,这是存在的理由

你在模仿之前所做的任何事情的成功与你在模仿之后执行相同动作的能力完全无关3。由于您尚未启用允许您更改内核对象所有者的权限(
SeTakeOwnershipPrivilege
以使自己成为所有者,并且正如Harry Johnston正确地说的-
SeRestorePrivilege
以将其他人设置为所有者),因此您更改它的尝试被拒绝

启用必要的权限(假设令牌拥有该权限)以更改所有者


1与故意针对另一个安全上下文进行检查的代码不同,例如将
OpenAsSelf=TRUE
传递到
OpenThreadToken

2解释客户端模拟时给出的典型示例是,在请求服务期间,文件服务器作为
LOCAL\u系统运行
模拟客户端,以确保它不会意外(或故意…)访问客户端不允许访问的文件。如果在模拟过程中,有任何能力(权限或特权)“泄漏”到模拟线程,这几乎会破坏模拟客户端的目的


3除了在特殊情况下的
模拟自己
,在这种情况下,显然你应该能够做任何你在模拟之前可以做的事情。

基于我们在评论中得出的结论:

当您调用任何模拟函数(
ImpersonateLoggedOnUser
ImpersonateNamedPipeClient
RpcImpersonateClient
)时,您基本上是在调用
SetThreadToken(GetCurrentThread(),u GetInterestingToken())
(其中
GetInterestingToken()
是一个占位符,用于获取每个函数的相关令牌)

当您执行任何针对当前安全上下文1进行安全检查的操作时,它会针对当前线程的令牌进行检查-无论它是什么-,如果它存在的话。否则,它将根据进程令牌进行检查

当线程附加了一个令牌时,从进程的安全上下文到线程的安全上下文没有任何形式的“继承”。您可以获取进程的安全上下文(全部安全上下文,没有其他内容)或线程的特定安全上下文(没有其他内容!)

这实际上是模仿背后的全部要点,这是存在的理由

你在模仿之前所做的任何事情的成功与你在模仿之后执行相同动作的能力完全无关3。由于您尚未启用允许您更改内核对象所有者的权限(
SeTakeOwnershipPrivilege
以使自己成为所有者,并且正如Harry Johnston正确地说的-
SeRestorePrivilege
以将其他人设置为所有者),因此您更改它的尝试被拒绝

启用必要的权限(假设令牌拥有该权限)以更改所有者


1与故意针对另一个安全上下文进行检查的代码不同,例如将
OpenAsSelf=TRUE
传递到
OpenThreadToken

2解释客户端模拟时给出的典型示例是,在请求服务期间,文件服务器作为
LOCAL\u系统运行
模拟客户端,以确保它不会意外(或故意…)访问客户端不允许访问的文件。如果在模拟过程中,有任何能力(权限或特权)“泄漏”到模拟线程,这几乎会破坏模拟客户端的目的


3除了
ImpersonateSelf
的特殊情况外,在这种情况下,您显然应该能够完成模拟之前可以完成的任何操作。

为什么要在服务器端使用
CreateFile()
?您应该改用
connectnamepippe()
。命名管道客户端使用
CreateFile()
连接到命名管道。命名管道服务器使用
CreateNamedPipe()
打开管道,然后
ConnectNamedPipe()
接受管道上的客户端。如果您在服务器端使用
CreateFile()
,它将连接到自己的管道,然后模拟自己。感谢您的响应@RemyLebeau我在这里输入了错误的代码,请检查编辑的代码您创建的进程没有什么权限?现在您正在谈论命名管道客户端。您的问题表明问题出在命名管道服务器运行的程序上。请决定是什么问题。我的心灵调试能力(TM Raymond Chen)告诉我,用户名存储在
u中的用户