被 Riru-hide 隐藏后的 so 会以匿名内存的形式存在。那么问题来了.
Riru-hide 是怎么做到匿名内存的,Riru-hide 还又什么隐藏手段呢?
关于 hide 的代码在 hide_utils.h 里.
1 |
|
分别来看一看
PrepareMapsHideLibrary
1 | void PrepareMapsHideLibrary() { |
这个函数仅加载 libriruhide.so 和填充 riru_hide_func, 无隐藏代码.
HideFromMaps
1 | void HideFromMaps() { |
继续跟进 hide::HidePathsFromMaps
1 | void HidePathsFromMaps(const std::set<std::string_view> &names) { |
继续跟进 riru_hide
1 | int riru_hide(const std::set<std::string_view> &names) { |
跟进 do_hide
1 | static int do_hide(hide_struct *data) { |
这里就可以看明白了,maps 的隐藏就是先把原来 so 给取消映射,然后在原位置重新匿名映射,再通过 backup 内存把原 so 内存 copy 过去.
HideFromSoList
这个代码的调用链是 nativeSpecializeAppProcess_post->Entry::Unload->hide::HideFromSoList.
1 | void HideFromSoList() { |
1 | static void RemoveFromSoList(const std::set<std::string_view> &names) { |
1 | void RemovePathsFromSolist(const std::set<std::string_view> &names) { |
1 | bool solist_remove_soinfo(soinfo *si) { |
哈,HideFromSoList 其实就是一个链表的隐藏,那么又是哪个链表呢?
注意到 solist 就是那个全局链表
1 | const auto initialized = []() { |
solist 其实就是 linker 的一个全局符号__dl__ZL6solist. 它是一个 soinfo 结构的链表,记录了所有 linker 加载的模块的信息.
到这里应该就明白了,HideFromSoList 去掉了 linker 里的全局 soinfo 链.
总结
Riru-hide 从两个地方进行了隐藏,分别是 maps 和 soinfo.