Yesterday, at SAS2019, BAE Systems presented findings related to DPRK SWIFT heist activity that took place in 2018. As part of this research (a leaked video of the presentation is available online), BAE included two key points not previously disclosed in the public domain:
– The existence of a PowerShell backdoor attributable to DPRK, which the researchers dubbed PowerBrace
– A possible overlap between TA505 intrusions and DPRK intrusions, suggesting a possible hand-off between the two groups.
This blog will leave a full analysis of those two points and the supporting context to the people that found them, as it’s theirs to share; however, data that may support such conclusions have been available in open source for quite some time.
In early January, VNCert issued an alert regarding attacks targeting financial institutions, containing a mix of DPRK IOCs (including a keylogger referred to as PSLogger previously analyzed by this blog), TA505 IOCs (previously published by 360 TIC), and a handful of PowerShell scripts that are generally identical aside from a handful of configuration changes. Furthermore, the aforementioned keylogger was first uploaded by a submitter (fabd7a52) in Pakistan in December 2018. That same submitter acted as the first uploader for one of the PowerShell samples identified below (b88d4d72fdabfc040ac7fb768bf72dcd), further corroborating a possible link.
Given the multi-sourced reporting overlaps and the additional Pakistan findings mentioned above, this blog assesses that the PowerShell scripts in question likely belong to the same family of DPRK-attributable malware reported by BAE systems.
A listing of selected IOCs is below the fold, alongside a few brief notes (and a script) for how to analyze the PowerShell malware.
IOCs from VNCert
These contain infrastructure overlaps with reporting from the same month found here: https://ti.360.net/blog/articles/excel-4.0-macro-utilized-by-ta505-to-target-financial-institutions-recently-en/
HSMBalance.exe MD5:34404a3fb9804977c6ab86cb991fb130 – Keylogger
ICAS.ps1 MD5: b12325a1e6379b213d35def383da2986 – Possible PowerBrace
MD5: 8a41520c89dce75a345ab20ee352fef0 – Possible PowerBrace
MD5: 7c651d115109fd8f35fddfc44fd24518 – Possible PowerBrace
MD5: b88d4d72fdabfc040ac7fb768bf72dcd – Possible PowerBrace
MD5: 3be75036010f1f2102b6ce09a9299bca – Possible PowerBrace
Several hashes were omitted: these were EML files that belong to specific financial organizations. Others were not on VirusTotal or were not read properly by OCR.
A Few Notes on the PowerShell Backdoor
MD5 Used: b12325a1e6379b213d35def383da2986 (ICAS.ps1)
As previously mentioned, this blog will not be publishing a full analysis of this backdoor in deference to the people who first found it; however, in the interest of helping analysts who need the data, there are a few key points to mention:
– The backdoor uses a configuration file that includes two C2 servers and a series of Base64 encoded commands
– Most of the malware’s function names have been replaced with MD5 hashes
A script below has been included that performs the Base64 transformation on values where it can find them. To analyze this script, this blog then recommends the following process:
1) Using an easily identifiable command name (decoded by the script), locate that command’s use in a function
2) Identify references between that command and other functions
3) Rename those other functions
An example of decoded data (with variables and functions renamed manually) is below:
A script to assist with this is here:
import base64 import re c = open("c:\\users\\[username]\\desktop\\[filename]").readlines() line_list =  for line in c: #print(line) try: enc = re.search("(?<=\$\(\[Text.Encoding\]::Unicode.GetString\(\[Convert\]::FromBase64String\().*?(?=\))",line).group() print(line) print(enc) d = ('"' + base64.b64decode(enc) + '"') e = (re.sub("\$\(\[Text.Encoding\]::Unicode.GetString\(\[Convert\]::FromBase64String\(.*?\)\)\)",d,line)) f = re.sub("\0","",e) line_list.append(f) except: line_list.append(line) with open("c:\\users\\[username]\\desktop\\laz_decoded.ps1","wt") as t: for unit in line_list: t.write(unit)