1

我正在构建一个需要修改某些仿生方法(例如 getaddrinfo、__android_print)行为的项目。我已经能够使用独立编译器或使用 Cmake 将其直接包含在 Apk 中来创建挂钩库。我已经能够使用 setprop wrap.com.foo.bar 和 LD_PRELOAD 预加载共享库,它正在工作并且我得到了我想要的结果。但是,我想以编程方式预加载挂钩库,因此每次重新启动设备后,我都不需要执行 LD_PRELOAD(又名禁用 SELinux、root 设备、setprop)的特定步骤。

我尝试使用

// MainActivity
companion object {
   System.load("/data/data/com.foo.bar/lib/libhookedmethod.so")
}

但我没有看到该方法被替换。

作为参考,钩子方法相当简单。这是一个极端的简化:


int __android_print(varargs a) {
   int realmethod(...);
   realmethod = dlsym("__android_print");
   doStuff();
   int res = realmethod(a) ;
   return res;
}

同样,编译和使用 LD_PRELOAD 有效,但我想在不使用 LD_PRELOAD 的情况下实现它......任何有帮助!提前致谢

4

1 回答 1

0

通过LD_PRELOAD要求动态加载器先加载引用的库来工作。加载器通过按加载顺序搜索加载的库来解析对给定符号的引用。

一旦一个符号被解析到一个特定的库,在这个过程中它不会被重新绑定到其他库。

上面的解释应该很明显为什么在程序已经运行libhookedmethod.so 之后加载没有效果。

关于实现所需目标的唯一方法是setenv()(如果尚未设置)并重新exec()执行当前流程。像这样的东西:

int main(int argc, char *argv[])
{
  char *e = getenv("LD_PRELOAD");
  if (e == NULL || /* any other checks that show LD_PRELOAD to not be as we want it */) {
    setenv("LD_PRELOAD", ..., 1);
    execvp(argv[0], argv);
  }
  // LD_PRELOAD is to our liking. Run the actual program.
  ...
}
于 2021-07-16T03:36:17.913 回答