参考: https://frida.re/docs/
frida可以监控某个进程,修改进程的入口, 修改执行的内容. 特别强大
在反编译的过程中会被使用.
例子不说了.
不过在我的本机上, 运行前面的单机例子没问题, 运行 Android的例子就不行了.
安装 : 要使用pip3 来安装
PC端:
$ pip3 install frida-tools (需要先安装好python 3 )
C:\Users\luelue>pip3 install frida-tools
Collecting frida-tools
  Downloading frida-tools-10.4.1.tar.gz (43 kB)
     |████████████████████████████████| 43 kB 212 kB/s
Collecting colorama<1.0.0,>=0.2.7
  Downloading colorama-0.4.4-py2.py3-none-any.whl (16 kB)
Collecting frida<16.0.0,>=15.0.0
  Downloading frida-15.1.8.tar.gz (9.1 kB)
Collecting prompt-toolkit<4.0.0,>=2.0.0
  Downloading prompt_toolkit-3.0.21-py3-none-any.whl (374 kB)
     |████████████████████████████████| 374 kB 312 kB/s
Collecting pygments<3.0.0,>=2.0.2
  Downloading Pygments-2.10.0-py3-none-any.whl (1.0 MB)
     |████████████████████████████████| 1.0 MB 467 kB/s
Requirement already satisfied: setuptools in c:\users\luelue\appdata\local\programs\python\python39\lib\site-packages (from frida<16.0.0,>=15.0.0->frida-tools) (49.2.1)
Collecting wcwidth
  Downloading wcwidth-0.2.5-py2.py3-none-any.whl (30 kB)
Using legacy 'setup.py install' for frida-tools, since package 'wheel' is not installed.
Using legacy 'setup.py install' for frida, since package 'wheel' is not installed.
Installing collected packages: colorama, frida, wcwidth, prompt-toolkit, pygments, frida-tools
    Running setup.py install for frida ... done
    Running setup.py install for frida-tools ... done
Successfully installed colorama-0.4.4 frida-15.1.8 frida-tools-10.4.1 prompt-toolkit-3.0.21 pygments-2.10.0 wcwidth-0.2.5
然后下载 frida-server: (注意,这个frida-server是安装到安卓端的,并且需要跟 PC端的frida的版本相对应)
https://github.com/frida/frida/releases/download/15.1.8/frida-core-devkit-15.1.8-android-arm64.tar.xz
下载后解压缩, 然后
$ 解压缩,把里面的文件 拿出来,例如叫 frida-server-android
$ unxz frida-server ..xz
$ adb push frida-server-android /data/local/tmp/
$ adb root (这里见我另外一篇文章 挨着本文)
$ cd /data/local/tmp
merlin:/data/local/tmp # su root (这一步特别关键! 否则会server 启动失败)
merlin:/data/local/tmp # chmod 755 frida-server-14.2.13-android-arm64
merlin:/data/local/tmp # ./frida-server-14.2.13-android-arm64 -v (建议首次运行时,一定要输入 -v , verbose 的意思)
总之就是执行上面的文件.
然后在PC端 直接 :
$ frida-ps -U 就可以看到结果
问题3. 如果frida-ps -U 不好用的话,就参考这里:https://github.com/frida/frida/issues/582
1. 在server端(android端),运行时,每次都要 su root 再运行
2. 在server端,ifconfig, 查看当前 android的ip, 然后 ./frida-server-15.1.8-android-arm64 -l 192.168.0.101 -v
3. 保证 client(windows/linux) 跟android在同一个局域网内. 然后 frida-ps --host 192.168.0.101
就可以了。
问题1: 提示: Failed to enumerate processes: unable to connect to remote frida-server: Unexpected lack of content trying to read a line
参考:https://stackoverflow.com/questions/62171745/frida-server-unable-to-connect/66652303#66652303
或者参考: https://github.com/frida/frida/issues/764
解决办法: 执行 frida-server 之前,务必 # su root , (你可以先试着ifconfig , 看看是否有权限,不要相信你安装的adb root )
问题2 unable to access zygote64 while preparing for app launch; try disabling Magisk Hide in case it is active
参考: https://stackoverflow.com/questions/56316329/frida-failed-to-spawn-unable-to-access-zygote64-while-preparing-for-app-launc
1. magisk -> settings -> Magisk -> MagiskHide , 要关掉. 否则会引起:
2. 无论你是否在magisk 中安装了 magisk adb root, 在进入到adb shell 之后, 执行 frida-server之前,都需要手动切换成root: $ su root
之后再执行 frida-server -v
在我的机器上, frida-ps -U的结果如下:
$ frida-ps -U PID Name ----- --------------------------------------------------- 14312 adbd 412 aee_aed 413 aee_aed64 414 aee_aedv 415 aee_aedv64 9175 android.ext.services 8444 android.hardware.audio@5.0-service-mediatek 766 android.hardware.biometrics.fingerprint@2.1-service 576 android.hardware.bluetooth@1.0-service-mediatek 577 android.hardware.cas@1.1-service 578 android.hardware.configstore@1.1-service 579 android.hardware.drm@1.0-service 580 android.hardware.drm@1.2-service.clearkey 581 android.hardware.drm@1.2-service.widevine 582 android.hardware.gatekeeper@1.0-service 583 android.hardware.gnss@2.0-service-mediatek .... 还有好多
使用: 绕过android https ( ssl 的验证)
假设,我们通过安卓逆向, 获得了目标app 的源代码, 对应校验证书的代码为:
package com.<target>.utilslibrary.retrofit;
import android.content.Context;
import java.io.BufferedInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import okhttp3.at;
public class a { 
  public static void a(Context paramContext, at paramat) {
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    BufferedInputStream bufferedInputStream = new BufferedInputStream(paramContext.getAssets().open("certs/cert.crt"));
    Certificate certificate = certificateFactory.generateCertificate(bufferedInputStream);
    bufferedInputStream.close();
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", certificate);
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);
    SSLContext sSLContext = SSLContext.getInstance("TLS");
    sSLContext.init(null, trustManagerFactory.getTrustManagers(), null);
    paramat.a(sSLContext.getSocketFactory(), new b(certificate));
  }
}
创建一个脚本
import frida, sys, time
# 该方法仅仅用于调试
def on_message(message, data):
    print("=== in on_message")
    print(message)
    print(data)
# 这段是核心代码,多行javascript.
jscode = """
Java.perform(function () {
  // 这里用的是class 的全名(package + class)
  var target_class = Java.use('com.target.utilslibrary.retrofit.a');
  // 这里的 target_class.a 就是我们需要绕过的方法
  var the_method = target_class.a;
  // 这里是对方法进行实现
  the_method.implementation = function (p1, p2) {
    // 该方法的实现中,没有任何内容.也就是说, 不做任何SSL证书的校验
  };
});
"""
device = frida.get_usb_device()
# 根据android package名字来唤醒对应的app
pid = device.spawn(["com.target.wallets"])  // 修改成你的目标app package
device.resume(pid)
# 进程停止1秒钟.让该APP启动
time.sleep(1)
script = device.attach(pid).create_script(jscode)
script.on('message', on_message)
print('==== script start ...')
script.load()
sys.stdin.read()