Jump to content

Recommended Posts

Posted
  On 12/12/2024 at 12:40 PM, Jos said:

This is a change to the func to close all $hToken handles properly:

Expand  
#RequireAdmin
#include <WinAPIProc.au3>
ConsoleWrite("ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
Local $aProcessList = ProcessList()
For $i = 1 To $aProcessList[0][0]
    _WinAPI_IsElevated_pid($aProcessList[$i][1])
;~     ConsoleWrite($aProcessList[$i][0] & ' = ' & _WinAPI_IsElevated_pid($aProcessList[$i][1]) & '   >Error code: ' & @error & @CRLF) ;### Debug Console
Next
ConsoleWrite("ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
For $i = 1 To $aProcessList[0][0]
    _WinAPI_IsElevated_pid($aProcessList[$i][1])
;~     ConsoleWrite($aProcessList[$i][0] & ' = ' & _WinAPI_IsElevated_pid($aProcessList[$i][1]) & '   >Error code: ' & @error & @CRLF) ;### Debug Console
Next
ConsoleWrite("ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)

.....

...that is my "golden test". Been looking around and this one goes about the token differently, I think.

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Ok that all made me curious.  I tested my own version of it :

#RequireAdmin ; needed to access services

; elevated - another process

#include <WinAPIProc.au3>
#include <ProcessConstants.au3>
#include <Constants.au3>
#include <Array.au3>

Example()

Func Example()
  ConsoleWrite("Start : " & _WinAPI_GetProcessHandleCount() & @CRLF)

  Local $aList = ProcessList(), $t1, $t2, $iCount = _WinAPI_GetProcessHandleCount()
  For $i = 3 To $aList[0][0]
    $t1 = IsProcessElevated($aList[$i][1])
    If @error Then ConsoleWrite("error c " & $aList[$i][0] & "/" & @error & @CRLF)
    If $iCount <> _WinAPI_GetProcessHandleCount() Then
      $iCount = _WinAPI_GetProcessHandleCount()
      ConsoleWrite($iCount & "/" & $aList[$i][0] & "/" & $aList[$i][1] & @CRLF)
    EndIf
  Next
  ConsoleWrite("End : " & _WinAPI_GetProcessHandleCount() & @CRLF)
EndFunc   ;==>Example

Func IsProcessElevated($iPID)
  Local $aRet, $iError = 0
  Local $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, False, $iPID, True)
  If Not $hProcess Then Return SetError(1, 0, False)
  Local $hToken = _WinAPI_OpenProcessToken($TOKEN_QUERY, $hProcess)
  If Not $hToken Then
    $iError = 2
  Else
    $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken, 'uint', 20, 'uint*', 0, 'dword', 4, 'dword*', 0)         ; TOKEN_ELEVATION
    If @error Or Not $aRet[0] Then $iError = 3
  EndIf
  _WinAPI_CloseHandle($hToken)
  _WinAPI_CloseHandle($hProcess)
  If $iError Then Return SetError($iError, 0, False)
  Return $aRet[3] = 1
EndFunc   ;==>IsProcessElevated

And in my case, only a single process creates a one shot 7 handles.  After digging, it has to do with one API LookupPrivilegeValueW that does it.  Nothing I can do about it, that seems to be a Windows "issue".

 

Posted (edited)

I think I've got it

#RequireAdmin
#include <WinAPIProc.au3>
ConsoleWrite("ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
Local $aProcessList = ProcessList()

For $n = 1 To 5
    For $i = 1 To $aProcessList[0][0]
        _WinAPI_IsElevated_pid($aProcessList[$i][1])
;~      ConsoleWrite($aProcessList[$i][1] & ' / ' & $aProcessList[$i][0] & ' = ' & _WinAPI_IsElevated_pid($aProcessList[$i][1]) & '   >Error code: ' & @error & @CRLF) ;### Debug Console
    Next
    ConsoleWrite("> ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
Next

Func _WinAPI_IsElevated_pid($iPID = 0)
    Local $hProcess, $hToken2, $aAdjust, $hToken, $iElev, $aRet, $iError = 0
    ; Enable "SeDebugPrivilege" privilege for obtain full access rights to another processes
;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    Local $hToken1 = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
    _WinAPI_AdjustTokenPrivileges($hToken1, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    _WinAPI_CloseHandle($hToken1)
;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    If $iPID <> 0 Then
        $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', ((_WinAPI_GetVersion() < 6.0) ? 0x00000400 : 0x00001000), _
                'bool', 0, 'dword', $iPID)
        If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, 0)
;~      ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
        $hToken2 = _WinAPI_OpenProcessToken(0x0008, $hProcess[0])
;~      ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    Else
        $hToken2 = _WinAPI_OpenProcessToken(0x0008)
    EndIf
    If Not $hToken2 Then
        _WinAPI_CloseHandle($hToken1)
        Return SetError(@error + 10, @extended, False)
    EndIf

;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    Do
        $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken2, 'uint', 20, 'uint*', 0, 'dword', 4, _
                'dword*', 0) ; TOKEN_ELEVATION
        If @error Or Not $aRet[0] Then
            $iError = @error + 10
            ExitLoop
        EndIf
;~      ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
        $iElev = $aRet[3]
        $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken2, 'uint', 18, 'uint*', 0, 'dword', 4, _
                'dword*', 0) ; TOKEN_ELEVATION_TYPE
        If @error Or Not $aRet[0] Then
            $iError = @error + 20
            ExitLoop
        EndIf
    Until 1
;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    _WinAPI_CloseHandle($hToken1)
    _WinAPI_CloseHandle($hToken2)
;~  If $hProcess Then _WinAPI_CloseHandle($hProcess)
;~  ConsoleWrite("@@ (" & @ScriptLineNumber & ") : ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    If $iError Then Return SetError($iError, 0, False)
    Return SetExtended($aRet[0] - 1, $iElev)
EndFunc   ;==>_WinAPI_IsElevated_pid

..and don't ask me why _WinAPI_CloseHandle($hToken1) twice 🤔

..am still wasting 1 on each loop. Anyone knows why ?

Fixed :) 

.. I kept editing :lol:

Edited by argumentum
better

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted (edited)

ok, I've cleaned it up, ready for copy'n'paste ( unless a better version is presented )

#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#RequireAdmin
#include <WinAPIProc.au3>

ConsoleWrite("+++ ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
Test()
ConsoleWrite("+++ ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
Func Test()
    Local $aProcessList = ProcessList()
    For $n = 1 To 5
        For $i = 1 To $aProcessList[0][0]
            _WinAPI_IsElevated_pid($aProcessList[$i][1])
;~          ConsoleWrite($aProcessList[$i][1] & ' / ' & $aProcessList[$i][0] & ' = ' & _WinAPI_IsElevated_pid($aProcessList[$i][1]) & '   >Error code: ' & @error & @CRLF) ;### Debug Console
        Next
        ConsoleWrite("> ProcessHandleCount: " & _WinAPI_GetProcessHandleCount() & @CRLF)
    Next
EndFunc   ;==>Test

Func _WinAPI_IsElevated_pid($iPID = 0) ; https://www.autoitscript.com/forum/topic/203065-check-if-any-process-run-as-administrator/?do=findComment&comment=1539373
    Local Static $dwDesiredAccess = ((_WinAPI_GetVersion() < 6.0) ? 0x00000400 : 0x00001000) ; https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
    Local $hProcess, $hToken2, $aAdjust, $hToken1, $iElev, $aRet, $iError = 0
    ; Enable "SeDebugPrivilege" privilege for obtain full access rights to another processes
    $hToken1 = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY))
    _WinAPI_AdjustTokenPrivileges($hToken1, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
    _WinAPI_CloseHandle($hToken1)
    If $iPID <> 0 Then
        $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', $dwDesiredAccess, _
                'bool', 0, 'dword', $iPID)
        If @error Or Not $hProcess[0] Then Return SetError(@error + 10, @extended, 0)
        $hToken2 = _WinAPI_OpenProcessToken(0x0008, $hProcess[0])
    Else
        $hToken2 = _WinAPI_OpenProcessToken(0x0008)
    EndIf
    If Not $hToken2 Then
        _WinAPI_CloseHandle($hToken1)
        Return SetError(@error + 20, @extended, False)
    EndIf

    Do
        $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken2, 'uint', 20, 'uint*', 0, 'dword', 4, _
                'dword*', 0) ; TOKEN_ELEVATION
        If @error Or Not $aRet[0] Then
            $iError = @error + 30
            ExitLoop
        EndIf
        $iElev = $aRet[3]
        $aRet = DllCall('advapi32.dll', 'bool', 'GetTokenInformation', 'handle', $hToken2, 'uint', 18, 'uint*', 0, 'dword', 4, _
                'dword*', 0) ; TOKEN_ELEVATION_TYPE
        If @error Or Not $aRet[0] Then
            $iError = @error + 40
            ExitLoop
        EndIf
    Until 1
    _WinAPI_CloseHandle($hToken1)
    _WinAPI_CloseHandle($hToken2)
    If $iError Then Return SetError($iError, 0, False)
    Return SetExtended($aRet[0] - 1, $iElev)
EndFunc   ;==>_WinAPI_IsElevated_pid

... and the @error codes are basically 10, 20, 30, 40. I don't feel it deserves greater finesse.

Edit: made dwDesiredAccess static, as I do run this constantly ( reason that I found the handle leak )

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

@Nine After remove the $bDebugPriv from
Local $hProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, False, $iPID, True)

I have no leak.
I've come out with a Handle Count equal to the ones I entered

Thank you very much  :)

I know that I know nothing

Posted (edited)

@argumentum with your function I have a small leak (in windows10)  with 7 handles,

as the @Nine mentioned above  'One process generate 7 handles from nowhere'

However, after commented the line
; _WinAPI_AdjustTokenPrivileges($hToken1, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust)
which does not seem to affect the result, :(

the leak is disappeared

Thank you very much  :)

Edit:
This is also invalid :(
after further testing it seems to affect some applications and it shows them incorrectly and some not at all

 

Edited by ioa747

I know that I know nothing

Posted

@ioa747 I know, but then there are @error in the detection of elevation.  It must be set at True to catch correctly all processes (see below).

  Reveal hidden contents

 

Posted (edited)

I noticed this too, (less often)

  Reveal hidden contents

and I checked what it was about

  Reveal hidden contents

and I thought that since they are elements of the Windows 10 system, they can be bypassed,
by searching for the rights that some application has (obviously wrong) :(

Edited by ioa747

I know that I know nothing

Posted (edited)

I saw in my PC that the border coloring script had the handle count increased to over 30,000 and I realized that I was f:censored: !.
The resource behavior now is decent.
 

  Reveal hidden contents

Myself, am not a programmer. I mix and match until it works, or looks like working. Am close to a living, breathing: LLM/ChatGPT with less memory :lol:

If this gets perfected by those that actually know what they are doing, I'll copy'n'paste that. But for now this is what we've got 🤷‍♂️

PS: Added _ArrayTranspose() to "Memory leak script". Next time I share the resource usage it will look better than this. Next time around :)

Edited by argumentum

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...