Locating the Trojan inside an infected COVID-19 contact tracing app

A remote shell for the attacker

When the victim launches the infected app on the smartphone, the legitimate COVID-19 application begins, but, additionally, in background, the malicious part connects to a remote server (samples were found connecting to IP addresses 87.19.73.8 and 95.239.79.156 — there may be others).

The malware includes the legitimate app. So, it is difficult for the victim to understand this is an infected version.
An infected version is connected to the attacker’s server. For this study, we do not contact the real server (!) but our own local host, whose IP address is 192.168.0.42 (we’ll explain how to do that later).
Seen from attacker’s end. What s/he can have your smartphone do. Uses metasploit console (msfconsole)

Locating the trojan in the code (easy case)

Depending on the sample, the difficulty may vary. For example, in a non-obfuscated sample , the malicious part is obvious and located within the explicit hierarchy com.metasploit.stage.

In this sample (sha256: f3d452befb5e319251919f88a08669939233c9b9717fa168887bfebf43423aca), the injected meterpreter hasn’t been obfuscated. Its code is located within com.metasploit.stage.

Locating the trojan in an obfuscated sample (intermediate)

But, of course, there are obfuscated samples 😏 where the name for the trojanized part isn’t going to be so immediate. A close inspection of the Android manifest can help. We skip the permissions and jump to the “application” part.

Android manifest of sample 7b8794ce2ff64a669d84f6157109b92f5ad17ac47dd330132a8e5de54d5d1afc
Obfuscated name “Xmevv” for com.metasploit.stage.MainService. All other malicious classes are located in “apzcp” namespace.

Locating the trojan in difficult cases!

Now, what if the malicious activity or service names are not mentioned in the manifest (or you don’t spot them)? Actually, I was unlucky, this is what happened with the first sample I examined 😓

  1. Long (but educational): generate a Meterpreter APK and decompile it (with your favorite Android decompiler). This also has the advantage to show you exactly what to expect in the decompiled code.
  2. Short: read the sources on GitHub (it’s quick once you have the link, huh 😏)
  1. The payload uses a configuration byte array. The content in the sample will be different, but if you see a byte array in a class, give it a second look… especially that this byte string contains the IP address of the remote attacker’s server !
    private static final byte [] configBytes = new byte[] { (byte) 0xde, (byte) 0xad, (byte) 0xba, (byte) 0xad, //placeholder /*8192 bytes */ 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, … };
  2. Meterpreter connects to the remote server via a Socket. So, you can search in your Android app which part uses Sockets. There shouldn’t be that many. You can typically use DroidLysis for that. Run the tool (python3 droidlysis3.py --input thesample.apk --output dir ). Then, in the output directory, search for “Socket” in autoanalysis.md, and you get a list of all parts that call Socket methods (for the precise pattern that is matched, in your DroidLysis configuration, go and see ./conf/smali.conf and search for a property named “socket”: the pattern is listed just below).
Meterpreter source code creates a Socket server or a Socket client. Search for Sockets in your sample!
DroidLysis shows the code instantiates a Socket and calls SocketServer.accept() and in a class named Snotq. This helps locate malicious code within the package.
  • 992f9eab66a2846d5c62f7b551e7888d03cea253fa72e3d0981d94f00d29f58a
  • f3d452befb5e319251919f88a08669939233c9b9717fa168887bfebf43423aca
  • 7b8794ce2ff64a669d84f6157109b92f5ad17ac47dd330132a8e5de54d5d1afc

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
@cryptax

@cryptax

Mobile and IoT malware researcher. The postings on this account are solely my own opinion and do not represent my employer.