代码之家  ›  专栏  ›  技术社区  ›  user6567423

操纵x64展开信息以匹配程序集挂钩

  •  0
  • user6567423  · 技术社区  · 7 年前

    编辑:我似乎弄错了,回溯在Linux上的任何地方都能很好地工作——只有当从ubuntu上的gdb到远程windows进行远程调试时,在msvcrt中输入一个内存分配函数后,stacktrace才会被彻底销毁。。。该死的微软。

    这在64位和32位的窗口中都会发生,所以我不确定这是否与释放信息有关。。。

    编辑:似乎添加-g3和-Og在某些程序中帮助解决了部分问题,但问题仍然存在于其他程序中,无法在此处发布其源代码,因为它是我公司的IP—抱歉!

    背景

    我用gcc编译ubuntu->ubuntu,用mingw编译ubuntu->windows。

    我已经创建了一个跨平台(linux+windows)内存跟踪和泄漏检测库,它在第一条指令上用程序集bytepatch(而不是IAT/PLT hooking)钩住malloc/calloc/realloc/free。

    钩子重定向到一个门,该门检查钩子是否在当前线程中被启用,如果它们被启用,则重定向到内存跟踪钩子函数,否则如果它们在该线程中被禁用,则只重定向到实际函数的蹦床。

    这个库工作得很好,可以在linux/windows上检测到漏洞(可能在mac上也可以,但我没有)。

    我使用该库以编程方式检测代码中的泄漏,我可以在内存分配例程上安装回调,并以编程方式在回调中引发断点(通过循环并等待调试器附加,然后执行asm(“int3”)),这样我就可以在程序位于泄漏内存的调用中时附加到程序。

    在我尝试从回调中查看回溯之前,一切都很正常,我知道这可能是因为展开信息可能不再与堆栈匹配,因为我通过插入的hook例程插入了新的帧和数据。

    编辑:如果我是错误的关于释放信息不匹配的堆栈是不正确的回溯的原因,那么请纠正我的错误!

    问题

    有没有什么小技巧可以让GDB从钩子回调中正确地重建回溯?

    我知道我可以用libdwarf之类的工具手动行走和编辑放松信息,但我想那会非常麻烦和庞大。

    所以我想知道是否有一个黑客或欺骗我可以做,这将诱使GDB正确地重建回溯?

    如果没有简单的黑客或技巧,那么我有什么办法来解决这个问题?

    编辑:只是为了理清所有事情的确切通话顺序:

    program
       V
    malloc
       V
    hook_malloc -> hooks are disabled -> return malloc trampoline -> real malloc > program
       V
    hooks are enabled 
       V
    Call original malloc -> malloc trampoline -> real malloc -> returns to hook
       V
    Record memory size/info etc from malloc
       V
    Call user defined callback -> **User defined callback* -> returns to hook
       V
    return to program
    

    它是“用户定义的回调”,我想在这里捕获回溯

    1 回复  |  直到 7 年前
        1
  •  -1
  •   user6567423    7 年前

    显然这是同一个问题 GDB Windows ?? in Backtraces

    编辑:没关系,这不是全部答案。似乎此修复对某些测试程序有效,但其他程序仍显示不正确的回溯,如:

    (gdb) bt
    #0  malloc_callback (s=38, rv=0x2c5058) at test_dll.c:729
    #1  0x000000000040731d in hook_malloc_raw (file=0x410ea1 <__FUNCTION__.63079+55> "", function=0x410ea1 <__FUNCTION__.63079+55> "", line=0, s=38, rv=8791758343065)
    #2  0x0000000000407367 in hook_malloc (s=38)
    #3  0x000007fefda20b9e in ?? ()
    #4  0x0000000000000026 in ?? ()
    #5  0x0000000000410ea1 in __FUNCTION__.63079 ()
    #6  0x0000000000000000 in ?? ()
    

    显然,第4帧实际上不是堆栈帧,我也不知道为什么第5帧被标记为“函数63079”。

    社论2:如果人们要否决这一点,至少要留下评论,说明原因

    推荐文章