MS Detours 2.1 - 出栈

Posted

技术标签:

【中文标题】MS Detours 2.1 - 出栈【英文标题】:MS Detours 2.1 - Popping out of stack 【发布时间】:2011-06-05 20:26:41 【问题描述】:

我不会绕过扫雷中的 PlaySoundW 功能。 游戏一调用 PlaySoundW 函数就会崩溃。 如果我在代码中取消注释 Beep,游戏会发出哔哔声,然后崩溃。

现在代码正在从挂钩函数调用原始函数,所以它不应该做任何事情。但无论如何它都会崩溃。

你能告诉我有什么问题吗?

在 Olly 中调试应用程序后,我发现当 detour 处于活动状态时,并非所有垃圾都会从堆栈中弹出。 如何解决?

这是我的代码:

#include <Windows.h>
#include <tchar.h>
#include <detours.h>

namespace Hooks

    BOOL(__stdcall *OrgPlaySoundW)(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound) = &PlaySoundW;

    BOOL HookPlaySoundW(LPCTSTR pszSound, HMODULE hmod, DWORD fdwSound)
    
        //Beep(1000, 250);
        //return TRUE;
        return OrgPlaySoundW(pszSound, hmod, fdwSound);
    

    void DetourPlaySoundW(BOOL disable)
    
        if(!disable)
        
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourAttach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
            DetourTransactionCommit();
         else 
        
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourDetach(&(PVOID&)OrgPlaySoundW, &HookPlaySoundW);
            DetourTransactionCommit();
        
    


BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

    switch(fdwReason)
    
    case DLL_PROCESS_ATTACH:
        Hooks::DetourPlaySoundW(FALSE);
        break;
    case DLL_PROCESS_DETACH:
        Hooks::DetourPlaySoundW(TRUE);
        break;
    
    return TRUE;

【问题讨论】:

Detours 真的需要所有可怕的转换(尽管如此)吗? @Ben 是的,可怕的是一种观点,就像 Lisp 的括号一样。 @Seth:未定义的行为不是观点。函数指针和void* 之间的转换是未定义的行为。该代码不是有效的 C++。他们至少应该使用FARPROC(如GetProcAddress 返回),它保证是函数指针的正确大小。 @Ben 当人们说未定义的行为时,他们的意思是标准没有定义应该发生什么,因此编译器编写者可以决定发生什么吗?在任何情况下,它都有效。 @Seth:该标准有另一个名称:实现定义的行为。实际上,这是正确的术语,而不是未定义的行为。 “有条件地支持将函数指针转换为对象指针类型或反之亦然。这种转换的含义是实现定义的,除非实现支持双向转换,将一种类型的纯右值转换为另一种类型并返回,可能具有不同的 cv- 限定,应产生原始指针值。" 【参考方案1】:

尝试将HookPlaySoundW的调用约定设置为__stdcall(因为PlaySoundW的CC也是__stdcall(来自Windows.h):WINMMAPI BOOL WINAPI PlaySoundW( __in_opt LPCWSTR pszSound, __in_opt HMODULE hmod, __in DWORD fdwSound);)。

我之前和之后都曾绕过弯路,随便一瞥,除了我上面提到的之外,一切看起来都是正确的。如果这不能解决您的问题,我很乐意做进一步的调查。

Visual C++ 的默认设置是 __cdecl,其中 call*er* 清理堆栈,但在 __stdcall 中, call*ee* 清理堆栈在堆栈上。这可能是(可能是)所有“垃圾从堆栈中弹出”的原因。

【讨论】:

以上是关于MS Detours 2.1 - 出栈的主要内容,如果未能解决你的问题,请参考以下文章

Delphi 如何与 Detours 库互操作?

Linux Ubuntu下的绕行功能

MS Detours - DetourAttach 失败

Microsoft Detours 2.1简介

MS Detours库,绕行非win api函数

EasyHook库系列使用教程之四钩子的启动与停止