{
	"id": "289ddb4f-e0ec-4f18-af0b-a7016ab5de0e",
	"created_at": "2026-04-06T00:08:45.367422Z",
	"updated_at": "2026-04-10T03:30:33.448669Z",
	"deleted_at": null,
	"sha1_hash": "51c631a64b53c084c8617b648f20d06f3e8da338",
	"title": "Geost: Anatomy of the Android Trojan Targeting Russia",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1968842,
	"plain_text": "Geost: Anatomy of the Android Trojan Targeting Russia\r\nBy By: Vit Sembera Mar 05, 2020 Read time: 8 min (2271 words)\r\nPublished: 2020-03-05 · Archived: 2026-04-05 19:39:17 UTC\r\nThe Android banking trojan Geost was first revealed in a research by Sebastian García, Maria Jose Erquiaga and\r\nAnna Shirokova from the Stratosphere Laboratoryopen on a new tab. They detected the trojan by monitoring\r\nHtBot malicious proxy network. The botnet targets Russian banks, with the victim count at over 800,000 users at\r\nthe time the studyopen on a new tab was published in Virus Bulletin last year.\r\nThe research disclosed the types of information that Geost (detected by Trend Micro as AndroidOS_Fobus.AXM)\r\nsteals from victims, as well as the activities of the group behind the botnet, including operational tactics and\r\ninternal communication between masters and botnet coders.\r\nBuilding upon this interesting finding, we decided to dig deeper into the behavior of Geost by reverse engineering\r\na sample of the malware. The trojan employed several layers of obfuscation, encryption, reflection, and injection\r\nof non-functional code segments that made it more difficult to reverse engineer. To study the code and analyze the\r\nalgorithms, we had to create Python scripts to decrypt strings first.\r\nInitial Analysis\r\nGeost hides in malicious apps that are distributed via unofficial web pages with randomly generated server\r\nhostnames. The victims usually encounter these as they look for apps that are not available on Google Play, or\r\nwhen they don’t have access to the app store. They then find a link to that application on some obscure web\r\nserver, download the app, then launch it on their phones. The app will then request for permissions that, when the\r\nvictims allow, enables malware infection.\r\nThe Geost sample we analyzed resided in the malicious app named “установка” in Russian, which means\r\n“setting” in English. The app showed a version of the Google Play logo as its own icon, which did not appear on\r\nthe phone screen after launch.\r\nFigure 1. Application icon of the malicious app установка\r\nWhen the app was launched, it requested device administrator privileges. This was unusual since legitimate apps\r\ndon’t often ask for this, as it basically gives an app complete rights over a device.\r\nImportant permissions that the user might unknowingly allow include those for accessing SMS messages,\r\nincluding confirmation messages from banking apps. These messages allow the malware to harvest the victims’\r\nnames, balances, and other bank account details. With just a few clicks, attackers can then transfer money from the\r\nbank accounts of unaware victims.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 1 of 20\n\nFigure 2: Screen that requests device admin permission\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 2 of 20\n\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 3 of 20\n\nFigure 3: Application permissions requested\r\nAfter confirming necessary permissions, the visible part of the app will close and the app icon disappears, making\r\nvictims think that the app was deleted. The sample device did not show any alarming signs of malicious activity at\r\nfirst, but the malware is working in the background and the attackers just gained access to the device, allowing\r\nthem to monitor sent and received messages, including SMS confirmation messages from banking apps.\r\nTo maintain persistence across reboots, it registers for BOOT_COMPLETED and QUICKBOOT_POWERON\r\nbroadcasts.\r\nFigure 4: Registering services to boot broadcasts (some codes were obfuscated)\r\nStage One\r\nLike many malware types, Geost’s run-time life is split into stages. The first stage is small and simple, which will\r\nthen download and/or decrypt and run the next stage, which is more complex.\r\nThe Geost sample’s APK housed compiled Java code in classes.dex file. It also contained AndroidManifest.xml\r\nand resource files, which are usual contents of APK files. It also had a “.cache” file with a size of 125k.\r\nTo decompile the extracted classes.dex file, several Java decompilers, namely dex2jar, jadx, jd-core/jd-gui and\r\nGhidra, were all used, as no single decompiler was able to decompile all the Smali code.\r\nFigure 5: Decompiled Java source code\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 4 of 20\n\nAt first glance, the decompiled code seemed to be partially encoded in a series of strings; however, character\r\nfrequency analysis showed random character usage.\r\nFurther analysis revealed that the malware contained additional pieces of code that have no impact on the app’s\r\nbehavior except to slow down its execution. It made reverse engineering more difficult because the malware split\r\nuseful code into parts and frequently changed execution paths. Which branch was taken was usually dependent on\r\nsome variable with an unknown value. The same is applied with “switch”, “if”, and “try/catch” command blocks.\r\nFunctions without meaningful code were inserted to make overall understanding of the malware actions harder.\r\nFigure 6: Example of code with case switch\r\nThe non-functional code segments were gradually removed and the first decryption algorithm used was identified.\r\nAll strings in stage one were encrypted through RC4, using an algorithm that was split into several functions to\r\navoid indication that it used RC4. After this, the next step was to find the key for RC4 decryption.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 5 of 20\n\nFigure 7: Decompiled Java source, which is part of the RC4 algorithm\r\nFigure 8: Part of cleaned up RC4 code\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 6 of 20\n\nFigure 9: RC4 key\r\nRC4 is a stream cipher, with an internal state that changes with every decrypted symbol. To decrypt several\r\nencrypted strings, usually the decryption must be performed in the very same order the encryption used.\r\nFortunately, this was not the case with the sample. The code authors simplified RC4 without keeping internal state\r\nbetween decryptions, as the RC4 encryption code always copied state array S[].\r\nFigure 10: RC4 encryption always copied state array S[]\r\nAfterwards, the search for common code libraries began. Android.support.v4 libraries and ReflectASM Java\r\nReflection libraries were found.\r\nFigure 11: Code with encrypted strings\r\nFigure 12: Code with strings after decryption and symbol deobfuscation\r\nAt this point, the stage one code became understandable: It uses reflection code to hide interesting classes and\r\nmethods from curious eyes. Basically, the first stage decrypted the second stage file with the same RC4 algorithm\r\nand key.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 7 of 20\n\nFigure 13: Example of reflection method invocation\r\nThe aforementioned “.cache” file is renamed to .localsinfotimestamp1494987116 and saved after decryption as\r\nydxwlab.jar, from which the .dex file is loaded and launched.\r\nFigure 14: Decrypting and saving second stage\r\nCode authors inserted a false flag, HttpURLConnection and its URL, which seemed to connect to the Command\r\nand Control (C\u0026C) server. But this http open connection is never executed.\r\nFigure 15: False flag\r\nStage one loads a class from the second stage, which the researcher named “MaliciousClass”.\r\nFigure 16: Launching the second stage\r\nStage Two\r\nLooking at the classes.dex, it’s clear that obfuscation and encryption were used again in stage two. But this time,\r\nthe symbol names were partially replaced by strings 1-2 characters long instead of the previous 6-12 character\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 8 of 20\n\nstrings. Also, the string encryption algorithm is modified, making it different from the algorithm used in the\r\nprevious stage. Different tools were used. Additionally, parameters of the decryption algorithm were modified\r\nseparately for each class.\r\nAll Java decompilers had problems decompiling the decryption algorithm due to goto command jumping into the\r\nif block. Only Jeb decompiler handled this construction well.\r\nFigure 17: Smali code of decryption algorithm\r\nFigure 18: Java code of decryption algorithm\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 9 of 20\n\nEach class decryption method contained different parameter orders and different constants; writing the Python\r\ndecryption script was made more difficult. It meant either the decryption script must detect the algorithm setup\r\nfrom the Smali code and adapt itself, or the parameters must be manually set up within the script before\r\ndecryption for each class.\r\nFigure 19: Example of an encrypted string\r\nAfter string decryption, libraries used could be detected. These include:\r\nAES encryption engine\r\nBase64 encoding\r\nEmulator detector\r\nFile download service\r\nIExtendedNetworkService\r\nUSSD api library\r\nZip4jUtil\r\nInitialization phase\r\nThe aforementioned MaliciousClass invoked from the first stage serves as an envelope for the instantiated class\r\nthe researcher named “Context.”\r\nFigure 20: Context Class\r\nThe Context class launches the EmulatorDetector service first. It then starts two other services: AdminService and\r\nLPService, followed by the main application Intent.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 10 of 20\n\nFigure 21: Main initialization routine\r\nEmulator Detector\r\nThe emulator detector checks for signs that it’s running in an emulated environment. The sample detected the\r\nexistence of Nox, Andy, Geny, Bluestacks and Qemu Android emulators.\r\nFigure 22: Emulated enviroment traces\r\nAdminService\r\nThis service is responsible for granting admin permission to the application. This is a critical part since it enables\r\naccess to sensitive data and can launch privileged actions.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 11 of 20\n\nFigure 23: Critical part of AdminService\r\nLPService\r\nThis service was responsible for keeping the application running and connected to the C\u0026C server. It used\r\nWakeLock and WifiLock acquire() calls to reach this state. A side effect to this is high battery drain, which most\r\nvictims usually ignore.\r\nFigure 24: Locking to CPU and WiFi resources\r\nLPService then creates LPServiceRunnable Thread, which wakes up every five seconds and is responsible for\r\nmonitoring and relaunching these services:\r\nMainService\r\nAdminService\r\nSmsKitkatService\r\nThis service also collects information about running processes and tasks. It also periodically starts\r\nWebViewActivity, which can open browser window to arbitrary URLs or launch malicious code.\r\nWebViewActivity code was not implemented in this sample.\r\nMainService\r\nThe MainService first hooks to AlarmManager for time scheduling tasks, then registers two broadcast receivers,\r\nMainServiceReceiver1 and MainServiceReceiver2. At the end of the initialization phase, it will launch\r\nMainServiceRunnable Thread. When the sample executes overloaded onDestroy() method, it restarts the\r\nMainService again.\r\nFigure 25: Overloaded onDestroy to restart MainService\r\nAn important method of MainService is processApiResponse(), which processes commands formatted as JSON\r\nstring received from C\u0026C server.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 12 of 20\n\nFigure 26: Processing C\u0026C server commands\r\nClearService\r\nThis service invokes the ClearServiceRunnable thread, which takes care of locking/unlocking commands\r\n(blocking/unblocking user activity) so the botnet operator can perform remote tasks without user intervention. The\r\nClearService also relaunches itself if there is an attempt to terminate it.\r\nFigure 27: ClearService class\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 13 of 20\n\nFigure 28: ClearServiceRunnable\r\nSmsKitkatService\r\nThis service was prepared to replace the standard SMS messaging application with a different one written by the\r\nattackers. In this version, it used a default one.\r\nFigure 29: Code for replacement of default SMS application\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 14 of 20\n\nCommands\r\nThe list of commands that this malware recognized can be seen in the table and screenshot below (organized by\r\nthe order they were defined in the code):\r\nCommands Description\r\n#conversations\r\nCollects the address, body, date, and type columns from all SMS messages\r\nfrom content://sms/conversations/, content://sms/inbox and content://sms/sent,\r\nand sends to the C\u0026C server\r\n#contacts\r\nCollects a list of all contacts from content://com.android.contacts/data/phones\r\nand sends to the C\u0026C server\r\n#calls\r\nCollects all calls performed from content://call_log/calls and sends to the C\u0026C\r\nserver\r\n#apps Collects list of installed package names and labels and sends to C\u0026C server\r\n#bhist This command is ignored in this sample\r\n#interval {set:number} Sets time period for fetching C\u0026C server commands\r\n#intercept\r\nSets the phone numbers from which to intercept SMS (“all” or a list of\r\nnumbers)\r\n#send id:, to:, body: Sends SMS\r\n#ussd {to:address,\r\ntel:number}\r\nCalls a number via USSD framework\r\n#send_contacts Sends SMS to all contacts in phonebook\r\n#server Sets scheduled time to run\r\n#check_apps\r\n{path:uri_to_server}\r\nSends a list of running apps to C\u0026C server, downloads archive.zip file from\r\npath defined in parameter as error.zip, and unzip it. Zip archive has password\r\n“encryptedz1p”. Default server name is hxxp://fwg23tt23qwef.ru/\r\n#send_mass {messages:\r\n{to:address, body:text},\r\ndelay:ms}\r\nSends multiple SMS messages to different addresses, with a delay between\r\nsends\r\n#lock\r\nStarts RLA service from ClearServiceRunnable, which intercepts events from\r\nkey press AKEYCODE_HOME, AKEYCODE_CAMERA, and\r\nAKEYCODE_FOCUS. It also intercepts onBackPressed() Activity method,\r\nmutes ringer, clears all SMS notifications, stops itself, and makes the phone\r\nunresponsive\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 15 of 20\n\n#unlock\r\nDisables actions listed under #lock command and unlocks phone by stopping\r\nClearServiceRunnable\r\n#makecall\r\n{number:tel_number}\r\nCalls a number using standard android.intent.action.CALL API\r\n#openurl {filesDir=j:url} Opens a webpage URL\r\n#hooksms\r\n{number:tel_number}\r\nHooks to a number – it forwards all incoming SMS messages to a number in\r\nthe parameter\r\n#selfdelete Sets task time to unparsable string value, which stops its self-scheduling tasks\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 16 of 20\n\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 17 of 20\n\nFigure 30: List of C\u0026C SERVER commands\r\nApiRequest, ApiResponse, ApiInterfaceImpl\r\nThe ApiRequest, ApiResponse, and ApiInterfaceImpl classes enable communication with the C\u0026C server. In the\r\nconnection parameters initialization, the value of replaceWithRandomStr variable was set to true by default and is\r\nnot changed within the code.\r\nFigure 31: Building C\u0026C server connection string\r\nFigure 32: Connection parameters initialization\r\nAn algorithm was used to generate a random string for the C\u0026C server URL. The API connection was then\r\ninitialized, and the hostname of the C\u0026C server was set up.\r\nFigure 33: Building random string for the C\u0026C server URL\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 18 of 20\n\nFigure 34: API connection initialization\r\nFigure 35: Setting up C\u0026C server hostname\r\nAn example of C\u0026C server API usage was shown as the C\u0026C server command “#contacts“ was implemented.\r\nFinally, parameters for commands are appended as JSON format and converted to string.\r\nFigure 36: Example of C\u0026C server API calling\r\nBest Practices and Trend Micro Solutions\r\nIn its 2020 Security Predictionspredictions, Trend Micro predicted the continued proliferation of mobile malware\r\nfamilies, such as Geost, that target online banking and payment systems. Mobile users should safeguard\r\nthemselves as they navigate the treacherous mobile landscape by following best practices for securing mobile\r\ndevicesnews article. One such step is to avoid downloading apps outside official app stores.\r\nUnfortunately, threat actors also find ways to spread malicious apps via legitimate app stores. Along with the\r\ncontinued campaigns of these stores to remove compromised appsopen on a new tab, users can also avoid such\r\napps by carefully inspecting app reviews and other information before downloading.\r\nApp users should scrutinize the permissions requested by an installed app before allowing them. Afterwards, users\r\nshould watch out for changes in their devices, such as the decreased performance or battery life, which may\r\nindicate a malware infection. In this case, users should delete the newly installed app immediately. Users should\r\nalso conduct regular audits to remove unused apps.\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 19 of 20\n\nFor additional defense against mobile threats, users can install a multilayered mobile security solution such as\r\nTrend Micro™ Mobile Securityproducts to protect devices from malicious applications and other mobile threats.\r\nIndicator of Compromise\r\nSHA 256 Detection Name\r\n92394e82d9cf5de5cb9c7ac072e774496bd1c7e2944683837d30b188804c1810 AndroidOS_Fobus.AXM\r\nSource: https://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-bank\r\ns.html\r\nhttps://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html\r\nPage 20 of 20",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.trendmicro.com/en_us/research/20/c/dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html"
	],
	"report_names": [
		"dissecting-geost-exposing-the-anatomy-of-the-android-trojan-targeting-russian-banks.html"
	],
	"threat_actors": [
		{
			"id": "75108fc1-7f6a-450e-b024-10284f3f62bb",
			"created_at": "2024-11-01T02:00:52.756877Z",
			"updated_at": "2026-04-10T02:00:05.273746Z",
			"deleted_at": null,
			"main_name": "Play",
			"aliases": null,
			"source_name": "MITRE:Play",
			"tools": [
				"Nltest",
				"AdFind",
				"PsExec",
				"Wevtutil",
				"Cobalt Strike",
				"Playcrypt",
				"Mimikatz"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434125,
	"ts_updated_at": 1775791833,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/51c631a64b53c084c8617b648f20d06f3e8da338.pdf",
		"text": "https://archive.orkl.eu/51c631a64b53c084c8617b648f20d06f3e8da338.txt",
		"img": "https://archive.orkl.eu/51c631a64b53c084c8617b648f20d06f3e8da338.jpg"
	}
}