Frida简单使用

1.得到android手机当前最前端Activity所在的进程
python文件 exampleFrida.py

import frida
rdev = frida.get_remote_device()
front_app = rdev.get_frontmost_application()
print (front_app)

2.枚举android手机所有的进程
python文件

import frida
rdev = frida.get_remote_device()
processes = rdev.enumerate_processes()
for process in processes:
    print (process)

3.枚举某个进程加载的所有模块以及模块中的导出函数
python文件

import frida
rdev = frida.get_remote_device()
session = rdev.attach("com.tencent.mm")  # 使用frida,attach里为需要注入的app,如果存在两个一样的进程名可以采用rdev.attach(pid)的方式
modules = session.enumerate_modules() #enumerate_modules()方法来获取进程中加载模块的host信息
for module in modules:
    print (module)
    export_funcs = module.enumerate_exports()
    print ("\tfunc_name\tRVA")
    for export_func in export_funcs:
        print ("\t%s\t%s"%(export_func.name,hex(export_func.relative_address)))

session对象允许你获取信息,同时也可以操作目标进程。可以调用enumerate_modules()方法来获取进程中加载模块的host信息。

session =frida.get_remote_device().attach("com.mahh.secretsafe")
>>> printsession.enumerate_modules()
[Module(name="app_process", base_address=0x40096000, size=8192, path="/system/bin/app_process"), Module(name="linker", base_address=0x4009a000, size=61440, path="/system/bin/linker"), Module(name="libcutils.so", base_address=0x400b0000, size=36864, path="/system/lib/libcutils.so"), Module(name="liblog.so", base_address=0x400bb000, size=12288, path="/system/lib/liblog.so"), Module(name="libc.so", base_address=0x400c0000, size=53248, path="/system/lib/libc.so"), Module(name="libstdc++.so", base_address=0x4011b000, size=4096, path="/system/lib/libstdc++.so"), Module(name="libm.so", base_address=0x4011e000, size=98304, path="/system/lib/libm.so")

4.app
(1)打开模拟器,安装UnCrackable-Level1.apk
(2)打开app
这里写图片描述
会弹出如图的对话框,我们发现一旦点击ok,app就会退出

(3)开启frida-server 方法见上篇
(4)用压缩软件从apk中提取dex文件,然后用dex2jar将dex文件转换为jar文件,最后用jd-gui打开,我们就可以看apk里面的代码了。代码中调用了几个方法来检测手机是否被root:

protected void onCreate(Bundle paramBundle)
  {
    if ((sg.vantagepoint.a.c.a()) || (sg.vantagepoint.a.c.b()) || (sg.vantagepoint.a.c.c())) {
      a("Root detected!");
    }
    if (sg.vantagepoint.a.b.a(getApplicationContext())) {
      a("App is debuggable!");
    }
    super.onCreate(paramBundle);
    setContentView(2130903040);
  }

sg.vantagepoint.a.c

package sg.vantagepoint.a;

import android.os.Build;
import java.io.File;

public class c
{
  public static boolean a()
  {
    boolean bool2 = false;
    String[] arrayOfString = System.getenv("PATH").split(":");
    int j = arrayOfString.length;
    int i = 0;
    for (;;)
    {
      boolean bool1 = bool2;
      if (i < j)
      {
        if (new File(arrayOfString[i], "su").exists()) {
          bool1 = true;
        }
      }
      else {
        return bool1;
      }
      i += 1;
    }
  }

  public static boolean b()
  {
    String str = Build.TAGS;
    return (str != null) && (str.contains("test-keys"));
  }

  public static boolean c()
  {
    String[] arrayOfString = new String[7];
    arrayOfString[0] = "/system/app/Superuser.apk";
    arrayOfString[1] = "/system/xbin/daemonsu";
    arrayOfString[2] = "/system/etc/init.d/99SuperSUDaemon";
    arrayOfString[3] = "/system/bin/.ext/.su";
    arrayOfString[4] = "/system/etc/.has_su_daemon";
    arrayOfString[5] = "/system/etc/.installed_su_daemon";
    arrayOfString[6] = "/dev/com.koushikdutta.superuser.daemon/";
    int j = arrayOfString.length;
    int i = 0;
    while (i < j)
    {
      if (new File(arrayOfString[i]).exists()) {
        return true;
      }
      i += 1;
    }
    return false;
  }
}

MainActivity中

private void a(String paramString)
  {
    AlertDialog localAlertDialog = new AlertDialog.Builder(this).create();
    localAlertDialog.setTitle(paramString);
    localAlertDialog.setMessage("This in unacceptable. The app is now going to exit.");
    localAlertDialog.setButton(-3, "OK", new b(this));
    localAlertDialog.setCancelable(false);
    localAlertDialog.show();
  }

点击ok调用了 System.exit(0);退出

class b
  implements DialogInterface.OnClickListener
{
  b(MainActivity paramMainActivity) {}

  public void onClick(DialogInterface paramDialogInterface, int paramInt)
  {
    System.exit(0);
  }
}

(5)为了实现点击ok不退出,用frida覆盖onClick方法
uncrackable1.js

//实现OnClickListener接口并覆盖其onClick方法
setImmediate(function() { //代码封装到setImmediate函数中以防止超时
    console.log("[*] Starting script");
    Java.perform(function() {//通过Java.perform来使用frida用于处理Java的方法,输入的代码必须包装在Java.perform(function(){...})中,这是Fridas的Java API的硬性要求
      bClass = Java.use("sg.vantagepoint.uncrackable1.b");//定义需要hook的类,Java.use('...');
      bClass.onClick.implementation = function(v) {
         console.log("[*] onClick called");//console.log是为了向控制台输出
      }
      console.log("[*] onClick handler modified")
    })
})

终端进入到js文件所在文件夹执行:

frida -U -l uncrackable1.js sg.vantagepoint.uncrackable1

这里写图片描述
这时候再回到模拟器点击ok程序就不会退出了

(6)追踪密码

package sg.vantagepoint.uncrackable1;

import android.util.Base64;
import android.util.Log;

public class a
{
  public static boolean a(String paramString)
  {
    byte[] arrayOfByte2 = Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0);
    byte[] arrayOfByte1 = new byte[0];
    try
    {
      arrayOfByte2 = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), arrayOfByte2);
      arrayOfByte1 = arrayOfByte2;
    }
    catch (Exception localException)
    {
      for (;;)
      {
        Log.d("CodeCheck", "AES error:" + localException.getMessage());
      }
    }
    return paramString.equals(new String(arrayOfByte1));
  }

  public static byte[] b(String paramString)
  {
    int j = paramString.length();
    byte[] arrayOfByte = new byte[j / 2];
    int i = 0;
    while (i < j)
    {
      arrayOfByte[(i / 2)] = ((byte)((Character.digit(paramString.charAt(i), 16) << 4) + Character.digit(paramString.charAt(i + 1), 16)));
      i += 2;
    }
    return arrayOfByte;
  }
}

arrayOfByte2是函数sg.vantagepoint.a.a.a的返回值,string.equals会将输入的密码与arrayOfByte2进行比较。所以需要要追踪sg.vantagepoint.a.a.a的返回值。

uncrackable2.js

setImmediate(function() {
    console.log("[*] Starting script");
    Java.perform(function() {
        bClass = Java.use("sg.vantagepoint.uncrackable1.b");
        bClass.onClick.implementation = function(v) {//public void onClick(DialogInterface paramDialogInterface, int paramInt)
         console.log("[*] onClick called.");
        }
        console.log("[*] onClick handler modified")
        aaClass = Java.use("sg.vantagepoint.a.a");
        aaClass.a.implementation = function(arg1, arg2) {//public static byte[] a(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
            retval = this.a(arg1, arg2);
            password = ''
            for(i = 0; i < retval.length; i++) {
               password += String.fromCharCode(retval[i]);//String.fromCharCode() 方法返回使用指定的Unicode值序列创建的字符串下例返回字符串 "ABC": String.fromCharCode(65,66,67)
            }
            console.log("[*] Decrypted: " + password);
            return retval;
        }
        console.log("[*] sg.vantagepoint.a.a.a modified");
    });
});

运行脚本之后,在frida下已经得到解码的密码:I want believe,将密码输入进去会显示success!
这里写图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值