如何使用 DetourAttachEx 创建蹦床函数? (有MS绕路)

发布于 2024-10-05 13:26:02 字数 774 浏览 7 评论 0原文

我有一个 dll,我希望绕道其导出函数之一,

  • 该 dll 不是 Windows 的一部分。
  • 我需要能够在绕道后调用真实函数(从绕道调用真实函数)
  • 我知道该函数的确切签名。
  • 我已经能够绕过该函数,但现在我无法调用真正的函数。

我意识到我需要使用蹦床功能,我在网上看到了例子。 问题是:所有这些示例都展示了如何绕过 Windows API 函数,我需要对通过 dll 导入获得的函数执行相同的操作。

欢迎任何帮助

--编辑 只是为了澄清一下,我尝试通过指针调用原始函数,但这不起作用。 的方法

还尝试使用此堆栈溢出 文章中 甚至没有崩溃,但看起来它进入了无限循环(我假设是因为在原始函数中存在跳转到绕道的函数)

编辑 - 解决了! 不知道是什么解决了它, 使用作为参考。

  • 停止使用 getProcadder 并开始使用 DetourFindFunction 来
  • 清理代码(很确定我清理了导致问题的任何内容)

有效, 无论如何,谢谢

I have a dll and i wish to create a detour to one of its exported functions,

  • The dll is not part of windows.
  • I need to be able to call the real function after my detour (call the real function from a detoured one)
  • I know the exact signature of the function.
  • I already have been able to detour the function, but right now i can't call the real one.

I realize i need to use a trampoline function, I've seen examples online.
the problem is: all those examples show how to detour a windows API function, i need to do the same for a function i get thorough a dll import.

any help would be welcomed

--edit
just to clarify, I have attempted to call the original function by its pointer, but that does not work.
also tried using the method from this stack overflow article

that doesn't even crash but it looks like it goes into to an infinite loop (i assume because in the original function there is a jump to the detoured one)

edit -- solved!
not sure what solved it,
used this as reference.

  • stopped using getProcadder and instead started using DetourFindFunction instead
  • cleaned up the code (pretty sure i cleaned out whatever caused the issue)

works,
thanks anyway

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

傾旎 2024-10-12 13:26:02

我不使用弯路(我实际上讨厌它!),但绕道任何不可热修补的函数可以通过通用方式完成,如下所示:

步骤 1:
在函数开头插入 JMP,需要 5 个字节,可能需要多一点以与最近的指令对齐。例如,

要挂钩的函数的开头:

SUB ESP,3C
PUSH EDI
PUSH ESI
//more code

将变为:

JMP MyFunction
//more code

通过在第一个字节写入 0xE9 然后写入值 (function_addr - patch_addr + sizeof(INT_PTR))< /code> 在下面的 DWORD 中。使用 VirtualProtectEx 设置读/写/执行权限后,应使用 WriteProcessMemory 完成写入

步骤 2:
接下来,我们创建一个程序集接口:

void __declspec(naked) MyFunc()
{

    __asm
    {
        call Check             ;call out filter func
        test eax,eax           ; test if we let the call through
        je _EXIT
        sub esp,3c             ; its gone through, so we replicate what we overwrote
        push edi
        push esi
        jmp NextExecutionAddress ; now we jump back to the location just after our jump
    _EXIT:
        retn                   ; note, this must have the correct stack cleanup
    }

}

NextExecutionAddress 需要在运行时使用 ModuleBase + RVA 填充。


说实话,更简单,也更好(!),只需 EAT(导出地址表)挂钩 dll 的导出表,或者 IAT(导入地址表)挂钩调用您想要过滤的函数的导入表。 Detours 应该有这些类型的钩子的函数,如果没有,还有其他免费可用的库可以做到这一点。

另一种方法是使用 detour 来挂钩应用程序中的每个调用,使用 dll 将它们重新路由到您自己代码中的代理函数,这样做的优点是允许仅过滤某些调用,而不是二进制文件中的所有调用(可以使用 _ReturnAddress 执行相同的操作,但这需要更多工作),但缺点是捕获要修补的位置(我使用 ollydbg + 自定义修补引擎)并且它无法在非- 常规调用约定函数(例如在 Watcom 中使用 #pragma aux 进行的调用或由 VC7+ 生成的优化调用)。

需要注意的一件重要事情:如果您挂钩多线程应用程序,则需要在应用程序挂起的情况下完成修补程序,或者使用 InterlockedExchangeInterlockExchange64以原子方式完成InterlockedExchangePointer(我对所有 IAT/EAT 挂钩使用后者,特别是从“第三方进程”挂钩时)


查看您链接到的帖子,我认为那里的方法很糟糕,主要是由于汇编:P 但是,你如何调用你获得的这个指针,它是如何获得的?

I don't use detours(I actually detest it!), but detouring any non hot-patchable function can be done in a generic manner, like so:

Sstep 1:
insert a JMP <your code> at the start of the function, takes 5 bytes, probably a little more to align to the nearest instruction. as an example

the start of the function to hook:

SUB ESP,3C
PUSH EDI
PUSH ESI
//more code

would become:

JMP MyFunction
//more code

one would do this by writing 0xE9 at the first byte then writing the value (function_addr - patch_addr + sizeof(INT_PTR)) in the following DWORD. writing should be done using WriteProcessMemory after setting Read/write/execute permissions with VirtualProtectEx

Step 2:
next, we create an assembly interface:

void __declspec(naked) MyFunc()
{

    __asm
    {
        call Check             ;call out filter func
        test eax,eax           ; test if we let the call through
        je _EXIT
        sub esp,3c             ; its gone through, so we replicate what we overwrote
        push edi
        push esi
        jmp NextExecutionAddress ; now we jump back to the location just after our jump
    _EXIT:
        retn                   ; note, this must have the correct stack cleanup
    }

}

NextExecutionAddress will need to be filled at run time using ModuleBase + RVA.


To be honest, its way easier, and better(!) to just EAT (Export Address Table) hook the export table of the dll, or IAT (Import Address Table) hook the import tables of whats calling the funcs you want to filter. Detours should have functions for these type of hooks, if not, there are other freely available libs to do it.

The other way would be to use detour to hook every call in the apps using the dll to reroute them to a proxy function in your own code, this has the advantage of allowing one to filter only certain calls, and not everything across a binary(it is possible to do the same using _ReturnAddress, but thats more work), the disadvantage though is capturing the locations to patch(I use ollydbg + a custom patching engine) and it won't work on non-regular calling convention functions(like those made with #pragma aux in Watcom or the optimized calls generated by VC7+).

One important thing to note: if your hooking a multithreaded app, your patches need to be done with the app suspended, or be done attomically use InterlockedExchange, InterlockExchange64 and InterlockedExchangePointer(I use the latter for all IAT/EAT hooks, especially when hooking from a 'third party process')


Looking at the post you link to, the method there is horrible in my opinion, mainly due to the assmebly :P but, how are you calling this pointer you obtain, and how is it obtained?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文