kptr_restrict是什么?
从前文中我们知道,利用漏洞的时候往往需要知道内核内部指针的信息:不论是为了劫持他们,还是以一种受控的方式来打断它们。
众所周知:Linux内核有一个功能可以让它过滤掉一些地址,以此来避免将内核地址泄漏给潜在的攻击者。这个可配置的特性被称为“kptr_restrict”,这一功能在Android 内核的源码树中至少已经出现了2年了。
对于所有可配置的内核参数,有一个特殊的文件能设置该特性如何过滤这些内核地址。对于kptr_restrict而言,这个特殊的文件在“proc/sys/kernel/kptr_restrict”下,但有一些很高的权限设置。
事实上:只有root用户才能对它进行读写,其它的用户只能对它进行读取操作。
那么kptr_restrict是如何工作的了?首先,在输出的时候内核开发者需要一种方式来标记内核指针。这通过使用一种特殊的格式标识“%pk”来实现,它表示写到该处的值是内核指针,因此需要进行这些指针进行保护。
一共有三种值可以控制kptr_restrict提供的保护:
0.-该特性被完全禁止;
1-那些使用“%pk”打印出来的内核指针被隐藏(会以一长串0替换掉),除非用户有CAP_SYSLOG权限,并且没有改变他们的UID/GID(防止在撤销权限之前打开的文件泄露指针信息);
2.所有内核指使用“%pk”打印的都被隐藏。
该配置的默认值是通过CONFIG_SECURITY_KPTR_RESTRICT创建内核时提供的,但是所有我遇到的现代的Android设备,该值都被设置为了2。
然而,有多少内核开发者知道需要用”%pK”来保护内核指针了?通过grep正则在内核中查找这种格式的字符串就能容易的知道了。不言而喻,结果和预期的一样遭。
在内核源代码中,在23个文件中一共发现了35次。不用说,内核指针常常使用普通指针格式标识”%p”来打印-简单的搜寻就能发现成百上千处用“%p”显示指针的地方。
既然都已经说到这了,那我们就来讨论下为什么kptr_restrict本身提供的保护就不够。
Method #1 – 通过shell获得dmesg
所有通过内核打印的log消息都被写到一个环形缓冲区中,它位于内核内存中。用户可以通过调用””dmesg”(display message)命令来读取该缓冲区。该命令实际上通过调用sysylog系统调用,来访问该缓冲区,我们可以从如下strace输出中看到。
然而,syslog系统调用并