How to get the OWNERs name of a process? [Solved]

Just starting out? Need help? Post your questions and find answers here.
BigJack
User
User
Posts: 76
Joined: Tue May 16, 2006 6:46 am
Location: Germany
Contact:

How to get the OWNERs name of a process? [Solved]

Post by BigJack »

Hi folks,:D
in an attempt to develop a program similar to Windows task-manager, I encountered a problem:
How can I get the owners name (user name) of a running process?
I couldn't find anything helpful in the forum, probably because it is a very specific question. Even google didn't help, except for code examples written in C++ or VB.
Thus far I know how to list all running processes and get their exe-names (thanks to POBSL Process...)

Using PB 4.2 / WindowsXP Pro
Last edited by BigJack on Sun Apr 13, 2008 8:04 pm, edited 1 time in total.
Greetings to all the folks back home in the States...
PB4.2 Windows XP SP3
BigJack
User
User
Posts: 76
Joined: Tue May 16, 2006 6:46 am
Location: Germany
Contact:

Post by BigJack »

I thought it was time to refresh this topic...
Any solutions?
Greetings to all the folks back home in the States...
PB4.2 Windows XP SP3
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

might give some clues:

http://www.purebasic.fr/english/viewtop ... cess+owner

http://www.purebasic.fr/english/viewtop ... r&start=15

But...i've seen some API code somewhere that does this, just have to find it.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Everything I found on the web uses Windows Management Instrumentation (WMI) to obtain the user names. I haven't found any code doing it natively with API.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Code: Select all

; code      : KarLKoX
; date      : 04/05/2008
; changelog : 1.0 - Initial Release
;
; Note      : activate unicode support

#ANYSIZE_ARRAY              = 1
#OWNER_SECURITY_INFORMATION = $00000001

Enumeration ; SID_NAME_USE
  #SidTypeUser = 1
  #SidTypeGroup
  #SidTypeDomain
  #SidTypeAlias
  #SidTypeWellKnownGroup
  #SidTypeDeletedAccount
  #SidTypeInvalid
  #SidTypeUnknown
  #SidTypeComputer
  #SidTypeLabel
EndEnumeration

Enumeration ; SE_OBJECT_TYPE
  #SE_UNKNOWN_OBJECT_TYPE
  #SE_FILE_OBJECT
  #SE_SERVICE
  #SE_PRINTER
  #SE_REGISTRY_KEY
  #SE_LMSHARE
  #SE_KERNEL_OBJECT
  #SE_WINDOW_OBJECT
  #SE_DS_OBJECT
  #SE_DS_OBJECT_ALL
  #SE_PROVIDER_DEFINED_OBJECT
EndEnumeration

Structure SID
  Revision.b
  SubAuthorityCount.b
  *IdentifierAuthority.SID_IDENTIFIER_AUTHORITY
  SubAuthority.l[#ANYSIZE_ARRAY]
EndStructure

Prototype.l PFNCreateToolhelp32Snapshot(dwFlags.l, th32ProcessID.l)
Prototype.b PFNProcess32First(hSnapshot.l, *lppe.PROCESSENTRY32)
Prototype.b PFNProcess32Next(hSnapshot.l, *lppe.PROCESSENTRY32)
Prototype.b PFNThread32First(hSnapshot.l, *lppe.THREADENTRY32)
Prototype.b PFNThread32Next(hSnapshot.l, *lppe.THREADENTRY32)

Procedure DBG(out.s)
CompilerIf #PB_Compiler_Debugger
  Debug out
CompilerEndIf
EndProcedure

Procedure.l GetPidByName(name.s)
Protected hDLL.l, process_name.s
Protected PEntry.PROCESSENTRY32, hTool32.l
Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot
Protected pProcess32First.PFNProcess32First
Protected pProcess32Next.PFNProcess32Next

  hDLL = OpenLibrary(#PB_Any,"kernel32.dll")
  If hDLL
    ; get function pointer
    pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot")
    pProcess32First = GetFunction(hDLL,"Process32FirstW")
    pProcess32Next = GetFunction(hDLL,"Process32NextW")
  Else
    DBG("GetPidByName:: OpenLibrary failed !")
    ProcedureReturn 0
  EndIf
   
  PEntry\dwSize = SizeOf(PROCESSENTRY32)
  hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0)
  pProcess32First(hTool32, @PEntry)
  process_name = Space(#MAX_PATH)
  CopyMemory(@PEntry\szExeFile,@process_name,StringByteLength(process_name))
  If process_name = name 
    ProcedureReturn PEntry\th32ProcessID
  EndIf
  While pProcess32Next(hTool32, @PEntry) > 0
    process_name = Space(#MAX_PATH)
    CopyMemory(@PEntry\szExeFile,@process_name,StringByteLength(process_name))
    If process_name = name
      ProcedureReturn PEntry\th32ProcessID
    EndIf
  Wend
    
  CloseLibrary(hDLL)
  CloseHandle_(pCreateToolhelp32Snapshot)
  
  ProcedureReturn 0
EndProcedure

Macro MAKELANGID(p, s)
  (s << 10 | p)
EndMacro 

; format the errcode to the corresponding message error string
Procedure.s GetLastErrorString(lErrCode.l)
Protected lpMsgBuf.l
Protected out.s = ""
  
  If lErrCode
    FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, #Null, lErrCode, MAKELANGID(#LANG_NEUTRAL, #SUBLANG_DEFAULT), @lpMsgBuf, 0, #Null)
    out = PeekS(lpMsgBuf)
    LocalFree_(lpMsgBuf)
  EndIf
 
  ProcedureReturn out
EndProcedure 

Procedure.s getOwnerObject(pid.l)
Protected owner.s
Protected *pSidOwner.SID, *pSD.SECURITY_DESCRIPTOR
Protected dwRtnCode.l, bRtnBool.l
Protected AcctName.s, DomainName.s
Protected dwAcctName.l, dwDomainName.l
Protected eUse.l = #SidTypeUnknown

  If pid = #INVALID_HANDLE_VALUE
    DBG("Invalid pid !")
    ProcedureReturn ""
  EndIf
  
  object = OpenProcess_(#READ_CONTROL, #False, pid)
  If object = #INVALID_HANDLE_VALUE
    DBG("Invalid object handle !")
    ProcedureReturn ""
  EndIf
  
  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY | #TOKEN_ADJUST_PRIVILEGES, @htok) <= 0
    DBG("OpenProcessToken failed")
    ProcedureReturn ""
  EndIf
  
  ; allocate memory for the SID structure
  *pSidOwner = AllocateMemory(SizeOf(SID))
  If *pSidOwner = 0
    DBG("Can't allocate memory for the SID structure")
    ProcedureReturn ""
  EndIf
  
  ; allocate memory for the security descriptor structure
  *pSD = AllocateMemory(SizeOf(SECURITY_DESCRIPTOR))
  If *pSD = 0
    DBG("Can't allocate memory for the SECURITY_DESCRIPTOR structure")
    ProcedureReturn ""
  EndIf
  
  ; get the owner SID of the object
  dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @*pSD)
  
  ; check GetLastError for GetSecurityInfo error condition
  If dwRtnCode <> #ERROR_SUCCESS
    DBG("GetSecurityInfo error = " + GetLastErrorString(dwRtnCode) )
    ProcedureReturn ""
  EndIf  
  
  ; first call to LookupAccoundSid to get the buffer sizes
  bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
  
  ; reallocate memory for the buffers
  AcctName = Space(dwAcctName)
  DomainName = Space(dwDomainName)
  
  ; second call to LookupAccountSid to get the account name
  bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse)
  
  ; close the process handle
  CloseHandle_(object)
  
  ProcedureReturn AcctName
EndProcedure

Procedure Test()
Protected pid1.l, pid2.l
Protected owner1.s, owner2.s

  ; should be different
  pid1 = GetPidByName("explorer.exe")
  pid2 = GetPidByName("lsass.exe")  
  owner1 = getOwnerObject(pid1)
  owner2 = getOwnerObject(pid2)
  
  MessageRequester("Result", "The Owner of explorer.exe is " + owner1 + " and the owner of lsass.exe is " + owner2 )
EndProcedure

Test()
Hope it helps.
Last edited by KarLKoX on Sat Apr 05, 2008 10:21 pm, edited 1 time in total.
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Yeah, what karlkox posted, thats the api stuff I was thinking of.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Does it work for you? Although I haven't tested other executables yet I get "Invalid handle" error on both demo .EXE's.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

; Note : activate unicode support
i assume this means you have to switch unicode mode on :wink:
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Indeed! Image

One more thing ...

For "lsass.exe" it says "Administratoren" and the taskmanager says "SYSTEM". That is the same, isn't it?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

I've noticed that too, Administrator and System are not the same it turns out. One is an account the other is root level system. Its possible they can both be at the same permission level, but they would still be different and be called Administrator and System. So for "lsass.exe" it might say Administrator because it ran when the administrator logged in with those permissions because the admin long in actually triggered it to run so the admin would be the owner in terms of it running instead of the system running it whereas its a system level access for the process task which would mean that it shows system in task manager. At least from what I can tell.

that make sense? I'm probably wrong or said it wrong, done it before so this would not be the last time :)
BigJack
User
User
Posts: 76
Joined: Tue May 16, 2006 6:46 am
Location: Germany
Contact:

Post by BigJack »

Very impressive code you posted - thanks!
But unfortunately it doesn't return any value here.
System: Windows XP Pro SP2
PureBasic 4.2 Beta
Greetings to all the folks back home in the States...
PB4.2 Windows XP SP3
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

without unicode enabled returns the names of the two processes but never gives the owner and gives two errors in the debug

GetSecurityInfo error = The handle is invalid.
GetSecurityInfo error = The handle is invalid.

This is on Vista so it might not like the SECURITY_DESCRIPTOR in some way. With unicode enabled it gives the owner of explorer.exe correctly (owner 1) but never shows the owner for lsass.exe and still gives one error in the debug GetSecurityInfo error = The handle is invalid.
jpd
Enthusiast
Enthusiast
Posts: 167
Joined: Fri May 21, 2004 3:31 pm

Post by jpd »

Hi,

here a modified code that running in Ansi/Unicode and

solve the Problem described by SFSyOI on Vista.


Code: Select all


; code      : KarLKoX 
; date      : 04/05/2008 
; changelog : 1.0 - Initial Release 
; 
; Note      : activate unicode support 



#ANYSIZE_ARRAY              = 1 
#OWNER_SECURITY_INFORMATION = $00000001 

Enumeration ; SID_NAME_USE 
  #SidTypeUser = 1 
  #SidTypeGroup 
  #SidTypeDomain 
  #SidTypeAlias 
  #SidTypeWellKnownGroup 
  #SidTypeDeletedAccount 
  #SidTypeInvalid 
  #SidTypeUnknown 
  #SidTypeComputer 
  #SidTypeLabel 
EndEnumeration 

Enumeration ; SE_OBJECT_TYPE 
  #SE_UNKNOWN_OBJECT_TYPE 
  #SE_FILE_OBJECT 
  #SE_SERVICE 
  #SE_PRINTER 
  #SE_REGISTRY_KEY 
  #SE_LMSHARE 
  #SE_KERNEL_OBJECT 
  #SE_WINDOW_OBJECT 
  #SE_DS_OBJECT 
  #SE_DS_OBJECT_ALL 
  #SE_PROVIDER_DEFINED_OBJECT 
EndEnumeration 

Structure SID 
  Revision.b 
  SubAuthorityCount.b 
  *IdentifierAuthority.SID_IDENTIFIER_AUTHORITY 
  SubAuthority.l[#ANYSIZE_ARRAY] 
EndStructure 

; ------------------------ Get PID 

#TH32CS_SNAPPROCESS = $2 


Procedure DBG(out.s) 
CompilerIf #PB_Compiler_Debugger 
  Debug out 
CompilerEndIf 
EndProcedure 


Macro MAKELANGID(p, s) 
  (s << 10 | p) 
EndMacro 

; format the errcode to the corresponding message error string 
Procedure.s GetLastErrorString(lErrCode.l) 
Protected lpMsgBuf.l 
Protected out.s = "" 
  
  If lErrCode 
    FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, #Null, lErrCode, MAKELANGID(#LANG_NEUTRAL, #SUBLANG_DEFAULT), @lpMsgBuf, 0, #Null) 
    out = PeekS(lpMsgBuf) 
    LocalFree_(lpMsgBuf) 
  EndIf 
  
  ProcedureReturn out 
EndProcedure 

Procedure SearchPID(Name.s) 
;-http://www.purebasic.fr/german/viewtopic.php?t=10576&postdays=0&postorder=asc&highlight=processentry33&start=10
  Protected result.l, Snapshot.l, ProcessFound.l, PN$, Process.PROCESSENTRY32 
  Process\dwSize = SizeOf(PROCESSENTRY32) 
  Snapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
  If Snapshot 
    ProcessFound = Process32First_(Snapshot, Process) 
    While ProcessFound 
      PN$ = UCase(PeekS(@Process\szExeFile, #PB_Any, #PB_Ascii)) 
      If UCase(Name) = GetFilePart(PN$)  
        ProcedureReturn Process\th32ProcessID 
      EndIf 
      ProcessFound = Process32Next_(Snapshot, Process) 
    Wend 
    CloseHandle_(Snapshot) 
  EndIf 
  ProcedureReturn 0
EndProcedure 

Procedure.s getOwnerObject(pid.l) 
Protected owner.s 
Protected *pSidOwner.SID, *pSD.SECURITY_DESCRIPTOR 
Protected dwRtnCode.l, bRtnBool.l 
Protected AcctName.s, DomainName.s 
Protected dwAcctName.l, dwDomainName.l 
Protected eUse.l = #SidTypeUnknown 

  If pid = #INVALID_HANDLE_VALUE 
    DBG("Invalid pid !") 
    ProcedureReturn "" 
  EndIf 
  
  object = OpenProcess_(#READ_CONTROL, #False, pid) 
  If object = #INVALID_HANDLE_VALUE 
    DBG("Invalid object handle !") 
    ProcedureReturn "" 
  EndIf 
  
  If OpenProcessToken_(GetCurrentProcess_(), #TOKEN_QUERY | #TOKEN_ADJUST_PRIVILEGES, @htok) <= 0 
    DBG("OpenProcessToken failed") 
    ProcedureReturn "" 
  EndIf 
  
  ; allocate memory for the SID structure 
  *pSidOwner = AllocateMemory(SizeOf(SID)) 
  If *pSidOwner = 0 
    DBG("Can't allocate memory for the SID structure") 
    ProcedureReturn "" 
  EndIf 
  
  ; allocate memory for the security descriptor structure 
  *pSD = AllocateMemory(SizeOf(SECURITY_DESCRIPTOR)) 
  If *pSD = 0 
    DBG("Can't allocate memory for the SECURITY_DESCRIPTOR structure") 
    ProcedureReturn "" 
  EndIf 
  
  ; get the owner SID of the object 
  dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @*pSD) 
   ; dwRtnCode = GetSecurityInfo_(object, #SE_KERNEL_OBJECT, #OWNER_SECURITY_INFORMATION, @*pSidOWner, #Null, #Null, #Null, @pSD) 
  ; check GetLastError for GetSecurityInfo error condition 
  If dwRtnCode <> #ERROR_SUCCESS 
    DBG("GetSecurityInfo error = " + GetLastErrorString(dwRtnCode) ) 
    ProcedureReturn "" 
  EndIf  
  
  ; first call to LookupAccoundSid to get the buffer sizes 
  bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse) 
  
  ; reallocate memory for the buffers 
  AcctName = Space(dwAcctName) 
  DomainName = Space(dwDomainName) 
  
  ; second call to LookupAccountSid to get the account name 
  bRtnBool = LookupAccountSid_(#Null, *pSidOwner, AcctName, @dwAcctName, DomainName, @dwDomainName, @eUse) 
  
  ; close the process handle 
  CloseHandle_(object) 
  
  ProcedureReturn AcctName 
EndProcedure 






Procedure Test() 
Protected pid1.l, pid2.l 
Protected owner1.s, owner2.s 

pid1=SearchPID("explorer.exe")
pid2=SearchPID("lsass.exe")

 
  Debug pid1
  Debug pid2
  owner1 = getOwnerObject(pid1) 
  owner2 = getOwnerObject(pid2) 
  
  MessageRequester("Result", "The Owner of explorer.exe is " + owner1 + " and the owner of lsass.exe is " + owner2 ) 
EndProcedure 

#SE_DEBUG_NAME="SeDebugPrivilege" ; missing constant 

Procedure EnableDebugPrivNT() 
;-http://www.purebasic.fr/english/viewtopic.php?t=31161&highlight=enabledebugprivnt

   DebugValue.LUID; 
   tkp.TOKEN_PRIVILEGES 
    
   ; Retrieve a handle of the access token 
   If Not OpenProcessToken_(GetCurrentProcess_(),#TOKEN_ADJUST_PRIVILEGES|#TOKEN_QUERY,@hToken) 
      ProcedureReturn #False; 
   EndIf 
    
   ; Enable the SE_DEBUG_NAME privilege 
   If Not LookupPrivilegeValue_("",#SE_DEBUG_NAME,@DebugValue) 
      ProcedureReturn #False; 
   EndIf 
    
   NewState.TOKEN_PRIVILEGES 
   NewState\PrivilegeCount=1 
   NewState\Privileges[0]\Luid\HighPart=DebugValue\HighPart 
   NewState\Privileges[0]\Luid\LowPart=DebugValue\LowPart 
   NewState\Privileges[0]\Attributes=#SE_PRIVILEGE_ENABLED 
   AdjustTokenPrivileges_(hToken,#False,@NewState,SizeOf(TOKEN_PRIVILEGES),@PreviousState.TOKEN_PRIVILEGES,@ReturnLength) 
    
   If GetLastError_()<>#ERROR_SUCCESS 
      ProcedureReturn #False 
   EndIf 

   ProcedureReturn #True 
EndProcedure



If EnableDebugPrivNT() 

  Debug "privilege loaded..."
  Test() 
 Else
  Debug "privilege not setted...."
 EndIf
 

PB 5.10 Windows 7 x64 SP1
BigJack
User
User
Posts: 76
Joined: Tue May 16, 2006 6:46 am
Location: Germany
Contact:

Post by BigJack »

WOW....
absolutely great - and it now return the required values. :D
Thanks for sharing this piece of code...
Greetings to all the folks back home in the States...
PB4.2 Windows XP SP3
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: How to get the OWNERs name of a process? [Solved]

Post by IdeasVacuum »

[PB5.20LTS WinXP x86]

jpd's version reports GetSecurityInfo error = The handle is invalid. with Compiler set to Unicode, but delivers the correct names when set to ASCII. The original KarLKoX code works with Unicode only.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply