Malicious Ukrainian themed DELTA Android Application Analysis
Reverse engineering a Ukrainian themed malicious Android application
I was able to retrieve the sample from my previous blog, where I identified a likely malicious Ukrainian themed APK.1 In this blog we dive deeper into the sample and infrastructure associated with the malware. The initial blog indicates correctly that it correlates from code freely available online via a Russian cybercrime forum.2 We identify a C2 which is based in Ukraines IP assignment and analyse the functionality of the malicious APK.
Analysis
Filename: DELTA.mil.gov.ua (РФ).apk
SHA256 Hash: 827d77be9a145df7826558ec62fdefb1609827001f182b6b900511109858c80f
Size: 9133663 bytes (8.7MB)
Description: Malicious Android Application
File Format: APK
File Submission Date: 26-02-2025 16:38:05
We start our static analysis, reviewing the signing certificate associated with the sample. We observe the sample was likely compiled in January 2025. Previously we observed this from the sandbox but can now confirm the sample has been parsed correctly:
Type: X.509
Version: 1
Serial number: 0x1
Subject: C=US, O=Android, CN=Android Debug
Valid from: Tue Jan 14 11:38:18 GMT 2025
Valid until: Thu Jan 07 11:38:18 GMT 2055
Public key type: RSA
Exponent: 65537
Modulus size (bits): 2048
Modulus: 24113345786077045726601397938226377303172432070326925522249560744716261559237261219387352112385841421754275582687671986254256427510864102976282441991100882185433611765726173077928809127924603621622691705625586489763416607393545489724498016487523164887089634076674306931524956357752180527795501931524946394601744506145251609059304806063981301229252450971476076701755488854090596831894973729627317077371681859744262311366373313510043025224189331574027097934979284086140711897803758839073678829421875516201109247884137859138976783309196758917634715707722250368403911120121316305625768171865322904046689498761842423051559
Signature type: SHA256withRSA
Signature OID: 1.2.840.113549.1.1.11
MD5 Fingerprint: 07 8E 6A D6 DA 31 D4 33 65 D3 93 05 5D 04 37 59
SHA-1 Fingerprint: 1E 46 8C CF 4B CC 8F C8 78 DC 1C 3E 83 80 B7 6E 6B 1A 55 50
SHA-256 Fingerprint: 3B 4B 2F 55 D0 25 53 39 0A 67 49 5D 35 90 9F 94 DB 24 CE 59 0A 0A B0 35 AF F8 EF 53 01 BC C9 20
The following permissions are used by the Android application indicating it wants to communicate to the internet, read contacts and access to the filesystem.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
Throughout the Android applications manifest, we identify regular references to the online code example ‘GallGrab’. References identified are:
Custom user permission called xss.nmz.gallgrab_nmz.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
Theme called @style/Theme.GallGrabNMZ
Android application entrypoint called xss.nmz.gallgrab_nmz.MainActivity
Android manifest name called xss.nmz.gallgrab_nmz
Initialisation startup provider called xss.nmz.gallgrab_nmz.androidx-startup
The following libraries are imported by the threat actor according to decompilation results:
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.MediaStore;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
The entrypoint activity class OnCreate method3 checks the application has the targeted permissions using ContextCompat.checkSelfPermission().4 The following permissions are checked:
android.permission.READ_EXTERNAL_STORAGE
android.permission.READ_CONTACTS
These permissions were expected to be checked as we observed them in the Android manifest, if the result of the permission check is that they aren’t given, the android application will request them via ActivityCompat.requestPermissions() using the request code 100. If the permissions are already available the application will go straight to data exfiltration via a method called startZipAndSendTask() as shown in Figure 1.
The application contains a handler for when context is changed to allow permissions, the handler verifies if the request code is 100. If the permissions have been granted, it too will start the method startZipAndSendTask().
The malicious android application utilises in most of its methods the executorService, a task provider with the ability to execute tasks asynchronously.5 This task provider is used throughout to gain results of activity, however, the power of the service is not fully utilised - often opting for essentially single threaded collection of results. It is unclear why the threat actor has not utilised the executorService.
The startZipAndSendTask function will use the ContentResolver class6 to query about the Android systems file storage, specifically:
Images (MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
Videos (MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
General files (MediaStore.Files.getContentURI)
The application will exit if it identifies that there are not any images, videos and files present on the system. If there are, the application will begin collecting the paths of images, videos and files on the phone. The malicious android application is specifically interested in files, shown in Figure 2, from the following directories:
/Downloads/
/Download/
/download/
/downloads/
/Documents/
/documents/
/artmap/
/resources/
/res/
After finding media or file content, the android application will also attempt to find contacts using the ContentResolver class (ContactsContract.CommonDataKinds.Phone.CONTENT_URI). The malware will log the name and phone number in the following format:
name: 01234567890
The malware will concatenate with new lines as delimiters between different contacts.e.g:
name1: 01234567890
name2: 09876543210
The contacts from the phone will be saved into a statically named log file named message.txt. Every media, file, video or contact item is compressed into a zip called images.zip which is stored in the cache directory. The malware will zip and send one item at a time to the C2, this makes forensic recovery difficult on the phone due to the constant rewriting of the same file location and storage being in the cache directory. The cache directory will start automatically deleting files when disk space is needed and is seen as a temporary files directory in the Android operating system.
C2 communication is done via HTTP POST as shown in Figure 3, which is a different implementation to the original code which used raw sockets to communicate. The code is expecting a response code and body, indicating its interacting with some form of HTTP server. The C2 server is located in Ukraine by a hosting provider called VIKHOST (AS207560) on a non-standard application port.
Infrastructure Analysis
Online port scanning services indicate that Apache and nginx services were deployed between the 14th-15th January 2025 on the C2 IP. The following ports were observed to be open:
14th January port 80:
HTTP/1.1 200 OK
Date: Tue, 14 Jan 2025 02:26:31 GMT
Server: Apache/2.4.62 (Debian)
Last-Modified: Thu, 12 Dec 2024 00:28:27 GMT
ETag: "29cd-62907cafe80f1"
Accept-Ranges: bytes
Content-Length: 10701
Vary: Accept-Encoding
Content-Type: text/html
14th January port 81:
HTTP/1.1 503 Service Temporarily Unavailable
Server: nginx
Date: Tue, 14 Jan 2025 16:32:30 GMT
Content-Type: text/html
Content-Length: 592
Connection: keep-alive
15th January port 9090:
HTTP/1.1 301 Moved Permanently
Content-Type: text/html
Location: https[:]//46.229.55[.]57/
These dates align with the initial compilation time of the android application, unfortunately the port scanning services did not identify a banner response on port 41010 (the C2 port). In my assessment it is probable that these services are associated with the threat actor and can be used for pivoting purposes.
Analysis of the infrastructure from this threat continues outside the scope of this blog.
Indicators of Compromise (IoC)
Network indicators likely valid between 14th January 2025 - 2nd February 2025:
46.229.55[.]57
827d77be9a145df7826558ec62fdefb1609827001f182b6b900511109858c80f
https://threatintelligence.substack.com/p/malicious-delta-themed-android-app
https://lolz.live/threads/7713628/
https://dagger.dev/hilt/android-entry-point.html
https://developer.android.com/reference/androidx/core/content/ContextCompat#checkSelfPermission(android.content.Context,java.lang.String)
https://developer.android.com/reference/java/util/concurrent/ExecutorService
https://developer.android.com/reference/android/content/ContentResolver