首页 > 其他分享 >android ebpf初体验实现文件重定位

android ebpf初体验实现文件重定位

时间:2023-10-20 15:15:25浏览次数:47  
标签:info 初体验 ebpf openat bpf pid filename filter android

之前通过修改内核插桩并编写内核模块的方式hookdo_sys_open函数(这种方式有点像tracepoint,都属于静态探测),这种方式优点是可以hook内核中的任意函数,但是需要编译内核和驱动模块较为麻烦。

eBPF相当于在内核中定义了一个虚拟机,能够加载eBPF字节码并依赖kprobe,uprobe,tracepoint实现内核层以及用户层函数的hook。每次更新hook代码不需要重新编译内核,只需要编写新的eBPF程序生成新的eBPF字节码。缺点是eBPF程序有很多限制,包括堆栈大小限制,内核函数调用限制(只能通过BPF Helper函数调用部分内核函数)等。同时在android平台上的开发编译和部署也是不太成熟,eBPF程序开发和部署相关参考https://github.com/eunomia-bpf/bpf-developer-tutorial/blob/main/src/0-introduce/README.md

目前最常用的的eBPF开发就是使用BCCBCC全称为BPF Compiler Collection,该项目是一个python库,包含了完整的编写、编译、和加载BPF程序的工具链。可以使用c编写内核部分代码并使用python加载和解析输出,环境搭建参考https://bbs.kanxue.com/thread-275176.htm#msg_header_h1_5https://cloud.tencent.com/developer/article/2312646

BCC官方开发教程https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#2-attach_kretprobehttps://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md,官方也提供了很多小工具作为例子。

参考官方文档编写一个文件重定位的BCC脚本,使用的pixel6内核是Linux 5.10,查看内核代码中openopenatopenat2系统调用最后的实现都是do_sys_openat2。对do_sys_openat2函数进行hook并修改参数即可实现文件重定位。

BCC脚本如下:

import argparse
from bcc import BPF

# define BPF program
prog = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
struct openat_entry_info {
    u32 pid;
    u64 time;
    char filename[NAME_MAX];
    char comm[TASK_COMM_LEN];
};

struct openat_filter_info {
    int fd;
    u32 pid;
    u64 time;
    char filename[NAME_MAX];
    char comm[TASK_COMM_LEN];
};
//key : pid_tid
BPF_HASH(entry_info, u64, struct openat_entry_info);

int pre_openat(struct pt_regs *ctx, int dfd, const char __user *filename, struct open_how *how) {
    struct openat_entry_info _info = {};
    u64 pid_tid = bpf_get_current_pid_tgid();
    _info.pid = pid_tid >> 32;
    _info.time = bpf_ktime_get_ns();

    if(bpf_get_current_comm(&_info.comm, sizeof(_info.comm)) != 0){
        return 0;
    }

    if(bpf_probe_read(&_info.filename, sizeof(_info.filename), (void*)PT_REGS_PARM2(ctx)) < 0){
        return 0;
    }
    entry_info.update(&pid_tid, &_info);

    size_t filename_len;
    for (filename_len = 0; filename_len < NAME_MAX; filename_len++) {
        if (_info.filename[filename_len] == '\\0') {
            break;
        }
    }   
    
    size_t num = 0;
    char hide_file[] = "HIDE_FILE_NAME";
    if(strlen(hide_file) == filename_len){
        for(int i = 0; i < filename_len; i++){
            if(hide_file[i] == _info.filename[i]){
                num++;
            }
            else{
                break;
            }
        }

        if(num == strlen(hide_file)){
            char relocate_file[] = "RELOCATE_FILE_NAME";
            bpf_probe_write_user((void*)filename, relocate_file, sizeof(relocate_file));
            bpf_trace_printk("Hello, World : %s!\\n", relocate_file);
        }
    }
    return 0;
}

BPF_PERF_OUTPUT(openat_filter_events);
int post_openat(struct pt_regs *ctx) {
    struct openat_filter_info filter_info = {};
    u64 pid_tid = bpf_get_current_pid_tgid();
    struct openat_entry_info* p_info;
    
    p_info = entry_info.lookup(&pid_tid);
    if(p_info == 0){
        return 0;
    }
    
    filter_info.fd = PT_REGS_RC(ctx);
    filter_info.pid = p_info->pid;
    filter_info.time = p_info->time;
    bpf_probe_read_kernel(&filter_info.comm, sizeof(filter_info.comm), p_info->comm);
    bpf_probe_read_kernel(&filter_info.filename, sizeof(filter_info.filename), p_info->filename);
    openat_filter_events.perf_submit(ctx, &filter_info, sizeof(filter_info));
    entry_info.delete(&pid_tid);
    return 0;
}
"""

# Get args
parser = argparse.ArgumentParser(description="file relocate by bcc")
parser.add_argument("--hide", type=str)
parser.add_argument("--relocate", type=str)
args = parser.parse_args()
prog = prog.replace("HIDE_FILE_NAME", args.hide)
prog = prog.replace("RELOCATE_FILE_NAME", args.relocate)

# load BPF program
b = BPF(text=prog)
b.attach_kprobe(event="do_sys_openat2", fn_name="pre_openat")
b.attach_kretprobe(event="do_sys_openat2", fn_name="post_openat")

# read events
def print_openat_filter(cpu, data, size):
    event = b["openat_filter_events"].event(data)
    print("%-10d %-32s %-6d %-32s" % (event.pid, event.comm, event.fd, event.filename))

b["openat_filter_events"].open_perf_buffer(print_openat_filter)
while True:
    try:
        b.perf_buffer_poll()
    except KeyboardInterrupt:
        exit()

在手机的BCC环境中运行脚本python relocate_file.py --hide /data/local/tmp/as --relocate /tmp/234234234,将/data/local/tmp/as文件重定位到一个不存在的文件/tmp/234234234

标签:info,初体验,ebpf,openat,bpf,pid,filename,filter,android
From: https://www.cnblogs.com/revercc/p/17777123.html

相关文章

  • android 友盟SNS_SDK为Android应用加入SNS分享、同步功能
    使用友盟SNS_SDK为Android应用加入SNS分享、同步功能很多朋友在开发Android应用的过程中,都想加入社会化的分享功能,如将自己的应用使用状态或心得同步到新浪微博、人人网或腾讯微博等。这些社交网络或微博都已经发布了针对开发者的开放平台(关于开放平台的相关信息,请参考《说说微......
  • Android studio的Device File Explorer不见了
    手机文件管理器路径View------>toolwindows----->DeviceFileExplorer  ......
  • Android入门教程 | RecyclerView使用入门
    想必大家对列表的表现形式已经不再陌生。手机上有联系人列表,文件列表,短信列表等等。本文讲述的是在Android开发中用RecyclerView来实现列表效果。使用步骤引入RecyclerView在app的build.gradle文件中添加引用。我们使用的是androidx包。gradle:dependencies{//........
  • Android入门教程 | DrawerLayout 侧滑栏
    DrawerLayout是实现了侧滑菜单效果的控件。DawerLayout分为侧边菜单和主内容区两部分:主内容区要放在侧边菜单前面,还有就是主内容区最好以DrawerLayout最好为界面的根布局,否则可能会出现触摸事件被屏蔽的问题。侧滑菜单部分的布局必须设置layout_gravity属性,表示侧滑菜单是在......
  • android 升级到java11,升级到androidx的操作方法
    androidstudioAndroid9(28)升级到Android10(29)Androidx小计_sdk29对应依赖androidx.appcompat:appcompat-resources是-CSDN博客java.lang.NoClassDefFoundError:Failedresolutionof:Landroidx/appcompat/R$drawable;-简书(jianshu.com)......
  • Android 一例Base64错误问题
    在Android11下正常,8.1下不正常修改importimportorg.apache.commons.codec.binary.Base64;为importandroid.util.Base64;publicstaticStringencrypt(Stringdata){try{SecretKeysecretKey=newSecretKeySpec(SECRET_KEY.getBytes(),ENCRYPT......
  • 一张图去除焦虑,我还能在Android这行继续“裸泳”
    每当新技术潮流兴起时,总会有人声称它们将使"程序员"失业,例如云服务、低代码等等...云原生的出现甚至引发了一种观点,认为很多程序员工作将会集体下岗,生成式技术正在颠覆多个行业,有专家预言在三年内编程将终结...今年,随着技术的不断突破和创新,它们具备更加完善的能力,可以应用于多个工......
  • Android(S)系统属性服务详解
    1.简介 Android系统中,为统一管理系统的属性,设计了一个统一的属性系统,包括两部分:文件保存的持久属性和每次开机导入的cache属性,前者主要保存在.prop文件中,需要注意的是android属性的名称是有一定的格式要求。每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Andro......
  • 科大讯飞-人工智能chatgpt初体验
    前段时间「科大讯飞版ChatGPT」上线,需要体验的按照如下步骤进行体验:PC端可以直接访问:https://xinghuo.xfyun.cn/sparkapi?ch=blapi_06qIrm 领取后会获取token目前1.5个汉字是一个token领取后创建应用,然后下载官网代码就可以跑起来,下面是图示:运行需要输入你自己的appid,APISecre......
  • 如何在Android中获取图片路径
    Android中获取图片路径的方法在Android开发中,获取图片路径是一个常见的需求。下面介绍几种途径来实现获取图片路径的方法。途径一:从相册中获取图片路径要从相册中获取图片的路径,我们需要调用相应的系统接口实现。具体步骤如下:在Manifest文件中添加获取相册的权限:<uses-per......