鍍金池/ 問答/Java  網(wǎng)絡(luò)安全  HTML/ java通過jni調(diào)用hook無效

java通過jni調(diào)用hook無效

我需要實現(xiàn)一個鉤子程序來禁用鼠標(biāo)鍵盤的輸入,然后將其生成為dll,然后在java中調(diào)用,調(diào)用時候程序沒有報錯,但是調(diào)用無效.下面是部分代碼

c++部分:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "stdio.h"

HHOOK g_HookHwnd = NULL;
HHOOK g_hMouse = NULL;

// 鉤子子程
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookFun(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("in hook key function\n");
    // 這個Structure包含了鍵盤的信息
    /*typedef struct {
    DWORD vkCode;
    DWORD scanCode;
    DWORD flags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
    } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
    // 我們只需要那個vkCode
    PKBDLLHOOKSTRUCT pVirKey = (PKBDLLHOOKSTRUCT)lParam;

    // MSDN說了,nCode < 0的時候別處理
    if (nCode >= 0)
    {
        // 按鍵消息
        switch (wParam)
        {
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
            switch (pVirKey->vkCode)
            {
            case VK_LWIN:
            case VK_RWIN:
                return 1;  // 吃掉消息
                break;
            }
            return 1;
            break;
        }
    }

    return CallNextHookEx(g_HookHwnd, nCode, wParam, lParam);
}

extern "C" _declspec(dllexport) LRESULT CALLBACK  MyHookMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("in hook mouse function\n");
    return 1;
}


HMODULE g_Module;
extern "C" _declspec(dllexport)  BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    {

        break;
    }
    }
    return TRUE;
}


extern "C" _declspec(dllexport) void FuncHookDevice()
{
    if (!g_HookHwnd)
    {
        printf("start hook\n");
        g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_Module, 0);
        //g_hMouse = SetWindowsHookEx(WH_MOUSE_LL, MyHookMouse, g_Module, 0);  //暫時禁用鼠標(biāo)鉤子
    }
}

extern "C" _declspec(dllexport) void FuncEndHook()
{
    printf("end hook\n");
    UnhookWindowsHookEx(g_HookHwnd);
    //UnhookWindowsHookEx(g_hMouse);   //暫時禁用鼠標(biāo)鉤子
    g_HookHwnd = NULL;
}

java程序:

public class HookTest {
    public interface  Hook extends Library{
        Hook INSTANCE = (Hook) Native.loadLibrary("lib/Hook",Hook.class);
        public void FuncEndHook();
        public void FuncHookDevice();
    }

    public static void main(String[] args) {
        Hook.INSTANCE.FuncHookDevice();
    }
}

運行結(jié)果:
clipboard.png

程序運行完后發(fā)現(xiàn)只輸出了"start hook" 然后程序就停止了運行.并沒有打印出"in hook key function".說明程序是沒有進入到鉤子函數(shù)內(nèi)部的. 這個c++程序的鉤子我是經(jīng)過測試的,使用c++調(diào)用dll可以成功的禁用掉鍵盤或者鼠標(biāo).

所以為什么用java調(diào)用的時候就無效呢.

回答
編輯回答
醉淸風(fēng)

終于解決了這個問題,在stackoverflow上面提問找到了解答:問答詳情

做法是添加消息隊列.為什么添加在這個問答:為什么添加消息隊列,大致意思是因為低級鼠標(biāo)鍵盤鉤子默認(rèn)會馬上返回返回值,通過添加消息隊列就能解決.

添加了一個線程來控制鉤子,如果不添加好像程序不能按要求退出.

最后c++部分代碼:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "stdio.h"

HHOOK g_HookHwnd = NULL;
HHOOK g_hMouse = NULL;
HANDLE hThread = NULL;

// 鉤子子程
extern "C" _declspec(dllexport) LRESULT CALLBACK MyHookFun(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("in hook key function\n");
    // 這個Structure包含了鍵盤的信息
    /*typedef struct {
    DWORD vkCode;
    DWORD scanCode;
    DWORD flags;
    DWORD time;
    ULONG_PTR dwExtraInfo;
    } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
    // 我們只需要那個vkCode
    PKBDLLHOOKSTRUCT pVirKey = (PKBDLLHOOKSTRUCT)lParam;

    // MSDN說了,nCode < 0的時候別處理
    if (nCode >= 0)
    {
        // 按鍵消息
        switch (wParam)
        {
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
            switch (pVirKey->vkCode)
            {
            case VK_LWIN:
            case VK_RWIN:
                return 1;  // 吃掉消息
                break;
            }
            return 1;
            break;
        }
    }

    return CallNextHookEx(g_HookHwnd, nCode, wParam, lParam);
}

extern "C" _declspec(dllexport) LRESULT CALLBACK  MyHookMouse(int nCode, WPARAM wParam, LPARAM lParam)
{
    printf("in hook mouse function\n");
    return 1;
}


HMODULE g_Module;
extern "C" _declspec(dllexport)  BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    {

        break;
    }
    }
    return TRUE;
}


extern "C" _declspec(dllexport) DWORD WINAPI controllHook(LPVOID lpParamter)
{
    g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_Module, 0);
    g_hMouse = SetWindowsHookEx(WH_MOUSE_LL, MyHookMouse, g_Module, 0);
    while (true) {
        MSG msg;
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}


extern "C" _declspec(dllexport) void FuncHookDevice()
{
    if (!g_HookHwnd)
    {
        hThread = CreateThread(NULL, 0, controllHook, NULL, 0, NULL);
        
        printf("start hook\n");
        g_HookHwnd = SetWindowsHookEx(WH_KEYBOARD_LL, MyHookFun, g_Module, 0);

    }
}

extern "C" _declspec(dllexport) void FuncEndHook()
{
    printf("end hook\n");
    UnhookWindowsHookEx(g_HookHwnd);
    UnhookWindowsHookEx(g_hMouse);
    CloseHandle(hThread);
    g_HookHwnd = NULL;
}
2017年12月14日 13:04