Private Declare Function NtReadVirtualMemory _ Lib "NTDLL.DLL" (ByVal ProcessHandle As Long, _ ByVal BaseAddress As Long, _ ByVal pBuffer As Long, _ ByVal NumberOfBytesToRead As Long, _ ByRef NumberOfBytesReaded As Long) As Long Private Declare Function NtWriteVirtualMemory _ Lib "NTDLL.DLL" (ByVal ProcessHandle As Long, _ ByVal BaseAddress As Long, _ ByVal pBuffer As Long, _ ByVal NumberOfBytesToWrite As Long, _ ByRef NumberOfBytesWritten As Long) As Long 'Private Const pgSharedInfo = &H77D700A0 //can be located now. Private Const NtGetCurrentProcess = -1 '//0xFFFFFFFF
Private Type SHAREDINFO psi As Long 'tagSERVERINFO aheList As Long '_HANDLEENTRY - handle table pointer pDispInfo As Long 'global displayinfo ulSharedDelta As Long 'delta between client and kernel mapping of ... '省略 End Type
Private Type HANDLEENTRY phead As Long 'pointer to the real object pOwner As Long 'pointer to owning entity (pti or ppi) bType As Byte 'type of object bFlags As Byte 'flags - like destroy flag wUniq As Integer 'uniqueness count End Type
Private Type SERVERINFO 'si wRIPFlags As Integer 'RIPF_ flags wSRVIFlags As Integer 'SRVIF_ flags wRIPPID As Integer 'PID of process to apply RIP flags to (zero means all) wRIPError As Integer 'Error to break on (zero means all errors are treated equal) cHandleEntries As Long 'count of handle entries in array End Type
Private Enum HANDLE_TYPE TYPE_FREE = 0 'must be zero! TYPE_WINDOW = 1 'in order of use for C code lookups TYPE_MENU = 2 TYPE_CURSOR = 3 TYPE_SETWINDOWPOS = 4 TYPE_HOOK = 5 TYPE_CLIPDATA = 6 'clipboard data TYPE_CALLPROC = 7 TYPE_ACCELTABLE = 8 TYPE_DDEACCESS = 9 TYPE_DDECONV = 10 TYPE_DDEXACT = 11 'DDE transaction tracking info. TYPE_MONITOR = 12 TYPE_KBDLAYOUT = 13 'Keyboard Layout handle (HKL) object. TYPE_KBDFILE = 14 'Keyboard Layout file object. TYPE_WINEVENTHOOK = 15 'WinEvent hook (EVENTHOOK) TYPE_TIMER = 16 TYPE_INPUTCONTEXT = 17 'Input Context info structure TYPE_CTYPES = 18 'Count of TYPEs; Must be LAST + 1 TYPE_GENERIC = 255 'used for generic handle validation End Enum
Private Type HEAD hObject As Long cLockObj As Long End Type
Private Type THROBJHEAD headinfo As HEAD pti As Long 'PTHREADINFO End Type
Private Type DESKHEAD rpdesk As Long 'PDESKTOP pSelf As Long 'PBYTE End Type
Private Type THRDESKHEAD ThreadObjHead As THROBJHEAD DesktopHead As DESKHEAD End Type
Private Type HOOK 'hk tshead As THRDESKHEAD phkNext As Long iHook As Integer '// WH_xxx hook type offPfn As Long flags As Integer '// HF_xxx flags ihmod As Integer ptiHooked As Long '//PTHREADINFO - Thread hooked. rpdesk As Long '// Global hook pdesk. Only used when hook is locked and owner is destroyed End Type
Private Type W32THREAD pEThread As Long RefCount As Long ptlW32 As Long pgdiDcattr As Long pgdiBrushAttr As Long pUMPDObjs As Long pUMPDHeap As Long dwEngAcquireCount As Long pSemTable As Long pUMPDObj As Long End Type
Public Type MsgHookInfo hHook As Long iHookType As HOOK_TYPE pEThread As Long offPfn As Long End Type
Private pgSharedInfo As Long
Private Declare Function GetModuleHandle _ Lib "kernel32.dll" Alias "GetModuleHandleA" _ (ByVal lpModuleName As String) As Long Private Declare Function GetProcAddress _ Lib "kernel32.dll" (ByVal hModule As Long, _ ByVal lpProcName As String) As Long
Private Sub LocateSharedInfo() 'locate gSharedInfo Dim pfnUserRegisterWowHandlers As Long: pfnUserRegisterWowHandlers = GetProcAddress(GetModuleHandle("user32.dll"), "UserRegisterWowHandlers") Dim I As Long For I = pfnUserRegisterWowHandlers To pfnUserRegisterWowHandlers + &H1000 If ((ReadMemoryToInt(I) = &H40C7) And _ (ReadMemoryToInt(I + 1 * 7) = &H40C7) And _ (ReadMemoryToInt(I + 2 * 7) = &H40C7) And _ (ReadMemoryToInt(I + 3 * 7) = &H40C7) And _ (ReadMemoryToInt(I + 4 * 7) = &H40C7) And _ (ReadMemoryToInt(I + 5 * 7) = &H40C7)) Then If (ReadMemoryToByt(I + 6 * 7) = &HB8) Then '40c7: mov dword ptr Debug.Print "position="; Hex(I) pgSharedInfo = ReadMemoryToLong(I + 6 * 7 + 1) Debug.Print "gSharedInfo="; Hex(pgSharedInfo) End If End If Next End Sub
Private Function ReadMemoryToInt(ByVal dwAddress As Long) As Integer Dim st As Long Dim ret As Integer Dim nReadBytes As Long st = NtReadVirtualMemory(NtGetCurrentProcess, dwAddress, VarPtr(ret), LenB(ret), nReadBytes) ReadMemoryToInt = ret End Function
Private Function ReadMemoryToLong(ByVal dwAddress As Long) As Long Dim st As Long Dim ret As Long Dim nReadBytes As Long st = NtReadVirtualMemory(NtGetCurrentProcess, dwAddress, VarPtr(ret), LenB(ret), nReadBytes) ReadMemoryToLong = ret End Function
Private Function ReadMemoryToByt(ByVal dwAddress As Long) As Byte Dim st As Long Dim ret As Byte Dim nReadBytes As Long st = NtReadVirtualMemory(NtGetCurrentProcess, dwAddress, VarPtr(ret), LenB(ret), nReadBytes) ReadMemoryToByt = ret End Function
Public Function EnumMsgHook_Init() As Boolean Call LocateSharedInfo EnumMsgHook_Init = (pgSharedInfo <> 0) End Function
Public Function EnumMsgHook() As MsgHookInfo() Dim hProcess As Long: hProcess = NtGetCurrentProcess '??? Dim gSharedInfo As SHAREDINFO Dim gHandleEntries() As HANDLEENTRY Dim gsi As SERVERINFO Dim retArray() As MsgHookInfo Dim st As Long Dim nReadBytes As Long Dim I As Long Dim hHookInfo As HOOK Dim tmpBytArray() As Byte Dim w32thd As W32THREAD ReDim retArray(0) st = NtReadVirtualMemory(hProcess, pgSharedInfo, VarPtr(gSharedInfo), LenB(gSharedInfo), nReadBytes) If (Not NT_SUCCESS(st)) Then GoTo ExitFunc__ st = NtReadVirtualMemory(hProcess, gSharedInfo.psi, VarPtr(gsi), LenB(gsi), nReadBytes) If (Not NT_SUCCESS(st)) Then GoTo ExitFunc__ ReDim gHandleEntries(gsi.cHandleEntries - 1) st = NtReadVirtualMemory(hProcess, gSharedInfo.aheList, VarPtr(gHandleEntries(LBound(gHandleEntries))), _ LenB(gHandleEntries(LBound(gHandleEntries))) * gsi.cHandleEntries, nReadBytes) If (Not NT_SUCCESS(st)) Then GoTo ExitFunc__ For I = LBound(gHandleEntries) To UBound(gHandleEntries) If (gHandleEntries(I).bType = TYPE_HOOK) Then 'generally, phead is in kernel memory, so we cannot read through NtReadVirtualMemory ReDim tmpBytArray(LenB(hHookInfo) - 1) If (DumpKernelMemory(gHandleEntries(I).phead, LenB(hHookInfo), tmpBytArray)) Then If (CopyMemory(VarPtr(hHookInfo), VarPtr(tmpBytArray(LBound(tmpBytArray))), LenB(hHookInfo))) Then With retArray(UBound(retArray)) .hHook = hHookInfo.tshead.ThreadObjHead.headinfo.hObject .iHookType = hHookInfo.iHook .offPfn = hHookInfo.offPfn ReDim tmpBytArray(LenB(w32thd) - 1) If (DumpKernelMemory(hHookInfo.tshead.ThreadObjHead.pti, LenB(w32thd), tmpBytArray)) Then If (CopyMemory(VarPtr(w32thd), VarPtr(tmpBytArray(LBound(tmpBytArray))), LenB(w32thd))) Then .pEThread = w32thd.pEThread End If End If 'Debug.Print String(30, "="); vbCrLf; _ ' " hHook: "; Format(Hex(.hHook), "@@@@@@@@"); vbCrLf; _ ' " offPfn: "; Format(Hex(.offPfn), "@@@@@@@@"); vbCrLf; _ ' " iHook: "; .iHookType; vbCrLf; _ ' " pEThread: "; Format(Hex(.pEThread), "@@@@@@@@"); vbCrLf '====================================================================== End With ReDim Preserve retArray(UBound(retArray) + 1) End If End If End If Next ExitFunc__: If (UBound(retArray) > 0) Then ReDim Preserve retArray(UBound(retArray) - 1) EnumMsgHook = retArray Erase retArray Erase tmpBytArray End Function
Public Function CopyMemory(ByVal pDst As Long, ByVal pSrc As Long, ByVal nLength As Long) As Boolean Dim st As Long st = NtWriteVirtualMemory(NtGetCurrentProcess, pDst, pSrc, nLength, ByVal 0) CopyMemory = NT_SUCCESS(st) End Function
Public Function NT_SUCCESS(ByVal Status As Long) As Boolean NT_SUCCESS = (Status >= 0) End Function