Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Analysis of Frida Java Hook example

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly explains the "Frida Java Hook sample analysis", the content of the article is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "Frida Java Hook sample analysis" bar!

1.1 Java layer intercepts inner class functions

HOOK in Android reverse, we also often encounter inner classes in the Java layer. Java internal class functions make it more difficult to analyze the code. In this chapter, we have a basic understanding of inner classes and use FRIDA to intercept inner classes with hooks. What is an inner class? The so-called inner class is the nesting operation of other class structures within a class, its advantage is that the inner class and the outer class can easily access each other's private domain (including private methods and private properties), so there are many places in the Android to use the inner class, and it is most intuitive for us to see an example, as shown in figure 4-17 below.

Figure 4-17 clz class in the User class

It is not uncommon to see a clz nested in the User class in figure 4-17. In frida, we can use the $symbol to process pairs. First of all, open the jadxgui software to decompile the code. After decompilation, enter the User class. There will be a button for smali below. Click smali to enter the smali code. Enter the smali code and directly press the ctrl+f local search string clz. Because clz is the name of the inner class, you will find Lcom/roysue/roysueapplication/User\ $clz;,. We will translate it into java code: com.roysue.roysueapplication.User\ $clz, remove the L and / of the first string, and The specific class name of the inner class is formed, as shown in figure 4-18 below.

Figure 4-18 smali Code

After the above analysis, we already know the path of the most important part of the class: com.roysue.roysueapplication.User\ $clz. Now let's HOOK the inner class and start writing the js script.

1.1.1 intercept the inner class function code example function hook_overload_3 () {if (Java.available) {Java.perform (function () {console.log ("start hook"); / / notice here that the path of the class is filled in to change the analyzed path var clz = Java.use ('com.roysue.roysueapplication.User$clz'). If (clz! = undefined) {/ / here is also like the normal function to hook clz.toString.implementation = function () {console.log ("successful hook clz class"); return this.toString () }} else {console.log ("clz: undefined");} console.log ("start end");};}}

After executing the script, we can see that the control has also successfully attached and printed the successful hook clz class, so that we can also deal with the inner class of the Java layer.

[Google Pixel::com.roysue.roysueapplication]-> successful hook clz class successfully hook clz class 1.2 Java layer enumerates all classes and locates the class

Before we learned how to HOOK the various functions in the java layer, now we begin to learn to enumerate all the classes and locate the tricks of the class. before we learn, we need to understand the enumerateLoadedClasses method in API, which belongs to the Java object. Can enumerate all the loaded classes, enumerateLoadedClasses has two callback functions, namely onMatch:function (ClassName): for each loaded class call with className, each ClassName returns a class name; and onComplete:function (): callback once after enumerating all classes.

1.2.1 enumerate all classes and locate the class code example setTimeout (function () {Java.perform (function () {console.log ("n [*] enumerating classes...")) / / the API enumerateLoadedClasses Java.enumerateLoadedClasses of the Java object ({/ / the _ className parameter in the callback function is the name of the class, and each callback returns the name of a class: onMatch: function (_ className) {/ / output console.log ("[*] found instance of'" + _ className+ "'") here) / / if you only need to print out all the classes under the com.roysue package to make this comment, you can locate to ~ / / if (_ className.toString (). IndexOf ("com.roysue")! =-1) / / {/ / console.log ("[*] found instance of'" + _ className+ ") if you want to print something else to replace the parameters in indexOf. / /}}, onComplete: function () {/ / this function console.log ("[*] class enuemration complete");});}) will be called back once after the enumeration class ends.

When we execute the script, the onMatch function will be called after the target process is injected, and the name of the class will be printed for each call. When the callback of the onMatch function is completed, the onComplete function will be called once, and finally the class enuemration complete will be printed, as shown in the figure below.

Figure 4-19 enumerates all classes

1.3 Java layer enumerates all the methods of the class and locates the methods

Now that the classes and instances are enumerated, let's enumerate all the methods and print the internal method names of the specified class or all the classes. the main core function is through the getDeclaredMethods () in the reflection method of the class, which belongs to the API that comes with JAVAJDK and belongs to the function defined in the java.lang.Class package. This method gets all methods declared by the class or interface, including public, protected, default (package) access, and private methods, but does not include inherited methods. Of course, it also includes the methods of the interfaces it implements. In Java it is defined like this: public Method [] getDeclaredMethods (); its return value is an array of Method, and Method is actually a string of method names and, of course, an array of objects, and then we print it out.

1.3.1 enumerate all methods of the class and locate the method code example function enumMethods (targetClass) {var hook = Java.use (targetClass); var ownMethods = hook.class.getDeclaredMethods (); hook.$dispose; return ownMethods } function hook_overload_5 () {if (Java.available) {Java.perform (function () {var a = enumMethods ("com.roysue.roysueapplication.User$clz") a.forEach (function (s) {console.log (s);}

We first define an enumMethods method, whose parameter targetClass is the path name of the class, which is used for Java.use to obtain the class object itself, and then obtain all the method name arrays of the target class through its .class.getDeclaredMethods () method. When the getDeclaredMethods () method is called, the $dispose method is called to release the target class object, returning all the method names, return types and function permissions of the target class. This is the core method to get the method name. The following method is mainly used to inject the logic code into the target process to execute the logic code. In the hook_overload_5 method, the Java.perform method is first used, and then the enumMethods method is called internally to get all the method names, return types and function permissions of the target class. What is returned is a Method array, and each value in the array is looped out through the forEach iterator. Because it is actually a string, you can get the method name by outputting it directly. The script execution effect is shown in figure 4-20.

Figure 4-20 the effect after script execution in figure 4-17 shows that clz has only one toString method. We can locate all the methods in this class by filling in the parameter com.roysue.roysueapplication.User$clz.

1.4 all methods of Java layer interception methods are overloaded

After we have learned to enumerate all the classes and methods of the class, then we also want to know how to get all the method overloading functions. After all, method overloading is not rare in the Android decompiled source code, so it is very necessary to learn all the method overloading of hook at one time. We already know that we need to write overload ('x') when hook overloads the method, which means we need to construct an overloaded array and print out each overload.

1.4.1 all method overloading code examples for intercepting methods function hook_overload_8 () {if (Java.available) {Java.perform (function () {console.log ("start hook"); var targetMethod = 'add'; var targetClass =' com.roysue.roysueapplication.Ordinary_Class'; var targetClassMethod = targetClass +'.'+ targetMethod / / Target class var hook = Java.use (targetClass); / / number of overloads var overloadCount = hook [targetMethod] .overloads.length; / / print log: how many overloaded console.log are there in the tracked method ("Tracing" + targetClassMethod + "[" + overloadCount + "overload (s)]") / / each overload enters a for (var I = 0; I)

< overloadCount; i++) { //hook每一个重载 hook[targetMethod].overloads[i].implementation = function() { console.warn("n*** entered " + targetClassMethod); //可以打印每个重载的调用栈,对调试有巨大的帮助,当然,信息也很多,尽量不要打印,除非分析陷入僵局 Java.perform(function() { var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()); console.log("nBacktrace:n" + bt); }); // 打印参数 if (arguments.length) console.log(); for (var j = 0; j < arguments.length; j++) { console.log("arg[" + j + "]: " + arguments[j]); } //打印返回值 var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?) console.log("nretval: " + retval); console.warn("n*** exiting " + targetClassMethod); return retval; } } console.log("hook end"); }); }}1.4.2 拦截方法的所有方法重载代码示例详解 上面这段代码可以打印出com.roysue.roysueapplication.Ordinary_Class类中add方法重载的个数以及hook该类中所有的方法重载函数,现在来剖析上面的代码为什么可以对一个类中的所有的方法重载HOOK挂上钩子。首先我们定义了三个变量分别是targetMethod、targetClass、targetClassMethod,这三个变量主要于定义方法的名称、类名、以及类名+方法名的赋值,首先使用了Java.use获取了目标类对象,再获取重载的次数。这里详细说一下如何获取的:var method_overload = cls[].overloads[index];这句代码可以看出通过cls索引func_name到类中的方法,而后面写到overloads[index]是指方法重载的第index个函数,大致意思就是返回了一个method对象的第index位置的函数。而在代码中写道:var overloadCount = hook[targetMethod].overloads.length;,采取的方法是先获取类中某个函数所有的方法重载个数。继续往下走,开始循环方法重载的函数,刚刚开始循环时hook[targetMethod].overloads[i].implementation这句对每一个重载的函数进行HOOK。这里也说一下Arguments:Arguments是js中的一个对象,js内的每个函数都会内置一个Arguments对象实例arguments,它引用着方法实参,调用其实例对象可以通过arguments[]下标的来引用实际元素,arguments.length为函数实参个数,arguments.callee引用函数自身。这就是为什么在该段代码中并看不到arguments的定义却能够直接调用的原因,因为它是内置的一个对象。好了,讲完了arguments咱们接着说,打印参数通过arguments.length来循环以及arguments[j]来获取实际参数的元素。那现在来看apply,apply在js中是怎么样的存在,apply的含义是:应用某一对象的一个方法,用另一个对象替换当前对象,this[targetMethod].apply(this, arguments);这句代码简言之就是执行了当前的overload方法。执行完当前的overload方法并且打印以及返回给真实调用的函数,这样不会使程序错误。那么最终执行效果见下图4-21: 图4-21 终端显示 可以看到成功打印了add函数的方法重载的数量以及hook打印出来的参数值、返回值! 1.5 Java层拦截类的所有方法 学会了如何HOOK所有方法重载函数后,我们可以把之前学习的整合到一起,来hook指定类中的所有方法,也包括方法重载的函数。下面js中核心代码是利用重载函数的特点来HOOK全部的方法,普通的方法也是一个特殊方法重载,只是它只是一个方法而已,直接把它当作方法重载来HOOK就好了,打个比方正方形是特殊的长方形,而长方形是不是特殊的正方形。这个正方形是普通函数,而长方形是重载方法这样大家应该很好理解了~在上一章节中已经知道了如何hook方法重载,只是方法名称和类名是写死的,只需要把成员的targetClass、targetMethod定义方法中的参数即可,在该例子中拿到指定类所有的所有方法名称,更加灵活使用了,代码如下。 1.5.1 拦截类的所有方法代码示例function traceClass(targetClass){ //Java.use是新建一个对象哈,大家还记得么? var hook = Java.use(targetClass); //利用反射的方式,拿到当前类的所有方法 var methods = hook.class.getDeclaredMethods(); //建完对象之后记得将对象释放掉哈 hook.$dispose; //将方法名保存到数组中 var parsedMethods = []; methods.forEach(function(method) { //通过getName()方法获取函数名称 parsedMethods.push(method.getName()); }); //去掉一些重复的值 var targets = uniqBy(parsedMethods, JSON.stringify); //对数组中所有的方法进行hook targets.forEach(function(targetMethod) { traceMethod(targetClass + "." + targetMethod); });}function hook_overload_9() { if(Java.available) { Java.perform(function () { console.log("start hook"); traceClass("com.roysue.roysueapplication.Ordinary_Class"); console.log("hook end"); }); }}s1etImmediate(hook_overload_9); 执行脚本效果可以看到,hook到了com.roysue.roysueapplication.Ordinary_Class类中所有的函数,在执行其被hook拦截的方法时候,也打印出了每个方法相应的的参数以及返回值,见下图4-22。 图4-22 终端运行显示效果 1.6 Java层拦截类的所有子类 这里的核心功能也用到了上一小章节中定义的traceClass函数,该函数只需要传入一个class路径即可对class中的函数完成注入hook。那么在本小章节来hook掉所有类的子类,使我们的脚本更加的灵活方便。通过之前的学习我们已经知道enumerateLoadedClasses这个api可以枚举所有的类,用它来获取所有的类然后再调用traceClass函数就可以对所有类的子进行全面的hook。但是一般不会hook所有的函数,因为AndroidAPI函数实在太多了,在这里我们需要匹配自己需要hook的类即可,代码如下。 //枚举所有已经加载的类Java.enumerateLoadedClasses({ onMatch: function(aClass) { //迭代和判断 if (aClass.match(pattern)) { //做一些更多的判断,适配更多的pattern var className = aClass.match(/[L]?(.*);?/)[1].replace(///g, "."); //进入到traceClass里去 traceClass(className); } }, onComplete: function() {}});1.7 RPC远程调用Java层函数 在FRIDA中,不但提供很完善的HOOK机制,并且还提供rpc接口。可以导出某一个指定的函数,实现在python层对其随意的调用,而且是随时随地想调用就调用,极其方便,因为是在供给外部的python,这使得rpc提供的接口可以与python完成一些很奇妙的操作,这些导出的函数可以是任意的java内部的类的方法,调用我们自己想要的对象和特定的方法。那我们开始动手吧,现在我们来通过RPC的导出功能将图4-9中的add方法供给外部调用,开始编写rpc_demo.py文件,这次是python文件了哦~不是js文件了 1.7.1 rpc导出Java层函数代码示例import codecsimport fridafrom time import sleep# 附加进程名称为:com.roysue.roysueapplicationsession = frida.get_remote_device().attach('com.roysue.roysueapplication')# 这是需要执行的js脚本,rpc需要在js中定义source = """ //定义RPC rpc.exports = { //这里定义了一个给外部调用的方法:sms sms: function () { var result = ""; //嵌入HOOK代码 Java.perform(function () { //拿到class类 var Ordinary_Class = Java.use("com.roysue.roysueapplication.Ordinary_Class"); //最终rpc的sms方法会返回add(1,3)的结果! result = Ordinary_Class.add(1,3); }); return result; }, };"""# 创建js脚本script = session.create_script(source)script.load()# 这里可以直接调用java中的函数rpc = script.exports# 在这里也就是python下直接通过rpc调用sms()方法print(rpc.sms())sleep(1)session.detach() 当我们执行python rpc_demo.py时先会创建脚本并且注入到目标进程,在上面的source实际上就是js逻辑代码了。在js代码内我们定义了rpc可以给python调用的sms函数,而sms函数内部嵌套调用Java.perform再对需要拿到的函数的类进行主动调用,把最终的结果返回作为sms的返回值,当我们在python层时候可以任意调用sms中的原型add方法~ 1.8 综合案例一:在安卓8.1上dump蓝牙接口和实例 一个比较好的综合案例 :dump蓝牙信息的"加强版"--BlueCrawl。 VERSION="1.0.0"setTimeout(function(){ Java.perform(function(){ Java.enumerateLoadedClasses({ onMatch: function(instance){ if (instance.split(".")[1] == "bluetooth"){ console.log("[->

] t "+ lightBlueCursor () + instance+closeCursor ();}}, onComplete: function () {}}); Java.choose (" android.bluetooth.BluetoothGattServer ", {onMatch: function (instance) {... OnComplete: function () {console.log ("[*] -");}}); Java.choose ("android.bluetooth.BluetoothGattService", {onMatch: function (instance) {... OnComplete: function () {console.log ("[*] -");}}); Java.choose ("android.bluetooth.BluetoothSocket", {onMatch: function (instance) {... OnComplete: function () {console.log ("[*] -");}}); Java.choose ("android.bluetooth.BluetoothServerSocket", {onMatch: function (instance) {... OnComplete: function () {console.log ("[*] -");}}); Java.choose ("android.bluetooth.BluetoothDevice", {onMatch: function (instance) {... OnComplete: function () {console.log ("[*] -");}});});}, 0)

The script first enumerates many Bluetooth-related classes, and then choose many classes, including Bluetooth interface information and Bluetooth service interface objects, and loads the Bluetooth device objects that have been allocated in memory, that is, the information we have demonstrated above. We can use this script to "see" which Bluetooth interfaces are loaded by App, whether App is looking for Bluetooth devices, or whether to steal Bluetooth device information, and so on. Run the command on the computer: $frida-U-l bluecrawl-1.0.0.js com.android.bluetooth will print all Bluetooth interface information and service interface objects in detail when executing the script.

1.9 Comprehensive case 2: dynamic and static combination of reverse WhatsApp

Let's try several of its main functions, first of all, the export function of the local library.

SetTimeout (function () {Java.perform (function () {trace)); / / trace ("exportsmistress write *"); / / trace ("exportsmistress malloco *"); / / trace ("exportsmovemaking free *");}, 0)

We hook is the open () function, run to see the effect:

$frida-U-f com.whatsapp-l raptor_frida_android_trace_fixed.js-- no-pause

As shown in the figure *! open* regularly matches to openlog, open64 and other export functions, and hook all these functions, printing out their parameters and return values. Which part you want to see next, just throw it into jadx, statically "analyze" it, flip through it yourself, or search it according to the string. For example, if we want to see the contents of the com.whatsapp.app.protocol package in the figure above, we can set trace ("com.whatsapp.app.protocol"). You can see that the functions, methods, including overloads, parameters, and return values in the package are all printed out. That's the charm of frida scripts. Of course, scripts are just tools after all, and it's your understanding of Java, Android App, and your creativity that matters. Next, you can work with Xposed module to see what modules others have done for whatsapp, which functions of hook, what functions have been achieved, and learn to write for yourself.

Thank you for your reading, the above is the content of "Frida Java Hook sample Analysis", after the study of this article, I believe you have a deeper understanding of the problem of Frida Java Hook example analysis, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report