Malware Downloader Triage Notes
Researching malware downloaders, detection and triage
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
9211...
Triage of 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())
r = requests.get(HASHDB_HASH_URL + '/crc32/' + str(api_hash))
print(r.json())
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 thecmd.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*)
}
"企划营销岗位_徐浩阳_硕士.exe": 1a10e2940151982f2ab4f1e62be6e4f53074a2ffb90c7977e16d6a183db98695
— MalwareHunterTeam (@malwrhunterteam) June 11, 2022
139.9.138[.]190 pic.twitter.com/pquwEW1ZW0
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": []
}
]