逆向工程核心原理 Chapter 21 | Windows消息钩取

开始DLL注入章节的学习。

知识点学习

消息钩子

这里主要是要弄明白Windows GUI程序的工作模式/流程。

GUI以事件驱动方式工作。核心概念:message queue

在这里插入图片描述

在这里插入图片描述

最具代表性的:MS提供的spy++

在这里插入图片描述

SetWindowsHookEX()

SetWindowsHookExA 函数 (winuser.h) - Win32 apps | Microsoft Learn

HHOOK SetWindowsHookExA(
  [in] int       idHook, 	// hook type
  [in] HOOKPROC  lpfn,   	// hook procedure 
  [in] HINSTANCE hmod,   	// hook procedure所属的DLL句柄 (Handle)
  [in] DWORD     dwThreadId // 待hook的线程ID
);

在这里插入图片描述

像这样,使用SetWindowsHookEX()设置好钩子后,

运行钩取示例 HookMain.exe

附件给的:

在这里插入图片描述

经测试,要在win7环境跑。

运行HookMain后打开notepad,再开Process Explorer。

选中notepad.exe CTRL+D

在这里插入图片描述

说明KeyHook.dll已经注入notepad.exe进程了。

然后HookMain.exe中输入q后就退出,KeyHook.dll也不在notepad.exe中了。

源码分析/书写

这一章的逆向都很简单,主要关注的是怎么自己写dll inject。

HookMain.cpp

// HookMain.cpp
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<Windows.h>

#define DLL_NAME "KeyHook.dll" // dll's name
#define HOOKSTART "HookStart" // start function in DLL
#define HOOKSTOP "HookStop" // stop function

typedef void(*P_FUNC)(); // 函数指针

int main() {
	HMODULE hDll = NULL;
	P_FUNC HookStart = NULL;
	P_FUNC HookStop = NULL;
	
	// 加载KeyHook.dll
	hDll = LoadLibraryA(DLL_NAME);

	// 获取导出函数地址
	HookStart = (P_FUNC)GetProcAddress(hDll, HOOKSTART);
	HookStop = (P_FUNC)GetProcAddress(hDll, HOOKSTOP);

	//
	HookStart();
	printf("press 'q' to quit!\n");
	while (_getch() != 'q');

	//
	HookStop();

	// 卸载KeyHook.dll
	FreeLibrary(hDll);
	return 0;
}

KeyHook.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

// KeyHook.cpp
#include<stdio.h>
#include<Windows.h>

constexpr auto PROCESS_NAME = "notepad.exe";
HINSTANCE hInstance = NULL;
HHOOK hHook = NULL;
HWND hWnd = NULL;

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

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    char szPath[MAX_PATH] = { 0 };
    char* p = NULL;

    if (nCode == 0) {
        // bit 31 —— 0 = key press   ;   1 = key release
        if ((lParam & 0x80000000) == 0) {
            GetModuleFileNameA(NULL, szPath, MAX_PATH); // 获取当前进程的可执行文件路径
            p = strrchr(szPath, '\\');
            
            // 比较当前进程名称,若为`notepad.exe`,则消息不会传递给下一个钩子。
            if (!_stricmp(p + 1, PROCESS_NAME))
                return 1;
        }
    }

    // 若不是`notepad.exe`,则将消息传递给下一个钩子。
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

#ifdef __cplusplus
extern "C" {
#endif
    __declspec(dllexport)void HookStart(){
        hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, hInstance, 0);
}
    __declspec(dllexport)void HookStop() {
        if (hHook) {
            // 注销挂钩
            UnhookWindowsHookEx(hHook);
            hHook = NULL;
        }
    }

#ifdef __cplusplus
}
#endif

KeybroadProc回调函数的说明:KeyboardProc 回调函数 - Win32 apps | Microsoft Learn

LRESULT CALLBACK KeyboardProc(
  _In_ int    code,  // HC_ACTION:0  HC_NOREMOVE:3
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

GetModuleFileNameA

GetModuleFileNameA 函数 (libloaderapi.h) - Win32 apps | Microsoft Learn

检索包含指定模块的文件的完全限定路径。 模块必须已由当前进程加载。

DWORD GetModuleFileNameA(
  [in, optional] HMODULE hModule, // 正在请求其路径的已加载模块的句柄。 如果此参数为 NULL, 则 GetModuleFileName 将检索当前进程的可执行文件的路径。
  [out]          LPSTR   lpFilename, // 指向接收模块的完全限定路径的缓冲区的指针。
  [in]           DWORD   nSize
);

CallNextHookEX

LRESULT CallNextHookEx(
  [in, optional] HHOOK  hhk, // 忽略此参数。
  [in]           int    nCode,
  [in]           WPARAM wParam,
  [in]           LPARAM lParam
);

SetWindowsHookExA

SetWindowsHookExA 函数 (winuser.h) - Win32 apps | Microsoft Learn

HHOOK SetWindowsHookExA(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId
);

两个源码写好后,先生成KeyHook.dll(注意选x86),将生成的dll放在HookMain的文件夹下,生成HookMain.exe。

但尝试运行:本地机直接卡炸。。(可能是写的有Bug)虚拟机的话缺库,跑不了。

看来后续得在win10虚拟机安个visual studio了。。

调试分析

这部分的dll都很简单,调试直接跟就行,就不展开了。

总结

逆向技术中极其重要的板块,Windows内网高级Bypass的基础。
Windows编程还很不熟悉,相应的API写法得多练习。

在这里插入图片描述

共勉!

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值