I am trying to impersonate a client with SYSTEM
privileges.
I noticed that this client it trying to connect to the named pipe: \\.\pipe\abc
.
I setup a named pipe server \\.\pipe\abc
and wait for it to connect.
Once it was connected, it failed:
[+] Creating pipe server
[+] Waiting for client to connect
[+] Client connected
[+] Client impersonated!
[+] Failed to get thread token! 1347
The error 1347 according to Microsoft:
ERROR_CANT_OPEN_ANONYMOUS
1347 (0x543)
Cannot open an anonymous level security token.
Why did it happen? It succeeded to impersonate but then failed to open the thread.
This is my code until the failure on 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;
}
based on comments, in client code -
FILE_FLAG_OPEN_NO_RECALL | FILE_FLAG_OVERLAPPED;
used if place dwFlagsAndAttributes in call of CreateFile
however need notice that FILE_FLAG_OPEN_NO_RECALL == (SECURITY_SQOS_PRESENT|SECURITY_ANONYMOUS)
and FILE_FLAG_OPEN_NO_RECALL == SECURITY_SQOS_PRESENT
both this flags have the same binary value 0x00100000
(and SECURITY_ANONYMOUS == 0
)
think this is problem of design of CreateFile
api. it have less parameters, compare NtCreateFile
and it try combine different parameters in single. for instance in single dwFlagsAndAttributes
combine FileAttributes
+ CreateOptions
+ ObjectAttributes->SecurityQualityOfService
. so parameter is "overloaded"