将功能指针从C Dll传递到C Dll

时间:2019-07-15 22:21:49

标签: python ctypes

我正在尝试使用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库存在,但是在某些情况下无法正常工作,因此我想自己尝试使用此路由。

1 个答案:

答案 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中函数名称的属性,并将其作为指针参数接受。我必须设置参数类型,然后它才能起作用。