How We Seized 15 Active Ransomware Campaigns Targeting Linux File Storage Servers

Written by Ignacio Sanmillan

    Share article
    FacebookTwitterLinkedInRedditCopy Link

    Top Blogs

    Introduction


    It is rare to see ransomware being used to target the Linux operating system. However, cyber criminals seem to adapt to this emerging environment and use a variety of creative methods to gain profits from this landscape.

    We at Intezer have detected and temporarily DoS’d the operation of a ransomware targeting Linux-based file storage systems (NAS servers).

    We have named the ransomware QNAPCrypt, as this is the name the authors have appeared to label the malware. QNAP is a well-known vendor for selling NAS servers, which the malware was intended to infect and encrypt the containing files for ransom. NAS servers normally store large amounts of important data and files, which make them a valuable target for attackers and especially a viable target for ransomware campaigns.

    This malware currently has very low detection rates in all major security solutions.

    The first two sections of this blog post will explain in brief how QNAPCrypt operates and how we were able to take advantage of two design flaws in the ransomware infrastructure in order to temporarily stop the campaign—preventing the malware from infecting additional victims and forcing the authors behind this malware to deploy new instances. Lastly, we will present a detailed technical analysis of the malware and the investigation of the entire campaign.

    For reference, here is the genetic analysis of the QNAPCrypt malware:

    QNAPCrypt malware

    How the Ransomware Works

    The QNAPCrypt ransomware works similarly to other ransomware, including encrypting all files and delivering a ransom note. However, there are several important differences:

    1. The ransom note was included solely as a text file, without any message on the screen—naturally, because it is a server and not an endpoint.

    2. Every victim is provided with a different, unique Bitcoin wallet—this could help the attackers avoid being traced.

    3. Once a victim is compromised, the malware requests a wallet address and a public RSA key from the command and control server (C&C) before file encryption.


    How We Seized the Campaign

    QNAPCrypt ransomware

    In order to further research the malware and its operation, we wrote a script to simulate infections on a wide scale to see how the wallet generation mechanism worked in the attackers’ back end.

    After simulating the infections of hundreds of virtual “victims”, we discovered two major design flaws in the ransomware infrastructure which led us to seize the operation:

    1. The list of bitcoin wallets was created in advance and it was static. Therefore, it does not create a new wallet for each new victim in real time, but rather it pulls a wallet address from a fixed, predetermined list.

    2. Once all of the wallets are allocated (or sent), the ransomware would not be able to continue its malicious operation in the victim’s machine.

    After simulating the infection of more than 1,091 victims from 15 different campaigns, we encountered that the attackers ran out of unique Bitcoin wallets to supply to their victims. As a result, any future infection will be unsuccessful and the authors behind this malware were forced to update their implants in order to circumvent this design flaw in their infrastructure to continue with their malicious operations.

    After several days of continuously DoS’ing their infrastructure, we have observed a newer variant in the wild that shares a significant amount of code with previous QNAPCrypt instances and Linux.Rex. This time, the newer variant uses an embedded static wallet and RSA public key in contrast to previous instances.


    Technical Analysis


    The initial implant we found came in the form of a statically linked Golang binary built with the Go linker for ARM architecture. Throughout our research, we were able to confirm that other variants exist for additional architectures such as x86 / x64.

    Go binaries may seem difficult to analyze when they come stripped, since trying to make sense of stripped statically linked binaries is usually a more difficult task than analyzing stripped dynamically linked binaries.

    Technical Analysis

    We can observe that this binary is indeed a Go executable by looking at the section names in its section header table.

    If we know the location of these sections, in particular the .gopclntab section, we will be able to reconstruct symbol names and offsets. This methodology is illustrated in the following diagram:

    .gopclntab 

    For further insights into populating function names in Go binaries we highly recommend to view Tim Strazzere’s presentation and scripts in GitHub which document this technique.

    After retrieving Go function names, analyzing the binary becomes much less complex since we can highlight the relevant functions of the application. Let’s not forget that the binary is 4MB in size.

    After several cryptography algorithm initializations and parsing of arguments for directory whitelisting and alike functionalities, the malware will send a GET request to the CNC as a means to communicate that a new victim has been compromised and that system locking is taking place:

    cryptography algorithm

    After sending this GET request, the malware will attempt to retrieve victim keys configuration using a client for the SOCKS proxy protocol version 5.

    SOCKS proxy protocol version 5

    This proxy will request to connect to an onion domain name. The following represents the relevant packets for this connection:

    ransomware REST API

    After successful connection through the proxy to the onion domain, an additional GET request to the ransomware REST API is completed in order to retrieve the RSA public key that will be used to encrypt the file system—a unique Bitcoin wallet and the ransom note specific to the victim. All of these artifacts seem to be retrieved based on a specific campaign ID.

    pasted image 0 5

    The response from the server is the following:

    pasted image 0 8

    After victim configuration has been retrieved, the malware will proceed to remove itself and then it will parse the retrieved RSA public key.

    RSA public key

    This RSA public key will be used to encrypt a random sequence of bytes that would be used to encrypt the file system later on. This encrypted key will be base64 encoded and it will be written at the end of the ransom note file called README_FOR_DECRYPT.txt. We also noted that the ransomware distributes a different Bitcoin wallet per each compromised system:

    pasted image 0

    After this file is created, the malware will proceed to execute the locking mechanism by walking the file system encrypting files using AES CFB with the derived encrypted key, avoiding to encrypt the ransom note just created:

    AES CFB

    The malware will target files with the following extensions:

    malware will target files

    After encryption, the malware will rename the affected files so that they will be prefixed with ‘.encrypt’:

    After encryption, the malware will rename the affected files

    In order for system decryption to take place the base64 encoded random sequence encrypted with the RSA public key will be needed to be sent to the ransomware operator via the onion domain site after paying the demanded ransom:

    RSA

    After system locking has taken place, the ransomware will communicate that it has finished with the victim once again to the CNC:

    pasted image 0 10


    Looking Outside of the Binary


    One of our intended goals that we wanted to achieve when analyzing QNAPCrypt was to assess the scale of victims the ransomware was dealing with.

    We were able to find a Reddit thread in which we contacted some of the affected victims:

    2019 07 02 161012 927x497 scrot

    While talking to some of the victims related to the various campaigns of this malware, we were able to identify the initial attack vector as SSH brute force attacks and that they were targeting mainly NAS server providers, which corresponds to how the attacker has chosen to label this malware:

    pasted image 0 16

    After making these findings we studied their infrastructure to determine if there was anything we could do to interact with this threat actor’s operations.

    While researching the ARM instance of the malware, we observed that there was a request through their REST API in order to retrieve new victim configuration keys as previously discussed. The following diagram is a high level overview of the ransomware operation:

    pasted image 0 9

    The connection to the SOCKS5 proxy is completed without any authentication enforced, and anyone would have the capability to connect to it.

    Therefore, we decided to interact with the ransomware infrastructure in order to retrieve configuration keys and potentially temporarily shut down the operation of the ransomware to prevent infection of future victims that were compromised by instances of the ransomware that followed the previous design architecture:

    pasted image 0 11

    This idea simply abuses the fact that no authentication is enforced to connect to the SOCKS5 proxy as previously mentioned. Since the authors behind this ransomware were delivering one Bitcoin wallet per victim from a static pool of already generated wallets, we could replicate the infection packets to retrieve all of the wallets until they had no further wallets under their control. Therefore, when a genuine infection would occur, the ransom client would not be able to retrieve configuration artifacts.

    We wrote the following script in order to implement the methodology described above:

    import socket
    import hexdump
    import json
    import sys
    
    HOST = '192.99.206.61'  
    PORT = 65000        
    
    for i in range(15):
        BTC_WALLETS = list()
        while True:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((HOST, PORT))
            
            s.send(b'\x05\x01\x00')
            data = s.recv(1024)
            hexdump.hexdump(data)
            
            s.send(b'\x05\x01\x00\x03\x16' + b'sg3dwqfpnr4sl5hh.onion\x00' + b'\x50')
            data = s.recv(1024)
            hexdump.hexdump(data)
            
            s.send(b'GET /api/GetAvailKeysByCampId/%.2d HTTP/1.1\x0d\x0a' % i +
                    b'Host: sg3dwqfpnr4sl5hh.onion\x0d\x0a' +
                    b'User-Agent: http/2\x0d\x0a' +
                    b'Accept-Encoding: gzip\x0a\x0d\x0a')
            data = s.recv(1024)
            print '[+] Campaign id %.2d' % i
            hexdump.hexdump(data)
    
            try:
                data = json.loads(data[data.find('{'):])
                print data['BtcPublicKey']
                s.close()
                
                if data['BtcPublicKey'] not in BTC_WALLETS:
                    BTC_WALLETS.append(data['BtcPublicKey'])
                else:
                    sys.exit()
    
            except ValueError as e:
                print "[+] CAMPAIN HAS NO WALLETS LEFT"
                with open("wallets_%0d.txt" % i, 'w+') as fd:
                    for wallet in BTC_WALLETS:
                        fd.write(wallet+'\n')
                break
    

    We were able to collect a total of 1,091 unique wallets meant to be delivered to new victims distributed among 15 different campaigns.

    2019 07 01 161151 610x63 scrot

    Furthermore, by depleting the attacker’s stored Bitcoin wallets we were able to stop this malware from infecting new victims temporarily, since if there is a failure to parse the RSA public key the client will just exit:

    pasted image 0 2

    The following screenshot shows the packets that the onion domain will retrieve after the entire static Bitcoin wallet pool was depleted:

    2019 07 01 160114 701x189 scrot

    The HTTP request returns a 200 but with a content length of 0, therefore failing to retrieve configuration, and thus the ransomware client stops execution. This implies that we were able to identify an easy method to prevent further infections of this ransomware by constantly depleting its static bitcoin wallet pool.


    Attribution and Attackers Reaction


    After several days of continuously DoS’ing QNAPCrypt clients, we encountered another QNAPCrypt sample—but this time targeting x86 systems.

    2019 07 06 224329 1406x603 scrot

    Based on Genetic Malware Analysis, we observed that this specific implant reused a large portion of code with old instances of x86 Linux.Rex builds. Linux.Rex is known for deploying exploits against Drupal servers in 2016, in order to conduct ransomware and DDoS operations.

    The following represents some of the code similarities between Linux.Rex and newer QNAPCrypt variants:

    pasted image 0 17

    Although both implants implement different functionality, it is noticeable that both were written in a similar manner.

    Furthermore, we can observe similarities with the ARM instance of QNAPCrypt but with a major difference—the RSA public key, Bitcoin wallet and ransom note are hardcoded in the binary:

    pasted image 0 13

    We can also see that the hardcoded onion domain is exactly the same as in the ARM variant, and the site design to pay the ransom is also the same, although the demanded ransom in Bitcoin seems to be lower than in previous variants:

    pasted image 0 6

    We interpret the discovery of these newer instances with hardcoded configuration to be a response from the threat actors behind this campaign to attempt to circumvent the DoS that their non connectionless instances were suffering. This implied that they were forced to change their implants and to centralize their bitcoin wallets, making the tracking of their income via their ransomware campaigns more convenient.


    Conclusion


    We have covered the operation of the QNAPCrypt ransomware, and how we were able to find design flaws to prevent the malware from running in newer victims’ machines and forcing the attackers behind the malware to update their implants in order to circumvent these flaws.

    Additionally, Golang malware seems to be on the rise, since it appears to be a very convenient language to create cross-platform malware.

    Furthermore, we have discussed how Linux ransomware has slightly different targets than Windows ransomware, in this case targeting NAS servers rather than Linux endpoints.

    Unfortunately detection rates of QNAPCrypt are low, and the ransomware could create significant monetary losses and economic damage in comparison to other types of Linux threats.

    We have created a custom YARA signature for detecting future variants of QNAPCrypt.

    Genetic Analysis


    The QNAPCrypt malware variants are now indexed in Intezer’s genetic database. If you have a suspicious file that you suspect to be QNAPCrypt or other malware from the Rex group, you can upload it to Intezer Analyze to detect code reuse to this threat family and many others. You are welcome to try it for free in our community edition.

    Screen Shot 2019 07 03 at 6.03.22 PM

    Genetic Analysis of the QNAPCrypt ARM variant

    IOCs


    sg3dwqfpnr4sl5hh[.]onion
    192.99.206[.]61
    3d7ebe73319a3435293838296fbb86c2e920fd0ccc9169285cc2c4d7fa3f120d
    076a6fa4e051c061e19b9e3e37da9c63a9bc7c1a99111ac13b32eb2f70b7fa5c

    Ignacio Sanmillan

    Nacho is a security researcher specializing in reverse engineering and malware analysis. Nacho plays a key role in Intezer\'s malware hunting and investigation operations, analyzing and documenting new undetected threats. Some of his latest research involves detecting new Linux malware and finding links between different threat actors. Nacho is an adept ELF researcher, having written numerous papers and conducting projects implementing state-of-the-art obfuscation and anti-analysis techniques in the ELF file format.

    Generic filters
    Exact matches only
    Search in title
    Search in content
    Search in excerpt