Xeno Rat — Basic Malware Analysis

Andrew Petrus
5 min readMar 13, 2024

--

In this post I’ll be providing a really quick and basic malware analysis of Xeno Rat.
If you don’t recognize the name, that’s fine, Xeno Rat is like the new kid on the block for RATs.
Released in mid October 2023, it’s quickly taken off in the malware space due to it’s open-source nature.
If you’d like to see it in action, check out the following post I’ve written.

Malware sample:

For the purpose of this analysis I have created a test stub with the default information that Xeno Rat prefills into the stub builder.
Check out my previous post on this RAT to see how simple it is to generate a stub.

Static Analysis:

To start our analysis, we’ll open the stub in PEStudio.

File type: 32-bit PE (portable executable), as indicated by the first two bytes ‘MZ’ in the .text section

Language: C# (.NET Framework)

Compiler timestamp: Sat Apr 09 13:44:02 2067 | UTC

SHA256: EEF18C81FAEEE1877AA9CD8D8AEF18B643A434FD3DA221CC724070EC863E5FCD

Main tab - PEStudio
Indicators tab — PEStudio

Imphash: Let’s briefly talk about the imphash for this sample and why we won’t be using it. If you try to look this up, you might find results from other malware families.
To touch on this, it’s due to the fact that the compiler of the majority of.NET executables will set the entry point of the program to the _CorExeMain function from the mscoree library.
This is because _CorExeMain initializes the CLR (Common Language Runtime), which is basically what loads the rest of the PE’s code, including the remaining libraries, at runtime. It is for this reason that we can’t rely on the imphash for a sample based on the .NET framework.
I highly recommend the following post by Joseliyo, who explains this brilliantly.
We can see a visual representation of the imphash by looking at the IAT (Import Address Table) of our sample in CFF Explorer. As you can see below, the imphash for this PE is simply the .NET runtime execution engine which is why it’s unusable for detection.

Visual representation of Imphash: F34D5F2D4577ED6D9CEEC516C1F5A744:mscoree._corexemain

Plan B: If you read the post linked above by Joseliyo, you’ll know that we should be using the TypeRefHash for .NET PE’s instead.

TypeRef Hash: 3644a5b99f77b9a64d458c8c7b006f8c2210430867b0c34f63c51049f62616ad

GUID: BEEF7B59–21B1–43BC-BEA4-A6168D4B668

TypeLibID: 310FC5BE-6F5E-479C-A246–6093A39296C0

Strings (some interesting ones):
My sample is not obfuscated, and the strings section of PEStudio has a plethora of valuable information. It tells me a lot about what this executable is capable of. I will list a couple of strings that caught my eye.

  • L0MgY2hvaWNlIC9DIFkgL04gL0QgWSAvVCAzICYgRGVsICI=
    The above is a base64 encoded string of:
    /C choice /C Y /N /D Y /T 3 & Del
    Xeno Rat uses this command in CMD to uninstall itself (more info).
Uninstall function in Xeno Rat source code
  • 630DCD2966C4336691125448BBB25B4FF412A49C732DB2C8ABC1B8581BD710DD
    Now this one caught my eye. I’m not sure how useful this could be as an IOC, but after some research, I found out that this is a SHA256 hash test vector found in the libtomcrypt hash_tv.txt file.
    I kept finding this same hash in multiple different samples of Xeno Rat that I created.
  • 1D1CC35EA61331C5A85D2A960611153E37A62DCD916269D6E3B5A0DAC2EF3824
    I also found this SHA256 hash existed in multiple samples but couldn’t find any info on what it is. It could be another test vector hash (please reach out to me on Twitter if you figure out what this is).
  • Xeno_rat_nd8912d
    This is the default mutex name that Xeno Rat assigns; if an attacker leaves it unchanged, it could make a great IOC.

- Full list of strings: https://pastebin.com/AED76vFz

Libraries:
-
mscoree.dll (default in most .NET applications)
-
ntdll.dll
-
kernel32.dll
-
msvcrt.dll
-
shell32.dll
-
user32.dll
- User32.dll (duplicate?) A brief note on this:
It looks like the author intentionally imported this library into the PE. The library is explicitly called in the Utils.cs file so that the author can use the function GetLastInputInfo.

User32.dll explicitly imported in source code
Xeno Rat imported libraries

Suspicious Imports/Namespaces:
A lot of these imports are what make the HVNC functionality of Xeno Rat possible (check out the Hvnc.cs file in the repo to learn more).

Suspicious imports

Dynamic Analysis:

I don’t see the need to perform dynamic analysis at this point in this analysis as I am satisfied with the information I have obtained during the static analysis.
After all, we are only analyzing our personally created samples running through localhost so it’s not like we are looking for specific C2 server to add as an IOC.

YARA:

To wrap this post up, I’ve created a YARA rule with a list of IOCs that I’ve gathered during my analysis of Xeno Rat:

rule XenoRat {
meta:
description = "Generic rule to detect Xeno Rat"
author = "Andrew Petrus"
reference = "https://medium.com/@andrew.petrus/xeno-rat-basic-malware-analysis-1d71dd5c613f"
date = "2024-03-13"
hash1 = "eef18c81faeee1877aa9cd8d8aef18b643a434fd3da221cc724070ec863e5fcd"

strings:
$s1 = "xeno rat client.exe" fullword ascii
$s2 = "Xeno_manager.exe" fullword wide
$s3 = "xeno rat client" fullword ascii
$s4 = "Xeno_rat_nd8912d" fullword wide
$s5 = "XenoUpdateManager" fullword wide
$s6 = "error with subnode, subnode type=" fullword wide
$s7 = "RecvAllAsync_ddos_unsafer" fullword ascii
$s8 = "RecvAllAsync_ddos_safer" fullword ascii
$s9 = "/xeno_rat_client.DllHandler+<DllNodeHandler>d__3" fullword ascii
$s10 = "-xeno_rat_client.Utils+<GetIdleTimeAsync>d__20" fullword ascii

$x1 = "630DCD2966C4336691125448BBB25B4FF412A49C732DB2C8ABC1B8581BD710DD" fullword ascii
$x2 = "1D1CC35EA61331C5A85D2A960611153E37A62DCD916269D6E3B5A0DAC2EF3824" fullword ascii
$x3 = "nothingset" fullword wide
$x4 = "SELECT * FROM AntivirusProduct" fullword wide
$x5 = "GetAntivirus" fullword ascii
$x6 = "CapturingConsoleWriter" fullword ascii
$x7 = "<currwin>5__2" fullword ascii
$x8 = "L0MgY2hvaWNlIC9DIFkgL04gL0QgWSAvVCAzICYgRGVsICI=" fullword wide
$x9 = "$310fc5be-6f5e-479c-a246-6093a39296c0" fullword ascii

$z1 = "mutex_string" fullword ascii
$z2 = "/query /v /fo csv" fullword wide

condition:
uint16(0) == 0x5a4d and filesize < 300KB and
(1 of ($s*)) or
(2 of ($x*) and all of ($z*)) or
(all of ($x*))
}

Wrapping things up

If you’ve reached it this far, I’d like to thank you for sticking around and reading my basic analysis report of Xeno Rat.

Feel free to reach out to me on Twitter (@AndrewPetrus) for any questions or comments.

--

--