基于块设备的Linux内核内存监视模块
Table of Contents
就在完成了支持Linux 5.10的ramdisk驱动模块后不久,突发奇想,既然之前提到Linux内核模块之间地址空间是完全共享的,那么可以编写一个模块,通过块设备驱动的方式来直接对内存进行读写。
因此,我便对之前块设备驱动的代码做了些许改动,编写了一个新的模块,名为spy
。
于是我便尝试从新的模块对之前的ramdisk
模块进行一个数据盗取。
获取数据的地址
Linux内核本身提供了一个查看内核符号的接口,位于/proc/kallsyms
,我们只需要将它cat
出来然后用grep
选择我们所需的数据即可。
$ sudo cat /proc/kallsyms | grep myramdisk
ffffffffc0bd8024 r _note_7 [myramdisk]
ffffffffc0bd7000 t myramdisk_queue_rq [myramdisk]
ffffffffc0bd900c d __warned.0 [myramdisk]
ffffffffc0bd8180 r myramdisk_mq_ops [myramdisk]
ffffffffc0bd8200 r myramdisk_fops [myramdisk]
ffffffffc0bd7272 t myramdisk_exit [myramdisk]
ffffffffc0bd80d2 r .LC1 [myramdisk]
ffffffffc0bd8278 r myramdisk_dev_size [myramdisk]
ffffffffc0bd9040 d __this_module [myramdisk]
ffffffffc0bd7272 t cleanup_module [myramdisk]
ffffffffc0bd9400 b myramdisk_devs [myramdisk]
ffffffffc0bd9680 b myramdisk_major [myramdisk]
然后我们已知,myramdisk_devs结构体长这样:
struct myramdisk_dev {
unsigned char *data;
struct request_queue *queue;
struct gendisk *gd;
struct blk_mq_tag_set tag_set;
} myramdisk_devs[myramdisk_ndev];
可见,如果我们要盗取data指针的数据,那么偏移量为0,但是需要访问1次嵌套指针。
使用我写的玩具spy模块
根据参数定义,使用如下:
sudo insmod spy.ko spy_addr=ffffffffc0bd9400 spy_ptr_nested=1
测试数据盗取效果
注:需要先写入数据再加载模块,否则可能会受到缓存影响。
$ sudo dd if=/dev/urandom of=/dev/myramdisk0 bs=1M count=16
16+0 records in
16+0 records out
16777216 bytes (17 MB, 16 MiB) copied, 0.438467 s, 38.3 MB/s
$ sudo md5sum /dev/myramdisk0
7a1715b7fdc38fd7923e7f7e410cee30 /dev/myramdisk0
$ sudo insmod spy.ko spy_addr=ffffffffc0bd9400 spy_ptr_nested=1
$ sudo md5sum /dev/spy0
7a1715b7fdc38fd7923e7f7e410cee30 /dev/spy0
可以看到,创建的spy完全复制了ramdisk模块的内存,测试成功。
注意事项
需要注意内存访问越界导致Page Fault,进而导致模块崩溃的问题。请注意设置spy_dev_size
参数。
成品代码
https://github.com/cyyself/simple-linux-kernel-module/tree/master/kernel_spy