无法打开 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;
}
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
)
认为这是CreateFile
api的设计问题。它的参数较少,比较 NtCreateFile
并尝试将不同的参数组合成一个。例如在单个 dwFlagsAndAttributes
组合 FileAttributes
+ CreateOptions
+ ObjectAttributes->SecurityQualityOfService
。所以参数“超载”
我正在尝试冒充具有 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;
}
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
但是需要注意 FILE_FLAG_OPEN_NO_RECALL == (SECURITY_SQOS_PRESENT|SECURITY_ANONYMOUS)
和 FILE_FLAG_OPEN_NO_RECALL == SECURITY_SQOS_PRESENT
这两个标志具有相同的二进制值 0x00100000
(和 SECURITY_ANONYMOUS == 0
)
认为这是CreateFile
api的设计问题。它的参数较少,比较 NtCreateFile
并尝试将不同的参数组合成一个。例如在单个 dwFlagsAndAttributes
组合 FileAttributes
+ CreateOptions
+ ObjectAttributes->SecurityQualityOfService
。所以参数“超载”