如何找到C程序的"退出"

lll*_*lll 5 c linux binary assembly

测试是在32-bit x86Linux上进行的.

所以基本上我试图通过在汇编代码中插入检测指令来记录执行的基本块的信息.

我的策略是这样的:在globl数组中写入已执行的基本块的索引,并在阵列已满(16M)时将数组从内存刷新到磁盘.

这是我的问题.当检测二进制文件的执行结束时,我需要将数组刷新到磁盘,即使它没有达到16M边界.但是,我只是不知道从哪里找到assembly程序的退出.

我试过这个:

  1. grep exit从目标汇编程序中,并在call exit指令之前刷新内存.但是根据一些调试经验,目标C程序,比如md5sum二进制文件,exit在完成执行时不会调用.

  2. main功能结束时冲洗内存.但是,在汇编代码中,我只是不知道main函数的确切结束在哪里.我可以做一个保守的方法,比如说,寻找所有的ret指令,但在我看来,并非所有的main函数都以ret指令结束.

所以这是我的问题,如何识别a的确切执行结束assembly code,并在那里插入一些仪表指令?挂钩一些库代码对我来说很好.我理解不同的输入,二进制可以退出不同的位置,所以我想我需要一些保守的估计.我清楚了吗?谢谢!

Bas*_*tch 4

我相信在一般情况下你不能这样做。首先,如果main返回一些代码,则它是一个退出代码(如果main没有显式的,return则最近的 C 标准要求编译器添加一个隐式的 return 0;)。然后,函数可以存储exit某些数据中的地址(例如全局函数、a 中的字段struct,...),而其他一些函数可以通过函数指针间接调用它实际上,程序可以使用名称加载一些插件dlopendlsym或者"exit"简单地exit在插件内部调用,等等...AFAIUexit完全一般性地解决该问题(在动态意义上找到实际调用)可以证明相当于停止问题。另请参见赖斯定理

在不要求详尽的方法的情况下,我会建议其他方法(假设您对用 C 或 C++ 等编码的程序感兴趣......其源代码可供您使用)。您可以使用MELT自定义 GCC 编译器,以更改 GCC 内部处理的基本块,以调用一些检测函数。这并不简单,但它是可行的......当然,您需要使用这样一个定制的 GCC 重新编译一些 C 代码来对其进行检测。

(免责声明,我是MELT的主要作者;请随时与我联系以获取更多信息......)

顺便说一句,你知道atexit(3)吗?它可能对您的刷新问题有所帮助...并且您还可以使用LD_PRELOAD技巧(阅读有关动态链接器的信息,请参阅ld-linux(8))。