我正在尝试使用Windows函数:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa注册全局钩子。
我已经在C ++ Dll中创建了一个钩子过程,并用C ++编写的可执行文件测试了该过程,该可执行文件调用SetWindowsHookEx,它似乎可以正常工作。
这是我的C ++ Dll中重要代码的摘要:
#include "pch.h"
#include "FSHooksLib.h"
#include "global.h"
typedef void (*callback_function)(int);
callback_function g_callback = nullptr;
HHOOK g_hook = nullptr;
extern "C" FSHOOKS_API void Init()
{
if (g_log)
{
g_log.close();
}
g_log.open("hookslog.txt", std::ofstream::out);
g_log << "FSHooksLib has been initialized" << std::endl;
}
extern "C" FSHOOKS_API void Release()
{
if (g_log)
{
g_log << "FSHooksLib has been releaseded" << std::endl;
g_log.close();
}
}
extern "C" FSHOOKS_API void SetCallback(callback_function callback)
{
g_callback = callback;
g_log << "Callback has been set" << std::endl;
}
extern "C" FSHOOKS_API LRESULT HookProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code != HC_ACTION)
return CallNextHookEx(nullptr, code, wParam, lParam);
MSLLHOOKSTRUCT* info = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
POINT point = info->pt;
DWORD flags = info->flags;
bool injected = flags & LLMHF_INJECTED;
bool lower_injected = flags & LLMHF_LOWER_IL_INJECTED;
DWORD time = info->time;
switch (wParam)
{
case WM_LBUTTONDOWN:
g_log << "Received a WM_LBUTTONDOWN message with injected=" << injected << std::endl;
if (g_callback)
{
g_callback(g_numProcesses);
}
break;
case WM_LBUTTONUP:
g_log << "Received a WM_LBUTTONUP message with injected=" << injected << std::endl;
break;
default:
break;
}
return CallNextHookEx(nullptr, code, wParam, lParam);
}
这是用C ++编写的Injector程序的样子:
#include <windows.h>
#include <iostream>
int main()
{
HMODULE hMod = LoadLibrary("FSHooks.dll");
if (!hMod)
{
std::cerr << "Count not load the FSHooks library" << std::endl;
return -1;
}
FARPROC fn_init = GetProcAddress(hMod, "Init");
if (!fn_init)
{
std::cerr << "Count not get the 'Init' function from FSHooks library" << std::endl;
return -1;
}
FARPROC fn_release = GetProcAddress(hMod, "Release");
if (!fn_release)
{
std::cerr << "Count not get the 'Release' function from FSHooks library" << std::endl;
return -1;
}
HOOKPROC fn_hook = reinterpret_cast<HOOKPROC>(GetProcAddress(hMod, "HookProc"));
if (!fn_hook)
{
std::cerr << "Count not get the 'HookProc' function from FSHooks library" << std::endl;
return -1;
}
HHOOK hook = SetWindowsHookEx(WH_MOUSE_LL, fn_hook, hMod, 0);
if (!hook)
{
std::cerr << "Failed to SetWindowsHookEx" << std::endl;
return -1;
}
fn_init();
MSG msg;
// TODO - We will need some manner of signal to terminate
// This is just a quick and dirty example program
while (true)
{
GetMessage(&msg, nullptr, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hook);
fn_release();
FreeLibrary(hMod);
return 0;
}
所以现在,如果我想尝试并从python应用程序中执行注射器的相同操作。我被困在如何传递钩子过程参数上。
我在wx窗口代码中有以下代码来初始化钩子:
import os.path
import threading
import win32con
import win32api
import wx
from ctypes import *
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(800, 600))
self.CreateStatusBar()
menu_file = wx.Menu()
menu_item_exit = menu_file.Append(wx.ID_EXIT, "E&xit", " Terminate the program")
menu_help = wx.Menu()
menu_item_about = menu_help.Append(wx.ID_ABOUT, "&About", " Information about this program")
menu_bar = wx.MenuBar()
menu_bar.Append(menu_file, "&File")
menu_bar.Append(menu_help, "&Help")
self.SetMenuBar(menu_bar)
self.panel = MainPanel(self)
self.Bind(wx.EVT_MENU, self.on_about, menu_item_about)
self.Bind(wx.EVT_MENU, self.on_exit, menu_item_exit)
self.Show(True)
def on_about(self, e):
dlg = wx.MessageDialog(self, "A window to test Windows Hooks", "About Test Windows Hooks",
wx.OK)
dlg.ShowModal()
dlg.Destroy()
def on_exit(self, e):
self.Close(True)
class MainPanel(wx.Panel):
def __init__(self, parent):
self.consuming = False
self.called_back_count = 0
wx.Panel.__init__(self, parent)
self.textbox = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)
self.horizontal = wx.BoxSizer()
self.horizontal.Add(self.textbox, proportion=1, flag=wx.EXPAND)
self.sizer_vertical = wx.BoxSizer(wx.VERTICAL)
self.sizer_vertical.Add(self.horizontal, proportion=1, flag=wx.EXPAND)
self.SetSizerAndFit(self.sizer_vertical)
# Set callback from windows hook procedure to our python code
dll_name = "FSHooks.dll"
dll_abspath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Win32',
'Debug', dll_name))
dll_handle = cdll.LoadLibrary(dll_abspath)
self.callback_type = CFUNCTYPE(None, c_int)
self.callback = self.callback_type(self.callback_from_c)
dll_handle.Init()
dll_handle.SetCallback(self.callback)
# TODO - Release the hooks when window closes
# Register the hook
# We want to pass dll_handle.HookProc
# which looks like:
# extern "C" FSHOOKS_API LRESULT HookProc(int code, WPARAM wParam, LPARAM lParam)
hookproc_type = CFUNCTYPE(c_int, c_int, c_int, POINTER(c_void_p))
hook_id = windll.user32.SetWindowsHookExA(win32con.WH_KEYBOARD_LL, pointer,
win32api.GetModuleHandle(None), 0)
def callback_from_c(self, number):
self.textbox.AppendText('Called back from C: {}'.format(number))
如果滚动到显示“#注册钩子”的部分,那是我被卡住的地方。指针变量未设置,我不知道该放在哪里。我只是想通过在同一线程上而不是从dll上的SetWindowsHookEx的python示例中,在Stackoverflow上找到自己的方式。
注意-我知道pyHook库存在,但是在某些情况下无法正常工作,因此我想自己尝试使用此路由。
答案 0 :(得分:0)
我使回调工作正常,并且钩子注册了以下代码:
# Set callback from windows hook procedure to our python code
dll_name = "FSHooks.dll"
dll_abspath = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'Win32',
'Debug', dll_name))
dll_handle = cdll.LoadLibrary(dll_abspath)
self.callback_type = CFUNCTYPE(None, c_int, c_int, c_int, c_bool)
self.callback = self.callback_type(self.callback_from_c)
dll_handle.Init()
dll_handle.SetCallback(self.callback)
# TODO - Release the hooks when window closes
# Register the hook
dll_handle.HookProc.argtypes = (c_int, wintypes.WPARAM, wintypes.LPARAM)
hook_proc_pointer = dll_handle.HookProc
self.hook_id = windll.user32.SetWindowsHookExA(win32con.WH_MOUSE_LL, hook_proc_pointer,
win32api.GetModuleHandle(None), 0)
似乎您可以只接受dll中函数名称的属性,并将其作为指针参数接受。我必须设置参数类型,然后它才能起作用。