Cryptojacking Campaign Adopts Platypus for C2

About The Project

Last week I looked at a Cryptojacking campaign that leveraged a curl trick in the bash dropper to resolve IPv4 addresses from large integers values. Revisiting the bash dropper, I discovered the threat actor has updated the script to download and execute a command-and-control payload called “Termite” from the Platypus Github project. This blog walks through the analysis of termite agent, and how to statically identify the upstream IPv4 address in use.

vt_analysis

Obtaining the Packed ELF Sample

Diffing the updated bash dropper revealed a new binary being downloaded and stored in /tmp/ as “.0urn”.

new_dropper.png

Downloading said executable and executing the fileutility revealed a 64-bit statically linked binary.

ubuntu@ip-172-31-8-175:~$ file termite
termite: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header

Radare2 revealed that the termite binary contained three segments. Two distinct sections of LOAD1 and LOAD0 indicate that this binary is in some way packed.

[0x0064f1f8]> s segment.
segment.GNU_STACK   segment.LOAD0       segment.ehdr        segment.LOAD1

Typically, additional string artifacts can be identified that might have some indication to the packer used. In this case, string artifacts led me to UPX. I’ve previously blogged about writing Ghidra scripts to auto identify binaries packed by UPX. To unpack this binary, one could dump the running process or simply execute the following command:

$> ubuntu@analysis:~$ upx -d termite 
$> ubuntu@analysis:~$ ls -lah termite
-rw-rw-r-- 1 ubuntu ubuntu 8.4M Oct 23 12:01 termite

The decompressed file results in a whopping 8.4MB Golang binary. When using the upx utility to unpack a file, the original file is overwritten. It’s always a good idea to create a backup of the original compressed file for hashing reasons when keeping track of your analysis process. The final binary revealed a dynamically linked Golang binary. A quick check of the hash within VirusTotal revealed zero hits. As an independent security researcher, this is pretty neat! So let’s dive deeper, and throw the binary into Ghidra and start analyzing the underlying functions.

termite: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=G_REFjey11jRGG7i3_qr/NJ3HbDjUi9zCp1sNfX-T/orGxD94D9qZGpvMty3WP/4uCbu0OsJudgOuUGzT0l, not stripped

Termite - Golang Binary Analysis

Golang binaries can be a bit tricky to analyze. A quick rundown on Go’s assembler in Golang’s documentation may be of interest to those looking at a lot of Golang Malware. Golang binaries have a “main” function just like C programs. However, this function is stored within the “main” package. So finding main involves identifying a function called “main.main”. This file was not stripped, so all of the symbols are still intact making this process easy. The image below shows numerous other functions within the main package.

blog_main_package_functions.png

Navigating to the main package’s main function (main.main), we can start analyzing how the binary begins execution. Shortly after preamble, references to a publicly available Github project “Platypus” is identified.

blog_github_project_identified

Per the Gtihub README, Platypus is a “modern multi-reverse shell sessions/client manager via terminal”. The agent component of this project is called “termite”, and its source code is available here. Core functionality of the termite agent includes:

The end-user can configure options such as the working directory, and the upstream IPv4 address to connect to. Here, we see an issue with Ghidra resolving the IPv4 address to a long pointer, making the disassembly difficult to read. Changing the data type (ctrl + L) to type char makes the disassembly easier to decipher. The next two images illustrates this, as well as reveals as the upstream C2 server.

ghidra_original.png

ghidra_type_change.png

Automating IPv4 Extraction with Radare2

To quickly triage and dump the IPv4 address one could write a Ghidra script to automate this analysis. However, time is money. So let’s use radare2 and write a quick and easy one-liner to obtain the IPv4 address. to analyze the binary(aaa), jump to the main function in the main package (s sym.main.main) and then dump some function calls and strings of said function (pds). The image below shows these functions being executed via radare2.At this point, one can add a simple grep command at the end to ensure they’re only obtaining said IPv4 address or upstream domain. Without the symbols, this command would not work. Instead, one could just dump and grep for IPv4 addresses out of the .rodata section of the binary.

r2_automation.png

Hunting for Termite

Agent Update

Reviewing the source code of the termite agent reveals a few unique opportunities for detection. By default, the update functionality reaches out to a URL structure of <IP_ADDRESS>/termite/<user_specified_resource>, looking at outbound proxy logs could help identify this binary being downloaded and executed on a target host. Additionally, YARA/SIGMA rules could be written to detect this type of structured request being made from a curl command or embedded within a bash script.

Hardcoded Hash Check

The termite agent’s startClient function contains a hardcoded hash that the server variable is checked against. Failure to change this, leaves a hard coded hash artifact of “4d1bf9fd5962f16f6b4b53a387a6d852”. This value makes an excellent resource for a YARA rule.

IoCs

fcc1420e25c17eb2a17723bfbd9cc293  ar.sh (newly modified dropper script with termite)
a92e77fd13e60e1b3a5d1a66ab582318  termite (upx packed md5)
c989ea0aea15a77d89a2e5405e99d8e6  termite (unpacked md5)
856228c6cf6d4620ead7575885a8ae10c187e8b70a30096f69b7706021e09145  termite (unpacked-sha256)
104[ . ]244[ . ]76[ . ]33[ . ]:13131 (Platypus server for termite)
rule generic_termite_agent
{
    meta:
        description = "Termite agent yara rule"
        author = "DLL_Cool_J - Arch Cloud Labs"
        last_modified = "2022-10-23"
        
    strings:
        $github_repo = "github.com/WangYihang/Platypus"
        $termite_hash = "4d1bf9fd5962f16f6b4b53a387a6d852"
        $termite_debug = "Termite (v%s) starting..."

    condition:
        any of them
}

Beyond The Blog

While bash droppers are not the most exciting thing in the world of malware, they often lead to more interesting binaries for analysis. As an independent researcher, It’s always worth tracking and revisiting some of these bash scripts and where they’re hosted to discover if functionality has been updated or if there’s new techniques being added. The fact that this sample had zero VirusTotal hits makes it even more exciting to analyze. If you enjoyed this, please like, share and link back to this article if you or your organization goes further with this analysis!