Home > Windows API > How to get name of owner of a process?

How to get name of owner of a process?

Here is a function that extracts the name of the owner of a process…

bool ExtractProcessOwner( HANDLE hProcess_i,
                          CString& csOwner_o )
{
   // Get process token
   HANDLE hProcessToken = NULL;
   if ( !::OpenProcessToken( hProcess_i, TOKEN_READ, &hProcessToken ) || !hProcessToken )
   {
      return false;
   }

   // First get size needed, TokenUser indicates we want user information from given token
   DWORD dwProcessTokenInfoAllocSize = 0;
   ::GetTokenInformation(hProcessToken, TokenUser, NULL, 0, &dwProcessTokenInfoAllocSize);

   // Call should have failed due to zero-length buffer.
   if( ::GetLastError() == ERROR_INSUFFICIENT_BUFFER )
   {
      // Allocate buffer for user information in the token.
      PTOKEN_USER pUserToken = reinterpret_cast<ptoken_user>( new BYTE[dwProcessTokenInfoAllocSize] );
      if (pUserToken != NULL)
      {
         // Now get user information in the allocated buffer
         if (::GetTokenInformation( hProcessToken, TokenUser, pUserToken, dwProcessTokenInfoAllocSize, &dwProcessTokenInfoAllocSize ))
         {
            // Some vars that we may need
            SID_NAME_USE   snuSIDNameUse;
            TCHAR          szUser[MAX_PATH] = { 0 };
            DWORD          dwUserNameLength = MAX_PATH;
            TCHAR          szDomain[MAX_PATH] = { 0 };
            DWORD          dwDomainNameLength = MAX_PATH;

            // Retrieve user name and domain name based on user's SID.
            if ( ::LookupAccountSid( NULL,
                                     pUserToken->User.Sid,
                                     szUser,
                                     &dwUserNameLength,
                                     szDomain,
                                     &dwDomainNameLength,
                                     &snuSIDNameUse ))
            {
               // Prepare user name string
               csOwner_o = _T("\\\\");
               csOwner_o += szDomain;
               csOwner_o += _T("\\");
               csOwner_o += szUser;

               // We are done!
               CloseHandle( hProcessToken );
               delete [] pUserToken;

               // We succeeded
               return true;
            }//End if
         }// End if

         delete [] pUserToken;
      }// End if
   }// End if

   CloseHandle( hProcessToken );

   // Oops trouble
   return false;
}// End GetProcessOwner

The key to this implementation is the function GetTokenInformation and the token information class TokenUser. Take a look in MSDN for this function. Take note of the information classes available. GetTokenInformation returns the users security identifier(SID) using which we called the function LookupAccountSid which returns the corresponding users name.

You may also need the SeDebugPrivilege set to execute this function successfully.

Advertisements
  1. June 26, 2008 at 3:13 am

    Sorry Safuwan, earlier I got it wrong it’s not TOKEN_READ, since your problem is not with the token but instead with “OpenProcess”.

    But in your source code I see a line like this…

    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );

    What I meant earlier was a change like this…

    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID );

    And before passing the process handle to GetProcessOwner make sure you validate returned handle!

    Open process with a lesser access privilege. Try not to use a higher access unless you absolutely require one. Try to minimize access request. For e.g. if you are opening a process for querying information use PROCESS_QUERY_INFORMATION instead of PROCESS_ALL_ACCESS because this will work in nearly all cases.

    Tell me if this doesn’t work out. IMO it should!

  2. safuwan
    June 26, 2008 at 2:04 am

    Mr. Nibuthomas

    i’am already usage TOKEN_READ on OpenProcesss like that

    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( TOKEN_READ, FALSE, pe32.th32ProcessID );

    but instead cannot get owner of process of curret user
    bellow is result:

    hProcess = 00000034
    OpenProcessToken return false : 5
    PROCESS NAME : notepad.exe dwSessionID = 2 processOwner =
    WARNING: GetPriorityClasss filed with error 5 (Access Denied) MODULE NAME : notepad.exe

    hProcess = 00000058
    OpenProcessToken return false : 5
    PROCESS NAME : notepad.exe dwSessionID = 0 processOwner =
    WARNING: GetPriorityClasss filed with error 5 (Access Denied) MODULE NAME : notepad.exe

    Thx

  3. June 25, 2008 at 11:57 am

    Hi Safuwan,

    ->
    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );

    Can you change PROCESS_ALL_ACCESS to a lesser one like TOKEN_READ. Since a normal user won’t get PROCESS_ALL_ACCESS privilege, an administrator will but not a ordinary user.

  4. safuwan
    June 25, 2008 at 11:48 am

    Sorry i’am still cannot get owner of process if running by non administrator member.

    This is may source code to get owner of notepad process.

    what wrong of my source code ?

    BOOL GetProcessList( )
    {
    HANDLE hProcessSnap;
    HANDLE hProcess;
    PROCESSENTRY32 pe32;
    DWORD dwPriorityClass;
    char processOwner[256];

    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
    if( hProcessSnap == INVALID_HANDLE_VALUE )
    {
    printError( “CreateToolhelp32Snapshot (of processes)” );
    return( FALSE );
    }

    // Set the size of the structure before using it.
    pe32.dwSize = sizeof( PROCESSENTRY32 );

    // Retrieve information about the first process,
    // and exit if unsuccessful
    if( !Process32First( hProcessSnap, &pe32 ) )
    {
    printError( “Process32First” ); // Show cause of failure
    CloseHandle( hProcessSnap ); // Must clean up the snapshot object!
    return( FALSE );
    }

    // Now walk the snapshot of processes, and
    // display information about each process in turn
    do
    {
    if (strcmp(pe32.szExeFile,”notepad.exe”)==0)
    {
    DWORD dwSessionId;
    ProcessIdToSessionId(pe32.th32ProcessID, &dwSessionId);

    // Retrieve the priority class.
    dwPriorityClass = 0;
    hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );

    GetProcessOwner( hProcess,processOwner);

    cout << “PROCESS NAME : ” << pe32.szExeFile << ” dwSessionId : ” << dwSessionId << ” processOwner = ” << processOwner << “\n”;

    if( hProcess == NULL )
    printError( “OpenProcess” );
    else
    {
    dwPriorityClass = GetPriorityClass( hProcess );
    if( !dwPriorityClass )
    printError( “GetPriorityClass” );
    CloseHandle( hProcess );
    }

    // List the modules and threads associated with this process
    ListProcessModules( pe32.th32ProcessID );
    //ListProcessThreads( pe32.th32ProcessID );
    }
    } while( Process32Next( hProcessSnap, &pe32 ) );

    CloseHandle( hProcessSnap );
    return( TRUE );
    }

    BOOL ListProcessModules( DWORD dwPID )
    {
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;

    // Take a snapshot of all modules in the specified process.
    hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
    if( hModuleSnap == INVALID_HANDLE_VALUE )
    {
    printError( “CreateToolhelp32Snapshot (of modules)” );
    return( FALSE );
    }

    // Set the size of the structure before using it.
    me32.dwSize = sizeof( MODULEENTRY32 );

    // Retrieve information about the first module,
    // and exit if unsuccessful
    if( !Module32First( hModuleSnap, &me32 ) )
    {
    printError( “Module32First” ); // Show cause of failure
    CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
    return( FALSE );
    }

    // Now walk the module list of the process,
    // and display information about each module
    do
    {
    cout << ” MODULE NAME : ” << me32.szModule < 31 ) || ( *p == 9 ) )
    ++p;
    do { *p– = 0; } while( ( p >= sysMsg ) &&
    ( ( *p == ‘.’ ) || ( *p < 33 ) ) );

    // Display the message
    printf( “\n WARNING: %s failed with error %d (%s)”, msg, eNum, sysMsg );
    }

    bool GetProcessOwner( HANDLE hProcess_i,char* csOwner_o)
    {
    enableDebugPrivileges();

    cout << “hProcess_i = ” << hProcess_i << “\n”;
    // Get process token
    HANDLE hProcessToken = NULL;
    if ( !::OpenProcessToken( hProcess_i, TOKEN_READ, &hProcessToken ) || !hProcessToken )
    {
    cout << “OpenProcessToken return false : ” << GetLastError() << “\n”;
    return false;
    }

    // First get size needed, TokenUser indicates we want user information from given token
    DWORD dwProcessTokenInfoAllocSize = 0;
    ::GetTokenInformation(hProcessToken, TokenUser, NULL, 0, &dwProcessTokenInfoAllocSize);

    // Call should have failed due to zero-length buffer.
    if( ::GetLastError() == ERROR_INSUFFICIENT_BUFFER )
    {
    // Allocate buffer for user information in the token.
    PTOKEN_USER pUserToken = reinterpret_cast( new BYTE[dwProcessTokenInfoAllocSize] );
    if (pUserToken != NULL)
    {
    // Now get user information in the allocated buffer
    if (::GetTokenInformation( hProcessToken, TokenUser, pUserToken, dwProcessTokenInfoAllocSize, &dwProcessTokenInfoAllocSize ))
    {
    // Some vars that we may need
    SID_NAME_USE snuSIDNameUse;
    TCHAR szUser[MAX_PATH] = { 0 };
    DWORD dwUserNameLength = MAX_PATH;
    TCHAR szDomain[MAX_PATH] = { 0 };
    DWORD dwDomainNameLength = MAX_PATH;

    // Retrieve user name and domain name based on user’s SID.
    if ( ::LookupAccountSid( NULL,
    pUserToken->User.Sid,
    szUser,
    &dwUserNameLength,
    szDomain,
    &dwDomainNameLength,
    &snuSIDNameUse ))
    {
    // Prepare user name string
    /*
    csOwner_o = _T(”\\\\”);
    csOwner_o += szDomain;
    csOwner_o += _T(”\\”);
    csOwner_o += szUser;
    */
    strcpy(csOwner_o,szUser);

    // We are done!
    CloseHandle( hProcessToken );
    delete [] pUserToken;

    // We succeeded
    return true;
    }//End if
    }// End if

    delete [] pUserToken;
    }// End if
    }// End if

    CloseHandle( hProcessToken );

    // Oops trouble
    return false;
    }// End GetProcessOwner

    void enableDebugPrivileges()
    {
    HANDLE hcurrent=GetCurrentProcess();
    HANDLE hToken;
    BOOL bret=OpenProcessToken(hcurrent,40,&hToken);
    LUID luid;
    bret=LookupPrivilegeValue(NULL,”SeDebugPrivilege”, &luid);
    TOKEN_PRIVILEGES NewState,PreviousState;
    DWORD ReturnLength;
    NewState.PrivilegeCount =1;
    NewState.Privileges[0].Luid =luid;
    NewState.Privileges[0].Attributes=2;
    AdjustTokenPrivileges(hToken,FALSE,&NewState,28,&PreviousState,&ReturnLength);
    }

  5. June 24, 2008 at 3:18 am

    Take a look here ->

    http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-10/0370.html

    Scroll down and click on next in thread.

  6. safuwan
    June 24, 2008 at 1:51 am

    I am already usage this function and success but if process running on user non administrator memeber then this fuction cannot get owner of process because error on OpenProcessToken.
    Can help me to soleve this problem ?

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: