├── images
├── JNIcall.png
├── favicon.ico
├── OpenArchive.png
├── pinkandroid.png
├── DevelopersFlow.jpg
├── Ex1.OpenInJadx.png
├── RetypedToJNIEnv.png
├── ReversersFlow.jpg
├── Mediacode.InJadx.png
├── loadingIntoGhidra.png
└── LoadedInDataTypeManager.png
├── _config.yml
├── README.md
├── conclusion.md
├── index.md
├── reversing_intro.md
├── obfuscation.md
├── reversing_dex.md
├── app_fundamentals.md
└── reversing_native_libs.md
/images/JNIcall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/JNIcall.png
--------------------------------------------------------------------------------
/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/favicon.ico
--------------------------------------------------------------------------------
/images/OpenArchive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/OpenArchive.png
--------------------------------------------------------------------------------
/images/pinkandroid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/pinkandroid.png
--------------------------------------------------------------------------------
/images/DevelopersFlow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/DevelopersFlow.jpg
--------------------------------------------------------------------------------
/images/Ex1.OpenInJadx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/Ex1.OpenInJadx.png
--------------------------------------------------------------------------------
/images/RetypedToJNIEnv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/RetypedToJNIEnv.png
--------------------------------------------------------------------------------
/images/ReversersFlow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/ReversersFlow.jpg
--------------------------------------------------------------------------------
/images/Mediacode.InJadx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/Mediacode.InJadx.png
--------------------------------------------------------------------------------
/images/loadingIntoGhidra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/loadingIntoGhidra.png
--------------------------------------------------------------------------------
/images/LoadedInDataTypeManager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/AndroidAppRE/master/images/LoadedInDataTypeManager.png
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-minimal
2 | title: Android App Reverse Engineering 101
3 | description: Learn to reverse engineer Android applications!
4 | logo: images/pinkandroid.png
5 | google_analytics: UA-153918544-1
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Intro to Android App Reverse Engineering workshop.
2 | If you're interested in learning to reverse engineer Android applications (both DEX and native code), check out the workshop at [maddiestone.github.io/AndroidAppRE](https://maddiestone.github.io/AndroidAppRE).
3 |
--------------------------------------------------------------------------------
/conclusion.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 | # 7. Conclusion
19 |
20 | Congratulations! You are now an Android App Reverse Engineer!
21 |
22 | I hope this workshop has helped introduce you to how to reverse engineer Android apps and provided you with the foundations such that you can go off and continue learning and applying these skills in whatever way you wish.
23 |
24 | If you're looking for some next steps, here are some suggested topics:
25 | * Malware Analysis
26 | * Dynamic Analysis of Android Apps
27 | + [frida.re](https://frida.re) is a great tool to play with!
28 | * Vulnerability Research
29 | * ARM Assembly
30 | * Android OS Internals
31 | * Android and Linux Kernel
32 |
33 | The possibilities are endless! If you want to reach out, Twitter ([@maddiestone](https://twitter.com/maddiestone)) is the best bet!
34 |
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 1. Introduction
4 | Welcome to AndroidTM App Reverse Engineering 101! This workshop's goal is to give you the foundations to begin reverse engineering Android applications. While this workshop won't teach you the details of Android app development, Android malware analysis, Android vulnerability hunting, etc., I hope to give you all the necessary foundations through this workshop such that you can apply your new Android reversing skills to doing those things.
5 |
6 | This workshop will be wholly based on reverse engineering through static analysis, or analyzing and understanding an application by examining its code. I won't be covering dynamic analysis where an analyst runs an application and understands the application by executing it, debugging it, etc. Why? Static analysis tends to be a less approachable skill for people to pick up on their own, so I want to help you do it! (And I really love static analysis)
7 |
8 | ## Environment
9 | All of the exercises in this workshop can be done in the virtual machine (VM) that is available here.
10 | * [Virtual Box VM](https://drive.google.com/file/d/1yP84Rrpe42slXliVAsHQNYeXlqAJfKgO/view?usp=sharing)
11 | * [.ova for VMWare](https://drive.google.com/file/d/1Og-mHwpIxX-ghxwJf_g7bS7Vt1gU9gsm/view?usp=sharing)
12 |
13 | The VM is an Ubuntu 18.04 64-bit image. The username is `AndroidAppRE` and the password is `android`. The VM has the following tools installed:
14 |
15 | * [jadx](https://github.com/skylot/jadx) - Android decompiler. We load the APKs into jadx. And are able to analyze the DEX bytecode using jadx.
16 | * [Ghidra](https://ghidra-sre.org/) - Software reverse engineering tool. We use its ARM disassembler/decompiler functionality in the exercises to statically analyze the native libraries.
17 |
18 | ## Table of Contents
19 |
20 | 1. [Introduction](index.html)
21 | 1. [Android Application Fundamentals](app_fundamentals.html)
22 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
23 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
24 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
25 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
26 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
27 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
28 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
29 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
30 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
31 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
32 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
33 | 1. [Conclusion](conclusion.html)
34 |
35 | ## Acknowledgements
36 |
37 | This workshop was modeled after the format used by Amanda Rousseau's ([@malwareunicorn](https://twitter.com/malwareunicorn)) RE 101 workshop which she released using GitHub pages. Thanks, Amanda, for the inspiration!
38 |
39 | _"The Android robot used as the logo is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License."_
40 |
41 | _Android is a trademark of Google LLC._
42 |
43 | [**NEXT** > 2. Android Application Fundamentals](app_fundamentals.html)
44 |
45 |
--------------------------------------------------------------------------------
/reversing_intro.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 |
19 |
20 | # 3. Getting Started with Reversing Android Apps
21 | Now that we've reviewed the basics of Android applications, it's time to start reversing them!
22 |
23 | ## Starting Points for RE
24 | One of the main keys of reverse engineering, regardless of platform, that all reverse engineers need to do, is figure out where to start their analysis. As a reverse engineer, when you've decided that your next step to solve your problem/answer your question is to use static analysis, then you need to know where you want to begin the static analysis.
25 |
26 | Android applications can be very large and realistically, you likely won't be able to review every line of code. So where do you begin? My guidance when deciding where to begin doing static analysis is:
27 |
28 | 1. **What is your goal?** In *most* cases, you are doing RE/static analysis to answer a specific question. Remember what that is and go back to it often. It's very easy to go down a rabbit hole of code that is not related to the problem you're trying to solve.
29 | 1. **API Calls** Most interesting behaviors that you may want to identify in Android, ultimately come down to a single, or a set of API calls. For example, let's say you're evaluating an application to see if it's doing [Premium SMS Fraud](https://developers.google.com/android/play-protect/phacategories#billing-fraud). Premium SMS Fraud means that an app is sending a premium SMS message without user consent. Therefore, to do the fraud, the app must send an SMS message. There's a finite number of API calls that will allow an application to send an SMS message. For example, `sendTextMessage`, `sendMultipartMessage`,`smsto:`. Therefore one of the key places to begin analysis, is to find the API calls that are required for the behavior you're interested in, and then search for them in your application. You can then begin your reversing around those API calls.
30 | 1. **App Entry Points** In many cases, you're only interested in code that can be executed, not dead code, in the application. Therefore, starting at an application entry point (detailed in [this section](app_fundamental.html#application-entry-points)) is a good choice if you're not sure where else to start.
31 | 1. **Decryption Methods** Java largely relies on strings to do many of its operations. For example, to send intents or call methods through reflection. If your application has no human readable strings, then it likely means its obfuscated or encrypted. A good starting point is to find if either "jumbled" strings or binary arrays are all passed to the same methods. If they are, those methods are likely the deobfuscation or decryption methods.
32 |
33 | ## Exercise #1 - Beginning RE with jadx
34 |
35 | In Exercise #1, we're going to practice coming up with the classes where we would begin our RE analysis. Your goal is to come up with a class or classes that you think would be a good place to begin your analysis. The sample is the ThaiCamera.apk. You can find this sample in the VM at `~/samples/ThaiCamera.apk`. The SHA256 digest of this sample is 55da412157e93153e419c3385ebcd5335bd0d0c3f77a75e2d2413dd128270be2.
36 |
37 | ### Goal
38 | The goal of this exercise is to:
39 |
40 | 1. Learn to use jadx for reverse engineering APKs
41 | 1. Practice identifying class(es) that would be good starting points to begin your revering
42 |
43 | ### Exercise Context
44 | You are a malware analyst for Android applications. You are concerned that this sample maybe doing premium SMS fraud, meaning that it sends an SMS to a premium phone number without disclosure & user consent.
45 |
46 | ### Instructions
47 |
48 | 1. Start jadx by opening the terminal in the VM and running the `jadx-gui` command in the terminal.
49 | 1. Open ThaiCamera.apk in the jadx GUI. It's in the VM's path at `~/samples/ThaiCamera.apk`. When you open the application in jadx, you will see the following. Under the Source Code heading, the packages (namespaces for the Java classes) included in the application. 
50 | 1. By clicking on the expansion tab of "Resources", you can see the contents of the APK. Some of the most interesting are the Manifest (`AndroidManifest.xml`), `classes.dex` (contains the DEX bytecode that is decompiled under the "Source Code" tab), and the `assets/` folder which contains any other files the APK may need to run.
51 | 1. Open AndroidManifest.xml and identify any of the application entry points described in the [Application Entry Points](app_fundamentals.html#application-entry-points) section.
52 | 1. Using the information gathered in the previous step and the [Starting Points for RE](#starting-points-for-re) section above. Decide on a class or classes, that you think would be classes that you'd begin analyzing when you start your reversing.
53 |
54 | ### Solution
55 |
56 |
57 |
58 |
59 |
60 |
61 | [**NEXT** > 4. Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
62 |
63 |
--------------------------------------------------------------------------------
/obfuscation.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 |
19 | # 6. Reverse Engineering Android Apps - Obfuscation
20 |
21 | There are many times when the application you're reversing will not be as straight forward as some of the examples we've discussed. The developer will implement one or more obfuscation techniques to hide the behavior and/or implementation of their app. This can be for both benign and malicious reasons.
22 |
23 | The key about obfuscation to remember is that if you want to de-obfuscate it, you will be able to. The key decision is not whether or not you can, but whether or not it's worth the resources to de-obfuscate.
24 |
25 | The reason that you can always de-obfuscate something is because ultimately the CPU at some point has to see the unobfuscated code in order to run it.
26 |
27 | ## How to De-Obfuscate
28 |
29 | How you choose to de-obfuscate the application will depend on the obfuscation method, but there are a couple of common techniques that usually work well. Here, we will only touch on the static de-obfuscation techniques since this workshop only covers static analysis/reversing. However, do remember that running the application and dynamically analyzing it can be another great way to get around obfuscation.
30 |
31 | For obfuscation in the DEX bytecode (Java), one of the easiest ways to statically deobfuscate is to identify the de-obfuscation methods in the application and copy their decompilation into a Java file that you then run on the obfuscated file, strings, code, etc.
32 |
33 | Another solution for both Java and Native Code is to transliterate the de-obfuscation algorithm into Python or any other scripting language that you're most comfortable. I say "transliterate" because it's important to remember that you don't always need to \*understand\* the de-obfuscation algorithm, you just need a way to execute it. I cover this in more detail in the "Unpacking the Packed Unpacker" talk that is linked in the "More Examples" section.
34 |
35 | ## Indicators of Obfuscation
36 |
37 | There are many different types of obfuscation and thus, just as many different types of indicators to alert you as the analyst that an application is likely obfuscated, but here are a few examples with proposed static analysis solutions for deobfuscating.
38 |
39 |
40 | * No strings: Java and Android are highly dependent on strings so if you don't see any or only scrambled strings, it's highly likely the strings are obfuscated.
41 | + Suggested solution: Look for method calls that take strings as an argument and trace back where that argument is coming from. At some point the string argument will be going through a deobfuscation method before it's passed to the API that takes the String argument.
42 | * Scrambled strings: The Java and Android APIs require the plain text strings, not scrambled.
43 | + Suggested solution: The scrambled strings are all likely passed to the same methods prior to being passed to the APIs. These methods are likely the deobfuscation methods.
44 | * Binary files in the assets/ directory and DexClassLoader calls in the app: Likely unpacking and loading additional code. (Could also be downloading from a remote location and then loading using DexClassLoader)
45 | + Suggestion Solution: Identify where the file is read and then follow the path. It is likely deobfuscated quickly after being read.
46 | * Native libraries - Can't identify the JNI functions (no funcs named Java_ and no calls to RegisterNatives): In order to execute any native methods, JNI has to be able to pair the function in the native library with the native method declaration in Java and thus one of the two must exist at some point.
47 | + Suggested Solution: Start at JNI_OnLoad method and look for a de-obfuscation routine that loads additional code.
48 |
49 |
50 | ## Exercise 7 - String Deobfuscation
51 |
52 | In this exercise, we will practice de-obfuscating strings in order to analyze an application. For the exercise we will use the sample at `~/samples/ClashOfLights.apk` in the VM. This sample has the SHA256 digest c403d2dcee37f80b6d51ebada18c409a9eae45416fe84cd0c1ea1d9897eae4e5.
53 |
54 | ### Goals
55 | To identify obfuscated strings and develop a solution to deobfuscate it.
56 |
57 | ### Exercise Context
58 | You are a malware analyst reviewing this application to determine if it's malware. You come across an obfuscated Javascript string that is being loaded and need to deobfuscate it to determine whether or not the application is malicious. You can't run the application dynamically and need to determine what the Javascript is statically.
59 |
60 | ### Instructions
61 |
62 | 1. Find the string that you need to de-obfuscate
63 | 1. Identify the routine that de-obfuscates it.
64 | 1. Determine how you want to write a solution to de-obfuscate the string.
65 | 1. Do it :)
66 |
67 | ### Solution
68 |
69 |
70 |
71 | The deobfuscated string is:
72 | ```
73 |
74 | ```
75 |
76 | The Python script I wrote to de-obfuscate it is:
77 | ```
78 | enc_str = "773032205849207A3831326F1351202E3B306B7D1E5A3B33252B382454173735266C3D3B53163735222D393B475C7A37222D7F38421B6A66643032205849206477303220584920643D2223725C503A3F39636C725F5C237A082C383C7950223F65023F3D5F4039353E3079755F5F666E1134141F5C4C64377A1B671F565A1B2C7F7B101F42700D1F39331717161574213F2B2337505D27606B712C7B0A543D342E317F214558262E636A6A6E1E4A37282233256C"
79 |
80 | length = len(enc_str)
81 | count = 0
82 | dec_str = [0] * (length/2)
83 | while (count < length):
84 | dec_str[count/2] = (int(enc_str[count], 16) << 4) + int(enc_str[count + 1], 16) & 0xFF
85 | count += 2
86 | print dec_str
87 |
88 |
89 | key = [75, 67, 81, 82, 49, 57, 84, 90]
90 | enc_str = dec_str
91 | count = 0
92 | length = len(enc_str)
93 | while (count < length):
94 | dec_str[count] = chr(enc_str[count] ^ key[count % len(key)])
95 | count += 1
96 | print ''.join(dec_str)
97 | ```
98 |
99 | ## More Examples
100 |
101 | I have done a few talks on de-obfuscating Android apps that include a variety of obfuscation mechanisms. In these talks, I discuss the advanced obfuscation techniques, my solution to de-obfuscate them, and the considerations and choices I made when deciding how I wanted to deobfuscate.
102 |
103 | * BlackHat USA 2018: "Unpacking the Packed Unpacker: Reverse Engineering an Android Anti-Analysis Library" \[[video](https://www.youtube.com/watch?v=s0Tqi7fuOSU)\]
104 | + This talk goes over reverse engineering one of the most complex anti-analysis native libraries I've seen used by an Android application. It covers mostly obfuscation techniques in native code.
105 | * REcon 2019: "The Path to the Payload: Android Edition" \[[video](https://recon.cx/media-archive/2019/Session.005.Maddie_Stone.The_path_to_the_payload_Android_Edition-J3ZnNl2GYjEfa.mp4)\]
106 | + This talk discusses a series of obfuscation techniques, solely in Java code, that an Android botnet was using to hide its behavior.
107 |
108 |
109 | [**NEXT** > 7. Conclusion](conclusion.html)
--------------------------------------------------------------------------------
/reversing_dex.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 |
19 |
20 | # 4. Reverse Engineering Android Apps - DEX Bytecode
21 |
22 | Now that we have starting points for where we think we ought to begin reversing, let's get started and then talk more about the "how" and "tips and tricks".
23 |
24 | ## Exercise 2 - Reverse Engineer the DEX
25 | In Exercise #2, we're going to continue with where we left off in [Exercise #1](reversing_intro.html#exercise-1---beginning-re-with-jadx) You can find this sample in the VM at `~/samples/ThaiCamera.apk`. The SHA256 digest of this sample is 55da412157e93153e419c3385ebcd5335bd0d0c3f77a75e2d2413dd128270be2. We are going to reverse engineer this application to determine if it is doing premium SMS fraud.
26 |
27 | To be doing premium SMS fraud, the application must send a premium SMS message (premium phone numbers are usually shortcodes) without disclosure that includes the phone number the SMS is being sent to and the cost of the SMS message and user consent.
28 |
29 | ### Goal
30 | The goal of this exercise is to: Reverse engineer our 1st Android application (DEX code)! More specifically:
31 |
32 | 1. Learn to analyze the Java decompilation of the DEX bytecode in jadx to understand what the Android application is doing.
33 | 1. Experience 1st hand how Android malware analysts apply reverse engineering to their context
34 |
35 | ### Exercise Context
36 | You are a malware analyst for Android applications. You are concerned that this sample maybe doing premium SMS fraud, meaning that it sends an SMS to a premium phone number without disclosure & user consent. In order to flag as malware, you need to determine if the Android application is:
37 |
38 | 1. Sending an SMS message, and
39 | 1. That SMS message is going to a premium number, and
40 | 1. If there is an obvious disclosure, and
41 | 1. If the SMS message is only sent to the premium number after user consent.
42 |
43 | ### Instructions
44 |
45 | 1. If jadx is not already started, start jadx by opening the terminal in the VM and running the `jadx-gui` command in the terminal and open ThaiCamera.apk in the jadx GUI in the same way as in Exercise #1.
46 | 1. Remember that the manifest is available under "Resources" by clicking on AndroidManifest.xml. To analyze the DEX bytecode, you can click on classes under the source code tab to open each class. jadx is a decompiler, rather than a disassembler, so it decompiles the DEX bytecode back to the Java. The decompiled Java will not look exactly the same as when the developer wrote it, however, it's often pretty close to functionally correct.
47 | 1. Begin analyzing the classes you identified as starting points in Exercise #1. When I say analyze, it's as simple as reading each line of decompiled output until you understand what a block of code is doing. Once you understand it, take a step back and evaluate the new information you learned against the questions you're trying to answer with your analysis (Exercise Context). Then decide where to analyze next. If you come from a Java development background, think about reverse engineering as debugging.
48 |
49 | ### Solution
50 |
51 |
52 |
53 |
54 |
55 | ## Exercise 3 - Find the Vulnerability in the Adups OTA Application
56 | The two exercises up until this point have focused on reverse engineering an Android app in order to determine if it is malware. Now, let's apply our reverse engineering skills to finding a vulnerability in an application. You can find the sample for this exercise in `~/samples/FotaProvider.apk`. The SHA256 digest for the sample is 6fddd183bc832659cbea0e55d08ae72016fae25a4aa3eca8156f0a9a0db7f491.
57 |
58 | ### Goal
59 | The goal of this exercise is to apply our DEX reverse engineering skills to finding a vulnerability in an Android app. This example is a little more complex and will introduce us to reversing across different components of the application.
60 |
61 | ### Exercise Context
62 | You are auditing a set of phones for security issues prior to allowing them onto your enterprise network. You are going through the apps that come pre-installed. For this pre-installed application, you are concerned that there may be a vulnerability that allows it to run arbitrary commands.
63 |
64 | ### Instructions
65 |
66 | 1. Start jadx as described in Exercise #1 and open FotaProvider.apk.
67 | 1. Use the Manifest to identify interesting components and the bytecode to analyze the code.
68 | 1. Find a code path that allows other applications or code on the phone to run arbitrary commands as a privileged user.
69 |
70 | Suggested Steps:
71 |
72 | 1. How do we execute arbitrary commands?
73 | 1. How could the app receive remote commands?
74 | 1. What would be a starting point for the classes?
75 | 1. Put it all together and how does it work?
76 |
77 | ### Solution
78 |
79 |
80 |
81 | There is a vulnerability in that any application or component on the device can have an aribtrary command executed as the privileged system user through this application. The FotaProvider.apk sample exports the `WriteCommandReceiver` broadcast receiver through the action `android.intent.action.AdupsFota.operReceiver`. Any component on the device can send an intent with this action and with the String extra "cmd" and that "cmd" will be executed as the system user. On Android, the system UID is the most privileged UID behind root.
82 |
83 | This vulnerability/backdoor was first identified by Kryptowire in 2016. They give a detail explanation of this command execution issue as well as other identified security issues in the Adups OTA apps in their 2017 BlackHat USA presentation, "All your SMS and Contacts Belong to Adups & Others" \[[slides](https://www.blackhat.com/docs/us-17/wednesday/us-17-Johnson-All-Your-SMS-&-Contacts-Belong-To-Adups-&-Others.pdf)\] \[[video](https://www.youtube.com/watch?v=2AL5oKdiNrs&list=PLH15HpR5qRsUyGhBVRDKGrHyQC5G4jQyd&index=46&t=6s)\].
84 |
85 | ## Exercise 4 - Arbitrary Command Execution Take 2
86 |
87 | In this exercise we will once again try and identify whether an application has a vulnerability that permits arbitrary command execution, but this time it is done in a different way. This will introduce us to how to reverse engineer apps that are using Binder, an Android inter-process communication mechanism.
88 |
89 | For this exercise, you will use the app at `~/samples/HonSystemService.apk` in the VM. The SHA256 digest for the sample is 86a1ba436be2d1ee480e1d40418df3aa5f47571d154a8c41e74c439fbfb04b27.
90 |
91 | ### Goal
92 |
93 | The goal of this exercise is to understand how to reverse engineer applications that are using Binder, specifically to look for vulnerabilities.
94 |
95 | ### Exercise Context
96 |
97 | Let's use the same context as Exercise #3, but this time the solution will look different. This will show us another pattern and help us understand Binder.
98 |
99 | ### Instructions
100 | 1. Start jadx as described in Exercise #1 and open HonSystemService.apk.
101 | 1. Use the Manifest to identify interesting components and the bytecode to analyze the code.
102 | 1. Find a code path that allows other applications or code on the phone to run arbitrary commands as a privileged user.
103 |
104 | ### Solution
105 |
106 |
107 |
108 | If you're interested in more resources on analyzing and reverse-engineering pre-installed Android applications, you can check out my Blackhat USA 2019 talk, "Securing the System: A Deep Dive into Reversing Android Pre-Installed Apps" \[[slides](https://github.com/maddiestone/ConPresentations/raw/master/Blackhat2019.SecuringTheSystem.pdf)\]. This example is covered in Case Study #1.
109 |
110 |
111 | [**NEXT** > 5. Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
--------------------------------------------------------------------------------
/app_fundamentals.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 |
19 |
20 | # 2. Android Application Fundamentals
21 |
22 | ## Build an App
23 | One of my biggest suggestions for folks looking to reverse engineer things, whatever they may be, is to try and build what you want to reverse. In the case of Android, you're lucky because there are so many free resources available to build your first application. If you've never built an Android application before, I suggest you start there. Pick any of the available tutorials and videos that spark your interest and get to building. When you understand *how* a developer builds something, it makes it much easier to understand how to reverse engineer it.
24 |
25 | ## Fundamentals Review
26 | Great! You've built an app or learned basic Android app development principles. Here is a review of some of the important points. This ["Application Fundamentals" page](https://developer.android.com/guide/components/fundamentals.html) in the Android developers' docs is a great review.
27 |
28 | * Android applications are in the _APK file format_. APK is basically a ZIP file. (You can rename the file extension to .zip and use unzip to open and see its contents.)
29 | * APK Contents (Not exhaustive)
30 | * AndroidManifest.xml
31 | * META-INF/
32 | * Certificate lives here!
33 | * classes.dex
34 | * Dalvik bytecode for application in the DEX file format. This is the Java (or Kotlin) code that the application will run by default.
35 | * lib/
36 | * Native libraries for the application, by default, live here! Under the lib/ directory, there are the cpu-specific directories. Ex: armeabi, mips,
37 | * assets/
38 | * Any other files that may be needed by the app.
39 | * Additional native libraries or DEX files may be included here. This can happen especially when malware authors want to try and "hide" additional code, native or Dalvik, by not including it in the default locations.
40 |
41 | ## Dalvik & Smali
42 | Most Android applications are written in Java. Kotlin is also supported and interoperable with Java. For ease, for the rest of this workshop, when I refer to "Java", you can assume that I mean "Java or Kotlin". Instead of the Java code being run in Java Virtual Machine (JVM) like desktop applications, in Android, the Java is compiled to the _Dalvik Executable (DEX) bytecode_ format. For earlier versions of Android, the bytecode was translated by the Dalvik virtual machine. For more recent versions of Android, the Android Runtime (ART) is used.
43 |
44 | If developers, write in Java and the code is compiled to DEX bytecode, to reverse engineer, we work the opposite direction.
45 |
46 | 
47 |
48 | 
49 |
50 | Smali is the human readable version of Dalvik bytecode. Technically, Smali and baksmali are the name of the tools (assembler and disassembler, respectively), but in Android, we often use the term "Smali" to refer to instructions. If you've done reverse engineering or computer architecture on compiled C/C++ code. SMALI is like the assembly language: between the higher level source code and the bytecode.
51 |
52 | For the following Hello World Java code:
53 | ```
54 | public static void printHelloWorld() {
55 | System.out.println("Hello World")
56 | }
57 | ```
58 |
59 | The Smali code would be:
60 | ```
61 | .method public static printHelloWorld()V
62 | .registers 2
63 | sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
64 | const-string v1, "Hello World"
65 | invoke-virtual {v0,v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
66 | return-void
67 | .end method
68 |
69 | ```
70 | The Smali instruction set is available [here](https://source.android.com/devices/tech/dalvik/dalvik-bytecode#instructions).
71 |
72 | Most often when reverse engineering Android applications, you will not need to work in Smali. Most applications can be lifted to an even higher level, decompiled Java. Like all tools, Java decompilers may have bugs. My suggestion to you is that whenever the decompiled Java output looks questionable, look at the Smali output. Work line by line with the instruction reference to figure out what the code is doing.
73 |
74 | To get the Smali from DEX, you can use the baksmali tool (disassembler) available at https://github.com/JesusFreke/smali/wiki. The smali tool will allow you to assemble smali back to DEX.
75 |
76 | ## Application Entry Points
77 | One of the most important points of reverse engineering is knowing where to begin your analysis and entry points for code execution is an important part of that.
78 |
79 | ### Launcher Activity
80 | The launcher activity is what most people think of as the entry point to an Android application. The launcher activity is the activity that is started when a user clicks on the icon for an application. You can determine the launcher activity by looking at the application's manifest. The launcher activity will have the following MAIN and LAUNCHER intents listed.
81 |
82 | Keep in mind that not every application will have a launcher activity, especially apps without a UI. Examples of applications without a UI (and thus a launcher activity) are pre-installed applications that perform services in the background, such as voicemail.
83 | ```
84 |
85 |
86 |
87 |
88 |
89 |
90 | ```
91 |
92 | ### Services
93 | [Services](https://developer.android.com/guide/components/services) run in the background without a UI. There are a myriad of ways that they can be started and thus are an entry point for applications. The default way that a service can be started as an entry point to an application is through [Intents](https://developer.android.com/guide/components/intents-filters).
94 |
95 | When the `startService` API is called to start a Service, the `onStart` method in the Service is executed.
96 |
97 | ### Broadcast Receivers
98 | Broadcasts can be thought of a messaging system and [broadcast receivers](https://developer.android.com/guide/components/broadcasts#receiving-broadcasts) are the listeners. If an application has registered a receiver for a specific broadcast, the code in that receiver is executed when the system sends the broadcast. There are 2 ways that an app can register a receiver: in the app's Manifest or dynamically registered in the app's code using the `registerReceiver()` API call.
99 |
100 | In both cases, to register the receiver, the intent filters for the receiver are set. These intent filters are the broadcasts that should trigger the receiver.
101 |
102 | When the specific broadcasts are sent that the receiver is registered for are sent, `onReceive` in the BroadcastReceiver class is executed.
103 |
104 | ### Exported Components (Services & Activities)
105 | Services and Activities can also be ["exported"](https://developer.android.com/guide/topics/manifest/service-element#exported), which allows other processes on the device to start the service or launch the activity. The components are exported by setting an element in the manifest like below. By default, `android:exported="false"` unless this element is set to true in the manifest or intent-filters are defined for the Activity or Service.
106 | ```
107 |
108 |
109 | ````
110 |
111 | ### Application Subclass
112 | Android applications can define a subclass of [Application](https://developer.android.com/reference/android/app/Application). Applications can, but do not have to define a custom subclass of Application. If an Android app defines a Application subclass, this class is instantiated prior to any other class in the application.
113 |
114 | If the `attachBaseContext` method is defined in the Application subclass, it is called first, before the `onCreate` method.
115 |
116 |
117 | [**NEXT** > 3. Getting Started with Reversing Android Apps](reversing_intro.html)
--------------------------------------------------------------------------------
/reversing_native_libs.md:
--------------------------------------------------------------------------------
1 | #### Table of Contents
2 |
3 | 1. [Introduction](index.html)
4 | 1. [Android Application Fundamentals](app_fundamentals.html)
5 | 1. [Getting Started with Reversing Android Apps](reversing_intro.html)
6 | * [Exercise 1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
7 | 1. [Reverse Engineering Android Apps - DEX Bytecode](reversing_dex.html)
8 | * [Exercise 2](reversing_dex.html#exercise-2---reverse-engineer-the-dex)
9 | * [Exercise 3](reversing_dex.html#exercise-3---reverse-engineer-the-dex-to-identify-the-vuln)
10 | * [Exercise 4](reversing_dex.html#exercise-4---arbitrary-command-execution-take-2)
11 | 1. [Reverse Engineering Android Apps - Native Libraries](reversing_native_libs.html)
12 | * [Exercise 5](reversing_native_libs.html#exercise-5---find-the-address-of-the-native-function)
13 | * [Exercise 6](reversing_native_libs.html#exercise-6---find-and-reverse-the-native-function)
14 | 1. [Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
15 | * [Exercise 7](obfuscation.html#exercise-7---string-deobfuscation)
16 | 1. [Conclusion](conclusion.html)
17 |
18 |
19 |
20 | # 5. Reverse Engineering Android Apps - Native Libraries
21 |
22 | Android applications can contain compiled, native libraries. Native libraries are code that the developer wrote and then compiled for a specific computer architecture. Most often, this means code that is written in C or C++. The benign, or legitimate, reasons a developer may do this is for mathematically intensive or time sensitive operations, such as graphics libraries. Malware developers have begun moving to native code because reverse engineering compiled binaries tends to be a less common skillset than analyzing DEX bytecode. This is largely due to DEX bytecode can be decompiled to Java whereas native, compiled code, often must be analyzed as assembly.
23 |
24 | # Goal
25 | The goal of this section is not to teach you assembly (ASM) or how to reverse engineer compiled code more generally, but instead how to apply the more general binary reverse engineering skills, specifically to Android. Because the goal of this workshop is not to teach you the ASM architectures, all exercises will include an ARM *and* an x86 version of the library to be analyzed so that each person can choose the architecture that they are more comfortable with.
26 |
27 | ### Learning ARM Assembly
28 | If you don't have previous binary reverse engineering/ assembly experience, here are some suggested resources. Most Android devices run on ARM, but all exercises in this workshop also include an x86 version of the library.
29 |
30 | To learn and/or review ARM assembly, I highly suggest the [ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) from [Azeria Labs](https://azeria-labs.com/).
31 |
32 | ## Introduction to the Java Native Interface (JNI)
33 | The Java Native Interface (JNI) allows developers to declare Java methods that are implemented in native code (usually compiled C/C++). JNI interface is not Android-specific, but is available more generally to Java applications that run on different platforms.
34 |
35 | The Android Native Development Kit (NDK) is the Android-specific toolset on top of JNI. According to the [docs](https://developer.android.com/ndk/guides):
36 | > In Android, the Native Development Kit (NDK) is a toolset that permits developers to write C and C++ code for their Android apps.
37 |
38 | Together, JNI and NDK allow Android developers to implement some of their app's functionality in native code. The Java (or Kotlin) code will call a Java-declared native method which is implemented in the compiled, native library.
39 |
40 | ### References
41 |
42 | **Oracle JNI Docs**
43 |
44 | * [JNI Specification](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)
45 | * [JNI Functions](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html) <-- I always have this one open and refer to it while reversing Android native libraries
46 |
47 | **Android JNI & NDK References**
48 | * [Android JNI Tips](https://developer.android.com/training/articles/perf-jni) <-- Highly suggest reading the "Native Libraries" section to start
49 | * [Getting Started with the NDK](https://developer.android.com/ndk/guides/) <-- This is guidance for how developers develop native libraries and understanding how things are built, makes it easier to reverse.
50 |
51 | ## Target of Analysis - Android Native Libraries
52 |
53 | For this section, we are focusing on how to reverse engineer app functionality that has been implemented in Android native libraries. When we say Android native libraries, what do we mean?
54 |
55 | Android native libraries are included in APKs as `.so`, shared object libraries, in the ELF file format. If you have analyzed Linux binaries previously, it's the same format.
56 |
57 | These libraries by default are included in the APK at the file path `/lib//lib.so`. This is the default path, but developers could also choose to include the native library in `/assets/` if they so choose. More often, we are seeing malware developers choose to include native libraries in paths other than `/lib` and using different file extensions to attempt to "hide" the presence of the native library.
58 |
59 | Because native code is compiled for specific CPUs, if a developer wants their app to run on more than 1 type of hardware, they have to include each of those versions of the compiled, native library in the application. The default path mentioned above, includes a directory for each cpu type officially supported by Android.
60 |
61 | | CPU | Native Library Path |
62 | | ------| ---- |
63 | | “generic” 32-bit ARM | `lib/armeabi/libcalc.so` |
64 | | x86 | `lib/x86/libcalc.so` |
65 | | x64 | `lib/x86_64/libcalc.so` |
66 | | ARMv7 | `lib/armeabi-v7a/libcalc.so` |
67 | | ARM64 | `lib/arm64-v8a/libcalc.so` |
68 |
69 | ## Loading the Library
70 | Before an Android app can call and execute any code that is implemented in a native library, the application (Java code) must load the library into memory. There are two different API calls that will do this:
71 | ```
72 | System.loadLibrary("calc")
73 | ```
74 | or
75 | ```
76 | System.load("lib/armeabi/libcalc.so")
77 | ```
78 | The difference between the two api calls is that `loadLibrary` only take takes the library short name as an argument (ie. libcalc.so = "calc" & libinit.so = "init") and the system will correctly determine the architecture it's currently running on and thus the correct file to use. On the other hand, `load` requires the full path to the library. This means that the app developer has to determine the architecture and thus the correct library file to load themselves.
79 |
80 | When either of these two (`loadLibrary` or `load`) APIs are called by the Java code, the native library that is passed as an argument executes its `JNI_OnLoad` if it was implemented in the native library.
81 |
82 | To reiterate, before executing any native methods, the native library has to be loaded by calling `System.loadLibrary` or `System.load` in the Java code. When either of these 2 APIs is executed, the `JNI_OnLoad` function in the native library is also executed.
83 |
84 | ## The Java to Native Code Connection
85 | In order to execute a function from the native library, there must be a Java-declared native method that the Java code can call. When this Java-declared native method is called, the "paired" native function from the native library (ELF/.so) is executed.
86 |
87 | A Java-declared native method appears in the Java code as below. It appears like any other Java method, except it includes the `native` keyword and has no code in its implementation, because its code is actually in the compiled, native library.
88 | ```
89 | public native String doThingsInNativeLibrary(int var0);
90 | ```
91 | To call this native method, the Java code would call it like any other Java method. However, in the backend, the JNI and NDK would instead execute the corresponding function in the native library. To do this, it must know the pairing between a Java-declared native method with a function in the native library.
92 |
93 | There are 2 different ways to do this pairing, or linking:
94 | 1. Dynamic Linking using JNI Native Method Name Resolving, or
95 | 1. Static Linking using the `RegisterNatives` API call
96 |
97 | ### Dynamic Linking
98 | In order to link, or pair, the Java declared native method and the function in the native library dynamically, the developer names the method and the function according to the specs such that the JNI system can dynamically do the linking.
99 |
100 | According to the spec, the developer would name the function as follow for the system to be able to dynamically link the native method and function. A native method name is concatenated from the following components:
101 |
102 | 1. the prefix Java_
103 | 1. a mangled fully-qualified class name
104 | 1. an underscore (“_”) separator
105 | 1. a mangled method name
106 | 1. for overloaded native methods, two underscores (“__”) followed by the mangled argument signature
107 |
108 | In order to do dynamic linking for the Java-declared native method below and let's say it's in the class `com.android.interesting.Stuff`
109 | ```
110 | public native String doThingsInNativeLibrary(int var0);
111 | ```
112 | The function in the native library would need to be named:
113 | ```
114 | Java_com_android_interesting_Stuff_doThingsInNativeLibrary
115 | ```
116 | If there is not a function in the native library with that name, that means that the application must be doing static linking.
117 |
118 | ### Static Linking
119 | If the developer doesn't want to or can not name the native functions according to the spec (Ex. wants to strip debug symbols), then they must use static linking with the `RegisterNatives` ([doc](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp5833)) API in order to do the pairing between the Java-declared native method and the function in the native library. The `RegisterNatives` function is called from the native code, not the Java code and is most often called in the `JNI_OnLoad` function since `RegisterNatives` must be executed prior to calling the Java-declared native method.
120 |
121 | ```
122 | jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);
123 |
124 | typedef struct {
125 | char *name;
126 | char *signature;
127 | void *fnPtr;
128 | } JNINativeMethod;
129 | ```
130 |
131 | When reverse engineering, if the application is using the static linking method, we as analysts can find the `JNINativeMethod` struct that is being passed to `RegisterNatives` in order to determine which subroutine in the native library is executed when the Java-declared native method is called.
132 |
133 | The `JNINativeMethod` struct requires a string of the Java-declared native method name and a string of the method's signature, so we should be able to find these in our native library.
134 |
135 | #### Method Signature
136 | The `JNINativeMethod` struct requires the method signature. A method signature states the types of the arguments that the method takes and the type of what it returns. This link documents [JNI Type Signatures](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html) in the "Type Signatures" section.
137 |
138 | * Z: boolean
139 | * B: byte
140 | * C: char
141 | * S: short
142 | * I: int
143 | * J: long
144 | * F: float
145 | * D: double
146 | * L fully-qualified-class ; :fully-qualified-class
147 | * [ type: type[]
148 | * ( arg-types ) ret-type: method type
149 | * V: void
150 |
151 | For the native method
152 | ```
153 | public native String doThingsInNativeLibrary(int var0);
154 | ```
155 | The type signature is
156 | ```
157 | (I)Ljava/lang/String;
158 | ```
159 |
160 | Here's another example of a native method and its signature. For the following is the method declaration
161 | ```
162 | public native long f (int n, String s, int[] arr);
163 | ```
164 | It has the type signature:
165 | ```
166 | (ILjava/lang/String;[I)J
167 | ```
168 |
169 | ### Exercise #5 - Find the Address of the Native Function
170 | In Exercise #5 we're going to learn to load native libraries in a disassembler and identify the native function that is executed when a native method is called. For this particular exercise, the goal is not to reverse engineer the native method, just to find the link between the call to the native method in Java and the function that is executed in the native library. For this exercise, we will be using the sample Mediacode.apk. This sample is available at `~/samples/Mediacode.apk` in the VM. Its SHA256 hash is a496b36cda66aaf24340941da8034bd53940d1b08d83a97f17a65ae144ebf91a.
171 |
172 | #### Goal
173 | The goal of this exercise is to:
174 |
175 | 1. Identify declared native methods in the DEX bytecode
176 | 1. Determine what native libraries are loaded (and thus where the native methods may be implemented)
177 | 1. Extract the native library from the APK
178 | 1. Load the native library into a disassembler
179 | 1. Identify the address (or name) of the function in the native library that is executed when the native method is called
180 |
181 | #### Instructions
182 |
183 | 1. Open Mediacode.apk in jadx. Refer back to [Exercise #1](reversing_intro.html#exercise-1---beginning-re-with-jadx)
184 | 1. This time, if you expand the Resources tab, you will see that this APK has a `lib/` directory. The native libraries for this APK are in the default CPU paths. 
185 | 1. Now we need to identify any declared native methods. In jadx, search and list all declared native methods. There should be two.
186 | 1. Around the declared native method, see if there is anywhere that a native library is loaded. This will provide guidance of what native library to look in for the function to be implemented.
187 | 1. Extract the native library from the APK by creating a new dir and copying the APK into that folder. Then run the command `unzip Mediacode.APK`. You will see all of the files extracted from APK, which includes the `lib/` directory.
188 | 1. Select the architecture of the native library you'd like to analyze.
189 | 1. Start ghidra by running `ghidraRun`. This will open Ghidra.
190 | 1. To open the native library for analysis, select "New Project", "Non-Shared Project", select a path to save the project to and give it a name. This creates a project that you can then load binary files into.
191 | 1. Once you've created your project, select the dragon icon to open the Code Browser. The go to "File" > "Import File" to load the native library into the tool. You can leave all defaults.
192 | 1. You will see the following screen. Select "Analyze". 
193 | 1. Using the linking information above, identify the function in the native library that is executed when the Java-declared native method is called.
194 |
195 | #### Solution
196 |
197 |
198 |
199 | ## Reversing Android Native Libraries Code - JNIEnv
200 |
201 | When beginning to reverse engineer Android native libraries, one of the things I didn't know I needed to know, was about `JNIEnv`. `JNIEnv` is a struct of function pointers to [JNI Functions](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html). Every JNI function in Android native libraries, takes `JNIEnv*` as the first argument.
202 |
203 | From the Android [JNI Tips](https://developer.android.com/training/articles/perf-jni) documentation:
204 | > The C declarations of JNIEnv and JavaVM are different from the C++ declarations. The "jni.h" include file provides different typedefs depending on whether it's included into C or C++. For this reason it's a bad idea to include JNIEnv arguments in header files included by both languages. (Put another way: if your header file requires #ifdef __cplusplus, you may have to do some extra work if anything in that header refers to JNIEnv.)
205 |
206 | Here are some commonly used functions (and their offsets in JNIEnv):
207 | * JNIEnv + 0x18: jclass (\*FindClass)(JNIEnv*, const char*);
208 | * JNIEnv + 0x34: jint (\*Throw)(JNIEnv*, jthrowable);
209 | * JNIEnv + 0x70: jobject (\*NewObject)(JNIEnv*, jclass, jmethodID, ...);
210 | * JNIEnv + 0x84: jobject (\*NewObject)(JNIEnv*, jclass, jmethodID, ...);
211 | * JNIEnv + 0x28C: jstring (\*NewString)(JNIEnv*, const jchar*, jsize);
212 | * JNIEnv + 0x35C: jint (\*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*, jint);
213 |
214 | When analyzing Android native libraries, the presence of JNIEnv means that:
215 |
216 | 1. For JNI native functions, the arguments will be shifted by 2. The first argument is always JNIEnv*. The second argument will be the object that the function should be run on. For static native methods (they have the static keyword in the Java declaration) this will be NULL.
217 | 2. You will often see indirect branches in the disassembly because the code is adding the offset to the JNIEnv* pointer, dereferencing to get the function pointer at that location, then branching to the function.
218 |
219 | Here is a [spreadsheet](https://docs.google.com/spreadsheets/d/1yqjFaY7mqyVIDs5jNjGLT-G8pUaRATzHWGFUgpdJRq8/edit?usp=sharing) of the C-implementation of the JNIEnv struct to know what function pointers are at the different offsets.
220 |
221 | In practice, in the disassembly this shows as many different branches to indirect addresses rather than the direct function call. The image below shows one of these indirect function calls. The highlighted line in the disassembly shows a `blx r3`. As reversers, we need to figure out what r3 is. It's not shown in the screenshot, but at the beginning of this function, `r0` was moved into `r5`. Therefore, `r5` is `JNIEnv*`. On line 0x12498 we see `r3 = [r5]`. Now `r3` is `JNIEnv` (no *).
222 |
223 | On line 0x1249e, we add 0x18 to `r3` and dereference it. This means that `r3` now equals whatever function pointer is at offset 0x18 in JNIEnv. We can find out by looking at the spreadsheet. `[JNIEnv + 0x18] = Pointer to the FindClass method`
224 |
225 | Therefore `blx r3` on line 0x124a4 is calling `FindClass`. We can look up information about `FindClass` (and all the other functions in JNIEnv) in the JNIFunctions documentation [here](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html).
226 |
227 | 
228 |
229 | Thankfully, there's a way to get the JNI function without doing all of this manually! In both the Ghidra and IDA Pro decompilers you can re-type the first argument in JNI functions to `JNIEnv *` type and it will automatically identify the JNI Functions being called. In IDA Pro, this work out of the box. In Ghidra, you have to load the JNI types (either the jni.h file or a Ghidra Data Types archive of the jni.h file) first. For ease, we will load the JNI types from the Ghidra Data Types archive (gdt) produced by Ayrx and available [here](https://github.com/Ayrx/JNIAnalyzer/blob/master/JNIAnalyzer/data/jni_all.gdt). For ease, this file is available in the VM at `~/jni_all.gdt`.
230 |
231 | To load it for use in Ghidra, in the Data Type Manager Window, click on the down arrow in the right-hand corner and select "Open File Archive".
232 |
233 | 
234 |
235 | Then select `jni_all.gdt` file to load. Once it's loaded, you should see jni_all in the Data Type Manager List as shown below.
236 |
237 | 
238 |
239 | Once this is loaded in Ghidra, you can then select any argument types in the decompiler and select "Retype Variable". Set the new type to JNIEnv *. This will cause the decompiler to now show the names of the JNIFunctions called rather than the offsets from the pointer.
240 |
241 | 
242 |
243 | ### Exercise #6 - Find and Reverse the Native Function
244 | We are going to point all of our previous skills together: identifying starting points for RE, reversing DEX, and reversing native code to analyze an application that may have moved its harmful behaviors in native code. The sample is `~/samples/HDWallpaper.apk`.
245 |
246 | #### Goal
247 | The goal of this exercise is to put all of our Android reversing skills together to analyze an app as a whole: its DEX and native code.
248 |
249 | #### Exercise Context
250 | You are a malware analyst for Android applications. You are concerned that this sample maybe doing premium SMS fraud, meaning that it sends an SMS to a premium phone number without disclosure & user consent. In order to flag as malware, you need to determine if the Android application is:
251 |
252 | 1. Sending an SMS message, and
253 | 1. That SMS message is going to a premium number, and
254 | 1. If there is an obvious disclosure, and
255 | 1. If the SMS message is only sent to the premium number after user consent.
256 |
257 | #### Instructions
258 | Go on and reverse!
259 |
260 | #### Solution
261 |
262 |
263 |
264 | [**NEXT** > 6. Reverse Engineering Android Apps - Obfuscation](obfuscation.html)
265 |
266 |
--------------------------------------------------------------------------------