我正在编写一些 C 代码来将 .so ELF (共享库)的某些函数加载到内存中。
我的 C 代码应该能够重定向另一个加载到应用程序/程序内存中的 .so 库的导出函数。
这里有一些详细说明:
Android 应用程序将加载多个 .so 文件。我的 C 代码必须查看属于另一个共享 .so 库(在本例中称为 target.so)的导出函数
这不是常规的 dlsym 方法,因为我不仅想要函数的地址,而且想用我自己的函数替换它;其中:当另一个库调用它自己的函数时,我的 hook_func 会被调用,然后我应该从我的 hook_func 调用original_func。
对于导入功能,这可以工作。但对于导出功能我不知道该怎么做。
导入函数在符号表中具有相应的条目,在重定位表中具有相应的条目,最终给出全局偏移表(GOT)中的条目地址。
但对于导出函数,符号的 st_value 元素本身具有过程的地址,而不是 GOT 地址(如果我错了,请纠正我)。
我如何执行挂钩export功能?
理论上来说,我应该得到的内存位置st_value
动态符号表条目的元素(Elf32_Sym
)的导出功能。如果我获得该位置,那么我应该能够用我的 hook_func 的地址替换该位置中的值。但是,到目前为止我还无法写入该位置。我必须假设动态符号表的内存是只读的。如果这是真的那么这种情况下的解决方法是什么?
非常感谢您的阅读和帮助我。
Update:LD_PRELOAD只能用我自己的函数替换原来的函数,但是我不确定是否有任何方法可以调用原来的函数。
以我为例:
应用程序通过调用初始化音频引擎Audio_System_Create
并传递一个引用AUDIO_SYSTEM
反对Audio_System_Create(AUDIO_SYSTEM **);
AUDIO API 分配此结构/对象并返回函数。
现在如果我能访问它就好了AUDIO_SYSTEM
对象,我可以轻松地将回调附加到该对象并开始接收音频数据。
因此,我的最终目标是获得参考AUIOD_SYSTEM
目的;根据我的理解,只有当我拦截该对象首先通过分配的调用时,我才能得到这一点Audio_System_Create(AUIOD_SYSTEM **)
。
目前,在 android 上没有直接的方法来获取输出音频。 (所有示例都讨论仅录制来自麦克风的音频)
Update2:正如 Basile 在他的回答中所建议的,我使用了 dladdr() 但奇怪的是,它给了我与我传递给它的地址相同的地址。
void *pFunc=procedure_addr; //procedure address calculated from the st_value of symbol from symbol table in ELF file (not from loaded file)
int nRet;
// Lookup the name of the function given the function pointer
if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
{
LOGE("Symbol Name is: %s", DlInfo.dli_sname);
if(DlInfo.dli_saddr==NULL)
LOGE("Symbol Address is: NULL");
else
LOGE("Symbol Address is: 0x%x", DlInfo.dli_saddr);
}
else
LOGE("dladdr failed");
这是我得到的结果:
条目地址=0x75a28cfc
Entry_addr_through_dlysm =0x75a28cfc
符号名称为:AUDIO_System_Create
符号地址为:0x75a28cfc
这里通过dlysm得到的地址或者通过ELF文件计算得到的地址就是程序的地址;虽然我需要这个地址本身所在的位置;这样我就可以用我的地址替换这个地址hook_func
地址。dladdr()
没有做我认为会做的事情。