Intermittent finally to the Android development and reverse of the two books, although there is no Java, and Android development of the basis, but the overall feeling is still relatively able to receive, after all, are analogy. Of course, it is necessary to dig into the details and Chine of the language.
Here are 2 books, and I personally think it's better for Android to get started and Android backwards:
Google Android Development Primer and Combat
"Android software security and reverse analysis"
1. My understanding of the reverse of Android
Because there were some basics of Windows reverse, it felt like a lot of things were common when looking at Android backwards. But because of the nature of the Android program itself, there are a lot of different places.
1.1 Decompile
The Android program is written in the Java language, and the Dex code (which can be seen as the machine code of the Android virtual machine) from Java to the Android virtual machine (Dalvik) requires an intermediate language conversion process. Similar. Net IL Intermediate virtual instruction. And we know that. Net IL Intermediate code can easily "decompile" back to C # source code, because in addition to IL Intermediate language, also contains a large number of meta metadata, these metadata so that we can easily one by one corresponding decompile back to C # source code. Java's intermediate language. class files are similar, and we can use tools to decompile the Java source code directly from the Dex machine code.
1.2 Reverse analysis means
In the reverse analysis of windows, we can use OD or c32asm to analyze assembly instructions (of course, OD can also be dynamically debugged), or use Ida + F5 (hex ray decompile plug-ins) to analyze source code statically (c + +)
In the Android reverse analysis process:
1 We can use Apktool (essentially the Baksmali disassembly engine) to disassemble the apk file, get the various classes, methods, resources, layout files ... Smali code, we can analyze the code flow of the program directly by reading the Smali code, modify the key point or inject the code.
2 we can extract the. dex file from the APK, use the Dex2jar tool to disassemble the Dex, get the jar pack (Java Virtual Instruction), and then decompile it again with tools such as Jd-gui, get the Java source code, and audit the code from the height of the source level. Find the key point function or judgment faster, then go back to the Smali level and modify the code. This approach is more accessible, and the final step is to go back to the Smali level to modify the code.
3 use IDA Pro to directly analyze the. dex file in the APK package, find the location of the key point code, note the file offset, and then modify the. dex file directly. After the modification, re-import the. dex file into the APK. At this point, be careful to modify the checksum field in Dexheader in the Dex file header. After you fix this value, re-import the APK and delete the Meta-inf folder in apk, and then sign it again to complete the break.
The combination of 1.3 Android and C
The hardest thing to do when learning about the reverse of Android is to parse native code, or JNI code. Developers use the Android NDK to write C + + code for Android Java code calls (through the Java Code Transfer layer to complete interface conversion).
Using the Android NDK to write C + + code will eventually generate an arm based on the arms elf executable file, we want to analyze the function of the software must master another skill, arm assembly, arm assembly personal feeling although and x86 assembly similar, but because Ida Pro on ARM Assembly has no decompile function and seemingly no tool can dynamically debug arm code (I did not find on the Internet), causing us to directly look at arm code, plus often accompanied by complex cryptography algorithms and so on, resulting in the reverse of the native code is relatively difficult, The requirements for basic skills are relatively high.
1.4 About analyzing Android programs
1 understand the androidmanifest.xml of the program. All activity (interactions) that are used in the program need to be manually declared in the Androidmanifest.xml file. Including the main activity that starts by default when the program starts, by studying this androidmanifest.xml file, we can know how much activity the program uses, who the main activity is, what permissions it uses, what services it uses, and what it does.
2) focus on application class
This would have been together with the 1 androidmanifest.xml, but it was because the idea had something to do with the reverse mentality of windows.
If there is a TLS entry in the Data directory table of the Windows EXE, the program executes the code in this TLS first after loading, and then the main main program entry is performed.
Other classes in the application analogy program in Android start early.
3 Positioning key Code
3.1) Feedback Method (keyword search method)
By running the program, find the keyword such as the prompt message or title that appears in the program UI, look for the di of the specified string in String.xmlzhong, and then look for the specified ID in the program.
3.2) Characteristic function method
The principle of this approach is similar to the feedback method, because no matter what message you are prompted, you will necessarily invoke the corresponding API function to display the string, such as Toast.maketext (). Show ()
For example, searching for toast in a program can quickly navigate to the calling code
3.3) Code injection method
Code injection method is a dynamic debugging method, we can manually modify the Smali disassembly code, add log input, with Logcat to see the program execution to a specific point of State data.
3.4) Stack Tracking method
The stack tracking method belongs to the dynamic debugging method, which is similar to the idea that we view call stack with OD debugging. We can inject the stack trace information from the output runtime into the Smali code, and then look at the sequence of function calls on the stack to understand the execution flow of the method (since the execution of each function will leave a record on the stack)
3.5) Method Profiling
Method Profiling, methods analysis (this is the name of the book, I prefer to call the benchmark test method), it is a dynamic debugging method, which is mainly used for hot spot analysis and performance optimization. This feature is provided in Ddms, which can track all function call relationships in addition to the CPU time that each function occupies.
1.5 Code obfuscation and Packers on Android
The code written in the Java language itself is easy to decompile, and Google officially joins the Proguard Code obfuscation tool in the Android 2.3 SDK, As long as the correct configuration of project.properties and proguard.cfg two files can use Proguard obfuscation software.
Because of the particularity of language itself, the Java language has no shell protection concept and can only be protected by obfuscation. The native code written for the Android NDK can be added to the shell, but at the moment it looks like only a UPS shell protection
2. Crackme_1 Analysis Study
2.1 Run the program and collect some Basic Information
There is only one input box, which means that the input of this verification code comes from somewhere else, because we know that no matter what your encryption algorithm is, always have a function input source, we enter the UI interface is the equivalent of the result, and the input source should come from somewhere else, after the calculation and we entered on the UI to compare the results , which is roughly the idea.
2.2 Analysis
Use Apktool to decompile the apk file. View the Androidmanifest.xml file. Understand that the main activity is: Main.
Then we extract the. dex file from the APK. Use Dex2jar->jd-gui to view Java source code.
See inside a lot of a,b,c method, basically can be judged to be mixed with proguard, but the problem is not big, although the display is meaningless function name but does not affect our analysis code flow.
Analysis of 2.2.1 Class B
From the OnCreate () code, we begin with Class B:
Class B provides a common constructor public B (Context Paramcontext), a private member function private String B (), and a publicly owned member function public final void a ().
B (): Obtain some information about the device through Telephonymanager, and then obtain the signature by Packagemanager. The strings are then spliced together and returned to the caller.
Telephonymanager Localtelephonymanager = (telephonymanager) this.a.getsystemservice ("Phone");
String str1 = Localtelephonymanager.getdeviceid ();
String str2 = Localtelephonymanager.getline1number ();
String STR3 = Localtelephonymanager.getdevicesoftwareversion ();
String STR4 = Localtelephonymanager.getsimserialnumber ();
String STR5 = Localtelephonymanager.getsubscriberid ();
Object localobject = "";
Packagemanager Localpackagemanager = This.a.getpackagemanager ();
try {String STR6 = Localpackagemanager.getpackageinfo ("Com.lohan.crackme1",). Signatures[0].tocharsstring ();
Localobject = STR6;
Return str1 + str2 + str3 + STR4 + STR5 + (String) localobject;
A (): sharedpreferences localsharedpreferences = preferencemanager.getdefaultsharedpreferences (THIS.A);
Sharedpreferences.editor Localeditor;
if (!localsharedpreferences.contains ("machine_id")) Localeditor = Localsharedpreferences.edit (); try {Localeditor.putstriNg ("machine_id", B ());
Localeditor.commit ();
Return
}
A () invokes method B () to get the string and then stores the string value to the key machine_id via Sharedpreferences.editor, which can be understood as machine code. In other words, the input of this cryptographic function is the machine code of the machine.
After the analysis above, Class B provides method A, function is to generate "machine code" and stored in the system, the corresponding key for machine_id.
Analysis of 2.2.2 Class C
Class C provides more methods, we analyze one by one.
1) constructor
Java code
Public C (Context Paramcontext)
{
a = Paramcontext;
b = "f0d412b5530e1f9841aab434d989cc77";
c = "4ec407446b872351e613111339daae9";
}
Localize the parameter environment context and declare two strings.
2) public static Boolean B ()
Java code
MessageDigest localmessagedigest = messagedigest.getinstance ("MD5");
Localmessagedigest.update (Paramstring.getbytes (), 0, Paramstring.length ());
return new BigInteger (1, Localmessagedigest.digest ()). toString (16);
The MD5 value of paramstring is computed by MessageDigest.
3) public static Boolean B ()
Java code
Packagemanager Localpackagemanager = A.getpackagemanager ();
Try
{
String str = b (New String (Localpackagemanager.getpackageinfo ("com.lohan.crackme1",). Signatures[0]. Tochars ()));
if (!str.equals (b))
{
Boolean bool = Str.equals (c);
if (!bool);
}
else
{return
false;
}
}
Obtains its own signature by Getpackagemanager if the signature is in the two string B (f0d412b5530e1f9841aab434d989cc77) or C ( 4EC407446B872351E613111339DAAE9) Any one is equal, then returns FALSE, otherwise returns true.
4 public static int A (String paramstring)
Java code
Try
{
if (b ()) return
0;
Sharedpreferences localsharedpreferences = Preferencemanager.getdefaultsharedpreferences (a);
if (b (localsharedpreferences.getstring ("machine_id", "")). Equals (paramstring))
{
if (b ()) return
0;
Sharedpreferences.editor localeditor = Localsharedpreferences.edit ();
Localeditor.putstring ("Serial", paramstring);
Localeditor.commit ();
return 1;
}
}
It can be seen that the function of this code is to compute the MD5 of machine code, if it is consistent with the incoming parameter paramstring, then the sharedpreferences is deposited into serial (machine code MD5 value paramstring) field. Of course, there is a call to B method to make some judgments, its own signature can not be known two.
5) public static Boolean A ()
Java code
Sharedpreferences localsharedpreferences = Preferencemanager.getdefaultsharedpreferences (a);
if (!localsharedpreferences.contains ("serial")) return
false;
String str = localsharedpreferences.getstring ("Serial", "");
if (Str.equals ("")) return
false;
return a (str) >= 0;
This is actually the wrapper function for int a (String paramstring) above, which obtains the serial field (the MD5 value of the machine code) by Sharedpreferences, and passes it back to this method, returning the corresponding return value (judging result).
2.2.3 Class A analysis
As you can see, Class A is a countdowntimer:
Schedule a countdown until the future, with regular notifications on intervals along the way. Example of showing a second countdown in a text field: (Android Developer)
From the OnFinish function we see that the function of this class is to countdown for 6 seconds and then call C.A (), which is to determine whether the serial we entered is equal to the MD5 value of "Machine code". If not, set the TextView content prompt registration.
2.2.4 Class Main analysis
1 in OnCreate (), initialize Class B and C first. Then call B.A () to generate and store "machine code", and then call C.A (), which is to determine if the serial has been stored, and to determine if the algorithm can be validated. If you can not pass, then do nothing, this is the start of the detection of registration status, that is, if you have previously registered, it will be automatically identified after the login, but if we are the first launch and did not register, then there is nothing to do.
If it passes, it calls its own method a (). And its own method A () also called the C.b () method, that is, we entered the serial and machine code MD5 values are the same, if the same do nothing, if the difference is the following button and TextView UI control to hide. and start the Countdown class A.start (). That is, two times verification.
Ps:
Note here that because the program uses Proguard to confuse the code, the Code that is translated with Jd-gui is counted from the beginning of the a,b,c, and often is the name of the variable, class, method mixed up. We look at the Java code when we encounter difficult to understand the combination of Smali code to look at, so as to obtain a more accurate flow of program code to grasp.
2 public void OnClick (View paramview)
Java code
if (((EditText) Findviewbyid (2131034114)). GetText (). toString ()) = = 0)
{
Toast.maketext (this, 2130968577 , 0). Show ();
return;
}
Toast.maketext (this, 2130968578, 0). Show ();
Determine if the serial we entered through the UI is the same as the MD5 value of machine code, and if not, pop-up prompts invalid serial! (the corresponding string can be detected by the ID value), if the same, pop-up the for purchasing!
Through the above analysis, we have to synthesize the idea:
When the program starts, it does some initialization work, and then the corresponding machine code is stored in the sharedpreferences.
Check to see if the serial key value pair has been saved in the current sharedpreferences and check for correctness, that is, check if it was registered last time. If you do not have this key value pair, the description is not registered, if this key-value pair is true and correct, the code will then continue to check whether the APK's own signature is the two defined in the code, and if it does nothing (that is, still not checking), if the code continues to perform a 6-second Class A, Check the serial key value pairs again after 6 seconds.
For that button click event, OnClick (), it gets the user input through the UI serial and detects if the MD5 value is equal to the machine code, if the equality is stored in the key value pair in the sharedpreferences.
The above is basically the code of this program thinking. As we can see, the author uses the idea of double protection, which is not only to have the same serial you entered, but also to limit the signature of your apk.
3. Crack the train of thought
3.1 Simple crack, code injection method to get the registration code.
After analysis, we know that there should be 155 lines in B.smali:
Move-result-object v2 Here code injection, because this B () function is to get the current "machine code" (note, here is the "machine code" without MD5, because the MD5 in the program is calculated temporarily)
We are here to join:
Const-string v3, "SN"
invoke-static {v3, v2}, Landroid/util/log;->v (ljava/lang/string; ljava/lang/string;) I
Re-compile the Smalli code.
Execute ADB logcat-s sn:v on the command line, and then start the program
will see a string of strings on the command line, which is the machine code we want.
After you have computed the MD5 values, you can complete the break.
3.2 Read the program corresponding file
We know that the so-called sharedpreferences is essentially stored in the current program space under the/data/data/<package name>/shared_prefs/<package name>_ Preferences.xml in the file.
We can connect through the ADB and read the contents of this file directly.
As you can see, the machine code is the same as the way we injected the code.
3.3 Write the registration machine
This method is the best, write the registration machine requires us to the target program code have a comprehensive understanding, and then simulate the original algorithm or reverse the original algorithm to write the Register machine
We regenerate a new engineering com.lohan.crackme with Eclipse. Note that the registration of the project must be the same as the package name of the target program, so that the APK signature will be the same when our registration machine is run.
The core algorithms are as follows:
Java code
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Settitle ("Crackme1_keygen");
Final context = Getapplicationcontext ();
Gets the UI control Txt_machinecode = (TextView) Findviewbyid (R.id.machinecode);
Txt_apksig = (TextView) Findviewbyid (R.ID.APKSIG);
Txt_serial = (TextView) Findviewbyid (r.id.serial);
Btn_go = (Button) Findviewbyid (R.id.ok);
Set Listener Event Btn_go.setonclicklistener (new Onclicklistener () {public void OnClick (View v) {//Compute machine code
Telephonymanager Localtelephonymanager = (telephonymanager) context.getsystemservice ("Phone");
String str1 = Localtelephonymanager.getdeviceid ();
String str2 = Localtelephonymanager.getline1number ();
String STR3 = Localtelephonymanager.getdevicesoftwareversion ();
String STR4 = Localtelephonymanager.getsimserialnumber (); String STR5 = Localtelephonymanager.getsubscribeRId ();
Object localobject = "";
Packagemanager Localpackagemanager = Context.getpackagemanager (); try {String STR6 = Localpackagemanager.getpackageinfo ("Com.lohan.crackme1",). Signatures[0].tocharsstrin
g ();
Localobject = STR6;
String Str_result = str1 + str2 + str3 + STR4 + STR5 + (String) localobject;
The Machine code Txt_machinecode.settext (Str_result) is obtained.
Computes the signature Txt_apksig.settext (STR6) of the current apk;
Compute the registration code messagedigest localmessagedigest = null;
try {localmessagedigest = messagedigest.getinstance ("MD5");
catch (NoSuchAlgorithmException e) {//TODO auto-generated catch block E.printstacktrace ();
} localmessagedigest.update (Str_result.getbytes (), 0, Str_result.length ());
String str_serial = new BigInteger (1, Localmessagedigest.digest ()). toString (16);
Txt_serial.settext (str_serial);
} catch (Packagemanager.namenotfoundexception localnamenotfoundexception) {while (true) Localna
Menotfoundexception.printstacktrace ();
}
}
});
Crack the results
APK:
Http://pan.baidu.com/s/1qsygp
4. Summary
At this point, the Android Crackeme_1 even cracked complete. This time the Android learning is also a temporary end, mobile wireless security is the new direction in the future, in the near future, based on the Android platform for a variety of applications and software is not only mobile phones and even a variety of interconnected terminals will enter the vision of people, wireless security research should also slowly become hot.
I also hope that the next time I study Android security will be more in-depth understanding and experience.
Interested students can look at this article, thank you all for the support of this site!