Frida开发环境搭建记录

Frida在安装时容易出现网络状况,两个小建议

  1. 使用镜像源,不要用豆瓣源
  2. 先pip install frida-tools --user,因为tools会一并尝试安装frida

Frida在环境搭建中会遇到各种问题

一、Frida版本问题

  • 由于frida版本更新极快,不断修复bug,不断增加新特性,因此建议使用较新版本的server,较新版本的frida,较新版本的frida-tools。
  • 手机上的server版本和电脑上的frida版本不一致也没关系,可以正常运行,但尽量一致。
  • 在必要的时候使用pyenv,virtualenv等版本管理工具。即每个项目给予单独的Frida版本和环境,这样可以避免许多烦恼。比如Objection的最新版就因为相关原因不支持frida-tools的最新版,因此如果没有使用注入Pyenv一类的版本管理工具,就只能Objection/Frida-tools二选一版本降级。

二、编写Frida脚本相关问题

  • Frida编写脚本时无智能提示,这个真的很烦,严重影响开发体验,我们可以通过Frida官方提供的方案解决。首先需要电脑上有nodejs以及npm环境,新版的nodejs似乎自带npm,如果不在环境变量里就加上去,如图方式检测是否配置好环境。

    在这里插入图片描述
    需要注意的是,由于国内的网络状况,后续install很容易失败,这里建议使用阿里的cnpm镜像。

    命令行输入如下,安装好了就可以使用cnpm install xxx来替代npm install进行js依赖的下载了。

     > npm install -g cnpm --registry=https://registry.npm.taobao.org
    

    其次需要一个智能IDE,建议Webstorm,Jetbrain家的东西总是好用的。我们需要clone或者下载这个项目,在Webstorm中打开这个文件夹,terminal里cnpm install。(不用Webstorm的朋友可以直接在命令行终端里cd到相应文件夹)
    在这里插入图片描述
    一切就绪,在agent目录下编写的javascript/typescript代码就将拥有Frida相关api的智能提示。你可以以如下代码进行测试。

    function frida_Java() {
        Java.perform(function () {
            //作为判断用
            if(Java.available)
            {
                //注入的逻辑代码
                console.log("hello java vm");
            }else{
                //未能正常加载JAVA VM
                console.log("error");
            }
        });
    }
    setImmediate(frida_Java,0);
    

    除此之外,它可以帮我们做更多的事。

    agent目录中新建一个文件夹test,编写test1.js内容如下

    var a = "测试var定义变量";
    console.log(a);
    const b = "测试const定义变量";
    console.log(b);
    let c = "测试let定义变量";
    console.log(c);
    

    根据ES6规范,Js中定义变量的方法由单一的 var 方式发展到了 var、let、const 三种之多。我们在Webstorm中测试一下。
    在这里插入图片描述
    启动手机上的frida server,将这个脚本随便注入一个应用,我这里注入了百度新闻。
    在这里插入图片描述
    可以发现,这里报了语法错误。注释掉let的两行,代码顺利运行。
    在这里插入图片描述
    在这里插入图片描述
    即Frida的引擎只支持var,const这两种变量声明。如果我们使用别人的Frida脚本,无法运行,就可以看一下是否存在变量未定义或者使用let的情况。我们再编写test2.js,测试一下其他语法。

    let func = value => value+1;
    console.log(func(6));
    

    这是ES6的箭头表达式,用于方便的定义函数,它等同于如下代码。

    var func = function (value) {
        return value+1;
    };
    

    Webstorm中运行顺利,我们试一下Frida
    在这里插入图片描述
    在这里插入图片描述
    又是语法错误,Frida的引擎无法使用ES6很多方便的特性。除此之外,Typescript也是不被支持的。
    Typescript是Javascript的超集,它增加了静态类型检查,这样你就能在运行代码之前发现错误了,更适合构建项目,很多基于Frida二次开发的项目都有Typescript的身影。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    但Frida的Js引擎似乎不支持Ts,新建demo3.ts,编写ts代码如下,如果你想在WebStorm中运行,需要配置WebStorm Typescript环境。我们这里直接尝试Frida注入,同样报语法错误。
    在这里插入图片描述
    在这里插入图片描述
    我们用三个demo说明了Frida的JS引擎似乎有很多缺陷,阻挠我们更高效的构建项目,可以开始谈谈Frida的JS运行引擎。Frida有两个Javascript运行引擎——Duktape和V8,原本使用的脚本引擎是V8,V8引擎功能完备,支持ES6诸多特性,但由于Frida曾经存在的一些问题,所以采用了Duktape引擎作为默认脚本引擎,Duk相比V8,缺失了非常多的Es6特性,比如箭头表达式,let等,没法充分释放JS的威力,但我们可以切换为V8,只需要在注入脚本时指定引擎“–runtime=v8/duk”。
    在这里插入图片描述在这里插入图片描述
    但除此之外,我们还有更好的解决方案——frida-compile,它是解决问题的最好办法。
    在这里插入图片描述
    图来自https://www.slideshare.net/ssusercf6665/frida-107244825,这是一份关于Frida全面而深入的PPT资料。

    我们当前所处的模块已经配置了frida-compile,我们可以直接使用。
    代码必须编写在index.ts中
    在这里插入图片描述
    Terminal运行npm run watch,它会监控代码修改,自动调用frida-compile,在目录中生成_agent.js,这个js脚本无需指定–runtime=v8,就可以被顺利的注入设备。
    在这里插入图片描述
    可以注意到,编译后得到的_agent.js代码,相比原先复杂了很多,而且可读性下降,但let被转成了var,可以被Frida的duk引擎识别。

    为什么npm run watch可以做到这样的事呢?实际上npm run watch 命令指的是监视项目的变化,具体怎么操作在于package.json中的定义,我们看一下。
    在这里插入图片描述
    我们是否能自己运行frida-compile呢,比如编译自己的脚本,或者编译别人的项目?只写在index.js中,或者每次修改package.json还是挺麻烦的,来试一下吧。
    命令行或者任意Terminal中输入:

    cnpm install frida-compile -g
    cnpm install frida-compile
    

    接下来我们就可以在任意位置compile项目了,格式如下

    frida-compile agent -o _agent.js -w
    

    agent:需要编译的脚本的路径,可不加文件后缀
    _agent.js:编译后输出文件,可自由命名
    -w:watch模式,持续检测原脚本改动并重新编译

三、调试Frida脚本

调试可以帮助我们检查脚本是否有误,又可以用于分析Frida源码实现。我们还是用这个简单的Frida脚本用于演示

function frida_Java() {
    Java.perform(function () {
        //作为判断用
        if(Java.available)
        {
            //注入的逻辑代码
            console.log("hello java vm");
        }else{
            //未能正常加载JAVA VM
            console.log("error");
        }
    });
}       
setImmediate(frida_Java,0);

在这里插入图片描述
启动时加上**–debug --runtime=v8**,两者缺一不可。在这里插入图片描述
打开chrome浏览器,输入网址 chrome://inspect/#devices
在这里插入图片描述
稍等片刻,Remote Target会连接我们的Python进程,端口号并不一致,但不用管,我们点击inspect
在这里插入图片描述
在这里插入图片描述
选择我们编写的脚本即可,后续debug操作应该大家都懂。
可能有的人会问,如果我基本都是通过Python脚本的方式运行Frida,那该如何操作?其实也一样,如果你想切换引擎,只需要修改runtime=“v8” 或者session.enable_jit(),如果想要debug,就再加上session.enable_debugger()

import time
import frida

device = frida.get_usb_device(10)
session = device.attach("com.baidu.news")
session.enable_debugger()
# session.enable_jit()
with open("debugMyScript.js", encoding='UTF-8') as f:
    script = session.create_script(f.read(), runtime="v8")

script.load()
input()

Python脚本方式debug更多细节参考这篇文章https://bbs.pediy.com/thread-254695.htm

我个人不建议使用Python+JS混合脚本方式Hook,Frida的Cli客户端实在是太丝滑了,JS脚本太好用了。

发布了27 篇原创文章 · 获赞 120 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_38851536/article/details/104895878