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!