Windows Practice_Dll&Hook_message hook

Keywords: Windows

Dll

Dll is what we usually call Dynamic Link Library. It is essentially the same as an application. It is also an executable file. They all have the same PE structure.
However, there are some differences between the two applications. Dll generally acts as a complement to exe applications. It is a module that is used to load exe files.
In Windows, some exe files can also be loaded, such as. oxc suffix control format.

Why do most applications like to make Dll?

  • Extending the features of the application;
  • Simplified project management;
  • Save memory (only one Dll in the system, need to use this Dll program, mapping to the current process through paging mechanism);
  • Promoting resource sharing;
  • Promoting localization;
  • Resolve the differences between versions.

Dll and applications share the same process space

  • The memory allocated in Dll must be released by Dll.
  • Applications do not release space because Dll is uninstalled.

Dll entry function

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:// When loaded
        // Initialization of Dll
        case DLL_THREAD_ATTACH:// When a new thread starts in the application
        // This point of time is very important. When the newly started thread of the application loads this Dll module, it will be called, usually for thread security settings.
        case DLL_THREAD_DETACH:// When unloaded
        case DLL_PROCESS_DETACH:// When a thread terminates
        // Destruction of Dll
            break;
    }
    return TRUE;
}

Dll Derived Function

For a dynamic link library, the most important thing is its export function. Only the export function can be used by its application program. The format of the derived function is as follows:

extern "C" bool _declspec(dllexport) OnHook();

Implementation of Keyboard Interceptor

Implementation of Dll

#pragma once
// Windows MsgHookDemo.h file
typedef void(*pFunc)(char *str);

extern "C" bool _declspec(dllexport) OnHook();
extern "C" bool _declspec(dllexport) OnSetFunc(pFunc func);
extern "C" bool _declspec(dllexport) UnHook();
// Windows HookDemo. cpp: Defines the export function of a DLL application.
//

#include "stdafx.h"
#include "WindowsMsgHookDemo.h"
#include <tchar.h>
#include <cstdio>


extern HMODULE g_hModule;
HHOOK g_hHook = nullptr;
pFunc g_myFunc;


LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code == HC_ACTION)
    {
        char str[MAXBYTE] = { 0 };
        if (lParam & 0x80000000)
        {
            sprintf_s(str, "[%c] The key is lifted. - Keyboard code [%04d]\r\n", wParam, wParam);
        }
        else
        {
            sprintf_s(str, "[%c] Key pressed - Keyboard code [%04d]\r\n", wParam, wParam);
        }

        g_myFunc(str);
    }

    return CallNextHookEx(g_hHook, code, wParam, lParam);
}

bool OnHook()
{
    bool bRet = true;
    if (g_hHook == nullptr)
    {
        g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hModule, 0);
    }
    else
    {
        bRet = false;
    }

    return bRet;
}

bool OnSetFunc(pFunc func)
{
    g_myFunc = func;
    return true;
}

bool UnHook()
{
    bool bRet = true;
    if (g_hHook != nullptr)
    {
        UnhookWindowsHookEx(g_hHook);
        g_hHook = nullptr;
    }
    else
    {
        bRet = false;
    }

    return bRet;
}
// dllmain.cpp: Defines entry points for DLL applications.
#include "stdafx.h"

HMODULE g_hModule;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        g_hModule = hModule;
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Test program

The Windows HookDemo. DLL generated above can be loaded by putting it into the test program.

// DllTestDemo.cpp: Defines the entry point for console applications.
//

#include "stdafx.h"
#include <Windows.h>

typedef void(*pFunc)(char *str);

typedef bool (*FUNC)(pFunc pfunc);

void myPrint(char *str)
{
    printf(str);
}

int main()
{
    HMODULE hDll = LoadLibrary(L"WindowsHookDemo.dll");
    FARPROC OnHook = GetProcAddress(hDll, "OnHook");
    FUNC OnSetFunc = (FUNC)GetProcAddress(hDll, "OnSetFunc");
    FARPROC UnHook = GetProcAddress(hDll, "UnHook");

    OnSetFunc(myPrint);
    OnHook();
    printf("OnHook()......\r\n");

    BOOL ret;
    MSG msg;
    while ((ret = GetMessage(&msg, nullptr, 0, 0)))
    {
        if (ret == -1)
            break;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    UnHook();
    printf("UnHook()......\r\n");

    return 0;
}

Running the test program prints all keyboard input information to the console.

Matters needing attention

This keyboard interceptor needs to pay attention to the use of a function:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

We monitor the keyboard, so we need a keyboard hook callback function, which is defined as follows:

LRESULT CALLBACK KeyboardProc(
  _In_ int    code,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

The important thing to note about this function is that:
Remarks
An application installs the hook procedure by specifying the WH_KEYBOARD hook type and a pointer to the hook procedure in a call to the SetWindowsHookEx function.
This hook may be called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
If the application loading this Dll does not have a message loop, it will not work properly and will not achieve the desired results.

When we test Dll program, we write our own exe program. There must be source code. When we debug LoadLibrary, we automatically attach Dll to exe program. But sometimes we don't have the source code of exe file, that is, we can't debug exe program. If we want to debug our loaded Dll program, we need to use the add-in provided by vs. Cheng's functions are shown in the following figure:


In this way, we can enter the breakpoint set by Dll and achieve the purpose of debugging.

Posted by eyespark on Sun, 16 Dec 2018 13:30:04 -0800