Overview

We are going to take a look at two different downloaders, which are so simple they don't have great static detection or information extraction in UnpacMe yet! Our goal is to generate some Yara rules, or maybe some code to identify and extract the relevant info (download URL) in a generic static way.

Samples

Triage of 9211...

The samples has a plaintext URL and the download functionality is not obfuscated/packed and can be identifed using CAPA as seen in UnpacMe.

The hardcoded URL is: http://apuservis.pe/ocultar/fw%d.exe.

There are 2 loops used to generate ULRs from 1 - 7 calling the URLs:

  • http://apuservis.pe/ocultar/fw1.exe
  • http://apuservis.pe/ocultar/fw2.exe
  • http://apuservis.pe/ocultar/fw3.exe
  • http://apuservis.pe/ocultar/fw4.exe
  • http://apuservis.pe/ocultar/fw5.exe
  • http://apuservis.pe/ocultar/fw6.exe

The file is writtent to %APPDATA% with a random file name using a random number "%08x.exe.

To execute the file the API ShellExecuteW is resolved dynamically using a CRC32 hash then it is called with the open command.

import requests

HASHDB_HUNT_URL = 'https://hashdb.openanalysis.net/hunt'
HASHDB_HASH_URL = 'https://hashdb.openanalysis.net/hash'

api_hash = 0x1FA8A1D4 + 5
hunt_request = {"hashes": [api_hash]}

r = requests.post(HASHDB_HUNT_URL, json=hunt_request)
print(r.json())
{'hits': [{'algorithm': 'crc32', 'count': 1, 'hitrate': 1.0}]}
r = requests.get(HASHDB_HASH_URL + '/crc32/' + str(api_hash))
print(r.json())
{'hashes': [{'hash': 531145177, 'string': {'string': 'ShellExecuteW', 'is_api': True, 'permutation': 'api', 'api': 'ShellExecuteW', 'modules': ['shell32']}}]}

Possible IOCs

  • There is self-delete functionatlity using the batch script: /c ping 127.0.0.1 && del \"%s\" >> NUL

  • They use GetEnvironmentVariableW(L"ComSpec", Filename, 0x104u) to get the cmd.exe path.

  • They have a hardcoded URL http://apuservis.pe/ocultar/fw%d.exe

  • They have a hardcoded HTTP header GET %S HTTP/1.1

  • They have a CRC32 hash algo used for the dynamic API resolving

Yara rule

rule download_hunt {

    meta:
        description = "Hunt for simple downloaders"

   strings:
       $s1 = "/c ping 127.0.0.1 && del \"%s\" >> NUL" wide ascii nocase
       $s2 = "http://" wide ascii
       $s3 = "GET %S HTTP/1.1" wide ascii nocase
       $x1 = { 35 20 83 B8 ED }
       $x2 = { 81 F? 20 83 B8 ED }

   condition:
       all of ($s*) and 1 of ($x*)

}

** let's also check file size

** these are small binaries with very few functions, one ID trick might be to try and identify how many functions and only trigger an bins with a few functions... for this we could maybe used CFG count... from @psifertex

You can see the function table from a CFG binary with dumpbin /loadconfig test.exe

Yara Rule Revisions

We ran a scan with the above rule over the MalwareBazaar corpus and the results only gave us one match (the sample we were originally looking at). This is a bad rule. We are going to loosen the rule to see if we can catch more samples.

rule download_hunt_2 {

    meta:
        description = "Hunt for simple downloaders"

   strings:
       $s1 = "/c ping 127.0.0.1 && del" wide ascii xor 
       $s2 = "http://" wide ascii xor 


   condition:
       all of ($s*) 

}

Triage of 1a10e...

There is a PDB path in the binary C:\Users\H0e4a0r1t\Documents\Visual Studio 2015\Projects\worddy\x64\Release\worddy.pdb. Based on the username H0e4a0r1t we found a possible GitHub https://github.com/h0e4a0r1t and this looks like maybe a "redteam" tools developer??

Possible IOCs

  • There is an embeded blob that is encrypted with a singl-byte XOR 0x99

  • Once decrypted the blob is a standard Cobalt Strike loader with the following "header" strings.

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: http://code.jquery.com/
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
  • The C2 IP is 139.9.138.190

  • To load and launch the decrypted shellcode they use the following APIs

    • VirtualAlloc
    • WriteProcessMemory
    • QueueUserAPC

Yara Rule

rule cs_downloader {

    meta:
        description = "Hunt for Cobalt Strike downloader"

   strings:
       $s1 = "Accept-Language:" xor(0x01-0xff)
       $s2 = "Referer: http://code.jquery.com/" xor(0x01-0xff)
       $s3 = "Accept-Encoding: gzip, deflate" xor(0x01-0xff)
       $s4 = "User-Agent:" xor(0x01-0xff)


   condition:
       all of ($s*) and uint32(@s1) == uint32(@s3) 

}

Yara Results

We only got 2 hits, this rule also sucks, lol!

[
  {
    "rule": "cs_downloader",
    "malware": "CobaltStrike",
    "sha256": "e54514b1164508c049733c7dafc97f24ae66d42b8146b0e1a1271f9af7c94d48",
    "mime_type": "application/x-msdownload",
    "virustotal_link": "https://www.virustotal.com/gui/file/e54514b1164508c049733c7dafc97f24ae66d42b8146b0e1a1271f9af7c94d48/detection",
    "malwarebazaar_link": "https://bazaar.abuse.ch/sample/e54514b1164508c049733c7dafc97f24ae66d42b8146b0e1a1271f9af7c94d48/",
    "tags": []
  },
  {
    "rule": "cs_downloader",
    "malware": "CobaltStrike",
    "sha256": "6220127ada00d84b58d718152748cd2c62007b1de92201701dc2968d2b00e31f",
    "mime_type": "application/x-msdownload",
    "virustotal_link": "https://www.virustotal.com/gui/file/6220127ada00d84b58d718152748cd2c62007b1de92201701dc2968d2b00e31f/detection",
    "malwarebazaar_link": "https://bazaar.abuse.ch/sample/6220127ada00d84b58d718152748cd2c62007b1de92201701dc2968d2b00e31f/",
    "tags": []
  }
]