RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1604658
Accepted
Стас Палыч
Стас Палыч
Asked:2025-01-12 21:15:27 +0000 UTC2025-01-12 21:15:27 +0000 UTC 2025-01-12 21:15:27 +0000 UTC

函数指针二维数组 PVOID

  • 772

我正在使用 Detours 挂钩并尝试在二维数组中实现函数指针以DetourAttach按索引生成。我们拥有什么:

// объявление функции двойника
    HIMAGELIST WINAPI MyImageList_Create(
        int  cx,
        int  cy,
        UINT flags,
        int  cInitial,
        int  cGrow
    );
    
// объявление указателя на оригинальную функцию
static HIMAGELIST(WINAPI* actualImageList_Create)(int cx, int cy, UINT flags, int cInitial, int cGrow) = ImageList_Create;
    
// подключение хука на функцию
DetourAttach(&(PVOID&)actualImageList_Create, MyImageList_Create);

// описание функции двойника
HIMAGELIST WINAPI MyImageList_Create(
    int  cx,
    int  cy,
    UINT flags,
    int  cInitial,
    int  cGrow
)
{
    
    return actualImageList_Create(cx, cy, flags, cInitial, cGrow);
}

这个示例工作正常,但在使用许多函数钩子时不方便。有必要将指向 double 和原始函数的指针放置在二维数组中,以便通过索引连接钩子,如下所示: DetourAttach(functptr[0][0], functptr[0][1]); 因此,在 double 函数的描述中,也从数组中调用原始函数:索引是这样的: functptr[0][0](cx, cy, flags, cInitial, cGrow);

需要实施什么:

// объявление функции двойника
        HIMAGELIST WINAPI MyImageList_Create(
            int  cx,
            int  cy,
            UINT flags,
            int  cInitial,
            int  cGrow
        );

// Объявление целевого массива
PVOID(*functptr[][2]) = { { /*...*/ , (PVOID*)MyImageList_Create} };

// объявление указателя на оригинальную функцию,
// который надо разместить в массиве в первой колонке, 
// во второй колонке разместить указатель на функцию двойника
// ...

// подключение хука на функцию
DetourAttach(&(PVOID&)functptr[0][0], functptr[0][1]);

 // описание функции двойника
    HIMAGELIST WINAPI MyImageList_Create(
        int  cx,
        int  cy,
        UINT flags,
        int  cInitial,
        int  cGrow
    )
    {
        
        return functptr[0][0](cx, cy, flags, cInitial, cGrow);
    }

Detours 说明https://www.codeproject.com/Articles/30140/API-Hooking-with-MS-Detours

c++
  • 2 2 个回答
  • 86 Views

2 个回答

  • Voted
  1. Стас Палыч
    2025-01-14T16:45:07Z2025-01-14T16:45:07Z

    这就是我决定执行任务的方式。该代码是从其他人的项目中获取的,因此需要清理和更正一些内容。 DetoursHelper.hpp:

    #pragma once
    
    namespace MyProject::HookHelper
    {
        template <size_t hookCount, size_t possibleImportCount>
        using DetoursDispatcherDependency = std::array<std::tuple<std::array<std::string_view, possibleImportCount>, LPCSTR, PVOID, PVOID>, hookCount>;
    
        template <size_t hookCount, size_t possibleImportCount>
    
        struct DetoursDispatcher
        {
            const DetoursDispatcherDependency<hookCount, possibleImportCount>& DetoursDependency{};
            //std::array<std::pair<OffsetStorage, std::optional<OffsetStorage>>, hookCount> hookInfoCache{}; // iat mem offset
            std::array<std::pair<PVOID, std::optional<HMODULE>>, hookCount> hookTable{}; // iat org value
            std::array<size_t, hookCount> hookRef{};
            mutable wil::srwlock hookLock{};
            PVOID moduleAddress{};
            void CacheHookData()
            {
                /*auto dllPath{ wil::GetModuleFileNameW<std::wstring, MAX_PATH + 1>(reinterpret_cast<HMODULE>(moduleAddress)) };
    
                if (dllPath.empty())
                {
                    return;
                }*/
    
                PVOID* functionAddress{ nullptr };
                HMODULE* moduleHandle{ nullptr };
                
                auto imageMapper{ ImageMapper(dllPath) };
                
                /*auto initialize_offset_storage = [&](size_t index)
                    {
                        auto [possibleImport, functionName, detourFunction, typeFunction] {DetoursDependency[index]};
                        moduleHandle = GetModuleHandleW(L"user32.dll");
                        typeFunction = reinterpret_cast<decltype(&detourFunction)>(GetProcAddress(moduleHandle, functionName));
                        functionAddress = typeFunction;
                        hookInfoCache[index].first = moduleHandle;
                        hookInfoCache[index].second = functionAddress;
                        
                    };*/
    
                auto bind = [&](const std::pair<HMODULE*, PVOID*> value)
                    {
                        functionAddress = value.second;
                        moduleHandle = value.first;
    
                        return functionAddress != nullptr;
                    };
    
                for (size_t i = 0; i < DetoursDependency.size(); i++)
                {
                    auto [possibleImport, functionName, detourFunction, typeFunction] {DetoursDependency[i]};
                    for (auto importDll : possibleImport)
                    {
                        std::string dll{importDll};
    // здесь получаю указатель на оригинальную функцию
                        typeFunction = reinterpret_cast<decltype(&detourFunction)>(GetProcAddress(GetModuleHandleA(dll.c_str()), functionName));
                        if (typeFunction)
                        {
                            OutputDebugStringA(
                                std::format(
                                    "{} - {}  0x{:x} DetoursHelper\n",
                                    importDll,
                                    functionName,
                                    (DWORD)typeFunction
                                ).c_str()
                            );
                            
                            break;
                        }
                    }
                    
                }
                
            }
    
            bool IsHookEnabled(size_t index) const { auto lock{ hookLock.lock_shared() }; return hookRef[index] > 0; }
    
            bool EnableHook(size_t index, bool enable)
            {
                /*if (!moduleAddress)
                {
                    return false;
                }
    
                auto lock{ hookLock.lock_exclusive() };*/
    
    // защита от повторного вызова
                hookRef[index] += enable ? 1 : -1;
                bool hookChanged{ false };
                if ((enable && hookRef[index] == 1) || (!enable && hookRef[index] == 0))
                {
                    hookChanged = true;
                }
    
                auto& [functionAddressOffset, moduleHandleOffset] {hookInfoCache[index]};
                auto iatFunctionAddress{ reinterpret_cast<PVOID*>(functionAddressOffset.To(moduleAddress)) };
                auto iatModuleAddress{ moduleHandleOffset.has_value() ? std::optional{reinterpret_cast<HMODULE*>(moduleHandleOffset.value().To(moduleAddress))} : std::nullopt };
    
                /*DetourTransactionBegin();
                DetourUpdateThread(GetCurrentThread());
    
                DetourAttach(&(PVOID&)iatFunctionAddress, detourFunction);
    
                DetourTransactionCommit();*/
            }
            
            template <size_t index, typename T = PVOID>
            [[nodiscard]] __forceinline auto GetOrg() const { auto lock{ hookLock.lock_shared() }; return reinterpret_cast<T>(hookTable[index].first); }
            DetoursDispatcher(
                const DetoursDispatcherDependency<hookCount, possibleImportCount>& dependency,
                PVOID targetDll = nullptr
            ) : DetoursDependency{ dependency }, moduleAddress{ targetDll }
            {
            }
            DetoursDispatcher() = delete;
        };
    
        template <size_t hookCount, size_t possibleImportCount>
        DetoursDispatcher(
            const DetoursDispatcherDependency<hookCount, possibleImportCount>&,
            PVOID, PVOID
        ) -> DetoursDispatcher<hookCount, possibleImportCount>;
    
        template <typename TDetoursDispatcherDependency>
        struct TDetoursDispatcher;
    
        template <size_t hookCount, size_t possibleImportCount>
        struct TDetoursDispatcher<DetoursDispatcherDependency<hookCount, possibleImportCount>> { using type = DetoursDispatcher<hookCount, possibleImportCount>; };
    }
    

    WinHook.cpp:

    using namespace MyProject;
    namespace MyProject::WinHooks
    {
        using namespace std::literals;
    
        typedef int(WINAPI* TypeDrawTextW)(HDC hdc, LPCWSTR lpchText, int cchText, LPRECT lprc, UINT format);
        TypeDrawTextW actualDrawTextW = nullptr;
    // [еще аналогичные объявления  функций...]
    
    // заполнение массива данными
        HookHelper::DetoursDispatcherDependency g_DetoursDependency
        {
            std::tuple
            {
                std::array
                {
                    "user32.dll"sv,
                    "ext-ms-win-ntuser-draw-l1-1-0.dll"sv,
                    "ext-ms-win-ntuser-misc-l1-1-0.dll"sv
                },
                "DrawTextW",
                reinterpret_cast<PVOID>(MyDrawTextW),
                reinterpret_cast<PVOID>(actualDrawTextW)
            }
            /*std::tuple
            {
                std::array
                {
                    "module.dll"sv,
                    "module-ntuser-draw-l1-1-0.dll"sv,
                    "module-win-ntuser-misc-l1-1-0.dll"sv
                },
                "MoreFunc",
                reinterpret_cast<PVOID>(MyMoreFunc),
                reinterpret_cast<PVOID>(actualMoreFunc)
            }
            [...]*/
        };
    
        HookHelper::DetoursDispatcher g_DetoursDispatcher
        {
            g_DetoursDependency
        };
    
    }
    // кэшируем адреса функций, здесь переменным actualDrawTextW нужно присвоить значения
    g_DetoursDispatcher.CacheHookData();
    
    // подключаем хук
    g_DetoursDispatcher.EnableHook(index, attach);
    
    // проблема заключается в получении оригинальной функции 
    // для возврата из функции двойника.
    // Нужно реализовать одно из двух:
    // либо переменным actualDrawTextW присвоить значения в функции CacheHookData,
    // либо вернуть значения как в этом примере:
    int WINAPI WinHooks::MyDrawTextW(HDC hdc, LPCWSTR lpchText, int cchText, LPRECT lprc, UINT format)
    {
        auto actualDrawTextW{ g_DetoursDispatcher.GetOrg<index, decltype(&MyDrawTextW)>() };
        
        return actualDrawTextW(hdc, lpchText, cchText, lprc, format);
    }
    
    • 0
  2. Best Answer
    avp
    2025-01-13T05:16:16Z2025-01-13T05:16:16Z

    我没有 Windows,所以我可能搞砸了 Windows typedef 的建模。
    特别是,根据enSO 的建议,我们必须确定

    #define WINAPI __stdcall
    #define __stdcall
    

    在HIMAGELIST谷歌浏览后,我这样确定

    struct _IMAGELIST;
    typedef struct _IMAGELIST * HIMAGELIST;
    

    ——这就是答案——

    我认为首先,为了简化函数二维数组的描述,functptr[][2]值得为函数指针定义一个 typedef,我们将这种类型称为 -- img_foo_t。

    typedef HIMAGELIST  (WINAPI *img_foo_t)(int cx, int cy, UINT flags, int cInitial, int cGrow);
    

    之后我能够编译以下代码(使用您的函数)

    // объявление указателя на оригинальную функцию
    static HIMAGELIST
           (WINAPI *actualImageList_Create)(int cx, int cy, 
                                            UINT flags, int cInitial, int cGrow) = ImageList_Create;
    
    
    int
    main (int ac, char *av[])
    {
    
          
      // подключение хука на функцию
      // DetourAttach(&(PVOID&)actualImageList_Create, MyImageList_Create);
      DetourAttach((PVOID *)&actualImageList_Create, MyImageList_Create);
    
    
      img_foo_t functptr[][2] = {
        {ImageList_Create, MyImageList_Create}
      };
      DetourAttach((PVOID *)&functptr[0][0], functptr[0][1]);
    
      return 0;
    }
    

    请注意将第一个参数传递给 DetourAttach 的更改
    (我们实际上是使用函数指针传递变量的地址(如 Detours API Hooking 链接中所述))。

    PS 很明显,我使用了 ImageList_Create 和 DetourAttach 函数的存根。

    • -1

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5