- https://unit42.paloaltonetworks.com/unit42-krbanker-targets-south-korea-through-adware-and-exploit-kits-2/
- https://threatpost.com/blackmoon-banking-trojan-using-new-infection-technique/125425/
- https://community.rsa.com/community/products/netwitness/blog/2017/05/19/the-blackmoon-trojan-framework
- https://www.fortinet.com/blog/threat-research/over-100-000-south-korean-users-affected-by-blackmoon-campaign.html
- https://www.fidelissecurity.com/threatgeek/threat-intelligence/blackmoon-banking-trojan-new-framework
Analysis
- 1. Loader
- 2.1. Packer
- 2.2. Process Injection
- 2. Main Module
- 2.1. Persistence
- 2.2. Encrypted Strings
- 3. Evolution
- 3.1. Encrypted Strings Evolution
- 3.2. BlackMoon Versions: Latest Version Under Development?
- 3.3. BinDiff
- 3.3.1. 2016-03-03 -> 2016-05-05 Statistics
- 3.3.2. 2016-05-05 -> 2018-06-18 Statistics
- 3.3.3. 2018-06-18 -> 2018-11-01 Statistics
- 3.3.4. 2016-03-03 -> 2016-05-05 Differences
- 3.3.5. 2016-05-05 -> 2018-06-18 Differences
- 3.3.5. 2018-06-18 -> 2018-11-01 Differences
- 4. Conclusions
- 5. Yara Rules and Scripts
- 5.1. BlackMoon Yara Rule
- 5.2. Script to Extract BlackMoon Encrypted Strings
- 6. Other notes
- 6.1. Another sample dated 2018 suspicious of being BlackMoon
1. Loader
1.1. Packer
Most of the analyzed samples's packers are wellknown packers such as PeCompact, Aspack, Fsg or Nspack:1.2. Process Injection
Most of the analyzed samples follow the same strategy, they launch an executable (I think it is choosen randomly) from %system32% folder and they inject the new process (hollow process). The unpacked code will be executed in the context of the new process. Some of the executables that we have seen the malware launchs are: wmiprvse.exe, dwwin.exe, comp.exe, cacls.exe, etc...2. Main Module
2.1. Persistence
The malware installs itself under a HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run's subkey. For most of the older samples, the run subkey is a 8-length combination of lowercase and uppercase letters and numbers. However the analyzed samples that date 2018, install themself in the subkey with fixed name 000C29FC2AB3.Curiously, the sample 00eae37eaaee93b8155e6bad95564c3d95d71e7397653ffcbae4f95614ffa723 that dates 2016-05-05 (from the older samples, one of the newest), installs itself under the same subkey 000C29FC2AB3.
In addition, these samples that create the subkey with name 000C29FC2AB3, they create a mutex named M_Test too (the other samples don't create this mutex).
2.2. Encrypted Strings
Most of the important strings of BlackMoon are encrypted.Here is a capture of the code responsible for decrypting the strings from the sample 09beec989993806345254ca9adcdb034f8649d8a9633bbe8933a52f5093e8be1:
To compose the definitive key that the malware uses to decrypt the strings, it carries an string that is the first part of the key, and then it appends 6 additional characters to that first part of the key. In the capture, the definitive key to be used would be "7ac13b3aa82136afa3090c5137B8a195".
Encrypted strings are like this:
The algorithm used to decrypt each string is rc4(unhexlify(rc4(unhexlify(encrypted_string), key)), key):
3. Evolution
3.1. Encrypted Strings Evolution
We have extracted the strings from samples from different dates, to compare them:Date 2016-02-28:
Sample 5f17cf9aee107458995c434d21263528132b5d0ab8a20121d3de48478ec6c467:
Date 2016-03-03:
Sample 2de1e47c650c0a8865ecc7e7b68379ca071062c0873f46a4addb1aa13b8d48dc:
Date 2016-05-05:
Sample 00eae37eaaee93b8155e6bad95564c3d95d71e7397653ffcbae4f95614ffa723:
Date 2018-06-18:
Sample 80ea86d195bbc4384a1b9a77a2d477e2c4e6dc6d48f3f80447877dbbe41a:
Date 2018-11-01:
Sample 09beec989993806345254ca9adcdb034f8649d8a9633bbe8933a52f5093e:
In the section 2.1 (about persistence), we had already noticed that most of the samples from 2016 create a 8 bytes length subkey under the registry \Run key, with a combination of lowercase and uppercase letters and numbers.
However a sample dated 2016-05-05 and the newer samples dated 2018 create a subkey under \Run with name 000C29FC2AB3. In addition these samples create a mutex with name M_Test (this mutex is not created by the 2016's samples).
If we take a look at the lists of strings, the sample dated 2016-05-05 and the samples dated 2018, all of them have similar lists of encrypted strings, where strings are ordered in similar order (thought they are not totally identicals).
The other samples dated 2016 contain another lists of strings, identical between them, but different from the lists of the samples dated 2018.
3.2. BlackMoon Versions: Latest Version Under Development?
Having in mind the IoCs collected in the previous sections, we can conclude that there is a first version of BlackMoon malware, whose samples are dated around 2016, and other version that could be under development, whose samples we have one of them dated 2016-05-05, and other two dated 2018-06 and 2018-11.Version 1:
- Persistence: 8 bytes length subkey under registry \Run key, with a combination of lowercase and uppercase letters and numbers
- Encrypted strings: "http://", "/ca.php", "?m=", "&h;=", "GET", "?p", "POST", "users.qzone.qq.com", "GET /fcg-bin/cgi_get_portrait.fcg?uins=", etc...
- Samples dated 2016
Version 2 - probably under development version:
- Persistence: subkey under \Run with name 000C29FC2AB3
- Mutex: M_Test
- Encrypted strings: "ScriptControl", "Language", "VBScript", "ExecuteStatement", "Function MACAddress()", "Dim mc,mo", "Set mc=GetObject(\"Winmgmts:\").InstancesOf(\"Win32_NetworkAdapterConfiguration\"), "For Each mo In mc", etc...
- A sample dated 2016-05-05, other 2 samples dated 2018
We have only 3 samples that we have classified as version 2. Probably they are quite similar, but we must have in mind that the lists of encrypted strings for these samples are not totally identical. However, the Run key 000C29FC2AB3 and the mutex M_Test, make us to think these 3 samples are the same version.
From my point of view, these 3 newer samples could be a version that is under development. Because of that, each version 2's sample is a bit different from the others. And because of that, the name M_Test for the mutex and the non-random name for the \Run subkey.
3.3. BinDiff
Lets compare with BinDiff the following samples (once they are already unpacked) trying to understand the evolution of this malware:
Version1:
- 2de1e47c650c0a8865ecc7e7b68379ca071062c0873f46a4addb1aa13b8d48dc
- 2016-03-03
- Original sample packed with Fsg
Version2:
- 00eae37eaaee93b8155e6bad95564c3d95d71e7397653ffcbae4f95614ffa723
- 2016-05-05
- Original sample packed with PeCompact
Version2:
- 80ea86d195bbc4384a1b9a77a2d477e2c4e6dc6d48f3f80447877dbbe41a
- 2018-06-18
- Original sample packed with AsPack
Version2:
- 09beec989993806345254ca9adcdb034f8649d8a9633bbe8933a52f5093e
- 2018-11-01
- Original sample packed with PeCompact
3.3.1. 2016-03-03 -> 2016-05-05 Statistics: 345 matching functions
3.3.2. 2016-05-05 -> 2018-06-18 Statistics: 591 matching functions
3.3.3. 2018-06-18 -> 2018-11-01 Statistics: 1743 matching functions
I think the most interesting indicator about similarity, at least in this case, is the number of matching functions because the unpacked modules were dumped with Volatility's procdump command, with --memory --unsafe modificators. Probably most of the primary and secondary unmatched functions are due to residual parts of the code of the packer in memory and maybe due to recompilations of the code with newer versions of the runtime.
If we compare the paired functions, we find that most of the changes between versions are due to ligth modifications, small fixes, etc... as we will see in the following sections.
3.3.4. 2016-03-03 -> 2016-05-05 Differences:
For example, here is a function from the sample dated 2016-03-03 compared to the same function from the sample dated 2016-05-05, where we can see that small changes were done in this function:
Another function. In this case a larger part of code was removed from the function in the newer version:
Btw, in the case of 2016-03-03 -> 2016-05-05, most of the matching functions are ubicated in totally different addresses:
Probably, in spite of the fact that the code doesn't change a lot and there are a lot of matching functions, a code refactorization was done from version 1 to the first samples of version 2 (around 2016-05).
3.3.5. 2016-05-05 -> 2018-06-18 Differences:
In this case, in addition to the similarity between functions pairs, lot of the matching functions are ubicated in the same offset into the unpacked sample:
This makes us to think both binaries are quite similiar, in spite of the fact that we find minimal changes like in this function:
However, there are other functions with more important changes that make us to think that there have been at least a minimal development between both samples (manual modifications on the code: improvements or fixes, not only recompilation + repacking):
3.3.5. 2018-06-18 -> 2018-11-01 Differences:
Again, lot of the matching functions ubicated in the same offset, and minimal changes between paired functions. And again, some parts of the code with more important changes that suggest a minimal development by the authors between the first and the second sample:
4. Conclusions
From my point of view, there are two main versions of BlackMoon family.
Samples from the first version date first half-year of 2016.
Around May-2016, a new version was started. In the sample that dates 2016-05-05 we can appreciate a code refactorization and more important changes in the code. In addition, we can find changes in the behavior, such as the non-random subkey under the \Run registry key, named 000C29FC2AB3, and the non-random mutex created by the malware with name M_Test.
There are minimal changes between the sample that dates 2018-06-18 and the samples that dates 2016-05-05, and again minimal changes between the samples that dates 2016-11-01 and the sample that dates 2018-06-18. However, there are enough changes between these version 2's samples to appreciate that a development was done by the authors, there must be modifications of the source code between them (not only recompilation + repacking).
My conclussion is, there is a version of the BlackMoon that is under development. We can find quite recent samples (based on the VirusTotal first seen date) of this version under development. I can't say totally sure if the code of that recent samples were modified and compiled in 2018 or previously (in spite of the fact that I think the code was recently modified and it is currently evolving, maybe that samples were only repacked or their bytes lightly modified, or maybe VirusTotal didn't see these samples before).
In addition to the larger changes from the first version to the second version, we can appreciate an evolution of the code of the second version: from the sample 00eae37eaaee93b8155e6bad95564c3d95d71e7397653ffcbae4f95614ffa723 (May-2016), to the sample 80ea86d195bbc4384a1b9a77a2d477e2c4e6dc6d48f3f80447877dbbe41a (June-2018), and to the sample 09beec989993806345254ca9adcdb034f8649d8a9633bbe8933a52f5093e (November-2018). So, from my point of view, it seems there are enough evidences to think that there is a BlackMoon version that is under development and currently evolving.
Samples from the first version date first half-year of 2016.
Around May-2016, a new version was started. In the sample that dates 2016-05-05 we can appreciate a code refactorization and more important changes in the code. In addition, we can find changes in the behavior, such as the non-random subkey under the \Run registry key, named 000C29FC2AB3, and the non-random mutex created by the malware with name M_Test.
There are minimal changes between the sample that dates 2018-06-18 and the samples that dates 2016-05-05, and again minimal changes between the samples that dates 2016-11-01 and the sample that dates 2018-06-18. However, there are enough changes between these version 2's samples to appreciate that a development was done by the authors, there must be modifications of the source code between them (not only recompilation + repacking).
My conclussion is, there is a version of the BlackMoon that is under development. We can find quite recent samples (based on the VirusTotal first seen date) of this version under development. I can't say totally sure if the code of that recent samples were modified and compiled in 2018 or previously (in spite of the fact that I think the code was recently modified and it is currently evolving, maybe that samples were only repacked or their bytes lightly modified, or maybe VirusTotal didn't see these samples before).
In addition to the larger changes from the first version to the second version, we can appreciate an evolution of the code of the second version: from the sample 00eae37eaaee93b8155e6bad95564c3d95d71e7397653ffcbae4f95614ffa723 (May-2016), to the sample 80ea86d195bbc4384a1b9a77a2d477e2c4e6dc6d48f3f80447877dbbe41a (June-2018), and to the sample 09beec989993806345254ca9adcdb034f8649d8a9633bbe8933a52f5093e (November-2018). So, from my point of view, it seems there are enough evidences to think that there is a BlackMoon version that is under development and currently evolving.
5. Yara Rules and Scripts
5.1. BlackMoon Yara Rule
Unpacked module:
rule blackmoon_unpacked {
strings:
$code1 = { 89 45 ?? 68 01 01 00 80 6A 00 68 ?? 00 00 00 68 01 00 00 00 BB ?? ?? 00 00 E8 ?? ?? ?? ?? 83 C4 10 }
$code2 = { FF 75 ?? FF 75 ?? FF 75 ?? FF 75 ?? FF 75 ?? FF 75 ?? FF 75 ?? B9 ?? ?? 00 00 E8 }
condition:
(all of them)
}
5.2. Script to Extract BlackMoon Encrypted Strings
The following script extracts and decrypts the encrypted strings from a BlackMoon unpacked sample:python strings_decryptor.py <path to unpacked blackmoon>
import os
import sys
import binascii
import traceback
#################################################
def rc4(data, key):
x = 0
box = range(256)
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
box[i], box[x] = box[x], box[i]
x = 0
y = 0
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
return ''.join(out)
#################################################
def findencstrings(s):
l = []
laststr = ""
for i in range(0, len(s)):
if s[i] in "0123456789ABCDEF":
laststr += s[i]
else:
if ord(s[i])==0 and len(laststr)>=6: l.append(laststr)
laststr = ""
return l
#################################################
def decstr(s, k, k2):
sorig=s
try:
if len(s)%2: s = s[0:-1]
s = binascii.unhexlify(s)
s = rc4(s, k+k2)
step1 = s
if len(s)%2: s = s[0:-1]
s = binascii.unhexlify(s)
s = rc4(s, k+k2)
return True, s
except Exception as e:
return False, "ERROR:" + repr(e) + ", string:" + sorig
#################################################
def findkey1(s):
l = []
laststr = ""
for i in range(0, len(s)):
if s[i] in "0123456789abcdefABCDEF":
laststr += s[i]
else:
if ord(s[i])==0 and len(laststr)>=20 and len(laststr)<=30 and not len(laststr)%2 and laststr not in l: l.append(laststr)
laststr = ""
if len(l): return l
return None
#################################################
def findkey2(s):
key=""
for i in range(0x0, len(s)-0x100):
if s[i:i+8]=="\x68\x01\x01\x00\x80\x6a\x00\x68" and s[i+8] in "0123456789abcdefABCDEF" and s[i+9:i+12]=="\x00\x00\x00":
key+=s[i+8]
return key
#################################################
def get_strings_from_pe(s):
ldecs = []
lenc = findencstrings(s)
lk1 = findkey1(s)
k2 = findkey2(s)
if lk1 and k2 and lenc:
for k1 in lk1:
for i in range(0,len(k2)-6):
for senc in lenc:
decs = decstr(senc, k1, k2[i:i+6])
if decs[0]: ldecs.append(decs[1])
return ldecs
#################################################
def analexe(s):
decrypted_string_list = []
try: decrypted_string_list = get_strings_from_pe(s)
except Exception as e:
print "blackmoon exception in get_strings_from_pe"
print traceback.format_exc()
for e in decrypted_string_list:
print "blackmoon decrypted string:", e
#################################################
if __name__ == "__main__":
if os.path.exists(sys.argv[1]):
f = open(sys.argv[1], "rb")
s = f.read()
f.close()
analexe(s)
else:
print "Incorrect path"
6. Other Notes
6.1. Another sample dated 2018 suspicious of being BlackMoon
I toke a quick look at this sample, here you can find the unpacked module. Some interesting strings from this unpacked module:
- http://aa.mrmr11[.]cn:8000/fdeee.dll
- yPBfy0A4q1Y3gvgmREe0r1UR0fZVidMd4V8CB3oKTzNaOYCyPaSVz48Sw5mVifR3sVxYgeM7EyVu6DwnrfAG/AxGgDr+9GIP3cQ59d/eLtPqTBMb7bzrty65ymU5lH4omQOCFGqOfHggHlhjv97kF1eKnstRomin+KSVtT1TWWtI4BqcY6tP7xJBMzDUgouwpGUwzDY4wnnDEU+8B+MtEncFn1EOAXA3ZMW3/3mVwLFpKP9XH6xJSjjJqbXr4y1VqqwH/lZOYnPVcYlpfbmwdOYvbsIwCxLaU1HvWmBiDNxKRTLhhXAn3GuBy5OzbI01IVVnQtG2WrbM2T5Rk6m1+eMW2c90Uouf7pTesS6m8oCNEclwGQNZtpEIZojzjwPSrPUQPxz/sKtHrhMEdl90wI+GyO7mwvrONsO6h+OvYas6f2QgxxiaIYlK/IJIVFM=
- C:\Program Files\AppPatch\lpDllName
- 360zipUpdate.EXE
The original sample was packed with Aspack, as other recent BlackMoon samples. However this first unpacked module doesn't look like BlackMoon: the code, the strings, etc... are totally different.
Anyway, when I have analyzed this sample, the dll that it tries to download (http://aa.mrmr11[.]cn:8000/fdeee.dll) had been already removed. Maybe that dll was the BlackMoon module. I can't be sure if this sample is BlackMoon or not (this other any.run analysis contains this same IoC: "C:\Program Files\AppPatch\lpDllName", it downloads a dll too, and the second process name is similar format. Maybe same family. This other one was tagged as #trojan #dupzom).
No comments:
Post a Comment