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 测试机选择
  3. 3. 0x0N Crackme
  4. 4. 参考资料