Frida 进阶:脱壳、自动化、objection 内存漫游、hook anywhere、Wallbreaker插件、fridaUiTools

转载:实用FRIDA进阶:内存漫游、hook anywhere、抓包:https://www.anquanke.com/post/id/197657

frida github 地址:https://github.com/frida/frida
objection github:https://github.com/sensepost/objection
objection pypi:https://pypi.org/project/objection/

本章中我们进一步介绍,大家在学习和工作中使用 Frida 的实际高频场景,比如:

  • 动态查看 安卓应用程序 在当前内存中的状态
  • 指哪儿就能 hook 哪儿
  • 比如 脱壳,
  • 还有使用 Frida 来自动化获取参数、返回值等数据,
  • 主动调用 API 获取签名结果 sign 等。。。

最后介绍一些经常遇到的高频问题解决思路,希望可以切实地帮助到读者。

Frida进阶:脱壳、自动化、高频问题

实用 FRIDA 进阶:脱壳、自动化、高频问题

Frida 用于脱壳

  • 文件头搜dex:https://github.com/r0ysue/frida_dump
  • DexClassLoader:objection:安卓只能使用继承自BaseDexClassLoader的两种ClassLoader,一种是PathClassLoader,用于加载系统中已经安装的apk;一种就是DexClassLoader,加载未安装的jar包或apk。 可以用objcetion直接在堆上暴力搜索所有的dalvik.system.DexClassLoader实例,:android heap search instances dalvik.system.DexClassLoader
  • 暴力搜内存:DEXDump:https://github.com/hluwa/FRIDA-DEXDump 对于完整的dex,采用暴力搜索dex035即可找到。而对于抹头的dex,通过匹配一些特征来找到,然后自动修复文件头。
  • 暴力搜内存:objection 既然直接使用Frida的API可以暴力搜索内存,objection也可以暴力搜内存。命令:memory search "64 65 78 0a 30 33 35 00"

远程调用(RPC)
反调试基本思路
打印 byte[] [B

hook管理子进程

经常有人会问,像那种com.xxx.xxx:push、com.xxx.xxx:service、com.xxx.xxx:notification、com.xxx.xxx:search这样的进程如何hook,或者说如何在其创建伊始进行hook,因为这样的进程一般都是由主进程fork()出来的。 这种的就要用到Frida最新的Child gating机制,可以参考我的过往的文章,官方的完整代码在这里( https://github.com/frida/frida-python/blob/main/examples/child_gating.py )。可以在进程创建之初对该进程进行控制和hook,已经很多人用了,效果很好,达成目标。

hook混淆方法名

有些方法名上了很强的混淆,如何处理?其实很简单,可以看上面ZenTracer的源码,hook类的所有子类,hook类的所有方法,并且hook方法的所有重载。

中文参数问题

hook某些方法的时候,发现传进来的参数竟然是中文的,如何打印出来?如果是utf8还好,Frida的CLI也是直接支持utf8的,如果是GBK字符集的,目前没有找到在js里进行打印的方法,可以send()到电脑上进行打印。

hook主动注册

使用Frida来hook JNI的一些函数,打印出主动调用的执行路径。
https://github.com/lasting-yang/frida_hook_libart

追踪JNI API

https://github.com/chame1eon/jnitrace

延迟hook

很多时候在带壳 hook 的时候,善用两个 frida 提供的延时 hook 机制:

  • frida --no-pause是进程直接执行,有时候会hook不到,如果把--no-pause拿掉,进入CLI之后延迟几秒再使用%resume恢复执行,就会hook到;
  • js 中的 setTimeout(func, delay[, ...parameters]) 函数,会延时 delay 毫秒来调用 func,有时候不加延时会 hook 不到,加个几百到几千毫秒的延时就会 hook 到。

fridaUiTools

菜鸟学飞之frida整合怪:https://bbs.kanxue.com/thread-268219.htm

github:https://github.com/dqzg12300/fridaUiTools

  1. fridaUiTools整合怪

  1. ZenTracer
  2. r0capture
  3. jnitrace/JNI-Frida-Hook
  4. DroidSSLUnpinning
  5. stalker
  6. frida_hook_libart
  7. frida_dump
  8. fart
  9. Wallbreaker

Frida GUI 工具

https://zhuanlan.zhihu.com/p/603913742

Objection 简单使用

安装 objection

Frida 只是提供了各种 API 供我们调用,在此基础之上可以实现具体的功能,比如禁用证书绑定之类的脚本,就是使用 Frida 的各种 API 来组合编写而成。于是有大佬将各种常见、常用的功能整合进一个工具,供我们直接在命令行中使用,这个工具便是objectionobjection 功能强大,命令众多,而且不用写一行代码,便可实现诸如内存搜索、类和模块搜索、方法hook打印参数返回值调用栈等常用功能,是一个非常方便的,逆向必备、内存漫游神器。

安装命令:pip3 install objection
查看帮助:objection --help

objection 是基于 frida 的命令行 hook 工具,可以让你不写代码, 敲几句命令就可以对 java 函数的高颗粒度 hook, 还支持 RPC 调用

objection 目前只支持 Java层的 hook,但是 objection 有提供插件接口,可以自己写 frida 脚本去定义接口,

比如葫芦娃大佬的脱壳插件,实名推荐: https://github.com/hluwa/FRIDA-DEXDump

官方仓库: https://github.com/sensepost/objection

objection 命令行 帮助

更多命令行参数 ( 命令行没有显示的参数 ) 可以查看 cli.py 文件得到:https://github.com/sensepost/objection/blob/master/objection/console/cli.py

启动 frida 并加载 js 脚本

adb forward tcp:27042 tcp:27042

frida -U -l js_okhttp.js     -F com.cdsb.newsreader --no-pause
frida -U -l okhttp_poker.js  -F com.cdsb.newsreader --no-pause
frida -U -l okhttp_poker.js  -F com.huanqiu.news --no-pause
frida -U -l frida_hook_js.js -f com.huanqiu.news --no-pause

启动 objection 并加载插件

objection -g com.android.settings explore -c "2.txt"    运行批量hook

objection -g com.app.name explore -P ~/objection/plugins
objection -g com.cdsb.newsreader explore -P objection_plugins

python r0capture.py -U -f com.cdsb.newsreader -v
python r0capture.py -U com.cdsb.newsreader -v -p cdsb.pcap

objection -g "com.ss.android.ugc.aweme" explore    // 通过 "包名" 好像是 spawn 方式
objection -g "抖音" explore                        // 通过 "软件名" 是 attach 方式

查看 objection 日志

cat .objection/objection.log    日志查看
cat objection.log |grep -i http    日志筛选

进入 objection 后 的 所有命令

进入 objection 后的几个基本操作:

  • 键入命令之后,回车执行;
  • help: 不知道当前命令的效果是什么,在当前命令前加 help 比如:help env,回车之后会出现当前命令的解释信息;
  • 按 空格、tab: 不知道输入什么就按空格,会有提示出来,上下选择之后再按空格选中,又会有新的提示出来;
  • jobs: 作业系统很好用,建议一定要掌握,可以同时运行 多项 ( hook ) 作业

!             # 执行操作系统的命令(注意:不是在所连接device上执行命令)
android     # 执行指定的 Android 命令
        clipboard
                monitor
        deoptimize    # Force the VM to execute everything in the interpreter
        heap
                evaluate    # 在 Java 类中执行 JavaScript 脚本。
                execute     # 在 Java 类中执行 方法。android heap execute 实例ID 实例方法
                print
                search
                        instances  # 在当前Android heap上搜索类的实例。android heap search instances 类名
        hooking
                generate
                        class    #  A generic hook manager for Classes
                        simple   #  Simple hooks for each Class method
                get
                        current_activity    #  获取当前 前景(foregrounded) activity
                list
                        activities    # 列出已经登记的 Activities
                        class_loaders # 列出已经登记的 class loaders 
                        class_methods # 列出一个类上的可用的方法
                        classes       # 列出当前载入的所有类
                        receivers     # 列出已经登记的 BroadcastReceivers
                        services      # 列出已经登记的 Services
                search
                        classes 关键字    # 搜索与名称匹配的Java类
                        methods 关键字    # 搜索与名称匹配的Java方法
                set
                        return_value    # 设置一个方法的返回值。只支持布尔返回
                watch
                        class           # Watches for invocations of all methods in a class
                        class_method    # Watches for invocations of a specific class method
        intent
                launch_activity    # 使用Intent启动Activity类
                launch_service     # Launch a Service class using an Intent
        keystore
                clear    # 清除 Android KeyStore
                list     # 列出 Android KeyStore 中的条目
                watch    # 监视 Android KeyStore 的使用
        proxy    
                set      # 为应用程序设置代理
        root
            disable    # 试图禁用 root 检测
            simulate   # 试图模拟已经 root 的环境
        shell_exec     # 执行shell命令
        sslpinning
                disable    # 尝试禁用 SSL pinning 在各种 Java libraries/classes
        ui
            FLAG_SECURE    # Control FLAG_SECURE of the current Activity
            screenshot     # 在当前 Activity 进行截图
cd          # 改变当前工作目录
commands        
        clear    # 清除当前会话命令的历史记录
        history  # 列出当前会话命令历史记录
        save     # 将在此会话中运行的所有惟一命令保存到一个文件中
env         # 打印环境信息
evaluate    # 执行 JavaScript。( Evaluate JavaScript within the agent )
exit        # 退出
file
        cat         # 打印文件内容
        download    # 下载一个文件
        http        
                start    # Start's an HTTP server in the current working directory
                status   # Get the status of the HTTP server
                stop     # Stop's a running HTTP server
        upload           # 上传一个文件
frida       # 获取关于 frida 环境的信息
import      # 从完整路径导入 frida 脚本并运行
ios         执行指定的 ios 命令
        bundles
        cookies
        heap
        hooking
        info
        jailbreak
        keychain
        monitor
        nsurlcredentialstorage
        nsuserdefaults
        pasteboard
        plist
        sslpinning
        ui
jobs
        kill    # 结束一个任务。这个操作不会写在卸载或者退出当前脚本
        list    # 列出当前所有的任务
ls              # 列出当前工作目录下的文件
memory
        dump
                all 文件名                      # Dump 当前进程的整个内存
                from_base 起始地址 字节数 文件  # 将(x)个字节的内存从基址转储到文件
        list
                exports    # List the exports of a module. (列出模块的导出)
                modules    # List loaded modules in the current process. (列出当前进程中已加载的模块)
        search    # 搜索模块。用法:memory search "<pattern eg: 41 41 41 ?? 41>" (--string) (--offsets-only)
        write     # 将原始字节写入内存地址。小心使用!
ping        # ping agent
plugin      
        load    # 载入插接
pwd             # 打印当前工作目录
reconnect       # 重新连接 device
rm              # 从 device 上删除文件 
sqlite          # sqlite 数据库命令
        connect  # 连接到SQLite数据库文件
ui
        alert    # 显示警报消息,可选地指定要显示的消息。(目前iOS崩溃)

进入 objection 后 的 常用命令

https://blog.csdn.net/weixin_42453905/article/details/109395414

objection 改源码,解决 app 的双进程保护 和 双进程保护原理

采用双进程的方式,对父进程进行保护,基于信号的发送和接收,实现相互的保护防止被动态攻击。简单的双进程保护就是从原进程再fork一个空进程出来,让逆向分析的时候附加到空进程中导致hook不上。双进程进程保护主要功能: 1、保护父进程,ptrace所有线程,防止被附加、调试、暂停; 2、保护子进程,防止被暂停、异常退出;

objection 当用 spwan 方式时,就会触发 双进程防护,需要修改 objection 源码

def get_session(self) -> frida.core.Session: 函数修改。

         ###################################################################
        debug_print('Resuming PID test {pid}'.format(pid=self.spawned_pid))
        self.device.resume(self.spawned_pid)
        self.session = self.device.attach(self.spawned_pid)
        ###################################################################

inject 函数修改的部分 ( 不需要添加代码,直接注释掉 )

效果:( 没修改之前直接报错,修改后可以正常进入 objection )

help frida             # 不知道当前命令的作用时,进入objection后就在命令前加 help 会有提示

objection -g 包名 explore     # 注入进程,如果进程没有启动,会以spwan方式启动进程
objection -N -h 192.168.1.3 -p 9999 -g 包名 explore    # 指定ip和端口的连接

# spawn启动前就Hook
objection -N -h 192.168.1.3 -p 9999 -g 包名 explore --startup-command "android hooking watch class '包名.类名'"
# 示例:hook方法的参数、返回值和调用栈,这种实现方式是 启动的时候就 hook
objection -g com.hd.zhibo explore --startup-command "android hooking watch class_method android.app.AlertDialog.onCreate --dump-args --dump-backtrace --dump-return"

# spawn启动前就Hook 打印参数、返回值、函数调用栈
objection -N -h 192.168.1.3 -p 9999 -g 包名 explore --startup-command "android hooking watch class_method '包名.类名.方法'  --dump-args --dump-return --dump-backtrace"

android hooking list classes                    # 列出内存中所有的类
android hooking search classes 关键字           # 在内存中所有已加载的类中搜索包含特定关键词的类
android hooking list class_methods 包名.类名    # 列出类的所有方法

android hooking search methods 关键字         # 在内存中所有已加载的类的方法中搜索包含特定关键词的类

android hooking list services                  # 查看可供开启的服务
android intent launch_service 完整Service名      # 启动 指定 服务

android hooking list activities                  # 列出 所有可用 activities
android intent launch_activity 类名              # 启动 指定的 activities

android hooking watch class 类名    
android hooking watch class 包名.类名       # hook类的所有方法。监视进行某个操作的时候调用了哪些方法
android hooking watch class_method 包名.类名.方法  # 默认会Hook方法的所有重载

# hook方法的参数、返回值和调用栈(–dump-args: 显示参数; --dump-return: 显示返回值; --dump-backtrace: 显示堆栈)
android hooking watch class_method 包名.类名.方法 --dump-args --dump-return --dump-backtrace
#示例:具体方法调用之前 hook输出结果依次是:调用堆栈、参数、返回值
android hooking watch class_method android.app.AlertDialog.onCreate --dump-args --dump-return --dump-backtrace

android hooking search classes okhttp3
android hooking watch class okhttp3.OkHttpClient --dump-args --dump-return
android hooking watch class_method okhttp3.OkHttpClient.newCall --dump-args --dump-backtrace --dump-return

# 如果只需hook其中一个重载函数 指定参数类型 多个参数用逗号分隔
android hooking watch class_method 包名.类名.方法 "参数1,参数2"

android sslpinning disable      # 禁用 SSL,过 ssl 证书认证
android root disable          # 禁用 root

env    应用环境信息
ls    
jobs list                     # 查看 hook 的任务有多少个
jobs kill jobid               # 把正在 hook 的任务关闭

android heap search instances 包名.类名 --fresh    # 搜索堆中的实例
android heap execute 地址(hashcode的地址) 方法名   # 调用实例的方法

android hooking generate simple 类名    # 生成 指定类 的 hook 代码

memory list modules              # 枚举内存中所有模块(即so库)
memory list exports 文件名.so    # 枚举模块中所有导出函数
# 示例:memory list exports libssl.so    查看库的导出函数
memory dump all from_base    提取整个(或部分)内存
memory dump from_base 0xc935628c 100 memory.dex    
memory search "64 65 78 0a 30 33 35 00"     # 暴力搜内存
memory search "aiyou,bucuoo" --string     # 搜索整个内存
memory search "aiyou,bucuoo" --string --offsets-only    # 仅看偏移地址

memory 操作

# 列举加载的 modules,也就是so文件
        memory list modules
        memory list modules --json result.txt

# 列举 so 文件的导出方法
        memory list exports xxx.so

# dump所有内存
        memory dump all /tmp/dump

# dump内存指定地址和大小
        memory dump from_base 0x130b4060 1024 /tmp/dump

# 在内存搜索
        memory search "64 65 78 0a 30 33 35 00"
        memory search "99999999999" --string
        memory search "66 72 ?? ?? 61"

# 修改内存
        memory write 0x130b4060 "99999999999" --string

activity / services / receivers 组件相关

# 列出应用程序具有的组件
        android hooking list activities
        android hooking list services
        android hooking list receivers

# 获取当前activity
        android hooking get current_activity

# 启动某个activity
        android intent launch_activity com.xxx.xxx.Activity

# 启动某个service
        android intent launch_service xxxx

class / method 相关

# 列举所有加载的类
        android hooking list classes

# 查找已加载的类中带有关键词的类
        android hooking search classes xxx

# 查看xx类有哪些方法
        android hooking list class_methods com.xx.xx

# 在内存中所有已加载的类的方法中搜索包含特定关键词的方法
        android hooking search methods xxx

# 查找所有类的实例
        android heap search instances xxx

# 主动调用指定实例的函数
        android heap execute instance_ID function

# hook指定类的所有方法, 会打印该类下的所有调用
        android hooking watch class com.xxx.xxx            

# hook指定方法, 如果有重载会hook所有重载
        android hooking watch class_method com.xxx.xxx.methodName

# 以上命令支持下面参数
# --dump-args : 打印参数
# --dump-backtrace : 打印调用栈
# --dump-return : 打印返回值
# eg:
android hooking watch class_method com.xxx.xxx.methodName --dump-args --dump-backtrace --dump-return
android hooking set return_value com.xxx.xxx.methodName false    # 设置返回值(只支持bool类型)


# 生成某个类的hook js代码
        android hooking generate  simple  com.xxx.xxx

任务管理

# 列举出当前任务
        jobs list

# 关闭任务
        jobs kill [job_id]

文件操作

# 文件基本操作
        ls
        file download
        file upload
        file cat

# 文件服务器,在当前目录下启动一个http server
        file http start/stop/status

抓包

#关闭ssl校验
        android sslpinning disable

其他操作

# 打印出应用程序文件、缓存和其他目录的位置
        env

# 对APP隐藏root
        android root disable 

# 执行命令
        android shell_exec ls 

# 截屏
        android ui screenshot /sdcard/1.png

# 导入外部 js 脚本
        import 1.js 

日志

objection日志文件位于:

        ~/.objection/objection.log

命令历史文件位于:

~/.objection/objection_history
删除 ~/.objection目录后,在下次 objection 启动时会重新创建。

参考:https://github.com/sensepost/objection/wiki/Using-objection

1. 内存漫游

1.1 获取基本信息

简单使用

  • 启动 Frida-server,并转发端口 ( adb forward tcp:27042 tcp:27042 )
  • 附加需要调试的 app,进入交互界面 ( objection -g [packageName] explore )

连接逍遥模拟器,需要先进入模拟器所在目录,使用目录中 adb.exe 命令执行:adb.exe connect 127.0.0.1:21503

可以使用该 env 命令枚举与所讨论的应用程序相关的其他有趣目录:env

可以使用以下 file download 命令从远程文件系统中下载文件:file download [file] [outfile]

com.opera.mini.native on (samsung: 6.0.1) [usb] # file download fhash.dat fhash.dat
Downloading /data/user/0/com.opera.mini.native/cache/fhash.dat to fhash.dat

可以列出 app 具有的所有avtivity:android hooking list activities

com.opera.mini.native on (samsung: 6.0.1) [usb] # android hooking list activities
com.facebook.ads.AudienceNetworkActivity
com.google.android.gms.ads.AdActivity
com.google.android.gms.auth.api.signin.internal.SignInHubActivity
com.google.android.gms.common.api.GoogleApiActivity
com.opera.android.AssistActivity
com.opera.android.MiniActivity
com.opera.android.ads.AdmobIntentInterceptor
com.opera.mini.android.Browser
 
Found 8 classes

启动指定 avtivity:android intent launch_activity [class_activity]

com.opera.mini.native on (samsung: 6.0.1) [usb] # android intent launch_activity 
com.facebook.ads.AudienceNetworkActivity
Launching Activity: com.facebook.ads.AudienceNetworkActivity...

RPC 调用命令:curl -s "http://127.0.0.1:8888/rpc/invoke/androidHookingListActivities"

$ curl -s "http://127.0.0.1:8888/rpc/invoke/androidHookingListActivities"
["com.reddit.frontpage.StartActivity","com.reddit.frontpage.IntroductionActivity", ... snip ...]
 
- RPC调用执行脚本:`url -X POST -H "Content-Type: text/javascript" http://127.0.0.1:8888/script/runonce -d "@script.js"`
 
$ cat script.js
{
    send(Frida.version);
}
 
[{"payload":"12.8.0","type":"send"}]

RPC WIKIhttps://github.com/sensepost/objection/wiki/API

API 介绍

以下只是写了一部分指令和功能, 详细的功能需要合理运用 空格 和 help


Memory 指令
    memory list modules               //枚举当前进程模块
    memory list exports [lib_name]    //查看指定模块的导出函数
    memory list exports libart.so --json /root/libart.json //将结果保存到json文件中
    memory search --string --offsets-only                  //搜索内存

android heap 指令
    //堆内存中搜索指定类的实例, 可以获取该类的实例id
    search instances search instances com.xx.xx.class
     
    //直接调用指定实例下的方法
    android heap execute [ins_id] [func_name]
     
    //自定义frida脚本, 执行实例的方法
    android heap execute [ins_id]

android 指令
    android root disable   //尝试关闭app的root检测
    android root simulate  //尝试模拟root环境
    
    android ui screenshot [image.png]    //截图
    android ui FLAG_SECURE false         //设置FLAG_SECURE权限

内存漫游
    android hooking list classes    //列出内存中所有的类
     
    //在内存中所有已加载的类中搜索包含特定关键词的类
    android hooking search classes [search_name] 
     
    //在内存中所有已加载的方法中搜索包含特定关键词的方法
    android hooking search methods [search_name] 
     
    //直接生成hook代码
    android hooking generate simple [class_name]

hook 方式
    /*
        hook指定方法, 如果有重载会hook所有重载,如果有疑问可以看
        --dump-args : 打印参数
        --dump-backtrace : 打印调用栈
        --dump-return : 打印返回值
    */
    android hooking watch class_method com.xxx.xxx.methodName --dump-args --dump-backtrace --dump-return
     
    //hook指定类, 会打印该类下的所有调用
    android hooking watch class com.xxx.xxx
     
    //设置返回值(只支持bool类型)
    android hooking set return_value com.xxx.xxx.methodName false

Spawn 方式 Hook
    objection -g packageName explore --startup-command '[obejection_command]'

activity 和 service 操作
    android hooking list activities                   //枚举activity
    android intent launch_activity [activity_class]   //启动activity
    android hooking list services                     //枚举services
    android intent launch_service [services_class]    //启动services

任务管理器
    jobs list            // 查看任务列表
    jobs kill [task_id]  // 关闭任务

关闭 app 的 ssl 校验
    android sslpinning disable

监控系统剪贴板
    // 获取Android剪贴板服务上的句柄并每5秒轮询一次用于数据。 
    // 如果发现新数据,与之前的调查不同,则该数据将被转储到屏幕上。
    help android  clipboard

执行命令行
    help android shell_exec [command]
	

插件编写 : objection pluginghttps://github.com/sensepost/objection/wiki/Plugins

不写一行代码探索应用行为 --- 使用 objection

From:https://www.y4f.net/77651.html

这里拿 XCTF 的三个题目做演示,分别是mobile进阶区的第3题、第8题和第17题。

示例:以安卓 内置应用 "设置" 演示基本用法

在手机上启动 frida-server,并且点击启动 "设置" 图标,手机进入设置的界面,首先查看一下 "设置" 应用的包名。

# frida-ps -U|grep -i setting
 7107  com.android.settings
13370  com.google.android.settings.intelligence

再使用 objection 注入 "设置" 应用。

# objection -g com.android.settings explore

启动 objection之后,会出现提示它的 logo,这时候不知道输入啥命令的话,可以按下空格,有提示的命令及其功能出来;
再按空格选中,又会有新的提示命令出来,这时候按回车就可以执行该命令,

见下图 2-2 执行的应用环境信息命令 env 和 frida-server 版本信息命令。

1.2 提取内存信息

1.2.1 查看内存中加载的库( memory list modules )

运行命令 memory list modules,效果如下图2-3所示。内存中加载的库

1.2.2 查看库的导出函数 ( memory list exports libssl.so )

运行命令 memory list exports libssl.so,效果如下图2-4所示。 libssl.so 库的导出函数

1.2.3 将结果保存到 json文件中

当结果太多,终端无法全部显示的时候,可以将结果导出到文件中,然后使用其他软件查看内容,见下图2-5。

# memory list exports libart.so --json /root/libart.json  
Writing exports as json to /root/libart.json...
Wrote exports to: /root/libart.json

使用 json 格式保存的 libart.so 的导出函数

1.2.4 提取整个(或部分)内存( memory dump all from_base )

命令是 memory dump all from_base,这部分内容与下文脱壳部分有重叠,我们在脱壳部分介绍用法。

1.2.5 搜索整个内存( memory search --string --offsets-only )

命令是 memory search --string --offsets-only,这部分也与下文脱壳部分有重叠,我们在脱壳部分详细介绍用法。


1.3 内存堆 (heap上的搜索执行

1.3.1 在堆 (heap)上搜索实例

我们查看AOSP源码关于设置里显示系统设置的部分,发现存在着 DisplaySettings类,可以在堆上搜索是否存在着该类的实例。

首先在手机上点击进入 "显示" 设置,然后运行命令:android heap search instances com.android.settings.DisplaySettings

并得到相应的实例地址:

1.3.2 调用实例的方法

查看源码得知 com.android.settings.DisplaySettings类 有一个 getPreferenceScreenResId()方法,这样就可以直接调用该实例的 getPreferenceScreenResId()方法,

后文也会介绍在objection中直接打印类的所有方法的命令

用 excute 命令:android heap execute 0x2526 getPreferenceScreenResId

Handle 0x2526 is to class com.android.settings.DisplaySettings
Executing method: getPreferenceScreenResId()
2132082764

可见结果被直接打印了出来。

1.3.3 在实例上执行 js 代码

也可以在找到的实例上直接编写 js 脚本,输入android heap evaluate 0x2526 命令后,会进入一个迷你编辑器环境,

  • 输入 console.log("evaluate result:"+clazz.getPreferenceScreenResId()) 这串脚本,
  • 按ESC退出编辑器,然后按回车,即会开始执行这串脚本,输出结果。
# android heap evaluate 0x2526                                          
(The handle at `0x2526` will be available as the `clazz` variable.)

console.log("evaluate result:"+clazz.getPreferenceScreenResId()) 

JavaScript capture complete. Evaluating...
Handle 0x2526 is to class com.android.settings.DisplaySettings
evaluate result:2132082764

这个功能其实非常厉害,可以即时编写、出结果、即时调试自己的代码,不用再:编写→注入→操作→看结果→再调整,而是直接出结果。

1.4 启动 activity 或 service

1.4.1 直接启动 activity

直接上代码,想要进入显示设置,可以在任意界面直接运行以下代码进入显示设置:

# android intent launch_activity com.android.settings.DisplaySettings                      
(agent) Starting activity com.android.settings.DisplaySettings...
(agent) Activity successfully asked to start.

1.4.2 查看当前可用的 activity

可以使用 android hooking list 命令来查看当前可用的 activities,然后使用上述命令进行调起。

# android hooking list activities

com.android.settings.ActivityPicker
com.android.settings.AirplaneModeVoiceActivity
com.android.settings.AllowBindAppWidgetActivity
com.android.settings.AppWidgetPickActivity
com.android.settings.BandMode
com.android.settings.ConfirmDeviceCredentialActivity
com.android.settings.CredentialStorage
com.android.settings.CryptKeeper$FadeToBlack
com.android.settings.CryptKeeperConfirm$Blank
com.android.settings.DeviceAdminAdd
com.android.settings.DeviceAdminSettings
com.android.settings.DisplaySettings
com.android.settings.EncryptionInterstitial
com.android.settings.FallbackHome
com.android.settings.HelpTrampoline
com.android.settings.LanguageSettings
com.android.settings.MonitoringCertInfoActivity
com.android.settings.RadioInfo
com.android.settings.RegulatoryInfoDisplayActivity
com.android.settings.RemoteBugreportActivity
com.android.settings.RunningServices
com.android.settings.SetFullBackupPassword
com.android.settings.SetProfileOwner
com.android.settings.Settings
com.android.settings.Settings
com.android.settings.Settings$AccessibilityDaltonizerSettingsActivity
com.android.settings.Settings$AccessibilitySettingsActivity
com.android.settings.Settings$AccountDashboardActivity
com.android.settings.Settings$AccountSyncSettingsActivity
com.android.settings.Settings$AdvancedAppsActivity

1.4.3 直接启动 service

也可以先使用 android hooking list services 查看可供开启的服务,

然后使用 android intent launch_service com.android.settings.bluetooth.BluetoothPairingService 命令来开启服务。

2. Frida hook anywhere

很多新手在学习 Frida 的时候,遇到的第一个问题就是:无法找到正确的类及子类,无法定位到实现功能的准确的方法,无法正确的构造参数、继而进入正确的重载

这时候可以使用 Frida 进行动态调试,来确定以上具体的名称和写法,最后写出正确的hook代码。


2.1 objection(内存漫游)

2.1.1 列出内存中所有的类

执行命令:android hooking list classes

# android hooking list classes

sun.util.logging.LoggingSupport
sun.util.logging.LoggingSupport$1
sun.util.logging.LoggingSupport$2
sun.util.logging.PlatformLogger
sun.util.logging.PlatformLogger$1
sun.util.logging.PlatformLogger$JavaLoggerProxy
sun.util.logging.PlatformLogger$Level
sun.util.logging.PlatformLogger$LoggerProxy
void

Found 11885 classes

2.1.2 内存中搜索包含特定关键词的类

执行命令:android hooking search classes 关键字。在内存中所有已加载的类中搜索包含特定关键词的类。

示例( 搜索包含关键 display 的 类 ):android hooking search classes display     

# android hooking search classes display
[Landroid.hardware.display.WifiDisplay;
[Landroid.icu.impl.ICUCurrencyDisplayInfoProvider$ICUCurrencyDisplayInfo$CurrencySink$EntrypointTable;
[Landroid.icu.impl.LocaleDisplayNamesImpl$CapitalizationContextUsage;
[Landroid.icu.impl.LocaleDisplayNamesImpl$DataTableType;
[Landroid.icu.number.NumberFormatter$DecimalSeparatorDisplay;
[Landroid.icu.number.NumberFormatter$SignDisplay;
[Landroid.icu.text.DisplayContext$Type;
[Landroid.icu.text.DisplayContext;
[Landroid.icu.text.LocaleDisplayNames$DialectHandling;
[Landroid.view.Display$Mode;
[Landroid.view.Display;
android.app.Vr2dDisplayProperties
android.hardware.display.AmbientBrightnessDayStats
android.hardware.display.AmbientBrightnessDayStats$1
android.hardware.display.BrightnessChangeEvent
com.android.settings.wfd.WifiDisplaySettings$SummaryProvider
com.android.settings.wfd.WifiDisplaySettings$SummaryProvider$1
com.android.settingslib.display.BrightnessUtils
com.android.settingslib.display.DisplayDensityUtils
com.google.android.gles_jni.EGLDisplayImpl
javax.microedition.khronos.egl.EGLDisplay

Found 144 classes

2.1.3 内存中搜索所有的方法

在内存中所有已加载的类的方法中搜索包含特定关键词的方法,上文中可以发现,内存中已加载的类就已经高达11885个了,那么他们的方法一定是类的个数的数倍,整个过程会相当庞大和耗时,见下图2-6。

# android hooking search methods display

内存中搜索所有的方法

2.1.4 列出指定类的所有方法

当搜索到了比较关心的类之后,就可以直接查看它有哪些方法,

比如:我们想要查看 com.android.settings.DisplaySettings 类 有哪些方法,就可以执行命令:android hooking list class_methods com.android.settings.DisplaySettings

# android hooking list class_methods com.android.settings.DisplaySettings                                                                                                                        
private static java.util.List<com.android.settingslib.core.AbstractPreferenceController> com.android.settings.DisplaySettings.buildPreferenceControllers(android.content.Context,com.android.settingslib.core.lifecycle.Lifecycle)
protected int com.android.settings.DisplaySettings.getPreferenceScreenResId()
protected java.lang.String com.android.settings.DisplaySettings.getLogTag()
protected java.util.List<com.android.settingslib.core.AbstractPreferenceController> com.android.settings.DisplaySettings.createPreferenceControllers(android.content.Context)
public int com.android.settings.DisplaySettings.getHelpResource()
public int com.android.settings.DisplaySettings.getMetricsCategory()
static java.util.List com.android.settings.DisplaySettings.access$000(android.content.Context,com.android.settingslib.core.lifecycle.Lifecycle)

Found 7 method(s)

列出的方法与源码相比对之后,发现是一模一样的。

2.1.5 自动生成 hook 代码

上文中在列出类的方法时,还直接把参数也提供了,也就是说我们可以直接动手写 hook 了,既然上述写 hook 的要素已经全部都有了,objection 这个 "自动化" 工具,当然可以直接生成代码。

自动生成 hook 代码的命令:android hooking generate  simple  com.android.settings.DisplaySettings

# android hooking generate  simple  com.android.settings.DisplaySettings

Java.perform(function() {
    var clazz = Java.use('com.android.settings.DisplaySettings');
    clazz.getHelpResource.implementation = function() {

        //

        return clazz.getHelpResource.apply(this, arguments);
    }
});


Java.perform(function() {
    var clazz = Java.use('com.android.settings.DisplaySettings');
    clazz.getLogTag.implementation = function() {

        //

        return clazz.getLogTag.apply(this, arguments);
    }
});


Java.perform(function() {
    var clazz = Java.use('com.android.settings.DisplaySettings');
    clazz.getPreferenceScreenResId.implementation = function() {

        //

        return clazz.getPreferenceScreenResId.apply(this, arguments);
    }
});

生成的代码大部分要素都有了,只是参数貌似没有填上,还是需要我们后续补充一些,看来还是无法做到完美。

2.2 objection(hook)

上述操作均是基于在内存中直接枚举搜索,已经可以获取到大量有用的静态信息,我们再来介绍几个方法,可以获取到执行时动态的信息,当然、同样地,不用写一行代码。

2.2.1 hook类的所有方法

我们以手机连接蓝牙耳机播放音乐为例,看看手机蓝牙接口的动态信息。

  • 首先我们将手机连接上我的蓝牙耳机(一加蓝牙耳机OnePlus Bullets Wireless 2),并可以正常播放音乐;
  • 然后我们按照上文的方法,搜索一下与蓝牙相关的类,搜到一个高度可疑的类:android.bluetooth.BluetoothDevice
  • 运行命令,hook 这个类:# android hooking watch class android.bluetooth.BluetoothDevice

使用 jobs list 命令可以看到 objection 为我们创建的 Hooks 数为 57也就是将 android.bluetooth.BluetoothDevice类 下的所有方法都 hook了。这时候我们在 设置→声音→媒体播放到上进行操作,在蓝牙耳机与“此设备”之间切换时,会命中这些hook之后,此时objection就会将方法打印出来,会将类似这样的信息“吐”出来:

com.android.settings on (google: 9) [usb] # (agent) [h0u5g7uclo] Called
android.bluetooth.BluetoothDevice.getService()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.isConnected()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getService()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAliasName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAlias()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getService()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.isConnected()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getService()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAliasName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAlias()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBondState()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAliasName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAlias()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBatteryLevel()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.equals(java.lang.Object)
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getBondState()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAliasName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getAlias()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getName()
(agent) [h0u5g7uclo] Called android.bluetooth.BluetoothDevice.getService()

可以看到我们的切换操作,调用到了 android.bluetooth.BluetoothDevice 类中的多个方法。

2.2.2 hook 方法的参数、返回值、调用栈

在这些方法中,我们对哪些方法感兴趣,就可以查看哪些个方法的参数、返回值和调用栈,比如想看 getName()方法,则运行以下命令:# android hooking watch class_method android.bluetooth.BluetoothDevice.getName --dump-args --dump-return --dump-backtrace

​编辑

注意最后加上的三个选项 --dump-args --dump-return --dump-backtrace,为我们成功打印出来了我们想要看的信息,其实返回值 Return Value 就是 getName()方法的返回值,我的蓝牙耳机的型号名字 OnePlus Bullets Wireless 2;从调用栈可以反查如何一步一步调用到 getName()这个方法的;虽然这个方法没有参数,大家可以再找个有参数的试一下。

2.2.3 hook 方法的所有重载

objection 的 help 中指出,在 hook 给出的单个方法的时候,会 hook 它的所有重载

# help android hooking watch class_method
Command: android hooking watch class_method

Usage: android hooking watch class_method <fully qualified class method> <optional overload>
       (optional: --dump-args) (optional: --dump-backtrace)
       (optional: --dump-return)

Hooks a specified class method and reports on invocations, together with
the number of arguments that method was called with. This command will
also hook all of the methods available overloads unless a specific    
overload is specified. 

If the --include-backtrace flag is provided, a full stack trace that 
lead to the methods invocation will also be dumped. This would aid in 
discovering who called the original method.     

Examples: 
   android hooking watch class_method com.example.test.login
   android hooking watch class_method com.example.test.helper.executeQuery 
   android hooking watch class_method com.example.test.helper.executeQuery 
                                      "java.lang.String,java.lang.String"
   android hooking watch class_method com.example.test.helper.executeQuery --dump-backtrace
   android hooking watch class_method com.example.test.login --dump-args --dump-return

那我们可以用 File 类的构造器来试一下效果。

# android hooking watch class_method java.io.File.$init --dump-args

可以看到 objection 为我们 hook 了 File 构造器的所有重载,一共是6个。在设置界面随意进出几个子设置界面,可以看到命中很多次该方法的不同重载,每次参数的值也都不同,

见下图。 方法重载的参数和值都不同

2.3 objection 插件 --- Wallbreaker

葫芦娃 github:https://github.com/hluwa?tab=repositories

Wallbreaker:从内存里面进行 逆向

Wallbreaker 是一个有用的工具,用于实时分析 Java 堆,由frida提供支持。提供一些命令从内存中搜索对象或类,并精美地可视化目标的真实结构。

想知道真实的数据内容吗?项目清单?地图条目?想知道接口的实现吗?尝试一下!你所看到的就是你得到的!

使用方法:参看 github:https://github.com/hluwa/Wallbreaker

使用 Wallbreaker 快速分析 Java 类/对象结构

From:https://bbs.pediy.com/thread-260110.htm

Wallbreaker 取自 wikipedia 上对《三体》"破壁者"的翻译。

wallbreaker 是一个超级懒人(我)为了减少编写重复性垃圾代码而产生的一个工具,主要作用是将内存中 Java 类或对象的结构数据进行可视化。

就像介个亚子:

应用场景

如何使用

目前我是比较喜欢以 objection 插件的形式来使用,本来我也想自己写交互式控制台,但我觉得 objection 已经写得挺好,直接上车就好了,所以暂时不打算自己实现了。
开发的时候就使用 ipython 或者写 testcase 调试。

  1. 安装 objection:pip3 install objection
  2. 下载 wallbreaker 到自己的插件目录:git clone https://github.com/hluwa/Wallbreaker ~/.objection/plugins/Wallbreaker
  3. 启动 frida-server,使用 -P 参数带着插件启动 objection:objection -g com.app.name explore -P ~/.objection/plugins

然后就可以愉快的使用 wallbreaker 的几个命令了:

  • 搜索 plugin wallbreaker classsearch <type-pattern>
        根据给的 pattern 对所有类名进行匹配,列出匹配到的所有类名。[return all matched class]
  • 搜索 实例对象:plugin wallbreaker objectsearch <instance-class-name>
        根据类名搜索内存中已经被创建的实例,列出 handle 和 toString() 的结果。 [return all matched object-handle and toString]
  • ClassDump,输出类的结构:plugin wallbreaker classdump <class-name> [--fullname]
        输出类的结构, 若加了 --fullname 参数,打印的数据中类名会带着完整的包名。
            [
               pretty print class structure: fields declare, static field value, methods declare.
                  set --fullname to display package name of type name.
            ]
  • ObjectDump:plugin wallbreaker objectdump <object-handle> [--fullname] [--as-class class-name]
        在 ClassDump 的基础上,输出指定对象中的每个字段的数据。
            [
               pretty print object structure: fields declare and value, methods declare.
                  set --fullname to display package name of type name;
                  set --as-class to cast instance type(super class, not interface).
               if instance is a collection or map, dump all entries.
            ]

DEMO:https://asciinema.org/a/XZf8yLWJylCKJfcaYzcKlNbIy

Wallbreaker 的使用

objection 基本使用 + Wallbreaker:https://www.52pojie.cn/forum.php?mod=viewthread&tid=1626964

加载并使用 Wallbreaker插件:objection -g com.android.phone explore -P ~/.objection/plugins

搜索类:plugin wallbreaker classsearch <pattern>
        根据给的 pattern 对所有类名进行匹配,列出匹配到的所有类名。

搜索对象:plugin wallbreaker objectsearch <classname>
        根据类名搜索内存中已经被创建的实例,列出 handle 和 toString() 的结果。

ClassDump:plugin wallbreaker classdump <classname> [--fullname]
        输出类的结构, 若加了 --fullname 参数,打印的数据中类名会带着完整的包名。

ObjectDump:plugin wallbreaker objectdump <handle> [--fullname]
        在 ClassDump 的基础上,输出指定对象中的每个字段的数据。

2.3 ZenTracer(hook)

前文中介绍的 objection 已经足够强大,优点是 hook 准确、粒度细。这里再推荐个好友自己写的批量 hook 查看调用轨迹的工具ZenTracer ( https://github.com/hluwa/ZenTracer ),可以更大范围地 hook,帮助读者辅助分析。

# pyenv install 3.8.0
# git clone https://github.com/hluwa/ZenTracer
# cd ZenTracer
# pyenv local 3.8.0
# python -m pip install --upgrade pip
# pip install PyQt5
# pip install frida-tools
# python ZenTracer.py

上述命令执行完毕之后,会出现一个 PyQt 画出来的界面,如图 2-10 所示。

点击 Action之后,会出现匹配模板(Match RegEx)和过滤模板(Black RegEx)。匹配就是包含的关键词,过滤就是不包含的关键词,见下图2-11。其代码实现就是

通过如下的代码实现,hook 出来的结果需要通过匹配模板进行匹配,并且筛选剔除掉过滤模板中的内容。

var matchRegEx = {MATCHREGEX};
var blackRegEx = {BLACKREGEX};
Java.enumerateLoadedClasses({
    onMatch: function (aClass) {
        for (var index in matchRegEx) {
            // console.log(matchRegEx[index]);
            // 通过匹配模板进行匹配
            if (match(matchRegEx[index], aClass)) {
                var is_black = false;
                for (var i in blackRegEx) {
                    //如果也包含在过滤模板中,则剔除
                    if (match(blackRegEx[i], aClass)) {
                        is_black = true;
                        log(aClass + "' black by '" + blackRegEx[i] + "'");
                        break;
                    }
                }
                if (is_black) {
                    break;
                }
                log(aClass + "' match by '" + matchRegEx[index] + "'");
                traceClass(aClass);
            }
        }

    },
    onComplete: function () {
        log("Complete.");
    }
});

通过下述代码实现的模糊匹配和精准匹配:

function match(ex, text) {
    if (ex[1] == ':') {
        var mode = ex[0];
        if (mode == 'E') {
            ex = ex.substr(2, ex.length - 2);
            return ex == text;
        } else if (mode == 'M') {
            ex = ex.substr(2, ex.length - 2);
        } else {
            log("Unknown match mode: " + mode + ", current support M(match) and E(equal)")
        }
    }
    return text.match(ex)
}

通过下述代码实现的导入导出调用栈及观察结果:

def export_onClick(self):
    jobfile = QFileDialog.getSaveFileName(self, 'export', '', 'json file(*.json)')
    if isinstance(jobfile, tuple):
        jobfile = jobfile[0]
    if not jobfile:
        return
    f = open(jobfile, 'w')
    export = {}
    export['match_regex'] = self.app.match_regex_list
    export['black_regex'] = self.app.black_regex_list
    tree = {}
    for tid in self.app.thread_map:
        tree[self.app.thread_map[tid]['list'][0].text()] = gen_tree(self.app.thread_map[tid]['list'][0])
    export['tree'] = tree
    f.write(json.dumps(export))
    f.close()

def import_onClick(self):
    jobfile = QFileDialog.getOpenFileName(self, 'import', '', 'json file(*.json)')
    if isinstance(jobfile, tuple):
        jobfile = jobfile[0]
    if not jobfile:
        return
    f = open(jobfile, 'r')
    export = json.loads(f.read())
    for regex in export['match_regex']: self.app.match_regex_list.append(
        regex), self.app.match_regex_dialog.setupList()
    for regex in export['black_regex']: self.app.black_regex_list.append(
        regex), self.app.black_regex_dialog.setupList()
    for t in export['tree']:
        tid = t[0: t.index(' - ')]
        tname = t[t.index(' - ') + 3:]
        for item in export['tree'][t]:
            put_tree(self.app, tid, tname, item)

示例 ( ZenTracer ):hook java.io.File类的所有方法

我们来完整的演示一遍,比如现在看java.io.File类的所有方法,我们可以这样操作,首先是精准匹配:

  • 点击打开 "设置" 应用;
  • 选择 Action → Match RegEx
  • 输入E:java.io.File,点击add,然后关闭窗口
  • 点击 Action → Start

可以看到 java.io.File 类的所有方法都被 hook 了,并且像 java.io.File.createTempFile 方法的所有重载也被 hook 了。

1. 在 "设置" 应用上进行操作,打开几个子选项的界面之后,观察方法的参数和返回值;

2. 导出 json 来观察方法的调用树,选择 File → Export json,导出为 tmp.json,使用 vscode 来 format Document 之后,效果如下:

{
    "match_regex": [
        "E:java.io.File"
    ],
    "black_regex": [],
    "tree": {
        "2 - main": [
            {
                "clazz": "java.io.File",
                "method": "exists()",
                "args": [],
                "child": [],
                "retval": "false"
            },
            {
                "clazz": "java.io.File",
                "method": "toString()",
                "args": [],
                "child": [
                    {
                        "clazz": "java.io.File",
                        "method": "getPath()",
                        "args": [],
                        "child": [],
                        "retval": "/data/user/0/com.android.settings"
                    }
                ],
                "retval": "/data/user/0/com.android.settings"
            },
            {
                "clazz": "java.io.File",
                "method": "equals(java.lang.Object)",
                "args": [
                    "/data/user/0/com.android.settings"
                ],
                "child": [
                    {
                        "clazz": "java.io.File",
                        "method": "toString()",
                        "args": [],
                        "child": [
                            {
                                "clazz": "java.io.File",
                                "method": "getPath()",
                                "args": [],
                                "child": [],
                                "retval": "/data/user/0/com.android.settings"
                            }
                        ],
                        "retval": "/data/user/0/com.android.settings"
                    },
                    {
                        "clazz": "java.io.File",
                        "method": "compareTo(java.io.File)",
                        "args": [
                            "/data/user/0/com.android.settings"
                        ],
                        "child": [
                            {
                                "clazz": "java.io.File",
                                "method": "getPath()",
                                "args": [],
                                "child": [],
                                "retval": "/data/user_de/0/com.android.settings"
                            },
                            {
                                "clazz": "java.io.File",
                                "method": "getPath()",
                                "args": [],
                                "child": [],
                                "retval": "/data/user/0/com.android.settings"
                            }
                        ],
                        "retval": "48"
                    }
                ],
                "retval": "false"
            },

3. 点击 Action→Stop,再点击 Action→Clean,本次观察结束。

也可以使用模糊匹配模式,比如输入M:java.io.File之后,会将诸如 java.io.FileOutputStream 类的诸多方法也都 hook上,见下图2-14。

ZenTracer 的目前已知的缺点,无法打印调用栈,无法 hook 构造函数,也就是 $init。当然这些 “缺点” 无非也就是加几行代码的事情,整个工具非常不错,值得用于辅助分析。

Frida逆向与抓包实战是一本关于移动端应用逆向和抓包技术的实践指南。本书主要介绍了Frida这一强大的逆向工具的使用方法,并结合实际案例进行讲解。 首先,Frida是一款强大的动态分析工具,可以在运行中的应用程序中注入自定义的JavaScript代码,从而实现应用程序的行为监控与控制。本书以Frida为基础,详细介绍了如何使用Frida进行Android和iOS应用程序的逆向分析。读者可以学习到如何使用Frida的API来动态修改应用程序的行为,如动态调试、函数替换、Hook等。 其次,本书还介绍了抓包技术在移动应用逆向中的应用。通过抓包技术,读者可以捕获应用程序与服务器之间的通信数据,分析应用程序的网络请求和响应,了解应用程序的数据传输方式和协议。本书讲解了常用的抓包工具和技术,如使用Fiddler、Charles等工具进行HTTPS抓包,分析加密通信数据等。 本书还通过实例演示了如何使用Frida和抓包技术进行实际的应用分析。例如,通过使用Frida获取应用程序的敏感数据并进行修改,探测应用程序中的漏洞,发现应用程序的安全问题等。通过抓包技术,读者可以分析应用程序的通信过程,了解应用程序与服务器之间的交互,发现潜在的数据泄漏风险等。 综上所述,Frida逆向与抓包实战是一本介绍了Frida工具的基本原理和实际应用的实践指南。通过学习本书,读者可以了解到Frida的使用方法以及如何利用抓包技术进行移动应用逆向分析,并能够应用这些技术进行实际的应用分析与调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值