Skip to content

Commit

Permalink
Support for showing if app is 32bit vs 64bit, and support for doing m…
Browse files Browse the repository at this point in the history
…essage hooks on both

Added support for message hook viewer to hook both 32 and 64 bit
applications.
Fixed filtering on the msg hook viewer
Added custom filtering on msg hook viewer
Added Process Id targetting on msg hook viewer
Added SetMsgHook.exe command line app as an alternative way of starting
msg hook viewer.
  • Loading branch information
ejakubowski committed Jun 3, 2014
1 parent 05748b4 commit d100d23
Show file tree
Hide file tree
Showing 41 changed files with 1,232 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ native/uiabridge/release
native/uiabridge/Debug
!native/uiabridge/bin
!native/MsgHook/bin
!native/MsgHookTest/bin
!native/SetMsgHook/bin
35 changes: 35 additions & 0 deletions native/MsgHook.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MsgHook", "MsgHook\MsgHook.vcxproj", "{8E038A94-7D02-49E9-B9F6-5224D9D11225}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetMsgHook", "SetMsgHook\SetMsgHook.vcxproj", "{34A73B55-8A93-4FB5-83CE-7759C1D23348}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|Win32.ActiveCfg = Debug|Win32
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|Win32.Build.0 = Debug|Win32
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|x64.ActiveCfg = Debug|x64
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|x64.Build.0 = Debug|x64
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|Win32.ActiveCfg = Release|Win32
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|Win32.Build.0 = Release|Win32
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|x64.ActiveCfg = Release|x64
{8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|x64.Build.0 = Release|x64
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Debug|Win32.ActiveCfg = Debug|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Debug|Win32.Build.0 = Debug|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Debug|x64.ActiveCfg = Debug|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Release|Win32.ActiveCfg = Release|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Release|Win32.Build.0 = Release|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Release|x64.ActiveCfg = Release|Win32
{34A73B55-8A93-4FB5-83CE-7759C1D23348}.Release|x64.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
146 changes: 137 additions & 9 deletions native/MsgHook/MsgHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@

// MsgHook.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"


//to fix export declaration had to add .def file
LRESULT CALLBACK CwpHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
COPYDATASTRUCT CDS;
Expand Down Expand Up @@ -55,7 +54,11 @@ LRESULT CALLBACK CwpHookProc(int nCode, WPARAM wParam, LPARAM lParam)
}
}

BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed
//printf("debug: sending to hwnd (%ld) msg %d, wParam %ld, lParam %ld\n", pData->g_hWnd, Event.nCode, Event.wParam, Event.lParam);
if (cwps->hwnd != pData->g_hWnd)
{
BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed
}
}
return CallNextHookEx(pData->g_CwpHook, nCode, wParam, lParam); // pass hook to next handler
//return bRes; // Don't tell the other hooks about this message.
Expand All @@ -70,7 +73,7 @@ LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
CDS.cbData = sizeof(Event);
CDS.lpData = &Event;

//if (nCode == HC_ACTION)
if (nCode >=0 && nCode == HC_ACTION)
{
//For WH_GETMESSAGE hook a pointer to a MSG structure that contains details about the message.
MSG *msg = (MSG *)lParam;
Expand All @@ -84,19 +87,48 @@ LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam)
//if (msg->message == WM_SETTEXT && msg->lParam != 0)
// _tcscpy_s(Event.lParamStr, 25, (const wchar_t*)Event.lParam);
//if (msg->message == WM_COMMAND || msg->message == WM_MENUCOMMAND) //infinite loop?
BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed
if (msg->hwnd != pData->g_hWnd)
{
BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed
}
}

return CallNextHookEx(pData->g_MsgHook, nCode, wParam, lParam); // pass hook to next handler
//return bRes; // Don't tell the other hooks about this message.
}

//support for 32-bit/64-bit apps means the dll might be different to match the process we want to see
extern "C" __declspec(dllexport) BOOL SetCustomMsgHookDll(const TCHAR * hookDll, const char * hookDllProcName)
{
HMODULE dll = LoadLibrary(hookDll); //should provide full dll path and filename
if (dll == NULL)
{
TCHAR errorStr[200];
_stprintf_s(errorStr, _T("Error loading hook library %s"), hookDll);
MessageBox(0, errorStr, _T("Set Hook Dll Error"), 0);
return false;
}
HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, hookDllProcName); //should provide the 'CwpHookProc'
if (addr == NULL)
{
char errorStr[200];
sprintf_s(errorStr, "Error loading hook library procedure %s", hookDllProcName);
MessageBoxA(0, errorStr, "Set Hook Dll Error", 0);
return false;
}
pData->g_hInstance = dll;
pData->g_CwpHookProc = addr;
return true;
}

extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId)
{
if(bStartingProcess) // if we're just starting the DLL for the first time,
// if(bStartingProcess) // if we're just starting the DLL for the first time,
{
pData->g_hWnd = callerHWnd; // remember the windows and hook handle for further instances
pData->g_CwpHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CwpHookProc, (HINSTANCE)pData->g_hInstance, threadId);
if (pData->g_CwpHookProc == NULL)
pData->g_CwpHookProc = (HOOKPROC)CwpHookProc;
pData->g_CwpHook = SetWindowsHookEx(WH_CALLWNDPROC, pData->g_CwpHookProc, (HINSTANCE)pData->g_hInstance, threadId);
//pData->g_MsgHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MsgHookProc, (HINSTANCE)pData->g_hInstance, threadId);
if (pData->g_CwpHook == NULL) {
TCHAR tmp[100];
Expand All @@ -106,11 +138,21 @@ extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId

return (pData->g_CwpHook != NULL); //pData->g_CwpHook != NULL &&
}
else
/*else
{
//MessageBox(0, _T("Error: Not starting process"), _T("Set Hook Error"), 0);
return false;
}
}*/
}

extern "C" __declspec(dllexport) HHOOK GetCurrentHookHandle()
{
return pData->g_CwpHook; //if NULL hook isn't running
}

extern "C" __declspec(dllexport) void SetGlobalDLLInstance(HANDLE dllInstance)
{
pData->g_hInstance = dllInstance;
}

extern "C" __declspec(dllexport) BOOL RemoveHook()
Expand All @@ -127,7 +169,93 @@ extern "C" __declspec(dllexport) BOOL RemoveHook()
BOOL ret = UnhookWindowsHookEx(pData->g_CwpHook);
pData->g_hWnd = NULL; // reset data
pData->g_CwpHook = NULL;
pData->g_CwpHookProc = NULL;
return ret;
}
return false;
}


//testing if process 64 bit, needed to verify this dll can hook & attach to target process
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;

extern "C" __declspec(dllexport) BOOL IsCurrentProcess64Bit()
{
return IsProcess64Bit(_getpid());
}

extern "C" __declspec(dllexport) BOOL IsProcess64Bit(DWORD procId)
{
SYSTEM_INFO stInfo;
GetNativeSystemInfo(&stInfo); // if native system is x86 skip wow64 test
if (stInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
return false; //printf( "Processor Architecture: Intel x86\n");

BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.

fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if(fnIsWow64Process != NULL)
{
HANDLE procHandle = NULL;//GetCurrentProcess();
procHandle = OpenProcess(PROCESS_QUERY_INFORMATION, false, procId);
if (!fnIsWow64Process(procHandle, &bIsWow64))
{
//handle error
}
CloseHandle(procHandle);
if (bIsWow64) // NOT a native 64bit process
return false;
return true;// is a native 64bit process
}
return false; //some error finding function "IsWow64Process" assume not 64-bit
}

extern "C" __declspec(dllexport) DWORD GetProcessMainThreadId(DWORD procId)
{

#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif
#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif

DWORD dwMainThreadID = 0;
ULONGLONG ullMinCreateTime = MAXULONGLONG;
//includes all threads in the system
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) {
THREADENTRY32 th32;
th32.dwSize = sizeof(THREADENTRY32);
BOOL bOK = TRUE;
//Enumerate all threads in the system and filter on th32OwnerProcessID = pid
for (bOK = Thread32First(hThreadSnap, &th32); bOK ; bOK = Thread32Next(hThreadSnap, &th32)) {
//if (th32.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(th32.th32OwnerProcessID)) {
if (th32.th32OwnerProcessID == procId && (th32.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(th32.th32OwnerProcessID))) {
//_tprintf(_T("DEBUG Enumerate Process (%ld) Thread Id: %ld\n"), procId, th32.th32ThreadID);
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, th32.th32ThreadID);
if (hThread) {
FILETIME afTimes[4] = {0};
if (GetThreadTimes(hThread, &afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime, afTimes[0].dwHighDateTime);
if (ullTest && ullTest < ullMinCreateTime) { //check each thread's creation time
ullMinCreateTime = ullTest;
dwMainThreadID = th32.th32ThreadID; // let it be main thread
}
}
CloseHandle(hThread); //must close opened thread
}
}
}
#ifndef UNDER_CE
CloseHandle(hThreadSnap); //close thread snapshot
#else
CloseToolhelp32Snapshot(hThreadSnap); //close thread snapshot
#endif
}
return dwMainThreadID; //returns main thread id or returns 0 if can't find it
}
5 changes: 5 additions & 0 deletions native/MsgHook/MsgHook.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LIBRARY MsgHook

EXPORTS
CwpHookProc @1
MsgHookProc @2
9 changes: 9 additions & 0 deletions native/MsgHook/MsgHook.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>MsgHook.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
Expand All @@ -99,6 +100,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>MsgHook.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
Expand All @@ -115,6 +117,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>MsgHook.def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
Expand All @@ -135,20 +138,26 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>MsgHook.def</ModuleDefinitionFile>
</Link>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(TargetExt)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="..\SetMsgHook\bin\SetMsgHook32.exe" />
<None Include="..\SetMsgHook\bin\SetMsgHook64.exe" />
<None Include="binary1.bin" />
<None Include="MsgHook.def" />
<None Include="MsgHookTest.ico" />
<None Include="ReadMe.txt" />
<None Include="small.ico" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="MsgLookup.h" />
<ClInclude Include="org_synthuse_MsgHook.h" />
<ClInclude Include="ResExtract.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
Expand Down
11 changes: 11 additions & 0 deletions native/MsgHook/MsgHook.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
<None Include="small.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="MsgHook.def">
<Filter>Source Files</Filter>
</None>
<None Include="binary1.bin">
<Filter>Resource Files</Filter>
</None>
<None Include="..\SetMsgHook\bin\SetMsgHook64.exe" />
<None Include="..\SetMsgHook\bin\SetMsgHook32.exe" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
Expand All @@ -39,6 +47,9 @@
<ClInclude Include="MsgLookup.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ResExtract.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
Expand Down
Binary file modified native/MsgHook/MsgHookTest.aps
Binary file not shown.
Binary file modified native/MsgHook/MsgHookTest.rc
Binary file not shown.
Loading

0 comments on commit d100d23

Please sign in to comment.