Speedrunning malware analysis with Exalyze.io

Exalyze.io is a malware analysis platform we developped to help us as well as our fellow malware analysts and reversers during their hunting! Our goal is also to speed-up and streamline the firsts step of a sample analysis.

In this post we will showcase some of its features by analyzing a new strain of malware we dubbed Sentel Agent.

What is Sentel Agent

Sentel Agent is a new malware family identified during our regular threat hunting. As we’ll see, it embeds many features useful as a first foothold for an attacker.

We assess with moderate confidence that this family of sample is probably a custom beacon for red team usage, and that the threat actor is currently testing it against AV engines for detection.

Malware analysis process

When triaging an unknown malware sample, we often encounter the same questions:

We developped the Exalyze.io platform to speed up this analysis process, with several features:

In the following parts of this article, we will use each of these features in order to quickly analyze Sentel Agent samples and extract actionable knowledge about this malware family.

Identifying Sentel Agent’s capabilities using the sequences extraction

During manual malware analysis, a large amount of time is usually spent on cross referencing what we call sensitive external libraries usage (such as CreateProcess, etc), and also which strings are used with those calls. It can tell us quite a lot about what a malware is actually doing, but this is time consuming

With Exalyze, we automatically do this tedious work for you and represent it in a view we call Sequences.

This provides an overview (albeit partial) of the malware capabilities, which enables us to get a basic understanding of the sample capabilities without having to manually reverse it.

The following screenshot comes from the sequences view of the sample 25f7636f415bf868a57eab5a149e2c32b572cbdf54ab55fea603a0c0bbdf7fd2.

By only reading the strings of this sample, we can quickly guess that:

While the sequence view is not 100% exhaustive, it offers a quick overview of what the sample is doing in a few seconds. This is a major time saver when triaging samples.

Finding variants of this malware

Finding malware variants is an interesting task because it enables us as malware analysts to find evolutions of a malware, attribute a sample to a known family, but also to find other samples that may have been used in different attacks.

To tackle this challenge, we introduced a new Control Flow Graph based similarity analysis algorithm named Machoke at BotConf, and this algorithm is what’s used behind the scenes when clicking the Find Similar Samples button on Exalyze.

Using the first sample as a starting point and by pivoting multiple times over similar samples, we where able to find several clusters of samples.

We confirmed with a manual analysis that all of these samples are from the same family, some of them sharing the uncommon Sentel-Agent

Available pivots

Exalyze also offers several search pivots allowing to find variants of this family!

For example, the Import Hash search2 starting from the sample 90cf80cf957f068b23f1895b8de56018a2060d67c46f8422c84ec58e6be774af leads to the discovery of 4 similar samples!

We also extract network indicators from the samples, which can be used for pivoting! For example, we found a probable C2 url http://192.168.1[.]8:5000 in one of the sample, allowing us to pivot to 34 samples at the time of writing.

Useful features for malware analysts

Automated TTP matching

We implemented a set of capabilities detection wich translates back to an ATT&CK Tools Tactics & Procedures3 (TTPs) table than can be included in a report, gaining several minutes when writing an analysis.

Yara rule generation

One of the tasks of malware analysts is to write Yara rules in order to improve the detection of a sample but also find similar ones.

In order facilitate this task, Exalyze comes with a fully fledged Yara rule generator. This generator is also the one used internally at ExaTrack to create new hunting capabilities from discovered malware.

With a single click you will get a ready to go Yara rule, such as the one in this post!

Further analysis

A manual analysis of the sample revealed that the attacker had left the command descriptions in the binary.

While we’re unsure about the why of it (in a sample that should at least try to hide what it is doing), it clearly was an help during our reverse 😀!

The following commands were found implemented:

Command Included help Comment
shell Execute shell command Implements a shell using a PowerShell In-Memory Execution Framework and raw syscalls supporting further basic commands such as ls, cd, …
command Execute shell command (alias)
download Download file from agent
upload Upload file to agent
ps List running processes
kill Terminate process by PID
services List system services
sysinfo Get system information
screenshot Capture desktop screenshot
inject Inject shellcode into process
mimikatz Execute Mimikatz credential extraction
exit Terminate agent
quit Terminate agent (alias)
cd Change current directory
pwd Print working directory

What’s next?

We’re working to integrate new features in the platform, such as Yara matching and extending the pivots! Do not hesitate to try our platform and join our Discord server to contact us!

IOCs

Hashes

All the samples are available on the Exalyze platform!

SHA256 Sample link Comment
25f7636f415bf868a57eab5a149e2c32b572cbdf54ab55fea603a0c0bbdf7fd2 See sample on Exalyze First variant
da04064c03bb202e09eb2c9f2b945ed94264effdeceef10fb2234458ee07c413 See sample on Exalyze First variant, 96% match. Also includes a custom mimikatz module ( mimikatz 2.2.0 (Sentel Agent Integration) - MSV ENABLED)
a8f27e18692052944216dae31fc1530b29e4939f7933c765f3e9b8282eb8a3e0 See sample on Exalyze First variant, 92% match
3d1d57d16e951376188f7ecff31f311c5e7908643eac9890123aaa91a8e62158 See sample on Exalyze First variant, 92% match
c0542fe5420945cd2295f56863905a5625174ae8668236c508aaa2275ed5a167 See sample on Exalyze Second variant
3b6f016270b9c5a1dcbd6f158b9fb93aa6f43ae415e10f55f97afae0f068dc18 See sample on Exalyze Second variant, 100% match
4d21d8e685598cfbace4ed736b7d74d5b4f63526483c6b6c4da01280e72cc31c See sample on Exalyze Second variant, 100% match
3711c53b91b7f822bc9f0f10d3e817c33119670b7c2ea210c9555011e830e31d See sample on Exalyze Second variant, 92% match (also matches with fifth variant)
4dc054ce010c5276dc55dfcda1fa3b3bf9ce90cd564dcd9c76a3ec8587d167d8 See sample on Exalyze Second variant, 92% match (also matches with fifth variant)
63ce4dda2a7b767004bdbf423ccacf4a207bf558460eb1eb0c93fcda9873c895 See sample on Exalyze Second variant, 92% match (also matches with fifth variant)
c19610d27fdaf675bc9b9eff3d717f7caf1fefc1b14b5b5c547ca5f3b779b42a See sample on Exalyze Second variant, 92% match (also matches with fifth variant)
a1c1685ff2fd17bb28b653039aa71ab6dfcc967b2c7a9e3f7df9de7650930501 See sample on Exalyze Second variant, 91% match (also matches with fifth variant)
a2b34065c1171a81828487982bc6e707e454005e0a53d583a68a8ccf62786e4d See sample on Exalyze Third variant
705410e44d03ed8c53827ebdc4feb28f5e8a4d34e16f5c97f76d0bdb5c48a921 See sample on Exalyze Third variant, 93% match
90cf80cf957f068b23f1895b8de56018a2060d67c46f8422c84ec58e6be774af See sample on Exalyze Third variant, 93% match
d17a5b5271be95a775e8cf1ece9df20325ecd78b19b32a111868c480b0818032 See sample on Exalyze Third variant, 93% match
a33d28f6afad944be3715dd0e82fb5d5951e21369644c4a32a66b4c3f34782fc See sample on Exalyze Third variant, 90% match
bdbed1635f78eb558a383a10e0c1ecce1ec23140e267fe4ff28f4f10e52ead19 See sample on Exalyze Third variant, 86% match
7a3163a5c10f44554352ecd7d6e37e9bc82c27e03701fe84c6718a6ad8681b59 See sample on Exalyze Fourth variant
6c05ef7d093dccc5bda576300c65123ad7ecb76b6ec257f33fb7467780f5960e See sample on Exalyze Fourth variant, 96% match with 7a3163a5c10f44554352ecd7d6e37e9bc82c27e03701fe84c6718a6ad8681b59
438ffc114e2d642dd37e6dcd92337f28cec2ae3ac755eb658fbc3576957d1ee7 See sample on Exalyze Fifth variant
104ec5b388314087c1ab51cb843c1089b1684094ea6869d85a89cf2d4c573e52 See sample on Exalyze Fifth variant, 100% match
2f67be7579cfef2d17a14bed00da5b95f55fe00912ed9377037973868c06d08a See sample on Exalyze Fifth variant, 100% match
ed3afacd286b2f4ab0309949b3b7005e5c4f946859c5fa7615c35ded370c92e6 See sample on Exalyze Fifth variant, 100% match
ef05041d872c20579852286cff5ba2cdbd8e413fbcf101b523c706586c545db5 See sample on Exalyze Fifth variant, 100% match
5bc7d673e01199ab0e986736b60c09b56c9fcc1ebf38373ec69c9851a84a8629 See sample on Exalyze Fifth variant, 98% match
179dfc5429c604a0a483ae8cf6ebc56a653c205958194222c63d2ef6e233dcf5 See sample on Exalyze Fifth variant, 96% match
8036db4dbb9ff1aa06613df7042518e04f6a56f6c873769046868db496ec9dce See sample on Exalyze Fifth variant, 96% match
5352fb7dcf7de4b17d0f34b95ca23e769029a797df10d068b981be51be482ce7 See sample on Exalyze Fifth variant, 90% match
30ab47c6ab9b4d3582334d95e274f5ad61b0129fe16e78e020499384e9e7f383 See sample on Exalyze Fifth variant, 90% match
571ccfeee45c72a27465269a10b573e01cda60d59f1b804541261ef1825e5b18 See sample on Exalyze Fifth variant, 90% match
60a472464285dabb253cc11ab9dce15bfdbc714456e1ecf1769a5676952a16ea See sample on Exalyze Fifth variant, 90% match
73d1279d610de91be2ecebf314570907eaa475d23a2a9aacf6251cf8345b0e2b See sample on Exalyze Fifth variant, 90% match
884a27d8a85b868fdb34356b61d23fadbda278e773a22caa478ffa1a2922beee See sample on Exalyze Fifth variant, 89% match
cddeb1f8720b69327a419bfd4e1054f2c5f638c4b5251e5eeaf1ac890f9c8062 See sample on Exalyze Fifth variant, 88% match
76b26832a2ea14bb673fdda94fbda3824c38e6131edd4430c03cbe8a7725dfc3 See sample on Exalyze Fifth variant, 77% match
931711826a6bd596979a26a8df2a81c6d12fd5ed96ee47b1d448c29dec0703de See sample on Exalyze Sixth variant
1fea46ed3b5b818b65e16dcc07ae6b4468afcfbd7bc2d659634c70a409005a53 See sample on Exalyze Sixth variant, 100% match
2515caee7c083f838ac6a585132aa6a86a825565f5b5dadcaa2dc7431be66d9c See sample on Exalyze Sixth variant, 97% match
86a14c68248332dd535dced538331cf72a55e4fbef9aca74a2f93dfdc3678096 See sample on Exalyze Seventh variant
c7afa84b82f74c6e062b185c2e8a121fd9e91651f064e36bf190f9413a7dbd76 See sample on Exalyze Seventh variant, 100% match
cf11d146469aa3326c727768aa946d7a915a790af69a75b6c92a40eff789b45e See sample on Exalyze Seventh variant, 94% match
d79a8f2dcfe3ac6a6819fb00e92f2ca37a1de90cb0664f8b5f6ba709a67166c7 See sample on Exalyze 8th variant
d1858f0d26e0e1f61e56aa4513827d10f0736a7eff84f871e590cedcc6cd9660 See sample on Exalyze Sentel Minimal Stealth Agent
abe676efb67d2230f81f2ea5600af7dd2b0019a23ebbe50d9dc761f5e818e8e0 See sample on Exalyze 9th variant
342791435f009357ae70d930b01b8e2f8a10c8815b8b7a263e81aae36eb22668 See sample on Exalyze Sentel Minimal Stealth Agent wininet variant
8e278bf78b8ed119c903136bfc6fba0740b9d77882d7d6c7e11eb7f4060332a4 See sample on Exalyze Sentel Minimal Stealth Agent

Filenames

Network IOCs

We were not able to find live C2 addresses, as most of the configurations found included local routed addresses such as 127.0.0.1 or 192.168.1.8.

Yara rules


rule auto_sentel_agent {
    meta:
        author = "Exatrack"
        date =   "2025-09-19"
        update =   "2025-09-19"
        description = "Rule autogenerated by Exalyze"
        score =   50
        tlp =  "GREEN"
        source =  "Exalyze"
        sample_hash = "705410e44d03ed8c53827ebdc4feb28f5e8a4d34e16f5c97f76d0bdb5c48a921"
    strings:
        $str_001 = "Directory Contents (via syscalls):" ascii fullword
        $str_002 = "Failed to terminate process %lu (%s): %s" ascii fullword
        $str_003 = "Upload file to agent" ascii fullword
        $str_004 = "Access denied - insufficient privileges" ascii fullword
        $str_005 = "Failed to create process: %lu" ascii fullword
        $str_007 = "Error getting current directory" ascii fullword
        $str_008 = "Failed to load required functions" ascii fullword
        $str_009 = "%s%s/sendMessage" ascii fullword
        $str_010 = "Failed to create process snapshot" ascii fullword
        $str_011 = "Failed to allocate memory for screenshot" ascii fullword
        $str_012 = "/bot%s/getUpdates?offset=%d&timeout=30" ascii fullword
        $str_013 = "%dd %dh %dm" ascii fullword
        $str_014 = "File copied from '%s' to '%s'" ascii fullword
        $str_015 = "Successfully terminated process %lu (%s)" ascii fullword
        $str_016 = "%-32s %-20s %-12s %-12s" ascii fullword
        $str_017 = "http://192.168.1.8:5000" ascii fullword
        $str_018 = "Failed to write complete file" ascii fullword
        $str_019 = "%-30s %-8s %-10s" ascii fullword
        $str_020 = "Failed to enumerate processes" ascii fullword
        $str_021 = " *Agent Beacon*" ascii fullword
        $str_022 = "Directory listing:" ascii fullword
        $str_023 = "%s%s/getMe" ascii fullword
        $str_024 = "Failed to capture screen" ascii fullword
        $str_025 = "Directory Path: Unable to determine" ascii fullword
        $str_027 = "Get-NetIPConfiguration" ascii fullword
        $str_028 = "Command: reg %s" ascii fullword
        $str_029 = "%s%s/getUpdates?offset=%d&timeout=30" ascii fullword
        $str_030 = "[\"192.168.1.1\"]" ascii fullword
        $str_031 = "Invalid file size: %ld" ascii fullword
        $str_033 = "Environment variable '%s' set to '%s'" ascii fullword
        $str_034 = "%.1000s%s" ascii fullword
        $str_035 = "File too large: %ld bytes (max: %ld)" ascii fullword
        $str_036 = "Get-ComputerInfo" ascii fullword
        $str_037 = "Failed to change directory: %lu" ascii fullword
        $str_038 = "%lu-core processor" ascii fullword
        $str_039 = "Cannot open file '%s': %lu" ascii fullword
        $str_040 = "[\"8.8.8.8\",\"8.8.4.4\"]" ascii fullword
        $str_041 = "%Y-%m-%dT%H:%M:%SZ" ascii fullword
        $str_042 = "Capture desktop screenshot" ascii fullword
        $str_043 = "Download file from agent" ascii fullword
        $str_044 = "  VirtualProtect failed with code 0x%x" ascii fullword
        $str_045 = "%s_%s_%d_%ld_%04d" ascii fullword
        $str_046 = "\"encrypted\":true" ascii fullword
        $str_047 = "%-8s %-8s %-32s" ascii fullword
        $str_048 = "Failed to convert filename" ascii fullword
        $str_049 = "Failed to copy file: %lu" ascii fullword
        $str_050 = "Available Physical Memory: %llu MB" ascii fullword
        $str_051 = "  \"encrypted\": true," ascii fullword
        $str_052 = "Total Physical Memory: %llu MB" ascii fullword
        $str_053 = "[-] Error: Invalid shellcode hex format" ascii fullword
        $str_054 = "Windows %d.%d Build %d" ascii fullword
        $str_055 = "AMSI_DISABLE" ascii fullword
        $str_056 = "cmd.exe H" ascii fullword
        $str_057 = "    - PowerShell Engine initialization" ascii fullword
        $str_058 = "Execute shell command (alias)" ascii fullword
        $str_059 = "Error opening directory: 0x%08lx" ascii fullword
        $str_060 = "Failed to allocate memory for file data" ascii fullword
        $str_061 = "Failed to enumerate services: %lu" ascii fullword
        $str_062 = "--working-hours" ascii fullword
        $str_063 = "Command: wmic %s" ascii fullword
        $str_064 = "Terminate agent (alias)" ascii fullword
        $str_065 = "OS Version: %lu.%lu Build %lu" ascii fullword
        $str_066 = "Terminate agent" ascii fullword
        $str_067 = "Directory not found or access denied" ascii fullword
        $str_068 = "Failed to open process %lu: %s" ascii fullword
        $str_069 = "    \"active_connections\": %s" ascii fullword
        $str_070 = "[*] Bypassing GetCurrentDirectory API" ascii fullword
        $str_071 = "Environment variable '%s' not found" ascii fullword
        $str_072 = "List system services" ascii fullword
        $str_073 = "/bot%s/sendMessage" ascii fullword
        $str_074 = "[-] Error: Target process '%s' not found" ascii fullword
        $str_075 = "    - Output pipeline handling" ascii fullword
        $str_076 = " *Task Result*" ascii fullword
        $str_077 = "Failed to load required DLLs" ascii fullword
        $str_078 = "Failed to encode screenshot to base64" ascii fullword
        $str_079 = "%d-%d-%d" ascii fullword
        $str_080 = "%c %12s  %s" ascii fullword
        $str_081 = "File '%s' deleted successfully" ascii fullword
        $str_082 = "%-8lu %-8lu %-32s" ascii fullword
        $str_083 = "--telegram-chat" ascii fullword
        $str_084 = "Error reading directory: 0x%08lx" ascii fullword
        $str_085 = "Failed to delete file '%s': %lu" ascii fullword
        $str_086 = "Screenshot captured successfully" ascii fullword
        $str_087 = "Start Type" ascii fullword
        $str_088 = "Inject shellcode into process" ascii fullword
        $str_089 = "Command failed with exit code: %lu" ascii fullword
        $str_090 = "Usage: copy <source> <destination>" ascii fullword
        $str_091 = "Directory Path: %s" ascii fullword
        $str_092 = "sentel_agent.exe" ascii fullword
        $str_093 = "Terminate process by PID" ascii fullword
        $str_094 = "Failed to get bitmap data" ascii fullword
        $str_095 = "  Unknown pseudo relocation bit size %d." ascii fullword
        $str_096 = "Failed to allocate services buffer" ascii fullword
        $str_097 = "Changed directory to: %s" ascii fullword
        $str_098 = "/bot%s/getMe" ascii fullword
        $str_099 = "Current Directory: [Error retrieving]" ascii fullword
        $str_100 = "Get system information" ascii fullword

        $bin_001 = { e8????????488d????42c6843c70????????488d8d????????e8 }
        $bin_002 = { d9e8c34aff??4c89??e8 }
        $bin_003 = { 4c89??48c7842480000000????????4839??0f45??e8 }
        $bin_004 = { 488d8b????????ba00040000????????a30000e872????????89e9e8 }
        $bin_005 = { 48c7442428????????4c8d05????????48c7442420????????488d15????????e8 }
        $bin_006 = { 48984801??488d??????4829??e8 }
        $bin_007 = { b902000000????????15????????488d0d????????4989??e8 }
        $bin_008 = { c7442428????????48c7442430????????4889??c7442420????????e8 }
        $bin_009 = { 8944????4d89??ba00040000????????8300??e8 }
        $bin_010 = { 41ff??4889??4889??48898424????????e8 }
        $bin_011 = { 4889??f2ae48c7442430????????4c89??e8 }
        $bin_012 = { 0fb690????????8954????0fb680????????ba20000000????????e8 }
        $bin_013 = { 488d0d????????48c70598400100????????c70596400100????????ff15????????eb }
        $bin_014 = { 8d8e????????e8????????4889??c6842471????????e8 }
        $bin_015 = { eb??4c8b??????4989??ba01000000????????7f }
        $bin_016 = { 4d89??ba00000200????????204c8d05????????488d8b????????e8 }
        $bin_017 = { eb??ffc34883????81fb????????75 }
        $bin_018 = { 41b832000000????????d249??f04c8dbc01????????4c89??e8 }
        $bin_019 = { e8????????48984801??4d8d??????eb }
        $bin_020 = { 483d????????76??41b8f4010000????????89f1e8 }
        $bin_021 = { 8b4c????4c8d05????????448b8c24????????8944????e8 }
        $bin_022 = { 76??4889??befeffffff????????ff4c????e8 }
        $bin_023 = { c7442430????????4989??c7442428????????4c89??????e8 }
        $bin_024 = { 448d2485????????4963??4889??48898424????????e8 }
        $bin_025 = { 4889??31db4c8d25????????4c89??e8 }
        $bin_026 = { c7442448????????f3abc7442420????????488d0d????????e8 }
        $bin_027 = { 4889??e8????????488d????41b840000000????????7c }
        $bin_028 = { 4489??????c7442428????????4889??????0f298424????????e8 }
        $bin_029 = { bc24e00200????????f3ab488dbc24????????4889??e8 }
        $bin_030 = { 41b810000000????????ff48??4c24??31d2e8 }
        $bin_031 = { 31c04889??f3aa488b8c24????????e8 }
        $bin_032 = { ffd74889??4889??48898424????????e8 }
        $bin_033 = { bf00040000????????89fa488d??????4829??e8 }
        $bin_034 = { e8????????31c94889??c7842478030000????????e8 }
        $bin_035 = { 004c????4c899c24????????4c8d05????????f20f????e8 }
        $bin_036 = { 4885??75??ba24000000????????5972 }
        $bin_037 = { 4c89??4889??4c899424????????4c89??????e8 }
        $bin_038 = { ffff4c89??ba10000000????????58e8 }
        $bin_039 = { ff15????????80????????48898424????????89e9e8 }
        $bin_040 = { 4d85??c7442464????????75??488d0d????????e8 }

    condition:
        40 of ($str_*) or 16 of ($bin_*)
}

ATT&CK Techniques used

References