Giter Site home page Giter Site logo

stackplz's Introduction

stackplz

wbstack/watch breakpoint stack/stackplz plus

stackplz是一款基于eBPF的堆栈追踪工具,目前仅适用于Android平台

特性:

  • 支持arm64 syscall trace,可以打印参数(包括详细的结构体信息)、调用栈、寄存器
  • 支持对64位用户态动态库进行uprobe hook,可以打印参数、调用栈、寄存器
  • 支持硬件断点功能,可以打印调用栈、寄存器,并且提供了frida rpc调用
  • 支持进程号、线程号、线程名的黑白名单过滤
  • 支持追踪fork产生的进程

要求:

  • root权限,系统内核版本5.10+(可执行uname -r查看)
  • 对于4.1x的内核,内核开启了CONFIG_HAVE_HW_BREAKPOINT,硬件断点功能同样可以使用

不仅仅是真机,这些环境下也可以使用:

  • arm开发板刷安卓镜像
  • arm开发板/云服务器 + Docker + ReDroid
  • Apple M系列设备 + 安卓官方arm64模拟器
  • 有root权限,内核版本5.10+的云真机也可以

使用

从Releases或者Github Action下载最新预编译好的二进制文件即可

  1. 推送到手机的/data/local/tmp目录下,添加可执行权限即可
adb push stackplz /data/local/tmp
adb shell
su
chmod +x /data/local/tmp/stackplz

注意:v3.0.1之前,使用不同版本时,需要释放库文件,请使用下面的命令

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

2. 选项说明

stackplz的所有可用选项,可以通过./stackplz --help查看

2.1 用于对目标进程/线程进行过滤的选项

注意:如果存在多个目标,使用逗号隔开;--no-xxx意为黑名单

选项 黑名单选项 说明
-n/--name APP包名,分组名(root/system/shell/app/iso)
-u/--uid --no-uid 目标uid
-p/--pid --no-pid 目标pid
-t/--tid --no-tid 目标tid
--tname --no-tname 目标线程名,注意最多16字节

2.2 syscall/uprobe hook选项

  • -s/--syscall name/group

即syscall hook,后跟系统调用号对应的名字,或者分组,对应的黑名单选项--no-syscall

  • -w/--point symbol/offset[type,type,...]

即uprobe hook,必须配合-l/--lib使用,具体用法参考后面的命令演示

2.3 硬件断点相关选项

选项 默认值 说明
--pid 目标进程pid,与--brk-lib搭配使用计算断点地址
--brk 要下断的地址
--brk-len 4 断点长度
--brk-lib 目标库,使用该选项时--brk为相对偏移
--brk-pid -1 目标进程pid,通常不建议设置该选项

2.4 发送信号选项

--kill SIGSTOP/SIGABRT/SIGTRAP/...,只能设置一个,效果是在命中hook时向目标进程发送信号

注意:对于syscall来说,发送信号的时机位于syscall执行完成之后,所以对于exit/exit_group等syscall可能无法实现预期效果

2.5 参数过滤选项

-f/--filter,该选项用于设定参数的过滤规则

规则 示例 说明
w/white w:/sbin/su 字符串白名单,过滤以/sbin/su开头的内容,最多256字节
b/black b:/sbin/su 字符串黑名单,过滤以/sbin/su开头的内容,最多256字节
bx/bufhex bx:73ea68 buffer数据白名单,过滤16进制以73ea68开头的内容,最多比较8字节
eq/equal eq:0x748a484d2c 寄存器值白名单,过滤寄存器值等于0x748a484d2c的内容

2.6 部分布尔类型选项

选项 说明
--auto 该选项需要配合--kill SIGSTOP使用,效果是自动恢复被挂起的进程
--btf 显式声明当前环境的内核开启了CONFIG_DEBUG_INFO_BTF
--color 该选项需要配合--dumphex使用,效果是在终端显示颜色
--dumphex 启用该选项后,对于buf类型数据将输出为hexdump,风格与CyberChef保持一致
--getoff 输出PC和LR的偏移信息,注意使用该选项会导致性能降低
--json 将日志输出为json格式
--jstack 配合--kill SIGSTOP使用,可对堆栈中的jar/vdex进行解析
--mstack 简易实现堆栈回溯,没有符号信息
--nocheck 禁用bpf特性检查,没有/proc/config.gz或者是其他路径时使用
--quiet 不在终端输出日志
--regs 输出全部寄存器
--showpc 输出堆栈原始PC值
--showtime 输出自开机以来的时间,单位ns
--showuid 输出记录的uid
--stack 输出堆栈

2.7 rpc选项

主要用于frida联动,远程下硬件断点

  • server 监听命令 ./stackplz --rpc --stack
  • client frida脚本参考 frida_hw_brk.js
  • 端口可以通过--rpc-path修改,默认127.0.0.1:41718
  • 用其他方式发socket联动也可以,自行实现

2.8 杂项选项

  • -a/--arch 目标进程架构,默认aarch64,计划为aarch32 syscall trace提供支持
  • -b/--buffer perf缓冲区大小,默认8,即8M
    • 增大该数值可以减少数据丢失,如果太大会出现了失败的错误,请停止重新设置一个数值,通常建议不超过32M
  • -c/--config 配置文件模式
  • --full-tname 默认对于一些高频调用syscall的系统线程进行了屏蔽,启用该选项后将解除屏蔽
  • -l/--lib 动态库名或者动态库完整路径,配合-w/--point选项使用
  • -o/--out 日志文件名,默认不生成日志文件
  • --dump 即dump模式,hook获取到的数据不会被解析,仅保存到单个文件
  • --parse 即针对dump得到的文件进行解析,可能比较耗时,可能存在bug
  • --stack-size 堆栈大小,默认8192字节,基本够用,最大65528

3. 命令演示

3.1 追踪syscall

./stackplz -n com.starbucks.cn --syscall connect,sendto,recvfrom -o tmp.log --dumphex

自定义syscall参数类型

受限于代码结构,暂时采取了一种迂回的方法

即,在uprobe的写法下,末尾加上s/ss,即可转为hook syscall,两个s表示syscall退出时也同样读取结构体的详细数据

常规类型末尾的x表示输出为hex

./stackplz -n com.termux -w writev[int,ptr,intx]s
./stackplz -n com.termux -w writev[ptrx,buf,ptrx]ss --dumphex --color

关于syscall名,请查阅Linux kernel syscall tables

3.2 追踪libc的open

注:默认设定的库是/apex/com.android.runtime/lib64/bionic/libc.so,要自定义请使用--lib指定

./stackplz -n com.starbucks.cn --point strstr[str,str] --point open[str,int] -o tmp.log

3.3 在命中uprobe hook时发送信号

有时候希望在经过特定点位的时候停止进程,以便于dump内存,那么可以使用--kill来发送信号,示例:

./stackplz -n com.sfx.ebpf --lib libnative-lib.so -w _Z5func1v --stack --kill SIGSTOP
./stackplz -n com.starbucks.cn --syscall exit --kill SIGSTOP --stack

如果要恢复进程运行,可以用下面这样的命令(另起一个shell,root下执行):

kill -SIGCONT 4326

v3.0.0版本起,可以在终端输入c后回车恢复进程运行

3.4 硬件断点示例如下,支持的断点类型:r,w,rw,x

pid + 绝对地址

./stackplz --pid `pidof com.sfx.ebpf` --brk 0x70ddfd63f0:x --stack

pid + 偏移 + 库文件

./stackplz --pid `pidof com.sfx.ebpf` --brk 0xf3a4:x --brk-lib libnative-lib.so --stack

对内核中的函数下硬件断点:

!!!注意,内核函数通常触发非常频繁,该操作可能导致设备重启,请谨慎使用,原因不明

echo 1 > /proc/sys/kernel/kptr_restrict
cat /proc/kallsyms  | grep "T sys_"
./stackplz --brk 0xffffff93c5beb634:x --pid `pidof com.sfx.ebpf` --stack
./stackplz --brk 0xffffffc0003654dc:x --pid `pidof com.sfx.ebpf` --regs

3.5 以寄存器的值作为大小读取数据、或者指定大小

./stackplz --name com.sfx.ebpf -w write[int,buf:x2,int]
./stackplz --name com.sfx.ebpf -w write[int,buf:32,int]
./stackplz --name com.sfx.ebpf -w write[int,buf:0x10,int]

进阶用法:

libc.so+0xA94E8处下断,读取x1int,读取sp+0x30-0x2cptr

./stackplz --name com.sfx.ebpf -w 0xA94E8[int:x1,ptr:sp+0x30-0x2c]

libc.so+0xA94E8处下断,读取x1int,读取sp+0x30-0x2cbuf,长度为8

./stackplz --name com.sfx.ebpf -w 0xA94E8[int:x1,buf:8:sp+0x30-0x2c]
.text:00000000000A94E4                 LDR             W1, [SP,#0x30+var_2C]
.text:00000000000A94E8                 MOV             W20, W0

按默认顺序读取,以及按指定寄存器读取,下面的示例中两个方式输出结果相反:

./stackplz --name com.sfx.ebpf -w 0xA94E8[int,int]
./stackplz --name com.sfx.ebpf -w 0xA94E8[int:x1,int:x0]

call_constructors处获取soinfo内容

# 打印名称和完整路径
./stackplz -n com.coolapk.market -l linker64 -w __dl__ZN6soinfo17call_constructorsEv[ptr,str.f0:x0+409,str:x0+448.] -f w:libjiagu
./stackplz -n com.coolapk.market -l linker64 -w __dl__ZN6soinfo17call_constructorsEv[ptr,std.f0:x0+408,std:x0+432] -f w:libjiagu
# 将 init_array_count_ 和 init_array_ 内容打印出来 
./stackplz -n com.coolapk.market -l linker64 -w __dl__ZN6soinfo17call_constructorsEv[ptr,std.f0:x0+408,*int:x0+160,ptr_arr:6:x0+152.] -f w:libjiagu --dumphex --color

偏移说明如下,这些偏移可以根据call_constructors get_realpath get_soname得到:

  • 408 -> std::string soname_;
  • 432 -> std::string realpath_;
  • 152 -> linker_ctor_function_t* init_array_;
  • 160 -> size_t init_array_count_;

在指定偏移处做退出读取,退出偏移即RET指令的偏移,示例如下

./stackplz -n com.termux -w gettimeofday[timeval,timezone]0x4B320
./stackplz -n com.termux -w 0x9D150[int,buf:x2,int]0x9D164 --dumphex --color

3.6 按分组批量追踪进程

追踪全部APP类型的进程,但是排除一个特定的uid:

./stackplz -n app --no-uid 10084 --point open[str,int] -o tmp.log

同时追踪一个APP和(所有)isolated进程:

./stackplz -n com.starbucks.cn,iso --syscall openat -o tmp.log

可选的进程分组:root system shell app iso

3.7 按分组批量追踪syscall

./stackplz -n com.xingin.xhs -s %file,%net --no-syscall openat,recvfrom

可选的syscall分组如下:

  • all
  • %attr %file
  • %exec %clone %process
  • %net %send %recv %read %write
  • %signal
  • %kill %exit %dup
  • %epoll %stat

具体分组情况请查看Parse_SyscallNames

3.8 应用过滤规则

黑白名单:

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

LR比较,需要提前计算用于比较的值:

./stackplz -n com.chinarainbow.tft -w memcpy[ptr,ptr,int,ptr.f0:lr] -f eq:0x748a484d2c --stack --kill SIGSTOP

引入buffer数据比较,bx/bufhex,可以进行最多8字节的比较

./stackplz -n com.netease.cloudmusic -w sendto[int,buf.f0:x2,int] -f bx:73ea68 -o tmp.log --dumphex --color --stack

3.9 尝试输出更详细的java堆栈

注意:--jstack必需搭配--kill SIGSTOP使用,应用被挂起后可按c回车恢复运行

./stackplz_arm64 -n com.wsy.crashcatcher -w raise --stack --jstack --showpc --kill SIGSTOP

使用提示:

  • --showtime 输出事件发生的时间
    • 因为日志中的顺序和实际发生顺序不完全一致
    • 如果要精确发生顺序,请使用该选项
  • --showuid 输出触发事件的进程的uid
    • 在大范围追踪的时候建议使用
  • 可以用--name指定包名,用--uid指定进程所属uid,用--pid指定进程
  • 默认hook的库是/apex/com.android.runtime/lib64/bionic/libc.so,可以只提供符号进行hook
  • hook目标加载的库时,默认在对应的库目录搜索,所以可以直接指定库名而不需要完整路径
    • 例如 /data/app/~~t-iSPdaqQLZBOa9bm4keLA==/com.sfx.ebpf-C_ceI-EXetM4Ma7GVPORow==/lib/arm64
  • 如果要hook的库无法被自动检索到,请提供在内存中加载的完整路径
    • 最准确的做法是当程序运行时,查看程序的/proc/{pid}/maps内容,这里的路径是啥就是啥
  • hook动态库请使用--point/-w,可设置多个,语法是{符号/基址偏移}{+符号偏移}{[参数类型,参数类型...]}
    • --point _Z5func1v
    • --point strstr[str,str] --point open[str,int]
    • --point write[int,buf:64]
    • --point 0x9542c[str,str]
    • --point strstr+0x4[str,str]
  • hook syscall需要指定--syscall/-s选项,多个syscall请使用,隔开
    • --syscall openat
  • 特别的,指定为all表示追踪全部syscall
    • --syscall all
  • 特别说明,如果期望将0xffffff9c这样的结果输出为负数,请明确指定类型为int
  • 注意,本项目中syscall的返回值通常是errno,与libc的函数返回结果不一定一致
  • --dumphex表示将数据打印为hexdump,否则将记录为ascii + hex的形式,另外可添加--color选项
  • 输出到日志文件添加-o/--out tmp.log,只输出到日志,不输出到终端再加一个--quiet即可

注意,默认屏蔽下列线程,原因是它们属于渲染或后台相关的线程,会触发大量的syscall调用

如果有需求追踪下列线程,请添加--full-tname使用,或者手动修改DefaultThreadBlacklist函数

  • Profile Saver
  • Runtime worker
  • ReferenceQueueD
  • FinalizerDaemon
  • FinalizerWatchd
  • HeapTaskDaemon
  • perfetto_hprof_
  • RenderThread
  • FinalizerDaemon
  • RxCachedThreadS
  • mali-cmar-backe
  • mali-utility-wo
  • mali-mem-purge
  • mali-hist-dump
  • mali-event-hand
  • hwuiTask0
  • hwuiTask1
  • NDK MediaCodec_

更多用法,请通过-h/--help查看:

  • /data/local/tmp/stackplz -h

编译

可参考workflow或查看编译文档

Q & A

  1. preload_libs里面的库怎么编译的?

参见:unwinddaemon,注意v3.0.3之后采用了新的编译方案

  1. perf event ring buffer full, dropped 9 samples

使用-b/-buffer设置每个CPU的缓冲区大小,默认为8M,如果出现数据丢失的情况,请适当增加这个值,直到不再出现数据丢失的情况

命令示意如下:

./stackplz -n com.starbucks.cn -b 32 --syscall all -o tmp.log

增大缓冲区大小也可能带来新的问题,比如分配失败,这个时候建议尽可能清理正在运行的进程

failed to create perf ring for CPU 0: can't mmap: cannot allocate memory

  1. 通过符号hook确定调用了但是不输出信息?

某些符号存在多种实现(或者重定位?),这个时候需要指定具体使用的符号或者偏移

例如strchr可能实际使用的是__strchr_aarch64,这个时候应该指定__strchr_aarch64而不是strchr

coral:/data/local/tmp # readelf -s /apex/com.android.runtime/lib64/bionic/libc.so | grep strchr
   868: 00000000000b9f00    32 GNU_IFUNC GLOBAL DEFAULT   14 strchrnul
   869: 00000000000b9ee0    32 GNU_IFUNC GLOBAL DEFAULT   14 strchr
  1349: 000000000007bcf8    68 FUNC    GLOBAL DEFAULT   14 __strchr_chk
   689: 000000000004a8c0   132 FUNC    LOCAL  HIDDEN    14 __strchrnul_aarch64_mte
   692: 000000000004a980   172 FUNC    LOCAL  HIDDEN    14 __strchrnul_aarch64
   695: 000000000004aa40   160 FUNC    LOCAL  HIDDEN    14 __strchr_aarch64_mte
   698: 000000000004ab00   204 FUNC    LOCAL  HIDDEN    14 __strchr_aarch64
  5143: 00000000000b9ee0    32 FUNC    LOCAL  HIDDEN    14 strchr_resolver
  5144: 00000000000b9f00    32 FUNC    LOCAL  HIDDEN    14 strchrnul_resolver
  5550: 00000000000b9ee0    32 GNU_IFUNC GLOBAL DEFAULT   14 strchr
  6253: 000000000007bcf8    68 FUNC    GLOBAL DEFAULT   14 __strchr_chk
  6853: 00000000000b9f00    32 GNU_IFUNC GLOBAL DEFAULT   14 strchrnul

文章

个人碎碎念太多,有关stackplz文章就不同步到本项目了,请移步博客查看:

之前针对syscall追踪并获取参数单独开了一个项目,整体结构更简单,没有interface,有兴趣请移步estrace

不过目前estrace的全部功能已经在stackplz中实现,不日将存档

Ref

本项目参考了以下项目和文章:


wbstack

./wbstack_arm64 -p `pidof com.sfx.ebpf` --brk 0x6dd9d563a4:x --stack
./wbstack_arm64 -p `pidof com.sfx.ebpf` --brk 0x6dd9d563a4:x -w 0x0[str,ptr,buf:32:x0] --color --dumphex
./wbstack_arm64 -p `pidof com.sfx.ebpf` --brk 0xF3A4:x --brk-lib libnative-lib.so -w 0x0[str,ptr,buf:32:x0] --color --dumphex --stack
./wbstack_arm64 -p `pidof com.sfx.ebpf` --brk 0xF3A4:x --brk-lib libnative-lib.so -w 0x0[str,ptr,buf:32:x0] --color --dumphex --stack --jstack --kill SIGSTOP

stackplz's People

Contributors

joeycold avatar seeflowerx avatar ylarod avatar yxsra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stackplz's Issues

Error when using --stack option in Redroid

您好,

在 Redroid 中对所有应用程序和选项添加 --stack 选项时,出现以下错误,导致无法输出 stack:

Error when GetStack:[GetStack] get pid_maps failed by pid:2017599488

当前在 Redroid 上运行:

redroid_arm64:/data/local/tmp # uname -a
Linux localhost 6.5.0-1025-oracle #25~22.04.1-Ubuntu SMP Fri Jun 14 14:45:36 UTC 2024 aarch64

特别情况:

130|redroid_arm64:/data/local/tmp # ./stackplz
CheckKernelConfig failed, error:Kernel config read failed, error:open /proc/config.gz: no such file or directory
1|redroid_arm64:/data/local/tmp #

由于 Ubuntu 中不存在 /proc/config.gz 文件,因此必须使用 --nocheck 选项。

以下是执行命令和完整日志:

执行命令:

./stackplz --nocheck -n re.pwnme -s openat:f0 --no-tname crash_dump64 -f w:/sbin/su --stack

完整日志:

findBTFAssets btf_file=a12-5.10-arm64_min.btf
warn, no running process of re.pwnme
hook syscall count:1
ConfigMap{stackplz_pid=19251,thread_whitelist=0}
uid => whitelist:[10118];blacklist:[]
pid => whitelist:[];blacklist:[]
tid => whitelist:[];blacklist:[]
start 2 modules
Error when GetStack:[GetStack] get pid_maps failed by pid:2017599488
Error when GetStack:[GetStack] get pid_maps failed by pid:2017599488
[2017599488|0|re.pwnme] openat(dirfd=-100, *pathname=0xf51b80b7f3af(/sbin/su), flags=0x0, mode=0o000) LR:0xf51e75369740 PC:0xf51e753ab1d8 SP:0xf51b809c6650
[2017599488|0|re.pwnme] openat(dirfd=-100, *pathname=0xf51b80b7f3af, flags=0x0, mode=0o000, ret=-2)
Error when GetStack:[GetStack] get pid_maps failed by pid:2017599488
Error when GetStack:[GetStack] get pid_maps failed by pid:2017599488
[2017599488|0|re.pwnme] openat(dirfd=-100, *pathname=0xf51b80b7f3af(/sbin/su), flags=0x0, mode=0o000) LR:0xf51b80a64184 PC:0xf51b80a642a8 SP:0xf51b809c6780
[2017599488|0|re.pwnme] openat(dirfd=-100, *pathname=0xf51b80b7f3af, flags=0x0, mode=0o000, ret=-2)

请帮忙确认此问题并提供解决方案。
谢谢。

module Run failed, [skip it]. error:couldn't init manager error:map filter_map

hi,请问下出现module Run failed及以下问题应该如何解决?感谢!(微信群过期了加不了)

./stackplz --name com.xxx.xxx stack --symbol strstr --regs --stack 
11:45:39 StackMod	hook info:libc.so + strstr
11:45:39 StackMod	module Run failed, [skip it]. error:couldn't init manager error:map filter_map: load BTF: detect support for Map BTF (Var/Datasec): detect support for BTF: no such file or directory , couldn't load eBPF programs, cs:&{map[data_buffer_heap:PerCPUArray(keySize=4, valueSize=32, maxEntries=1, flags=0) filter_map:Hash(keySize=4, valueSize=32, maxEntries=1, flags=0) stack_events:PerfEventArray(keySize=0, valueSize=0, maxEntries=0, flags=0)] map[probe_stack:0x40002ec3f0] 0x4000024980 LittleEndian}
11:45:39 No runnable modules, Exit(1)

运行环境:
redmi K30S Ultra / MIUI13.0.5(Android12)

uname -r 
4.19.157-perf-gc52b9c484a64

能否追踪内核任意函数?

能否做到 类似于bcc的trace工具,追踪vfs read中的信息(inode、offset、len)?
测试了stackplz可以追踪read write syscall,但是这些系统调用只能获取到fd,没办法获取到inode这些需要用到的信息。

mac m1 ubuntu redroid下,pid和tid一直为0

macbookAir m1 pd ubuntu22.04 全新拉取镜像 redroid/redroid:14.0.0_64only-latest 13 12 下 hook任意apk 任意点 均有此问题,

在默认的5.15.0-76-generic内核下

使用 ./stackplz --nocheck -n com.chinarainbow.tft -s %file 时 显示的pid和tid为0

在自己编译的6.5.8内核(仅多开启了/proc/config,gz相关的功能)中,

使用./stackplz -n com.chinarainbow.tft -s %file 时pid和tid也为0

有时候pid会为极大值(没截到图

image

ps -ef回显正常
image

但在orangepi5b上的redroid获取pid和tid正常显示,5b的cuttlefish下也正常工作

dev 版 `--stack`及 `--point strstr[str,str]` 无法取得

v2.1.4正常, 但563fd9d版出现以下问题

  1. --stack can't get sp reg value
  2. --point strstr[str,str] 無法取得[str,str]的值, 如下例0x46c99c
 ./stackplz  --nocheck --btf -u 10077 --point strstr[str,str] --getoff --stack
hook uprobe, count:1
idx:0 [/apex/com.android.runtime/lib64/bionic/libc.so] -> sym:strstr off:0x0 str,str
uid => whitelist:[10077];blacklist:[]
pid => whitelist:[];blacklist:[]
tid => whitelist:[];blacklist:[]
start 2 modules
can't get sp reg value[6888|6888|xxxxxxx] strstr(arg_0=0xfffff4212608(), arg_1=0xf240219c97a0()) LR:0xf240218ad99c(libmbjlidejfdjc.so + 0x46c99c) PC:0xf2434cbd8b20(libc.so + 0x98b20) SP:0xfffff4211320
can't get sp reg value[6888|6888|xxxxxxx] strstr(arg_0=0xf240218d2cf7(), arg_1=0xf2434cb5d8b3()) LR:0xf2434cb9bf40(libc.so + 0x5bf40) PC:0xf2434cbd8b20(libc.so + 0x98b20) SP:0xfffff4213af0
can't get sp reg value[6888|6924|pool-5-thread-1] strstr(arg_0=0xf24339a464e7(), arg_1=0xf2401a3e2cf0()) LR:0xf24339b8e464(libicuuc.so + 0x185464) PC:0xf2434cbd8b20(libc.so + 0x98b20) SP:0xf2401a3e2c30

 ./stackplz214  --nocheck --btf -u 10077 --point strstr[str,str] --getoff --stack
hook uprobe, count:1
uid => whitelist:[10077];blacklist:[]
pid => whitelist:[];blacklist:[]
tid => whitelist:[];blacklist:[]
start 2 modules
[6527|6527|xxxxxxx] strstr(arg_0=0xfffff4212608(Name:   xxxxxxx
Umask:  0077
State:  R (running)
Tgid:   6527
Ngid:   0xxxxxxxxxxxxx), arg_1=0xf2401d1a57a0(TracerPid:)) LR:0xf2401d08999c(libmbjlidejfdjc.so + 0x46c99c) PC:0xf2434cbd8b20(libc.so + 0x98b20) SP:0xfffff4211320, Stackinfo:
  #00 pc 0000000000098b20  /apex/com.android.runtime/lib64/bionic/libc.so (strstr)
  #01 pc 000000000046c998  /data/app/~~p0QUg1dRyl2-1COPcUYS4w==/xxxxxxx-5iYdnEcaT5eCIWaG17t8-g==/lib/arm64/libmbjlidejfdjc.so
  #02 pc 00000000000513b8  /apex/com.android.runtime/bin/linker64 (__dl__ZN6soinfo17call_constructorsEv+748)
  #03 pc 000000000003beb8  /apex/com.android.runtime/bin/linker64 (__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv+1996)```

[feature request] 命令行交互支持

目前的操作都是在执行前就确定了的,如果能像objection这样,那么将极大提高生产力。

与构建一个web gui管理相比,命令行交互更合适专业逆向人员。

redroid13找不到/proc/config.gz

stackplz是不是對host os也有要求?

android: (docker run -itd --rm --privileged -v ~/data:/data -p 5555:5555 redroid/redroid:13.0.0-latest)

130|redroid_arm64:/data # ./stackplz                                                                                
CheckKernelConfig failed, error:Kernel config read failed, error:open /proc/config.gz: no such file or directory
130|redroid_arm64:/data # uname -r
5.15.0-76-generic
redroid_arm64:/ $ zcat /proc/config.gz                                                                              
zcat: /proc/config.gz: No such file or directory

host: 阿里云 ECS Ubuntu 22.04 64位 ARM版

root@xxxxxxxxxxxxx:~# uname -a
Linux xxxxxxxxxxxxx 5.15.0-76-generic #83-Ubuntu SMP Thu Jun 15 19:21:56 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux

stackplz v2.1.4

使用pid抓取syscall,无反应

ps -ef | grep setting

system 19849 16944 0 19:06:38 ? 00:00:51 com.android.settings

./stackplz-v3 -p 19849 -s all --nocheck

findBTFAssets btf_file=a12-5.10-arm64_min.btf
[*] save maps to maps_19849.txt
hook syscall count:306
ConfigMap{stackplz_pid=30461,thread_whitelist=0}
uid => whitelist:[];blacklist:[]
pid => whitelist:[19849];blacklist:[]
tid => whitelist:[];blacklist:[]
start 2 modules

使用pid抓取syscall时,无反应。
表现为可以正常启动stackplz,但是操作时,无syscall输出

[feature request] 采用ringbuf读取传递数据

目前stackplz用的是常规的PerfMap传递数据,比较耗费资源,在某些调用特别高频的时候下会出现大量数据丢失(虽然改用了tracee的方式传递数据好了很多,但...)

上游ebpfmanager已经添加了ringbuf map的支持,ringbuf效率更高

gojue/ebpfmanager#35

但是为了传递其他的FLAG以获取更多参数,ebpfmanager和ebpf库都有所修改,需要进行合并适配

Is replace filter deprecated?

Based on this post you can set a filter starting with 'r:' that will replace the argument for another one of your choice (specified with :::)

This filter seems not to be valid anymore but I am really interested on it. Is there any workaround that I could do to have the same effect? Can you help me?

[feature request] 读取超大数据

map create: cannot allocate memory

当前基于ebpf的数据传递是有上限的,单次数据提交无法超过32K,即使缓冲区可以设置到64M甚至128M

需要设计一种方案提高数据大小上限。

设想一:

多次传递数据,例如单次4K*1024次

设想二:

uprobe + shellcode,可以在命中hook点的时候写入shellcode,shellcode做完操作之后,再跳转回到之前下的hook点

不同于一般的inlinehook,uprobe相当于是单个指令就能实现中断,那么我们可以把shellcode就直接放在hook点后面,执行完成之后跳转回来,再还原指令

例如A是uprobe下的点,在命中A的时候,将A-B之间改为shellcode,shellcode最终会间接跳转回到A,这个时候我们再把原本的指令还原回去;这样没有必要去开辟新的内存空间,当然只适合一些简短的shellcode,基于这个思路也能实现对寄存器的修改(应该

image

设想三:

基于ebpf的硬件断点,参考bpftrace,但是初步看起来应该只能支持计数,最多加一个获取寄存器信息,要读数据似乎不可行

设想四:

提示用户在定位到关键点后,使用内核模块去获取数据(或者用CE之类的),这个也是基于硬件断点的

https://github.com/junknet/kernel-debugger

低版本4.14内核报错,这个咋解决?

cannon:/data/local/tmp # uname -a
Linux localhost 4.14.186-perf-g7c6a9bff2dc6 #1

cannon:/data/local/tmp # ./stackplz --name  com.xxx .xxx stack --config config.json
stack_2022/11/17 02:54:56 StackMod	hook info:libc.so + open
stack_2022/11/17 02:54:56 StackMod	module Run failed, [skip it]. error:couldn't start bootstrap manager error:1 error occurred:
	* error:opening uprobe: creating trace event '/apex/com.android.runtime/lib64/bionic/libc.so:open' in tracefs: creating probe entry on tracefs: error opening '/sys/kernel/debug/tracing/uprobe_events': open /sys/kernel/debug/tracing/uprobe_events: no such file or directory , isRet:false, {UID:, `EbpfFuncName:probe_stack}

可否加一些过滤条件?

可能是我刚学会用,按照目前看到的教程,使用效果很不错,但log太多了,比如:./stackplz --name com.wodi.who stack --symbol strstr ,可否指定只输出来自某个so的调用,或者只输出指定--name的调用?

illegal structures

Can this only run in a real machine environment? 64 bit anroid-emulators will report illegal structures

Error: unknown flag: --nr

使用最新版本的2.0.beta6。
PIxel6,Android13,Linux localhost 5.10.149-android13-4-gebdbc9fbe2e2-dirty #1 SMP PREEMPT Mon Feb 27 10:44:09 UTC 2023 aarch64 Toybox

事例:3.追踪系统调用时的堆栈,以及寄存器信息,支持按pid过滤

./stackplz --name com.lemon.lv --pid 11267 syscall --nr 63 --regs --stack

尝试测试自己写的demo

oriole:/data/local/tmp # ./stackplz-20b6  --name com.debug.cdemo --pid 11419 syscall --nr 63 --regs --stack
Error: unknown flag: --nr

Report:error:uid is 0, libc.so + pthread_create

./stackplz --name com.p1.mobile.putong stack --symbol pthread_create --reg x2 -o tmp.log
stack_2023/05/31 01:42:43 StackMod hook info:libc.so + pthread_create
stack_2023/05/31 01:42:43 StackMod module Run failed, [skip it]. error:uid is 0, libc.so + pthread_create
stack_2023/05/31 01:42:43 No runnable modules, Exit(1)

报错如上?为什么uid为0不能用呢?

[feature request] 开发WEB GUI

该特性短期内可能无法实现

WEB GUI的好处:

  • 操作更直观
  • 采集结果可以更自由组合分类、排序
  • 更好看

另外可以开放能力给第三方开发者

--stack堆栈回溯出现Segmentation fault

云真机,https://aochenyun.com/index.html
这个云真机官方采用的是rk3588开发板
内核是5.10.110-2.6.2.lxc,
其他功能都能正常使用,
但是一加上--stack命令进行堆栈回溯时便会出现Segmentation fault,从2.1.4到最新版都是出现Segmentation fault
这是libunwindstack.so这个库与这个云真机不匹配的原因么
输入:
./stackplz -n mark.via --syscall sendto --dumphex --stack
输出:
uid => whitelist:[10101];blacklist:[]
pid => whitelist:[29842];blacklist:[]
tid => whitelist:[];blacklist:[]
start 2 modules
Segmentation fault

小建议

有没有考虑加个修改寄存器值的功能啊

dev 分支执行命令报错

环境:Redmi Note 11T Pro android 13 miui 14 内核为:5.10.101-android12-9-00027-g1292f517889e-ab8602202
执行命令: ./stackplz -n ???.???.???,iso -w popen[str.f0.f1] -f r:mount:::mounx -f "r:which su:::which zz" --stack
报错内容:

findBTFAssets btf_file=a12-5.10-arm64_min.btf
hook uprobe, count:1
StackMod module Run failed, [skip it]. error:couldn't start bootstrap manager error:1 error occurred:
* error:opening uprobe: creating perf_uprobe PMU: token :0xe5230: opening perf event: invalid argument , isRet:false, opts:&{0 0 0 0 0 false }, {UID:, EbpfFuncName:probe_stack_0}

, probes activation validation failed .

Android T 部分系统进程及系统 APP 无法 Hook

大佬好,我在 Android T 版本的 Pixel 4 上使用 stackplz 后发现部分系统进程及系统 APP 无法 Hook

./stackplz --name com.android.systemui syscall --nr 63 --regs --stack
Error: not support package=com.android.systemui primaryCpuAbi=null
./stackplz --name android syscall --nr 63 --regs --stack
Error: not support package=android primaryCpuAbi=null

能否像 uprobe_events 那样不用必须指定 name 或 uid,直接指定 so 的路径即可 hook 呢?

这样就方便 hook surfaceflinger 等没有在 dumpsys package 里的进程了。

硬件断点 读取操作 无效

硬件断点示例如下,支持的断点类型:r,w,rw,x
测试过程
:按照实例执行
./stackplz --pid pidof com.taobao.taobao --brk 0x70ddfd63f0:r
./stackplz --pid pidof com.taobao.taobao --brk 0x70ddfd63f0:rw

目标进程循环读取指定位置字节 ,使用绝对内存地址,地址为libart.so RegisterNative函数处

使用自编写apk读取也无法触发读断点

期望结果:
触发读取事件

测试结果:
未触发任何事件

测试环境:
真机pixel6 android13 lineageos系统 软件为lastest release版本

[FR] 回溯堆栈时打印原始PC值

有些加固后的 so 可能显示的是基于[anon:.bss] 的偏移,但是这种有多个,无法确定具体是哪个,可以加一个选项打印原始PC值

[FR] 快速发送SIGCONT

当使用 --kill SIGSTOP 的时候,直接在 CLI 里面 回车就发送 SIGCONT,让对应进程继续运行

android12下无法使用

/stackplz stack --prepare
< 2022/12/08 01:44:44 Kernel config read failed, error:Config disabled, item :CONFIG_UPROBES.

uname -r

4.9.270-g862f51bac900-ab7613625
是内核不够版版吗?

报错

panic: unexpected EOF

goroutine 13 [running]:
stackplz/user/argtype.parse_STRING_ARRAY({0x77a6caca68?, 0x20?}, 0x4000316d08?, 0x598df06478?, 0x0?)
/home/runner/work/stackplz/stackplz/user/argtype/argtype_complex.go:91 +0x3a0
stackplz/user/argtype.(*ARG_STRUCT).Parse(0x598e02a2e0?, 0x40000aab10?, 0x590000003a?, 0x70?)
/home/runner/work/stackplz/stackplz/user/argtype/argtype_base.go:631 +0x70
stackplz/user/config.(*PointArg).Parse(0x598e097940?, 0x4001cec9f0?, 0x598e09bb00?, 0x8e47c238?)
/home/runner/work/stackplz/stackplz/user/config/config_point_arg.go:116 +0x88
stackplz/user/config.(*SyscallPoint).ParseEnterPoint(0x40010136c0?, 0x598e005c00?)
/home/runner/work/stackplz/stackplz/user/config/config_syscall.go:55 +0xd8
stackplz/user/event.(*SyscallEvent).ParseContext(0x40010136c0)
/home/runner/work/stackplz/stackplz/user/event/event_raw_syscalls.go:56 +0x260
stackplz/user/event.(*SyscallEvent).ParseEvent(0x40010136c0)
/home/runner/work/stackplz/stackplz/user/event/event_raw_syscalls.go:31 +0x4c
stackplz/user/event_processor.(*EventProcessor).dispatch(0x40002ee920, {0x598e09c130, 0x40010136c0})
/home/runner/work/stackplz/stackplz/user/event_processor/processer.go:55 +0x48
stackplz/user/event_processor.(*EventProcessor).Serve(0x40002ee920)
/home/runner/work/stackplz/stackplz/user/event_processor/processer.go:41 +0x44
stackplz/user/module.(*Module).Run.func2()
/home/runner/work/stackplz/stackplz/user/module/imodule.go:128 +0x28
created by stackplz/user/module.(*Module).Run
/home/runner/work/stackplz/stackplz/user/module/imodule.go:127 +0xc0

报错

BrkMod readEvents error:creating PerfEventArray(brk_events)#3 reader dns: failed to create perf ring for CPU 0: can't create perf event: no space left on device
这种情况是被监听软件自己给自己下断点占用位置防止被监听吗

[feature request] 事件信息输出json

将详细的结果输出为json,特别是包含时间信息,这样用户可以自行处理需要的数据,特别是计算偏移这种会更加方便。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.