最新要闻
- 【世界独家】30层楼高、叶轮直径191米!国内单机容量最大高原山地风机成功吊装
- 全球今头条!19999元!铁威马发布12盘位NAS T12-450:总容量可达240TB
- 羊了个羊创始人没想到一季度挣了20万:公司仅7人参保
- 焦点速递!俞敏洪最想读的三本书:《道德经》《红楼梦》《金瓶梅》
- LG发布全新光学变焦手机镜头模组:支持4~9倍光学变焦自由切换
- 【独家】女子搬家后发现新房藏有豪华地堡:眼尖网友指出关键所在
- 每日简讯:《羊了个羊》老板曾被嘲笑不懂做游戏:最初目标是一季度挣20万
- 当前热议!一加携手AAC瑞声科技联合打造!官方详解安卓最强马达细节
- 【聚看点】网络游戏作品首次!《王者荣耀》《和平精英》入藏中国国家版本馆
- 速看:Chrome浏览器强化安全性:将阻止HTTP链接下载文件
- 真功夫快餐成被执行人:之前因侵权被功夫巨星李小龙之女起诉
- 热讯:京东苹果年货节超低价:iPhone 14系列最高降1000元
- 天天新资讯:壕无人性!Uzi沉迷《原神》竟然直播时充钱充到限额
- 世界短讯!赢麻!我国世界热点论文数量第一:远超美国、日本
- 天天热头条丨Intel 13代酷睿i5-1350P使劲挤牙膏:只提升了2%
- 简讯:对标理想L8、问界M7 魏牌首款大六座SUV官宣:设计很有料
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
linux跟踪技术之ebpf
ebpf简介
eBPF是一项革命性的技术,起源于 Linux 内核,可以在操作系统内核等特权上下文中运行沙盒程序。它可以安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块。 比如,使用ebpf可以追踪任何内核导出函数的参数,返回值,以实现kernel hook 的效果;通过ebpf还可以在网络封包到达内核协议栈之前就进行处理,这可以实现流量控制,甚至隐蔽通信。
(资料图片仅供参考)
ebpf追踪
ebpf本质上只是运行在linux 内核中的虚拟机,要发挥其强大的能力还是要跟linux kernel 自带的追踪功能搭配:
kprobe
uprobe
tracepoint
USDT
通常可以通过以下三种工具使用ebpf:
bcc
libbpf
bpftrace
bcc
BCC 是一个用于创建高效内核跟踪和操作程序的工具包,包括几个有用的工具和示例。它利用扩展的 BPF(Berkeley Packet Filters),正式名称为 eBPF,这是 Linux 3.15 中首次添加的新功能。BCC 使用的大部分内容都需要 Linux 4.1 及更高版本。
源码安装bcc v0.25.0
首先clone bcc 源码仓库
git clonehttps://github.com/iovisor/bcc.gitgit checkout v0.25.0 git submodule init git submodule update
bcc 从v0.10.0开始使用libbpf 并通过submodule 的形式加入源码树,所以这里需要更新并拉取子模块
安装依赖
apt install flex bison libdebuginfod-dev libclang-14-dev
编译bcc
mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Release .. make -j #n取决于机器的cpu核心数
编译安装完成后,在python3中就能使用bcc模块了 安装bcc时会在/usr/share/bcc目录下安装bcc自带的示例脚本和工具脚本,以及manual 文档 可以直接使用man -M /usr/share/bcc/man
使用python + bcc 跟踪内核函数
bcc 自带的工具execsnoop可以跟踪execv系统调用,其源代码如下:
#!/usr/bin/python# @lint-avoid-python-3-compatibility-imports## execsnoop Trace new processes via exec() syscalls.# For Linux, uses BCC, eBPF. Embedded C.## USAGE: execsnoop [-h] [-T] [-t] [-x] [-q] [-n NAME] [-l LINE]# [--max-args MAX_ARGS]## This currently will print up to a maximum of 19 arguments, plus the process# name, so 20 fields in total (MAXARG).## This won"t catch all new processes: an application may fork() but not exec().## Copyright 2016 Netflix, Inc.# Licensed under the Apache License, Version 2.0 (the "License")## 07-Feb-2016 Brendan Gregg Created this.from __future__ import print_functionfrom bcc import BPFfrom bcc.containers import filter_by_containersfrom bcc.utils import ArgString, printbimport bcc.utils as utilsimport argparseimport reimport timeimport pwdfrom collections import defaultdictfrom time import strftimedef parse_uid(user): try: result = int(user) except ValueError: try: user_info = pwd.getpwnam(user) except KeyError: raise argparse.ArgumentTypeError( "{0!r} is not valid UID or user entry".format(user)) else: return user_info.pw_uid else: # Maybe validate if UID < 0 ? return result# argumentsexamples = """examples: ./execsnoop # trace all exec() syscalls ./execsnoop -x # include failed exec()s ./execsnoop -T # include time (HH:MM:SS) ./execsnoop -U # include UID ./execsnoop -u 1000 # only trace UID 1000 ./execsnoop -u user # get user UID and trace only them ./execsnoop -t # include timestamps ./execsnoop -q # add "quotemarks" around arguments ./execsnoop -n main # only print command lines containing "main" ./execsnoop -l tpkg # only print command where arguments contains "tpkg" ./execsnoop --cgroupmap mappath # only trace cgroups in this BPF map ./execsnoop --mntnsmap mappath # only trace mount namespaces in the map"""parser = argparse.ArgumentParser( description="Trace exec() syscalls", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=examples)parser.add_argument("-T", "--time", action="store_true", help="include time column on output (HH:MM:SS)")parser.add_argument("-t", "--timestamp", action="store_true", help="include timestamp on output")parser.add_argument("-x", "--fails", action="store_true", help="include failed exec()s")parser.add_argument("--cgroupmap", help="trace cgroups in this BPF map only")parser.add_argument("--mntnsmap", help="trace mount namespaces in this BPF map only")parser.add_argument("-u", "--uid", type=parse_uid, metavar="USER", help="trace this UID only")parser.add_argument("-q", "--quote", action="store_true", help="Add quotemarks (\") around arguments." )parser.add_argument("-n", "--name", type=ArgString, help="only print commands matching this name (regex), any arg")parser.add_argument("-l", "--line", type=ArgString, help="only print commands where arg contains this line (regex)")parser.add_argument("-U", "--print-uid", action="store_true", help="print UID column")parser.add_argument("--max-args", default="20", help="maximum number of arguments parsed and displayed, defaults to 20")parser.add_argument("--ebpf", action="store_true", help=argparse.SUPPRESS)args = parser.parse_args()# define BPF programbpf_text = """#include#include #include #define ARGSIZE 128enum event_type { EVENT_ARG, EVENT_RET,};struct data_t { u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel) u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel) u32 uid; char comm[TASK_COMM_LEN]; enum event_type type; char argv[ARGSIZE]; int retval;};BPF_PERF_OUTPUT(events);static int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data){ bpf_probe_read_user(data->argv, sizeof(data->argv), ptr); events.perf_submit(ctx, data, sizeof(struct data_t)); return 1;}static int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data){ const char *argp = NULL; bpf_probe_read_user(&argp, sizeof(argp), ptr); if (argp) { return __submit_arg(ctx, (void *)(argp), data); } return 0;}int syscall__execve(struct pt_regs *ctx, const char __user *filename, const char __user *const __user *__argv, const char __user *const __user *__envp){ u32 uid = bpf_get_current_uid_gid() & 0xffffffff; UID_FILTER if (container_should_be_filtered()) { return 0; } // create data here and pass to submit_arg to save stack space (#555) struct data_t data = {}; struct task_struct *task; data.pid = bpf_get_current_pid_tgid() >> 32; task = (struct task_struct *)bpf_get_current_task(); // Some kernels, like Ubuntu 4.13.0-generic, return 0 // as the real_parent->tgid. // We use the get_ppid function as a fallback in those cases. (#1883) data.ppid = task->real_parent->tgid; bpf_get_current_comm(&data.comm, sizeof(data.comm)); data.type = EVENT_ARG; __submit_arg(ctx, (void *)filename, &data); // skip first arg, as we submitted filename #pragma unroll for (int i = 1; i < MAXARG; i++) { if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; } // handle truncated argument list char ellipsis[] = "..."; __submit_arg(ctx, (void *)ellipsis, &data);out: return 0;}int do_ret_sys_execve(struct pt_regs *ctx){ if (container_should_be_filtered()) { return 0; } struct data_t data = {}; struct task_struct *task; u32 uid = bpf_get_current_uid_gid() & 0xffffffff; UID_FILTER data.pid = bpf_get_current_pid_tgid() >> 32; data.uid = uid; task = (struct task_struct *)bpf_get_current_task(); // Some kernels, like Ubuntu 4.13.0-generic, return 0 // as the real_parent->tgid. // We use the get_ppid function as a fallback in those cases. (#1883) data.ppid = task->real_parent->tgid; bpf_get_current_comm(&data.comm, sizeof(data.comm)); data.type = EVENT_RET; data.retval = PT_REGS_RC(ctx); events.perf_submit(ctx, &data, sizeof(data)); return 0;}"""bpf_text = bpf_text.replace("MAXARG", args.max_args)if args.uid: bpf_text = bpf_text.replace("UID_FILTER", "if (uid != %s) { return 0; }" % args.uid)else: bpf_text = bpf_text.replace("UID_FILTER", "")bpf_text = filter_by_containers(args) + bpf_textif args.ebpf: print(bpf_text) exit()# initialize BPFb = BPF(text=bpf_text)execve_fnname = b.get_syscall_fnname("execve")b.attach_kprobe(event=execve_fnname, fn_name="syscall__execve")b.attach_kretprobe(event=execve_fnname, fn_name="do_ret_sys_execve")# headerif args.time: print("%-9s" % ("TIME"), end="")if args.timestamp: print("%-8s" % ("TIME(s)"), end="")if args.print_uid: print("%-6s" % ("UID"), end="")print("%-16s %-7s %-7s %3s %s" % ("PCOMM", "PID", "PPID", "RET", "ARGS"))class EventType(object): EVENT_ARG = 0 EVENT_RET = 1start_ts = time.time()argv = defaultdict(list)# This is best-effort PPID matching. Short-lived processes may exit# before we get a chance to read the PPID.# This is a fallback for when fetching the PPID from task->real_parent->tgip# returns 0, which happens in some kernel versions.def get_ppid(pid): try: with open("/proc/%d/status" % pid) as status: for line in status: if line.startswith("PPid:"): return int(line.split()[1]) except IOError: pass return 0# process eventdef print_event(cpu, data, size): event = b["events"].event(data) skip = False if event.type == EventType.EVENT_ARG: argv[event.pid].append(event.argv) elif event.type == EventType.EVENT_RET: if event.retval != 0 and not args.fails: skip = True if args.name and not re.search(bytes(args.name), event.comm): skip = True if args.line and not re.search(bytes(args.line), b" ".join(argv[event.pid])): skip = True if args.quote: argv[event.pid] = [ b"\"" + arg.replace(b"\"", b"\\\"") + b"\"" for arg in argv[event.pid] ] if not skip: if args.time: printb(b"%-9s" % strftime("%H:%M:%S").encode("ascii"), nl="") if args.timestamp: printb(b"%-8.3f" % (time.time() - start_ts), nl="") if args.print_uid: printb(b"%-6d" % event.uid, nl="") ppid = event.ppid if event.ppid > 0 else get_ppid(event.pid) ppid = b"%d" % ppid if ppid > 0 else b"?" argv_text = b" ".join(argv[event.pid]).replace(b"\n", b"\\n") printb(b"%-16s %-7d %-7s %3d %s" % (event.comm, event.pid, ppid, event.retval, argv_text)) try: del(argv[event.pid]) except Exception: pass# loop with callback to print_eventb["events"].open_perf_buffer(print_event)while 1: try: b.perf_buffer_poll() except KeyboardInterrupt: exit()
此工具使用kprobe和kretprobe跟踪execv系统调用的进入和退出事件,并将进程名,进程参数,pid,ppid以及返回代码输出到终端。
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图 ② 60+网安经典常用工具包 ③ 100+SRC漏洞分析报告 ④ 150+网安攻防实战技术电子书 ⑤ 最权威CISSP 认证考试指南+题库 ⑥ 超1800页CTF实战技巧手册 ⑦ 最新网安大厂面试题合集(含答案) ⑧ APP客户端安全检测指南(安卓+IOS)
使用python + bcc 跟踪用户函数
bcc中使用uprobe跟踪glibc malloc 函数的工具,并统计malloc 内存的总量。
#!/usr/bin/python## mallocstacks Trace malloc() calls in a process and print the full# stack trace for all callsites.# For Linux, uses BCC, eBPF. Embedded C.## This script is a basic example of the new Linux 4.6+ BPF_STACK_TRACE# table API.## Copyright 2016 GitHub, Inc.# Licensed under the Apache License, Version 2.0 (the "License")from __future__ import print_functionfrom bcc import BPFfrom bcc.utils import printbfrom time import sleepimport sysif len(sys.argv) < 2: print("USAGE: mallocstacks PID [NUM_STACKS=1024]") exit()pid = int(sys.argv[1])if len(sys.argv) == 3: try: assert int(sys.argv[2]) > 0, "" except (ValueError, AssertionError) as e: print("USAGE: mallocstacks PID [NUM_STACKS=1024]") print("NUM_STACKS must be a non-zero, positive integer") exit() stacks = sys.argv[2]else: stacks = "1024"# load BPF programb = BPF(text="""#includeBPF_HASH(calls, int);BPF_STACK_TRACE(stack_traces, """ + stacks + """);int alloc_enter(struct pt_regs *ctx, size_t size) { int key = stack_traces.get_stackid(ctx, BPF_F_USER_STACK); if (key < 0) return 0; // could also use `calls.increment(key, size);` u64 zero = 0, *val; val = calls.lookup_or_try_init(&key, &zero); if (val) { (*val) += size; } return 0;};""")b.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid)print("Attaching to malloc in pid %d, Ctrl+C to quit." % pid)# sleep until Ctrl-Ctry: sleep(99999999)except KeyboardInterrupt: passcalls = b.get_table("calls")stack_traces = b.get_table("stack_traces")for k, v in reversed(sorted(calls.items(), key=lambda c: c[1].value)): print("%d bytes allocated at:" % v.value) if k.value > 0 : for addr in stack_traces.walk(k.value): printb(b"\t%s" % b.sym(addr, pid, show_offset=True))
libbpf
libbpf是linux 源码树中的ebpf 开发包。同时在github上也有独立的代码仓库。 这里推荐使用libbpf-bootstrap这个项目
libbpf-bootstrap
libbpf-bootstrap是使用 libbpf 和 BPF CO-RE 进行 BPF 应用程序开发的脚手架项目 首先克隆libbpf-bootstrap仓库
git clonehttps://github.com/libbpf/libbpf-bootstrap.git
然后同步子模块
cd libbpf-bootstrap git submodule init git submodule update
注意,子模块中包含bpftool,bpftool中还有子模块需要同步 在bpftool目录下重复以上步骤
libbpf-bootstrap中包含以下目录
这里进入example/c中,这里包含一些示例工具 直接make编译 等编译完成后,在此目录下会生成可执行文件
先运行一下bootstrap,这里要用root权限运行
bootstrap程序会追踪所有的exec和exit系统调用,每次程序运行时,bootstrap就会输出运行程序的信息。
再看看minimal,这是一个最小ebpf程序。
运行后输出大量信息,最后有提示让我们运行sudo cat /sys/kernel/debug/tracing/trace_pipe来查看输出 运行这个命令
minimal 会追踪所有的write系统调用,并打印出调用write的进程的pid 这里看到pid为11494,ps 查询一下这个进程,发现就是minimal
来看看minimal的源码,这个程序主要有两个C文件组成,minimal.c和minimal.bpf.c前者为此程序的源码,后者为插入内核虚拟机的ebpf代码。
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)/* Copyright (c) 2020 Facebook */#include#include #include #include #include "minimal.skel.h"static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args){ return vfprintf(stderr, format, args);}int main(int argc, char **argv){ struct minimal_bpf *skel; int err; libbpf_set_strict_mode(LIBBPF_STRICT_ALL); /* Set up libbpf errors and debug info callback */ libbpf_set_print(libbpf_print_fn); /* Open BPF application */ skel = minimal_bpf__open(); if (!skel) { fprintf(stderr, "Failed to open BPF skeleton\n"); return 1; } /* ensure BPF program only handles write() syscalls from our process */ skel->bss->my_pid = getpid(); /* Load & verify BPF programs */ err = minimal_bpf__load(skel); if (err) { fprintf(stderr, "Failed to load and verify BPF skeleton\n"); goto cleanup; } /* Attach tracepoint handler */ err = minimal_bpf__attach(skel); if (err) { fprintf(stderr, "Failed to attach BPF skeleton\n"); goto cleanup; } printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` " "to see output of the BPF programs.\n"); for (;;) { /* trigger our BPF program */ fprintf(stderr, "."); sleep(1); } cleanup minimal_bpf__destroy(skel); return -err;}
首先看一下minimal.c的内容,在main函数中首先调用了libbpf_set_strict_mode(LIBBPF_STRICT_ALL);设置为libbpf v1.0模式。此模式下错误代码直接通过函数返回值传递,不再需要检查errno。 之后调用libbpf_set_print(libbpf_print_fn);将程序中一个自定义输出函数设置为调试输出的回调函数,即运行minimal的这些输出全都时通过libbpf_print_fn输出的。
然后在minimal.c:24调用生成的minimal.skel.h中的预定义函数minimal_bpfopen打开bpf程序,这里返回一个minimal_bpf类型的对象(c中使用结构体模拟对象)。 在31行将minimal_bpf对象的bss子对象的my_pid属性设置为当前进程pid 这里minimal_bpf对象和bss都由minimal.bpf.c代码编译而来。minimal.bpf.c经过clang 编译连接,生成minimal.bpf.o,这是一个elf文件,其中包含bss段,这个段内通常储存着minimal.bpf.c中所有经过初始化的变量。 skel->bss->my_pid = getpid();就是直接将minimal.bpf.o中的my_pid设置为minimal进程的pid。 之后在34行调用minimal_bpfload(skel);加载并验证ebpf程序。 41行调用minimal_bpfattach(skel);使ebpf程序附加到bpf源码中声明的跟踪点上。 此时ebpf程序已经开始运行了。ebpf中通过bpf_printk输出的内容会写入linux debugFS中的trace_pipe中。可以使用sudo cat /sys/kernel/debug/tracing/trace_pipe输出到终端里。 之后minimal程序会进入一个死循环,以维持ebpf程序的运行。当用户按下发送SIGINT信号后就会调用minimal_bpfdestroy(skel);卸载内核中的ebpf程序,之后退出。
接下来看minimal.bpf.c 这是ebpf程序的源码,是要加载到内核中的ebpf虚拟机中运行的,由于在运行在内核中,具有得天独厚的地理位置,可以访问系统中所有资源,再配合上众多的tracepoint,就可以发挥出强大的追踪能力。 下面是minimal.bpf.c的源码
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause/* Copyright (c) 2020 Facebook */#include#include char LICENSE[] SEC("license") = "Dual BSD/GPL";int my_pid = 0;SEC("tp/syscalls/sys_enter_write")int handle_tp(void *ctx){ int pid = bpf_get_current_pid_tgid() >> 32; if (pid != my_pid) return 0; bpf_printk("BPF triggered from PID %d.\n", pid); return 0;}
minimal.bpf.c会被clang 编译器编译为ebpf字节码,然后通过bpftool将其转换为minimal.skel.h头文件,以供minimal.c使用。 此代码中定义并初始化了一个全局变量my_pid,经过编译连接后此变量会进入elf文件的bss段中。 然后,代码中定义了一个函数int handle_tp(void *ctx),此函数中通过调用bpf_get_current_pid_tgid() >> 32获取到调用此函数的进程pid
然后比较pid与my_pid的值,如果相同则调用bpf_printk输出"BPF triggered from PID %d\n” 这里由于handle_tp函数是通过SEC宏附加在write系统调用上,所以在调用write()时,handle_tp也会被调用,从而实现追踪系统调用的功能。 SEC宏在bpf程序中处于非常重要的地位。可以参考此文档SEC宏可以指定ebpf函数附加的点,包括系统调用,静态tracepoint,动态的kprobe和uprobe,以及USDT等等。 Libbpf 期望 BPF 程序使用SEC()宏注释,其中传入的字符串参数SEC()确定 BPF 程序类型和可选的附加附加参数,例如 kprobe 程序要附加的内核函数名称或 cgroup 程序的挂钩类型。该SEC()定义最终被记录为 ELF section name。
通过llvm-objdump 可以看到编译后的epbf程序文件包含一个以追踪点命名的section
ebpf字节码dump
ebpf程序可以使用llvm-objdump -d dump 出ebpf字节码
bpftrace
bpftrace 提供了一种类似awk 的脚本语言,通过编写脚本,配合bpftrace支持的追踪点,可以实现非常强大的追踪功能
安装
sudo apt-get update sudo apt-get install -y \ bison \ cmake \ flex \ g++ \ git \ libelf-dev \ zlib1g-dev \ libfl-dev \ systemtap-sdt-dev \ binutils-dev \ libcereal-dev \ llvm-12-dev \ llvm-12-runtime \ libclang-12-dev \ clang-12 \ libpcap-dev \ libgtest-dev \ libgmock-dev \ asciidoctor git clonehttps://github.com/iovisor/bpftracemkdir bpftrace/build; cd bpftrace/build; ../build-libs.sh cmake -DCMAKE_BUILD_TYPE=Release .. make -j8 sudo make install
bpftrace命令行参数
# bpftraceUSAGE: bpftrace [options] filename bpftrace [options] -e "program"OPTIONS: -B MODE output buffering mode ("line", "full", or "none") -d debug info dry run -dd verbose debug info dry run -e "program" execute this program -h show this help message -I DIR add the specified DIR to the search path for include files. --include FILE adds an implicit #include which is read before the source file is preprocessed. -l [search] list probes -p PID enable USDT probes on PID -c "CMD" run CMD and enable USDT probes on resulting process -q keep messages quiet -v verbose messages -k emit a warning when a bpf helper returns an error (except read functions) -kk check all bpf helper functions --version bpftrace versionENVIRONMENT: BPFTRACE_STRLEN [default: 64] bytes on BPF stack per str() BPFTRACE_NO_CPP_DEMANGLE [default: 0] disable C++ symbol demangling BPFTRACE_MAP_KEYS_MAX [default: 4096] max keys in a map BPFTRACE_MAX_PROBES [default: 512] max number of probes bpftrace can attach to BPFTRACE_MAX_BPF_PROGS [default: 512] max number of generated BPF programs BPFTRACE_CACHE_USER_SYMBOLS [default: auto] enable user symbol cache BPFTRACE_VMLINUX [default: none] vmlinux path used for kernel symbol resolution BPFTRACE_BTF [default: none] BTF fileEXAMPLES:bpftrace -l "*sleep*" list probes containing "sleep"bpftrace -e "kprobe:do_nanosleep { printf("PID %d sleeping...\n", pid); }" trace processes calling sleepbpftrace -e "tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }" count syscalls by process name
bpftrace程序语法规则
bpftrace语法由以下一个或多个action block结构组成,且语法关键字与c语言类似
probe[,probe]/predicate/ { action}
probe:探针,可以使用bpftrace -l 来查看支持的所有tracepoint和kprobe探针
Predicate(可选):在 / / 中指定 action 执行的条件。如果为True,就执行 action
action:在事件触发时运行的程序,每行语句必须以 ; 结尾,并且用{}包起来
//:单行注释
/**/:多行注释
->:访问c结构体成员,例如:bpftrace -e "tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }"
struct:结构声明,在bpftrace脚本中可以定义自己的结构
bpftrace 单行指令
bpftrace -e 选项可以指定运行一个单行程序 1、追踪openat系统调用
bpftrace -e "tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }"
2、系统调用计数
bpftrace -e "tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }"
3、计算每秒发生的系统调用数量
bpftrace -e "tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }"
bpftrace脚本文件
还可以将bpftrace程序作为一个脚本文件,并且使用shebang#!/usr/local/bin/bpftrace可以使其独立运行 例如:
1 #!/usr/local/bin/bpftrace23 tracepoint:syscalls:sys_enter_nanosleep4 {5 printf("%s is sleeping.\n", comm);6 }
bpftrace探针类型
bpftrace支持以下类型的探针:
kprobe- 内核函数启动
kretprobe- 内核函数返回
uprobe- 用户级功能启动
uretprobe- 用户级函数返回
tracepoint- 内核静态跟踪点
usdt- 用户级静态跟踪点
profile- 定时采样
interval- 定时输出
software- 内核软件事件
hardware- 处理器级事件
更多靶场实验练习、网安学习资料,请点击这里>>
linux跟踪技术之ebpf
天天快报!AcWing246. 区间最大公约数
【世界独家】30层楼高、叶轮直径191米!国内单机容量最大高原山地风机成功吊装
全球今头条!19999元!铁威马发布12盘位NAS T12-450:总容量可达240TB
羊了个羊创始人没想到一季度挣了20万:公司仅7人参保
焦点速递!俞敏洪最想读的三本书:《道德经》《红楼梦》《金瓶梅》
Cubase11安装破解图文教程 【2022年12月29日亲测有效】
焦点速读:linux Makefile 如何将生成的 .o 文件放到指定文件夹
热点聚焦:python字典中dict.get()和dict.setdefault()的异同点
LG发布全新光学变焦手机镜头模组:支持4~9倍光学变焦自由切换
【独家】女子搬家后发现新房藏有豪华地堡:眼尖网友指出关键所在
每日简讯:《羊了个羊》老板曾被嘲笑不懂做游戏:最初目标是一季度挣20万
当前热议!一加携手AAC瑞声科技联合打造!官方详解安卓最强马达细节
【聚看点】网络游戏作品首次!《王者荣耀》《和平精英》入藏中国国家版本馆
热点在线丨还有企业没有在用JNPF吗! 适配于多行业的管理系统,各企业之首选
速看:火山引擎 DataTester:如何做 A/B 实验的假设检验
每日热议!折腾了我一周,原来Netty网络编程就是这么个破玩意儿!!!
【报资讯】LF Professional及WINTERACTER产品简介
全球短讯!几个函数的使用例子:更新VBRK-XBLNR,IB01设备BOM创建,LI11N输入库存盘点
速看:Chrome浏览器强化安全性:将阻止HTTP链接下载文件
真功夫快餐成被执行人:之前因侵权被功夫巨星李小龙之女起诉
热讯:京东苹果年货节超低价:iPhone 14系列最高降1000元
天天新资讯:壕无人性!Uzi沉迷《原神》竟然直播时充钱充到限额
世界短讯!赢麻!我国世界热点论文数量第一:远超美国、日本
天天日报丨【Python语法糖】闭包和装饰器
天天热头条丨Intel 13代酷睿i5-1350P使劲挤牙膏:只提升了2%
简讯:对标理想L8、问界M7 魏牌首款大六座SUV官宣:设计很有料
3999元 红魔8 Pro系列首销火爆售罄:高管感到出乎意料
天天时讯:致郑新黄河大桥200多辆车连撞!河南气象台回应郑州未发大雾预警
苹果市值一夜蒸发约4431亿元:iPhone出货量将迎锐减 万元高端机买不动了
每日热讯!郑州200多车相撞 雾天驾车开雾灯还是双闪灯?网友吵翻
信息:电竞级调校!Redmi K60 Pro《原神》须弥城跑图实测:1小时不降亮度
环球滚动:VueJS使用addEventListener的事件如何触发执行函数的this
农四师是什么意思?农四师属于哪个地区?
【焦点热闻】说好的比加油方便呢:英国特斯拉车主抱怨充电要排队数小时
世界视点!4999元 米粉入手小米13限定色:他最满意的安卓手机 太凉快了
今日热文:Win11 2023年“Moment 3”更新内容流出:将针对折叠屏设备进行优化
天天观热点:基于北斗定位实现!高德地图在全国近360城上线“绿灯导航”
2023新剧排排坐
时代少年团综艺节目有哪些?时代少年团成员资料
岁月不居天道酬勤是什么意思?时光不居天道酬勤的出处是哪里?
梅林是什么意思?梅林固件有什么功能?
指纹膜是什么?如何自制指纹膜?
骆驼的体重大约是多少?骆驼奶粉的功效和作用
湖北人有哪些特点?湖北人为什么被称为九头鸟?
包上恩演的电视剧有哪些?包上恩个人资料身高详情
大音希声扫阴翳是什么意思?大音希声扫阴翳出自哪里?
补丁怎么用?补丁的作用有哪些?
联想扬天4600c怎么样?联想扬天4600c参数
win7搜索在哪里?win7蓝牙怎么开启?
(三)elasticsearch 源码之启动流程分析
焦点要闻:特色功能(锐捷云桌面篇)
qq中毒了是什么原因?qq中毒了怎么办?
Win8系统如何关机?win8系统怎么连接wifi?
贝尔金路由器如何设置?贝尔金路由器怎么恢复出厂设置?
天天滚动:手机App秒测血氧 能替代血氧仪吗?专家科普
世界微动态丨雅阁、CR-V均中招!本田中国召回近20万辆混动车 润滑油不够
过去一年都听过什么歌?网易云音乐2022年度听歌报告正式上线
环球关注:汉仪字库定制打造!钉钉进步体来了:永久免费商用
【全球快播报】NASA分享火星冬天航拍照片:色彩斑斓、唯美壮阔
【爬虫实战项目】Python爬取Top100电影榜单数据保存本地(附源码)
【天天新要闻】说透IO多路复用模型
关注:李子柒与微念达成和解 断更500多天的“她”何时回归?
焦点日报:Epic免费送《死亡搁浅》导剪版变标准版后续:官方删除道歉微博
环球关注:你在干啥?2022年中国人每天用手机时长创新高:都在狂刷视频、玩游戏等
百事通!Redmi K60把国产2K OLED屏从不可能变成现实:这过程很痛苦很艰辛
全球观点:苹果市值一夜蒸发约4431亿元 曝其有意砍价iPhone供应链 确保自己利润
DirtyPipe(CVE-2022-0847)漏洞分析
热点聚焦:笔记本SSD普及率今年已达92%:机械硬盘凉凉了
PC硬件机能榨干的日子一去不返!显卡危机不会再有了
【环球报资讯】机箱接口套路多 这些小知识你都知道吗?
【焦点热闻】设计时速250公里!银兰高铁全线开通运营:最快3小时可达
暴降千元性价比还是低!苹果欲放弃iPhone 14销售最差机型:你会买Plus吗
委员建议禁放烟花改为限时燃放 网友争议是否污染环境:多地明确禁放
头条焦点:AMD机会来了?商家预售NV RTX 4070 Ti:售价最高8399元
天天快讯:把WSL安装到指定目录下的简易完美方法
环球热点!Azure 使用技巧
热推荐:卡梅隆急了!《阿凡达3》、《阿凡达4》已经开拍
焦点简讯:HTC Vive新品发布会定档1月6日:旗舰头显来了
全球视讯!TP-LINK Wi-Fi 7游戏路由器来了:三频19Gbps 双万兆网口
环球今亮点!又省117元 EPIC喜加一:硬核魂类游戏《致命躯壳 》免费送 手残党注意
冬至都过了 北半球日照越来越长:为什么却越来越冷了呢?
AcWing245. 你能回答这些问题吗
2022年抖音用户最爱的十本书:四大名著霸占前四名
全球最大规模“沙戈荒”风电光伏基地项目开工 投资超800亿元
今日关注:《王者荣耀》2023年第一款皮肤官宣:传说品质 首周135元
关注:MAUI新生6.2-浮出控件导航Flyout-FlyoutItem/MenuItem/Header/Footer
世界信息:2022年抖音十大热点歌曲出炉:你听过几首?
男子网购N95口罩收到2瓶酱油 驿站:已拒收
观天下!谎称电脑中毒 印度团伙假冒微软工程师骗了美国人100多亿美元
顺丰:快递业的人海战术已近黄昏
环球快看点丨分享20个Javascript中的数组方法,收藏
基于 Dubbo Admin 实现同机房/区域优先
天天微资讯!Autodesk Maya2023 安装教程(小白看了也说understand)
焦点速递!分布式三大热门"IP"之分布式事务随笔
虚假新闻检测(CANMD)《Contrastive Domain Adaptation for Early Misinformation Detection:
世界要闻:全球出行需求爆棚:飞机制造巨头订单积压1.27万架 飞机远远不够用
焦点快播:三星推出43寸奥德赛Neo G7显示器:Mini-LED屏幕、支持144Hz高刷
最令人期待的2023新片
报道:2022年跨年档预售票房破1000万:《阿凡达2》仅位居第二