专栏首页Serverless+使用 BPF 改变运行中的程序的函数参数
原创

使用 BPF 改变运行中的程序的函数参数

本文探索使用 BPF 改变运行中的程序的函数参数,挖掘 BPF 的黑魔法。

实验环境

  • Ubuntu 20.04.2 LTS
  • BCC

测试程序

这是我们的示例程序,打印第一个命令行参数:

package main

import (
	"fmt"
	"os"
	"time"
)

//go:noinline
func greet(s string) {
	fmt.Println(s)
}

func main() {
	for {
		greet(os.Args[1])
		time.Sleep(time.Second)
	}
}

注意到我们使用 //go:noinline 修饰了 main.greet 函数,防止被编译器内联,方便进行测试验证。

这是我们的 BPF 程序,尝试修改函数参数为字符串 You are hacked!:

#include <uapi/linux/ptrace.h>

int hack(struct pt_regs *ctx) {
    char text[] = "You are hacked!";
    // read string address
    u64 addr = 0;
    u64* sp = (u64*)ctx->sp;
    bpf_probe_read(&addr, sizeof(addr), sp + 1);
    // overwrite string content
    bpf_probe_write_user((u64*)addr, text, sizeof(text));
    return 0;
}

使用 bpf_probe_write_user 修改用户内存空间的内容,此操作存在风险,因此每当带有此函数的 BPF 程序被加载时,从 dmesg 中都可以看到如下日志:

tracer[609901] is installing a program with bpf_probe_write_user helper that may corrupt user memory!

实验结果

在第一个终端先启动示例程序,每隔一秒打印字符串 hello world!:

$ ./tracee 'hello world!'
hello world!
hello world!
...

在第二个终端再启动 BPF 程序:

$ sudo ./tracer /path/to/tracee 'main.greet'

此时再看看示例程序的输出:

$ ./tracee 'hello world!'
hello world!
hello world!
...
You are hack
You are hack
You are hack
...

修改成功!

结论

本文探索使用 BPF 修改执行中的 Go 程序的函数参数, 由于 Golang 的 ABI 是使用栈来传递函数参数,通过读取栈上的指针地址,使用 bpf_probe_write_user 修改对应地址的内存内容来达成修改函数参数的目的。你可以在这里找到本文的全部代码。

参考

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用EBPF追踪LINUX内核

    我们可以使用BPF对Linux内核进行跟踪,收集我们想要的内核数据,从而对Linux中的程序进行分析和调试。与其它的跟踪技术相比,使用BPF的主要优点是几乎可以...

    Linux阅码场
  • BCC和libbpf的转换

    本文讲述如何将基于BCC的BPF应用转换为libbpf + BPF CO-RE。BPF CO-RE可以参见上一篇博文。

    charlieroro
  • 基于 eBPF 实现容器运行时安全

    BPF 全称是「Berkeley Packet Filter」,中文翻译为「伯克利包过滤器」。它源于 1992 年伯克利实验室,Steven McCanne 和...

    灵雀云
  • BPF数据传递的桥梁——BPF Map(一)

    https://github.com/nevermosby/linux-bpf-learning/tree/master/bpf/bpf-maps

    nevermosby
  • BPF CO-RE 示例代码解析

    在BPF的可移植性和CO-RE一文的末尾提到了一个名为runqslower的工具,该工具用于展示在CPU run队列中停留的时间大于某一值的任务。现在以该工具来...

    charlieroro
  • 在生产环境中使用 eBPF 调试 GO 程序

    这是本系列文章的第一篇,讲述了我们如何在生产环境中使用 eBPF 调试应用程序而无需重新编译/重新部署。这篇文章介绍了如何使用 gobpf 和 uprobe 来...

    Linux阅码场
  • [译] 第 1 部分: 在生产环境中使用 eBPF 调试 Go 程序

    这是本系列文章的第一篇, 讲述了我们如何在生产环境中使用 eBPF 调试应用程序而无需重新编译/重新部署. 这篇文章介绍了如何使用 gobpf 和 uprobe...

    ritchiechen
  • 使用 eBPF 在生产环境调试 Go 应用

    本文是描述我们如何在生产中使用 eBPF 调试应用程序的系列文章中的第一篇,无需重新编译/重新部署,这篇文章介绍了如何使用 gobpf[1] 和uprobes ...

    我是阳明
  • 调试你的BPF程序

    文章涉及的实验环境和代码可以到这个git repo获取: https://github.com/nevermosby/linux-bpf-learning

    nevermosby
  • BCC(可观测性)

    BCC是一个用于跟踪内核和操作程序的工具集,其软件包中包含了一些有用的工具和例子,它扩展了BPF(Berkeley Packet Filters),通常被称为e...

    charlieroro
  • 张亦鸣 : eBPF 简史 (下篇)

    数日之前,笔者参加某一技术会议之时,为人所安利了一款开源项目,演讲者对其性能颇为称道,称其乃基于近年在内核中炙手可热的 eBPF 技术。

    Linuxer
  • eBPF技术简介

    “eBPF 是我见过的 Linux 中最神奇的技术,没有之一,已成为 Linux 内核中顶级子模块,从 tcpdump 中用作网络包过滤的经典 cbpf,到成为...

    CNCF
  • 一文入门eBPF

    bpf全称伯克利包过滤器(Berkeley Packet Filte),bpf技术诞生于1992年,早期主要用来提升对数据包的过滤性能,但是早期的bpf提供的指...

    fluyy
  • Linux超能力BPF技术介绍及学习分享(技术创作101训练营)

    近两年BPF技术跃然成为了一项热门技术,在刚刚结束的KubeCon 2020 Europe会议上有7个关于BPF的技术分享, 而在KubeCon 2020 Ch...

    nevermosby
  • Python使用多进程运行含有任意个参数的函数

    许多时候,我们对程序的速度都是有要求的,速度自然是越快越好。对于Python的话,一般都是使用multiprocessing这个库来实现程序的多进程化,例如:

    砸漏
  • 全面介绍eBPF-概念

    前面介绍了BCC可观测性和BCC网络,但对底层使用的eBPF的介绍相对较少,且官方欠缺对网络方面的介绍。下面对eBPF进行全面介绍。

    charlieroro
  • eBPF文章翻译(1)—eBPF介绍

    Brendan Gregg,他在2017年的linux.conf.au大会上的演讲提到「内核虚拟机eBPF」,表示,”超能力终于来到了Linux操作系统“。让e...

    nevermosby
  • eBPF 的发展历史和核心设计

    本文翻译自 2016 年 Daniel Borkman 在 NetdevConf 大会上的一篇文章:On getting tc classifier fully...

    米开朗基杨
  • 【答疑】带参数的例行程序运用

    EdenChen

扫码关注云+社区

领取腾讯云代金券