0

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

user207421
  • 305,947
  • 44
  • 307
  • 483
  • You pass a NULL (really should use `nullptr`) `[in] LPSTARTUPINFOW lpStartupInfo` in your `CreateProcessAsUserW` One of the values in that struct should contain the visibility flag and you should set it. All is described here [CreateProcessAsUser](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw) – Pepijn Kramer Jun 07 '23 at 05:58
  • `ImpersonateLoggedOnUser` not need and senseless. `RevertToSelf` must be called just after `OpenThreadToken`, `hDuppedToken` must be closed, after `CreateProcessAsUserW` - handles to process and thread must be closed, `PROCESS_INFORMATION` not need initi to 0, when in `si` size of struct must be init. all code full of errors. – RbMm Jun 07 '23 at 07:01
  • [`dwCreationFlags`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw) parameter which has a value of 0 specifies the process inherits both the error mode of the caller and the parent's console but `bInheritHandles` FALSE specifies the standard handles cannot be inherited and [you don't supply the standard handles](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa). And you don't set the size of `STARTUPINFO` *si*. Maybe you need to redirect the parent's handles? – YangXiaoPo-MSFT Jun 07 '23 at 07:20
  • thanks everyone, I will update my code accordingly and share findings/updates on how it goes. – g3tsyst3m Jun 07 '23 at 13:25

1 Answers1

0

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");