Learning Man's Blog

Frida —— 初体验

字数统计: 1.4k阅读时长: 7 min
2019/01/16

来自于Awesome Frida的介绍

Frida is Greasemonkey for native apps, or, put in more technical terms, it’s a dynamic code instrumentation toolkit. It lets you inject snippets of JavaScript into native apps that run on Windows, Mac, Linux, iOS and Android.

Frida可以认为是原生应用的油猴脚本,或其他更专业的技术术语。它是一种动态插桩工具集,可以将js代码插入到在WindowsMacLinuxiOSAndroid上运行的原生应用中。

  1. 比较
Frida CydiaSubstrate Substitute Detours Deviare EasyHook diStormX
Open Source ✔️ ✔️ ✔️ ✔️ ✔️
Allows use in closed-source software¹ ✔️ ✔️ ✔️ ✔️ ✔️
Windows ✔️ ✔️ ✔️ ✔️ ✔️
Mac ✔️ ✔️
Linux ✔️
iOS ✔️ ✔️ ✔️
Android ✔️ ✔️
QNX ✔️
x86-32 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
x86-64 ✔️ ✔️ ✔️ ✔️ ✔️ ✔️
arm ✔️ ✔️ ✔️
arm64 ✔️ ✔️ ✔️
MIPS ✔️
Language bindings ✔️ ✔️
Instruction-level probes ✔️
Zero-knowledge before/after hooks² ✔️ ✔️
Transactional (batching) ✔️ ✔️ ✔️ ✔️ ✔️
Intelligent relocation³ ✔️ ✔️
Tiny functions (code caves) ✔️
Rollback ✔️ ✔️ ✔️ ✔️ ✔️

0x01 安装

  1. 安装frida

     > pip install frida frida-tools
  2. 下载对应版本frida-server,使用adb推送

     > adb push frida-server /data/local/tmp/
  3. root 下执行frida-server

     > adb shell
     bullhead:/ $ su -
     bullhead:/ # cd /data/local/tmp
     bullhead:/ # chmod +x frida-server
     bullhead:/ # ./frida-server

0x02 测试机选择

经测试最好还是使用物理机,x64架构虚拟机上很多app无法安装,arm虚拟机太卡且有时候frida会莫名报错

Android

选用Nexus 5X,刷8.1.0 & Magisk,具体操作可见参考资料1

iOS

待更新

0x0N Crackme

环境

  • 主机

    • frida
  • 手机

    • Nexus 5 (with Android 8.1.0) 已 root
    • frida-server

注意

需要要注意几点

  1. setImmediate据说可以避免一些执行时间过长问题
  2. 使用-f参数 新启动并暂时挂起进程,然后待布置好hook代码后再恢复进程运行,配合使用--no-pause取消挂起相当于直接创建一个新进程后进行hook,这里在hook onCreate时会有问题,下面会提到

一些常用命令

安装apk

> adb install UnCrackable-Level1.apk

快捷截图

> adb shell screencap -p > `date "+%Y%m%d%H%M%S"`.png

Crack

  1. 启动后会检测是否Root

  2. 查看检测代码,将apk拖入到jadx-gui中

     public class MainActivity extends Activity {
         private void a(String str) {
             AlertDialog create = new Builder(this).create();
             create.setTitle(str);
             create.setMessage("This in unacceptable. The app is now going to exit.");
             create.setButton(-3, "OK", new b(this));
             create.setCancelable(false);
             create.show();
         }
    
         protected void onCreate(Bundle bundle) {
             if (c.a() || c.b() || c.c()) {
                 a("Root detected!");
             }
             if (b.a(getApplicationContext())) {
                 a("App is debuggable!");
             }
             super.onCreate(bundle);
             setContentView(R.layout.activity_main);
         }
    
         public void verify(View view) {
             String obj = ((EditText) findViewById(R.id.edit_text)).getText().toString();
             AlertDialog create = new Builder(this).create();
             if (a.a(obj)) {
                 create.setTitle("Success!");
                 create.setMessage("This is the correct secret.");
             } else {
                 create.setTitle("Nope...");
                 create.setMessage("That's not it. Try again.");
             }
             create.setButton(-3, "OK", new c(this));
             create.show();
         }
     } 
  3. 这里有两种方法

    1. 通过所有检测,即Hook掉c.a&c.b&c.c&b.a

    2. 注意到弹窗的监听类为b,可Hook b.onClick不执行退出

      class b implements OnClickListener {
       final /* synthetic */ MainActivity a;
      
       b(MainActivity mainActivity) {
           this.a = mainActivity;
       }
      
       public void onClick(DialogInterface dialogInterface, int i) {
           System.exit(0);
       }
      }
  4. 先尝试ii中的Hook b.onClick

     setImmediate(function () {
         Java.perform(function(){
             cClass = Java.use("sg.vantagepoint.uncrackable1.b");
             cClass.onClick.implementation = function () {
                 console.log("[!] hook click");
             }})
     });

    注入脚本,点击ok按钮

     > frida -U -f sg.vantagepoint.uncrackable1 -l 1.js --no-pause
          ____
         / _  |   Frida 12.2.29 - A world-class dynamic instrumentation toolkit
        | (_| |
         > _  |   Commands:
        /_/ |_|       help      -> Displays the help system
        . . . .       object?   -> Display information about 'object'
        . . . .       exit/quit -> Exit
        . . . .
        . . . .   More info at http://www.frida.re/docs/home/
     Spawned `sg.vantagepoint.uncrackable1`. Resuming main thread!
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> [!] Hook click
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> exit
    
     Thank you for using Frida!
  1. 尝试iHook onCreate

    初步尝试在加上--no-pauseZygote启动后,由于取消挂起这时候代码并没有hook进去,而是在onCreate结束后才开始注入,所以需要去掉--no-pause等待 hook 后恢复进程,会比较耗时,但能正常 hook onCreate

     > frida -U -f package -l script_file

    Hook脚本

     setImmediate(function () {
         Java.perform(function(){
             cClass = Java.use("sg.vantagepoint.a.c");
             cClass.a.implementation = function () {
                 console.log('[!] Hook c.a');
                 return false;
             };
             cClass.b.implementation = function () {
                 console.log('[!] Hook c.a');
                 return false;
             };
             cClass.c.implementation = function () {
                 console.log('[!] Hook c.c');
                 return false;
             };
             bClass = Java.use("sg.vantagepoint.a.b");
             bClass.a.implementation = function () {
                 console.log('[!] Hook b.a');
                 return false;
             }
         })
     });

    执行注入,就没有弹窗了

     > frida -U -f sg.vantagepoint.uncrackable1 -l 1.js
          ____
         / _  |   Frida 12.2.29 - A world-class dynamic instrumentation toolkit
        | (_| |
         > _  |   Commands:
        /_/ |_|       help      -> Displays the help system
        . . . .       object?   -> Display information about 'object'
        . . . .       exit/quit -> Exit
        . . . .
        . . . .   More info at http://www.frida.re/docs/home/
     Spawned `sg.vantagepoint.uncrackable1`. Use %resume to let the main thread start executing!
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> [!] Hook c.a
     [!] Hook c.a
     [!] Hook c.c
     [!] Hook b.a
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> exit
    
     Thank you for using Frida!
  2. 接下来是一个输入字符串返回比较结果,事件函数为a.a,重要的是获取bArr,即sg.vantagepoint.a.a.a返回结果

     public class a {
         public static boolean a(String str) {
             byte[] bArr = new byte[0];
             try {
                 bArr = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0));
             } catch (Exception e) {
                 Log.d("CodeCheck", "AES error:" + e.getMessage());
             }
             return str.equals(new String(bArr));
         }
    
         public static byte[] b(String str) {
             int length = str.length();
             byte[] bArr = new byte[(length / 2)];
             for (int i = 0; i < length; i += 2) {
                 bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
             }
             return bArr;
         }
     }

    sg.vantagepoint.a.a.a代码如下,我们不用在意代码内容,只要 hook 结果就好了

     public class a {
         public static byte[] a(byte[] bArr, byte[] bArr2) {
             Key secretKeySpec = new SecretKeySpec(bArr, "AES/ECB/PKCS7Padding");
             Cipher instance = Cipher.getInstance("AES");
             instance.init(2, secretKeySpec);
             return instance.doFinal(bArr2);
         }
     }

    Hook 代码,使用this.a调用原a函数

     setImmediate(function () {
         Java.perform(function(){
             ...
             aaClass = Java.use("sg.vantagepoint.a.a");
             aaClass.a.implementation = function (arg1, arg2) {
                 pass = "";
                 s = this.a(arg1, arg2);
                 for(i=0; i<s.length; i++) {
                     pass += String.fromCharCode(s[i]);
                 }
                 console.log("[*] content: " + pass);
                 return s;
             }
         })
     });

    执行代码,获取隐藏内容

     > frida -U -f sg.vantagepoint.uncrackable1 -l 1.js --no-pause
          ____
         / _  |   Frida 12.2.29 - A world-class dynamic instrumentation toolkit
        | (_| |
         > _  |   Commands:
        /_/ |_|       help      -> Displays the help system
        . . . .       object?   -> Display information about 'object'
        . . . .       exit/quit -> Exit
        . . . .
        . . . .   More info at http://www.frida.re/docs/home/
     Spawned `sg.vantagepoint.uncrackable1`. Resuming main thread!
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> [!] Hook click
     [*] content: I want to believe
     [LGE Nexus 5X::sg.vantagepoint.uncrackable1]-> exit
    
     Thank you for using Frida!

参考资料

  1. https://www.52pojie.cn/thread-836277-1-1.html
  2. https://github.com/iromise/AOS-Note/blob/42544f4635/frida-exp/frida.md
  3. https://github.com/dweinstein/awesome-frida
CATALOG
  1. 1. 0x01 安装
  2. 2. 0x02 测试机选择
    1. 2.1. Android
    2. 2.2. iOS
  3. 3. 0x0N Crackme
    1. 3.1. 环境
    2. 3.2. 注意
    3. 3.3. Crack
  4. 4. 参考资料