Attribute VB_Name = "ModLzOpenProcess"
Option Explicit
'
'炉子的LzOpenProcess,不用多说了吧
'
'由 嗷嗷叫的老马 摘于网络
'http://www.m5home.com/
'
Public Declare Function ZwQueryInformationProcess _
        Lib "NTDLL.DLL" (ByVal ProcessHandle As Long, _
        ByVal ProcessInformationClass As PROCESSINFOCLASS, _
        ByVal ProcessInformation As Long, _
        ByVal ProcessInformationLength As Long, _
        ByRef ReturnLength As Long) As Long

Public Enum PROCESSINFOCLASS
    ProcessBasicInformation
    ProcessQuotaLimits
    ProcessIoCounters
    ProcessVmCounters
    ProcessTimes
    ProcessBasePriority
    ProcessRaisePriority
    ProcessDebugPort
    ProcessExceptionPort
    ProcessAccessToken
    ProcessLdtInformation
    ProcessLdtSize
    ProcessDefaultHardErrorMode
    ProcessIoPortHandlers    '// Note: this is kernel mode only
    ProcessPooledUsageAndLimits
    ProcessWorkingSetWatch
    ProcessUserModeIOPL
    ProcessEnableAlignmentFaultFixup
    ProcessPriorityClass
    ProcessWx86Information
    ProcessHandleCount
    ProcessAffinityMask
    ProcessPriorityBoost
    ProcessDeviceMap
    ProcessSessionInformation
    ProcessForegroundInformation
    ProcessWow64Information
    ProcessImageFileName
    ProcessLUIDDeviceMapsEnabled
    ProcessBreakOnTermination
    ProcessDebugObjectHandle
    ProcessDebugFlags
    ProcessHandleTracing
    ProcessIoPriority
    ProcessExecuteFlags
    ProcessResourceManagement
    ProcessCookie
    ProcessImageInformation
    MaxProcessInfoClass    '// MaxProcessInfoClass should always be the last enum
End Enum

Public Type PROCESS_BASIC_INFORMATION
    ExitStatus As Long    'NTSTATUS
    PebBaseAddress As Long    'PPEB
    AffinityMask As Long    'ULONG_PTR
    BasePriority As Long    'KPRIORITY
    UniqueProcessId As Long    'ULONG_PTR
    InheritedFromUniqueProcessId As Long    'ULONG_PTR
End Type

Public Declare Function ZwQuerySystemInformation _
        Lib "NTDLL.DLL" (ByVal SystemInformationClass As SYSTEM_INFORMATION_CLASS, _
        ByVal pSystemInformation As Long, _
        ByVal SystemInformationLength As Long, _
        ByRef ReturnLength As Long) As Long

Public Enum SYSTEM_INFORMATION_CLASS
    SystemBasicInformation
    SystemProcessorInformation    '// obsolete...delete
    SystemPerformanceInformation
    SystemTimeOfDayInformation
    SystemPathInformation
    SystemProcessInformation
    SystemCallCountInformation
    SystemDeviceInformation
    SystemProcessorPerformanceInformation
    SystemFlagsInformation
    SystemCallTimeInformation
    SystemModuleInformation
    SystemLocksInformation
    SystemStackTraceInformation
    SystemPagedPoolInformation
    SystemNonPagedPoolInformation
    SystemHandleInformation
    SystemObjectInformation
    SystemPageFileInformation
    SystemVdmInstemulInformation
    SystemVdmBopInformation
    SystemFileCacheInformation
    SystemPoolTagInformation
    SystemInterruptInformation
    SystemDpcBehaviorInformation
    SystemFullMemoryInformation
    SystemLoadGdiDriverInformation
    SystemUnloadGdiDriverInformation
    SystemTimeAdjustmentInformation
    SystemSummaryMemoryInformation
    SystemMirrorMemoryInformation
    SystemPerformanceTraceInformation
    SystemObsolete0
    SystemExceptionInformation
    SystemCrashDumpStateInformation
    SystemKernelDebuggerInformation
    SystemContextSwitchInformation
    SystemRegistryQuotaInformation
    SystemExtendServiceTableInformation
    SystemPrioritySeperation
    SystemVerifierAddDriverInformation
    SystemVerifierRemoveDriverInformation
    SystemProcessorIdleInformation
    SystemLegacyDriverInformation
    SystemCurrentTimeZoneInformation
    SystemLookasideInformation
    SystemTimeSlipNotification
    SystemSessionCreate
    SystemSessionDetach
    SystemSessionInformation
    SystemRangeStartInformation
    SystemVerifierInformation
    SystemVerifierThunkExtend
    SystemSessionProcessInformation
    SystemLoadGdiDriverInSystemSpace
    SystemNumaProcessorMap
    SystemPrefetcherInformation
    SystemExtendedProcessInformation
    SystemRecommendedSharedDataAlignment
    SystemComPlusPackage
    SystemNumaAvailableMemory
    SystemProcessorPowerInformation
    SystemEmulationBasicInformation
    SystemEmulationProcessorInformation
    SystemExtendedHandleInformation
    SystemLostDelayedWriteInformation
    SystemBigPoolInformation
    SystemSessionPoolTagInformation
    SystemSessionMappedViewInformation
    SystemHotpatchInformation
    SystemObjectSecurityMode
    SystemWatchdogTimerHandler
    SystemWatchdogTimerInformation
    SystemLogicalProcessorInformation
    SystemWow64SharedInformation
    SystemRegisterFirmwareTableInformationHandler
    SystemFirmwareTableInformation
    SystemModuleInformationEx
    SystemVerifierTriageInformation
    SystemSuperfetchInformation
    SystemMemoryListInformation
    SystemFileCacheInformationEx
    MaxSystemInfoClass    '// MaxSystemInfoClass should always be the last enum
End Enum

Public Type SYSTEM_HANDLE_TABLE_ENTRY_INFO
    UniqueProcessId As Integer
    CreatorBackTraceIndex As Integer
    ObjectTypeIndex As Byte
    HandleAttributes As Byte
    HandleValue As Integer
    pObject As Long
    GrantedAccess As Long
End Type

Public Const STATUS_INFO_LENGTH_MISMATCH = &HC0000004

Public Enum SYSTEM_HANDLE_TYPE
    OB_TYPE_UNKNOWN = 0
    OB_TYPE_TYPE = 1
    OB_TYPE_DIRECTORY
    OB_TYPE_SYMBOLIC_LINK
    OB_TYPE_TOKEN
    OB_TYPE_PROCESS
    OB_TYPE_THREAD
    OB_TYPE_UNKNOWN_7
    OB_TYPE_EVENT
    OB_TYPE_EVENT_PAIR
    OB_TYPE_MUTANT
    OB_TYPE_UNKNOWN_11
    OB_TYPE_SEMAPHORE
    OB_TYPE_TIMER
    OB_TYPE_PROFILE
    OB_TYPE_WINDOW_STATION
    OB_TYPE_DESKTOP
    OB_TYPE_SECTION
    OB_TYPE_KEY
    OB_TYPE_PORT
    OB_TYPE_WAITABLE_PORT
    OB_TYPE_UNKNOWN_21
    OB_TYPE_UNKNOWN_22
    OB_TYPE_UNKNOWN_23
    OB_TYPE_UNKNOWN_24
    OB_TYPE_IO_COMPLETION
    OB_TYPE_FILE
End Enum

Public Declare Function ZwDuplicateObject _
        Lib "NTDLL.DLL" (ByVal SourceProcessHandle As Long, _
        ByVal SourceHandle As Long, _
        ByVal TargetProcessHandle As Long, _
        ByRef TargetHandle As Long, _
        ByVal DesiredAccess As Long, _
        ByVal HandleAttributes As Long, _
        ByVal Options As Long) As Long

Public Const DUPLICATE_CLOSE_SOURCE = &H1    '// winnt

Public Const DUPLICATE_SAME_ACCESS = &H2    '// winnt

Public Const DUPLICATE_SAME_ATTRIBUTES = &H4

Public Declare Function ZwOpenProcess _
        Lib "NTDLL.DLL" (ByRef ProcessHandle As Long, _
        ByVal AccessMask As Long, _
        ByRef ObjectAttributes As OBJECT_ATTRIBUTES, _
        ByRef ClientID As CLIENT_ID) As Long

Public Type OBJECT_ATTRIBUTES
    Length As Long
    RootDirectory As Long
    ObjectName As Long    'PUNICODE_STRING 的指针
    Attributes As Long
    SecurityDescriptor As Long
    SecurityQualityOfService As Long
End Type

Public Type CLIENT_ID
    UniqueProcess As Long
    UniqueThread As Long
End Type

Public Const PROCESS_QUERY_INFORMATION As Long = (&H400)

Public Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Public Const SYNCHRONIZE As Long = &H100000

Public Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Public Const PROCESS_DUP_HANDLE As Long = (&H40)

Public Declare Function ZwClose _
        Lib "NTDLL.DLL" (ByVal ObjectHandle As Long) As Long

Public Const ZwGetCurrentProcess As Long = -1    '//0xFFFFFFFF

Public Declare Sub CopyMemory _
        Lib "kernel32.dll" _
        Alias "RtlMoveMemory" (ByVal Destination As Long, _
        ByVal Source As Long, _
        ByVal Length As Long)

'before you call this function, you need SE_DEBUG, ret value=hProcess
Public Function LzOpenProcess(ByVal dwDesiredAccess As Long, _
                              ByVal ProcessId As Long) As Long
    Dim st As Long
    Dim cid As CLIENT_ID
    Dim oa As OBJECT_ATTRIBUTES
    Dim NumOfHandle As Long
    Dim pbi As PROCESS_BASIC_INFORMATION
    Dim I As Long
    Dim hProcessToDup As Long, hProcessCur As Long, hProcessToRet As Long
    
    oa.Length = Len(oa)
    '首先尝试ZwOpenProcess
    cid.UniqueProcess = ProcessId
    st = ZwOpenProcess(hProcessToRet, dwDesiredAccess, oa, cid)
    If (NT_SUCCESS(st)) Then LzOpenProcess = hProcessToRet: Exit Function
    st = 0
    Dim bytBuf() As Byte
    Dim arySize As Long: arySize = 1
    Do
        ReDim bytBuf(arySize)
        st = ZwQuerySystemInformation(SystemHandleInformation, VarPtr(bytBuf(0)), arySize, 0&)
        If (Not NT_SUCCESS(st)) Then
            If (st <> STATUS_INFO_LENGTH_MISMATCH) Then
                Erase bytBuf
                Exit Function
            End If
        Else
            Exit Do
        End If

        arySize = arySize * 2
        ReDim bytBuf(arySize)
    Loop
    NumOfHandle = 0
    Call CopyMemory(VarPtr(NumOfHandle), VarPtr(bytBuf(0)), Len(NumOfHandle))
    Dim h_info() As SYSTEM_HANDLE_TABLE_ENTRY_INFO
    ReDim h_info(NumOfHandle)
    Call CopyMemory(VarPtr(h_info(0)), VarPtr(bytBuf(0)) + Len(NumOfHandle), Len(h_info(0)) * NumOfHandle)
    '//枚举句柄完成，下来开始测试句柄
    For I = LBound(h_info) To UBound(h_info)
        With h_info(I)
            If (.ObjectTypeIndex = OB_TYPE_PROCESS) Then
                cid.UniqueProcess = .UniqueProcessId
                st = ZwOpenProcess(hProcessToDup, PROCESS_DUP_HANDLE, oa, cid)
                If (NT_SUCCESS(st)) Then
                    st = ZwDuplicateObject(hProcessToDup, .HandleValue, ZwGetCurrentProcess, hProcessCur, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ATTRIBUTES)
                    If (NT_SUCCESS(st)) Then
                        st = ZwQueryInformationProcess(hProcessCur, ProcessBasicInformation, VarPtr(pbi), Len(pbi), 0)
                        If (NT_SUCCESS(st)) Then
                            If (pbi.UniqueProcessId = ProcessId) Then
                                st = ZwDuplicateObject(hProcessToDup, .HandleValue, ZwGetCurrentProcess, hProcessToRet, dwDesiredAccess, 0, DUPLICATE_SAME_ATTRIBUTES)
                                If (NT_SUCCESS(st)) Then LzOpenProcess = hProcessToRet
                            End If
                        End If
                    End If
                    st = ZwClose(hProcessCur)
                End If
                st = ZwClose(hProcessToDup)
            End If
        End With
    Next
    Erase h_info
End Function

Public Function NT_SUCCESS(ByVal Status As Long) As Boolean
    NT_SUCCESS = (Status >= 0)
End Function

