-
-
[讨论]Android Reverse Project No.9, "Types of App Security Protection, Identification and Handling Methods"
-
发表于: 2024-1-4 07:17 3528
-
[讨论]Android Reverse Project No.9, "Types of App Security Protection, Identification and Handling Methods"
入门学习逆向的个人笔记,预览(欢迎探讨)
[原创] 肉丝的r0env2022(kali linux)配置xrdp远程桌面,以及Genymotion安卓11的ssh登陆问题和11系统amr64转译问题.
[分享] (Android) 逆向入门记录 一篇杂文, 记录.
[分享] Adndroid逆向的基础环境准备 的一些记录 , 抄袭royuse的课 第3课
[分享] 安卓逆向课题之4, Activity,service,content provider,broadcast receiver和实例演示,完毕
[分享] 安卓逆向课题之5, mobile spider get started. 两天高度集中学习, 承上启下的流程,a明白,b上手练.(5th完结)
[分享] 安卓逆向课题之6, mobile spider get started. Object的自动化动态分析和快速定位(笔记完毕)
[分享] 安卓逆向课题之7, mobile spider get started. 看电视直播App(未加固)去广告升级 (笔记待完善)
[分享] 安卓逆向课题之8, 真实App实操带壳App重打包去强制升级(部分抄袭别人笔记)(一次不完美的实践)
[讨论] Android Reverse Project No.9, "Types of App Security Protection, Identification and Handling Methods"
[原创] Android Reverse Project No.9, "Types of App Protection“ ---- Video Course
Thanks
Thank you to all the people for the shared spirit, thank you to r0yuse, thank you to the wechat group of royuse fans, thanks for KanXUE.
What is native, the closer to the CPU definition.
dex file, in fact, is explained in java. Native program, natively interpreted by Android.
1 2 3 4 5 6 7 | ps - e | grep - i frida adb push / root / Downloads / 20200815 / frida - server - 15.2 . 2 - android - arm64 / data / local / tmp / chmod + x frida - server - 15.2 . 2 - android - arm64 . / frida - server - 15.2 . 2 - android - arm64 & objection - g com.android.chrome memory list modules dex file with libart.so interpretation and execution |
libart.so written by CPP , and run at CPU.
1 | libart.so 0xf3189000 4562944 ( 4.4 MiB) / system / lib / libart.so |
This is android system architecture.
Too easy
When Android first started, around 2010, not to mention the security of APPs, even the security of the Android system itself was not taken seriously.
After all, the protagonists of the world are still PC and WEB.
However, the world is relatively fair. Although there are no security measures, there is no need for cracking. It would be good if a new platform could perform the functions that a mobile operating system should have. As for other third-party applications, there were very few paid applications. The mobile network environment at that time was completely different from today.
In the beginning
The people who are most concerned about Android security should be hackers and blackmailers.
After all, the meal still needs to be ate, and the virus still needs to be written. .
In 2009, smali/baksmali turned out. This should be the first public DEX assembler/disassembler. Most people’s Android cracking road, Android reverse road, Android virus analysis road, and Android ** road , also starts from here.
So in 2010, Kaspersky intercepted the first Android virus...
In the same year, various technical papers on Android virus analysis and Android security began to appear, such as smali-based static analysis, sandbox-based dynamic analysis, etc.
In the same year, excellent Android reverse analysis tools such as dex2jar and apktool began to be developed and open sourced. In the following years, the black industry based on these two tools became increasingly prosperous...
Taishi
2010 can be said to be the beginning of the rapid development of Android security.
If you want to crack a software without protection, you only need to use apktool, dex2jar and other tools to clearly and completely see the original code logic of a product. Coupled with perseverance and a certain amount of reverse thinking, you can It can be done.
Although there was no one-click APP reinforcement service like today, code protection technology was not new, and the routines could be copied and used.
One of the most commonly used protection methods is: code obfuscation
For example, Google comes with the obfuscator ProGuard. The only function of ProGuard is to modify class names, method names, and field names. There are two main benefits. One is symbol obfuscation. Changing the original XXXActivity to a makes it difficult for you to guess the purpose of this class. Another benefit is the compressed file size. After all, there are tens of thousands of types, and the byte ratio of symbol strings in the dex file is not small.
1 2 3 | If you want to analyze a hardening /protection application, you should first implement this hardening /protection , which requires looking at the problem from a development perspective. |
Another representative one is DexGuard, another product from the same developer as ProGuard. The difference is that it has richer functions and is a commercial software sold for money, while ProGuard is a free software for all developers to use for free. Dexguard's obfuscation function is more powerful and supports functions such as string encryption, flower instructions, and resource encryption. With development now, DexGuard has richer functions and even some runtime protections. It is no longer a simple obfuscator.
Commonly used protection methods include: dynamic loading
Compile the code that needs to be protected separately, encrypt it and decrypt it while the program is running, and use ClassLoader to load it dynamically. This is a common way to protect code on PC, and it was also the basis for the first generation of shells.
Please Check the artcile blow.
https://github.com/xiaokanghub/Android
Dynamic Loading Method 1: Android Reinforcement Application Hook Method-Frida
I apologize for the obfuscation. Here's the explanation of the provided code using a copyable Markdown source format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // Use Java.perform to execute the following code in the context of the running Android application. Java.perform( function () { // Obtain a reference to the 'android.app.Application' class using Java.use. var application = Java.use( 'android.app.Application' ); // Hook the 'attach' method of the 'android.app.Application' class with a specific parameter type. application.attach.overload( 'android.content.Context' ).implementation = function (context){ // Call the original 'attach' method with the provided context and store its result. var result = this .attach(context); // Obtain the class loader from the provided context. var classloader = context.getClassLoader(); // Set the obtained class loader as the loader for the Java class factory in Frida. Java.classFactory.loader = classloader; // Use the Java class factory to load the 'com.zcm.MainWindow' class. var yeyoulogin = Java.classFactory.use( 'com.zcm.MainWindow' ); // Output information about the loaded class to the console. console.log( "yeyoulogin:" + yeyoulogin); // Hook the 'Button_UserLogin$ByClick' method of the 'com.zcm.MainWindow' class. yeyoulogin.Button_UserLogin$ByClick.implementation = function (arg) { // Output the value of the 'ReturnValueAAAA' property of 'this' object to the console. console.log( "retval:" + this .ReturnValueAAAA); } } }); |
Explanation:
The code uses
Java.perform
to execute the provided code in the context of the running Android application.It obtains a reference to the
android.app.Application
class.It hooks the
attach
method of theandroid.app.Application
class, specifically targeting the overload that takes a parameter of typeandroid.content.Context
.The original
attach
method is called with the provided context, and its result is stored.The class loader from the provided context is obtained.
The obtained class loader is set as the loader for the Java class factory in Frida.
The
com.zcm.MainWindow
class is loaded using the Java class factory.Information about the loaded class is output to the console.
The
Button_UserLogin$ByClick
method of thecom.zcm.MainWindow
class is hooked, allowing the interception and modification of its behavior when called.The value of the
ReturnValueAAAA
property of thethis
object (which represents the instance of the hooked method) is output to the console.
Dynamic Loading Method 2 : List loaded classes
1 2 3 4 5 6 7 8 9 | Java.enumerateLoadedClasses({ "onMatch" : function (className) { // Callback function called for each matched class name console.log(className); }, "onComplete" : function () { // Callback function called when the enumeration is complete } }); |
Explanation:
Java.enumerateLoadedClasses
: This function is provided by Frida and is used to enumerate all currently loaded Java classes in the application."onMatch": function(className) { console.log(className) }
: This is a callback function that will be invoked for each matched class name during the enumeration. It simply logs each class name to the console."onComplete": function() { }
: This is another callback function that will be invoked when the enumeration is complete. In this case, it is an empty function, meaning it does not perform any specific action.
Overall, this code is designed to log the names of all loaded Java classes in the application, providing insights into the class structure and loaded components during runtime.
Certainly! Here's the explanation of the provided code using Markdown source format:
Dynamic Loading Method 3 : Hook dynamically loaded classes ----》 Get the parameters of the constructor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Use Java.perform to execute the following code in the context of the running Android application. Java.perform( function (){ // Create a wrapper for the DexClassLoader. var dexclassLoader = Java.use( "dalvik.system.DexClassLoader" ); // Hook its constructor $init and print its four parameters. dexclassLoader.$init.implementation = function (dexPath, optimizedDirectory, librarySearchPath, parent){ console.log( "dexPath:" + dexPath); console.log( "optimizedDirectory:" + optimizedDirectory); console.log( "librarySearchPath:" + librarySearchPath); console.log( "parent:" + parent); // Do not disrupt its original logic; call its original constructor. this .$init(dexPath, optimizedDirectory, librarySearchPath, parent); } // Log a message indicating that the hooking is completed. console.log( "down!" ); }); |
Explanation:
The code uses
Java.perform
to execute the provided code in the context of the running Android application.It creates a wrapper for the
DexClassLoader
class.It hooks the constructor
$init
of theDexClassLoader
class and prints its four parameters:dexPath
,optimizedDirectory
,librarySearchPath
, andparent
.The original logic of the constructor is not disrupted; it calls the original constructor.
It logs a message indicating that the hooking process is completed.
if you wanted the known where is the function from, You can search the keywords "dalvik.system.DexClassLoader" , you may get the new page to understood , how it is implemented?
Positive development ideas Android dynamically loading dex,
Please refer to the following web links.
https://blog.csdn.net/lx768863620/article/details/79414010
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); start(); } public void start(){ File dexOutputDir = getDir( "dex" , 0 ); //Dex 文件存放位置 String dexPath = "/storage/emulated/0/output.jar" ; // Environment.getExternalStorageDirectory().toString() + File.separator + "output.jar"; DexClassLoader loader = new DexClassLoader(dexPath, dexOutputDir.getAbsolutePath(), null , ClassLoader.getSystemClassLoader().getParent()); try { Class clz = loader.loadClass( "com.youbo.switchsky.LogUtils" ); Object instance= clz.newInstance(); Method method = clz.getMethod( "show" , Context. class ); method.invoke(instance, this ); } catch (Exception e) { Log.d( "TEST111" , "error happened" , e); } } } |
so the most important problem is to realize and write on by yourself.
The most hard-core protection: Native development
Use NDK to write applications and directly generate native code
They are using NDK developmented. by C++ or C .
Because he writes the key logic in the so file, which makes it difficult for you to analyze.
Java-level protectino is almost abandoned now.
Well, this is the basis of today's java2cpp technology. . .
The most modern protection: core data and functions are cloud-based.
Put all important functions and data into cloud computing, and the client can be used only for display. Well, this is barely the basis of current risk control. . .
Therefore, most of the current code protection methods on the mobile terminal are constantly upgraded and adapted based on the predecessors.
Taisu
If protection is standing on the shoulders of giants, then cracking is standing on the shoulders of God.
Since static analysis is not possible, the attacker can also perform dynamic analysis from a God's perspective.
Regarding dynamic analysis, I wrote a special article "Summary of Android Dynamic Analysis Attack and Defense" and talked about some routines. You can check the historical information on the official account.
In the face of dynamic analysis, dynamic loading, which was originally the most direct, effective and low-cost method, has become the most fragile protection method.
Usually you only need to attach a process to do a memory roaming search for dex.035 or even look directly at the Segment name to find the dynamically loaded dex file in the memory and dump it. As of 2020, this method is still effective for most hardened generation protections. .
Of course, there's a lot of manual work, such as dvmDexFileOpenPartial and other function break points about loading code, and you can easily find the decrypted dex file by doing Hook.
This is the unpacking method of Android hardened No. 1 machine.
Because simple dynamic loading alone cannot stop people at all, there are probably several other development routes for application protection at this time:
Fight against debuggers
This part has been discussed a lot in the article "Android Dynamic Analysis Offense and Defense Summary" published by the public account (Hu Ke Laoshiji), you can refer to it.
Of course, there are not many methods at the beginning, but they are obtained through continuous exploration, competitive product analysis, and community sharing by all parties.
Fight against decompilers
By looking for vulnerabilities and BUGs in various decompilers and disassemblers, the payload is inserted into the DEX or resource files that need to be protected, causing the tool to crash and prevent it from running normally.
However, this road is obviously a dead end. With the continuous maintenance of various tools, compatibility becomes stronger and stronger. It is not easy to find such bugs that can be bypassed directly. Even if there are any, they will be quickly fixed.
Typical examples are Black Hat USA 2012 - Dex Education: Practicing Safe Dex, and 360 hardening which also had some such protection before.
Against people: disgusting flow
The code protects millions of roads, but only disgusting people are the king.
So the responsibility of this road is to carry forward the essence of obfuscation: "disgusting".
for example:
1. Symbol obfuscation upgraded version:
Previously, the class name, method name, and field name were replaced by abcd. Later, I started to use a obfuscation dictionary, which includes various small language symbols and invisible symbols. Just use the symbols in these dictionaries to generate new class names, method names, and field names. The final effect is that it looks garbled or blank.
Of course, there are many countermeasures. For example, the anti-obfuscation function of the open source decompiler Jadx supports automatic renaming of symbols into meaningless names like abcd;
Another example is another anti-obfuscation function, which reads the sourcefile attribute from the DEX file to restore the real class name. However, this is just debugging information, so many obfuscators will directly remove this field.
More advanced, such as blank obfuscation.
The effect shown by the code
So the most effective tool to combat this kind of obfuscation is: people
2. String encryption enhanced version:
Many of the initial string encryptions were relatively monotonous. Generally, there was a decryption method that accepted an encrypted string or byte[] and then returned a string. This is of course easy to target. As long as you first use dex2jar and then dynamically load the Jar package and call the decryption method through reflection, you can get the plaintext string.
So many mutation methods appeared later, probably the following:
1. Guerrilla play method, group strings and use multiple algorithms to encrypt them. Instead of relying on only one method to decrypt, each decryption method corresponds to a different algorithm, so you can't catch them all at once.
2. The Self-Defense Force’s approach is to check the running environment when initializing the decryption algorithm, or rely on the context environment to increase the difficulty of calling.
3. Use native decryption and SO protection.*
3. Native protection
For Native's disgusting flow protection, the most popular and most effective one is OLLVM. OLLVM is something that only appeared since 2013, and may have a lot of content. I will talk about this later.
As for other Native protection, there are basically only two methods at the beginning:
1. Destroy the ELF file structure and even customize the linker to load customized SO.
2. Encrypt the code segment and decrypt it at runtime, which is similar to Dex dynamic loading. Or directly apply a traditional ELF shell such as UPX.
While dynamic DUMPing of memory can result in real code, not being able to repair the complete file structure leaves a lot missing that can aid in analysis.
4. Other obfuscations:
I have seen before that there is no normal file in the APK package except the necessary manifest. The assert, lib, dex, and res are all protected (including some of the methods mentioned above), let alone compatibility. Or how about the performance, anyway, it’s really disgusting...
Tai Chi
2010 was the year of creation of Android application security. By about 2013, various code protection technologies for Android applications had basically taken shape, and most of the above technologies had been stably implemented.
It can be said that the period from 2009 to 2012 was a period when Android application security went from Wuji to Tai Chi and ushered in a new era.
During this time, Android has captured most of the mobile phone market.
In 2013, the global market share of Android mobile phones was as high as 80%, and a large number of users and developers poured in.
Google’s Android empire is unstoppable.
At the same time, the spring of the Android application security market is also coming.
To predict what will happen in the future, please press and hold the QR code below to follow Hu Ke Lao Shi Ji and listen to the next chapter's breakdown...
Here function was not encrypted. read directly.
Here, you can look directly at his logic without any obfuscation.
earch for the main dex file of 学而思
1 2 3 4 5 | / root / Downloads / anzhuo - yingyong - rumen2 / 20200822 / com.xes.jazhanghui.activity / cd / root / Downloads / anzhuo - yingyong - rumen2 / 20200822 / com.xes.jazhanghui.activity / grep - ril "okhttp3" |
// check the dumped file size
1 | du - sh `ls` |
There are too many files, and it is confusing to look directly.
The goal is to use frida -- interceptors of this goal
The specific location of the error, the core requirements, and the okhttp3hook .js of the restore system (the course and the steps to detail how to build a js file)
why the script report error.
There are two ways for Frida to load scripts
objection -g com.xes.jazhanghui.activity explore -P /root/.objection/plugin
a, solve the problem of envirment configuration .
// Here is Spanwan Mode ---->
1 | frida - U - l / root / Downloads / anzhuo - yingyong - rumen2 / AndroidFridaBeginnersBook / hookOkhttp3.js - f com.singleman.freevideo - - no - pause |
// Here is Attach Mode ---->
1 | frida - U - l / root / Downloads / anzhuo - yingyong - rumen2 / AndroidFridaBeginnersBook / hookOkhttp3.js com.singleman.freevideo - - no - pause |
// system envirmoment configuration only for Jul 28, 2020
1 2 3 4 5 | pyenv local 3.8 . 3 frida version 12.11 . 6 frida - tools version 8.1 . 0 objection version 1.9 . 5 Jul 28 , 2020 / / date |
// installing step
// The installation order here should not be messed up, and the frida must be in front of the frida-tools first
1 2 3 4 | proxychains pyenv install 3.8 . 3 pip install frida = = 12.11 . 6 pip install frida - tools = = 8.1 . 0 pip install objection = = 1.9 . 5 |
// debug the App called com.xes.jazhanghui.activity
1 | objection - g com.xes.jazhanghui.activity explore |
dumped path is
1 | / root / com.xes.jazhanghui.activity / |
Author dumped path of Course is
1 | / root / desktop20200820 / com.xes.jazhanghui.activity |
I didn't have a problem with my operation,But I have these files included in my script.
1 2 | / data / local / tmp / myok2curl.dex / data / local / tmp / okhttplogging.dex |
The following 3 package names should exist in the system and have been installed.
1 2 3 | com.moczul.ok2curl.CurlInterceptor com.moczul.ok2curl.logger.Loggable com.r0ysue.learnokhttp.okhttp3Logging |
Problems mentioned in the script
As you can see from the lesson, my phone doesn't have these two files, so the error is reported.
The solution is to comment out all the useless code blocks and manually load them into Frida
As you can see from the screenshot above, there is no obfuscation.
We can go directly to the target class name okhttp3 by way of script.
Follow the final Video Requirements toggle
1 2 | pyenv lcoal 3.8 . 3 frida version 12.11 . 6 |
Modified js script (maybe it was correct )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | function searchClient(){ Java.perform( function (){ // //Java.openClassFile("/data/local/tmp/r0gson.dex").load(); // //const gson = Java.use('com.r0ysue.gson.Gson'); // var gson2 = Java.use('com.google.gson.Gson'); // // 加载包含CurlInterceptor拦截器的DEX // Java.openClassFile("/data/local/tmp/myok2curl.dex").load(); // console.log("loading dex successful!") // const curlInterceptor = Java.use("com.moczul.ok2curl.CurlInterceptor"); // const loggable = Java.use("com.moczul.ok2curl.logger.Loggable"); // var Log = Java.use("android.util.Log"); // var TAG = "okhttpGETcurl"; // //注册类————一个实现了所需接口的类 // var MyLogClass = Java.registerClass({ // name: "okhttp3.MyLogClass", // implements: [loggable], // methods: { // log: function (MyMessage) { // Log.v(TAG, MyMessage); // }} // }); // const mylog = MyLogClass.$new(); // // 得到所需拦截器对象 // var curlInter = curlInterceptor.$new(mylog); // // 加载包含logging-interceptor拦截器的DEX // Java.openClassFile("/data/local/tmp/okhttplogging.dex").load(); // var MyInterceptor = Java.use("com.r0ysue.learnokhttp.okhttp3Logging"); // var MyInterceptorObj = MyInterceptor.$new(); Java.choose( "okhttp3.OkHttpClient" ,{ onMatch: function (instance){ console.log( "1. found instance:" ,instance) console.log( "2. instance.interceptors():" ,instance.interceptors().$className) console.log( "3. instance._interceptors:" ,instance._interceptors.value.$className) //console.log("4. interceptors:",gson2.$new().toJson(instance.interceptors())) console.log( "5. interceptors:" ,Java.use( "java.util.Arrays" ).toString(instance.interceptors().toArray())) var newInter = Java.use( "java.util.ArrayList" ).$ new (); newInter.addAll(instance.interceptors()); console.log( "6. interceptors:" ,Java.use( "java.util.Arrays" ).toString(newInter.toArray())); console.log( "7. interceptors:" ,newInter.$className); newInter.add(MyInterceptorObj); newInter.add(curlInter); instance._interceptors.value = newInter; },onComplete: function (){ console.log( "Search complete!" ) } }) }) } setImmediate(searchClient) |
b, Troubleshoot issues and execute them successfully
execute following Script.
1 | frida - UF - l / root / Downloads / anzhuo - yingyong - rumen2 / 20240104 / 2024.01 . 04.testfor_xueersi_education .js.js |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ┌──(root㉿r0env)-[~] └─ # frida -UF -l /root/Downloads/anzhuo-yingyong-rumen2/20240104/2024.01.04.testfor_xueersi_education.js.js ____ / _ | Frida 12.11.6 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit /quit -> Exit . . . . . . . . More info at https: //www .frida.re /docs/home/ 1. found instance: okhttp3.OkHttpClient@6046fbb 2. instance.interceptors(): java.util.Collections$UnmodifiableRandomAccessList 3. instance._interceptors: java.util.Collections$UnmodifiableRandomAccessList 5. interceptors: [com.networkbench.agent.impl.h.b@13a6831, com.tal.xes.app.net.interceptor.LocalCacheInterceptor@8837b16, com.tal.xes.app.net.interceptor.HttpLoggingInterceptor@8804c97, com.xes.cloudlearning.bcmpt.net.CommonHeaderIntercept@9c0ce84, com.tal.xes.app.netbusiness.interceptor.ServerStatusInterceptor@41c566d, com.tal.xes.app.netbusiness.interceptor.AppHeadersInterceptor@7b432a2, com.tal.xes.app.netbusiness.interceptor.AppParamsInterceptor@a731b33, com.tal.xes.app.netbusiness.interceptor.SaveServerTimeInterceptor@1be4ef0, com.tal.xes.app.net.interceptor.ParamsInterceptor@7b4ec69, com.tal.xes.app.netbusiness.interceptor.SignInterceptor@a46d6ee, com.tal.xes.app.netbusiness.interceptor.NetResponseErrorInterceptor@fba378f, com.tal.xes.app.net.retrofit_url.RetrofitUrlManager$1@326e625] 6. interceptors: [com.networkbench.agent.impl.h.b@13a6831, com.tal.xes.app.net.interceptor.LocalCacheInterceptor@8837b16, com.tal.xes.app.net.interceptor.HttpLoggingInterceptor@8804c97, com.xes.cloudlearning.bcmpt.net.CommonHeaderIntercept@9c0ce84, com.tal.xes.app.netbusiness.interceptor.ServerStatusInterceptor@41c566d, com.tal.xes.app.netbusiness.interceptor.AppHeadersInterceptor@7b432a2, com.tal.xes.app.netbusiness.interceptor.AppParamsInterceptor@a731b33, com.tal.xes.app.netbusiness.interceptor.SaveServerTimeInterceptor@1be4ef0, com.tal.xes.app.net.interceptor.ParamsInterceptor@7b4ec69, com.tal.xes.app.netbusiness.interceptor.SignInterceptor@a46d6ee, com.tal.xes.app.netbusiness.interceptor.NetResponseErrorInterceptor@fba378f, com.tal.xes.app.net.retrofit_url.RetrofitUrlManager$1@326e625] 7. interceptors: java.util.ArrayList ReferenceError: identifier 'MyInterceptorObj' undefined at [anon] (../../.. /frida-gum/bindings/gumjs/duktape .c:83728) at /2024 .01.04.testfor_xueersi_education.js.js:44 at frida /node_modules/frida-java-bridge/lib/class-factory .js:310 at frida /node_modules/frida-java-bridge/lib/class-factory .js:264 at tt (frida /node_modules/frida-java-bridge/lib/android .js:462) [Nexus 5X::学而思培优]-> |
There are several practical examples of obfuscation
examples of no obfuscation XueErSi APP
This is an obvious certificate binding class
Only one we care about that is the operation of the OkHttp3 sub class interceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | package okhttp3 class OkHttpClient { /* static fields */ static java.util.List DEFAULT_PROTOCOLS; => [0x6912]: [h2, http/1.1] static java.util.List DEFAULT_CONNECTION_SPECS; => [0x690a]: [ConnectionSpec(cipherSuites=[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_256_CCM_8_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA], tlsVersions=[TLS_1_3, TLS_1_2, TLS_1_1, TLS_1_0], supportsTlsExtensions= true ), ConnectionSpec()] /* instance fields */ int shadow$_monitor_; => -1916673143 java.lang.Class shadow$_klass_; => [0x6862]: class okhttp3.OkHttpClient java.util.List _connectionSpecs; => [0x6856]: [ConnectionSpec(cipherSuites=[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_256_CCM_8_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA], tlsVersions=[TLS_1_3, TLS_1_2, TLS_1_1, TLS_1_0], supportsTlsExtensions= true ), ConnectionSpec()] okhttp3.CookieJar _cookieJar; => [0x681a]: okhttp3.CookieJar$1@35c2f45 okhttp3.Authenticator _proxyAuthenticator; => [0x65ba]: okhttp3.Authenticator$1@ad59d9f java.net.Proxy _proxy; => null okhttp3.CertificatePinner _certificatePinner; => [0x6586]: okhttp3.CertificatePinner@0 javax.net.SocketFactory _socketFactory; => [0x6556]: javax.net.DefaultSocketFactory@905569a javax.net.ssl.HostnameVerifier _hostnameVerifier; => [0x6536]: com.tal.xes.app.net.-$$Lambda$NetHelper$6BAsjZ5QKjp5NoLA82QXE-fjgFI@3c98f4d int pingInterval; => 0 int callTimeout; => 0 int connectTimeout; => 30000 okhttp3.Dns _dns; => [0x6516]: okhttp3.Dns$1@456cb3e javax.net.ssl.SSLSocketFactory _sslSocketFactory; => [0x64f6]: com.android.org.conscrypt.OpenSSLSocketFactoryImpl@62ddee4 okhttp3.ConnectionPool _connectionPool; => [0x64d6]: okhttp3.ConnectionPool@cc4fbcb okhttp3.Cache _cache; => [0x64b6]: okhttp3.Cache@e993fa8 okhttp3.Dispatcher _dispatcher; => [0x6496]: okhttp3.Dispatcher@c957ac1 int readTimeout; => 30000 okhttp3.internal.tls.CertificateChainCleaner certificateChainCleaner; => [0x6476]: okhttp3.internal.tls.BasicCertificateChainCleaner@0 java.net.ProxySelector _proxySelector; => [0x6456]: sun.net.spi.DefaultProxySelector@4c5e03e java.util.List _protocols; => [0x6542]: [h2, http/1.1] java.util.List _networkInterceptors; => [0x6432]: [com.tal.xes.app.net.interceptor.NetCacheInterceptor@9524266] okhttp3.EventListener$Factory _eventListenerFactory; => [0x6416]: okhttp3.EventListener$2@92589a7 boolean _retryOnConnectionFailure; => true okhttp3.internal.cache.InternalCache _internalCache; => null java.util.List _interceptors; => [0x6402]: [com.networkbench.agent.impl.h.b@316ae54, com.tal.xes.app.net.interceptor.LocalCacheInterceptor@2be01fd, com.tal.xes.app.net.interceptor.HttpLoggingInterceptor@6301ef2, com.xes.cloudlearning.bcmpt.net.CommonHeaderIntercept@d171943, com.tal.xes.app.netbusiness.interceptor.ServerStatusInterceptor@95a5bc0, com.tal.xes.app.netbusiness.interceptor.AppHeadersInterceptor@9edc0f9, com.tal.xes.app.netbusiness.interceptor.AppParamsInterceptor@49d383e, com.tal.xes.app.netbusiness.interceptor.SaveServerTimeInterceptor@c08069f, com.tal.xes.app.net.interceptor.ParamsInterceptor@f6973ec, com.tal.xes.app.netbusiness.interceptor.SignInterceptor@5c073b5, com.tal.xes.app.netbusiness.interceptor.NetResponseErrorInterceptor@9309a4a, com.tal.xes.app.net.retrofit_url.RetrofitUrlManager$1@7f06dbb] boolean _followSslRedirects; => true int writeTimeout; => 30000 okhttp3.Authenticator _authenticator; => [0x6506]: okhttp3.Authenticator$1@ad59d9f boolean _followRedirects; => true /* constructor methods */ void OkHttpClient(); void OkHttpClient(okhttp3.OkHttpClient$Builder); /* static methods */ static int identityHashCodeNative(java.lang.Object); static int identityHashCode(java.lang.Object); static javax.net.ssl.SSLSocketFactory newSslSocketFactory(javax.net.ssl.X509TrustManager); /* instance methods */ int hashCode(); void wait(); void wait(long); void wait(long, int); void notify(); void notifyAll(); boolean equals(java.lang.Object); java.lang.Object clone(); void finalize(); java.lang.Object internalClone(); java.lang.String toString(); java.lang.Class getClass(); int readTimeoutMillis(); javax.net.ssl.HostnameVerifier hostnameVerifier(); boolean retryOnConnectionFailure(); javax.net.ssl.SSLSocketFactory sslSocketFactory(); okhttp3.Dispatcher dispatcher(); boolean followRedirects(); okhttp3.OkHttpClient$Builder newBuilder(); okhttp3.Dns dns(); okhttp3.CookieJar cookieJar(); java.util.List connectionSpecs(); javax.net.SocketFactory socketFactory(); int pingIntervalMillis(); int callTimeoutMillis(); boolean followSslRedirects(); java.util.List networkInterceptors(); okhttp3.Call newCall(okhttp3.Request); java.net.Proxy proxy(); okhttp3.CertificatePinner certificatePinner(); java.net.ProxySelector proxySelector(); okhttp3.EventListener$Factory eventListenerFactory(); int writeTimeoutMillis(); int connectTimeoutMillis(); okhttp3.Authenticator proxyAuthenticator(); okhttp3.Cache cache(); java.util.List protocols(); okhttp3.ConnectionPool connectionPool(); okhttp3.WebSocket newWebSocket(okhttp3.Request, okhttp3.WebSocketListener); java.util.List interceptors(); okhttp3.Authenticator authenticator(); okhttp3.internal.cache.InternalCache internalCache(); } |
<!-- -->
<!-- -->
<!-- -->
This is offcial API handbook of Interceptors. Its structure can be roughly guessed
This is we wanted find the target of interceptor function of okhttp3.client class
examples of obfuscation Mooc
Generally, it is cracked with a confusing mode.
you can using Frida Hook to print the Area's result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Java.choose( "okhttp3.OkHttpClient" ,{ onMatch: function (instance){ console.log( "1. found instance:" ,instance) console.log( "2. instance.interceptors():" ,instance.interceptors().$className) console.log( "3. instance._interceptors:" ,instance._interceptors.value.$className) //方法的是 interceptors //console.log("4. interceptors:",gson2.$new().toJson(instance.interceptors())) console.log( "5. interceptors:" ,Java.use( "java.util.Arrays" ).toString(instance.interceptors().toArray())) var newInter = Java.use( "java.util.ArrayList" ).$ new (); newInter.addAll(instance.interceptors()); console.log( "6. interceptors:" ,Java.use( "java.util.Arrays" ).toString(newInter.toArray())); console.log( "7. interceptors:" ,newInter.$className); newInter.add(MyInterceptorObj); newInter.add(curlInter); instance._interceptors.value = newInter; },onComplete: function (){ console.log( "Search complete!" ) } }) |
we can use this idea to replace the idea of the interceptor as a whole.
we were dynamic position this class.
ok , this is correct .
How to judge ? it is based on his class name.
examples of obfuscation Free cinema APP
this App className alll was disappeard.
how to judge the class is correct or not.
watch them structure is correct.
1 2 3 4 | smali / فمضﺝ / ﻙﺫتك$ﻝبـق.smali smali / فمضﺝ / ﻙﺫتك$ﺯﺵتﻝ.smali smali / فمضﺝ / ﻙﺫتك.smali < - - - smali / okhttp3 / internal / platform / Platform.smali |
this is for the obfs later charector.
Almost exactly the same as the normal function structure.
ok, finally, i will write the javascript to the loaded manually.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | function searchClient(){ Java.perform( function (){ // //Java.openClassFile("/data/local/tmp/r0gson.dex").load(); // //const gson = Java.use('com.r0ysue.gson.Gson'); // var gson2 = Java.use('com.google.gson.Gson'); // // 加载包含CurlInterceptor拦截器的DEX // Java.openClassFile("/data/local/tmp/myok2curl.dex").load(); // console.log("loading dex successful!") // const curlInterceptor = Java.use("com.moczul.ok2curl.CurlInterceptor"); // const loggable = Java.use("com.moczul.ok2curl.logger.Loggable"); // var Log = Java.use("android.util.Log"); // var TAG = "okhttpGETcurl"image.png; // //注册类————一image.png个实现了所需接口的类 // var MyLogClass = Java.registerClass({ // name: "okhttp3.MyLogClass"image.png, // impimage.pnglements: [loggable], // methods: { // log: function (MyMessage) {image.png // Log.v(TAG, MyMessage); // }} // }); // const mylog = MyLogClass.$new(); // // 得到所需拦截器对象 // var curlInter = curlInterceptor.$new(mylog); // 加载包含logging-interceptor拦截器的DEX // Java.openClassFile("/data/local/tmp/okhttplogging.dex").load(); // var MyInterceptor = Java.use("com.singleman.freevideo.okhttp3Logging"); // var MyInterceptorObj = MyInterceptor.$new(); Java.choose( "فمضﺝ.ﻙﺫتك" ,{ onMatch: function (instance){ console.log( "1. found instance:" ,instance) //console.log("2. instance.interceptors():",instance.interceptors().$className) console.log( "3. instance._interceptors:" ,instance.ﻭﻍﺫﻉ.value.$className) //console.log("4. interceptors:",gson2.$new().toJson(instance.interceptors())) console.log( "5. interceptors:" ,Java.use( "java.util.Arrays" ).toString(instance.ﻭﻍﺫﻉ.value.toArray())) /* var newInter = Java.use("java.util.ArrayList").$new(); newInter.addAll(instance.interceptors()); console.log("6. interceptors:",Java.use("java.util.Arrays").toString(newInter.toArray())); console.log("7. interceptors:",newInter.$className); newInter.add(MyInterceptorObj); newInter.add(curlInter); instance._interceptors.value = newInter; */ },onComplete: function (){ console.log( "Search complete!" ) } }) // Java.choose("okhttp3.OkHttpClient",{ // onMatch:function(instance){ // console.log("1. found instance:",instance) // console.log("2. instance.interceptors():",instance.interceptors().$className) // console.log("3. instance._interceptors:",instance._interceptors.value.$className) // //console.log("4. interceptors:",gson2.$new().toJson(instance.interceptors())) // console.log("5. interceptors:",Java.use("java.util.Arrays").toString(instance.interceptors().toArray())) // var newInter = Java.use("java.util.ArrayList").$new(); // newInter.addAll(instance.interceptors()); // console.log("6. interceptors:",Java.use("java.util.Arrays").toString(newInter.toArray())); // console.log("7. interceptors:",newInter.$className); // newInter.add(MyInterceptorObj); // newInter.add(curlInter); // instance._interceptors.value = newInter; // },onComplete:function(){ // console.log("Search complete!") // } // }) }) } // setImmediate(searchClient) // I think using SetImmediate function can using at the SPan mode, will start at the app started before.! simply . Firda First. and App second. // if there im comment , load Java script to Memory. and useing function name to call When using Frida in interactive mode // Here is Spanwan Mode ----> frida -U -l /root/Downloads/anzhuo-yingyong-rumen2/AndroidFridaBeginnersBook/hookOkhttp3.js -f com.singleman.freevideo --no-pause // |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ┌──(root㉿r0env)-[~] └─ # frida -U -l /root/Downloads/anzhuo-yingyong-rumen2/AndroidFridaBeginnersBook/hookOkhttp3.js com.singleman.freevideo --no-pause ____ / _ | Frida 12.11.6 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit /quit -> Exit . . . . . . . . More info at https: //www .frida.re /docs/home/ [Nexus 5X::com.singleman.freevideo]-> searchClient function [Nexus 5X::com.singleman.freevideo]-> searchClient() 1. found instance: فمضﺝ.ﻙﺫتك@1b76d08 2. instance._interceptors: java.util.Collections$UnmodifiableRandomAccessList 3. interceptors: [ﻝبـق.ﻍبﺯﺫ.ﻝبـق.ﻝبـق.بﺙذن.بﺙذن.ﻝبـق@a820ca1] 4. found instance: فمضﺝ.ﻙﺫتك@ebe9ec6 5. instance._interceptors: java.util.Collections$UnmodifiableRandomAccessList 6. interceptors: [ﻝبـق.ﻍبﺯﺫ.ﻝبـق.ﻝبـق.بﺙذن.بﺙذن.ﻝبـق@eae1e87] 7. found instance: فمضﺝ.ﻙﺫتك@da51b4 8. instance._interceptors: java.util.Collections$UnmodifiableRandomAccessList 9. interceptors: [ﻝبـق.ﻍبﺯﺫ.ﻝبـق.ﻝبـق.بﺙذن.بﺙذن.ﻝبـق@711d1dd] 10. found instance: فمضﺝ.ﻙﺫتك@e75e152 11. instance._interceptors: java.util.Collections$UnmodifiableRandomAccessList 12. interceptors: [ﻝبـق.ﻍبﺯﺫ.ﻝبـق.ﻝبـق.بﺙذن.بﺙذن.ﻝبـق@a441c23] Search complete! [Nexus 5X::com.singleman.freevideo]-> |
All reference links
nexus 5x brush machine pointing North
https://www.jianshu.com/p/f0dc69b75476
Flash magisk for nexus with ADB Sideload !
https://bbs.kanxue.com/thread-279435-1.htm#1759925
frida js script using methods
https://papayawd.github.io/2020/10/18/frida-js%E8%84%9A%E6%9C%AC%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/
https://cmsblogs.cn/3706.html
Android Frida Reverse & Packet Grabbing Combat PDF Download
Android: Create a Screenshot with ADB
https://supportcommunity.zebra.com/s/article/000021675?language=en_US
OkHttpClient (OkHttp 3.7.0 API).
https://javadoc.io/static/com.squareup.okhttp3/okhttp/3.7.0/okhttp3/OkHttpClient.html#connectionSpecs--
Location analysis based on memory roaming
https://onejane.github.io/2021/02/12/%E5%9F%BA%E4%BA%8E%E5%86%85%E5%AD%98%E6%BC%AB%E6%B8%B8%E5%AE%9A%E4%BD%8D%E5%88%86%E6%9E%90/#%E6%A1%88%E4%BE%8B%E4%B8%80
Socket&Websocket&ProtobufSelf-spitting and killing Everything can be reversed
https://onejane.github.io/2021/03/14/Socket&Websocket&Protobuf%E8%87%AA%E5%90%90%E9%80%9A%E6%9D%80/#%E5%85%B3%E9%94%AE%E7%B1%BB%E5%AE%9A%E4%BD%8D
siyujie_OkHttpLogger-Frida Frida implements a script that intercepts okhttp
https://github.com/siyujie/OkHttpLogger-Frida
r0gson.dex
https://github.com/r0ysue/AndroidSecurityStudy/blob/master/FRIDA/r0gson.dex.zip
xiaokanghub_Android Android 加固应用Hook方式-Frida
https://github.com/xiaokanghub/Android
Basic Syntax Markdown Guide
https://www.markdownguide.org/basic-syntax/
Android App Protection (1)
https://mp.weixin.qq.com/s/tI89U6eht0F_KrMJXooo1A
siyujie_okhttp_find Search for okhttp3 based on features and use java reflection.
https://github.com/siyujie/okhttp_find/
adb - How to mount _system rewritable or read-only (RW_RO) - Android Enthusiasts Stack Exchange
https://android.stackexchange.com/questions/110927/how-to-mount-system-rewritable-or-read-only-rw-ro
How to connect Burp Suite to an Android Emulator by artx MII Cyber Security Consulting Services Medium
https://medium.com/mii-cybersec/how-to-connect-burp-suite-to-an-android-emulator-9da19b0ad2c3
[Original] null obfuscation - android security - see snow - security community _ security recruitment _ kanxue.com
https://bbs.kanxue.com/thread-247680.htm
Boutique Serial丨Android App Reverse Course No. 3 frida injected Okhttp Capture Packet Part I
https://mp.weixin.qq.com/s?__biz=Mzg3MjU3NzU1OA==&mid=2247496420&idx=1&sn=9a1460a6755524f3e22bf53878a4802c&source=41#wechat_redirect
GitHub - w296488320_NullProguard_ Blank Obfuscation source code
https://github.com/w296488320/NullProguard
https://blog.cxplay.org/works/vscode-to-markdown-editor/
将 VS Code 打造成一个体验舒适的 Markdown 编辑器 _ CXPLAY World
http://www.dtasecurity.cn:20080/androidjunior/readme.html
0822 class Course 9th : real app practice
1 2 3 4 5 6 7 8 9 10 11 12 | Types, screening and treatment methods of reinforcement》 Confuse the development process of reinforcement technology Identification of common obfuscation reinforcement techniques The core principle of shelling (tooling). Memory enumeration, trace, and visualization Memory - based deobfuscation and feature localization Example: Okhttp3 key class positioning after obfuscation The so - called native is closer to the interpreter: Android native is libart.so to explain, and Linux native is CPU direct interpretation If you want to analyze a reinforcement / protection method, you must first implement this reinforcement / protection. Look at the problem from a development perspective |
Android App Protection (2)
https://mp.weixin.qq.com/s/DkpQ_71Gt-jkwOuRU1Mv0A?
DexClassLoader Android Developers
https://developer.android.com/reference/dalvik/system/DexClassLoader
Concerns about the cybersecurity industry in Japan
「onMatch function(instance){」の検索結果 - Yahoo!検索
https://
search.yahoo.co.jp/search?p=onMatch%3Afunction(instance)%7B&ei=UTF-8&ts=498&aq=-1&x=nl&rkf=1&fl=2
How many security industry researchers are there in Japan?
株式会社アクティブディフェンス研究所
http://blog.activedefense.co.jp/2021/12/fridaandroid-malwaremoqhao-xloader.html
事業概要 - 株式会社アクティブディフェンス研究所
https://www.activedefense.co.jp/consultingetc/
改竄とリバースエンジニアリング (Android)
https://github.com/coky-t/owasp-mastg-ja/blob/master/Document/0x05c-Reverse-Engineering-and-Tampering.md
Frida Tutorial 1 - HackTricks
https://book.hacktricks.xyz/v/jp/mobile-pentesting/android-app-pentesting/frida-tutorial/frida-tutorial-1
Useful Words
1 2 3 4 5 | Lexical Obfuscation 它们分别为符号混淆 object - code obfuscation 目标代码混淆 obfuscation tool 混淆工具 code obfuscation tool 工具 identifier renaming obfuscation 标识符重命名混淆 |
赞赏
|
|
---|---|
|
看了下,有丢失图片
|
|
|
|
mb_ldbucrik这个是不要的,具体看上面代码,和下面的图片。 3 者一样, 去掉了中间。 |
|
好的,感谢回答
|
- [原创动画] 写壳学习之__读取A_PE图标写入到B_PE文件,思路分析 7847
- [原创动画] 破解 ida9.0 的 安卓服务端报错 和 反调试, 课件包含可用服务端,可能存在bug【动画垃圾,求勿喷】 4345
- [分享] ida pro 7.6 在win7 x64 综合解决 ipyida | py3.9.10 | 路径 | idapyswitch 2014
- [原创] macOS 13.3 intel, install keypatch For IDA Pro 9.0 2703
- [分享] calleng 的汇编日记,Hidden Camera Manager算法(考古系列)(天草算法第五课) 1530