DSLA Protocol x Satoshi Club AMA Recap from 21th of December

A decentralized alternative service level agreement. Use DSLA to hedge against staking risks, and earn rewards for protecting staking deposits! Welcome to another episode of our AMA series. Today we…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Hacking Android app with Frida

Even if Frida is pretty easy to use, there are some steps you will need to take to make it work.

To achieve it all pretty easly and cheap, I just used emulator :) with following details:

To install Frida on your PC just go to console and type pip install frida

Notice that you wont get any info in console, it will just start running. Every other command should be run from separate terminal. It’s also a good idea to open logcat in separate terminal with adb logcat.

We are all good to go :) Let’s check if Frida on PC is getting along with Frida-server on device: frida -U asvid.github.io.fridaapp - It’s necessary to know full app package name, and to have app running on device. Flag -U tells Frida to check the USB connected device, or in my case, Android emulator.

Console should now look like that:

We are officially in. Now we can type commands here and our target app should obey. Lets just do something simple: Java.androidVersion will just return in console which Android is our device running. Pretty…lame. Lets run something better: Java.perform(function(){Java.enumerateLoadedClasses({"onMatch":function(className){ console.log(className) },"onComplete":function(){}})}) - now we are printing name of every object that Dalivik has created. And if we have object instance, maybe we can run its methods? We’ll get to that shortly.

Running frida commands in console is a bit annoying, it’s extremely easy to mistype or forget to close some braces. Other way is to write script to file and run it by Frida. frida -U -l script.js asvid.github.io.fridaapp It can be even better with Python script that will run JavaScript script. Why we need Python and JavaScript if we want to hack app written in Java or Kotlin compiled to bytecode and that runs on Dalvik Virtual Machine? Well Python is just to make it easer to run JavaScript files, that will fool Dalvik to run them instead of app instructions.

If we look into script.py we can see that it does similar thing as we did in console, it looks for pid for our app package and attatches JavaScript file to run with it. All hacking JavaScript files are already listed there. To run this script just type python script.py.

Interesting thing is that we can still use this.sum() - it’s because we haven’t change original method or class, we just told Dalvik to run our JavaScript instead. In this case we are printing in console original method parameters and then run it with completely others, and return value.

We’ve changed method implementation, but we still needed app to run method, it’s because we didn’t have access to actual object. But we can have it, why not, we are world class hackers at this point. In file instance.js we use a bit different method Java.choose() that looks for loaded objects and selects one with fitting name.

Method takes two callbacks: called when instance is found and other called when method is completed. In first callback we get access to instance of class we were looking for, and we can call it’s methods. Remember that it means method will be called when instance is found, not at start of your app, because looking for instances takes a while. So YAY! we’ve showed a toast.

In some apps like Evernote you can set internal PIN to protect your data from unwanted access. It means PIN has to be stored locally on your device, encrypted and hashed. When user provides PIN you just compare hashes, so no plain text PIN is available at any point. In FridaApp I’ve provided just simple method that checks if PIN is “1234”, but image that its reading hash from SharedPreferences and compares it with hashed user input. No matter what security precautions you take, at the end of a day you want method that takes a String and returns a Boolean. Lets hack it! In brutal.js we have our PIN destroyer. At first we need instance of class that contains PIN checking method. Than we can run this method for diferent PIN numbers and check which one returns true. I’ve done it in a loop that iterates from 0 to 100000, so it covers all 5 digit PIN numbers. Loop stopes when method returns true and prints number in console along with time it took.

Yes in console you can use | grep asvid but its usefull to do it inside script in case you would need to use it further.

All previous scripts were working arount MainActivity class or instance, it’s safe to assume 99% of apps has such class. But now since we’ve listed loaded objects we can see there is mysterious Security object loaded. If we check app code, we can see its a field in MainActivity and its used to encode text from input and stores it in SharedPreferences. It’s also used to read and decode this text that is next printed below input. If you check SharedPreferences of sample app it might contain something like that:

Looks serious, but why even bother cracking it when we can read it like it wasn’t even encoded? In script security.js I’m using some old tricks: Java.choose() to find instance of Security class, and running method getPassword() on found instance. I guess that’s why you shouldn’t store passwords at all in your app.

I’m getting a class that I want to create instance of, and just… create an instance. And now I can do whatever I want with this instance. At first script is just printing in console output from methods with same name but different signatures — easy. Then it’s changing both implementations with help of overload() method, because we need to specify which ones implementation we are changing. Finally, script is printing values in public and private field of our SomeClass instance. Private doesn’t really mean anything for us now, script will change its value (which was also final) to anything we want.

Last script is inspired by silly idea, that developers can hide things from users simply checking if APK build is debug or release. Like additional buttons used for testing, app logic changes or logging. Remember that in MainActivity there is a method that runs every second and prints in console result of adding 30 and 50, we were changing this method implementation before. This method uses two types of logging, standard Log.d() and Logger.log(). This second method is checking build type, and prints only for debug. So if you build release app you will see only first log. Script debug.js is at first looking for Logger instance in memory, and then changes its showLogs flag to true, from its original value of kinda isDebug(). And now we get both logs in logcat.

I’ve tried to show some basic functions of Frida with easy to use scripts. Hope you had fun and will experiment on your own apps, I surely will. Real world app would have obfuscated code, so it will be much harder to know which class and method you need to use to achieve what you want, but it will still work the same way. I’m just an Android developer — not really a hacker, or security guru, but learning about Frida forced me to think way more about my apps security. It’s always better to break (and fix) your own app before someone else does it.

This post is based on:

Add a comment

Related posts:

Queue management system structure of stages of a customer service process

A Director of Operations manages limited resources to meet the diverse needs of the organization. Depending on the quality of the management (and available resources), the waiting time (of customers…

Erasing memories

The waves of words exchanged, experiences shared, connections made, promises made and broken, anger unleashed, kindness retracted — all the good and bad, I wish I could erase them all much like in…

Infografik zum Wandel der Digitalisierung in der Mitarbeiterkommunikation

HOFFMANN UND CAMPE X hat gemeinsam mit juptr.io eine spannende Infografik zum Thema “Wandel der Digitalisierung in der Mitarbeiterkommunikation” veröffentlicht. Über diese spannende Zusammenstellung…