准备工作
Frida
在这里对Frida进行了简单的介绍。
设备
设备: Android 10 ROOT
PC: Ubuntu18.04
Python切换
有些时候,需要使用Python的2.x版本,而有些时候又需要使用python的3.x版本,这个时候就需要能够灵活设置python版本 使用下面的命令设置Python2是默认:
sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100
使用下面的命令设置Python3是默认
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150
使用sudo update-alternatives--config python
命令切换到制定的版本 由于Frida建议使用Python3.x,因此这里切换到3的版本。在二进制漏洞中,exploit使用的基本都是Python2.7。
Frida脚本
FRIDA脚本就是利用FRIDA动态插桩框架,使用FRIDA导出的API和方法,对内存空间里的对象方法进行监视、修改或者替换的一段代码。FRIDA的API是使用JavaScript实现的,所以我们可以充分利用JS的匿名函数的优势、以及大量的hook和回调函数的API。
Hello world
Hello world经典的入门程序,frida版本的来一个。
setTimeout(function (){
Java.perform(function (){
console.log("Hello world");
});
});
使用的API
setTimeout(func, delay[, …parameters]): call func after delay milliseconds, optionally passing it one or more parameters. Returns an id that can be passed to clearTimeout to cancel it.
clearTimeout(id): cancel id returned by call to setTimeout.
Java.perform(fn): ensure that the current thread is attached to the VM and call fn. (This isn’t necessary in callbacks from Java.) Will defer calling fn if the app’s class loader is not available yet. Use Java.performNow() if access to the app’s classes is not needed.
console.log(line), console.warn(line), console.error(line): write line to the console of your Frida-based application.
JavaScript匿名函数
匿名函数:就是没有函数名的函数。这怎么可能,一个函数居然没有函数名,但JavaScript就是支持这种语法的,这和Java等编译型语言又很大的区别。匿名函数最大的用途是创建闭包。闭包是JavaScript的精髓,后续会专门讲解。
<script>
var fun = function (){
alert("欢迎关注我的微信公众号:无情剑客")
}
fun();
</script>
运行程序
通过前面的分析,可知这个程序最终调用console.log("Hello world");
在手机端开启frida-server. 然后在PC端运行下面的命令:
frida -U -l hello.js android.process.media
运行后的结果如下
枚举所有的类
setTimeout(function (){
Java.perform(function (){
console.log("n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(_className){
console.log("[*] found instance of '"+_className+"'");
},
onComplete: function(){
console.log("[*] class enuemration complete");
}
});
});
});
其中: Java.enumerateLoadedClasses(callbacks): enumerate classes loaded right now, where callbacks is an object specifying:
-
onMatch: function (name, handle): called for each loaded class with name that may be passed to use() to get a JavaScript wrapper. You may also Java.cast() the handle to java.lang.Class.
-
onComplete: function (): called when all classes have been enumerated.
运行js代码,同上,结果如下
枚举蓝牙类和实例
setTimeout(function (){
Java.perform(function (){
console.log("n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(_className){
if(_className.split(".")[1] == bluetooth){
console.log("[*] found instance of '"+_className+"'");
}
},
onComplete: function(){
console.log("[*] class enuemration complete");
}
});
});
});
运行后,可以看出有关bluetooth相关的类和实例都被枚举出来了。 选定”android.bluetooth.BluetoothDevice”,获取peer device的实例信息。
Java.choose("android.bluetooth.BluetoothDevice",{
onMatch: function (instance){
console.log("[*] "+" android.bluetooth.BluetoothDevice instance found"+" :=> '"+instance+"'");
//这里是类型转化的用法
//console.log(Java.cast(instance,Java.use("android.bluetooth.BluetoothDevice") ).getName());
console.log(instance.getName());
// bluetoothDeviceInfo(instance);
},
onComplete: function() { console.log("[*] -----");}
});
其中: Java.choose(className, callbacks): enumerate live instances of the className class by scanning the Java heap, where callbacks is an object specifying:
- onMatch: function (instance): called with each live instance found with a ready-to-use instance just as if you would have called Java.cast() with a raw handle to this particular instance. This function may return the string stop to cancel the enumeration early.
- onComplete: function (): called when all instances have been enumerated
运行脚本,打印出peer device的名字和地址。
frida -U -l hello.js com.android.bluetooth
枚举所有方法
function enumMethods(targetClass)
{
var hook = Java.use(targetClass);
var ownMethods = hook.class.getDeclaredMethods();
hook.$dispose;
return ownMethods;
}
var a = enumMethods("android.bluetooth.BluetoothDevice")
a.forEach(function(s) {
console.log(s);
});
其中: Java.use(className): dynamically get a JavaScript wrapper for className that you can instantiate objects from by calling $new() on it to invoke a constructor. Call $dispose() on an instance to clean it up explicitly (or wait for the JavaScript object to get garbage-collected, or script to get unloaded). Static and non-static methods are available, and you can even replace a method implementation and throw an exception from it:
Java.perform(function () {
var Activity = Java.use('android.app.Activity');
var Exception = Java.use('java.lang.Exception');
Activity.onResume.implementation = function () {
throw Exception.$new('Oh noes!');
};
});
使用下面的命令运行脚本,枚举android.bluetooth.BluetoothDevice声明的所有方法。
frida -U -l hello.js com.android.bluetooth
通过frida hook就能够对想要hook的方法进行控制了。这里举一个简单的例子,我想让所有的getName()都返回”Redmi”。
setTimeout(function (){
Java.perform(function (){
console.log("n[*] enumerating classes...");
var targetClass = Java.use("android.bluetooth.BluetoothDevice");
targetClass.getName.implementation=function(){
var x = this.getName();
return 'Redmi';
}
Java.choose("android.bluetooth.BluetoothDevice",{
onMatch: function (instance){
console.log("[*] "+" android.bluetooth.BluetoothDevice instance found"+" :=> '"+instance+"'");
// console.log(Java.cast(instance,Java.use("android.bluetooth.BluetoothDevice") ).getName());
console.log(instance.getName());
// bluetoothDeviceInfo(instance);
},
onComplete: function() { console.log("[*] -----");}
});
});
});
或者
import frida,sys
def on_message(message, data):
if message['type'] == 'send':
print(" {0}".format(message['payload']))
else:
print(message)
pass
session = frida.get_usb_device().attach("com.android.bluetooth")
jscode = """
if(Java.available){
Java.perform(function(){
var targetClass = Java.use("android.bluetooth.BluetoothDevice");
targetClass.getName.implementation=function(){
x = this.getName();
sned(x);
return 'Redmi';
}
});
}
"""
script = session.create_script(jscode)
script.on("message", on_message)
print(' Start attach')
script.load()
sys.stdin.read()
前者的运行结果: 微信运动的步数,支付宝的总金额等都可以用类似的方式进行修改。
完整的代码
setTimeout(function (){
Java.perform(function (){
console.log("n[*] enumerating classes...");
Java.enumerateLoadedClasses({
onMatch: function(_className){
if(_className.split(".")[1] == "bluetooth"){
console.log("[*] found instance of '"+_className+"'");
}
},
onComplete: function(){
console.log("[*] class enuemration complete");
}
});
Java.choose("android.bluetooth.BluetoothDevice",{
onMatch: function (instance){
console.log("[*] "+" android.bluetooth.BluetoothDevice instance found"+" :=> '"+instance+"'");
// console.log(Java.cast(instance,Java.use("android.bluetooth.BluetoothDevice") ).getName());
console.log(instance.getName());
// bluetoothDeviceInfo(instance);
},
onComplete: function() { console.log("[*] -----");}
});
function enumMethods(targetClass)
{
var hook = Java.use(targetClass);
var ownMethods = hook.class.getDeclaredMethods();
hook.$dispose;
return ownMethods;
}
var a = enumMethods("android.bluetooth.BluetoothDevice")
a.forEach(function(s) {
console.log(s);
});
});
});
参考
https://frida.re/docs/javascript-api/
公众号
更多Frida相关的文章,欢迎关注我的公众号:无情剑客。
来源:freebuf.com 2020-08-02 14:04:02 by: 无情剑客Burning
请登录后发表评论
注册