 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Conquer
Joined: 27 Jun 2006 Posts: 384 Location: Canada
|
Posted: Sun Feb 10, 2008 1:00 am Post subject: [SOLVED] Get a list of _user_ processes only |
|
|
EDIT>> Updated script below:
Gets the list of processes running under the current user. Special thanks to the below posters for making/updating the code
| Code: | d = `n ; string separator
s := 4096 ; size of buffers and arrays (4 KB)
Process, Exist ; sets ErrorLevel to the PID of this running script
; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
VarSetCapacity(ti, 16, 0) ; structure of privileges
NumPut(1, ti, 0, 4) ; one entry in the privileges array...
; Retrieves the locally unique identifier of the debug privilege:
DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "UIntP", luid)
NumPut(luid, ti, 4, 8)
NumPut(2, ti, 12, 4) ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
; Update the privileges of this process with the new access token:
DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)
DllCall("CloseHandle", "UInt", h) ; close this process handle to save memory
MySIDsize:=255, VarSetCapacity(MySID,MySIDsize,0)
sDomainSize:=255, VarSetCapacity(sDomain,sDomainSize,0)
if( !dllCall("advapi32\LookupAccountNameA" ,"uint",0,"str",A_UserName
,"uint",&MySID,"uint*",MySIDsize,"str",sDomain,"uint*",sDomainSize,"uint*",SIDtype))
msgbox Cannot obtain SID for "%A_UserName%"
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; increase performance by preloading the libaray
s := VarSetCapacity(a, s) ; an array that receives the list of process identifiers:
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4 ; parse array for identifiers as DWORDs (32 bits):
{
id := NumGet(a, A_Index * 4)
; open process with: PROCESS_QUERY_INFORMATION (0x0400) | PROCESS_VM_READ (0x0010) | READ_CONTROL
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400 | 0x20000, "Int", false, "UInt", id)
bMyProcess=0
if(0=dllcall("advapi32\GetSecurityInfo","uint",h, "uint",6,"uint",1
,"uintP",ppSIDowner,"uint",0,"uint",0,"uint",0,"uintP",ppSecuDsc))
if ppSecuDsc
{ bMyProcess:=DllCall("advapi32\EqualSid","uint",&MySID,"uint",ppSIDowner)
dllCall("LocalFree","uint",ppSecuDsc)
}
if bMyProcess
{
s := VarSetCapacity(m, 2 << 9) ; for array of modules:
DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r)
s := VarSetCapacity(n, 32) ; for module base name:
e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s)
If n ; if image is not null add to list:
l = %l%%n%%d%
}
DllCall("CloseHandle", "UInt", h) ; close process handle to save memory
}
DllCall("FreeLibrary", "UInt", hModule) ; unload the library to free memory
; Remove the first and last items in the list (possibly ASCII signitures)
StringMid, l, l, InStr(l, d) + 1, InStr(l, d, false, 0) - 2 - InStr(l, d)
StringReplace, l, l, %d%, %d%, UseErrorLevel ; gets the number of processes
;Sort, l, C ; uncomment this line to sort the list alphabetically
MsgBox, 0, %ErrorLevel% Processes, %l% |
Thanks again  _________________

Last edited by Conquer on Thu Feb 14, 2008 1:09 am; edited 1 time in total |
|
| Back to top |
|
 |
wOxxOm
Joined: 09 Feb 2006 Posts: 322
|
Posted: Sun Feb 10, 2008 3:48 pm Post subject: |
|
|
| use a dllcall to "GetSecurityInfo" api function |
|
| Back to top |
|
 |
Conquer
Joined: 27 Jun 2006 Posts: 384 Location: Canada
|
Posted: Mon Feb 11, 2008 11:55 pm Post subject: |
|
|
| MSDN: "GetSecurityInfo" wrote: | | The GetSecurityInfo function retrieves a copy of the security descriptor for an object specified by a handle. |
| MSDN: "Security Descriptor" wrote: | | A structure and associated data that contains the security information for a securable object. A security descriptor identifies the object's owner and primary group. It can also contain a DACL that controls access to the object, and a SACL that controls the logging of attempts to access the object. |
| MSDN: "Discretionary Access Control List" wrote: | | (DACL) An access control list that is controlled by the owner of an object and that specifies the access particular users or groups can have to the object. |
| MSDN: "System Access Control List" wrote: | | (SACL) An ACL that controls the generation of audit messages for attempts to access a securable object. The ability to get or set an object's SACL is controlled by a privilege typically held only by system administrators. |
Okay, so besides expanding my vocabulary, whats the point of the GetSecurityInfo call? Why do I need a copy of the 'Security Descriptor'?
Thanks. _________________

Last edited by Conquer on Tue Feb 12, 2008 12:00 am; edited 1 time in total |
|
| Back to top |
|
 |
ahklerner
Joined: 26 Jun 2006 Posts: 1317 Location: USA
|
Posted: Mon Feb 11, 2008 11:57 pm Post subject: |
|
|
| Quote: | | A security descriptor identifies the object's owner and primary group |
_________________
ʞɔпɟ əɥʇ ʇɐɥʍ |
|
| Back to top |
|
 |
Conquer
Joined: 27 Jun 2006 Posts: 384 Location: Canada
|
Posted: Tue Feb 12, 2008 4:47 am Post subject: |
|
|
Alright, I'm still really new to DLL Calls.
What section of the 2nd parameter do I use?
These are the following "object" types:
| Code: | SE_UNKNOWN_OBJECT_TYPE
Unknown object type.
SE_FILE_OBJECT
Indicates a file or directory. The name string that identifies a file or directory object can be in one of the following formats:
* A relative path, such as FileName.dat or ..\FileName
* An absolute path, such as FileName.dat, C:\DirectoryName\FileName.dat, or G:\RemoteDirectoryName\FileName.dat.
* A UNC name, such as \\ComputerName\ShareName\FileName.dat.
* A local file system root, such as \\\\.\\C:. Security set on a file system root does not persist when the system is restarted.
SE_SERVICE
Indicates a Windows service. A service object can be a local service, such as ServiceName, or a remote service, such as \\ComputerName\ServiceName.
SE_PRINTER
Indicates a printer. A printer object can be a local printer, such as PrinterName, or a remote printer, such as \\ComputerName\PrinterName.
SE_REGISTRY_KEY
Indicates a registry key. A registry key object can be in the local registry, such as CLASSES_ROOT\SomePath or in a remote registry, such as \\ComputerName\CLASSES_ROOT\SomePath.
The names of registry keys must use the following literal strings to identify the predefined registry keys: "CLASSES_ROOT", "CURRENT_USER", "MACHINE", and "USERS".
SE_LMSHARE
Indicates a network share. A share object can be local, such as ShareName, or remote, such as \\ComputerName\ShareName.
SE_KERNEL_OBJECT
Indicates a local kernel object.
The GetSecurityInfo and SetSecurityInfo functions support all types of kernel objects. The GetNamedSecurityInfo and SetNamedSecurityInfo functions work only with the following kernel objects: semaphore, event, mutex, waitable timer, and file mapping.
SE_WINDOW_OBJECT
Indicates a window station or desktop object on the local computer. You cannot use GetNamedSecurityInfo and SetNamedSecurityInfo with these objects because the names of window stations or desktops are not unique.
SE_DS_OBJECT
Indicates a directory service object or a property set or property of a directory service object. The name string for a directory service object must be in X.500 form, for example:
CN=SomeObject,OU=ou2,OU=ou1,DC=DomainName,DC=CompanyName,DC=com,O=internet
SE_DS_OBJECT_ALL
Indicates a directory service object and all of its property sets and properties.
SE_PROVIDER_DEFINED_OBJECT
Indicates a provider-defined object.
SE_WMIGUID_OBJECT
Indicates a WMI object.
SE_REGISTRY_WOW64_32KEY
Indicates an object for a registry entry under WOW64. |
And I might be wrong, but do I use "OWNER_SECURITY_INFORMATION" for the 3rd parameter?
| MSDN: "OWNER_SECURITY_INFORMATION wrote: | | The owner identifier of the object is being referenced. |
http://msdn2.microsoft.com/en-us/library/aa379573
Thanks. _________________
 |
|
| Back to top |
|
 |
wOxxOm
Joined: 09 Feb 2006 Posts: 322
|
Posted: Tue Feb 12, 2008 2:20 pm Post subject: |
|
|
as always with api dllcalls just google for an example in any programming language you easily understand, for example visual basic then transcode the call and analysis into ahk |
|
| Back to top |
|
 |
Conquer
Joined: 27 Jun 2006 Posts: 384 Location: Canada
|
Posted: Wed Feb 13, 2008 3:31 am Post subject: |
|
|
Good suggestion, but I don't know any programming languages.  _________________
 |
|
| Back to top |
|
 |
wOxxOm
Joined: 09 Feb 2006 Posts: 322
|
Posted: Wed Feb 13, 2008 4:23 am Post subject: |
|
|
that was some fun, here it is:
| Code: | d = `n ; string separator
s := VarSetCapacity(a, 2 << 9) ; 1KiB for array
MySIDsize:=255, VarSetCapacity(MySID,MySIDsize,0)
sDomainSize:=255, VarSetCapacity(sDomain,sDomainSize,0)
if( !dllCall("advapi32\LookupAccountNameA" ,"uint",0,"str",A_UserName
,"uint",&MySID,"uint*",MySIDsize,"str",sDomain,"uint*",sDomainSize,"uint*",SIDtype))
msgbox Cannot obtain SID for "%A_UserName%"
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; for speed
; get array of processes and parse identifiers as DWORDs:
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4 {
id := NumGet(a, A_Index * 4)
; open process with: PROCESS_QUERY_INFORMATION (0x0400) | PROCESS_VM_READ (0x0010) | READ_CONTROL
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400 | 0x20000, "Int", false, "UInt", id)
bMyProcess=0
if(0=dllcall("advapi32\GetSecurityInfo","uint",h, "uint",6,"uint",1
,"uintP",ppSIDowner,"uint",0,"uint",0,"uint",0,"uintP",ppSecuDsc))
if ppSecuDsc
{ bMyProcess:=DllCall("advapi32\EqualSid","uint",&MySID,"uint",ppSIDowner)
dllCall("LocalFree","uint",ppSecuDsc)
}
if bMyProcess
{
s := VarSetCapacity(m, 2 << 9) ; for array of modules:
DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r)
s := VarSetCapacity(n, 32) ; for module base name:
e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s)
If n ; if image is not null add to list:
l = %l%%n%%d%
}
DllCall("CloseHandle", "UInt", h) ; close process handle to save memory
}
DllCall("FreeLibrary", "UInt", hModule) ; free memory
StringTrimLeft, l, l, InStr(l, d) ; remove first item (ASCII sig?)
Msgbox, %l% |
|
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 7185
|
Posted: Wed Feb 13, 2008 8:25 am Post subject: Re: Get a list of _user_ processes only |
|
|
| Conquer wrote: | | I'm using this script by Titan: |
That is outdated code
The correct version of Titan's code is this and has been included in AHK Doc under Process command.
@wOxxOm
That is fantastic code. Thanks.
However, with initial testing I find some process missing like taskmgr.exe, wscntfy.exe.
Has it got something to do with Debug Privilege ?
 |
|
| Back to top |
|
 |
wOxxOm
Joined: 09 Feb 2006 Posts: 322
|
Posted: Wed Feb 13, 2008 3:38 pm Post subject: |
|
|
yeah, dig MSDN, probably SE_DEBUG_PRIVILEGE or something else is needed somewhere  |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 7185
|
Posted: Wed Feb 13, 2008 5:16 pm Post subject: |
|
|
| wOxxOm wrote: | | yeah, dig MSDN |
No,.. er .. I had pointed out that you should have adapted from Titan's corrected code posted at:
http://www.autohotkey.com/forum/viewtopic.php?p=81564#81564
instead of the code posted by Conquer.
I just inserted/replaced some code with yours ( in Red ) and you have to tell me if it is right:
| Code: | d = `n ; string separator
s := 4096 ; size of buffers and arrays (4 KB)
Process, Exist ; sets ErrorLevel to the PID of this running script
; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel)
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "UInt", h, "UInt", 32, "UIntP", t)
VarSetCapacity(ti, 16, 0) ; structure of privileges
NumPut(1, ti, 0, 4) ; one entry in the privileges array...
; Retrieves the locally unique identifier of the debug privilege:
DllCall("Advapi32.dll\LookupPrivilegeValueA", "UInt", 0, "Str", "SeDebugPrivilege", "UIntP", luid)
NumPut(luid, ti, 4, 8)
NumPut(2, ti, 12, 4) ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
; Update the privileges of this process with the new access token:
DllCall("Advapi32.dll\AdjustTokenPrivileges", "UInt", t, "Int", false, "UInt", &ti, "UInt", 0, "UInt", 0, "UInt", 0)
DllCall("CloseHandle", "UInt", h) ; close this process handle to save memory
MySIDsize:=255, VarSetCapacity(MySID,MySIDsize,0)
sDomainSize:=255, VarSetCapacity(sDomain,sDomainSize,0)
if( !dllCall("advapi32\LookupAccountNameA" ,"uint",0,"str",A_UserName
,"uint",&MySID,"uint*",MySIDsize,"str",sDomain,"uint*",sDomainSize,"uint*",SIDtype))
msgbox Cannot obtain SID for "%A_UserName%"
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; increase performance by preloading the libaray
s := VarSetCapacity(a, s) ; an array that receives the list of process identifiers:
DllCall("Psapi.dll\EnumProcesses", "UInt", &a, "UInt", s, "UIntP", r)
Loop, % r // 4 ; parse array for identifiers as DWORDs (32 bits):
{
id := NumGet(a, A_Index * 4)
; open process with: PROCESS_QUERY_INFORMATION (0x0400) | PROCESS_VM_READ (0x0010) | READ_CONTROL
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400 | 0x20000, "Int", false, "UInt", id)
bMyProcess=0
if(0=dllcall("advapi32\GetSecurityInfo","uint",h, "uint",6,"uint",1
,"uintP",ppSIDowner,"uint",0,"uint",0,"uint",0,"uintP",ppSecuDsc))
if ppSecuDsc
{ bMyProcess:=DllCall("advapi32\EqualSid","uint",&MySID,"uint",ppSIDowner)
dllCall("LocalFree","uint",ppSecuDsc)
}
if bMyProcess
{
s := VarSetCapacity(m, 2 << 9) ; for array of modules:
DllCall("Psapi.dll\EnumProcessModules", "UInt", h, "UInt", &m, "UInt", s, "UIntP", r)
s := VarSetCapacity(n, 32) ; for module base name:
e := DllCall("Psapi.dll\GetModuleBaseNameA", "UInt", h, "UInt", m, "Str", n, "Chr", s)
If n ; if image is not null add to list:
l = %l%%n%%d%
}
DllCall("CloseHandle", "UInt", h) ; close process handle to save memory
}
DllCall("FreeLibrary", "UInt", hModule) ; unload the library to free memory
; Remove the first and last items in the list (possibly ASCII signitures)
StringMid, l, l, InStr(l, d) + 1, InStr(l, d, false, 0) - 2 - InStr(l, d)
StringReplace, l, l, %d%, %d%, UseErrorLevel ; gets the number of processes
;Sort, l, C ; uncomment this line to sort the list alphabetically
MsgBox, 0, %ErrorLevel% Processes, %l% |
 |
|
| Back to top |
|
 |
wOxxOm
Joined: 09 Feb 2006 Posts: 322
|
Posted: Wed Feb 13, 2008 5:22 pm Post subject: |
|
|
| great! |
|
| Back to top |
|
 |
Conquer
Joined: 27 Jun 2006 Posts: 384 Location: Canada
|
Posted: Thu Feb 14, 2008 12:53 am Post subject: |
|
|
Wow, thanks so much w0xx0m! And thanks SKAN! You're both heroes  _________________
 |
|
| Back to top |
|
 |
maraskan_user
Joined: 20 Jun 2008 Posts: 17
|
Posted: Fri Jun 20, 2008 12:56 pm Post subject: |
|
|
I was staring at this code for a while but got no wiser. Totally opaque to me. @_@ Could somebody explain how I'd have to change it to simply find out whether a single specified process has admin rights or not? Like, get the ahd_id of a process, check if it's admin or not and save the return value in a bool variable.
Greetings,
Gernot |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|