Frida-server运行报错问题的解决

VSole2023-05-04 09:11:08

刚刚开始学Android逆向,发现Frida是个好东西,于是赶紧下载研究一番。

下载源码编译,切换到最新版16.0.11, 编译之前注意先更新nodejs。

wget -qO- https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

然后执行:

make core-android-arm64 
make tools-linux-x86_64 PYTHON=$HOME/miniconda3/bin/python

就可以成功生成frida-server以及frida相关tools,于是push到手机上执行。

redfin:/data/local/tmp # ./frida-server                                                       
{"type":"error","description":"Error: Java API not available","stack":"Error: Java API not available    at _checkAvailable (frida/node_modules/frida-java-bridge/index.js:298:1)    at _.perform (frida/node_modules/frida-java-bridge/index.js:203:1)    at /internal-agent.js:490:6","fileName":"frida/node_modules/frida-java-bridge/index.js","lineNumber":298,"columnNumber":1}

报错了,继续往下试试。

把手机上的名为com.example.myapplication的demo app放到前台,然后注入一个helloword级别的js。

setTimeout(
    function() {
        Java.perform(function() {
            console.log("Hello frida!")
        })
    }
)
//test.js

然后执行:

(base) /data/code/OpenSource/crack/frida/build/frida-linux-x86_64/bin (16.0.11 ✔) ./frida -U -l ../../../../frida_script/test.js com.example.myapplication
     ____
    / _  |   Frida 16.0.11 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to AOSP on redfin (id=0A051FDD4003BW)
Failed to spawn: cannot read properties of undefined (reading 'getRunningAppProcesses')

咳,出师不利,不过反正我也是做c++开发的,虽然不懂javascript, 连蒙带猜也能看个差不多,那就研究研究报错原因吧。

从现有信息来看,第一怀疑对象应该是那个报错"Error: Java API not available", 也指明了报错位置at _checkAvailable (frida/nodemodules/frida-java-bridge/index.js:298:1) at.perform (frida/node_modules/frida-java-bridge/index.js:203:1) ,那就在源码里搜索下。

发现这个index.js位于build/tmp-android-arm64/frida-gum/bindings/gumjs/node_modules/frida-java-bridge目录。然后看下perform实现:

 perform (fn) {
    this._checkAvailable();
    if (!this._isAppProcess() || this.classFactory.loader !== null) {
      try {
        this.vm.perform(fn);
      } catch (e) {
        Script.nextTick(() => { throw e; });
      }
    } else {
      this._pendingVmOps.push(fn);
      if (this._pendingVmOps.length === 1) {
        this._performPendingVmOpsWhenReady();
      }
    }
  }

这个函数第一行就是_checkAvailable,跟进去看看。

  _checkAvailable () {
    if (!this.available) {
      throw new Error('Java API not available');
    }
  }

果然报错就是在这里,那么关键的判断就是available了,再跳过去看看。

  
get available () {
    return this._tryInitialize();
  }
  _tryInitialize () {
    if (this._initialized) {
      return true;
    }
    if (this._apiError !== null) {
      throw this._apiError;
    }
    let api;
    try {
      api = getApi();
      this.api = api;
    } catch (e) {
      this._apiError = e;
      throw e;
    }
    if (api === null) {
      return false;  //只有这里返回为false
    }
    const vm = new VM(api);
    this.vm = vm;
    Types.initialize(vm);
    ClassFactory._initialize(vm, api);
    this.classFactory = new ClassFactory();
    this._initialized = true;
    return true;
  }

那么只有一种可能,就是getApi()返回为null,再跟进去看看,这个getApi的有几层跳转如下:

// index.js
const getApi = require('./lib/api');
// ./lib/api.js
let { getApi, getAndroidVersion } = require('./android');
try {
  getAndroidVersion();
} catch (e) {
  getApi = require('./jvm').getApi;
}
module.exports = getApi;
// ./lib/android.js
function getApi () {
  if (cachedApi === null) {
    cachedApi = _getApi();
  }
  return cachedApi;
}
function _getApi () {
  const vmModules = Process.enumerateModules()
    .filter(m => /^lib(art|dvm).so$/.test(m.name))
    .filter(m => !/\/system\/fake-libs/.test(m.path));
  if (vmModules.length === 0) {
    return null; // 这里返回了null
  }
  //以下代码省略...
}

看代码的意思是进程内没找到加载的libart.so或者libdvm.so,真奇怪了,你可是android进程,没有虚拟机咋跑的?

那就看下这个进程加载了什么,首先找到进程id。

redfin:/ # ps -ef | grep com.example.myapplication                                                                                                                                                                
u0_a108      27168 21776 0 11:18:29 ?     00:00:03 com.example.myapplication
root         28255 28250 35 14:11:06 pts/1 00:00:00 grep com.example.myapplication

然后检查下maps。

redfin:/ # cat /proc/27168/maps | grep libart.so                                                                                                                                                                  
1|redfin:/ #

果然没有,我把maps的输出保存下来,在编辑器里查看才发现了端倪,原来进程加载的so里有一个libartd.so,因为这个手机是pixel5,系统是我自己下载AOSP编译的,选择的是eng版,这样编出来的系统so都是debug版,也就意味着后缀都有一个d,难怪frida找不到。

知道了原因,那解决方案就简单了,把那段查找libart.so的代码改成查找libartd.so即可。不过还有一个问题,这个frida-java-bridge是编译的时候从网上下载的,我们本地修改会被覆盖,那么就得研究下frida的编译系统了,让它使用我们本地的frida-java-bridge。

首先在源码里搜索frida-java-bridge,果不其然,是在一个generate-runtime.py里面,代码如下:

XACT_DEPS = {
    "frida-java-bridge": "6.2.3",
    "frida-objc-bridge": "7.0.2",
    "frida-swift-bridge": "2.0.6"
}
def generate_runtime(backends, arch, endian, input_dir, gum_dir, capstone_incdir, libtcc_incdir, quickcompile, output_dir):
    frida_compile = output_dir / "node_modules" / ".bin" / make_script_filename("frida-compile")
    if not frida_compile.exists():
        pkg_files = [output_dir / "package.json", output_dir / "package-lock.json"]
        for f in pkg_files:
            if f.exists():
                f.unlink()
        (output_dir / "tsconfig.json").write_text("{ \"files\": [], \"compilerOptions\": { \"typeRoots\": [] } }", encoding="utf-8")
        node_modules = output_dir / "node_modules"
        if node_modules.exists():
            shutil.rmtree(node_modules)
        npm = os.environ.get("NPM", make_script_filename("npm"))
        try:
            subprocess.run([npm, "init", "-y"],
                           capture_output=True,
                           cwd=output_dir,
                           check=True)
            subprocess.run([npm, "install"] + [f"{name}@{version_spec}" for name, version_spec in RELAXED_DEPS.items()],
                           capture_output=True,
                           cwd=output_dir,
                           check=True)
            subprocess.run([npm, "install", "-E"] + [f"{name}@{version_spec}" for name, version_spec in EXACT_DEPS.items()],
                           capture_output=True,
                           cwd=output_dir,
                           check=True) <=========这里下载了EXACT_DEPS里面的依赖项

看来是编译的时候,用npm install -E把frida-java-bridge下载下来了,那么接下来就是要把这个依赖项改成我们本地的。

首先下载一个到本地:

git clone https://github.com/frida/frida-java-bridge.git

然后全局查找libart.so,改成libartd.so。

这时候需要用到npm link把我们本地的frida-java-bridge注册到系统中。

(base) /data/code/OpenSource/crack/frida/frida-java-bridge (main ✗) npm link
up to date, audited 3 packages in 574ms
found 0 vulnerabilities
(base) /data/code/OpenSource/crack/frida/frida-java-bridge (main ✗) npm install   
added 214 packages, and audited 215 packages in 1s
62 packages are looking for funding
  run `npm fund` for details
found 0 vulnerabilities

然后要让frida中的编译脚本指向我们这个,也就是不要用npm install了,需要改成npm link, 修改generate-runtime.py代码如下:

然后再重新编译, 生成后推到手机执行。

果然没有报错了,非常完美!

installnode
本作品采用《CC 协议》,转载必须注明作者和本文链接
开源智能 (OSINT) 工具
2022-05-12 06:10:39
Insta侦察 子域扫描仪 端口扫描 用户侦察 邮件查找器 网址扫描器 Exif 元数据提取 Whois 查询 IP 查询 标题信息 域名时代 DNS 查询 用户代理查找 Git侦察 展开网址 Instagram DP Viwer 将结果保存到文件
TIGMINT是一款功能强大的开源情报GUI软件框架,该工具针对Twitter、Instagram和地理标记应用设计。
正因如此,WebAssembly 指令有时候被称为虚拟指令。模糊测试AFL模糊测试是一种软件测试技术。模糊测试常常用于检测软件或计算机系统的安全漏洞。阵阵的雷暴在线路上造成噪音,这些噪音又导致两端的UNIX命令获得错误的输入,并导致崩溃。作为一名科学家,他想探究该问题的严重程度及其原因。最后Fuzzm对AFL进行了高度优化,因此可以在wasm虚拟机上对程序进行模糊测试。
刚刚开始学Android逆向,发现Frida是个好东西,于是赶紧下载研究一番。下载源码编译,切换到最新版16.0.11, 编译之前注意先更新nodejs。就可以成功生成frida-server以及frida相关tools,于是push到手机上执行。报错了,继续往下试试。/ _ | Frida 16.0.11 - A world-class dynamic instrumentation toolkit. /_/ |_| help -> Displays the help system. . . . . Connected to AOSP on redfin . 然后看下perform实现: perform {. 果然报错就是在这里,那么关键的判断就是available了,再跳过去看看。
该工具可以通过WhatsApp文本和文件消息发送TCP网络包,此时它会将其拆分为不同文本消息或文件。为了不让WhatsApp发送超时,默认情况下,每条消息限制为2万个字符,目前它是用wasocket.js硬编码的。开发人员已经做了多次测试,任何超过8万个字符的消息都可能超时。文件消息以二进制文件的形式发送,TCP响应与分隔符连接,并使用brotli压缩以减少数据使用。
声明:本篇文章由 可可@QAX CERT 原创,仅用于技术研究,不恰当使用会造成危害,严禁违法使用 ,否则后
访问http://ip:9200 检查elasticsearch是否正常启动NO.2 安装kibanaapt-get install kibanaserver.host: "ip"service elasticsearch start
虚机ubuntu20.04, 安装docker, sudo apt install docker.io, sudo systemctl enable docker, sudo gpasswd -a ubuntu docker, newgrp docker, 安装docker-compose, sudo apt install docker-compose, 给harbor起个本地域
kubesphere的安装部署
2021-09-25 16:08:00
书接上回,本周把kubesphere的安装部署记录发出来, 首先要安装部署storageclass, 需要在每个node上安装nfs客户端软件,sudo apt install nfs-common, 然后下载storageclass的安装部署yaml模板, wget https://raw.githubusercontent.com/kubernetes-incubator/extern
harbor2.5版本开始支持cosign做镜像签名,本周实践了一下, ubuntu20.04.4,安装docker,sudo apt install docker.io, sudo systemctl enable docker, sudo gpasswd -a ubuntu docker, newgrp docker, 安装docker-compose,sudo apt instal
VSole
网络安全专家