kprobes

Linux kprobes调试技术用于跟踪内核函数执行状态所设计的一种轻量级内核调试技术。利用这个技术,可以在大部分函数中动态的插入探测点来收集所需的调试状态信息,而不会影响内核原有的执行流程。

目前提供三种技术:

kprobe:可以在任意的位置放置探测点,提供探测点调用前pre_handler、调用后post_handler和内存访问出错fault_handler

A Kprobe is a general purpose hook that can be inserted almost anywhere in the kernel code. To allow it to probe an instruction, the first byte of the instruction is replaced with the breakpoint instruction for the architecture being used. When this breakpoint is hit, Kprobe takes over execution, executes its handler code for the probe, and then continues execution at the next instruction.

jprobe:获取被探测函数的入参值

kretprobe:用于获取被探测函数的返回值

A return probe, also called a kretprobe, attaches to the entry point of a function like a regular Kprobe. When the function is called, the return probe gets the return address and replaces it with a trampoline address. When the function exits, it returns to the trampoline address instead of where it was originally set to return, and the handler code for the probe is called. Return probes have access to the return values from functions.

SystemTap

SystemTap框架允许用户开发简单的脚本来调查和监视内核空间发生的内核函数、系统调用和其它事件。支持kprobe和kretprobe两种模式

官方文档

https://sourceware.org/systemtap/SystemTap_Beginners_Guide/

下载符号

SystemTap下载路径

https://sourceware.org/systemtap/ftp/releases/

Cuckoo中SystemTap可能是基于3.1版本制作得patch,但最新版本有出入,需要自己手动修改一波。

Ubuntu的符号主要从下方的链接来搜索,1604 Xenial、1804 Bionic、2004 Focal

https://launchpad.net/ubuntu

linux-image-4.15.0-45.48-generic-dbgsym_4.15.0-45.48~16.04.1

CentOS可以试一试下面的:

http://debuginfo.centos.org
http://mirror.facebook.net/centos-debuginfo
http://linuxsoft.cern.ch/centos-debuginfo

kernel-debuginfo-common-x86_64-3.10.0-693.el7.x86_64.rpm
kernel-debug-debuginfo-3.10.0-693.el7.x86_64.rpm
kernel-debuginfo-3.10.0-693.el7.x86_64.rpm

下载调试符号,查看系统版本号uname -r

安装的系统调试符号,以查看cat /proc/version_signature为准:

Ubuntu 4.15.0-45.48~16.04.1-generic 4.15.18

此时,需要寻找的符号:linux-image-4.15.0-45.48-generic-dbgsym_4.15.0-45.48~16.04.1

下载地址:https://launchpad.net/ubuntu/xenial/i386/linux-image-4.15.0-45-generic-dbgsym/4.15.0-45.48~16.04.1

搜索:linux-image generic-dbgsym 4.15.0-45.48~16.04.1,注意16.04.1这个一定要匹配哈,不然后续的测试是不行的。

http://ddebs.ubuntu.com/pool/main/l/linux/

http://ddebs.ubuntu.com/pool/main/l/linux-hwe/

安装符号

sudo dpkg -i linux-image-4.15.0-45-generic-dbgsym_4.15.0-45.48_16.04.1_i386.ddeb

检查符号是否正确安装

sudo ./stap-prep

编译

安装依赖

sudo apt-get install -y linux-headers-$(uname -r)

sudo apt-get install -y gcc zlib1g zlib1g-dev m4 libdw-dev

下载elfutils

https://sourceware.org/elfutils/ftp/

https://sourceware.org/elfutils/ftp/0.176/

tar -xjf elfutils-0.176.tar.bz2

编译systemtap

./configure --with-elfutils=./elfutils-0.176

make all

make install

编译成功后,开始测试.

第一步,只要systemtap安装正确,这一步不会有太大问题

sudo stap -ve 'probe begin { log("hello systemtap!") exit() }'

第二步测试,如果前序的符号未正确安装,会报错:

sudo stap -v -e 'probe vfs.read {printf("read performed\n"); exit()}'

输出的结果,输出Pass5 表明SystemTap能够成功创建检测内核、运行检测、检测正在被检测的事件,并执行有效的处理程序。

Pass 1: parsed user script and 468 library scripts using 61908virt/56876res/4820shr/52468data kb, in 70usr/150sys/224real ms.
Pass 2: analyzed script: 1 probe, 1 function, 5 embeds, 0 globals using 183516virt/180216res/6464shr/174076data kb, in 2010usr/730sys/2811real ms.
Pass 3: translated to C into "/tmp/stapS0KsUq/stap_9ac881f11ee69cd94f1188a34bfa71c8_2634_src.c" using 183516virt/180344res/6592shr/174076data kb, in 0usr/0sys/6real ms.
Pass 4: compiled C into "stap_9ac881f11ee69cd94f1188a34bfa71c8_2634.ko" in 1530usr/400sys/1935real ms.
Pass 5: starting run.
read performed
Pass 5: run completed in 0usr/30sys/452real ms.

第三步测试,这一步如果systemtap版本、内核符号没安装对,都会报错。

sudo stap -vv -L ‘kprobe.function(“do_execve”)’

如果没问题,输出如下:

Systemtap translator/driver (version 4.5/0.170, non-git sources)
Copyright © 2005-2021 Red Hat, Inc. and others
This is free software; see the source for copying conditions.
tested kernel versions: 2.6.32 … 5.12.0-rc2
enabled features: BPF PYTHON2 NLS
Created temporary directory “/tmp/stapRLStzX”
Session arch: x86_64 release: 5.4.0-81-generic
Build tree: “/lib/modules/5.4.0-81-generic/build”
Kernel symbol table /lib/modules/5.4.0-81-generic/build/System.map unavailable, (No such file or directory)
Searched for library macro files: “/usr/local/share/systemtap/tapset/linux”, found: 7, processed: 7
Searched for library macro files: “/usr/local/share/systemtap/tapset”, found: 11, processed: 11
Searched: “/usr/local/share/systemtap/tapset/linux/x86_64”, found: 20, processed: 20
Searched: “/usr/local/share/systemtap/tapset/linux”, found: 407, processed: 407
Searched: “/usr/local/share/systemtap/tapset/x86_64”, found: 1, processed: 1
Searched: “/usr/local/share/systemtap/tapset”, found: 34, processed: 34
Pass 1: parsed user script and 480 library scripts using 127640virt/98528res/6104shr/92668data kb, in 180usr/50sys/221real ms.
derive-probes (location #0): kprobe.function(“do_execve”) of keyword at :1:1
kprobe.function(“do_execve”) /* name = do_execve*/
Pass 2: analyzed script: 1 probe, 0 functions, 0 embeds, 0 globals using 129224virt/100232res/6232shr/94252data kb, in 10usr/0sys/8real ms.
Running rm -rf /tmp/stapRLStzX
Spawn waitpid result (0x0): 0
Removed temporary directory “/tmp/stapRLStzX”

如果有问题,尝试一下:

  1. 更新systemtap的版本(源码编译,采用最新的版本);
  2. 检查调试符号表。

后话

从实际抓取行为日志的角度来看,效果太一般~~~