Frida强大的功能让无数安全研究人员沉溺其中。我们往往使用pc编写好frida的js脚本,然后使用spawn或者attach的方式使得我们的hook脚本生效。那么能否做到像Xposed一样,让我们编写的hook脚本不依赖于pc,从而达到hook脚本的持久化呢?同时,是否能够在手机上单独设置哪一个js脚本只对哪一个app生效呢?答案是可以,得益于fridagadget共享库的强大功能,可以让我们达成frida脚本的持久化!众所周知,要想使用fridagadget,就需要对app进行重打包,注入该so库,首先,鉴于众多app开发人员安全意识的增强,app大多都会对签名进行校验,使得重打包后的app并不会正常的运行,往往会伴随大量的crash。同时,众多加固厂商的技术也不容小觑。不管是从重打包繁琐的流程还是从app保护的角度出发,对app进行重打包来使用fridagadget都不是一个良好的解决方案。那么有没有一个一劳永逸同时足够简单的方案呢?自然是有,我们依然从app的生命周期出发,在我在FART系列脱壳文章中针对加壳app的运行流程做了简单的介绍,当我们点击一个app的图标后,最先进入的便是ActivityThread这个类,同时,不同于对加固app的脱壳,需要选择尽可能晚的时机来完成对已经解密dex的dump和修复,要想对任意一款app实现Frida hook脚本的持久化,我们的hook时机应当是尽可能的早,如果时机晚了,就可能会错过对app中自身类函数的hook时机,比如壳自身的类函数。因此,我们对于fridagadget注入的时机至少要早于app自身声明的APPlication子类的attachBaseContext函数的调用。因此,我们依然可以从ActivityThread中选择足够多的时机(只要还没有完成对APPlication子类的attachBaseContext函数的调用的时机都可以)。同时,我们又可以根据不同的app的包名来对当前运行的app进程注入不同的js脚本,这样,我们就不仅能够实现对Frida脚本的持久化,同时,还能够根据配置,针对不同的app进程,选择不同的js脚本。FridaManager就是基于此原理实现。
这里暂时只提供了nexus 5x的7.1.2 ,之后会放出Android 10的FridaManager版本rom,后期根据需求会逐步增加更多版本rom。
安装后进入设置授予该app读写sd卡权限,FridaManager app主要用于方便对不同的app选择需要持久化的js脚本,界面非常简单(请忽略FridaManager丑陋的界面......)
特别注意:安装完成后不要立即打开该app,同时注意到设置中授予该app读写sd卡权限(因为接下来要读取位于sd卡中的配置文件以及要持久化的js文件)
FridaManager的主界面主要分为两块,左边是用于选择要持久化的app;在选择好要进行注入的app后,接下来可以通过右边选择对其持久化的js脚本文件,此时可通过进入js脚本所在目录,点击选中。
当选中要持久化的app以及其对应的js脚本后,会弹出对话框,这时,便配置成功 (如下图)。
接下来只需要退出FridaManager,打开要持久化hook的app即可,这便是FridaManager的简单的使用流程。(同时,需要注意,当修改了需要持久化的js脚本文件后,需要kill掉app进程,重新打开才能生效)
代码逻辑非常清晰,只是使用Frida对Log类函数进行了主动调用,打印出hello fridamanager!以及goodbye fridamanager!这两个字符串.
接下来,我们只需要设置该frida脚本生效的app(由于需要读取sd卡,自然app需要有sd卡读写权限)。此时,需要使用FridaManager进行对特定app的配置,配置该app需要持久化的该js脚本,然后打开app,便可看到logcat中的信息:
将下面代码保存命名为traceJNIRegisterNative.js,拷贝到手机sd卡当中
接下来安装一个加壳了的app,并到设置中授予sd卡读写权限,之后在FridaManager中完成对该app要持久化的traceJNIRegisterNative.js的配置,
接下来只需要打开该app,便可以观察到该app中每一个jni函数的绑定流程(包括静态注册和动态注册的jni函数)。
好了,就到这里吧,想要体验的可以gitub或者到微信群中去下载,enjoy the frida world!
后续更新会放在github:
FridaManager
交流体验、获取更多机型支持以及反馈问题可加微信 hanbing1e,进群深入讨论
#为了让更多人体验到FridaManager带来的快感,这里已经将FridaManager编译成Magisk模块,配合FridaManager管理目标APP和js脚本更为顺滑爽快!(可以配合使用魔改的fridagadget,轻松绕过APP的检测),下载链接:https://pan.baidu.com/s/1OXQW3T4ENDsfg2GR-Z8zDA 提取码:t1xl
function Log(info) {
Java.perform(function () {
var LogClass
=
Java.use(
"android.util.Log"
);
LogClass.e(
"FridaManager"
, info);
})
}
function main() {
Log(
"hello fridamanager!"
);
Log(
"goodbye fridamanager!"
);
}
setImmediate(main);
function Log(info) {
Java.perform(function () {
var LogClass
=
Java.use(
"android.util.Log"
);
LogClass.e(
"FridaManager"
, info);
})
}
function main() {
Log(
"hello fridamanager!"
);
Log(
"goodbye fridamanager!"
);
}
setImmediate(main);
function Log(info) {
Java.perform(function () {
var LogClass
=
Java.use(
"android.util.Log"
);
LogClass.e(
"FridaManager"
, info);
})
}
function readStdString(
str
) {
const isTiny
=
(
str
.readU8() &
1
)
=
=
=
0
;
if
(isTiny)
return
str
.add(
1
).readUtf8String();
return
str
.add(
2
*
Process.pointerSize).readPointer().readUtf8String();
}
function hook_register_native() {
var libartmodule
=
Process.getModuleByName(
"libart.so"
);
var PrettyMethodaddr
=
null;
var RegisterNativeaddr
=
null;
libartmodule.enumerateExports().forEach(function (symbol) {
/
/
android7.
1.2
if
(symbol.name
=
=
"_ZN3art12PrettyMethodEPNS_9ArtMethodEb"
) {
PrettyMethodaddr
=
symbol.address;
}
});
var PrettyMethodfunc
=
new NativeFunction(PrettyMethodaddr, [
"pointer"
,
"pointer"
,
"pointer"
], [
"pointer"
,
"int"
]);
Interceptor.attach(RegisterNativeaddr, {
onEnter: function (args) {
var ArtMethodptr
=
args[
0
];
this.JniFuncaddr
=
args[
1
];
var result
=
PrettyMethodfunc(ArtMethodptr,
1
);
var stdstring
=
Memory.alloc(
3
*
Process.pointerSize);
ptr(stdstring).writePointer(result[
0
]);
ptr(stdstring).add(
1
*
Process.pointerSize).writePointer(result[
1
]);
ptr(stdstring).add(
2
*
Process.pointerSize).writePointer(result[
2
]);
this.funcnamestring
=
readStdString(stdstring);
Log(
"[RegisterJni begin]"
+
this.funcnamestring
+
"--addr:"
+
this.JniFuncaddr);
}, onLeave: function (retval) {
Log(
"[RegisterJni over]"
+
this.funcnamestring
+
"--addr:"
+
this.JniFuncaddr);
}
})
}
function main() {
Log(
"hello fridamanager!"
);
hook_register_native();
Log(
"goodbye fridamanager!"
);
}
setImmediate(main);
function Log(info) {
Java.perform(function () {
var LogClass
=
Java.use(
"android.util.Log"
);
LogClass.e(
"FridaManager"
, info);
})
}
function readStdString(
str
) {
const isTiny
=
(
str
.readU8() &
1
)
=
=
=
0
;
if
(isTiny)
return
str
.add(
1
).readUtf8String();
return
str
.add(
2
*
Process.pointerSize).readPointer().readUtf8String();
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-6-27 01:20
被hanbingle编辑
,原因: 更新Magisk支持,无需刷机,支持更多机型