{
	"id": "b131a71c-d88f-4ca6-b1c0-d56f6612a75a",
	"created_at": "2026-04-06T00:10:24.378997Z",
	"updated_at": "2026-04-10T13:12:26.85843Z",
	"deleted_at": null,
	"sha1_hash": "19137905e407e99f961b9dfe31c0a4ca49f37bbf",
	"title": "\"LegionLoader\" exposed ! - TEHTRIS",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 256150,
	"plain_text": "\"LegionLoader\" exposed ! - TEHTRIS\r\nBy Pierre-Henri PEZIER\r\nPublished: 2025-02-03 · Archived: 2026-04-05 19:46:44 UTC\r\nThe hidden threat no one is talking about… Yet!\r\nLefebvre Fabien (CTI), Pezier Pierre-Henri (CTI)\r\nLegionLoader, also known as Satacom, CurlyGate, and RobotDropper, is an active downloader that has been operating in\r\nthe shadows, gained significant traction in recent months, quietly amassing over 2,000 samples in just a matter of weeks.\r\nVirusTotal (VT) retro-hunting and live-hunting have allowed us to uncovered an ongoing campaign using LegionLoader that\r\nappears to have kicked off on December 19, 2024.\r\nThis is TEHTRIS Threat Intelligence team analysis. Wee’ll break down everything we’ve uncovered so far (including: list of\r\nIoCs, phishing url, IDAPython script etc.).\r\n#Stayinformed, #staysecured\r\nLegionLoader oldest found sample\r\nVT Submission rate over time\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 1 of 18\n\nThe malware seems to target entities globally, with Brazil emerging as the most affected country, accounting for\r\napproximately 10% of all submissions.\r\nVT Submission per originating country\r\nIn this article, we will delve into the reverse engineering and analysis of the MSI file and the first two stages of this malware\r\ncampaign, uncovering its techniques and behaviors.\r\nThe following list consists of the samples analyzed in the current article. This list is non-exhaustive.\r\nSamples\r\nHashes of “setup.msi”:\r\nType Value\r\nFile Type\r\nComposite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, MSI Installer, Code page: 1252, Name o\r\nRotq App, Create Time/Date: Sun Jan 19 16:03:15 2025, Last Printed: Sun Jan 19 16:03:15 2025, Title: Installation Database,\r\nAuthor: Viqwo Stars Ci, Keywords: Installer, MSI, Database, Comments: This installer database contains the logic and data r\r\nApp., Template: x64;2057, Revision Number: {8D95B8E0-79E2-422A-8620-2E2986EF3D60}, Last Saved Time/Date: Tue J\r\nNumber of Pages: 450, Number of Words: 10, Security: 0\r\nDateTimestamp N/A\r\nSize 59.4 MB\r\nMD5 70a9a5c89b0bb7b8a61515131e3d49f0\r\nSHA256 41c1006feead9af3e9a563e2814acc8550d36b991e0998015cee00ebb0ac4e85\r\nSHA512 abb057c218327b9f82d6fdc9e4a2c4d910356e70c651164b7ba58ef44fa1e470b039a20c1cd046fe15c847cfefa554102e4fe91f05\r\nType Value\r\nFile Type\r\nComposite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, MSI Installer, Security: 0, Code page: 12\r\n{0E8F0152-F75A-41DE-82DC-13392C51F4A9}, Number of Words: 10, Subject: Joas App, Author: Barsoc Quite Sols, Nam\r\nJoas App, Template: x64;2057, Comments: This installer database contains the logic and data required to install Joas App., Ti\r\nKeywords: Installer, MSI, Database, Create Time/Date: Sat Jan 18 12:53:02 2025, Last Saved Time/Date: Sat Jan 18 12:53:02\r\n18 12:53:02 2025, Number of Pages: 450\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 2 of 18\n\nDateTimestamp N/A\r\nSize 59.4 MB\r\nMD5 cc041f6ca77fbb37f083e557ed051055\r\nSHA256 cd72eaba97bb94947529a1e652e2d1cc7197b6224e00bf39e55ad634b7e82047\r\nSHA512 f10c541123b79745c6c4870433cfdba40cc8784bb55cd12a0c7a90356279789395b06048e18b8bca06718be2bc4e10095c46a72\r\nType Value\r\nFile Type\r\nComposite Document File V2 Document, Little Endian, Os: Windows, Version 10.0, MSI Installer, Security: 0, Code page: 12\r\n{38EAC3F4-3CAF-4CEE-9FFA-36F53F42006E}, Number of Words: 10, Subject: Rotq App, Author: Viqwo Stars Ci, Name\r\nRotq App, Template: x64;2057, Comments: This installer database contains the logic and data required to install Rotq App., T\r\nKeywords: Installer, MSI, Database, Create Time/Date: Mon Jan 20 11:06:39 2025, Last Saved Time/Date: Mon Jan 20 11:06\r\nMon Jan 20 11:06:39 2025, Number of Pages: 450\r\nDateTimestamp N/A\r\nSize 59.4 MB\r\nMD5 3f86649d211a7faea0cf75296e3ed3c8\r\nSHA256 e88cb0e892537a1dfd7d7d7a4802caeee43d25f871602466a735df0eb5096eb3\r\nSHA512 e71e8e39f01b1a5b5033c1ff3634ff57ed9a5a25678573aa0d6d40b8ff11dcd89d3e8fcbc9138d331391c402e7bc750507d623732\r\nHashes of “obs.dll” (Dropper payload):\r\nType Value\r\nFile Type PE32+ executable (DLL) (GUI) x86-64, for MS Windows\r\nDateTimestamp 2025-01-18 12:59:37\r\nSize 1.2 MB (pesize = 1.2 MB)\r\nMD5 f7e61f06fc606f68b1f8a6270752b832\r\nSHA256 23f064df01ee9eedf9e1341185505b86148873ccc0a922c64bb085ceb5b091fc\r\nSHA512 fe067a0c121678f9f20248dafd56d7567c531a309dbdba2e58c80242453ede5ae486caab22749dd5b3076fef9b1fe7fdba99946ed\r\nType Value\r\nFile Type PE32+ executable (DLL) (GUI) x86-64, for MS Windows\r\nDateTimestamp 2025-01-19 16:52:44\r\nSize 1.1 MB (pesize = 1.1 MB)\r\nMD5 0b5d9b80c9bbee71482202720d1bbc3a\r\nSHA256 4c3772e12e710645341f18015c05f67e8f320dd13a4259eff05dacca4c664244\r\nSHA512 3ed21f93293d4eb1af2d902f1d2dd678e23c9700b5a43312aec09b60f15d188210b4d7d890bac2d02a62f554b62c4d1f19009b90\r\nType Value\r\nFile Type PE32+ executable (DLL) (GUI) x86-64, for MS Windows\r\nDateTimestamp 2025-01-20 11:31:08\r\nSize 1.1 MB (pesize = 1.1 MB)\r\nMD5 908431381d588caea53a651679dacee8\r\nSHA256 4df98a4f9ecacf1f1676814ad5980dd94d7d33ce4b7d9aec9d96f3c3ea602363\r\nSHA512 e2eb3874ac7c03aa7fd7a2449d7b948962b48552a825c34248902566923f2cca9531adcd9e3a807457e8f7e7fa3856849cea1caf8\r\nHashes of “stage2.exe” (The payload dropped by the previous samples of legion dropper):\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 3 of 18\n\nType Value\r\nFile Type PE32 executable (GUI) Intel 80386, for MS Windows\r\nDateTimestamp 2025-01-19 13:28:07\r\nSize 151.6 kB (pesize = 151.6 kB)\r\nMD5 97a42de72ada85aaa4198559779b58b0\r\nSHA256 76cbe366ea370235dfea2d72378f9d946e49370b4c7bac58e99073e117062e1f\r\nSHA512 77a5f20dcfa8b61196fe98c8c024fdf3bc8f39962d73ee774f308c0091c90b687cbf1f162b6ea8e374ab2b9b2645ec905a5e6eb50e\r\nType Value\r\nFile Type PE32 executable (GUI) Intel 80386, for MS Windows\r\nDateTimestamp 2025-01-17 15:47:34\r\nSize 151.6 kB (pesize = 151.6 kB)\r\nMD5 4756fa2af7d98078f29911d5ffc90ec7\r\nSHA256 b1cff28f26270779d53e14797430d77d9e44911976c916966e4ab2049aa5232e\r\nSHA512 b686b6daa4f37cef3590f3994ef3def41de7022156358f4edd9915102b7c0d084aaaae0eb2d93cda0a8eababc400bc7314d3f619bd\r\nCode details\r\nThe MSI files were created using Advanced Installer, the stage 1 is a 64 bit DLL compiled with Visual C/C++ 2022 as\r\nidentified by DIE and the stage 2 is a 32 bit executable.\r\nTechniques\r\nThe following techniques have been identified by our team:\r\nAnalysis\r\nInitial access\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 4 of 18\n\nThe malware is delivered by “drive by download” technique. Pcrisk has identified insecure websites such as illegal\r\ndownload platforms that redirect use traffic into unverified web pages.\r\nCredit: pcrisk.com\r\nThe malicious pages are usually deleted in few hours. It almost every time inciting the user to redirects himself to a mega\r\nshare with a single zip file in it. The “.monster” TLD is massively used to host the malicious redirection page.\r\nMalicious zip hosted by mega.io\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 5 of 18\n\nThis archive contains 2 files: A 7zip password protected archive, the sole purpose of this protection is to bypass malware\r\nanalysis; and a picture file reminding the password of the next archive to the victim.\r\nMalicious archive content\r\nThe campaign has high activity with 25 unique URL detected in 12H on the 31/01/2025.\r\nMSI\r\nThe sample requires user interaction to execute, triggered by the execution of the setup.msi file.\r\nThe MSI had a VT detection ranging between 3 and 9 out of 60 at the time or analysis.\r\nWithin the MSI, two anti-sandbox mechanisms have been identified.\r\nThe first anti-sandbox measure presents a button with the label “Please verify that you are not a robot.”.\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 6 of 18\n\nAnti sandbox: Are you a robot ?\r\nIn one of the samples, it was observed that a virtual environment is detected through a feature of Advanced Installer. This\r\ndetection can be bypassed by modifying the MSI file using Orca.\r\nDisable the antisandbox using Orca\r\nThe MSI extracts multiple files into a predefined directory within %APPDATA%. These include several clean DLLs and\r\nexecutables, a password-protected archive named iwhgjds.rar, and the extraction utility UnRar.exe. The UnRar.exe utility\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 7 of 18\n\nis used to decompress the archive using a hard coded password embedded in the MSI, revealing the Stage 1 payload, obs.dll.\r\nThe command used for extraction is as follows:\r\n\"C:\\Users\\???\\AppData\\Roaming\\Viqwo Stars Ci\\Rotq App\\UnRar.exe\" x -p3809610121t -o+ \"C:\\Users\\???\\AppData\\Roaming\\Viqwo\r\nFollowing extraction, the MSI executes obsffmpegmux.exe, which sideloads the malicious obs.dll.\r\nA script has been developed to directly extract the data from MSI to dll. It extracts the payload and displays the password\r\nlike this:\r\npython extract_stage1.py setup.msi obs.dll\r\nFile exists. Overwrite? [y/N]: y\r\nFound password: 156427613t\r\nFound rarfile: iwhgjds.rar\r\nfound file: obs.dll\r\nStage 2 extracted to: obs.dll\r\nThis script is attached in appendice.\r\nStage 1 (obs.dll)\r\nStatic analysis\r\nThe exports of this DLL are largely empty. Using scripting in IDA, we identified four exports containing code; however,\r\nthese appear to be largely nonsensical and intended primarily to waste an analyst’s time. The IDA script is available at the\r\nbottom of the article.\r\nWe used BinDiff to compare multiple malicious obs.dll and found out that the similarity score on all functions is 1.00,\r\nwhich indicate exact replicates. The difference between the samples are the stage 2 payload and compilation artifacts.\r\nDynamic analysis\r\nUsing x64dbg, we set a breakpoint on VirtualAlloc to find buffer creation that could indicate unpacking.\r\nHigh entropy buffer\r\nThis buffer is then decoded, revealing the shellcode.\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 8 of 18\n\nShellcode decoding\r\nShellcode entrypoint\r\nAnother buffer in then created and data is copied to it using the rep movsb instruction. This buffer is then decoded,\r\nrevealing the stage 2 executable. We can extract this executable by dumping the memory section of the buffer for further\r\nanalysis.\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 9 of 18\n\nStage 2 decoding\r\nThe api calls are retrieved by hashing the function names with a custom hash. In the following captures from left to right:\r\nthe call to the custom getprocaddress, the hashing function, and the relocation section parsing. A yara is available at the end\r\nof the article to detect this specific method.\r\nShellcode API calls retrieving\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 10 of 18\n\nThe shellcode then proceed to start explorer.exe and use process hollowing to load the malicious stage 2 using\r\nCreateProcessInternalA, ZwQueryInformationProcess, ReadProcessMemory, ZtUnmapViewOfSection,\r\nVirtualAllocEx, WriteProcessMemory and NtResumeThread API calls.\r\nStage2\r\nThe stage2 is not part of LegionDropper, because the malware family is a dropper, any payload can be embedded inside. The\r\nanalysis has been performed on the previously given samples.\r\nStage 2 is responsible for communicating with the command and control (C2) server and appears to be designed to\r\ndownload the final payload. However, all extracted C2 servers were inactive at the time of analysis, preventing further\r\ninvestigation.\r\nThe domain name is hard coded within the executable.\r\nThe user-agent string Mozilla/5.0 (Windows NT 6.3; Trident/7.0; Touch; rv:11.0) like Gecko is decoded by XORing two\r\nvalues:\r\nUser agent decoding\r\nAdditionally, the parameter ‘a’, which is transmitted to the C2 later on, is randomly generated, and always consists of 10\r\ncharacters:\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 11 of 18\n\nParameter ‘a’ generation\r\nOnce these values are set, the malware attempts to establish a connection to the C2 using WinHttpSendRequest.\r\nIf the connection to the C2 was successful, the malware would perform the following actions.\r\nDisables file system redirection by creating a thread that calls Wow64DisableWow64FsRedirection.\r\nDownloads a shellcode, saves it as a .dat file, decrypts it using XTEA, and executes it in memory.\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 12 of 18\n\nShellcode with Xtea decryption\r\nThe malware downloads an additional file from the C2 using URLDownloadToFileA, then creates a directory in %TMP%\r\nwith a randomly generated 15-character name. It copies the downloaded file into this directory under the name svchost,\r\nretaining the original extension, and finally executes it using ShellExecuteA with the “open” option.\r\nSince the malware later attempts to execute the payload using rundll32, it is highly likely that the final payload is a DLL,\r\nwhich is launched via ShellExecuteA with the “open” option.\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 13 of 18\n\nShellExecuteA\r\nIOC\r\nSHA256\r\nSimilar SHA256 samples have been encountered. This is a short list,hundreds of sample have been found.\r\n41c1006feead9af3e9a563e2814acc8550d36b991e0998015cee00ebb0ac4e85\r\ncd72eaba97bb94947529a1e652e2d1cc7197b6224e00bf39e55ad634b7e82047\r\ne88cb0e892537a1dfd7d7d7a4802caeee43d25f871602466a735df0eb5096eb3\r\n21d325a59140755b3cf6b075d5e157f37c2771deb29ae7756092fa8978209f77\r\n7e9d148d6ebcf927292bba0948ab4d006cb0667084a7f43c04ab7d7efcb9074b\r\n23f064df01ee9eedf9e1341185505b86148873ccc0a922c64bb085ceb5b091fc\r\n4df98a4f9ecacf1f1676814ad5980dd94d7d33ce4b7d9aec9d96f3c3ea602363\r\n76cbe366ea370235dfea2d72378f9d946e49370b4c7bac58e99073e117062e1f\r\n8134948177ca6fc350b4c651f27137eaef8dabbb2daf9a1d0447bf1102cfd7d9\r\nHTTP requests\r\nflash3hit.com/front.php\r\nflash-hit.com/front.php\r\nfatal-hit.com/front.php\r\nvikincdesigns.com/front.php\r\nlamotionpicture.com/front.php\r\nFiles and directories\r\nAppdata\\Roaming\\Viqwo Stars Ci\\Rotq App\\iwhgjds.rar\r\nAppdata\\Roaming\\Viqwo Stars Ci\\Rotq App\\obs.dll\r\nAppdata\\Roaming\\Viqwo Stars Ci\\Rotq App\\UnRar.exe\r\nAppData\\Roaming\\Barsoc Quite Sols\\Joas App\\iwhgjds.rar\r\nAppData\\Roaming\\Barsoc Quite Sols\\Joas App\\obs.dll\r\nAppData\\Roaming\\Barsoc Quite Sols\\Joas App\\UnRar.exe\r\nRegistry\r\nHKU\\S-1-5-21-178964467-512603846-2268572703-1002\\SOFTWARE\\Barsoc Quite Sols\\Joas App\\Version\r\nHKU\\S-1-5-21-178964467-512603846-2268572703-1002\\SOFTWARE\\Barsoc Quite Sols\\Joas App\\Path\r\nHKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Folders\\C:\\Users\\???\\AppData\\Roaming\\Barsoc\r\nQuite Sols\\Joas App\\una_front\r\nPhishing URL\r\nHundreds of malicious URL have been found (up to 30 in 12 hours for monster TLD), this is just a shortlist.\r\nPhishing URL Samples related malicious file URL\r\nhttps://linefreeapp[.]monster\r\nd43590b090ac1ece44ded29b03301323958e344394e94c439999f6a2d0648c53,\r\na6b5759a273fd6df4dcb0f5c82935b4b60a6f28bfb4d69b6c7c503c8614c39d0,\r\n17be6c8a4cf914056e5cb5d6a1d087069bd4c8d5a3ed104fefeace42c4fc6083\r\nhttps://mega.nz/file/SN8jG\r\nhttps://dipsos-troak.com/s\r\nhttps://mega.nz/file/GRhg\r\nhttps://dipsos-troak[.]com\r\ne69a7a881daca7637220d0407454e678ef3a9cf373406b363179f002acd8144d,\r\n038cbe87c4ddb39e7c7accc95d221950d96f2adb0649acaaea60258255c203a6\r\nhttps://dipsos-troak.com/s\r\nhttps://dipsos-troak.com/s\r\nhttps://webrecentapp[.]monster/\r\n74ed663ad5369aed6f784d601c1755bbb12ab5df4c5111599332b1bf057d8fe9,\r\nd2bcc865d00890a3ba675dc1952c3470205dc9811d4fb354a0b44630879df7c7\r\nhttps://mega.nz/file/SQ9E\r\nhttps://runstarapp[.]monster/\r\n5b790d2d085d2498aa63822812562acc256a26febae6cc78563ba656eb9d0c1f,\r\n2eae05e829f353c9a8d01683187eb759dbf73f90ccd435f03d46761b03247fbd\r\nhttps://mega.nz/file/nRcB\r\nhttps://topstarapp[.]monster/\r\n4c2c0de6474c17486e5abe2323da0abe4af395a89d0cc46994265ca7719e4ccc,\r\neaaec1cc3ee9a3d590d17c73ab7b174354c1c7be13d26026891424289d0c57fe\r\nhttps://mega.nz/file/wjUV\r\nhttps://saveactiveapps[.]monster/\r\n23d0db70ba7848789fa117d25f2e94936cf06e58a03fc36647defdd91bf6f1ca,\r\ncd0a77c945f9eb2a8e0cc7b16f00b8426b737618da06df7e65c1913eefbcc18b\r\nhttps://mega.nz/file/6nozw\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 14 of 18\n\nhttps://cleanactiveapp[.]monster/\r\n66241b0c08194263eeb62bae9c4e8ef7e38bb447e671638c9c340d305e23af16,\r\n1a43da62d09a56f50e2797cffb77001027461a6b5ef0713c63d96c60bf8ecadd\r\nhttps://mega.nz/file/uFwV\r\nhttps://webnewapp[.]monster/ 49c74021ab818ff7a07c184c920585b96000e9079d5beaed3a3dc0ed2fd4834b https://mega.nz/file/XBQB\r\nhttps://elitenewapp[.]monster/\r\nd8f2f667708a14734a20d7731ab659fa1ab23ddd25ee96ba4ca33fedf4b7c613,\r\n082a0596b474806cc0ea58c4f7067a4f1166dbb4aa1800bc58af6f99f1209a4a\r\nhttps://mega.nz/file/vUtj2\r\nhttps://eliteleaderapp[.]monster/\r\n3938e304ddb11dc02b514e10daa2810bc91fd963e007f5bfba789846e08c6b8e,\r\nb59e172cda955322b0cbdc152f723b82eef222014a631dc3b1d8fe4144480374\r\nhttps://mega.nz/file/xq1H\r\nhttps://freeleaderapp[.]monster/\r\n5f01f481065fefdf0c34c7f1e0a5dd527857962dae46bcbddb4a2b941bf5a3dc,\r\n1f8ec7a76f4486fdff94743275b2d65e1e4c871f7f933ed5c65c1dfca22909be\r\nhttps://mega.nz/file/UtpzlT\r\nhttps://webabilityapp[.]monster/ 75cdf91e7f10807b81e9cc9754dc37d447d46912537f585e6f6b3e2a84fdb7df https://mega.nz/file/87sgE\r\nhttps://topgrandapp[.]monster/ b974015e21e86ca6c89545e86e69732d4dd6e41d588aeb31e4e112a6cd0e237f https://mega.nz/file/3VcyT\r\nhttps://safegrandapp[.]monster/ 77bbf883dc365ca72fa4e5cd203055a2e14787fc363fbf3409ca266c0607185e https://mega.nz/file/9MJx\r\nhttps://extragrandapp[.]monster/ f1064a9546766a69b2df901a0d9df31d31b01c6507cf614ef3ab73f5869af524 https://mega.nz/file/WV5T\r\nhttps://safepowerapp[.]monster/ 82eda9820fc42229b2f75d075ef34d11d1b4feb598983640226770c5e2cf8475 https://mega.nz/file/AVpg\r\nhttps://freepowerapp[.]monster/ 9cd58f52226fc376f837447d0c4ebed7b0473cc4166f9e8ad0265bbfd7ac4462 https://mega.nz/file/toZU1\r\nhttps://getglobal[.]monster f4f4dd8a1fca44d6d7c78da7dc5741b91250eabf8faae79604c786672ea2efb8 https://drive.google.com/f\r\nhttps://sendspeed[.]monster/ d1a0115f4afe30d9a973cb18bf95d34b67b2d548b4d49989fd0e36399dc562d0 https://drive.google.com/f\r\nDetection\r\nyara\r\nrule crypto_alg_obs_dll {\r\n meta:\r\n author = \"PEZIER Pierre-Henri. Copyright TEHTRIS 2025\"\r\n description = \"The cryptographic diffuser of OBS.dll\"\r\n strings:\r\n $obj_180005250 = { // 4707b17284e0bdbb92d915e66a8fe4dff18441c958a5230c786d5af6fa05b4bd \"C:\\Users\\user\\Desktop\\Legi\r\n 49 8d 41 01 // lea rax, [r9+1]\r\n 44 0f b6 c8 // movzx r9d, al\r\n 48 8d 52 01 // lea rdx, [rdx+1]\r\n 43 0f b6 0c 11 // movzx ecx, byte ptr [r9+r10]\r\n 4a 8d 04 19 // lea rax, [rcx+r11]\r\n 44 0f b6 d8 // movzx r11d, al\r\n 43 0f b6 04 13 // movzx eax, byte ptr [r11+r10]\r\n 43 88 04 11 // mov [r9+r10], al\r\n 43 88 0c 13 // mov [r11+r10], cl\r\n 43 0f b6 04 11 // movzx eax, byte ptr [r9+r10]\r\n 48 03 c1 // add rax, rcx\r\n 0f b6 c0 // movzx eax, al\r\n 42 0f b6 0c 10 // movzx ecx, byte ptr [rax+r10]\r\n 30 4a ff // xor [rdx-1], cl\r\n 49 83 e8 01 // sub r8, 1\r\n 75 c1 // jnz short loc_180005250\r\n }\r\n condition:\r\n all of them\r\n}\r\nrule shellcode_library_resolution {\r\n meta:\r\n author = \"PEZIER Pierre-Henri. Copyright TEHTRIS 2025\"\r\n description = \"Legion Loader implementation of GetProcAddress\"\r\n strings:\r\n $hashed_libs = { // 27e48b5e7925fdc17bef8b7efb8576ee336dbfba31b5f3296bfa9d33c906e385 \"C:\\Users\\user\\Desktop\\Legion\r\n ba (4A 0D CE 09|DD F5 53 CD|A0 F7 BF 08|C5 B1 66 2D|33 13 E2 81|4D 82 2E E6|FE 90 CB 49|42 AE C7 F7|2E 97 58 4\r\n 48 [4] // mov rcx, [rsp+0A8h+var_78]\r\n e8 // call RE_GETPROCADDRESS\r\n }\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 15 of 18\n\n$hash_algorithm = { // 27e48b5e7925fdc17bef8b7efb8576ee336dbfba31b5f3296bfa9d33c906e385 \"C:\\Users\\user\\Desktop\\Leg\r\n d1 e8 // shr eax, 1\r\n 8b [3] // mov ecx, [rsp+28h+RE_FUNCNAME]\r\n 81 e1 20 83 b8 ed // and ecx, 0EDB88320h\r\n 33 c1 // xor eax, ecx\r\n 89 ?? ?? // mov [rsp+28h+var_28], eax\r\n eb // jmp short loc_153D97E0662\r\n }\r\n $section_parser = { // 27e48b5e7925fdc17bef8b7efb8576ee336dbfba31b5f3296bfa9d33c906e385 \"C:\\Users\\user\\Desktop\\Leg\r\n c7 44 ?? ?? 20 00 00 00 // mov [rsp+18h+var_10], 20h ; ' '\r\n c7 44 ?? ?? b9 79 37 9e // mov [rsp+18h+var_C], 9E3779B9h\r\n 8b 44 ?? ?? // mov eax, [rsp+18h+var_C]\r\n 0f af 44 // imul eax, [rsp+18h+var_10]\r\n }\r\n $path_loading = { // 27e48b5e7925fdc17bef8b7efb8576ee336dbfba31b5f3296bfa9d33c906e385 \"C:\\Users\\user\\Desktop\\Legio\r\n 48 ?? 5c 53 79 73 57 4f 57 36 // mov rcx, 36574F577379535Ch; \\SysWOW6\r\n [8-16]\r\n 48 ?? 34 5c 65 78 70 6c 6f 72 // mov rcx, 726F6C7078655C34h; 4\\explor\r\n [8-16]\r\n 48 ?? 65 72 2e 65 78 65 00 00 // mov rcx, 6578652E7265h; er.exe\r\n }\r\n condition:\r\n #hashed_libs \u003e 5\r\n or $hash_algorithm\r\n or $section_parser\r\n or $path_loading\r\n}\r\nAppendice\r\nStage 2 extractor\r\n 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n#include \u003cwindows.h\u003e\r\n#include \u003cstdio.h\u003e\r\nchar suffix[] = \"_stage2.exe\";\r\nBYTE writeprocessmemory_trampoline[] = {\r\n0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, \u0026MyWriteProcessMemory\r\n0xFF, 0xE0 // jmp rax\r\n};\r\nBOOL MyWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWrit\r\n{\r\nchar file_name[MAX_PATH + 1] = {0};\r\nif(!GetModuleFileName(NULL, file_name, MAX_PATH) || strlen(file_name) \u003e= MAX_PATH - sizeof(suffix)) {\r\nfprintf(stderr, \"Cannot get file name\\n\");\r\nexit(0);\r\n}\r\nstrncat(file_name, suffix, MAX_PATH);\r\nprintf(\"Stage 2 saved to %s\\n\", file_name);\r\nFILE *out = fopen(file_name, \"wb\");\r\nif(!out) {\r\nfprintf(stderr, \"Cannot open file for writing: %s\\n\", file_name);\r\nexit(0);\r\n}\r\nfwrite(lpBuffer, 1, nSize, out);\r\nfclose(out);\r\nexit(0); // DO NOT EXECUTE THE PAYLOAD\r\nreturn TRUE;\r\n}\r\nint main(int argc, char ** argv)\r\n{\r\nif(argc != 2) {\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 16 of 18\n\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50\r\n51\r\n52\r\n53\r\n54\r\n55\r\nfprintf(stderr, \"Usage: %s \u003cfile_to_extract\u003e\\n\", argv[0]);\r\nreturn 1;\r\n}\r\nDWORD oldprotect;\r\nif(!VirtualProtect(WriteProcessMemory, sizeof(writeprocessmemory_trampoline), PAGE_EXECUTE_READWRITE, \u0026oldprotect))\r\nfprintf(stderr, \"Failed to patch WriteProcessMemory\\n\");\r\nreturn 1;\r\n}\r\nSIZE_T MyWriteProcessMemory_addr = (SIZE_T)\u0026MyWriteProcessMemory;\r\nmemcpy(\u0026writeprocessmemory_trampoline[2], \u0026MyWriteProcessMemory_addr, sizeof(MyWriteProcessMemory_addr));\r\nmemcpy(WriteProcessMemory, writeprocessmemory_trampoline, sizeof(writeprocessmemory_trampoline));\r\nif(!LoadLibrary(argv[1])) {\r\nfprintf(stderr, \"Failed to load the DLL (%i).\\n\", GetLastError());\r\nreturn 2;\r\n}\r\nsystem(\"pause\");\r\n}\r\nIDAPython script to identify exports\r\nimport idc\r\nimport pefile\r\nimport ida_nalt\r\nimport idaapi\r\nfile_path = idc.get_input_file_path()\r\nmype = pefile.PE(file_path)\r\nfor imp in mype.DIRECTORY_ENTRY_EXPORT.symbols:\r\nif idaapi.get_byte(ida_nalt.get_imagebase() + imp.address) != 194:\r\nprint(impt.name, hex(ida_nalt.get_imagebase() + imp.address))\r\nStage1 extractor\r\n 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\nimport magic\r\nimport re\r\nimport shutil\r\nimport subprocess\r\nimport binascii\r\nimport tempfile\r\nfrom pathlib import Path\r\nfrom cabarchive import CabArchive\r\nfrom rarfile import RarFile\r\n\"\"\"\r\npip install git+https://github.com/hughsie/python-cabarchive.git\r\n\"\"\"\r\nCABINET_FILE_HEADER = binascii.unhexlify(\"4D 53 43 46 00 00 00 00\".replace(\" \", \"\"))\r\ndef extract_legionstealer_stage1(file_path: Path, output_file: Path) -\u003e None:\r\n assert \"MSI Installer\" in magic.from_file(file_path), \"The given file is not a MSI executable\"\r\n assert file_path.stat().st_size \u003c 1024 * 1024 * 100, \"File too big\"\r\n data = file_path.read_bytes()\r\n assert (key_re := re.search(rb\"QuiteSes(.{,20}?)(?=#)\", data)), \"Unable to find the rar password. Is it a LegionLoader s\r\n try:\r\n password = key_re.group(1).decode(\"utf-8\")\r\n except UnicodeError:\r\n raise AssertionError(\"Unable to find the rar password. Is it a LegionLoader sample?\") from UnicodeError\r\n print(\"Found password:\", password)\r\n assert (offset := data.find(CABINET_FILE_HEADER)), \"Cannot find cabinet file. Is MSI corrupted ?\"\r\n archive = CabArchive(data[offset:])\r\n assert (rarfile := archive.find_file(\"*.rar\")), \"No rar file in the MSI. Is it a LegionLoader sample?\"\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 17 of 18\n\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50\r\n51\r\n52\r\n53\r\n54\r\n55\r\n56\r\n57\r\n with tempfile.TemporaryDirectory() as _tmp:\r\n tmp = Path(_tmp)\r\n tmp_rar = tmp / \"tmp.rar\"\r\n print(\"Found rarfile:\", rarfile.filename)\r\n tmp_rar.write_bytes(rarfile.buf)\r\n try:\r\n res = subprocess.run([\"/usr/bin/unar\", \"-p\", password, \"-o\", tmp, tmp_rar], capture_output=True)\r\n except FileNotFoundError:\r\n raise AssertionError(\"Unable to find unar. Please install unar (apt install unar).\")\r\n if res.returncode:\r\n raise AssertionError(\"Unable to extract rarfile. Is it a LegionLoader sample?\")\r\n tmp_rar.unlink()\r\n assert len(res := list(tmp.glob(\"*.dll\"))) == 1, \"More than one file found. Is it a LegionLoader sample?\"\r\n print(\"found file:\", res[0].name)\r\n shutil.copy(res[0], output_file)\r\nif __name__ == \"__main__\":\r\n import sys\r\n if len(sys.argv) != 3:\r\n print(\"Usage:\", sys.argv[0], \"\u003cmsi\u003e \u003coutput_stage_2\u003e\", file=sys.stderr)\r\n sys.exit(1)\r\n output_file = Path(sys.argv[2])\r\n if output_file.exists() and input(\"File exists. Overwrite? [y/N]: \") != \"y\":\r\n print(\"exitting\")\r\n else:\r\n extract_legionstealer_stage1(Path(sys.argv[1]), output_file)\r\n print(\"Stage 2 extracted to:\", output_file)\r\nSource: https://tehtris.com/en/blog/legionloader-exposed/\r\nhttps://tehtris.com/en/blog/legionloader-exposed/\r\nPage 18 of 18",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://tehtris.com/en/blog/legionloader-exposed/"
	],
	"report_names": [
		"legionloader-exposed"
	],
	"threat_actors": [],
	"ts_created_at": 1775434224,
	"ts_updated_at": 1775826746,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/19137905e407e99f961b9dfe31c0a4ca49f37bbf.pdf",
		"text": "https://archive.orkl.eu/19137905e407e99f961b9dfe31c0a4ca49f37bbf.txt",
		"img": "https://archive.orkl.eu/19137905e407e99f961b9dfe31c0a4ca49f37bbf.jpg"
	}
}