APT 36 Campaign – Poseidon Malware Technical Analysis

This is the open version of APT 36 Campaign – Poseidon Malware Technical Analysis. If you want to download it as a PDF click here.

Introduction

Transparent Tribe (a.k.a APT36, Earth Karkaddan, TEMP. Lapis, Mythic Leopard…) is an advanced threat actor group that is politically motivated and has suspected Pakistani origins. They mainly target government, diplomatic, defense, military, education, energy, and research organizations in India, Afghanistan, and Iran since 2012.

NOTE: The same threat actor group has different names because of the different naming conventions of threat intelligence companies.

The main reason for suspected origins is based on the Unit42 analyst’s suggested direct linkage of individuals from Pakistan to the infrastructure. This linkage is based on an individual’s OPSEC failure based on real name and mail address usage during infrastructure domain registration.

NOTE: Other than this link, no public resource or research supports this claim. Although a revealed individual has Pakistan origins, the group cannot be attributed to the Pakistani government or even a homogenous group of Pakistani individuals only with this finding. However, this interpretation does not mean Transparent Tribe has no Pakistan-related affiliations. It only means there is not enough data and research to back this verdict at this point.

The group primarily focuses on Indian government institutions and employees. Phishing domain names squatted by the group are based on payment service authorities and India’s military and government personnel websites. Their contents are also the same as mimicked via tools such as httrack. Aside from this, domain names similar to file-sharing services are used to trick the general audience into downloading malicious XLS files with macros that download malware samples of CrimsonRAT, ObliqueRAT, and Poseidon families. Targeted malspam campaigns that contained malicious XLS files with VBA macros, which later dropped CrimsonRAT and ObliqueRAT. For instance, this report explains the usage of Poseidon malware which targets government employees who use UNIX-based systems for their jobs by mimicking Kavach service that is used for automation in train protection and collision avoidance systems in India by locomotive pilots and rail-station workers.

Malicious documents crafted for generic campaigns include resumes, CVs, or honeytraps (pictures of women). Malicious documents are disguised as conference agendas, invitations, and diplomatic reports if diplomatic entities are targeted. Malspam campaigns target government officials and military entities’ masquerades as guidelines, policies, and activity plans for defense organizations’ personnel, advisories, or top secret briefings.

apt36 mythic leopard infection chain for poseidon
Figure 1: APT36 infection chain

Poseidon is one of many agents of the open-source Mythic C2 Framework. Since this framework is open-sourced, the Poseidon agent can be used by any other actor with internet access. Therefore, it is impossible to say every Poseidon build seen in the wild can be attributed to Transparent Tribe. The same occasion is not valid for CrimsonRAT and ObliqueRAT. These two families are unavailable for everyone, not sold in forums with the MaaS model, and their previous activities are attributed to the activities of the Transparent Tribe group with high confidence.

However, this interpretation does not mean Transparent Tribe has no Pakistan-related affiliations. It only means there is not enough data and research to back this verdict at this point.

APT 36 Poseidon Malware Technical Analysis

You will find technical analysis results of first-stage downloader malware detected by APT 36 to be used in a cyber espionage campaign against the Indian government and second-stage Poseidon malware used as all-in-one backdoor software.

First Stage Malware Analysis

The first ELF file detected in the attack campaign is the Python script file wrapped in ELF format, and the file’s header information shows the presence of the .pydata section.

poseidon malware first stage section headers
Figure 2: First-stage malware section headers

By extracting the compiled Python file (Kavach.pyc) from the pydata section of the ELF file and converting it to the source code, it becomes clear to understand the purpose of the 1st stage file.

malicious Python code
Figure 3: Decompiled malicious Python code

In the Python code we extracted, we first see the URL of the official website of the Indian government. The threat actor uses the official website login panel to display in the browser to the user.

kavach login page
Figure 4: Legitimate Kavach login page

It creates a two command line scheduled task in /dev/shm/mycron for the currently logged-in user. The threat actor has set the scheduled task to run the specified files every time the system is rebooted.

@reboot ~/. local / share / bosshelp
@reboot ~/. local / share / usbdriver

After setting the crontab, it deletes the /dev/shm/mycron file containing the above commands from the system. Another vital function of the 1st stage file is downloading additional files from the remote server. Notice that the file to download (bosshelp) matches the filename in the scheduled task set earlier.

Second Stage Malware Analysis

The 2nd stage file is defined as a payload named Poseidon, written in Go programming language and included in the MythicAgents project on GitHub. The first time the Poseidon malware is run on the target system, a new profile is created for C2 communication. This operation is defined in the main.init function before main.main.

C2 creation for poseidon malware
Figure 5: Creation of new C2 profile per victim

Information about the new profile is in the image below, and as a result, it is kept as a structure containing this information. Important information such as C2 IP address (hard coded), port number, RSA key, and KillDate are found in the C2 profile created in main.init. The RSA key in the profile is generated by the GenerateRSAKeyPair function in the C2 Check-in action, which we describe later.

rsa generation
Figure 6: RSA key generation

The use of the functionality of the program is decided by using the switch-case structure in the main_handleNewTask routine.

Poseidon main functions
Figure 7: Poseidon main functions

The listed functions are used as Wrappers for routines that will provide functionality. For example, the wrapper function of the shell command execution functionality corresponding to task number 4 is labeled as main_handleNewTask_dwrap_4. The code snippet of the function it calls internally is as follows: this structure is similar to other wrapper functions.

internal call wrapper function
Figure 8: Internal call wrapper function example

Each task can be associated with the number at the end of the function name, but remember that this number has no equivalent in the switch-case statement.

switch-case flow
Figure 9: Switch-case control flow

We will consider the numbers at the end of the function names as references for better understanding.

func handleNewTask() {
    for {
        select {
        case task := <-newTaskChannel:
            //fmt.Printf(“Handling new task: %v\n”, task)
            switch tasktypes[task.Command] {
            case EXIT_CODE:
                os.Exit(0)
                break
            case 1:
                go shell.Run(task)
                break
            case 2:
                go screencapture.Run(task)
                break
            case 3:
                go keylog.Run(task)
                break
            case 4:
                go download.Run(task)
                break
            case 5:
                go upload.Run(task)
                break
            case 6:
                go libinject.Run(task)
                break
            case 8:
                go ps.Run(task)
                break
            case 9:
                // Sleep
                go sleep.Run(task)
                break
            case 10:
                //Cat a file
                go cat.Run(task)
                break
            case 11:
                //Change cwd
                go cd.Run(task)
                break
            case 12:
                //List directory contents
                go ls.Run(task)
                break
            case 14:
                //Execute jxa code in memory
                go jxa.Run(task)
                break
            case 15:
                // Enumerate keyring data for linux or
                //the keychain for macos
                go keys.Run(task)
                break
            case 16:
                // Triage a directory and organize files by type
                go triagedirectory.Run(task)
                break
            case 17:
                // Test credentials against remote hosts
                go sshauth.Run(task)
                break
            case 18:
                // Scan ports on remote hosts.
                go portscan.Run(task)
                break
            case 21:
                // Return the list of jobs.
                go getJobListing(task)
                break
            case 22:
                // Kill the job
                go killJob(task)
                break
            case 23:
                go cp.Run(task)
                break
            case 24:
                // List drives on a machine
                go drives.Run(task)
                break
            case 25:
                // Retrieve information about the current user.
                go getuser.Run(task)
                break
            case 26:
                // Make a directory
                go mkdir.Run(task)
                break
            case 27:
                // Move files
                go mv.Run(task)
                break
            case 28:
                // Print working directory
                go pwd.Run(task)
                break
            case 29:
                go rm.Run(task)
                break
            case 30:
                go getenv.Run(task)
                break
            case 31:
                go setenv.Run(task)
                break
            case 32:
                go unsetenv.Run(task)
                break
            case 33:
                go kill.Run(task)
                break
            case 34:
                go curl.Run(task)
                break
            case 35:
                go xpc.Run(task)
                break
            case 36:
                go socks.Run(task)
                break
            case 37:
                go listtasks.Run(task)
                break
            case 38:
                go list_entitlements.Run(task)
                break
            case 39:
                go execute_memory.Run(task)
                break
            case 40:
                go jsimport.Run(task)
                break
            case 41:
                //Execute jxa code in memory from
                //the script imported by jsimport
                go jsimport_call.Run(task)
                break
            case 42:
                //Execute persist_launch command to install launchd
                //persistence
                go persist_launchd.Run(task)
                break
            case 43:
                // Execute persist_loginitem command to install
                //login item persistence
                go persist_loginitem.Run(task)
                break
            case 44:
                // Execute spawn_libinject command to spawn a
                //target application/binary with the
                //DYLD_INSERT_LIBRARIES variable set to
                //an arbitrary dylib
                go dyldinject.Run(task)
                break
            case 45:
                go link_tcp.Run(task)
                break
            case 46:
                go unlink_tcp.Run(task)
                break
            case 47:
                go run.Run(task)
                break
            case 48:
                go clipboard_monitor.Run(task)
                break
            case 49:
                go execute_macho.Run(task)
                break
            case 50:
                go rpfwd.Run(task)
                break
            case NONE_CODE:
                // No tasks, do nothing
                break
            }
            break
        }
    }
} 

Poseidon Malware Capabilities

The Poseidon malware agent installed on the target system can receive commands from the threat actor, as indicated in the table below.

posideon malware capabilities
Table 1: Poseidon capabilities – 1
poseidon capabilities
Table 2: Poseidon capabilities – 2

Network Activities

To initiate communication with C2, Poseidon first executes an action in the Poseidon project called Check-in. The information collected by the CreateCheckinMessage function indicates that the malware intended to gather information before communicating with C2 on the system it is running. Below we have listed the types of information included in the Check-in message.

  • “checkin” string 
  • Hostname 
  • IP Address 
  • PID
  • OS 
  • Process Name 
  • “amd64aring” string 
  • URI to send data to 
  • 3b54bd24-92a5-4b91-ad15-de771a497372
    • This value is used as the UUID (HTTP, WEBSOCKET, or TCP) value found in the configuration data while the threat actor prepares a new Poseidon instance and is specific to the detected file.
command&control server message check-in
Figure 10: C2 start check-in message

The image below shows the configuration data used by Poseidon.

Poseidon configuration data
Figure 11: Poseidon configuration data

The malware used in the campaign is trying to send data to the remote server with a POST request by establishing a TCP connection with the IP address 70.34.214[.]252, but we cannot obtain details because the server is inactive when the file is analyzed.

Indicator of Compromises

Poseidon Payload SHA-256 Hashes

78480e7c9273a66498d0514ca4e959a2c002f8f5578c8ec9153bb83cbcc2b206

3285032b8e1cd080ce5df8839db03a1eb9e4d16db252fd64d4c0c5a66d8b0ff8
3164c7d572bd3f59f31a3bb6ac8a7f0769f2cbdddea7cadf843b99076a952b81
8affdfea794bc04340a453160237e7b6ae77bd909146321daf2ed50401928827
4fac5b0618348de1e6e4843bb4560320eea175ecc4ba807beadd56e2e6a66e32
58eedd3277014bb45a294f4c299bbfcdfc38a212fa0cda7a781dda132e8928a5
3d180606a60e0a25b78fde6b3cb52afc8443105e672cdcc420be781e9ec32488
9bb990a54460437c14be4cdd25ab5f8027a49c4e8e8b83445bd57f06ad1e1512
cc53c74a8be261fab1f231e20d127cb815787ff3437daff8162855130f8ff271
dcfb42328840a3524ceda176f5fe5041e1dd5c86e126dc6e4fc47826a1bbcc96
40a42f392fc58c047cfbbda566d70ebd2654f2919f8ee8e6b5d76e5bc11ec5cc
51ff7043b2bc87f52e71a265080acd0a1b3d5d2a07ef541ebf3af5c6d44b3761
fe843154f38202f17379dd2bed25306e8357e9e1bf56bd89565e81a67a286d6e
95ed0e02c6bbfe065ad79d595b7a607de64156c368cf1e85323ce829bffb3d0b
67a0d54e73ab0f76634e80b2723c3ac7d4df73b55aea5323856a42bbc19859a6
dc1ec8aa04a71f595454dba88473fba2a970533eceee2d155a3956d8dc9ecda0
91e08c6ee0d6b6f472a5df371318d56d2442c3487caad0a093754f57142ece6f
ec93724a82f487f960acd51f427e660793f6e868a25f666e4cf5babb3bdcfe54
aa53cfadd21956ea50e1a504ac6b4287076c64056e4b57a877b2f564ea315eb9
8f19a4b6a3fe19d577e71c458c3c0565599b57863f0efbdf4e109b4e92c0bbeb
7328240b03a5992537f7b3371bab7fd4e3b631d31b3919596daa8265886a07ae
e45909e6a7c50b34deba248c7e1b419706c3d6e9c638980099d6860db9e5c53b
f688280c7cc7523989809472594c36f97d7e2cc5e3ef5721ca67ab1f8b458104
185254efe497aed539fe0d95ca40451985b8fa60a54a707760bfe5c53cce56d9
489703daffea94c11319c74f2a43d4ca3198baa9081a42f047f029a39c335981
0416006b9043b8f45f343fedcef9bfdb8e1c8cafc30951755c0d7eb60e409c78
3b8b06eb6e30296e74fc7c6a039c1a05d6785bce9745b85851fe686306abbf35
34059561b4adc524128c61e886177f8e87674ebe90f227acc8828b9d566f3e5c
293e51eecb94da90d4237b219584efd6afc805b0da2792ffa53fc132cf1d32b3
7f6b1ed3549fc58ade807898bd458fff0bbfd7aaddbc75a2710ddfc580f5248a
897bd48be8fc5b10603e10d262035282024d0c092ef8dbde796568d627aa1c60
8626a35ce2b1211fad630909165b67ae1391da02529da20e0c1fa05ba989bcf4
5b41f55410f835a0fc2702dffe74b32ab1eebdd22437585ca5349729329a89d8
ca3f34dfd9540e59bc0cdb36bbe6fe77cbb9eb44d682add9e38123281a3f4e55
37ffaccba0469d9125dd072241ec7d99652e2e46897f7c6d3db98a19d92b20e6

  • 70[.]34[.]214[.]252
  • sharing1[.]filesharetalk[.]com/bosshelp

YARA Rule

rule poseidon_elf{
    strings:
        $main_func = {E8 ?? 2? D4 FF 31 C0 48 8D 1D ?? 0B 00}
        $command_call = {48 8B 42 08 48 8B 5A 10 48 8B 4A 18 48 8B 7A 20 F2
        0F 10 42 28  48 8B 72 30 4C 8B 42 38 4C 8B 4A 40 66 90  E8 ?B ?? F?
        FF 48 8B 6C 24 40  48 83 C4 48 C3}
        $s1 = “poseidon_tcp”
    condition:
        $main_func or $command_call or $s1
} 

 

References:

  • https://unit42.paloaltonetworks.com/unit42-projectm-link-found-between-pakistani-actor-and-operation-transparent-tribe/

You can fin also these indicator of compromises on our GitHub repo.