OpenProcessToken fails with ERROR_ACCESS_DENIED from a local system service - c++

Let me explain my situation first. The issue I describe below comes from an end-user's machine, and all I have to work with is just a copy of the Windows Event Log. I cannot access the machine itself to run any debugging tests.
Now the issue. I have a service application that I create as such:
SC_HANDLE hScService = CreateService(hScManager,
L"MyServiceID",
L"My Service Name",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
SrvcPath,
NULL, NULL, NULL, NULL, _T(""));
The service process later has its SE_DEBUG_NAME privilege set using the AdjustTokenPrivileges API.
Later on I have a method that enumerates running processes and later gets processes LUIDs, using a code as such:
//'pProcIDs' = list of process IDs obtained from EnumProcesses()
for(UINT i = 0; i < nNumProc; i++)
{
DWORD dwProcID = pProcIDs[i];
//Skip obvious system processes
if(dwProcID != 0 &&
dwProcID != 4)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcID);
if(hProcess)
{
HANDLE hTokenHandle;
if(::OpenProcessToken(hProcess, TOKEN_QUERY, &hTokenHandle))
{
TOKEN_STATISTICS ts;
DWORD dwcbSz = 0;
if(::GetTokenInformation(hTokenHandle, TokenStatistics, &ts, sizeof(ts), &dwcbSz))
{
//And so on...
}
else
{
//Handle error here
}
::CloseHandle(hTokenHandle);
}
else
{
//***Here's where I get my error in question***
}
::CloseHandle(hProcess);
}
else
{
//Handle error here
}
}
}
When I run the code above on my own development computers, it runs just fine. Note that those computers run "stock" copies of the OS without any AVP or other third-party software installed.
The event log copy I received from a customer running Windows 7 Professional machine (that is a member of an Active Directory domain) has 3 processes that return ERROR_ACCESS_DENIED when I call OpenProcessToken on them from the code above. Their PIDs are just regular values, such as 1824, 2760, 5024 (that obviously change after a reboot.)
Does anyone have any idea why it happens? Do I need to set additional privileges for my service?
PS. From the event log I can tell that the workstation in question has some Symantec Antivirus product installed, judging by this line:
New virus definition file loaded. Version: 140217066.

Symantec antivirus software (as well as that of many other security software vendors) may attempt to prevent tampering with their processes by un-authorized actors. Acquiring the process token for one of their processes just might qualify.
That said, you can quickly verify that the PIDs in question are in fact part of the Symantec package by examining the path to executable images that back the processes. If they are part of the Symantec AV software package, you'll need to look in to configuring it to trust your application, or disable it while you run this code (not recommended), or simply ignore errors of this type.

Related

WinUSB crashes with Error 1450 "Insufficient system resources exist to complete the requested service"

i'm developing an Application in C++ for communicating via USB with a custom hardware based on a SAM-E70 which exchanges large amounts of data with the PC. While normally working fine, the WinUSB Driver will always crash after roughly two hours during a Transmission with Windows-Error 1450:
"Insufficient system resources exist to complete the requested service".
Visual Studio and the WinUSB Guide do not provide any information for this problem, so any idea is appreciated.
if (WinUsb_WritePipe(deviceData.WinusbHandle, list.Bulk.PipeOutId, bulk_tx_buf, 512, &bulk_tx_transferred, 0)) {
//when transmission was successful, remove command from the stack
command_list.pop();
}
else {
DWORD err = GetLastError();
callback_error("Error during transmission, Code: " + std::to_string(err));
call_terminate = true;
}

DIrectshow function is blocked at system bootup

I have an Directshow based mediaplayer application . It works very well without any issues during normal playabck . But occasionally i am facing one issue when the Mediaplayer started just after system boot .
HRESULT CSDirectShow::RenderOutputPins (IBaseFilter* pFilter)
{
const char* funcName = "CSDirectShow::RenderOutputPins()";
HRESULT hr = S_OK;
// Enumerate all pins on the source filter,
// looking for the output pins so that I can call Render() on them
//
CComPtr< IEnumPins > pEnumPin;
if (!FAILED (pFilter->EnumPins (&pEnumPin)))
{
while (true)
{
// get the next pin
//
CComPtr< IPin > pPin;
if (pEnumPin->Next (1L, &pPin, NULL) != S_OK) break;
// I'm not interested in connected pins
// if this pin is an unconnected output pin, then render it.
//
CComPtr< IPin > pConnectedPin;
if (pPin->ConnectedTo (&pConnectedPin) == VFW_E_NOT_CONNECTED)
{
PIN_DIRECTION pinDirection;
PIN_INFO pinInfo;
//Get the information of the pin
if (pPin->QueryDirection (&pinDirection) == S_OK
&& pinDirection == PINDIR_OUTPUT
&& pPin->QueryPinInfo(&pinInfo) == S_OK
&& strstr((char*)pinInfo.achName,"~")==NULL)
{
if (FAILED (hr = m_pGB->Render (pPin)))
{
SafeRelease(&pinInfo.pFilter);
return hr;
}
}
SafeRelease(&pinInfo.pFilter);
}
}
}
TraceMsg ("%s: exit",funcName);
return S_OK;
}
When m_pGB->Render (pPin) is called ,This function never returns and it is blocked inside .I confirmed using logs .This issue happens only when i start my application immediately after bootup . When issues occures if I close and restart my application it works like a charm .Since application is designed to start automatically after system bootup this behaviour has become a bigger concern .Kindly help
IGraphBuilder.Render call does a lot internally, and specifically it goes over enumeration of potentially suitable filter, which in turn attempts to load additional DLLs registered with DirectShow environment. Such file could have missing dependencies, or dependencies on remote or temporarily inaccessible drivers (just one example).
If you experience a deadlock, you can troubleshoot it further (debug it) and get details on locked state, and on activity during Render call.
If the problem is caused by third party filters (esp. codec packs registering a collection of filters at once without thinking too much on compatibility) registered with the system in a not so good way, perhaps you could identify them and uninstall.
If you want to improve the player on your side, you should avoid Render call, and build your filter graph with smaller increments - adding specific filter and connecting pins, without leaving big tasks at mercy of Intelligent Connect, which works well in general but is sensitive to compatibility problems as mentioned above.

Trying to run user-mode process from a local service with medium integrity level

My goal is to run my user GUI process in a logged on user session from my local service. I roughly do the following:
//Pseudo-code, with error checks omitted
HANDLE hToken;
WTSQueryUserToken(dwUserSessionID, &hToken);
HANDLE hToken2;
DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken2);
//Need to adjust UIAccess for the needs of the user process
DWORD dwUIAccess = 1;
SetTokenInformation(hToken2, TokenUIAccess, &dwUIAccess, sizeof(dwUIAccess));
ImpersonateLoggedOnUser(hToken2);
CreateProcessAsUser(hToken2, strUserExeFilePath, ...);
RevertToSelf();
CloseHandle(hToken2);
CloseHandle(hToken);
This works and the user process starts just fine, but there's one issue with its integrity level. When this code runs right after the service is installed (when the user session has been long logged on) the user process it creates has SECURITY_MANDATORY_MEDIUM_RID, which is the level I would expect.
But if the code above is run right after an interactive Windows user logs on to the workstation, the user process starts up but it has the SECURITY_MANDATORY_HIGH_RID integrity level. (I am testing it on Windows 7.)
So I thought to add the following code to adjust the integrity level:
PSID pSidIL = NULL;
//INFO on SID: https://support.microsoft.com/en-us/kb/243330?wa=wsignin1.0
ConvertStringSidToSid(L"S-1-16-8192", &pSidIL);
TOKEN_MANDATORY_LABEL tml = {0};
tml.Label.Attributes = SE_GROUP_INTEGRITY;
tml.Label.Sid = pSidIL;
SetTokenInformation(hToken2, TokenIntegrityLevel, &tml, sizeof(TOKEN_MANDATORY_LABEL) + ::GetSidLengthRequired(1));
LocalFree(pSidIL);
but it made no difference, and the user process still ran with high integrity level after a user logon.
Any idea what am I doing wrong here?

WinAPI: OpenProcess() returns error 5 with SeDebugPrivilege enabled for host process

I've got a routine where I process-walk to obtain the HANDLE of each process as I 'walk' down the list (which works fine), but my issue lies when I do:
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID) where PROCESS_ALL_ACCESS is the access token, handle inheritance is set to FALSE, and pe32 is a PROCESSENTRY32
GetLastError() returns error code 5, and all the handles that are made are addresses which do not correspond to any appropriate process in Spy++32/64 (I've tried building the application under both platform targets, but as you'd expect, the result is the same).
The code for setting SeDebugPrivilege for the host process which I'm using is:
BOOL EnableDebugPrivilege(BOOL bEnable)
{
HANDLE hToken = nullptr;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE;
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE;
TOKEN_PRIVILEGES tokenPriv;
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE;
return TRUE;
}
Some questions that would be helpful to you:
I'm running Windows 7 x64 Professional.
Yes, devenv.exe is started with "Run as Administrator" privileges, which means that the debugger and the application itself are started under the same affinity.
I have tried toggling UAC or running the application with UAC off altogether. Still error code 5.
I just attempted doing it with PROCESS_QUERY_LIMITED_INFORMATION and I receive error code 6, or ERROR_INVALID_HANDLE. Also attempted with PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, result is error 5 again.
SeDebugPrivilege is enabled, verified with SysInternals' Process Explorer. Additionally, all processes that spawn from devenv/whatever the debugger is called inherit SeDebugPrivilege so...this is weird.
Thank you all very much for your time, I'm reaching wits end with this issue :S
Are you sure you are not passing 0 as a process ID value? The system idle process with ID 0 is included in the snapshot under the name [System Process], but you can't open a handle for it as the documentation for OpenProcess specifically says it'll fail. Well it says a bit more:
If the specified process is the System Process (0x00000000), the
function fails and the last error code is ERROR_INVALID_PARAMETER. If
the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
Well, it's not completely true as I was able to open handle to CSRSS (of course, it doesn't actually have the requested rights). But it may fail for some protected processes (audiodg), so you shouldn't not do this. Instead, check the name of the process if it's the one you want.

LsaEnumerateLogonSessions error

I have a Windows service which starts another application using CreateProcess. Thus, the application runs with SYSTEM privileges. This application calls LsaEnumerateLogonSessions, which returns the error code 8 (Not enough storage is available to process this command.). The service and the application are run under Windows 7 x64.
ULONG luLogonSessionCount = 0;
LUID *pLogonSessionList = NULL;
NTSTATUS lNtStatus = LsaEnumerateLogonSessions(
&luLogonSessionCount, &pLogonSessionList );
LsaNtStatusToWinError( lNtStatus ) returns 8. Does anyone know the cause of this?
Thanks in advance!
Most services nowadays run under a service account, for security reasons. Check that your service has adequate permissions. What is the actual NTSTATUS result?