Author: geneblue
Blog: https://geneblue.github.io/
在一些场景下,我们可以借助硬件断点技术分析kernel的某处地址是如何被更改的(读,写)。
何为硬件断点
程序员一般都熟知软件断点,所谓软件断点是指CPU通过指令来触发中断的行为,常见的调试器如gdb等,在对调试进程的某个函数下断点时,实际上是将该函数起始处的原始指令更改成了CPU的中断指令,当CPU执行到该中断指令时,进程处于停止状态,CPU会根据中断号发送给对应的中断处理例程,中断处理例程再发送信号给父进程(调试器)。调试器获取信号后,会还原断点处的原始指令,再使用一些系统调用获取子进程(被调试进程)的信息(寄存器等),以此达到调试的目的。这就是软件断点的简单过程。硬件断点不是在指令层面的监控,而是监控内存地址来触发断点的。所以支持在FLASH,ROM,RAM设断,只要是可访问的地址都行,只要监控地址的状态(读,写,执行)发生改变,就会触发断点,断点信息会以内核日志的形式呈现。
ARM Linux 硬件断点
现在 ARMV5 以上的 CPU都是支持硬件断点的,cpu提供了专用的硬件断点寄存器在来不断的匹配执行到的地址,当特定地址发生预设行为(读,写,执行)时,就会触发断点。在设定时可以设置监控的地址bit位,如按8位,16位,32位触发。
让 Linux Kernel 支持硬件断点,在编译内核时需要
CONFIG_HAVE_HW_BREAKPOIN
配置。 在 Android kernel
中,该配置不存在于menuconfig,需要手工加入到 arch/arm64/Kconfig.debug
中
1 | config HAVE_HW_BREAKPOINT |
在 menuconfig 中,将模块签名关闭 1
Main Menu/Enable loadable module support - Require modules to be validly signed
再编译内核模块
data_breakpoint
,我们就是通过该模块实现对监控地址的设定,代码位于
samples/hw_breakpoint
处将其中的 Makefile 更改如下:
Makefile 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24obj-m := data_breakpoint.o
KERNELDIR := /home/geneblue/Android/Source/kernel/android_msm_3.18_syzkaller/msm
PWD :=$(shell pwd)
ARCH=arm64
CROSS_COMPILE=/home/geneblue/tmp/android_kernel_build_toolchains/aarch64-linux-android-4.9/bin/aarch64-linux-android-
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CFLAGS_MODULE=-fno-pic
build:
make -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
push:
adb push data_breakpoint.ko /data/local/tmp/
install:
adb push data_breakpoint.ko /data/local/tmp/
adb shell su -c "insmod /data/local/tmp/data_breakpoint.ko ksym=selinux_enforcing"
# adb shell su -c "chmod 777 /dev/vuldev"
uninstall:
adb shell su -c "rmmod data_breakpoint"
clean:
rm -rf .tmp_versions
rm *.o *.ko *.mod.c *.order *.symvers
rm .*
可以根据自己需求更改
data_breakpoint.c
,下面是简单分析
1 | // 回调函数,当触发硬件断点时会执行该处 |