c - 使用 ptrace 查找 main 函数的开始

标签 c macos debugging ptrace

我有一个文件范围内核扩展,可以在应用程序启动时通知守护进程。守护进程需要在 main() 中的第一条指令开始时暂停启动的应用程序。

当使用 PT_ATTACH 调用 ptrace 时,守护进程似乎过早附加并且在动态链接器 (dyld) 中。

这是附加时线程 0 的调用堆栈的示例:-

Thread 0:
0   dyld                            0x00007fff6e4cd35e mach_reply_port + 10
1   dyld                            0x00007fff6e4cd4d4 _mig_init + 13
2   dyld                            0x00007fff6e4cd17f mach_init + 46
3   dyld                            0x00007fff6e4aa239 dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) + 411
4   dyld                            0x00007fff6e4aa05e _dyld_start + 54

因此,有没有办法确保守护程序可以在加载库完成后附加到主函数的开头,或者重复单步执行到该点,在这种情况下,我如何才能找到考虑到可能没有可用于已启动应用程序的符号,主要地址?

谢谢。

最佳答案

只是一个猜测,但由于 libc 必须在 main 之后调用 exit,您可能可以通过步行识别对 main 的调用_start 直到找到对 .text 部分的调用,然后是对 .plt 部分的调用。您还知道 main 的退出状态是 exit 的参数,因此您正在寻找 mov %eax, %edi 和可能 main_start 之后,而 .plt.text 之前,你知道两者都不会走得太远, 所以你可以让它变得非常通用。

鉴于运行时/libc/编译器是健全的(Mac OS X 基于 FreeBSD,对吗?),您可能只需匹配几个字节就可以逃脱,像这样(您可能至少应该增加一些安全性):

size_t *find_main_vmoffset(char *text_start, size_t text_size)
{
    char *p = text_start;

    const char sig[] = {
        /* 0xe8, ??, ??, */ 0, 0,       /* callq  main */
        0x89, 0xc7,             /* mov    %eax, %edi */ 
        0xe8, /* ??, ??, 0xff, 0xff, */     /* callq  exit */
    };

    while (p = memmem(p, text_size - (p - text_start), sig, sizeof(sig))) {
        /* Check it's one call followed by another */
        if (p[-3] != 0xe8)
            continue;
        /* Check the second call is backwards (into .plt) */
        if (p[7] != 0xff || p[8] != 0xff)
            continue;

        /* Eureka! */
        return (p - text_start) + 2 + *(int32_t *)(p - 2);
    }
    return 0;
}

你只需要添加.text的虚拟地址,你基本上就完成了:)。

关于c - 使用 ptrace 查找 main 函数的开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16524988/

相关文章:

java - 如何将所有值保存在内存中,并使用命令查看它们,就像在Matlab中调试一样

visual-studio - 使用 Firefox 作为默认浏览器的 VS2008 调试 - 如何使调试器在退出时停止/关闭?

c - -m32 在参数为 unsigned long long 时给出无法解释的问题

c++ - 热在多个显示器上播放高清视频

java - JDBC ODBC 驱动程序连接

macos - OS X - x64 : stack not 16 byte aligned error

java - Eclipse 调试器 "jumps"跳过重要代码

c++ - 在我的程序中分析 CPU 使用情况的最佳选择?

c - 将c字符串解析为指针数组时出现段错误

c - 如何计算链表中的节点数?为什么输出显示节点数为 '2' ?