First, preface
Today, finally, the final article of the break series, the two previous articles were:
First article: How to use eclipse Dynamic debugging Smali source code
Second article: How to use Ida to dynamically debug so files
Now to say is the last article, how to deal with some of the Android APK security protection, in the previous two cracked articles, we can see one is for the Java layer of the crack, one is aimed at the native layer of crack, has not involved in the APK reinforcement, So today is going to introduce how to deal with some of the current market to overcome some of the hardening of the APK, the market is now the way to strengthen the APK is generally two: one is to the source apk overall to do a reinforcement, put in the specified location, when the operation of the decryption dynamic loading, there is a reinforcement of so Decryption is released when so loads the memory. We mainly look at the first form of reinforcement today, is to strengthen the apk as a whole.
second, case analysis
According to international practice, we still have to use a case to analyze the explanation, this time is still using Ali's CTF competition, the third question:
The topic is: Ask for a URL to enter a webpage, and then jump to this page, but must ask to pop up the specified content of the toast prompt, this content is: Xianglong!
To understand the topic, we will be a simple analysis, the general logic here is that the input URL will be passed to a WebView control, to display the Web page, if the logic of the topic, it should be the Web page JS will call a local Java method, and then pop the corresponding hint, So here we go and start working on it.
Follow our previous hack steps:
The first step: must first use the decompression software to get out his Classes.dex file, and then use Dex2jar+jd-gui to view the Java code
Wipe, here we see there is only one application class, from here we can see that this apk may be hardened, why do you say so? Because we know an apk reinforcement, there must be a shell outside, this shell has to be a custom application class, because he needs to do some initialization operation, then generally now hardened apk shell of the application class are like called Stubapplication. And, here we can see, in addition to a application class, no other class, including our activity class are not, then we will find that the egg hurts, nowhere to start.
Second step: We will use the Apktool tool to do the anti-compilation apk, to get the APK androidmanifest.xml and resource content
After the anti-compilation, see the program will have a portal activity is the Mainactivity class, we remember that, regardless of the last apk how to harden, even if we do not see the code of the four components of the definition, But it will certainly be declared in the Androidmanifest.xml, because if not declared, the operation will be error. So here we also analyzed the content of the analysis, or did not find our entry activity class, and we know that he must be placed in a local place, because the need to decrypt the dynamic loading, so it can not be placed on the Internet, is certainly local, so here are some tips:
When we find that the main class in the APK is gone, it must be that the APK is hardened, the source of the reinforcement is definitely local, there are a few places to be aware of:
1, the Asset directory of the application, we know that this directory is not involved in the APK resource compilation process, so a lot of hardened applications like to put encrypted source apk here
2, the source APK encryption into the shell of the end of the Dex file, this is certainly not our case, but there are such reinforcement methods, this reinforcement method will find using the Dex2jar tool to parse Dex is a failure, we know at this time, certainly to Dex did the hands and feet
3, the source APK encryption into so file, this is more difficult, is generally the source apk to be split, stored in so file, analysis difficulty will increase.
Generally are these three places, in fact we know to remember a point: that is, regardless of the source apk is split, is encrypted, where to be put, as long as the local, we have a way to get his.
Well, according to the above three ideas, let us analyze, this apk in the reinforcement of the source apk put where?
With just the Dex file analysis, the second method is definitely not possible, so will it be placed in the asset directory? We look at the Asset directory:
See the asset directory does have two jar files, and our first reaction is to use Jd-gui to view the jar, unfortunately, the open failed, so guess this jar is processed, it should be encrypted, so this is probably the place to store the source apk. But we also said that there is a third way, let's go and see the so file in the Libs directory:
Wipe, here are three so files, and we have only one so file loaded in the application above: libmobisec.so, then the other two so files are probably the hiding place of the split apk file.
Through the above analysis, we generally know that two places are likely to be the source apk hiding place, one is the asset directory, one is the Libs directory, then after the analysis, we found that there are two problems:
First question: The jar file in the asset directory is processed, cannot be opened, and does not know the processing logic
The second question: The three so files in the Libs directory, the only libmobisec.so file loaded
Then the only entrance here is this libmobisec.so file, because the upper code is not, can not be analyzed, the following is a look at so file:
Rub, found that the egg is painful, there is no special method, such as Java_ at the beginning of what, so guess here should be their own registered native method, confused native method name, then here, we will find that we have encountered the problem with the current technology is unable to solve.
third, get the correct Dex content
After analyzing the above cracking process, found that the first task is to get the source APK program, through analysis, processing of the source APK program is difficult to find and analysis, so here will lead to the content of today, using dynamic debugging, To the function in libdvm.so: dvmdexfileopenpartial the breakpoint, then get the Dex file in the memory of the start address and size, and then dump the DEX data.
So here are a few questions:
The first question: Why give dvmdexfileopenpartial this function under the breakpoint?
Because we know that no matter how the previous source program is hardened, where it is, and ultimately it needs to be loaded into memory, and then run, and there is no encrypted content, then we just find this Dex's memory location, this part of the data can be done, how he was reinforced before, we do not care. So the question becomes, how to get the address and size of the Dex loaded into memory, this is the function: Dvmdexfileopenpartial because this function is the final parsing of the Dex file, loaded into memory functions:
int dvmdexfileopenpartial (const void* addr, int len, dvmdex** ppdvmdex);
The first parameter is the Dex memory start address, and the second parameter is the DEX size.
The second question: How to use IDA to give this function a breakpoint
As we said in a previous article, in the dynamic debug so, when the next breakpoint, you must know the absolute address of a function in memory, and the absolute address of the function is: the function in the so file relative address +so file map to the base address in memory, Here we know that this function must exist in the libdvm.so file, because generally related to the DVM function function is present in the so file, then we can find the relative address of this function from the so file, after running the program, find the base address of libdvm.so, add, then how we get Take this libdvm.so file? This file is stored in the/system/lib directory of the device:
Then we just need to use ADB pull to get this so file out.
OK, now that you've solved both of these problems, here's how to proceed:
First step: Run the android_server command in the device and use ADB forward for port forwarding
The Android_server tool here can be found in the Dbgsrv folder in the IDA installation directory
Step two: Start the apk with the command in debug mode
ADB shell am start-d-n com.ali.tg.testapp/. Mainactivity
Because we need to give libdvm.so the breakpoint, this library is the system library, so the loading time is very early, so we need to like before to jni_onload function under the same breakpoint, the debugger mode to run the program, Here we get the app's package name and entry activity through the above androidmanifest.xml:
And here's the android:debuggable=true, debug debugging can be done.
Step three: Dual Open Ida, one for static analysis libdvm.so, one for dynamic debugging libdvm.so
Process attach operations via Ida's Debugger menu:
Fourth step: Start the connection attach debugger using the JDB command
Jdb-connect com.sun.jdi.socketattach:hostname=127.0.0.1,port=8700
However, there may be errors like this:
This is because our 8700 port is not specified and we can view the port through Eclipse's DDMS:
See, this is port 8600, but the basic port 8700 is not, so here we have two methods, one is to change the port of the above command to 8600, and one is to select the application to have 8700 ports:
Click on this entry and we are running the JDB command above:
Is in a waiting state.
Fourth step: Give the Dvmdexfileopenpartial function a breakpoint
Use an IDA static analysis to get the relative address of this function: 43308
In the dynamic debug Ida decryption, use the Ctrl+s key to find the base address of libdvm.so in memory: 41579000
Then add the two to get the absolute address: 43308+41579000=415bc308, using the G key, jump:
Jump to Dvmdexfileopenpartial function, next breakpoint:
Fifth step: Click the Run button or F9 run the program
The previous JDB command was connected:
Ida appears in the following interface, ignore, all the way to click the Cancel button
Run to the Dvmdexfileopenpartial function:
Use F8 for single-step debugging, but it is important to note that as long as the push command has been run, remember not to cross the BL command below, because we do not have to go there, and when the push command is executed, we are using a script dump in memory of DEX data, Here is a knowledge point, that is, the R0~R4 register is generally used to store a function parameter value, then we know that the first parameter of the Dvmdexfileopenpartial function is the DEX memory start address, the second parameter is the DEX size:
Then you can use a script like this to dump it:
Static main (void)
{
Auto FP, dex_addr, end_addr;
fp = fopen ("F:\\dump.dex", "WB");
END_ADDR = r0 + r1;
for (dex_addr = r0; dex_addr < end_addr; dex_addr + +)
FPUTC (Byte (DEX_ADDR), FP);
}
The script doesn't explain it, it's very simple, and this is a fixed format, and then Dex in dump memory is the code, and we'll save the dump Dex to the F drive.
Then we use: Shirt+f2 to bring up Ida's script run interface:
Click to run, here may need to wait a while, after running successfully, we go to f disk to get Dump.dex file, actually here our IDA mission is finished, because we got the memory of the Dex file, the following start is simple, as long as the analysis of Dex files can be
Iv. analyzing the correct Dex file content
After we get dump.dex, we use the Dex2jar tool to decompile:
Unfortunately, the error, the anti-compilation failure, mainly has a class caused by, at the beginning I thought it was dump out of the Dex file has a problem, finally I use Baksmali tool to get Smali file is can, so not dump out of the problem, I finally use the Baksmali tool to convert Dex into a Smali source:
Java-jar Baksmali-2.0.3.jar-o C:\classout/dump.dex
Get the Smali source directory classout in the C drive:
We got the designated Smali source.
Then we can analyze the Smali in a static way:
First find the mainactivity source of the entrance:
This is not explained here, it must be to find the button click event code, here is a btn_listener variable, see the definition of this variable:
is mainactivity$1 internal class definition, look at this class of Smali source code, directly see his onclick method:
As you can see, the contents of the EditText are passed to the webviewactivity in intent, but the key of the intent data here is encrypted.
Let's continue to look at the Webviewactivity class:
We look directly at the OnCreate method, see here is the initialization of WebView, and then make some settings, here we see a @javascriptinterface
This note, we know in the use of WebView, he is used in JS can be accessed to set up the method of this annotation, without this annotation method JS is not accessible
Attention:
We know that this note was added to the SDK17, In the Android4.2 version, the previous version does not have this annotation, any public method can be accessed in the JS code, and the Java object Inheritance relationship will cause many public methods can be accessed in JS, one of the important method is GetClass ()。 Then JS can use reflection to access some other content. So here is the problem: for example, the following section of the JS code:
<script>
function Findobj () {
for (Var obj in window) {
if ("GetClass" in Window[obj]) {
return Window[obj]
}
}
}
</script>
See, this JS code is very dangerous, using the GetClass method to get this object (every object in Java has this method), this method can be used to get a Java object, and then we can call the method in this object. This is also a loophole in webview.
So by introducing @JavascriptInterface annotations, only the functions of @JavascriptInterface annotations can be accessed in JS. This will enhance security.
Return to the point, we analyzed above Smali source code, saw some of the WebView settings information, we can continue to look down:
Here we see some important methods, one is Addjavascriptinterface, the other is the Loadurl method.
We know the general usage of the Addjavaascriptinterface method:
Mwebview.addjavascriptinterface (New Javascriptobject (This), "Jiangwei");
The first parameter is a local Java object, and the second parameter is the name of the object used in JS. Then JS gets the name of the object to invoke the method in the native Java object.
See here the Addjavaascriptinterface method code, you can see, here with
Listviewautoscrollhelpern;->decrypt_native (ljava/lang/string;i) ljava/lang/string;
To confuse the name in JS encryption, this is to prevent malicious Web site to intercept URLs, and then call our local Java method.
Attention:
Here again there is a security issue about WebView, that is, the name of the object JS access here, such as now my program has a JS interactive class, the class has a method to obtain important information about the device, such as the acquisition of the device's Imei method, If our program does not confuse the name, the cracker will get the JS name and method name, and then forge a malicious URL to invoke the method in our program, such as an example:
Then set the JS name:
We can forge a malicious URL page to access this method, such as this malicious page code is as follows:
To run the program:
See, the malicious page here has succeeded in invoking an important method in the program.
So, we can see that it is necessary to confuse the name of the object in the JS interaction, especially some important local methods.
Back to the point, we have analyzed some of WebView's initialization and setup code, and we know that if the method to be accessed by JS, then there must be @javascriptinterface annotations because annotations in Java are also a class, So we go to the source of the annotated class to see the method that is called by JS:
Here we see a showtoast method that shows the content: \u7965\u9f99\uff01, we convert online:
This is what the topic requires.
All right, here we go. APK logic, let's tidy up:
1, enter the URL of a page in mainactivity, jump to Webviewactivity to show
2, webviewactivity have JS interaction, you need to call the Showtoast method in the local Java object to display the message
Problem:
Because the JS object name here is encrypted, so here we write a Web page, but do not know the JS object name, unable to complete the Showtoast method call
Five, the method of crack
Below we will analyze how to solve the above problem, in fact, solve this problem, we have too many methods available
The first method: Modify the Smali source code, the above JS object name to change to our own, such as: Jiangwei, And then in the page you wrote directly call: Jiangwei.showtoast method can, but here need to modify Smali source code, in the use of Smali tool back to compile to Dex file, in the APK, run. method is feasible, but it is too complex to be used here.
The second method: use the Android4.2 in the webview of the vulnerability, directly using the following JS code can be
There is no need for any JS object name, just need the method name to complete the call, so here can see this vulnerability is still very dangerous.
The third method: We see that encryption method, we write a program ourselves, to call this method, altogether get the correct JS object name, here we use this way, because this way has a new skill, so here I will explain.
Then if you use the third method, then you need to analyze the encryption method logic:
Android.support.v4.widget.ListViewAutoScrollHelpern in this class, we go to find this Smali source:
This class loads the Libtranslate.so library, and the encryption method is native layer, so we use Ida to view the Libtranslate.so library:
We search the beginning of the Java function, found that there is no decrypt_native method corresponding to the native function, the native method to do here to register confusion, we directly see the Jni_onload function:
Here is the self-registered native function, but the analysis here, I will not down analysis, why? Because we don't really need to figure out the function of the native layer, we know the Java layer's native method definition, so we can define a native method to invoke the cryptographic function function in libtranslate.so:
We create a new demo project that mimics a Listviewautoscrollhelpern class that internally defines a native method:
Then we load the libtranslate.so in mainactivity:
Then call that native method and print the result:
The parameters of the method here can be viewed in the Smali source of the method parameters:
Click Run to see if there is a crash, we look at the log information:
There is a PAGERTITLESTRIPICSN class in libtranslate.so that cannot be found, and this class should also have a native method, which we construct in this class:
Run again, or error, the reason is similar, also need to construct a class: Taskstackbuilderjellybeann
OK, click Run again:
OK, success, from the log information can be seen, after the decryption of the JS object name is: Smokeybear, then the following is simple, we are constructing a URL page, directly call: Smokeybear.showtoast.
Attention:
Here we see that if we know the definition of Java layer's native method, then we can call this native method to get the function function of native layer, this is still very insecure, but how can we prevent our own so from being called by others? A previous article: The Battle of security in Android has already been said, can be in so in the native function to do an application signature verification, only the signature of their own application can be called, or exit directly.
Six, start testing
Above already knew the JS object name, below we to construct this page:
So here's another question, is this page constructed? Where do you put it? Some students say I have a server, put on the server, and then enter the URL address on it, indeed this method is possible, but some students do not have a server to do? This also has the method, we know WebView's Loadurl method is can load the local page, so we can save this page to the local, but need to note that, here cannot save to the SD card, because this application did not read the SD permission, We can view his Androidmanifest.xml file:
We can't do it without repackaging, so where do we put it? Actually very simple, put in this application/data/data/com.ali.tg.testapp/directory can, because in addition to the SD card location, this position is the best, then we know WebView Loadurl method in loading the local page format is:
File:///data/data/com.ali.tg.testapp/crack.html
Then we can enter it directly
Attention:
Here is a little trick: is that we enter in a text box so much content, is not a bit of egg pain, we can actually use the command to implement the input, that is, using: adb shell input Text "We need to enter the content."
The concrete usage is very simple, opens the edittext which we need to enter the content, clicks the system input interface, then executes the above command:
But here's a little problem, he doesn't recognize semicolons:
However, we directly modify the ingredient number click to enter:
Run successfully, see the toast of the show.
Preface's classmates can poke here: http://download.csdn.net/detail/jiangwei0910410003/9543445
Vii. Content Collation
Here we break the success of the following to see how to tidy up our crack steps:
1, the common routine of cracking
We follow the practice of cracking, First extract the Classses.dex file, use the Dex2jar tool to view the Java code, but found that there is only one application class, so guess the apk is shell, and then use Apktool to decompile the APK, get his resource files and androidmanifest.xml content , the activity class for the package name and entry is found.
2. The source program of the hardened apk is generally stored in the location
Know is the reinforcement apk, then we analyzed, this hardened apk must be stored in a local place, usually three places:
1 in the asset directory of the application
2 "So file in the Libs of the application
3 The end of the applied Dex file
After analyzing it, we found that there are two jar files in the asset directory, but it is not open, guess is processed, so we have to analyze the processing logic, but at this time we have no code, how to analyze it? So this is the time to use dump memory Dex technology:
Regardless of where the last source apk is placed, the last is the need to go through the decryption dynamic loading into memory, so the analysis of the underlying load Dex source, know that there is a function: dvmdexfileopenpartial This function has two important parameters, one is the real address of Dex, one is the size of Dex , and know that this function is in libdvm.so. So we can use IDA for dynamic debugging to get information
3. Dual open Ida start getting Dex content in memory
Double open Ida, go ahead of the dynamic crack so way to give the Dvmdexfileopenpartial function a breakpoint, get the value of two parameters, and then use a script to save the in-memory Dex data to the local disk.
4. Analysis of the Dex content obtained
After getting the in-memory Dex, we are using the Dex2jar tool to view the source code, but found that save, think it is dump out of the DEX format problem, but finally use the Baksmali tool for processing, get Smali source code is can, then we began to analyze Smali source code.
5, analyze the source to understand the idea of cracking
By analyzing the source to know that a page will be loaded on the Webviewactivity page, then JS in that page will invoke a method in the local Java object to show the toast information, but here we have a problem: JS Java object name is obfuscated encryption, So this time we need to analyze the cryptographic function, but this cryptographic function is native, and then we are using IDA to statically analyze the native function, but no analysis is done, because we do not need, in fact, it is very simple, we only need the result, do not need the process, Now the decrypted content we know, native method definition also know, then we go to write a simple demo to call this so native method, the result is successful, we got the correct JS object name.
6, understand the security of WebView
A vulnerability information for earlier versions of WebView, Prior to Android4.2 version WebView has a vulnerability, that is, you can execute all the public methods of Java objects, then in JS can be done so, first get the Geclass method to get this object, and then call this object in some specific methods, because all the objects in Java There is a GetClass method, and this method is public and can return the current object. So after the Android4.2, there is an annotation:
@JavascriptInterface, only the method identified by this annotation can be invoked in JS.
7. Get new skills for input
In the process of validating the results, we found a trick, which is that when we enter a very long text, it is cumbersome and can be implemented using the ADB shell Input text command.
Viii. Summary of technical points
1, through the dump out of the in-memory Dex data, can Buddha block kill Buddha, regardless of how the APK is hardened, eventually need to load into memory.
2, understand the webview of the security of the relevant knowledge, such as we in the WebView JS object name to do a confusion or necessary to prevent the malicious site call our local privacy method.
3, you can try to call the native method in so, after you know the definition of this method
4, adb shell Input Text command to assist our input
ix. Summary
Here's how to dump those hardened APK programs in Android, in fact, the core is one: no matter how the upper layer of reinforcement, eventually loaded into the memory of the Dex is certainly not a reinforcement, so this dex is what we want, Ida is used here to dynamically debug the Dvmdexfileopenpartial function in libdvm.so to get the Dex content in memory, and it can also be obtained using Gdb+gdbserver, the interested classmate to search by themselves. Combined with the previous two articles, even if finish, introduced the android in the general crack way, of course, these three ways is not omnipotent, because the reinforcement and crack is fits together, no one has the absolute advantage, but the two progress together, of course, there are many other ways to crack, if you encounter the words, will be in detail, our goal is not to write the application, and let other people's application become cannon fodder!!
Android dynamic mode hack apk ultimate (hardened apk hack mode)