4

PROBLEM

I've hooked the TerminateProcess calls to identify the process which is being terminated, but I'm getting an unexpected handle from TerminateProcess that does not match with the real process handle that I try to intercept.

I'm using Deviare library but I think this issue could be solved just knowing how the TerminateProcess function works and what I need to do to perform a proper handle comparison.

QUESTION:

If I know the handle of a process which I want to identify its termination, how I could identify that handle from hProcess param of TerminateProcess function?

CODE:

Note the part where I try to compare the handles:

If Process.GetProcessesByName("notepad").FirstOrDefault.Handle = hProcessValue Then ...

It will never be the same handles (I also tried with MainWindowHandle and the Process ID ID)

So, the value of hProcess parameter is very unknown for me.

Imports Nektra.Deviare2

Public NotInheritable Class Form1

Public WithEvents SpyMgr As NktSpyMgr
Public Hook As NktHook

ReadOnly libName As String = "kernel32.dll"
ReadOnly funcName As String = "TerminateProcess"
ReadOnly hookFlags As eNktHookFlags = eNktHookFlags.flgOnlyPreCall

' Processes to attach the hook.
ReadOnly processesToAttach As IEnumerable(Of Process) =
    Process.GetProcessesByName("taskmgr")

Private Sub Test() Handles MyBase.Load

    If Me.processesToAttach.Count = 0 Then
        MsgBox("Any process found.")

    Else
        Me.SpyMgr = New NktSpyMgr()
        Me.SpyMgr.Initialize()

        Me.Hook = SpyMgr.CreateHook(String.Format("{0}!{1}", libName, funcName), hookFlags)
        Me.Hook.Hook(sync:=True)

        For Each proc As Process In processesToAttach
            Debug.WriteLine("Attaching to: " & proc.ProcessName)
            Me.Hook.Attach(procOrId:=proc.Id, sync:=True)
        Next proc

    End If

End Sub

<MTAThread>
Private Sub OnTerminateProcess_Called(ByVal hook As NktHook,
                                      ByVal proc As NktProcess,
                                      ByVal callInfo As NktHookCallInfo) Handles SpyMgr.OnFunctionCalled

    ' Function params.
    Dim hProcessParam As NktParam = DirectCast(callInfo.Params(0), NktParam)
    Dim uExitCodeParam As NktParam = DirectCast(callInfo.Params(1), NktParam)

    ' Param values.
    Dim hProcessValue As IntPtr = New IntPtr(CInt(hProcessParam.Value))
    Dim uExitCodeValue As UInteger = CUInt(uExitCodeParam.Value)

    ' Debuf info.
    Trace.WriteLine(String.Format("hProcess : '{0}'", hProcessValue))
    Trace.WriteLine(String.Format("uExitCode: '{0}'", uExitCodeValue))

    ' Handle Comparison
    If Process.GetProcessesByName("notepad").FirstOrDefault.Handle = hProcessValue Then

        ' Skip precall to avoid process termination.
        If callInfo.IsPreCall Then
            callInfo.Result.Value = 1
            callInfo.SkipCall()
        End If

    End If

End Sub

End Class

RESEARCH:

I've been reading the MSDN doc of TerminateProcess.

Note the parts where it says:

The handle must have the PROCESS_TERMINATE access right

I'm not sure whether I'm missed something to compare the handles.

Also I've been reading here but I didn't take any in clear:

Hooking TerminateProcess & Getting Info From The Handle It Supplies

I also designed this Enum if it could be necessary to perform a good handle comparison:

    Public Enum ProcessAccessFlags As UInteger
       All = &H1F0FFF
       Terminate = &H1
       CreateThread = &H2
       VirtualMemoryOperation = &H8
       VirtualMemoryRead = &H10
       VirtualMemoryWrite = &H20
       DuplicateHandle = &H40
       CreateProcess = &H80
       SetQuota = &H100
       SetInformation = &H200
       QueryInformation = &H400
       QueryLimitedInformation = &H1000
       Synchronize = &H100000
   End Enum
Community
  • 1
  • 1
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • Why don't you try to get the process id from the handle and then check? Idk about comparing process handles since you can't share them. – SomeNickName Apr 08 '15 at 19:20
  • @SomeNickName thanks for comment, but I've tried to retrieve the PID from the handle of `hProcess` paratemer of `TerminateProcess` using `GetWindowThreadProcessId` function and I always get a **Zero** (null) PID. I really think the handle contained in `hProcess` needs an special kind of treatment that we are missing. – ElektroStudios Apr 08 '15 at 19:34
  • Same thing commented above happens when P/Invoking `GetProcessId`, it returns always **Zero** . – ElektroStudios Apr 08 '15 at 19:40
  • 2
    Then the handle is invalid, i'm sorry idk much about hooking and never used that library, hopefully someone will help you ;) – SomeNickName Apr 08 '15 at 19:42
  • What does GetLastError return in case GetProcessId returned 0? Maybe the handle does not have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right? In that case you might try to `DuplicateHandle`. – Werner Henze Apr 16 '15 at 14:30

1 Answers1

2

Your code is assuming that there is only one handle per process. This is not right. There is one process ID per process. But every time someone requests a handle for a process, for example with OpenProcess(..., ..., procid) he gets a new process handle (which also depends on the desired access).

So you cannot compare the handles, you should check the module name or the process id.

Werner Henze
  • 16,404
  • 12
  • 44
  • 69
  • Thanks, I understood, but please see the comment I wrote below my question, the handle seems not to be pointing on any PID (I get a Zero). – ElektroStudios Apr 16 '15 at 14:20
  • 1
    @ElektroStudios That's because it's not *your* handle, it's the other process' handle. Handles are personal and can not just be shared. It's like if I say "1 meter to my left", then that refers to something different than when you say "1 meter to my left'. You'd need to know where I am and the direction I am facing. The same thing holds true for handles; if my process has a handle 5 then that only has meaning within my process. – MicroVirus Apr 17 '15 at 16:11