安卓APP逆向进阶-Frida介绍

Frida 介绍以及功能

本文档中的信息仅用于学术研究和交流学习之目的,不涉及任何商业或非法用途。我们已对可能涉及的敏感信息,如抓包数据、特定网址、数据接口等,进行了必要的脱敏处理,以确保信息安全。任何未经授权的转载或修改后的二次传播均被严格禁止。

若擅自使用本文所述技术而引发的任何不良后果或意外,本文作者不承担任何责任。若认为本文内容涉及侵权,请通过公众号【小马哥逆向】与我们取得联系,我们将立即进行处理。感谢您的理解和配合。

Frida 介绍

Frida 是一款开源的动态代码检测工具,可以用于分析和修改移动应用程序的行为。它跨平台兼容,可以在 Android、iOS 以及桌面应用程序上使用。

功能

  1. API 监控: 可以监控应用程序内部的各种 API 调用,例如网络请求、文件 I/O 操作以及敏感数据访问等,帮助分析应用程序的行为和潜在的安全/隐私问题。

    import frida
    
    # 连接设备并获取目标进程
    session = frida.get_remote_device().attach("com.example.myapp")
    
    # 创建 JavaScript 脚本
    script = session.create_script("""
        Interceptor.attach(Module.findExportByName("libcurl.so", "curl_easy_perform"), {
            onEnter: function(args) {
                console.log("curl_easy_perform called with URL: " + Memory.readCString(args[0].add(offsetof("CURL", "url"))));
            }
        });
    """)
    
    # 加载并运行脚本
    script.load()
    session.detach()
    

    这个例子演示了如何使用 Frida 来监控 Android 应用程序中 libcurl.so 库的 curl_easy_perform 函数的调用情况,并打印出请求的 URL。

  2. 函数 Hook: 可以动态 hook 应用程序内部的函数,能够检查、修改或者替换函数的行为,用于绕过应用程序的安全检查、改变应用程序的逻辑或注入自定义功能。

    import frida
    
    # 连接设备并获取目标进程
    session = frida.get_remote_device().attach("com.example.myapp")
    
    # 创建 JavaScript 脚本
    script = session.create_script("""
        Interceptor.attach(Module.findExportByName("libcurl.so", "curl_easy_perform"), {
            onEnter: function(args) {
                console.log("curl_easy_perform called with URL: " + Memory.readCString(args[0].add(offsetof("CURL", "url"))));
            }
        });
    """)
    
    # 加载并运行脚本
    script.load()
    session.detach()
    

    这个例子演示了如何使用 Frida 来监控 Android 应用程序中 libcurl.so 库的 curl_easy_perform 函数的调用情况,并打印出请求的 URL。

  3. 应用程序检测和仪表化: 可以对应用程序进行动态检测和分析,添加日志记录、跟踪或性能分析等功能,用于调试、性能分析和复杂行为的调查。

  4. 运行时补丁: 可以在不重新编译应用程序的情况下,对其进行动态补丁和修改,用于快速修复漏洞或临时改变应用程序的行为。

  5. 动态代码注入: 可以在运行时动态地加载和执行自定义代码,用于扩展应用程序功能、注入安全控制或实现动态分析技术。

    import frida
    
    # 连接设备并获取目标进程
    
    session = frida.get_remote_device().attach("com.example.myapp")
    
    # 创建 JavaScript 脚本
    
    script = session.create_script("""
        // 添加性能监控
        Interceptor.attach(Module.findExportByName(null, "malloc"), {
            onEnter: function() {
                this.start = Process.getCurrentThreadId();
            },
            onLeave: function() {
                var duration = Process.getCurrentThreadId() - this.start;
                console.log("malloc took " + duration + " ms");
            }
        });
    """)
    
    # 加载并运行脚本
    
    script.load()
    session.detach()
    这个例子演示了如何使用 Frida 在运行时动态地加载和执行自定义 Java 代码,在这里我们重写了 com.example.myapp.MyClass 类的 myMethod 方法,添加了一个日志输出。
    
  6. 跨平台支持: Frida 可以在 Android、iOS 和桌面应用程序上使用,为分析和修改不同平台的应用程序提供了统一的解决方案。

  7. 自动化和脚本化: Frida 提供了强大的脚本引擎,可以用于自动化复杂的任务和工作流,如大规模的应用程序分析、模糊测试和安全测试。

    import frida
    import time
    
    # 连接设备并获取目标进程
    session = frida.get_remote_device().attach("com.example.myapp")
    
    # 创建 JavaScript 脚本
    script = session.create_script("""
        // 自动执行登录流程
        Java.perform(function() {
            var MainActivity = Java.use("com.example.myapp.MainActivity");
            MainActivity.login.implementation = function() {
                this.setUsername("testuser");
                this.setPassword("testpassword");
                this.doLogin();
            };
        });
    """)
    
    # 加载并运行脚本
    script.load()
    time.sleep(5)
    session.detach()
    这个例子演示了如何使用 Frida 编写自动化脚本,在这里我们 hook 了应用程序的登录流程,自动填充用户名和密码,并执行登录操作。这种方式可以用于大规模的应用程序测试、安全评估或其他自动化任务。
    

Hook Java 函数

以下是一个 Hook Java 函数的例子:

setImmediate(function () {
    Java.perform(function () {
        var MainActivity = Java.use('com.example.MainActivity');

        // Hook Java 方法
        MainActivity.foo.implementation = function (str) {
            // 调用方法
            var ret = this.foo(str);
            console.log('Return value:', ret);
            // 返回
            return ret;
        };
    })
})
这段代码是在 Frida 中 hook Java 方法的一个很好的示例。让我逐步解释一下:

setImmediate(function () { ... }) 是为了确保 Java 环境准备就绪后再执行后续的 JavaScript 代码。这是因为 Frida 会在单独的线程中执行 Java 代码,所以需要等待 Java 环境初始化完成。
在 Java.perform(function () { ... }) 中,我们获取了 com.example.MainActivity 类的引用。这个类是我们要 hook 的目标。
然后,我们 hook 了 MainActivity 类的 foo 方法。我们用自定义的实现替换了原始方法的实现。
在自定义的方法实现中:
首先调用了原始的 foo 方法,并获取返回值。
然后打印出返回值。
最后返回了原始方法的返回值。
这段代码演示了 Frida 如何 hook Java 方法并在执行前后添加自定义逻辑。这种能力非常强大,可以用于各种应用程序分析和修改的场景,例如:

监控和记录方法调用情况
修改方法参数或返回值
控制方法的执行流程
绕过应用程序的安全检查
修复应用程序中的漏洞

Hook Native 函数

以下是一个 Hook Native 函数的例子:

setImmediate(function () {
    Java.perform(function () {
        const nativeFuncAddr = Module.findExportByName(null, 'nativeFunc');

        // Frida Gadget
        Interceptor.attach(nativeFuncAddr, {
          onEnter: function(args) {
            // 输出函数的参数
            console.log('nativeFunc(' + args[0] + ', ' + args[1] + ')');

            // 修改参数
            args[0] = ptr('0x1234');
            args[1] = ptr('0x5678');
          },
          onLeave: function(retval) {
            // 输出函数的返回值
            console.log('returned: ' + retval);
          }
        });
    })
    
    
   这个代码示例展示了如何使用 Frida 来 hook 原生 C/C++ 函数。让我们逐步分析一下:

setImmediate(function () { ... }) 是为了确保 Java 环境准备就绪后再执行后续的 JavaScript 代码。这是因为 Frida 会在单独的线程中执行 Java 代码,所以需要等待 Java 环境初始化完成。
在 Java.perform(function () { ... }) 中, Frida 会在 Java 环境中执行后续的代码。
Module.findExportByName(null, 'nativeFunc') 用于获取名为 nativeFunc 的原生函数的地址。这个函数是我们要 hook 的目标。
接下来,我们使用 Interceptor.attach(nativeFuncAddr, {...}) 来 hook 这个原生函数。这个函数有两个回调函数:
onEnter: 在函数执行前调用,可以在这里修改参数值。
onLeave: 在函数执行后调用,可以在这里获取返回值。
在 onEnter 回调中:
我们首先打印出了函数的参数值。
然后,我们修改了参数 args[0] 和 args[1] 的值。
在 onLeave 回调中:
我们打印出了函数的返回值 retval。
这个示例代码演示了如何使用 Frida 的 Interceptor 模块来 hook 原生函数。通过这种方式,我们可以:

监控函数的参数和返回值
修改函数的参数和返回值
控制函数的执行流程
这种能力在应用程序分析和修改方面非常强大,可以用于各种场景,例如:

绕过原生库中的安全检查
修复原生库中的漏洞
动态分析原生库的行为
优化原生库的性能

Frida 启动的两种模式及区别

Frida 启动有两种方式,分别为 Spawn 模式和 Attach 模式:

  • Spawn 模式可以完全控制目标进程的生命周期,而 Attach 模式只能依附到已经运行的进程。
  • Spawn 模式更适合分析和干预应用程序的启动阶段,而 Attach 模式更适合分析和干预应用程序的运行时行为。

Spawn 模式启动方式: frida -U {package} -l xxx.js
Attach 模式启动方式: frida -U -l xxx.js -f {package}

Frida Hook 原理

  1. 动态代码注入:
    • Frida 使用动态代码注入技术将自己的代码注入到目标进程中。
    • 在 Android 和 iOS 上,Frida 会使用 ptrace 系统调用将自己的代码附加到目标进程。
    • 在 Windows 上,Frida 使用 CreateRemoteThread 函数在目标进程中创建一个新线程并执行其代码。
  2. 函数钩子:
    • Frida 使用函数钩子技术来拦截目标函数的执行。
    • 在 Java 环境中,Frida 会使用 Java.use 和 Java.implementation 来替换目标类和方法的实现。
    • 在原生环境中,Frida 会使用 Interceptor.attach 来拦截目标函数的执行,并提供 onEnter 和 onLeave 回调函数。
  3. 内存操作:
    • Frida 可以读取和修改目标进程的内存,这可以用于修改函数参数、返回值和执行流程。
    • 在 Java 环境中,Frida 提供了 Java.cast 和 Java.array 等 API 来操作对象和数组。
    • 在原生环境中,Frida 提供了诸如 Memory.readPointer 和 Memory.writePointer 等 API 来读写内存。
  4. 跨平台兼容:
    • Frida 是一个跨平台的工具,可以运行在 Android、iOS、macOS、Windows 和 Linux 等多种操作系统上。
    • 为了实现跨平台兼容,Frida 在每个平台上使用不同的底层机制来实现动态代码注入和函数钩子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值