在一篇文章帶你領悟Frida的精髓一文中,我們已經學會了對放的重載進行處理的方法,我們先回顧一下程式碼:
my_class.fun.overload("int" , "int").implementation = function(x,y){ my_class.fun.overload("java.lang.String").implementation = function(x){
也就是說我們需要建構一個重載的數組,並且把每一個重載都印出來。我們直接上程式碼:
//目标类 var hook = Java.use(targetClass); //重载次数 var overloadCount = hook[targetMethod].overloads.length; //打印日志:追踪的方法有多少个重载 console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]"); //每个重载都进入一次 for (var i = 0; i <p>這樣我們對於方法的所有重載就處理好了,接下來就是列舉所有方法。 </p><h4>0x02.hook類別的所有方法</h4><p>還是直接上程式碼:</p><pre class="brush:php;toolbar:false">function traceClass(targetClass) { //Java.use是新建一个对象哈,大家还记得么? var hook = Java.use(targetClass); //利用反射的方式,拿到当前类的所有方法 var methods = hook.class.getDeclaredMethods(); //建完对象之后记得将对象释放掉哈 hook.$dispose; //将方法名保存到数组中 var parsedMethods = []; methods.forEach(function(method) { parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]); }); //去掉一些重复的值 var targets = uniqBy(parsedMethods, JSON.stringify); //对数组中所有的方法进行hook,traceMethod也就是第一小节的内容 targets.forEach(function(targetMethod) { traceMethod(targetClass + "." + targetMethod); }); }
還是上核心部分的程式碼:
//枚举所有已经加载的类 Java.enumerateLoadedClasses({ onMatch: function(aClass) { //迭代和判断 if (aClass.match(pattern)) { //做一些更多的判断,适配更多的pattern var className = aClass.match(/[L]?(.*);?/)[1].replace(/\//g, "."); //进入到traceClass里去 traceClass(className); } }, onComplete: function() {} });
// 追踪本地库函数 function traceModule(impl, name) { console.log("Tracing " + name); //frida的Interceptor Interceptor.attach(impl, { onEnter: function(args) { console.warn("\n*** entered " + name); //打印调用栈 console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) .map(DebugSymbol.fromAddress).join("\n")); }, onLeave: function(retval) { //打印返回值 console.log("\nretval: " + retval); console.warn("\n*** exiting " + name); } }); }
終於到了實戰的時候,把以上程式碼拼接起來,形成一個腳本,其實這個腳本awesome-frida 裡面也有介紹,程式碼在這裡,就是有點小bug,經過葫蘆娃修改好之後,終於可以用了。
我們來試下它的幾個主要的功能,首先是本地庫的導出函數。
setTimeout(function() { Java.perform(function() { trace("exports:*!open*"); //trace("exports:*!write*"); //trace("exports:*!malloc*"); //trace("exports:*!free*"); }); }, 0);
我們hook
的是open()
函數,跑起來看下效果:
$ frida -U -f com.whatsapp -l raptor_frida_android_trace_fixed.js --no-pause
如圖所示*!open*
根據正則匹配到了openlog
、open64
等導出函數,並hook了所有這些函數,打印出了其參數以及返回值。
接下來要看哪個部分,只要丟到jadx
裡,靜態「分析」一番,自己隨便翻翻,或是根據字串搜一搜。
比如說我們想看上圖的com.whatsapp.app.protocol
套件裡的內容,就可以設定trace ("com.whatsapp.app.protocol")
。
可以看到套件內的函數、方法、包含重載、參數、以及回傳值全都印出來了。這就是frida
腳本的魅力。
當然,腳本終歸只是一個工具,你對Java
、安卓App的理解,和你的創意才是至關重要的。
接下來可以搭配Xposed module看看別人都給whatsapp
做了哪些模組,hook
的哪些函數,實作了哪些功能,學習自己寫一寫。
當然,再強調一句,做外掛是違法行為,千萬不要製作和分發任何App的外掛,否則等待你的只會是法律的製裁。
以上是使用Java的動態和靜態結合方法逆向WhatsApp的步驟的詳細內容。更多資訊請關注PHP中文網其他相關文章!