终于克服了拖延症写下了第一笔,前段时间看了Hooking Android System Calls for Pleasure and Benefit,于是就自己尝试着写了一下,综合了其他的思路改用动态获取sys_call_table的方法。思路简单,主要记录下遇到的问题。
定制内核
首先,为了必须使Kernel支持LKM,上文中给出的方法是在编译内核make defconfig之后,修改源码目录中的.config文件。这种方法修改的选项make时会被override。
回去看.config文件的已经被恢复,实际上选项并没有生效。更简单的方法是修改
在其中将MODULES,MODULE_UNLOAD添加到default y项中
定位sys_call_table
sys_call_table地址的获取方法有多种,如上文采用的/proc/kallsym读取的方法,还以从system.map读。这些方法原理已经已经很多,就不多说了。
这里我采用的是用sys_close偏移定位的方法。这种方法的原理是从PAGE_OFFSET开始暴力查找,从每一个地址找NR_close偏移处存储的是否是sys_close来判断当前地址是否是sys_call_table。测试过程中arm一切正常,但是在arm64下却会crash。经过一段时间的排查发现。arm64下由于进行arm兼容,多了一张compat_sys_call_table的表。在内存中它们的位置关系如下。
两张表中存储sys_close的相同,查找程序会先找到compat表中的sys_close,并且由于arm与arm64的系统调用号不同(查看对应的unistd.h确定),所以找到的地址既不是compat_sys_call_table也不是sys_call_table。根据内存的情况,扩展原来的定位方法,首先用arm的调用号确定compat_sys_call_table地址,在跳过这个地址继续暴力查找,用arm64的调用号确定sys_call_table的地址。
测试环境:android kernel 3.10 arm64
丑陋Code:ASyScallHookFrame