Detours学习5 - 进程内使用Detours

在进程内使用Detours来拦截用户函数

前面写4篇关于Detours的文章,主要是来自官方ReadMe的翻译和少量自己的理解

C++包管理器

用于 Windows、Linux 和 macOS 的 C++ 包管理器

写了比较长时间的C#,已经离不开Nuget这种包管理利器了,当再次使用C/C++时,那种下载源代码、看ReadMe、找依赖包、编译...一阵心乱如麻,在Google胡乱搜索了一通,发现C++也有了一些包管理的方案,后面就留意到VcPkg这个由微软以MIT协议开源的C++包管理。

下面就用VcPkg先安装Detours并集成到VS2019中

./VcPkg.exe install detours:x86-windows
./VcPkg.exe install detours:x64-windows
./VcPkg.exe integrate install

查看项目属性页可以看到vcpkg的选项

关于VcPkg的更多信息请查看微软官方文档


顺便提一下C/C++宏定义

这个特性真的是让人又爱又恨,写得过于复杂阅读性就差了,简单使用提供了方便,至于那个可以省去函数入栈出栈的开销我可没有那么关心

  1. 字符串化 #

    将宏定义中传参数名转化成用""包起来。

    #define LOGW(str) printf("W: %s\n", #str)

    它会忽略传入参数前面和后面的空格;当传入参数中间存在空格时,预处理器会自动连接各个子字符串,用一个空格连接子字符串。

    LOGW( 1 324 a bc );
    // 将预处理为
    printf("W: %s\n", "1 324 a bc");
  2. 符号连接 ##

    连接各个子部分,## 前后的空格可有可无,如:a##ba ## b是一样的意义。另外,如果##后的部分本身也是一个宏的话,##将会阻止后面这个宏的展开。

  3. 字符化 #@

    将传入的单字符转化成用''包起来。

    #define MAKECHAR(c) #@c
    // 将c赋值为'A'
    char c = MAKECHAR(A);

有时间遇到一些费解的宏定义时的确会比较头大,遇到那种情况可以将宏定义展开后再阅读一下,vs的加上/EP选项,不使用 #line 指令预处理到 stdout。关于/EP选项和更多编译/连接选项请查看微软官方文档


建立工程编写代码

│ Detour.cpp
│ Detour.h
│ DetourProcessInside.cpp
│ DetourProcessInside.vcxproj
│ DetourProcessInside.vcxproj.filters
│ DetourProcessInside.vcxproj.user
  1. Detour.h

    #pragma once
    class Detour
    {
    void* targetPtr;
    void* detourFunc;
    public:
    Detour(void* src, void* dest);
    ~Detour();
    };
    #define DETOURS(src, dest) Detour instance(src, dest)
  2. Detour.cpp

    #include "Detour.h"
    #include <Windows.h>
    #include <detours/detours.h>
    Detour::Detour(void* src, void* dest):
    targetPtr(src), detourFunc(dest)
    {
    DetourRestoreAfterWith();
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&targetPtr, detourFunc);
    DetourTransactionCommit();
    }
    Detour::~Detour()
    {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&targetPtr, detourFunc);
    DetourTransactionCommit();
    }
  3. 入口函数文件

    #include <iostream>
    #include <Windows.h>
    #include "Detour.h"
    double Add(double a, double b);
    double(__cdecl* targetPtr)(double, double) = Add;
    double Add(double a, double b)
    {
    return a + b;
    }
    double hkAdd(double a, double b)
    {
    std::cout << "The source function has been detoured" << std::endl;
    return 9527;
    }
    int main()
    {
    //DETOURS(targetPtr, hkAdd);
    auto pd = new Detour(targetPtr, hkAdd);
    std::cout << "1 + 1 = " << Add(1, 1) << std::endl;
    std::cout << "...Now Restore" << std::endl;
    delete pd;
    std::cout << "1 + 1 = " << Add(1, 1) << std::endl;
    std::cout << "Press Escape To Exit..." << std::endl;
    while (true)
    {
    if (GetAsyncKeyState(VK_ESCAPE))
    {
    break;
    }
    }
    return 0;
    }
  4. 输出结果,不是1 + 1 = 2而是1 + 1 = 9527,调用函数Add(1, 1)时跳转到hkAdd(1, 1)

    The source function has been detoured
    1 + 1 = 9527
    ...Now Restore
    1 + 1 = 2
    Press Escape To Exit...
posted @   非法关键字  阅读(763)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示