在這裡對Frida進行了簡單的介紹。
設備: android 10 ROOT
PC: Ubuntu18.04
有些時候,需要使用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導出的API和方法,對內存空間裡的對象方法進行監視、修改或者替換的一段代碼。FRIDA的API是使用JavaScript實現的,所以我們可以充分利用JS的匿名函數的優勢、以及大量的hook和回調函數的API。
Hello world經典的入門程序,frida版本的來一個。
setTimeout(function (){ Java.perform(function (){ console.log(&34;); });});
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就是支持這種語法的,這和Java等編譯型語言又很大的區別。匿名函數最大的用途是創建閉包。閉包是JavaScript的精髓,後續會專門講解。
<script> var fun = function (){ alert(&34;) } fun();</script>
通過前面的分析,可知這個程序最終調用 console.log(&34;);
在手機端開啟frida-server.
然後在PC端運行下面的命令:
frida -U -l hello.js android.process.media
運行後的結果如下
setTimeout(function (){ Java.perform(function (){ console.log(&34;); Java.enumerateLoadedClasses({ onMatch: function(_className){ console.log(&39;&34;&34;); }, onComplete: function(){ console.log(&34;); } }); }); });
其中: Java.enumerateLoadedClasses(callbacks): enumerate classes loaded right now, where callbacks is an object specifying:
運行js代碼,同上,結果如下
setTimeout(function (){ Java.perform(function (){ console.log(&34;); Java.enumerateLoadedClasses({ onMatch: function(_className){ if(_className.split(&34;)[1] == bluetooth){ console.log(&39;&34;&34;); } }, onComplete: function(){ console.log(&34;); } }); }); });
運行後,可以看出有關bluetooth相關的類和實例都被枚舉出來了。
選定&34;,獲取peer device的實例信息。
Java.choose(&34;,{ onMatch: function (instance){ console.log(&34;+&34;+&39;&34;&34;); //這裡是類型轉化的用法 //console.log(Java.cast(instance,Java.use(&34;) ).getName()); console.log(instance.getName()); // bluetoothDeviceInfo(instance); }, onComplete: function() { console.log(&34;);} });
其中: Java.choose(className, callbacks): enumerate live instances of the className class by scanning the Java heap, where callbacks is an object specifying:
運行腳本,列印出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(&34;) 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(&39;); var Exception = Java.use(&39;); Activity.onResume.implementation = function () { throw Exception.$new(&39;); };});
使用下面的命令運行腳本,枚舉android.bluetooth.BluetoothDevice聲明的所有方法。
frida -U -l hello.js com.android.bluetooth
通過frida hook就能夠對想要hook的方法進行控制了。這裡舉一個簡單的例子,我想讓所有的getName()都返回&34;。
setTimeout(function (){ Java.perform(function (){ console.log(&34;); var targetClass = Java.use(&34;); targetClass.getName.implementation=function(){ var x = this.getName(); return &39;; } Java.choose(&34;,{ onMatch: function (instance){ console.log(&34;+&34;+&39;&34;&34;); // console.log(Java.cast(instance,Java.use(&34;) ).getName()); console.log(instance.getName()); // bluetoothDeviceInfo(instance); }, onComplete: function() { console.log(&34;);} }); }); });
或者
import frida,sysdef on_message(message, data): if message[&39;] == &39;: print(&34;.format(message[&39;])) else: print(message)passsession = frida.get_usb_device().attach(&34;)jscode = &34;&34;android.bluetooth.BluetoothDevice&39;Redmi&34;&34;script = session.create_script(jscode)script.on(&34;, on_message)print(&39;)script.load()sys.stdin.read()
前者的運行結果:
微信運動的步數,支付寶的總金額等都可以用類似的方式進行修改。
setTimeout(function (){ Java.perform(function (){ console.log(&34;); Java.enumerateLoadedClasses({ onMatch: function(_className){ if(_className.split(&34;)[1] == &34;){ console.log(&39;&34;&34;); } }, onComplete: function(){ console.log(&34;); } }); Java.choose(&34;,{ onMatch: function (instance){ console.log(&34;+&34;+&39;&34;&34;); // console.log(Java.cast(instance,Java.use(&34;) ).getName()); console.log(instance.getName()); // bluetoothDeviceInfo(instance); }, onComplete: function() { console.log(&34;);} }); function enumMethods(targetClass) { var hook = Java.use(targetClass); var ownMethods = hook.class.getDeclaredMethods(); hook.$dispose; return ownMethods; } var a = enumMethods(&34;) a.forEach(function(s) { console.log(s); }); }); });
https://frida.re/docs/javascript-api/
更多Frida相關的文章,歡迎關注我的公眾號:無情劍客。