CreateProcessAsUserW spawns NT AUTHORITY/SYSTEM shell and still shows output from the parent cmd.exe

230 views Asked by At

I'm sure this is a likely a simple fix, but I've not been able to determine what the culprit is here. I don't want to spawn a new console (CREATE_NEW_CONSOLE), but rather use the existing parent thread/console.

Here's a snippet of the code:

std::wcout << "Impersonating the client..." << std::endl;
if (ImpersonateNamedPipeClient(serverPipe))
{
    printf("[+] Successfully Impersonated the client!!\n");
}
else
{
    printf("error: %i\n", GetLastError());
}

STARTUPINFO si = {};
wchar_t command[] = L"C:\\Windows\\system32\\cmd.exe";
PROCESS_INFORMATION pi = {};
HANDLE threadToken;
HANDLE hDuppedToken;
if (OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, false, &threadToken))
{
    printf("[+] OpenThreadToken was a success!!\n");
}
else
{
    printf("[!] OpenThreadToken error: %i\n", GetLastError());
}
if (DuplicateTokenEx(threadToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary,     &hDuppedToken))
{
    printf("[+] DuplicateToken was a success!!\n");
}
else
{
    printf("[!] DuplicateToken error: %i\n", GetLastError());
}
if (ImpersonateLoggedOnUser(hDuppedToken))
{
    printf("[+] ImpersonateLoggedOnUser was a success!!\n");
    TCHAR name[UNLEN + 1];
    DWORD size = UNLEN + 1;
    GetUserName((TCHAR*)name, &size);
    wcout << L"[+] You are now: " << name << "!\n";
}
else
{
    printf("[!] ImpersonateLoggedOnUser error: %i\n", GetLastError());
}
BOOL bRet = CreateProcessAsUserW(hDuppedToken, NULL, command, NULL, NULL, FALSE, NULL, NULL,     NULL, &si, &pi);
if (bRet)
{
    printf("[+] CreateProcess was a success!!\n");
}
else
{
    printf("CreateProcess error: %x\n", GetLastError());
}
RevertToSelf();
CloseHandle(threadToken);
return 0;

The problem is, I still see command output from the owner parent of the process, in this case local admin. I just want to see output from the SYSTEM user.

command output issue

1

There are 1 answers

0
g3tsyst3m On

setting the STARTUPINFO parameters correctly and identifying the si.lpDesktop to point to the appropriate Desktop value did the trick:

ZeroMemory(&si, sizeof(STARTUPINFO)); 
si.cb = sizeof(STARTUPINFO); si.lpDesktop = const_cast<wchar_t*>(L"WinSta0\\Default");