在Matrix发布后,可以检查文件是否存在泄漏的问题,处于好奇,了解一下原理
通过Hook系统在本进程中的open
和close
、read
、write
这些系统函数,来了解打开的文件以及其是否被释放。由于只是Hook本App的系统调用,所以不需要Root权限也可以完成。
libopenjdkjvm.so
、libjavacore.so
、libopenjdk.so
三个so中,所以需要分别注入这些So文件\proc\self\maps
获取So对应的位置 fopen
传入文件路径以及rb
来打开maps
文件,b
模式代表读取二进制(binary)fgets
函数,读取\proc\self\maps
的每一行strchr
函数,找到-
出现的第一个位置rwx
rx
,如果不是的话,则越过该页面继续查找strstr
函数,比较该So的路径是否在maps
的这一行中strtoul
将该行的首地址根据16进制转换成虚拟地址loaded_soinfo
来保存已经打开的ELF文件信息loaded_soinfo
中Elf_Addr
对象,该数据结构代表占用4字节的地址,属性为soinfo->base
Elf_Ehdr
对象,该数据结构代表ELF文件的文件头,里面包含着程序头、Section节表的信息e_phoff
与e_shoff
找到ELF文件中的程序头与节头的地址soinfo->phdr
与soinfo->ehdr->phnum
找到Elf32_Phdr
的范围,也就是程序头表的范围Segment
的Type,计算类型为PT_LOAD
的Segment的偏移量以及FlagDYNAMIC
的Segment,计算dynamic segment的地址,以及数量DYNAMIC
段中的所有Elf_Dyn
,然后根据dyn->d_un.d_val
是否为DT_RELA
来表示该So是否使用了重定向表Elf_Dyn
数据结构中的d_tag
,来判断该Entity是哪种类型的,例如SYSTAB
,REL
,STRTAB
,HASH
等等
DYNAMIC
段中保存的是Elf_Dyn
的数组,所以可以根据p->vaddr
+p_memsz
得到DYNAMIC
段的总大小,再除以sizeof(Elf_Dyn)
,就能得到Elf_Dyn
的总数了
首先,需要定位函数名的符号地址,再替换rel
段中的函数地址
符号地址的定位有两种方式,通过Hash表查找,或者通过线性比较查找
name_hash%nbucket
得到函数名对应的符号链,ELF文件也是通过链式方法来解决hash冲突的Elf_Sym
的类型是否为STT_FUNCTION
,如果不是则继续Elf_Sym
的sys_name
与函数名是否匹配,如果匹配则代表找到了函数对应的Elf_Sym
结构soinfo->sym
开始遍历Elf_Sym
的类型是否为STT_FUNCTION
,如果是的话,则比较名字在找到目标函数的符号(对应的Elf_Sym
)之后,需要开始替换
REL
/RELA
表进行遍历Elf_Rel
/Elf_Rela
结构中的r_info
来获取函数的IndexElf_Sym
相同的Index,如果相同则认为找到了目标函数在重定向表中的位置mprotect
修改目标页面的权限至此So的Hook完成,目标函数也替换完成