This is where I stopped my exploration. It is super useful to have the decompiled source code available even if it isnt in a functional state. Also note the This is unacceptable message from the first method of the class, private void a. There was one method that was calling this getMd5Digest method and another that outputted the actual API URL with the query parameters. Nevertheless, it was time for some hard-earned rest. Angr is written in Python 2 and available from PyPI.

This will allow you to temporarily shuffle register values, do your debugging, and then put the original register values back. The following command logs all translated blocks to a file: Unfortunately, it is not possible to generate a complete guest instruction trace with QEMU, because code blocks are written to the log only at the time they are translated not when theyre taken from the cache. To fix this, make sure you run mitmproxy with the block_global flag set to false: mitmproxy --set block_global=false. Note: Even with ro.debuggable set to 1 in default.prop, an app won't show up in the "debug app" list unless the android:debuggable flag is set to true in the Manifest. It is also really useful to use. Now you can set breakpoints and attach to the Uncrackable1 app process using the "Attach Debugger" button on the toolbar. This can complicate things for reverse engineers (to be fair, there might also be legitimate reasons for using JNI, such as improving performance or supporting legacy code).

After you choose the Uncrackable1 application from the list, the debugger will attach to the app process and you will hit the breakpoint that was set on the onCreate() method. To use Xposed, you first need to install the Xposed framework on a rooted device.

I used to assume that you can simply recompile a decompiled APK and it would work. This will generate an application-aligned.apk file. This results in the package name "sg.vantagepoint.uncrackable1", which matches the original package name.

If you learned something new in this post please subscribe to my weekly newsletter (scroll a bit further for the form) or the RSS feed for the website. This is the perfect time to use JADX to decompile the APK. Besides being great for function tracing, KProbes can be used to implement rootkit-like functionality such as file hiding. Then, terminate and re-launch the app. DroidScope - an extension to the DECAF dynamic analysis framework [20] - is a malware analysis engine based on QEMU.

Execute gdbserver to attach to the suspended app.

Your breakpoint should be hit when the first instruction of the JNI function is executed. Author, Blogger & artist who can't make up his mind.

Strace is a standard Linux utility that is used to monitor interaction between processes and the kernel. Congratulations - you just learned the fundamentals of static analysis! However, dealing with both Java and native code can make things more complicated at times. Frida gives you the possibility to solve the OWASP UnCrackable Crackme Level 1 easily. tracing_on: Echo 1 into this file to allow/start update of the ring buffer. On Mac OS, the same can be achieved with the greadelf tool, which you can install via Macports or Homebrew.

Just give it the APK and it will give you a zip file containing the decompiled source. It's pretty much standard Linux fare. Each basic block of guest instructions is disassembled and translated into an intermediate representation called Tiny Code Generator (TCG). We are gonna do the next best thing and decompile the APK into smali code.

I had recently learned that I could use a certain app to get step-by-step solutions to my problems.

The following commands will be super useful in those cases: This is moving the object reference from vy to vx and back. This method passes the user input to a static method called a.a, which returns a boolean value.

In general, these tools are backward-compatible, so you need only one version of those installed. The code wasnt all that hard to modify but it took me an embarrassingly long time to figure out the correct statements to insert in smali. Specifically a Pixel 3XL emulator image with API 28 and Android Oreo. This gives you a really unfair advantage, because most integrity checks and anti-tampering features ultimately rely on services performed by the kernel. JDWP is a standard debugging protocol that is supported by all command line tools and Java IDEs, including JDB, JEB, IntelliJ and Eclipse.

That way we can be sure that no original code in the method is using the new register. am commenting to let you know how useful your tutorial has been to me, and am sure to many people as well. Starting from loc_17DC, we see a series of comparisons of the decoded values with values obtained from further sub-function calls. Othervise, it might get complicated to identify which line will be executed next. My browser isn't connecting to public WiFi! Once a method breakpoint is hit, you will get the chance to single step throughout the method execution. We don't want the process to resume immediately though, so we pipe the suspend command into JDB as follows: Next, we want to suspend the process at the point the Java runtime loads libnative-lib.so. Echoing 0 will prevent further writes into the ring buffer.

To list the public methods of the android.view.View class you could create a wrapper for this class in Frida and call getMethods() from its class property: Besides loading scripts via frida CLI, Frida also provides Python, C, NodeJS, Swift and various other bindings. To support both older and newer ARM processors, Android apps ship with multple ARM builds compiled for different Application Binary Interface (ABI) versions. If you are interested, I highly recommend you to take a look at this wonderful presentation about Android code injection.

This had to be changed but it took a long time for that to happen. Run the following command, or add it to your .bash_profile or other startup script. It contains new stuff that I make, links You can find the function prototypes for all system calls in the kernel header file arch/arm/include/asm/unistd.h. By making some changes to this file, we can make the Android environment a bit more reverse-engineering-friendly. Quite the contrary.

Practical Python Projects book is now available! It is based on QEMU, a generic and open source machine emulator. This is where I needed a log statement (or so I thought).

In addition to the newly built kernel and the original ramdisk, specify the kernel offset, ramdisk offset, tags offset and commandline (use the values listed in your previously extracted bootimg.cfg). sys_call_table = (void*)0xc000f984; If you look into the lib directory of the APK archive, you'll see a total of eight subdirectories named after different processor architectures. Firstly, I changed .locals 6 to .locals 7. The original aims were to figure out how the sig hash was being generated and how to reverse-engineer the API to make custom query calls. Before booting into the new Kernel, make a copy of the original boot image from your device. The openat system call is defined in unistd.h which is found in the kernel sources: The final piece of the puzzle is the address of our replacement-openat. I was excited. It converts an APK file into a human-readable Java output.

I have adapted the code from Dong-Hoon Yous Phrack article [19] for this purpose - however, I used the file interface instead of mmap(), as I found the latter to cause kernel panics for some reason. The main function is located at address 0x1874 in the disassembly (note that this is a PIE-enabled binary, and IDA Pro chooses 0x0 as the image base address). With its capable disassembler and powerful scripting and extension capabilities, IDA Pro works great for static analysis of native programs and libraries.

} The endpoint returned an invalid signature error even on the slightest change in input: sig was some sort of hash but I wasnt sure what kind or how it was being generated and now this required a little bit of reverse engineering. rooted device submitting JEB [15], a commercial decompiler, packs all the functionality needed for static and dynamic analysis of Android apps into an all-in-one package, is reasonably reliable and you get quick support. A good approach would be to suspend the app at a state where the secret string is stored in a variable in plain text so we can retrieve it.

For navigating the decompiled sources we recommend using IntelliJ [9], a relatively light-weight IDE that works great for browsing code and allows for basic on-device debugging of the decompiled apps. This will help you to speed up your debugging while keeping eye on the return values of the core class functions. It also supports interaction with the Android Java runtime, such as interacting with objects inside the VM. With a little effort you can build a reasonable GUI-powered reverse engineering environment for free. Just like on other Linux-based operating systes, native code is packaged into ELF dynamic libraries ("*.so"), which are then loaded by the Android app during runtime using the System.load method. Seeing the following string in multiple places in the decompiled output gave me a good chuckle: So what are our options if JADX doesnt work? Enter "Uncrackable1" as the application name and "vantagepoint.sg" as the company name. For example, you could call it "Validator" (you can always revise the name later as you learn more about the class). Most importantly, it also supports Android guests and some of the DroidScope code has even been ported over. Was the processing happening on the phone?

I had always wanted to learn how to reverse engineer Android apps. Note the last part of the program where the final input string is obtained - it appears if we were simply reading the solution from memory. Even though it is possible to work with a completely free setup, you might want to consider investing in commercial tools. With this modification, no certificate checks are performed, and the application will accept all certificates. Rather, we'd like to keep it suspended so we can do some exploration first. Execute the resume command in JDB to resume execution of the Java runtime (we're done using JDB, so you can also detach it at this point). Lets suppose our APK is called application.apk. Another very useful tool built on QEMU is VxStripper by Sbastien Josse [22]. An Xposed module that overrides the function to always return "false" looks as follows. We need to provide several inputs to the symbolic execution engine: The address to start execution from. I send it out every other month. Xposed is a "framework for modules that can change the behavior of the system and apps without touching any APKs" [24]. [7] apkx - APK Decompilation for the Lazy -, [18] NetSPI Blog - Attacking Android Applications with Debuggers -, [19] Phrack Magazine - Android Platform based Linux kernel rootkit. sys_call_table on Android). Of course convenience like this doesnt come cheap - and since version 2.0 JEB has changed from a traditional licensing model to a subscription-based one, so you'll need to pay a monthly fee to use it.

Unfortunately, we won't get that far unless we deal with the root / tampering detection first. You can read more about where smali fits in the compilation life-cycle in this wonderful answer by Antimony on StackOverflow. The method equals of the java.lang.String class is used to compare the input string with the secret. Step into the System.getenv method call y using the "Force Step Into" functionality. This thread is used to allocate a chunk of memory and populate it with a mini-bootstrapper. This is what I came up with: I ran the program and the resulting URL was the same one I was seeing in mitmproxy.

More information on Traceview can be found in the Android Studio user guide. Each version is compiled from the same source and implements exactly the same functionality. No spam, I promise + you can unsubscribe at anytime, Arcus As it turns out it was extremely hard to figure out how the sig parameter was being generated. What's the right version to use depends on both the device architecture and host OS. Native code on Android is packed into ELF shared libraries and runs just like any other native Linux program. Similar to DroidScope, PANDA can be extended by registering callbacks that are triggered upon certain QEMU events. How to learn something is more important than just giving that info. Another issue is that the Android kernel is compiled with strict memory protection which prevents patching some parts of Kernel memory. I had to find out where the &sig= query parameter was being added to in the smali code. You'll be using a JDWP debugger most of the time when debugging "normal" Android apps that don't do a lot of calls into native libraries. This is the final return value, so R0 is left unchanged and the function ends. The string.equals comparison compares our input to arrby2. If you have the Android SDK installed then you already have a debug keystore that you can use to sign an APK. If you're reversing Android apps on a regular basis, building your own reverse engineering sandbox is a no-brainer. So far, we've been using static analysis techniques without ever running our target apps. The onClickListener implementation for the dialog button doesn't to much: It just exits the app. Looks like the base64 string stored in arrby1 in check_input is a ciphertext, which is decrypted using 128bit AES, and then compared to the user input. The app is now going to exit. Running the executable on any Android device should give you the following output. For one, it is simply faster to work on a real device. However, there's also a few Android-specific challenges.

return value. } Jprobes and Kretprobes are additional probe types based on Kprobes that allow hooking of function entries and exits. By reviewing the code, we can gather that the method sg.vantagepoint.uncrackable1.MainActivity.a is responsible for displaying the "This in unacceptable" message box. We can bypass this with a little runtime tampering. I tried modifying the input slightly just to check if the API was even checking the sig parameter. These functions are available to normal processes via the system call interface. You can start exploring the process with GDB. Clicking any of the methods in the profile panel highlights the selected method in the timeline panel.

The crackme takes the form of a native ELF binary that can be downloaded here: https://github.com/angr/angr-doc/tree/master/examples/android_arm_license_validation. The ABI defines how the application's machine code is supposed to interact with the system at runtime. Create an empty project in Android Studio and select "Tools->Android->SDK Manager" to open the SDK Manager GUI. First, we'll look at some simple ways of modifying and instrumenting mobile apps. Why didnt I simply put a debug statement here? If you have built a project in Android Studio before, the IDE has already created a debug keystore and certificate in $HOME/.android/debug.keystore. Nevertheless, even an imperfect debugger is still an invaluable tool - being able to inspect the runtime state of a program makes it a lot easier to understand what's going on. When you start the App on an emulator or a rooted device, you find that the app presents a dialog box and exits as soon as you press "Ok" because it detected root: Let us see how we can prevent this. The process is outlined in a bit more detail below. It should give you a fairly good idea of how APK reverse engineering generally works. If you want to add logging and do something super simple then Smali is fine but for anything more complex you will have to spend a lot of time with the Smali reference manual.

I started my exploration from there. The file "nowyouseeme" is now somewhat hidden from the view of all usermode processes (note that there's a lot more you need to do to properly hide a file, including hooking stat(), access(), and other system calls, as well as hiding the file in directory listings). We'll now set up our JNI demo app, HelloWorld-JNI.apk, for debugging. # Get the solution string from *(R11 - 0x24).

content I create. Once you have done this, "Developer options" will be shown at bottom of the Settings menu. In addition to the picking the right architecture, you need to specify the correct sysroot for the native API level you want to target. hi yasoob! len = strncpy_from_user(kbuf,pathname,255); Consequently, you can debug them using standard tools, including GDB and the built-in native debuggers of IDEs such as IDA Pro and JEB, as long as they support the processor architecture of the device (most devices are based on ARM chipsets, so this is usually not an issue). The MainActivity is found in the file MainActivity.java. The following ABIs are supported: Most disassemblers will be able to deal with any of those architectures.

In 325+ pages I will help you implement 12 end-to-end projects to enhance your Python knowledge.

Verify with the lsmod command that the module has been loaded successfully. This is where user supplied input is compared with the secret string. Make sure that you use an emulator Android image without Google Play. QEMU-specific parameters can be passed to the emulator with the -qemu command line flag. Voil!

The original, hijacked thread is restored to its original state and resumed, and execution of the process continues as usual.

The system should now boot normally. Using DDMS is a bit confusing however: It can be launched in several ways, and different trace viewers will be launched depending on how the trace was obtained.

In the following section, we'll show how to solve UnCrackable App for Android Level 1 using JDB only. In mobile app-sec however, the term is used rather loosely to refer to all kinds runtime manipulation, including overriding methods to change behavior. You can find a detailed solution on StackOverflow. Unfortunately, the Android VM doesn't support all available JDWP features. By instrumenting QEMU's dynamic binary translation mechanisms, it dynamically extracts an intermediate representation of a binary. You can modify the variable content by pressing F2 or Right-Click and "Set Value". To help with this problem, the bytecode can be patched to deactivate SSL pinning. For hacking purposes, I recommend using an AOSP-supported device. For convenience, you can export an environment variable that points to your toolchain directory - we'll be using this in the examples later. As a bonus task, try to decrypt the extracted ciphertext and get the secret value! move-result v2 moves the return value of this method call to the v2 register. This is typically the configuration on Android devices shipped to end users. Besides being useful for debugging, the JDB command line tool also offers basic execution tracing functionality. I tried the app and it worked! The result is printed to the console: Notice that you can also make use of Java's reflection capabilities. This is my favorite website now. This pointer points to a function table - an array of even more pointers, each of which points to a JNI interface function (is your head spinning yet?). Make sure that the following is installed on your system: The newest SDK Tools and SDK Platform-Tools packages. a.a now becomes Validator.a. To work with Frida interactively, you can use frida CLI which hooks into a process and gives you a command line interface to Frida's API. arm64-v8a: ABI for ARMv8-based CPUs that support AArch64, the new 64-bit ARM architecture. arrby2 is the return value of the function sg.vantagepoint.a.a.a. More elaborate tasks such as program analysis and automated de-obfuscation can be achieved with open source reverse engineering frameworks such as Radare2 [13] and Angr [14]. Frida injects a complete JavaScript runtime into the process, along with a powerful API that provides a wealth of useful functionality, including calling and hooking of native functions and injecting structured data into memory. Alternatively, Sonys Xperia series is also known for its openness. To quickly verify that the correct kernel is running, navigate to Settings->About phone and check the kernel version field. All of this makes it possible to build tracers that are practically transparent to the target application (as long as we can hide the fact it is running in an emulator). for this wonderfull info. It comes as part of the Android SDK. Tampering means making patches or runtime changes to the app to affect its behavior - usually in a way that's to our advantage.

The adb jdwp command lists the process ids of all debuggable processes running on the connected device (i.e., processes hosting a JDWP transport). I used an Android Emulator for this step. You'll end up with a structure that resembles the original Android Studio project from which the app was built. I was able to accomplish both of those aims and my curiosity was satisfied. After execution of the basic block has completed, QEMU repeats the process for the next block of guest instructions (or loads the already translated block from the cache). So we're looking for a 16 character base32-encoded string! Entering ? First, we resume execution of the Java VM by attaching JDB. Thanks bro. You can find some additional examples in the "case studies" section in the Bernhard Mueller's Hacking Soft Tokens Paper [27]. The remaining anti-tampering and anti-debugging controls can be defeated in similar ways to finally reach secret string verification functionality. The onClick event handler on the "OK" button is what actually terminates the app. But where do we get it? In the next dialog, pick any API number - we don't want to actually compile the project, so it really doesn't matter. If the output of apktool d application.apk was ~/application then simply go to ~ (your home folder) and run: This will generate an application.apk file in the ~/application/dist folder. Technically, it is an extended version of Zygote that exports APIs for running Java code when a new process is started.

No need for learning how to reverse-engineer the app. For example, if a block is repeatedly executed in a loop, only the first iteration will be printed to the log. The app does not exit anymore. Take care and I will see you in a future article! The JNI function java_sg_vantagepoint_helloworldjni_MainActivity_stringFromJNI() should be listed as a non-debugging symbol. Conveniently, CFR has been released under a MIT license, which means that it can be used freely for any purposes, even though its source code is not currently available. It's the same APK you downloaded in "Statically Analyzing Native Code". This is a classical Linux rootkit technique and has been described for Android by Dong-Hoon You [1].

Strace however depends on the ptrace() system call to attach to the target process, so it only works up to the point that anti-debugging measures kick in. In our case for example, this means that the programmer must have implemented the following C or C++ function: So where is the native implementation of this function?

The standard way is through the APIs of the Android Application Framework. Of course, this only works if a native library is loaded that exports a global symbol with the expected signature. On Linux systems, you can retrieve the list of symbols using readelf (included in GNU binutils) or nm. To get this working, we'll first use JDB to gently control the process into the state we need. Install it as follows: This should copy apkx to /usr/local/bin. Click the stop button to stop recording, after which the Traceview tool will open showing the recorded trace. To record an execution trace in Android studio, open the "Android" tab at the bottom of the GUI. Frida also lets you search for instantiated objects on the heap and work with them. In fact, this is the default app Android generates when you create a new project with C/C++ support - enough however to show the basic principles of how JNI calls work.

In order to defeat this control, you can modify the directory names (parent) or file name (child) at cycle which would otherwise detect the su binary on your device. This modification breaks the code signature, so you'll also have to re-sign the the altered APK archive. Monday, Aug 10, 2020 at 11:24 UTC, YasoobIn reply to Khalid Nuur

owasp tsvetelin However, instead of relying on widely used C libraries such as glibc, Android binaries are built against a custom libc named Bionic [17]. The address of the code block we want execution to reach.

It might be a good approach to "Force Step Into" once you reach the decompiled sources and "Step Out" of the core Java and Android classes.

We're now ready to attach JDB. This will make sure that your modifications arent the reason why the repacked APK isnt working. Even so, the functionality is sufficient for basic tasks, such as reconstructing the disassembly of a natively executed cryptographic algorithm. This is how the modified code looked like: While I was at it, I added some more debug statements in a couple of additional places in the same file but different methods. CFR is under active development, and brand-new releases are made available regularly on the author's website [6]. That's why it is a good idea to set a breakpoint on the onCreate() method just before the anti-tampering and anti-debugging checks performed. Open the file in IDA Pro. This instruction loads the pc-relative offset of the string "Hello from C++" into R1. It does this by translating the programs semantics into a logical formula, whereby some variables are represented as symbols with specific constraints. Restart the device in fastboot mode with the following command: Then, use the "fastboot boot" command to boot Android with the new kernel. The method verify is what's called when you tap on the "verify" button. An interface pointer is a pointer to a pointer.

To demonstrate how Certificate Pinning can be bypassed, we will walk through the necessary steps to bypass Certificate Pinning implemented in an example application. In those scenarios, you have to be a bit more creative and do some register shifting. Monday, Aug 31, 2020 at 22:36 UTC. current_tracer: This file is used to set or display the current tracer. The following example uses greadelf: This is the native function that gets eventually executed when the stringFromJNI native method is called. This is just to give you an idea of what to expect.

To install Frida locally, simply use Pypi: Your Android device doesn't need to be rooted to get Frida running, but it's the easiest setup and we assume a rooted device here unless noted otherwise. This script completely automates the process of extracting Java code from release APK files and makes it easy to experiment with different backends (we'll also use it in some of the examples below). sungju