无法打开 NamedPipe 客户端的线程令牌:"Cannot open an anonymous level security token"

Can't open thread token of NamedPipe client: "Cannot open an anonymous level security token"

我正在尝试冒充具有 SYSTEM 权限的客户。
我注意到这个客户端试图连接到命名管道:\.\pipe\abc.

我设置了命名管道服务器 \.\pipe\abc 并等待它连接。
连接后失败:

[+] Creating pipe server
[+] Waiting for client to connect
[+] Client connected
[+] Client impersonated!
[+] Failed to get thread token! 1347

根据微软的error 1347

ERROR_CANT_OPEN_ANONYMOUS

1347 (0x543)

Cannot open an anonymous level security token.

为什么会这样?模拟成功,但打开线程失败。

这是我的代码,直到 OpenThreadToken

失败
SECURITY_ATTRIBUTES SecurityAttrs = {
      sizeof(SECURITY_ATTRIBUTES),
      NULL,                               // assigned access token of calling process
      FALSE
  };

  DWORD openMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_OWNER;
  DWORD pipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;

  std::cout << "[+] Creating pipe server\n";
  for (;;) {
      // create the named pipe
      HANDLE pipe = NULL;

      DWORD msgSize = 1024;
      pipe = CreateNamedPipeA(
          "\\.\pipe\abc",
          openMode,
          pipeMode,
          1,              // max instances
          msgSize,        // out buffer size
          msgSize,        // in buffer size
          0,              // timeout. 0 ~= 50ms
          &SecurityAttrs);

      if (pipe == INVALID_HANDLE_VALUE) {
          DWORD err = GetLastError();
          std::cout << "[!] Pipe creation failed! " << err << std::endl;
          return err;
      }

      // wait for client to connect
      std::cout << "[+] Waiting for client to connect\n";
      bool connected = ConnectNamedPipe(pipe, NULL) ? true : (
          GetLastError() == ERROR_PIPE_CONNECTED);
      if (!connected)
          continue;
      std::cout << "[+] Client connected\n";

      // read from pipe
      char buf[msgSize];
      DWORD bytesread = 0;
      bool status = ReadFile(
          pipe,
          &buf,
          msgSize,
          &bytesread,
          NULL);

      // impersonate the connector
      if (!ImpersonateNamedPipeClient(pipe)) {
          DWORD err = GetLastError();
          std::cout << "[!] Impersonation failed! " << err << std::endl;
          return -1;
      }
      std::cout << "[+] Client impersonated!\n";

      HANDLE hToken = {};

      if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, &hToken)) {
          DWORD err = GetLastError();
          std::cout << "[!] Failed to get thread token! " << err << std::endl;
          return err;
      }

根据OpenThreadToken

If the token has the anonymous impersonation level, the token will not be opened and OpenThreadToken sets ERROR_CANT_OPEN_ANONYMOUS as the error.

并且根据 Impersonation Levels,

The client of a named pipe, RPC, or DDE connection can control the impersonation level. For example, a named pipe client can call the CreateFile function to open a handle to a named pipe and specify the server's impersonation level.

When the named pipe, RPC, or DDE connection is remote, the flags passed to CreateFile to set the impersonation level are ignored. In this case, the impersonation level of the client is determined by the impersonation levels enabled by the server, which is set by a flag on the server's account in the directory service. For example, if the server is enabled for delegation, the client's impersonation level will also be set to delegation even if the flags passed to CreateFile specify the identification impersonation level.

您的命名管道客户端确实需要调用 CreateFile 函数来打开命名管道的句柄并指定服务器的模拟级别。

基于注释,在客户端代码中 -

FILE_FLAG_OPEN_NO_RECALL | FILE_FLAG_OVERLAPPED;

CreateFile

的调用中放置 dwFlagsAndAttributes 时使用

但是需要注意 FILE_FLAG_OPEN_NO_RECALL == (SECURITY_SQOS_PRESENT|SECURITY_ANONYMOUS)FILE_FLAG_OPEN_NO_RECALL == SECURITY_SQOS_PRESENT

这两个标志具有相同的二进制值 0x00100000(和 SECURITY_ANONYMOUS == 0

认为这是CreateFileapi的设计问题。它的参数较少,比较 NtCreateFile 并尝试将不同的参数组合成一个。例如在单个 dwFlagsAndAttributes 组合 FileAttributes + CreateOptions + ObjectAttributes->SecurityQualityOfService 。所以参数“超载”