Jump to content

How to kill a mutex?


Recommended Posts

maybe I need to translate this in autoit

Private Sub CloseHandleEx(ByVal lPID As Long, ByVal lHandle As Long)
    Dim hProcess As Long
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, lPID)
    Call NtDuplicateObject(hProcess, lHandle, 0, ByVal 0, 0, 0, DUPLICATE_CLOSE_SOURCE)
    Call NtClose(hProcess)
End Sub

Post your attempt at converting this, and more will be willing to help.

If you don't know where to start, read up on "dllcall"...

go to msdn and search on those names to get more info... If you're qurious... (They can also tell you what dll to call...)

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

I do not even know if this code is correct plus I don't know where to get the parameters and what they are, that code is from this link

got the handle of a process by running it (in the below exambple), but I need at least to get the handles associated to that PID as long (i got the name as string)

#include <WinAPI.au3>

Dim $sProcess = @WindowsDir&"\system32\notepad.exe"
Dim $hProcess
Dim $tPI = DllStructCreate($tagPROCESS_INFORMATION), $pPI = DllStructGetPtr($tPI)
Dim $tSI = DllStructCreate($tagSTARTUPINFO), $pSI = DllStructGetPtr($tSI)
DllStructSetData($tSI, 'Size', DllStructGetSize($tSI))
Dim $iSuccess = _WinAPI_CreateProcess('', $sProcess, 0, 0, False, 0, 0, 0, $pSI, $pPI)
_WinAPI_CloseHandle(DllStructGetData($tPI, 'hThread'))
$hProcess = DllStructGetData($tPI, 'hProcess')
_WinAPI_WaitForInputIdle($hProcess)
MsgBox(0, "", $hProcess)
Edited by simon387
Link to comment
Share on other sites

here's a full attempt, I'm using the notepad process

#Include <WinAPI.au3>

Global Const $PROCESS_ALL_ACCESS = 0x000F0000 + 0x00100000
Global Const $DUPLICATE_CLOSE_SOURCE = 0x00000001
Global Const $MUTEX_ALL_ACCESS = 0x1F0001

$lPID = Run("notepad")
    ConsoleWrite("PID: " & @TAB & @TAB & @TAB & $lPID & @CR)
$MutexName = "MSCTF.Asm.MutexDefault1"
    ConsoleWrite("MUTEX exists: "& @TAB & @TAB & _MutexExists($MutexName) & @CR)

If _MutexExists($MUTEXname) == 1 Then

    $lhandle = _MutexOpen($MutexName)
        ConsoleWrite("MUTEX handle: " & @TAB & @TAB & $lhandle & @CR)
    $hprocess = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, $lPID , False)
        ConsoleWrite("Process handle: " & @TAB & $hprocess & @CR)

    $ret = DllCall("ntdll.dll", "long", "NtDuplicateObject", "long", $hprocess, "long", $lhandle, _
            "long", 0, "long", 0, "long", 0, "long", 0, "long", $DUPLICATE_CLOSE_SOURCE)
        ConsoleWrite("@error on DllCall #1: "& @TAB & @error & @CR)
        ;ConsoleWrite("Return on DllCall #1: "& @TAB & $ret & @CR)
    $ret = DllCall("ntdll.dll", "long", "NtClose", "long", $lhandle)
        ConsoleWrite("@error on DllCall #2: "& @TAB & @error & @CR)
        ;ConsoleWrite("Return on DllCall #2: "& @TAB & $ret & @CR)

        ConsoleWrite("MUTEX exists: "& @TAB & @TAB & _MutexExists($MUTEXname) & @CR)

    If _MutexExists($MUTEXname) == 1 Then
        ConsoleWrite("You have failed!" & @CR)
    Else
        ConsoleWrite("You have won!" & @CR)
    EndIf
Else
    ConsoleWrite("Mutex name not found, script terminated" & @CR)
EndIf

Sleep(500)
ProcessClose($lPID)

Func _MutexOpen($MutexName)
    Local $hMutex = DllCall("kernel32.dll", "hwnd", "OpenMutex", "int", $MUTEX_ALL_ACCESS, "int", 0, "str", $MutexName)
    If IsArray($hMutex) And $hMutex[0] Then Return $hMutex[0]
    Return 0
EndFunc

Func _MutexExists($MutexName)
    Local $hMutex = DllCall("Kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", 1, "str", $MutexName)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    If IsArray($hMutex) And $hMutex[0] Then DllCall("Kernel32.dll", "int", "CloseHandle", "hwnd", $hMutex[0])
    If IsArray($aGLE) And $aGLE[0] = 127 Then Return 1
    Return 0
EndFunc

#cs
Success:    @error = 0.
Failure:    set @error
@error: 1 unable to use the DLL file,
        2 unknown "return type",
        3 "function" not found in the DLL file,
        4 bad number of parameters.
#ce

I fail :|

Edited by simon387
Link to comment
Share on other sites

Please look at this code... It demonstrates a method for getting handles of remote processes. Much like in the link you mentioned.

You need to feed your "duplicate-function" the handle as seen by the remote process. :idea:

http://www.autoitscript.com/forum/index.php?showtopic=84939&st=20&p=703384&hl=DuplicateHandle&fromsearch=1&#entry703384

Study, chop up and edit... You will reach your goal. :)

/Manko

Edited by Manko
Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

thanks for the answer

omg it lists all the system's handles (until an AOB), I need only the one of a specific PID...

I'm sure the solution is there, but I just learned how to use dllcall()... gotta study a lot!

Link to comment
Share on other sites

(until an AOB)

What is that?

Anyway... You just need to filter what you need and rearrange a little... Make a second "duplicate"-call with "DUPLICATE_CLOSE_SOURCE" giving the correct handle this time. That wich has been listed as belonging to the intended process. And then when you close the duplicated handle it will also close the original....

Studying is good!

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

What is that?

Anyway... You just need to filter what you need and rearrange a little... Make a second "duplicate"-call with "DUPLICATE_CLOSE_SOURCE" giving the correct handle this time. That wich has been listed as belonging to the intended process. And then when you close the duplicated handle it will also close the original....

Studying is good!

/Manko

AOB = array out of bound

thx again for the infos!

Link to comment
Share on other sites

  • 3 weeks later...

I can not make it work

Post your code!

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

  • 1 year later...

Was there ever an update to this? I very much would like/need this ability.

Just to confirm that I did try to figure out whats going on:

Please note this will try to find the "SciTE-UniqueInstanceMutex-Default" mutex within SciTE.exe. If the mutex has been deleted successfully, when you go to edit another AU3 it will open a 2nd copy of SciTE, rather than reusing the same instance.

I think the error relies in how each call of _getMutexHandle($name) seems to output a different Handle address. I would think the use of OpenMutex was JUST to get the handle and not re-open a mutex... I am not sure what's going on but I do know that DuplicateHandle failed with GetLastError of 6...which a google seems to indicate a "INVALID HANDLE" error, however the handles of the PIDs are correct and getHandleType confrism the Mutex Handle is indeed a real mutant handle. So I am not sure which "handle" is "invalid".

#RequireAdmin
HotKeySet("{ESC}", "_Escape"); ESC to exit

#include <WinAPI.au3>
#include <array.au3>
Global Const $MUTEX_ALL_ACCESS = 0x1F0001
Global $hMutexGlobal
Global $name = "SciTE-UniqueInstanceMutex-Default"

Global $hGUI = GUICreate("Mutex Test", 400, 600)
Global $ctrlEdit = GUICtrlCreateEdit("Start...", 10, 10, 380, 580)
GUISetState()

    $hMutexGlobal = _getMutexHandle($name)
    _EditWrite("Mutex Exists: " & ($hMutexGlobal <> 0) & @CRLF)
    _EditWrite("Mutex Handle: " & $hMutexGlobal & " of type: " & getHandleType($hMutexGlobal) & @CRLF)

    _EditWrite("Mutex Handle: " & _getMutexHandle($name) & " of type: " & getHandleType($hMutexGlobal) & @CRLF)


    If _ReleaseMutex($hMutexGlobal) = 1 Then
        _EditWrite("Mutex Released!" & @CRLF & "Mutex Exists: " & (_MutexExists($hMutexGlobal) <> 0) & @CRLF & @CRLF)
    Else
        _EditWrite("Mutex Released: Failed with error code: " & @error & @CRLF)
        _EditWrite("Mutex Exists: " & (_MutexExists($hMutexGlobal) <> 0) & @CRLF & @CRLF)
    EndIf
    _EditWrite("Mutex Handle: " & _getMutexHandle($name) & " of type: " & getHandleType($hMutexGlobal) & @CRLF)
    While 1
    Sleep(1000)
WEnd

Func _MutexExists($hMutex)
        return (getHandleType($hMutex) == "Mutant")
EndFunc


Func getHandleType($hMutex)
    $tag_OBJECT_TYPE= _             ; TYPE / NAME Doesnt matter... I just want the unicodestring.
    "ushort Length;" & _
    "ushort MaximumLength;" & _
    "ptr    Name;" & _
    "byte[512]"

    Local $ObjType=DllStructCreate($tag_OBJECT_TYPE)
            dllcall("ntdll.dll", "int", "NtQueryObject", "hwnd", $hMutexGlobal, "int", 2, "ptr", dllstructgetptr($ObjType, 1), "int" ,DllStructGetSize($ObjType), "int*", 0)

    $buffer=DllStructCreate("wchar[256]", DllStructGetData($ObjType, "Name"))
    return DllStructGetData($buffer, 1)
EndFunc


Func _getMutexHandle($szMutexName)
    Dim $hMutex = DllCall("kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", False, "str", $szMutexName)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    If IsArray($aGLE) And $aGLE[0] = 127 Then Return $hMutex[0]
    Return 0
EndFunc  ;==>_MutexExists

Func _ReleaseMutex($hMutex)
    $test = _DuplicateHandle(ProcessExists("SciTE.exe"),$hMutex,@AutoItPID, true)
    if @error then Return SetError(@error, 0, 0)
    return 1
EndFunc  ;==>_ReleaseMutex

;===============================================================================
;
; Description:      Duplicates a Handle from or for another process
; Parameter(s):     $dwSourcePid - Pid from Source Process
;                   $hSourceHandle - The Handle to duplicate
;                   $dwTargetPid - Optional, Pid from Target Procces - Defaults to current process
;                   $fCloseSource - Optional, Close the source handle - Defaults to False
; Requirement(s):   3.2.4.9
; Return Value(s):  On Success - Duplicated Handle
;                   On Failure - 0 and sets error to
;                                               @error to:  1 - Api OpenProcess Failed
;                                                           2 - Api DuplicateHandle Falied
; Author(s):        Florian 'Piccaso' Fida
; Note(s):
;
;===============================================================================
Func _DuplicateHandle($dwSourcePid, $hSourceHandle, $dwTargetPid = @AutoItPID, $fCloseSource = False)
    Local $hTargetHandle, $hPrSource, $hPrTarget, $dwOptions
    $hPrSource = __dh_OpenProcess($dwSourcePid)
    $hPrTarget = __dh_OpenProcess($dwTargetPid)
    If $hPrSource = 0 Or $hPrTarget = 0 Then
        _CloseHandle($hPrSource)
        _CloseHandle($hPrTarget)
        Return SetError(1, 0, 0)
    EndIf
    ; DUPLICATE_CLOSE_SOURCE = 0x00000001
    ; DUPLICATE_SAME_ACCESS = 0x00000002
    If $fCloseSource <> False Then
        $dwOptions = 0x01 + 0x02
    Else
        $dwOptions = 0x02
    EndIf
    $hTargetHandle = DllCall("kernel32.dll", "int", "DuplicateHandle", "ptr", $hPrSource, "ptr", $hSourceHandle, "ptr", $hPrTarget, "long_ptr", 0, "dword", 0, "int", 1, "dword", $dwOptions)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    if $aGLE[0] > 0 then Return SetError($aGLE[0], 0, 0)

    If $hTargetHandle[0] = 0 Or $hTargetHandle[4] = 0 Then
        _CloseHandle($hPrSource)
        _CloseHandle($hPrTarget)
        Return SetError(2, 0, 0)
    EndIf
    Return $hTargetHandle[4]
EndFunc   ;==>_DuplicateHandle
Func __dh_OpenProcess($dwProcessId)
    ; PROCESS_DUP_HANDLE = 0x40
    Local $hPr = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", 0x40, "int", 0, "dword", $dwProcessId)
    If @error Then Return SetError(1, 0, 0)
    Return $hPr[0]
EndFunc   ;==>__dh_OpenProcess
Func _CloseHandle($hAny)
    If $hAny = 0 Then Return SetError(1, 0, 0)
    Local $fch = DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hAny)
    If @error Then Return SetError(1, 0, 0)
    Return $fch[0]
EndFunc   ;==>_CloseHandle


Func _EditWrite($sString)
    ControlSetText($hGUI, "", $ctrlEdit, ControlGetText($hGUI, "", $ctrlEdit) & $sString)
EndFunc  ;==>_EditWrite

Func _Escape()
    Sleep(5000)
    Exit
EndFunc  ;==>_Escape

Output:

Start...Mutex Exists: True

Mutex Handle: 0x000001A8 of type: Mutant

Mutex Handle: 0x000001A4 of type: Mutant

Mutex Released: Failed with error code: 6

Mutex Exists: True

Mutex Handle: 0x000001B4 of type: Mutant

Please note how the Handle seemingly changed from 0x000001A8 to 0x000001A4 and then 0x000001B4. Also these handles seem to be the same no matter which mutex/process I target...

Edited by ParoXsitiC
Link to comment
Share on other sites

  • 2 weeks later...

The clues are there... but use/edit my code. and when you have found the mutex:

Quoting me:

Anyway... You just need to filter what you need and rearrange a little... Make a second "duplicate"-call with "DUPLICATE_CLOSE_SOURCE" giving the correct handle this time. That wich has been listed as belonging to the intended process. And then when you close the duplicated handle it will also close the original....

You'll have to look up the "DUPLICATE_CLOSE_SOURCE"-value on the net.

Also sorry for the delay, I rarely visit here nowadays... This was the short answer if you need more help, I'll gladly look at code you post to see what went wrong...

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

The clues are there... but use/edit my code. and when you have found the mutex:

Quoting me:

Anyway... You just need to filter what you need and rearrange a little... Make a second "duplicate"-call with "DUPLICATE_CLOSE_SOURCE" giving the correct handle this time. That wich has been listed as belonging to the intended process. And then when you close the duplicated handle it will also close the original....

You'll have to look up the "DUPLICATE_CLOSE_SOURCE"-value on the net.

Also sorry for the delay, I rarely visit here nowadays... This was the short answer if you need more help, I'll gladly look at code you post to see what went wrong...

/Manko

I did originally use your code _DuplicateHandle routine I found seemed to be a bit more polished with error checking. It does use DUPLICATE_CLOSE_SOURCE when you give it a true last parameter. My only guess is that you mean to use "duplicate" to perhaps clone the handles to a new process and then close the source on that? I am pretty confused... I have also struggled with this same problem in c# with the same error messages.. http://stackoverflow.com/questions/6808831/delete-a-mutex-from-another-process

Link to comment
Share on other sites

I did originally use your code _DuplicateHandle routine I found seemed to be a bit more polished with error checking. It does use DUPLICATE_CLOSE_SOURCE when you give it a true last parameter. My only guess is that you mean to use "duplicate" to perhaps clone the handles to a new process and then close the source on that? I am pretty confused... I have also struggled with this same problem in c# with the same error messages.. http://stackoverflow.com/questions/6808831/delete-a-mutex-from-another-process

First problem: you open mutex locally... DuplicateHandle needs remote handle...

Second: you did not use correct bits of my code... (Hint:The specific instance of ZwQuerySystemInformation gives remote handles...)

Try again! :mellow:

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

First problem: you open mutex locally... DuplicateHandle needs remote handle...

Second: you did not use correct bits of my code... (Hint:The specific instance of ZwQuerySystemInformation gives remote handles...)

Try again! :mellow:

/Manko

Weird how I never found anything about the diff. from remote vs local handles in my search for solutions. Thanks though, I got it working with the following code:

#include <WinAPI.au3>
#include <array.au3>
Global Const $MUTEX_ALL_ACCESS = 0x1F0001
Global $hMutexRemote
Global $hMutexLocal
Global $MutexName = "SciTE-UniqueInstanceMutex-Default"
Global $PIDofMutex = ProcessExists("SciTE.exe")



$hMutexLocal = _getMutexLocalHandle($MutexName)
If ($hMutexLocal <> 0) Then
    $hMutexRemote = _getMutexRemoteHandle($MutexName, $PIDofMutex)
    ConsoleWrite("Mutex Handle: " & $hMutexRemote & " of type: " & _getHandleType($hMutexLocal) & @CRLF)

    If _ReleaseMutex($hMutexRemote, $PIDofMutex) = 1 Then
        ConsoleWrite("Mutex Released!" & @CRLF & "Mutex Exists: " & (_getMutexRemoteHandle($MutexName, $PIDofMutex) <> -1) & @CRLF & @CRLF)
    Else
        ConsoleWrite("Mutex Released: Failed with error code: " & @error & @CRLF)
        ConsoleWrite("Mutex Exists: " & (_getMutexLocalHandle($MutexName) <> 0) & @CRLF & @CRLF)
    EndIf
Else
    ConsoleWrite("The mutex " & $MutexName & " does not exist." & @CRLF)
EndIf


Func _getMutexRemoteHandle($sMutexName, $iPID=@AutoItPID)
    $a = _getHandles($iPID, "Mutant")
    $iIndex = _ArraySearch($a, "\Sessions\1\BaseNamedObjects\" & $MutexName, 0, 0, 0, 0, 1, 9)
    If @error == 6 Then Return SetError(1, 0, $iIndex)

    return $a[$iIndex][4]
EndFunc


Func _NtQueryObject($h, $i)
    $tag_OBJECT_TYPE= _             ; TYPE / NAME Doesnt matter... I just want the unicodestring.
    "ushort Length;" & _
    "ushort MaximumLength;" & _
    "ptr    Name;" & _
    "byte[512]"

    Local $ObjType=DllStructCreate($tag_OBJECT_TYPE)
    dllcall("ntdll.dll", "int", "NtQueryObject", "hwnd", $h, "int", $i, "ptr", dllstructgetptr($ObjType, 1), "int" ,DllStructGetSize($ObjType), "int*", 0)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    if $aGLE[0] > 0 then SetError($aGLE[0])

    $buffer=DllStructCreate("wchar[256]", DllStructGetData($ObjType, "Name"))
    return DllStructGetData($buffer, 1)
EndFunc

Func _getHandleType($hMutex)
    $Ret = _NtQueryObject($hMutex, 2)
    if @error then SetError(@error)
    If $Ret == 0 Then Return "Unknown?"
    Return $Ret
EndFunc

Func _getHandleName($hMutex)
    $Ret = _NtQueryObject($hMutex, 1)
    if @error then SetError(@error)

    If $Ret == 0 Then Return "No Name?"
    Return $Ret
EndFunc



Func _getHandles($iPID=Default, $sObjectType=Default, $sObjectName=Default)

    $tag_SYSTEM_HANDLE_INFO= _
        "USHORT UniqueProcessId;" & _;
        "USHORT CreatorBackTraceIndex;" & _;
        "ubyte ObjectTypeIndex;" & _;
        "ubyte HandleAttributes;" & _;
        "USHORT HandleValue;" & _;
        "ptr Object;" & _;
        "ptr GrantedAccess";

    Local $Mem=DllStructCreate("byte[" & 40000000 & "]")
    Local $ret=dllcall("ntdll.dll", "int", "ZwQuerySystemInformation","int", 16, "ptr", DllStructGetPtr($MEM), "int", DllStructGetSize($MEM), "int*",0)
    Local $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $ret[2]+4)
    Local $dw=DllStructCreate("dword",$ret[2])
    Local $Count=DllStructGetData($dw,1)
    Local $SysHnd_ptr=$ret[2]+4
    Local $SysHnd_Size=DllStructGetSize($SysHnd)
    Local $buffer, $i=0, $lastthread, $m=0, $NextEntryDelta, $k, $temp, $space, $l
    Local $avArray[1000000][10]
    const $DUPLICATE_SAME_ACCESS = 0x2
    Local $types[100]


    If ($iPID == Default) Then
        ProgressOn("Processing through PIDs", "Processing...", "0 / " & $Count & " PIDs")
        Local $ProgressSpacing = Int($Count / 100)
    EndIf
    While 1
        if $m=$count Then ExitLoop
        If ($iPID == Default and mod($m, $ProgressSpacing) == 0) Then ProgressSet(($m/$count) * 100, "Processing...", $m & " / " & $Count & " PIDs")

        $avArray[$i][0]=DllStructGetData($SysHnd, "UniqueProcessId")

        ; If its not a process in the process list, skip it --- Doesnt speed it up, infact slows it down because so many searches.
;~          Local $aProcessList = ProcessList()
;~      If _ArraySearch($aProcessList, $avArray[$i][0], 0,0,0,0,1,2) == -1 Then
;~          $m+=1
;~          $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
;~          Continueloop
;~      EndIf


        If $iPID <> Default Then
            If $avArray[$i][0] <> $iPID Then
                $m+=1
                $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
                Continueloop
            EndIf
        EndIf

        $avArray[$i][1]=DllStructGetData($SysHnd, "CreatorBackTraceIndex")
        if not $avArray[$i][1] Then $avArray[$i][1]=""
        $avArray[$i][2]=DllStructGetData($SysHnd, "ObjectTypeIndex")
        $avArray[$i][3]=DllStructGetData($SysHnd, "HandleAttributes")
        if not $avArray[$i][3] Then $avArray[$i][3]=""
        $avArray[$i][4]=ptr(DllStructGetData($SysHnd, "HandleValue"))
        $avArray[$i][5]=DllStructGetData($SysHnd, "Object")
        $avArray[$i][6]=DllStructGetData($SysHnd, "GrantedAccess")
        $hProcSource=_WinAPI_OpenProcess(0x1f0fff, 0, $avarray[$i][0])
        $hProcDest=_WinAPI_OpenProcess(0x1f0fff, 0, @AutoItPID)

        $ret=dllcall("kernel32.dll","int","DuplicateHandle","hwnd", $hProcSource, "hwnd", $avarray[$i][4], "hwnd", $hProcDest, "hwnd*", 0, "int",0, "int", 0, "int", $DUPLICATE_SAME_ACCESS)
        $avArray[$i][7]=$ret[4]
        $avArray[$i][7]=$ret[4]
        if $types[$avArray[$i][2]] == "" Then
            $avArray[$i][8]=_getHandleType($ret[4])
            $types[$avArray[$i][2]]=$avArray[$i][8]
        Else
            $avArray[$i][8]=$types[$avArray[$i][2]]
        EndIf



        ;Filter by ObjectType
        if $sObjectType <> Default and $avArray[$i][8] <> $sObjectType Then
             $m+=1
             $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
             Continueloop
         EndIf



        ; Try to filter out NAMED PIPES to not deadlock. Writing a driver to get names would be best. I'm researching...
        if $avArray[$i][2]=28 Then
            if $avArray[$i][6]=0x00120189 Then
                $avArray[$i][9]="    NAMED PIPES ??? - DANGER OF DEADLOCK - SKIPPED ..."
                $m+=1
                ;$i+=1
                $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
                Continueloop
            EndIf
            if $avArray[$i][6]=0x00100000 Then
                $avArray[$i][9]="    NAMED PIPES ??? - DANGER OF DEADLOCK - SKIPPED ..."
                $m+=1
                $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
                Continueloop
            EndIf
            if  $avArray[$i][6]=0x0012019F Then
                if $avArray[$i][3]<2 Then
                    $avArray[$i][9]="    NAMED PIPES ??? - DANGER OF DEADLOCK - SKIPPED ..."
                    $m+=1
                    $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
                    Continueloop
                EndIf
            EndIf
        EndIf

        Switch $avArray[$i][2]
            Case 5
                $ret1=dllcall("kernel32.dll", "int", "GetProcessId", "hwnd", $ret[4])
                $avArray[$i][9]=$ret1[0]
            Case Else
                if not $avArray[$i][9] Then
                    $avArray[$i][9]=_getHandleName($ret[4])
                    if not $avArray[$i][9] Then $avArray[$i][9]=""
                EndIf
        EndSwitch


         if $sObjectName <> Default and $avArray[$i][9] <> $sObjectName Then
             $m+=1
             $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
             Continueloop
         EndIf

        _WinAPI_CloseHandle($hProcSource)
        _WinAPI_CloseHandle($hProcDest)

        $i+=1
        $m+=1
        $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
        ContinueLoop
    WEnd

    If ($iPID == Default) Then
        ProgressSet(($m/$count) * 100)
        ProgressOff()
    EndIf

    If $i > 0 Then Redim $avArray[$i][10]
    Return $avArray
EndFunc

Func _getMutexLocalHandle($szMutexName)
    Dim $hMutex = DllCall("kernel32.dll", "hwnd", "OpenMutex", "int", 0x1F0001, "int", False, "str", $szMutexName)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    If IsArray($aGLE) And $aGLE[0] = 127 Then Return $hMutex[0]
    Return 0
EndFunc  ;==>_MutexExists

Func _ReleaseMutex($hMutex, $iPID=@AutoItPID)
    $test = _DuplicateHandle($iPID,$hMutex,@AutoItPID, true)
    if @error then Return SetError(@error, 0, 0)
    return 1
EndFunc  ;==>_ReleaseMutex

;===============================================================================
;
; Description:      Duplicates a Handle from or for another process
; Parameter(s):     $dwSourcePid - Pid from Source Process
;                   $hSourceHandle - The Handle to duplicate
;                   $dwTargetPid - Optional, Pid from Target Procces - Defaults to current process
;                   $fCloseSource - Optional, Close the source handle - Defaults to False
; Requirement(s):   3.2.4.9
; Return Value(s):  On Success - Duplicated Handle
;                   On Failure - 0 and sets error to
;                                               @error to:  1 - Api OpenProcess Failed
;                                                           2 - Api DuplicateHandle Falied
; Author(s):        Florian 'Piccaso' Fida
; Note(s):
;
;===============================================================================
Func _DuplicateHandle($dwSourcePid, $hSourceHandle, $dwTargetPid = @AutoItPID, $fCloseSource = False)
    Local $hTargetHandle, $hPrSource, $hPrTarget, $dwOptions
    $hPrSource = __dh_OpenProcess($dwSourcePid)
    $hPrTarget = __dh_OpenProcess($dwTargetPid)
    If $hPrSource = 0 Or $hPrTarget = 0 Then
        _CloseHandle($hPrSource)
        _CloseHandle($hPrTarget)
        Return SetError(1, 0, 0)
    EndIf
    ; DUPLICATE_CLOSE_SOURCE = 0x00000001
    ; DUPLICATE_SAME_ACCESS = 0x00000002
    If $fCloseSource <> False Then
        $dwOptions = 0x01 + 0x02
    Else
        $dwOptions = 0x02
    EndIf
    $hTargetHandle = DllCall("kernel32.dll", "int", "DuplicateHandle", "ptr", $hPrSource, "ptr", $hSourceHandle, "ptr", $hPrTarget, "long_ptr", 0, "dword", 0, "int", 1, "dword", $dwOptions)
    Local $aGLE = DllCall("Kernel32.dll", "int", "GetLastError")
    if $aGLE[0] > 0 then Return SetError($aGLE[0], 0, 0)

    Return $hTargetHandle[4]
EndFunc   ;==>_DuplicateHandle
Func __dh_OpenProcess($dwProcessId)
    ; PROCESS_DUP_HANDLE = 0x40
    Local $hPr = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", 0x40, "int", 0, "dword", $dwProcessId)
    If @error Then Return SetError(1, 0, 0)
    Return $hPr[0]
EndFunc   ;==>__dh_OpenProcess
Func _CloseHandle($hAny)
    If $hAny = 0 Then Return SetError(1, 0, 0)
    Local $fch = DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hAny)
    If @error Then Return SetError(1, 0, 0)
    Return $fch[0]
EndFunc   ;==>_CloseHandle


Func _Escape()
    Exit
EndFunc  ;==>_Escape

I use the local mutant address to check if it exists, because it's way faster than the remote way. The remote way goes through every PID, I am not sure if there is a way to filter a certain PID natively. Strangely the local mutant still exists when you duplicate the mutant with a CLOSE...but the remote mutant does not..however when you close your autoit.exe the local mutant address dies...probably not closing handles right maybe?

On a related note I tried to modify your function to Handles to "_getHandles" which was a function I was tyring to do the following with:

_getHandles(Default) -- get all objects of every PID

_getHandles(Default, "File") -- Get every file object from every PID

_getHandles(Default, "Mutant") -- Get every mutant from every PID

_getHandles(ProcessExists("Calc.exe"), "Mutant") -- Get mutant for process calc.exe

_getHandles(ProcessExists("SciTE.exe"), "Mutant", "\Sessions\1\BaseNamedObjects\SciTE-UniqueInstanceMutex-Default") -- Get info on the specific mutex from Scite.exe

Only the _getHandles(ProcessExists("Calc.exe"), "Mutant") works, something about NtQuery messes up for all the other, i assume not closing handles or something. I am not sure.

Edited by ParoXsitiC
Link to comment
Share on other sites

Great that you got it working! Keep it up!

Messes up? Is it the deadlocked process thing? Filtering works for me... (Didn't try your code...) It might be that you have found other instances of named pipes?

Describe mess up...

/Manko

Edited by Manko
Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

Great that you got it working! Keep it up!

Messes up? Is it the deadlocked process thing? Filtering works for me... (Didn't try your code...) It might be that you have found other instances of named pipes?

Describe mess up...

/Manko

Off the bat my function isn't working right. It wont detect any Object names at all. That is..

_getHandles(ProcessExists("SciTE.exe"), "Mutant", "\Sessions\1\BaseNamedObjects\SciTE-UniqueInstanceMutex-Default")

For all purposes and logic (assuming no errors on my half) should find a match, but it continues at this point:

if $sObjectName <> Default and $avArray[$i][9] <> $sObjectName Then
             $m+=1
             $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
             Continueloop
         EndIf

And it shouldn't.

This reasoning eludes me at the moment, I forgot since yesterday.. lol. However another issue I found, which could be related...

Well for one, half of the calls to NtQueryObject normally have a GetLastError of 50 (which google that error yields not much info). And in some/alot cases the return value is 0 for the typename (instead of Directory, File, Mutex). I know different type object numbers vary on versions of windows, which is why you need the NtQueryObject call to determine its true type. On my system when getting the objects of SciTE the objects with objecttypenumber 39 kept giving me an objecttypename of 0. Which then messed up my if statement of If ObjectTypeName == "Mutex"...it would return true, despite ObjectTypeName supposively being a zero.. I dont know why that would return true... So I just set the a check where it If $Ret == 0 Then Return "Unknown?" and for the Objectname .. If $Ret == 0 Then Return "No Name?"...

This works fine for SciTE but other processes such as osk.exe (Windows Onscreen Keyboard) it will not even detect any ObjectTypeNames...everything is returned Unknown or No name. I assumed maybe it was privledges because I took RequireAdmin out...as i didnt need it, but adding that seems to make things even more difficult as it seems osk.exe closes when you goto admin mode and then reopens... strangely.

Edited by ParoXsitiC
Link to comment
Share on other sites

For those interested, I have the problem in C# as well at stackoverflow.com - it suffers from the same issues.

http://stackoverflow.com/questions/6808831/delete-a-mutex-from-another-process However, if a googler happen to come across this, info may be useful.

Link to comment
Share on other sites

Off the bat my function isn't working right. It wont detect any Object names at all. That is..

_getHandles(ProcessExists("SciTE.exe"), "Mutant", "\Sessions\1\BaseNamedObjects\SciTE-UniqueInstanceMutex-Default")

For all purposes and logic (assuming no errors on my half) should find a match, but it continues at this point:

if $sObjectName <> Default and $avArray[$i][9] <> $sObjectName Then
             $m+=1
             $SysHnd=DllStructCreate($tag_SYSTEM_HANDLE_INFO, $SysHnd_ptr+$SysHnd_Size*$m)
             Continueloop
         EndIf

And it shouldn't.

This reasoning eludes me at the moment, I forgot since yesterday.. lol. However another issue I found, which could be related...

Well for one, half of the calls to NtQueryObject normally have a GetLastError of 50 (which google that error yields not much info). And in some/alot cases the return value is 0 for the typename (instead of Directory, File, Mutex). I know different type object numbers vary on versions of windows, which is why you need the NtQueryObject call to determine its true type. On my system when getting the objects of SciTE the objects with objecttypenumber 39 kept giving me an objecttypename of 0. Which then messed up my if statement of If ObjectTypeName == "Mutex"...it would return true, despite ObjectTypeName supposively being a zero.. I dont know why that would return true... So I just set the a check where it If $Ret == 0 Then Return "Unknown?" and for the Objectname .. If $Ret == 0 Then Return "No Name?"...

This works fine for SciTE but other processes such as osk.exe (Windows Onscreen Keyboard) it will not even detect any ObjectTypeNames...everything is returned Unknown or No name. I assumed maybe it was privledges because I took RequireAdmin out...as i didnt need it, but adding that seems to make things even more difficult as it seems osk.exe closes when you goto admin mode and then reopens... strangely.

I dunno about the logic... If you haven't got a valid typename... ? ...else, dunno what's wrong.

Yes not every query will be answered, sadly. That is why I populate an index of typenames, helped by the typeindex in the array from "ntgetsysteminfo..." , also, for speed...

About osk.exe and other security oriented apps... You should really be surprised if it WAS easy to get info from it... Finally MS added "secure" processes... I'm guessing that is one. :mellow:

/Manko

Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually...
Link to comment
Share on other sites

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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...