当前位置: 首页 > news >正文

基于eBPF的安卓逆向辅助工具——stackplz

前言

stackplz是一款基于eBPF技术实现的追踪工具,目的是辅助安卓native逆向,仅支持64位进程,主要功能如下:

  • hardware breakpoint 基于pref_event实现的硬件断点功能,在断点处可读取寄存器信息,不会被用户态探测到
    • 前提是需要内核启用CONFIG_HAVE_HW_BREAKPOINT,5.10+内核默认开启
  • uprobe hook 即在用户态对动态库下断点,在断点处可读取寄存器等上下文信息
  • trace syscall 即在内核态对syscall进行追踪,输出syscall信息,无视任何反调试
  • 自动追踪fork产生的进程,可按pid/uid/tid/package等组合进行过滤
  • 在命中hook的时候可发送信号,例如发送SIGSTOP可挂起进程(硬件断点暂未实现发送信号
    • 几乎无视反调试,并且此时可以使用lldb等调试器附加到进程,获取上下文内容
    • 如果进程已经处于相互ptrace的状态,则调试器不可附加,但此时还是可以通过dd等手段获取上下文内容
  • 使用上述功能时,均可回溯堆栈

使用要求:内核 5.10+(开发板+ReDroid也是可以的,当前支持rock5b),该限制主要来自于需要使用bpf_probe_read_user接口

stackplz最初是受到定制bcc/ebpf在android平台上实现基于dwarf的用户态栈回溯启发,加上自己对eBPF技术略有一点研究,然后决定开发这样一款工具

当时核心目的是寻求一种门槛低、不依赖额外环境、能实际落地的方案开发eBPF程序

受限于当时高版本内核安卓设备的普及程度,只实现了寄存器获取与堆栈回溯,限制是内核要求4.14+

经过一年左右的发展,GKI 2.0设备多了起来,各类eBPF相关的内容不断涌现 ,加上之前自己立了flag

于是最近几个月把之前给stackplz立的flag给陆续落地,加上了许多功能,以期能真正将eBPF技术投入实际的安卓逆向分析中

另外KernelSU近期也发布了新的计划:

  • su 使用日志;通过在内核中跟踪 fork, execve 等系统调用,给出调用 su 的进程调用的日志,如时间,命令行参数等。
  • 集成支持硬件断点并提供用户空间接口,为开发和调试提供便利。
  • 在 kernel 中集成 Lua 解释器并为用户空间提供接口;这样可以让内核运行 lua 脚本,等同于无限制的 eBPF,成为 tracing 好帮手。

什么,无限制的eBPF?那真的是太好了! 所以本文再不出,stackplz就要凉啦(>_<)

再次说明要求与限制:内核 5.10+,仅支持64位进程

请前往Releases或者Actions下载使用

1

2

3

adb push stackplz /data/local/tmp

chmod +x /data/local/tmp/stackplz

cd /data/local/tmp && ./stackplz --prepare

注意:每次更新版本请手动执行一次./stackplz --prepare

功能演示

本文演示过程中没有任何APP受到伤害!

写原理太枯燥你们可能就划走了,下次再写,还是先看看实际效果吧~

1. 硬件断点

硬件断点支持四种类型,即r,w,x,rw,断点长度为4字节

命令中必须提供pid,断点绝对地址或者断点偏移+动态库名,下面是两个示例效果:

1

./stackplz -p 37919 --brk 0xf3a4:x --brk-lib libnative-lib.so --stack

1

./stackplz -p 37919 --brk 0x763e6103a4:x --regs --stack --stack-size 4096

说明:

  • --regs 输出寄存器信息
  • --stack 默认获取用户态8192字节的栈上数据用于回溯堆栈
  • --stack-size 可以用于指定要获取的栈上数据大小,必须是8的倍数

如果要给内核空间的地址下硬件断点,可以使用pid+绝对地址的方式,pid给定一个存在的进程即可(不过目前没有回溯内核堆栈的功能,所以给内核空间地址下硬件断点聊胜于无

2. uprobe hook

其原理是替换目标位置动态库的指令为brk指令,执行到目标位置的时候会陷入内核,执行eBPF虚拟机中的代码

美中不足的是,这个brk指令是可以被扫描出来的,但优势也是只有这一个brk指令,没有inlinehook那么多特征

如果确实担心被扫描,那么可以采用硬件断点先检查下^_^

基于该能力,stackplz可以在断点位置读取上下文的内容,在逆向时以最小的侵入力度获取想要的内容,尽可能避开检测

下面是具体效果:

1

./stackplz -n com.sfx.ebpf --point strstr[str,str] --getoff --stack

1

./stackplz -n com.sfx.ebpf -l libnative-lib.so -w _Z5func4i[int] --regs

1

2

3

./stackplz -n com.sfx.ebpf -w open64[str,int] -f w:/data

./stackplz -n com.sfx.ebpf -w open64[str.f0,int] -f w:/data

./stackplz -n com.sfx.ebpf -w open64[str.f0.f1.f2,int] -f w:/data -f b:/sys -f w:/proc

说明:

  • --getoff 计算LR与PC的偏移情况,方便快速定位调用位置
  • -l/--lib 指定动态库路径,默认为libc.so
    • 大多数情况下使用库名即可,如果遇到同名不同路径,或者找不到的情况,可手动指定为/proc/{pid}/maps中的完整路径
  • -w/--point 意为观测点,配合动态库指定符号或者偏移,可设置多个,上限6个
    • 语法是{符号/基址偏移}{+偏移}{[参数类型{寄存器/读取地址},参数类型{.f{规则索引}}]}
    • 一个观测点下最多读取10个参数
    • 一个参数下最多应用6个过滤规则
    • 下面是一些使用组合示例,目前支持的类型:int,uint,int64,uint64,str,ptr,buf
    • -w _Z5func1v
    • -w 0x9542c[str,str]
    • -w strstr+0x4[str,str]
    • -w strstr[str,str] -w open[str,int]
    • -w 0xA94E8[int:x1,ptr:sp+0x30-0x2c]
      • 默认按寄存器顺序读取,也可以参考本示例,在第一个位置读取x1为int,在第二个位置读取sp+0x30-0x2c为指针
      • 没错,可以进行简单的计算,这样能够灵活读取栈上的内容
    • -w write[int,buf:x2,int]
    • -w write[int,buf:32,int]
    • -w write[int,buf:0x10,int]
      • buf较为特殊,规则如下:
      • 如果:后面是寄存器表明以该寄存器大小为长度读取数据
      • 如果:后面是十进制或十六进制字符串,则表明以这个数的大小为长度读取数据
    • -w write[buf:x2:x1,int,int]
      • 这里的规则表示,读取第一个参数时,读的是x1寄存器,长度为x2,即:后的第一个内容表示长度,末尾的才是要读取的寄存器
  • -f/--filter 字符串过滤规则,有三种,分别是w/white b/black r/replace,示例如下
    • 规则位于参数的末尾,多个规则以.作为分隔符
    • 替换规则涉及两个字符串,以:::作为分隔符
    • 示例如下,依次为白名单规则、黑名单规则、替换规则:
      • -f w:/data
      • -f b:/sys
      • -f r:/system/bin/su:::/system/bin/zz
    • -w openat[int,str.f0.f1] 意为对符号openat的第二个参数,应用规则0规则1
    • -s openat:f0 这是syscall,先在这里说了,意为对openat系统调用的第一个字符串参数应用规则0,注意分隔符为:

3. trace syscall

原理是将eBPF程序挂载到raw_tracepoint/sys_enterraw_tracepoint/sys_exit,然后根据预设配置解析参数

追踪syscall的时候自然也是能输出堆栈的,不过限于篇幅,下面的例子中就不演示了,加--stack即可

下面是具体效果:

1

./stackplz -n com.sfx.ebpf -s openat,socket,connect

1

./stackplz -n com.sfx.ebpf -s %file,%net --no-syscall openat,recvfrom

1

./stackplz -n ???.???.??? -s openat:f0.f1.f2 -f w:/system -f w:/dev -f b:/system/lib64 -o tmp.log

说明:

  • -s/--syscall 一般情况,追踪多个syscall要用,作为分隔符
    • 还可以使用下面的内容进行分组追踪,避免手打大量syscall名
      • all %attr %file %exec %clone %process %net %signal %kill %stat
    • 对syscall中的参数进行过滤,示例如下,使用:作为起始分隔符,使用.作为多个规则的分隔符
      • -s openat:f0.f1.f2
    • syscall的参数过滤仅支持syscall的首个字符串参数

4. 进阶使用

下面将演示如何过root检查,虽然对于eBPF来说做这个事情比较鸡肋,但是还是值得演示一下

核心原理就是通过bpf_probe_write_user方法修改内存数据,这里过root检查就是简单替换下相关的字符串

再次说明:本文演示过程中没有任何APP受到伤害!

这里请一位不愿透露姓名的APP做演示,过程如下:

  1. 首先执行第一个命令,该命令意为追踪execveopenat两个系统调用
  2. 打开APP,很快啊,APP就崩溃了;这个时候已经采集到syscall的调用情况了,从日志中检查调用的参数,发现有su相关的访问
  3. 还是执行第一个命令,然后另开一个shell,执行第二个命令,将有关su的访问替换为其他字符串
  4. 打开APP,很快啊,APP还是崩溃了,不过可以发现APP执行得更久一点...
  5. 配合使用--stack--mstack--getoff,进行更准确的分析
  6. 以此往复,最终发现APP还会执行mountwhich su等命令,而且是走的libc.so,于是再开一个shell执行第三个命令

1

2

3

./stackplz -n ???.???.???,iso -s execve,openat -o tmp_s.log

./stackplz -n ???.???.???,iso -s execve:f3,openat:f0.f1.f2 -f r:/sbin/su:::/xx -f r:/system/bin/su:::/xx -f r:/system/xbin/su:::/xx -f r:/system/bin/getprop:::/xx

./stackplz -n ???.???.???,iso -w popen[str.f0.f1] -f r:mount:::mounx -f "r:which su:::which zz" --stack

使用--mstack,该选项意为手工解析堆栈,因为某些情况下默认的方案可能无法给出详细的堆栈(全是unknown

在后面两个命令同时使用的情况下,最终能走到APP的启动页面:

不过使用eBPF过这个检查实在是麻烦...所以stackplz的定位是辅助分析,这里仅仅演示一下eBPF修改内存的能力

对了,APP怎么老是退出,想个办法让它不要退出好不好哇(

1

./stackplz -n ???.???.???,iso -s exit --kill SIGSTOP --stack

这样每次调用exit的时候,都会发送SIGSTOP信号,可以把整个进程挂起

每次挂起后如果要恢复进程运行,那么执行kill -SIGCONT {pid}这样的命令即可

不过有一个需要注意的问题,那就是发信号的时候,syscall还是会执行,也就是说如果在exit这个系统调用处发信号,进程有可能还是没办法挂起

那么可以配合使用--stack--mstack--getoff来判断从用户态的什么地方调用,从上面的结果来看,是libc.so的__exit

那么使用下面的命令进行追踪,这样就可以真正在执行到__exit的时候挂起,上下文也会保持在__exit的状态

1

./stackplz -n ???.???.???,iso -w __exit --kill SIGSTOP --stack

这是lldb附加上去的效果:

这里的iso指追踪isolated进程,-n/--name选项可以给定进程分组,目前的分组是root system shell app iso

5. 其他补充

如果单条命令hook无法一次性实现想要的追踪内容,那么多开stackplz即可,以及同一个位置多次下hook都是支持的

具有黑白名单的选项:

白名单黑名单
-u/--uid--no-uid
-p/--pid--no-pid
-t/--tid--no-tid
--tname--no-tname
-s/--syscall--no-syscall

在某些情况下,stackplz无法解析到偏移、堆栈,可以设置debug和输出日志到文件,然后根据日志中的各类事件信息进行分析

  • --debug -o tmp.log

仅将日志输出到文件,不输出到终端,这对于进行大量追踪的时候,有助于减少数据丢失

  • -q/--quiet

默认情况下,buf类型的数据打印为ASCII + hex,使用下面的选项将打印为hexdump

  • --dumphex

追踪一些特别频繁的调用时,可能会出现部分数据丢失的情况,这个时候请适当增加eBPF的数据缓冲区大小

  • -b/--buffer 默认8M,一般不建议超过32M

更多命令,请执行./stackplz --help查看

6. Q & A

Q: 不能修改寄存器吗
A: 是的,eBPF中无法修改寄存器,只能修改给定地址处的内存数据

Q: 运行不了
A: 首先请使用5.10+内核的设备,如果确实不行请反馈至issue

Q: 技术架构等
A: 语言:Golang + C
A: 三方库:ebpf + ebpfmanager + libbpf
A: 预编译:BTFHubForAndroid + unwinddaemon
A: 其他:ndk clang + Makefile

相关文章:

基于eBPF的安卓逆向辅助工具——stackplz

前言 stackplz是一款基于eBPF技术实现的追踪工具&#xff0c;目的是辅助安卓native逆向&#xff0c;仅支持64位进程&#xff0c;主要功能如下&#xff1a; hardware breakpoint 基于pref_event实现的硬件断点功能&#xff0c;在断点处可读取寄存器信息&#xff0c;不会被用户…...

十大排序——4.堆排序

前面我们讲了堆&#xff0c;现在我们来看一下队排序。 堆排序的步骤&#xff1a; 首先将一个无序数组建立成一个大顶堆然后&#xff0c;将堆顶的元素和堆低的元素进行交换&#xff08;即将最大的元素交换的到堆底&#xff09;&#xff0c;缩小并下潜调整堆重复上一步&#xf…...

独辟蹊径”之动态切换进程代理IP

前言 项目中遇到这样一个需求&#xff0c;需要动态切换指定进程Sockets5代理IP&#xff0c;目前了解到可通过编写驱动拦截或者劫持LSP实现&#xff0c;LSP劫持不太稳定&#xff0c;驱动无疑是相对较好的解决方案&#xff0c;奈何水平不足便有了这"蹊径"。 初步尝试…...

redis漏洞修复:(CNVD-2019-21763)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、漏洞内容二、镜像准备1.确认镜像版本2.下载镜像 三、配置文件准备1.获取配置文件2.修改配置文件 四、启动redis容器五、修改iptables文件总结 前言 漏扫发…...

手刻 Deep Learning -第壹章-PyTorch入门教学-基础概念与再探线性回归

一、前言 本章会需要 微分、线性回归与矩阵的基本观念 这次我们要来做 PyTorch 的简单教学&#xff0c;我们先从简单的计算与自动导数&#xff08; auto grad / 微分 &#xff09;开始&#xff0c;使用优化器与误差计算&#xff0c;然后使用 PyTorch 做线性回归&#xff0c;还有…...

深入学习 Redis - 如何使用 Redis 作缓存?缓存更新策略?使用需要注意哪些问题(工作/重点)

目录 一、Redis 作为缓存 1.1、缓存的基本概念 1.1.1、理解 1.1.2、缓存存什么样的数据&#xff1f;二八定律 1.2、如何使用 redis 作为缓存 1.3、缓存更新策略&#xff08;redis 内存淘汰机制 / 重点&#xff09; 1.3.1、定期生成 1.3.2、实时生成 内存淘汰策略&#…...

好用的软件测试框架有哪些?测试框架的作用是什么?

软件测试框架是现代软件开发过程中至关重要的工具&#xff0c;它可以帮助开发团队更加高效地进行测试和验证工作&#xff0c;从而大大提高软件质量和用户体验。 一、好用的软件测试框架 1. Selenium&#xff1a;作为一种开源的自动化测试框架&#xff0c;Selenium具有功能强大…...

PAT 1035 插入与归并

PAT 1035 插入与归并 题目描述思路讲解代码展示 题目描述 思路讲解 分析&#xff1a;先将i指向中间序列中满足从左到右是从小到大顺序的最后一个下标&#xff0c;再将j指向从i1开始&#xff0c;第一个不满足a[j] b[j]的下标&#xff0c;如果j顺利到达了下标n&#xff0c;说明…...

K-means 聚类算法学习笔记

K-means 聚类算法 是一种无监督学习算法&#xff0c;用来将 n n n 个样本点分成 k k k 类&#xff0c;使得整个数据集的误差平方和 S S E SSE SSE 最小。在本例中&#xff0c;样本点是指平面直角坐标系上的点&#xff0c;聚类中心也是平面直角坐标系上的点&#xff0c;而每个…...

API文档搜索引擎

导航小助手 一、认识搜索引擎 二、项目目标 三、模块划分 四、创建项目 五、关于分词 六、实现索引模块 6.1 实现 Parser类 6.2 实现 Index类 6.2.1 创建 Index类 6.2.2 创建DocInfo类 6.2.3 创建 Weight类 6.2.4 实现 getDocInfo 和 getInverted方法 6.2.5 实现 …...

文案内容千篇一律,软文推广如何加深用户印象

随着互联网技术的发展&#xff0c;企业营销的方式逐渐转向软文推广&#xff0c;但是现在软文推广的内容同质化越来越严重&#xff0c;企业应该如何让自己的软文推广保持差异性&#xff0c;在用户心中留下独特的印象呢&#xff1f;下面就让媒介盒子告诉你。 一、 找出产品独特卖…...

十二、流程控制-循环

流程控制-循环 1.while循环语句★2.do...while语句★3.for循环语句 —————————————————————————————————————————————————— 1.while循环语句★ while语句也称条件判断语句&#xff0c;它的循环方式是利用一个条件来控制是否…...

五、回溯(trackback)

文章目录 一、算法定义二、经典例题&#xff08;一&#xff09;排列1.[46.全排列](https://leetcode.cn/problems/permutations/description/)&#xff08;1&#xff09;思路&#xff08;2&#xff09;代码&#xff08;3&#xff09;复杂度分析 2.[LCR 083. 全排列](https://le…...

什么是分布式锁?他解决了什么样的问题?

相信对于朋友们来说&#xff0c;锁这个东西已经非常熟悉了&#xff0c;在说分布式锁之前&#xff0c;我们来聊聊单体应用时候的本地锁&#xff0c;这个锁很多小伙伴都会用 ✔本地锁 我们在开发单体应用的时候&#xff0c;为了保证多个线程并发访问公共资源的时候&#xff0c;…...

Ubuntu 12.04增加右键命令:在终端中打开增加打开文件

Ubuntu 12.04增加右键命令&#xff1a;在终端中打开 软件中心&#xff1a;搜索nautilus-open-terminal安装 用快捷键CtrlT打开命令行输入&#xff1a; sudo apt-get install nautilus-open-terminal 重新加载文件管理器 nautilus -q 或注销再登录即要使用...

Centos 7 访问局域网windows共享文件夹

Refer: centos7 访问windows系统的共享文件夹_centos访问windows共享_三希的博客-CSDN博客 一、在CentOS中配置CIFS网络存储服务 CIFS&#xff08;Common Internet File System&#xff09;是一种在网络上共享文件的协议&#xff0c;也称为SMB&#xff08;Server Message Blo…...

GDB的TUI模式(文本界面)

2023年9月22日&#xff0c;周五晚上 今晚在看GDB的官方文档时&#xff0c;发现GDB居然有文本界面模式 TUI (Debugging with GDB) (sourceware.org) GDB开启TUI的条件 GDB的文本界面的开启条件是&#xff1a;操作系统有适当版本的curses库 The TUI mode is supported only on…...

深入了解Python和OpenCV:图像的卡通风格化

前言 当今数字时代&#xff0c;图像处理和美化已经变得非常普遍。从社交媒体到个人博客&#xff0c;人们都渴望分享独特且引人注目的图片。本文将介绍如何使用Python编程语言和OpenCV库创建令人印象深刻的卡通风格图像。卡通风格的图像具有艺术性和创意&#xff0c;它们可以用…...

【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数

1004. 最大连续1的个数 III 1004. 最大连续1的个数 III 题目描述&#xff1a; 给定一个二进制数组 nums 和一个整数 k&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 解题思路&#xff1a; 首先题目要我们求出的最多翻转k个0后&#x…...

华为云HECS安装docker

1、运行安装指令 yum install docker都选择y&#xff0c;直到安装成功 2、查看是否安装成功 运行版本查看指令&#xff0c;显示docker版本&#xff0c;证明安装成功 docker --version 或者 docker -v 3、启用并运行docker 3.1启用docker 指令 systemctl enable docker …...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...