{
	"id": "75b139e8-0f3f-4c24-9ae5-76dbdf750c15",
	"created_at": "2026-04-06T00:18:31.895473Z",
	"updated_at": "2026-04-10T13:11:39.13714Z",
	"deleted_at": null,
	"sha1_hash": "dfc81cba8b10a0899c74bbf8de1f9bfe2949cbd1",
	"title": "An In-Depth analysis of the new Taurus Stealer",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2239728,
	"plain_text": "An In-Depth analysis of the new Taurus Stealer\r\nBy mpeintner\r\nPublished: 2021-05-07 · Archived: 2026-04-05 12:49:31 UTC\r\nIntroduction\r\nTaurus Stealer, also known as Taurus or Taurus Project, is a C/C++ information stealing malware that has been in the wild\r\nsince April 2020. The initial attack vector usually starts with a malspam campaign that distributes a malicious attachment,\r\nalthough it has also been seen being delivered by the Fallout Exploit Kit. It has many similarities with Predator The Thief at\r\ndifferent levels (load of initial configuration, similar obfuscation techniques, functionalities, overall execution flow, etc.) and\r\nthis is why this threat is sometimes misclassified by Sandboxes and security products. However, it is worth mentioning that\r\nTaurus Stealer has gone through multiple updates in a short period and is actively being used in the wild. Most of the\r\nchanges from earlier Taurus Stealer versions are related to the networking functionality of the malware, although other\r\nchanges in the obfuscation methods have been made. In the following pages, we will analyze in-depth how this new Taurus\r\nStealer version works and compare its main changes with previous implementations of the malware.\r\nUnderground information\r\nThe malware appears to have been developed by the author that created Predator The Thief, “Alexuiop1337”, as it was\r\npromoted on their Telegram channel and Russian-language underground forums, though they claimed it has no connection to\r\nTaurus. Taurus Stealer is advertised by the threat actor “Taurus Seller” (sometimes under the alias “Taurus_Seller”), who\r\nhas a presence on a variety of Russian-language underground forums where this threat is primarily sold. The following\r\nfigure shows an example of this threat actor in their post on one of the said forums:\r\nFigure 1. Taurus Seller post in underground forums selling Taurus Stealer\r\nThe initial description of the ad (translated by Google) says:\r\nStiller is written in C ++ (c ++ 17), has no dependencies (.NET Framework / CRT, etc.).\r\nThe traffic between the panel and the build is encrypted each time with a unique key.\r\nSupport for one backup domain (specified when requesting a build).\r\nWeight: 250 KB (without obfuscation 130 KB).\r\nThe build does not work in the CIS countries.\r\nTaurus Stealer sales began in April 2020. The malware is inexpensive and easily acquirable. Its price has fluctuated\r\nsomewhat since its debut. It also offers temporal discounts (20% discount on the eve of the new year 2021, for example). At\r\nthe time of writing this analysis, the prices are:\r\nConcept  Price \r\nLicense Cost – (lifetime)  150 $ \r\nUpgrade Cost   0 $ \r\nTable 1. Taurus Stealer prices at the time writing this analysis\r\nThe group has on at least one occasion given prior clients the upgraded version of the malware for free. As of January 21,\r\n2021, the group only accepts payment in the privacy-centric cryptocurrency Monero. The seller also explains that the\r\nlicense will be lost forever if any of these rules are violated (ad translated by Google):\r\nIt is forbidden to scan the build on VirusTotal and similar merging scanners\r\nIt is forbidden to distribute and test a build without a crypt\r\nIt is forbidden to transfer project files to third parties\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 1 of 39\n\nIt is forbidden to insult the project, customers, seller, coder\r\nThis explains why most of Taurus Stealer samples found come packed.\r\nPacker\r\nThe malware that is going to be analyzed during these lines comes from the packed sample\r\n2fae828f5ad2d703f5adfacde1d21a1693510754e5871768aea159bbc6ad9775, which we had successfully detected and\r\nclassified as Taurus Stealer. However, it showed some different behavior and networking activity, which suggested a new\r\nversion of the malware had been developed. The first component of the sample is the Packer. This is the outer layer of\r\nTaurus Stealer and its goal is to hide the malicious payload and transfer execution to it in runtime. In this case, it will\r\naccomplish its purpose without the need to create another process in the system. The packer is written in C++ and its\r\narchitecture consists of 3 different layers, we will describe here the steps the malware takes to execute the payload through\r\nthese different stages and the techniques used to and slow-down analysis.\r\nFigure 2. 2fae828f5ad2d703f5adfacde1d21a1693510754e5871768aea159bbc6ad9775 Packer layers\r\nLayer 1 The first layer of the Packer makes use of junk code and useless loops to avoid analysis and prevent detonation in\r\nautomated analysis systems. In the end, it will be responsible for executing the following essential tasks:\r\n1. Allocating space for the Shellcode in the process’s address space\r\n2. Writing the encrypted Shellcode in this newly allocated space.\r\n3. Decrypting the Shellcode\r\n4. Transferring execution to the Shellcode\r\nThe initial WinMain() method acts as a wrapper using junk code to finally call the actual “main” procedure. Memory for the\r\nShellcode is reserved using VirtualAlloc and its size appears hardcoded and obfuscated using an ADD instruction. The pages\r\nare reserved with read, write and execute permissions (PAGE_EXECUTE_READWRITE).\r\nFigure 3. Memory allocation for the Shellcode\r\nWe can find the use of junk code almost anywhere in this first layer, as well as useless long loops that may prevent the\r\nsample from detonating if it is being emulated or analyzed in simple dynamic analysis Sandboxes. The next step is to load\r\nthe Shellcode in the allocated space. The packer also has some hardcoded offsets pointing to the encrypted Shellcode and\r\ncopies it in a loop, byte for byte. The following figure shows the core logic of this layer. The red boxes show junk code\r\nwhilst the green boxes show the main functionality to get to the next layer.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 2 of 39\n\nFigure 4. Core functionality of the first layer\r\nThe Shellcode is decrypted using a 32 byte key in blocks of 8 bytes. The decryption algorithm uses this key and the\r\nencrypted block to perform arithmetic and byte-shift operations using XOR, ADD, SUB, SHL and SHR. Once the Shellcode\r\nis ready, it transfers the execution to it using JMP EAX, which leads us to the second layer.\r\nFigure 5. Layer 1 transferring execution to next layer\r\nLayer 2 Layer 2 is a Shellcode with the ultimate task of decrypting another layer. This is not a straightforward process, an\r\noverview of which can be summarized in the following points:\r\n1. Shellcode starts in a wrapper function that calls the main procedure.\r\n2. Resolve LoadLibraryA and GetProcAddress from kernel32.dll\r\n3. Load pointers to .dll functions\r\n4. Decrypt layer 3\r\n5. Allocate decrypted layer\r\n6. Transfer execution using JMP\r\nFinding DLLs and Functions This layer will use the TIB (Thread Information Block) to find the PEB (Process Environment\r\nBlock) structure, which holds a pointer to a PEB_LDR_DATA structure. This structure contains information about all the\r\nloaded modules in the current process. More precisely, it traverses the InLoadOrderModuleList and gets the BaseDllName\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 3 of 39\n\nfrom every loaded module, hashes it with a custom hashing function and compares it with the respective “kernel32.dll”\r\nhash.\r\nFigure 6. Traversing InLoadOrderModuleList and hashing BaseDllName.Buffer to find kernel32.dll\r\nOnce it finds “kernel32.dll” in this doubly linked list, it gets its DllBase address and loads the Export Table. It will then use\r\nthe AddressOfNames and AddressOfNameOrdinals lists to find the procedure it needs. It uses the same technique by\r\nchecking for the respective “LoadLibraryA” and “GetProcAddress” hashes. Once it finds the ordinal that refers to the\r\nfunction, it uses this index to get the address of the function using AddressOfFunctions list.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 4 of 39\n\nFigure 7. Resolving function address using the ordinal as an index to AddressOfFunctions list\r\nThe hashing function being used to identify the library and function names is custom and uses a parameter that makes it\r\nsupport both ASCII and UNICODE names. It will first use UNICODE hashing when parsing InLoadOrderModuleList (as it\r\nloads UNICODE_STRING DllBase) and ASCII when accessing the AddressOfNames list from the Export Directory.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 5 of 39\n\nFigure 8. Custom hashing function from Layer 2 supporting both ASCII and UNICODE encodings\r\nOnce the malware has resolved LoadLibraryA and GetProcAddress from kernel32.dll, it will then use these functions to\r\nresolve more necessary APIs and save them in a “Function Table”. To resolve them, it relies on loading strings in the stack\r\nbefore the call to GetProcAddress. The API calls being resolved are:\r\nGlobalAlloc\r\nGetLastError\r\nSleep\r\nVirtualAlloc\r\nCreateToolhelp32Snapshot\r\nModule32First\r\nCloseHandle\r\nFigure 9. Layer 2 resolving functions dynamically for later use\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 6 of 39\n\nDecryption of Layer 3 After resolving .dlls and the functions it enters in the following procedure, responsible of preparing\r\nthe next stage, allocating space for it and transferring its execution through a JMP instruction.\r\nFigure 10. Decryption and execution of Layer 3 (final layer)\r\nLayer 3 This is the last layer before having the unpacked Taurus Stealer. This last phase is very similar to the previous one\r\nbut surprisingly less stealthy (the use of hashes to find .dlls and API calls has been removed) now strings stored in the\r\nstack, and string comparisons, are used instead. However, some previously unseen new features have been added to this\r\nstage, such as anti-emulation checks. This is how it looks the beginning of this last layer. The value at the address\r\n0x00200038 is now empty but will be overwritten later with the OEP (Original Entry Point). When calling unpack the first\r\ninstruction will execute POP EAX to get the address of the OEP, check whether it is already set and jump accordingly. If\r\nnot, it will start the final unpacking process and then a JMP EAX will transfer execution to the final Taurus Stealer.\r\nFigure 11. OEP is set. Last Layer before and after the unpacking process.\r\nFinding DLLs and Functions As in the 2nd layer, it will parse the PEB to find DllBase of kernel32.dll walking through\r\nInLoadOrderModuleList, and then parse kernel32.dll Exports Directory to find the address of LoadLibraryA and\r\nGetProcAddress. This process is very similar to the one seen in the previous layer, but names are stored in the stack instead\r\nof using a custom hash function.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 7 of 39\n\nFigure 12. Last layer finding APIs by name stored in the stack instead of using the hashing approach\r\nOnce it has access to LoadLibraryA and GetProcAddressA it will start resolving needed API calls. It will do so by storing\r\nstrings in the stack and storing the function addresses in memory. The functions being resolved are:\r\nVirtualAlloc\r\nVirtualProtect\r\nVirtualFree\r\nGetVersionExA\r\nTerminateProcess\r\nExitProcess\r\nSetErrorMode\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 8 of 39\n\nFigure 13. Last Layer dynamically resolving APIs before the final unpack\r\nAnti-Emulation After resolving these API calls, it enters in a function that will prevent the malware from detonating if it is\r\nbeing executed in an emulated environment. We‘ve named this function anti_emulation. It uses a common environment-based opaque predicate calling SetErrorMode API call.\r\nFigure 14. Anti-Emulation technique used before transferring execution to the final Taurus Stealer\r\nThis technique has been previously documented. The code calls SetErrorMode() with a known value (1024) and then calls it\r\nagain with a different one. SetErrorMode returns the previous state of the error-mode bit flags. An emulator not\r\nimplementing this functionality properly (saving the previous state), would not behave as expected and would finish\r\nexecution at this point.   Transfer execution to Taurus Stealer After this, the packer will allocate memory to copy the clean\r\nTaurus Stealer process in, parse its PE (more precisely its Import Table) and load all the necessary imported functions. As\r\npreviously stated, during this process the offset 0x00200038 from earlier will be overwritten with the OEP (Original Entry\r\nPoint). Finally, execution gets transferred to the unpacked Taurus Stealer via JMP EAX.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 9 of 39\n\nFigure 15. Layer 3 transferring execution to the final unpacked Taurus Stealer\r\nWe can dump the unpacked Taurus Stealer from memory (for example after copying the clean Taurus process, before the\r\ncall to VirtualFree). We will focus the analysis on the unpacked sample with hash\r\nd6987aa833d85ccf8da6527374c040c02e8dfbdd8e4e4f3a66635e81b1c265c8.\r\nTaurus Stealer (Unpacked)\r\nThe following figure shows Taurus Stealer’s main workflow. Its life cycle is not very different from other malware\r\nstealers. However, it is worth mentioning that the Anti-CIS feature (avoid infecting machines coming from the\r\nCommonwealth of Independent States) is not optional and is the first feature being executed in the malware.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 10 of 39\n\nFigure 16. Taurus Stealer main workflow\r\nAfter loading its initial configuration (which includes resolving APIs, Command and Control server, Build Id, etc.), it will\r\ngo through two checks that prevent the malware from detonating if it is running in a machine coming from the\r\nCommonwealth of Independent States (CIS) and if it has a modified C2 (probably to avoid detonating on cracked builds).\r\nThese two initial checks are mandatory. After passing the initial checks, it will establish communication with its C2 and\r\nretrieve dynamic configuration (or a static default one if the C2 is not available) and execute the functionalities accordingly\r\nbefore exfiltration. After exfiltration, two functionalities are left: Loader and Self-Delete (both optional). Following this, a\r\nclean-up routine will be responsible for deleting strings from memory before finishing execution. Code Obfuscation Taurus\r\nStealer makes heavy use of code obfuscation techniques throughout its execution, which translates to a lot of code for every\r\nlittle task the malware might perform. Taurus string obfuscation is done in an attempt to hide traces and functionality from\r\nstatic tools and to slow down analysis. Although these techniques are not complex, there is almost no single relevant string\r\nin cleartext. We will mostly find:\r\nXOR encrypted strings\r\nSUB encrypted strings\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 11 of 39\n\nXOR encrypted strings We can find encrypted strings being loaded in the stack and decrypted just before its use. Taurus\r\nusually sets an initial hardcoded XOR key to start decrypting the string and then decrypts it in a loop. There are different\r\nvariations of this routine. Sometimes there is only one hardcoded key, whilst other times there is one initial key that decrypts\r\nthe first byte of the string, which is used as the rest of the XOR key, etc. The following figure shows the decryption of the\r\nstring “\\Monero” (used in the stealing process). We can see that the initial key is set with ‘PUSH + POP’ and then the same\r\nkey is used to decrypt the whole string byte per byte. Other approaches use strcpy to load the initial encrypted string directly,\r\nfor instance.\r\nFigure 17. Example of “\\Monero” XOR encrypted string\r\nSUB encrypted strings This is the same approach as with XOR encrypted strings, except for the fact that the decryption is\r\ndone with subtraction operations. There are different variations of this technique, but all follow the same idea. In the\r\nfollowing example, the SUB key is found at the beginning of the encrypted string and decryption starts after the first byte.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 12 of 39\n\nFigure 18. Example of “DisplayVersion” SUB encrypted string\r\nEarlier Taurus versions made use of stack strings to hide strings (which can make code blocks look very long). However,\r\nthis method has been completely removed by the XOR and SUB encryption schemes – probably because these methods do\r\nnot show the clear strings unless decryption is performed or analysis is done dynamically. Comparatively, in stack strings,\r\none can see the clear string byte per byte. Here is an example of such a replacement from an earlier Taurus sample, when\r\nresolving the string “wallet.dat” for DashCore wallet retrieval purposes. This is now done via XOR encryption:  \r\nFigure 19. Stack strings are replaced by XOR and SUB encrypted strings\r\nThe combination of these obfuscation techniques leads to a lot of unnecessary loops that slow down analysis and hide\r\nfunctionality from static tools. As a result, the graph view of the core malware looks like this:\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 13 of 39\n\nFigure 20. Taurus Stealer core functionality call graph\r\nResolving APIs The malware will resolve its API calls dynamically using hashes. It will first resolve LoadLibraryA and\r\nGetProcAddress from kernel32.dll to ease the resolution of further API calls. It does so by accessing the PEB of the process\r\n– more precisely to access the DllBase property of the third element from the InLoadOrderModuleList (which happens to\r\nbe “kernel32.dll”) – and then use this address to walk through the Export Directory information.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 14 of 39\n\nFigure 21. Retrieving kernel32.dll DllBase by accessing the 3rd entry in the InLoadOrderModuleList list\r\nIt will iterate kernel32.dll AddressOfNames structure and compute a hash for every exported function until the\r\ncorresponding hash for “LoadLibraryA” is found. The same process is repeated for the “GetProcAddress” API call. Once\r\nboth procedures are resolved, they are saved for future resolution of API calls.\r\nFigure 22. Taurus Stealer iterates AddressOfNames to find an API using a hashing approach\r\nFor further API resolutions, a “DLL Table String” is used to index the library needed to load an exported function and then\r\nthe hash of the needed API call.\r\nFigure 23. DLL Table String used in API resolutions\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 15 of 39\n\nResolving initial Configuration Just as with Predator The Thief, Taurus Stealer will load its initial configuration in a table\r\nof function pointers before the execution of the WinMain() function. These functions are executed in order and are\r\nresponsible for loading the C2, Build Id and the Bot Id/UUID. C2 and Build Id are resolved using the SUB encryption\r\nscheme with a one-byte key. The loop uses a hard-coded length, (the size in bytes of the C2 and Build Id), which means that\r\nthis has been pre-processed beforehand (probably by the builder) and that these procedures would work for only these\r\nproperties.\r\nFigure 24. Taurus Stealer decrypting its Command and Control server\r\nBOT ID / UUID Generation Taurus generates a unique identifier for every infected machine. Earlier versions of this\r\nmalware also used this identifier as the .zip filename containing the stolen data. This behavior has been modified and now\r\nthe .zip filename is randomly generated (16 random ASCII characters).\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 16 of 39\n\nFigure 25. Call graph from the Bot Id / UUID generation routine\r\nIt starts by getting a bitmask of all the currently available disk drives using GetLogicalDrivers and retrieving their\r\nVolumeSerialNumber with GetVolumeInformationA. All these values are added into the register ESI (holds the sum of all\r\nVolumeSerialNumbers from all available Drive Letters). ESI is then added to itself and right-shifted 3 bytes. The result is a\r\nhexadecimal value that is converted to decimal. After all this process, it takes out the first two digits from the result and\r\nconcatenates its full original part at the beginning. The last step consists of transforming digits in odd positions to ASCII\r\nletters (by adding 0x40). As an example, let’s imagine an infected machine with “C:\\\\”, “D:\\\\” and “Z:\\\\” drive letters\r\navailable.\r\n1. Call GetLogicalDrivers to get a bitmask of all the currently available disk drives.\r\n2. Get their VolumeSerialNumber using GetVolumeInformationA:\r\nESI holds the sum of all VolumeSerialNumber from all available Drive Letters\r\nGetVolumeInformationA(“C:\\\\”) -\u003e 7CCD8A24h\r\nGetVolumeInformationA(“D:\\\\”) -\u003e 25EBDC39h\r\nGetVolumeInformationA(“Z:\\\\”) -\u003e 0FE01h\r\nESI = sum(0x7CCD8A24+0x25EBDC3+0x0FE01) = 0xA2BA645E\r\n3. Once finished the sum, it will:\r\nmov edx, esi\r\nedx = (edx \u003e\u003e 3) + edx\r\nWhich translates to:\r\n(0xa2ba645e \u003e\u003e 0x3) + 0xa2ba645e = 0xb711b0e9\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 17 of 39\n\n4. HEX convert the result to decimal\r\nresult = hex(0xb711b0e9) = 3071389929\r\n5. Take out the first two digits and concatenate its full original part at the beginning:\r\n307138992971389929\r\n6. Finally, it transforms digits in odd positions to ASCII letters:\r\ns0w1s8y9r9w1s8y9r9\r\nAnti – CIS \r\nTaurus Stealer tries to avoid infection in countries belonging to the Commonwealth of Independent States (CIS) by\r\nchecking the language identifier of the infected machine via GetUserDefaultLangID. Earlier Taurus Stealer versions used to\r\nhave this functionality in a separate function, whereas the latest samples include this in the main procedure of the malware.\r\nIt is worth mentioning that this feature is mandatory and will be executed at the beginning of the malware execution.\r\nFigure 26. Taurus Stealer Anti-CIS feature\r\nGetUserDefaultLandID returns the language identifier of the Region Format setting for the current user. If it matches one on\r\nthe list, it will finish execution immediately without causing any harm.\r\nLanguage Id SubLanguage Symbol Country\r\n0x419 SUBLANG_RUSSIAN_RUSSIA Russia\r\n0x42B SUBLANG_ARMENIAN_ARMENIA Armenia\r\n0x423 SUBLANG_BELARUSIAN_BELARUS Belarus\r\n0x437 SUBLANG_GEORGIAN_GEORGIA Georgia\r\n0x43F SUBLANG_KAZAK_KAZAKHSTAN Kazakhstan\r\n0x428 SUBLANG_TAJIK_TAJIKISTAN Tajikistan\r\n0x843 SUBLANG_UZBEK_CYRILLIC Uzbekistan\r\n0x422 SUBLANG_UKRAINIAN_UKRAINE Ukraine\r\nTable 2. Taurus Stealer Language Id whitelist (Anti-CIS)\r\nAnti – C2 Mod. After the Anti-CIS feature has taken place, and before any harmful activity occurs, the retrieved C2 is\r\nchecked against a hashing function to avoid running with an invalid or modified Command and Control server. This hashing\r\nfunction is the same used to resolve API calls and is as follows:\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 18 of 39\n\nFigure 27. Taurus Stealer hashing function\r\nEarlier taurus versions make use of the same hashing algorithm, except they execute two loops instead of one. If the hash of\r\nthe C2 is not matching the expected one, it will avoid performing any malicious activity. This is most probably done to\r\nprotect the binary from cracked versions and to avoid leaving traces or uncovering activity if the sample has been modified\r\nfor analysis purposes.\r\nC2 Communication\r\nPerhaps the biggest change in this new Taurus Stealer version is how the communications with the Command and Control\r\nServer are managed. Earlier versions used two main resources to make requests:\r\nResource Description\r\n/gate/cfg/?post=1\u0026data=\u003cbot_id\u003e\r\nRegister Bot Id and get dynamic config. Everything is sent\r\nin cleartext\r\n/gate/log?post=2\u0026data=\r\n\u003csummary_information\u003e\r\nExfiltrate data in ZIP (cleartext) summary_information is\r\nencrypted\r\nTable 3. Networking resources from earlier Taurus versions\r\nhis new Taurus Stealer version uses:\r\nResource Description\r\n/cfg/ Register Bot Id and get dynamic config. BotId is sent encrypted\r\n/dlls/ Ask for necessary .dlls (Browsers Grabbing)\r\n/log/ Exfiltrate data in ZIP (encrypted)\r\n/loader/complete/ ACK execution of Loader module\r\nTable 4. Networking resources from new Taurus samples\r\nThis time no data is sent in cleartext. Taurus Stealer uses wininet APIs InternetOpenA, InternetSetOptionA,\r\nInternetConnectA, HttpOpenRequestA, HttpSendRequestA, InternetReadFile and InternetCloseHandle for its networking\r\nfunctionalities.  \r\nUser-Agent generation\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 19 of 39\n\nFigure 28. User-Agent generation routine call graph\r\nThe way Taurus generates the User-Agent that it will use for networking purposes is different from earlier versions and has\r\nintroduced more steps in its creation, ending up in more variable results. This routine follows the next steps:\r\n1. It will first get OS Major Version and OS Minor Version information from the PEB. In this example, we will let OS\r\nMajor Version be 6 and OS Minor Version be 1.\r\n1.1 Read TIB[0x30] -\u003e PEB[0x0A] -\u003e OS Major Version -\u003e 6\r\n1.2 Read PEB[0xA4] -\u003e OS Minor Version -\u003e 1\r\n2. Call to IsWow64Process to know if the process is running under WOW64 (this will be needed later).\r\n3. Decrypt string “.121 Safari/537.36”\r\n4. Call GetTickCount and store result in EAX (for this example: EAX = 0x0540790F)\r\n5. Convert HEX result to decimal result: 88111375\r\n6. Ignore the first 4 digits of the result: 1375\r\n7. Decrypt string “ AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.”\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 20 of 39\n\n8. Check the result from the previous call to IsWow64Process and store it for later.\r\n8.1 If the process is running under WOW64: Decrypt the string “ WOW64)”\r\n8.2 If the process is not running under WOW64: Load char “)” In this example we will assume the process is running under\r\nWOW64.\r\n9. Transform from HEX to decimal OS Minor Version (“1”)\r\n10. Transform from HEX to decimal OS Major Version (“6”)\r\n11. Decrypt string “Mozilla/5.0 (Windows NT ”\r\n12. Append OS Major Version -\u003e “Mozilla/5.0 (Windows NT 6”\r\n13. Append ‘.’ (hardcoded) -\u003e “Mozilla/5.0 (Windows NT 6.”\r\n14. Append OS Minor Version -\u003e “Mozilla/5.0 (Windows NT 6.1”\r\n15. Append ‘;’ (hardcoded) -\u003e “Mozilla/5.0 (Windows NT 6.1;”\r\n16. Append the WOW64 modifier explained before -\u003e “Mozilla/5.0 (Windows NT 6.1; WOW64)”\r\n17. Append string “ AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.” -\u003e “Mozilla/5.0 (Windows NT 6.1;\r\nWOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.”\r\n18. Append result of from the earlier GetTickCount (1375 after its processing) -\u003e “Mozilla/5.0 (Windows NT 6.1; WOW64)\r\nAppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.1375”\r\n19. Append the string “.121 Safari/537.36” to get the final result:\r\n“Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.1375.121\r\nSafari/537.36”\r\nWhich would have looked like this if the process was not running under WOW64:\r\n“Mozilla/5.0 (Windows NT 6.1;) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 83.0.1375.121 Safari/537.36”\r\nThe bold characters from the generated User-Agent are the ones that could vary depending on the OS versions, if the\r\nmachine is running under WOW64 and the result of GetTickCount call.\r\nHow the port is set In the analyzed sample, the port for communications is set as a hardcoded value in a variable that is\r\nused in the code. This setting is usually hidden. Sometimes a simple “push 80” in the middle of the code, or a setting to a\r\nvariable using “mov [addr], 0x50” is used. Other samples use https and set the port with a XOR operation like “0x3a3 ^\r\n0x218” which evaluates to “443”, the standard https port. In the analyzed sample, before any communication with the C2 is\r\nmade, a hardcoded “push 0x50 + pop EDI” is executed to store the port used for communications (port 80) in EDI. EDI\r\nregister will be used later in the code to access the communications port where necessary. The following figure shows how\r\nTaurus Stealer checks which is the port used for communications and how it sets dwFlags for the call to HttpOpenRequestA\r\naccordingly.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 21 of 39\n\nFigure 29. Taurus Stealer sets dwFlags according to the port\r\nSo, if the samples uses port 80 or any other port different from 443, the following flags will be used:\r\n0x4400100 = INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION |\r\nINTERNET_FLAG_PRAGMA_NOCACHE\r\nIf it uses port 443, the flags will be:\r\n0x4C00100 = NTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION |\r\nINTERNET_FLAG_SECURE | INTERNET_FLAG_PRAGMA_NOCACHE\r\nRC4 Taurus Stealer uses RC4 stream cipher as its first layer of encryption for communications with the C2. The symmetric\r\nkey used for this algorithm is randomly generated, which means the key will have to be stored somewhere in the body of\r\nthe message being sent so that the receiver can decrypt the content. Key Generation The procedure we’ve named\r\ngetRandomString is the routine called by Taurus Stealer to generate the RC4 symmetric key. It receives 2 parameters, the\r\nfirst is an output buffer that will receive the key and the second is the length of the key to be generated. To create the random\r\nchunk of data, it generates an array of bytes loading three XMM registers in memory and then calling rand() to get a\r\nrandom index that it will use to get a byte from this array. This process is repeated for as many bytes as specified by the\r\nsecond parameter. Given that all the bytes in these XMM registers are printable, this suggests that getRandomString\r\nproduces an alphanumeric key of n bytes length.  \r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 22 of 39\n\nFigure 30. Taurus Stealer getRandomString routine\r\nGiven the lack of srand, no seed is initialized and the rand function will end up giving the same “random” indexes. In the\r\nanalyzed sample, there is only one point in which this functionality is called with a different initial value (when creating a\r\nrandom directory in %PROGRAMDATA% to store .dlls, as we will see later). We’ve named this function getRandomString2\r\nas it has the same purpose. However, it receives an input buffer that has been processed beforehand in another function\r\n(we’ve named this function getRandomBytes). This input buffer is generated by initializing a big buffer and XORing it over\r\na loop with the result of a GetTickCount call. This ends up giving a “random” input buffer which getRandomString2 will use\r\nto get indexes to an encrypted string that resolves in runtime as\r\n“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789”, and finally generate a random\r\nstring for a given length. We have seen other Taurus Stealer samples moving onto this last functionality (using input buffers\r\nXORed with the result of a GetTickCount call to generate random chunks of data) every time randomness is needed\r\n(generation communication keys, filenames, etc.). The malware sample\r\nd0aa932e9555a8f5d9a03a507d32ab3ef0b6873c4d9b0b34b2ac1bd68f1abc23 is an example of these Taurus Stealer variants.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 23 of 39\n\nFigure 31. Taurus Stealer getRandomBytes routine\r\nBASE64 This is the last encoding layer before C2 communications happen. It uses a classic BASE64 to encode the message\r\n(that has been previously encrypted with RC4) and then, after encoding, the RC4 symmetric key is appended to the\r\nbeginning of the message. The receiver will then need to get the key from the beginning of the message, BASE64 decode the\r\nrest of it and use the retrieved key to decrypt the final RC4 encrypted message. To avoid having a clear BASE64 alphabet in\r\nthe code, it uses XMM registers to load an encrypted alphabet that is decrypted using the previously seen SUB encryption\r\nscheme before encoding.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 24 of 39\n\nFigure 32. Taurus Stealer hiding Base64 alphabet\r\nThis is what the encryption procedure would look like:\r\n1. Generate RC4 key using getRandomString with a hardcoded size of 16 bytes.\r\n2. RC4 encrypt the message using the generated 16 byte key.\r\n3. BASE64 encode the encrypted message.\r\n4. Append RC4 symmetric key at the beginning of the encoded message.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 25 of 39\n\nFigure 33. Taurus Stealer encryption routine\r\nBot Registration + Getting dynamic configuration Once all the initial checks have been successfully passed, it is time for\r\nTaurus to register this new Bot and retrieve the dynamic configuration. To do so, a request to the resource /cfg/ of the C2 is\r\nmade with the encrypted Bot Id as a message. For example, given a BotId “s0w1s8y9r9w1s8y9r9 and a key\r\n“IDaJhCHdIlfHcldJ”:\r\nRC4(“IDaJhCHdIlfHcldJ”, “s0w1s8y9r9w1s8y9r9”) = 018784780c51c4916a4ee1c50421555e4991\r\nIt then BASE64 encodes it and appends the RC4 key at the beginning of the message:\r\nIDaJhCHdIlfHcldJAYeEeAxRxJFqTuHFBCFVXkmR\r\nAn example of the response from the C2 could be:\r\nxBtSRalRvNNFBNqAx0wL840EWVYxho+a6+R+rfO/Dax6jqSFhSMg+rwQrkxh4U3t6EPpqL8xAL8omji9dhO6biyzjESDBIPBfQSiM4Vs7qQMSg==\r\nThe responses go through a decryption routine that will reverse the steps described above to get the plaintext message. As\r\nyou can see in the following figure, the key length is hardcoded in the binary and expected to be 16 bytes long.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 26 of 39\n\nFigure 34. Taurus Stealer decrypting C2 responses\r\nTo decrypt it, we do as follow: 1. Get RC4 key (first 16 bytes of the message) xBtSRalRvNNFBNqA 2. BASE64 decode the\r\nrest of the message (after the RC4 key)\r\nc41b5245a951bcd34504da80c74c0bf38d04595631868f9aebe47eadf3bf0dac7a8ea485852320fabc10ae4c61e14dede843e9a8bf3100bf289a38bd7613ba6e2cb38c44\r\n3. Decrypt the message using RC4 key (get dynamic config.) [1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;5000;0;0]#[]#\r\n[156.146.57.112;US]#[] We can easily see that consecutive configurations are separated by the character “;”, while the\r\ncharacter ‘#’ is used to separate different configurations. We can summarize them like this: [STEALER_CONFIG]#\r\n[GRABBER_CONFIG]#[NETWORK_CONFIG]#[LOADER_CONFIG]   In case the C2 is down and no dynamic configuration is available,\r\nit will use a hardcoded configuration stored in the binary which would enable all stealers, Anti-VM, and Self-Delete\r\nfeatures. (Dynamic Grabber and Loader modules are not enabled by default in the analyzed sample).\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 27 of 39\n\nFigure 35. Taurus uses a static hardcoded configuration If C2 is not available\r\nAnti – VM (optional) This functionality is optional and depends on the retrieved configuration. If the malware detects that\r\nit is running in a Virtualized environment, it will abort execution before causing any damage. It makes use of old and\r\ncommon x86 Anti-VM instructions (like the RedPill technique) to detect the Virtualized environment in this order:\r\nSIDT\r\nSGDT\r\nSTR\r\nCPUID\r\nSMSW\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 28 of 39\n\nFigure 36. Taurus Stealer Anti-VM routine\r\nStealer / Grabber\r\nWe can distinguish 5 main grabbing methods used in the malware. All paths and strings required, as usual with Taurus\r\nStealer, are created at runtime and come encrypted in the methods described before. Grabber 1 This is one of the most used\r\ngrabbing methods, along with the malware execution (if it is not used as a call to the grabbing routine it is implemented\r\ninside another function in the same way), and consists of traversing files (it ignores directories) by using kernel32.dll\r\nFindFirstFileA, FindNextFileA and FindClose API calls. This grabbing method does not use recursion. The grabber\r\nexpects to receive a directory as a parameter for those calls (it can contain wildcards) to start the search with. Every found\r\nfile is grabbed and added to a ZIP file in memory for future exfiltration. An example of its use can be seen in the Wallets\r\nStealing functionality, when searching, for instance, for Electrum wallets: Grabber 2 This grabber is used in the Outlook\r\nStealing functionality and uses advapi32.dll RegOpenKeyA, RegEnumKeyA, RegQueryValueExA and RegCloseKey API calls\r\nto access the and steal from Windows Registry. It uses a recursive approach and will start traversing the Windows Registry\r\nsearching for a specific key from a given starting point until RegEnumKeyA has no more keys to enumerate. For instance, in\r\nthe Outlook Stealing functionality this grabber is used with the starting Registry key “HKCU\\software\\microsoft\\office”\r\nsearching for the key “9375CFF0413111d3B88A00104B2A667“. Grabber 3 This grabber is used to steal browsers data and\r\nuses the same API calls as Grabber 1 for traversing files. However, it loops through all files and directories from\r\n%USERS% directory and favors recursion. Files found are processed and added to the ZIP file in memory. One curious\r\ndetail is that if a “wallet.dat” is found during the parsing of files, it will only be dumped if the current depth of the recursion\r\nis less or equal to 5. This is probably done in an attempt to avoid dumping invalid wallets. We can summarize the files\r\nTaurus Stealer is interested in the following table:\r\nGrabbed File Affected Software\r\nHistory Browsers\r\nformhistory.sqlite Mozilla Firefox \u0026 Others\r\ncookies.sqlite Mozilla Firefox \u0026 Others\r\nwallet.dat Bitcoin\r\nlogins.json Chrome\r\nsignongs.sqlite Mozilla Firefox \u0026 Others\r\nplaces.sqlite Mozilla Firefox \u0026 Others\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 29 of 39\n\nGrabbed File Affected Software\r\nLogin Data Chrome / Chromium based\r\nCookies Chrome / Chromium based\r\nWeb Data Browser\r\nTable 5. Taurus Stealer list of files for Browser Stealing functionalities\r\nGrabber 4\r\nThis grabber steals information from the Windows Vault, which is the default storage vault for the credential manager\r\ninformation. This is done through the use of Vaultcli.dll, which encapsulates the necessary functions to access the Vault.\r\nInternet Explorer data, since it’s version 10, is stored in the Vault. The malware loops through its items using:\r\nVaultEnumerateVaults\r\nVaultOpenVault\r\nVaultEnumerateItems\r\nVaultGetItem\r\nVaultFree\r\nGrabber 5 This last grabber is the customized grabber module (dynamic grabber). This module is responsible for grabbing\r\nfiles configured by the threat actor operating the botnet. When Taurus makes its first request to the C\u0026C, it retrieves the\r\nmalware configuration, which can include a customized grabbing configuration to search and steal files. This functionality is\r\nnot enabled in the default static configuration from the analyzed sample (the configuration used when the C2 is not\r\navailable). As in earlier grabbing methods, this is done via file traversing using kernel32.dll FindFirstFileA, FindNextFileA\r\nand FindClose API calls. The threat actor may set recursive searches (optional) and multiple wildcards for the search.\r\nFigure 37. Threat Actor can add customized grabber rules for the dynamic grabber\r\nTargeted Software This is the software the analyzed sample is targeting. It has functionalities to steal from: Wallets:\r\nElectrum\r\nMultiBit\r\nArmory\r\nEthereum\r\nBytecoin\r\nJaxx\r\nAtomic\r\nExodus\r\nDahscore\r\nBitcoin\r\nWasabi\r\nDaedalus\r\nMonero\r\nGames:\r\nSteam\r\nCommunications:\r\nTelegram\r\nDiscord\r\nJabber\r\nMail:\r\nFoxMail\r\nOutlook\r\nFTP:\r\nFileZilla\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 30 of 39\n\nWinSCP\r\n2FA Software:\r\nAuthy\r\nVPN:\r\nNordVPN\r\nBrowsers:\r\nMozilla Firefox (also Gecko browsers)\r\nChrome (also Chromium browsers)\r\nInternet Explorer\r\nEdge\r\nBrowsers using the same files the grabber targets.\r\nHowever, it has been seen in other samples and their advertisements that Taurus Stealer also supports other software not\r\nincluded in the list like BattleNet, Skype and WinFTP. As mentioned earlier, they also have an open communication\r\nchannel with their customers, who can suggest new software to add support to. Stealer Dependencies Although the posts\r\nthat sell the malware in underground forums claim that Taurus Stealer does not have any dependencies, when stealing\r\nbrowser information (by looping through files recursively using the “Grabber 3” method described before), if it finds\r\n“logins.json” or “signons.sqlite” it will then ask for needed .dlls to its C2. It first creates a directory in\r\n%PROGRAMDATA%\\\u003cbot id\u003e, where it is going to dump the downloaded .dlls. It will check if “%PROGRAMDATA%\\\r\n\u003cbot id\u003e\\nss3.dll” exists and will ask for its C2 (doing a request to /dlls/ resource) if not. The .dlls will be finally dumped in\r\nthe following order:\r\n1. freebl3.dll\r\n2. mozglue.dll\r\n3. msvcp140.dll\r\n4. nss3.dll\r\n5. softokn3.dll\r\n6. vcruntime140.dll\r\nIf we find the C2 down (when analyzing the sample, for example), we will not be able to download the required files.\r\nHowever, the malware will still try, no matter what, to load those libraries after the request to /dlls/ has been made (starting\r\nby loading “nss3.dll”), which would lead to a crash. The malware would stop working from this point. In contrast, if the C2\r\nis alive, the .dlls will be downloaded and written to disk in the order mentioned before. The following figure shows the call\r\ngraph from the routine responsible for requesting and dumping the required libraries to disk.  \r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 31 of 39\n\nFigure 38. Taurus Stealer dumping retrieved .dlls from its Command and Control Server to disk\r\nInformation Gathering After the Browser stealing process is finished, Taurus proceeds to gather information from the\r\ninfected machine along with the Taurus Banner and adds this data to the ZIP file in memory with the filename\r\n“Information.txt”. All this functionality is done through a series of unnecessary steps caused by all the obfuscation\r\ntechniques to hide strings, which leads to a horrible function call graph:\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 32 of 39\n\nFigure 39. Taurus Stealer main Information Gathering routine call graph\r\nIt gets information and concatenates it sequentially in memory until we get the final result:\r\n‘ ______ _____ __ __ ‘\r\n‘ ‘\r\n‘ /_ __/___ ___ _________ _______ / ___// /____ ____ _/ /__ ‘\r\n‘ _____’\r\n‘ / / / __ `/ / / / ___/ / / / ___/ \\__ \\/ __/ _ \\/ __ `/ / _ \\’\r\n‘/ ___/’\r\n‘ / / / /_/ / /_/ / / / /_/ (__ ) ___/ / /_/ __/ /_/ / / __/’\r\n‘ / ‘\r\n‘/_/ \\__,_/\\__,_/_/ \\__,_/____/ /____/\\__/\\___/\\__,_/_/\\___/_’\r\n‘/\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 33 of 39\n\n‘_________________________________________________________________’\r\n‘____________’\r\n‘|Buy at Telegram: t.me/taurus_seller |Buy at Jabber: taurus_selle’\r\n‘r@exploit.im|’\r\n‘““““““““““““““““““““““““““““““““`’\r\n‘““““““`’\r\n‘UID: s0w1s8y9r9w1s8y9r9’\r\n‘Prefix: MyAwesomePrefix’\r\n‘Date: 15.4.2021 14:57’\r\n‘IP: ‘\r\n‘Country: ‘\r\n‘OS: Windows 6.1 7601 x64’\r\n‘Logical drives: C: D: Z: ‘\r\n‘Current username: User’\r\n‘Computername: USER-PC’\r\n‘Domain: WORKGROUP’\r\n‘Computer users: All Users, Default, Default User, Public, User, ‘\r\n‘Keyboard: Spanish (Spain, International Sort)/English (United States)’\r\n‘Active Window: IDA – C:\\Users\\User\\Desktop\\TAURUS_v2.idb (TAURUS_’\r\n‘v2.exe)’\r\n‘CPU name: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz’\r\n‘Number of CPU kernels: 2’\r\n‘GPU name: VirtualBox Graphics Adapter’\r\n‘RAM: 3 GB’\r\n‘Screen resolution: 1918×1017’\r\n‘Working path: C:\\Users\\User\\Desktop\\TAURUS_v2.exe’,0\r\nOne curious difference from earlier Taurus Stealer versions is that the Active Window from the infected machine is now\r\nalso included in the information gathering process.\r\nEnumerate Installed Software As part of the information gathering process, it will try to get a list of the installed software\r\nfrom the infected machine by looping in the registry from\r\n“HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall” and retrieving DisplayName and DisplayVersion with\r\nRegQueryValueExA until RegEnumKeyA does not find more keys. If software in the registry list has the key “DisplayName”,\r\nit gets added to the list of installed software. Then, if it also has “Display Version” key, the value is appended to the name. In\r\ncase this last key is not available, “[Unknown]” is appended instead. Following the pattern:\r\n“DisplayName\\tDisplayVersion” As an example:\r\n“Cheat Engine 6.5.1\\t[Unknown]” “Google Chrome\\t[89.0.4389.90]” (…)\r\nThe list of software is included in the ZIP file in memory with the filename “Installed Software.txt”\r\nC2 Exfiltration\r\nDuring the stealing process, the data that is grabbed from the infected machine is saved in a ZIP file in memory. As we have\r\njust seen, information gathering files are also included in this fileless ZIP. When all this data is ready, Taurus Stealer will\r\nproceed to:\r\n1. Generate a Bot Id results summary message.\r\n2. Encrypt the ZIP file before exfiltration.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 34 of 39\n\n3. Exfiltrate the ZIP file to Command and Control server.\r\n4. Delete traces from networking activity\r\nGenerate Bot Id results summary The results summary message is created in 2 stages. The first stage loads generic\r\ninformation from the infected machine (Bot Id, Build Id, Windows version and architecture, current user, etc.) and a\r\nsummary count of the number of passwords, cookies, etc. stolen. As an example:\r\ns0w1s8y9r9w1s8y9r9|MyAwesomePrefix|Windows 6.1 7601 x64|USER-PC|WORKGROUP|||0|576|0|7|empty\r\nFinally, it concatenates a string that represents a mask stating which Software has been available to steal information from\r\n(e.g. Telegram, Discord, FileZilla, WinSCP. etc.).\r\ns0w1s8y9r9w1s8y9r9|MyAwesomePrefix|Windows 6.1 7601 x64|USER-PC|WORKGROUP|||0|576|0|7|empty|1|1|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0\r\nThis summary information is then added in the memory ZIP file with the filename “LogInfo.txt”. This behavior is different\r\nfrom earlier Taurus Stealer versions, where the information was sent as part of the URL (when doing exfiltration POST\r\nrequest to the resource /gate/log/) in the parameter “data”. Although this summary information was encrypted, the exfiltrated\r\nZIP file was sent in cleartext. Encrypt ZIP before exfiltration Taurus Stealer will then encrypt the ZIP file in memory\r\nusing the techniques described before: using the RC4 stream cipher with a randomly generated key and encoding the result\r\nin BASE64. Because the RC4 key is needed to decrypt the message, the key is included at the beginning of the encoded\r\nmessage. In the analyzed sample, as we saw before, the key length is hardcoded and is 16 bytes. As an example, this could\r\nbe an encrypted message being sent in a POST request to the /log/ resource of a Taurus Stealer C2, where the RC4 key is\r\nincluded at the beginning of the message (first 16 characters).\r\n“jaCghbIiGeGEADIjMayhQpGzXwORMFuHXzsUCiVH12jIA” (…)\r\nExfiltrate ZIP file to Command and Control server As in the earlier versions, it uses a try-retry logic where it will try to\r\nexfiltrate up to 10 times (in case the network is failing, C2 is down, etc.). It does so by opening a handle using\r\nHttpOpenRequestA for the “/log/” resource and using this handle in a call to HttpSendRequestA, where exfiltration is done\r\n(the data to be exfiltrated is in the post_data argument). The following figure shows this try-retry logic in a loop that\r\nexecutes HttpSendRequestA.\r\nFigure 40. Taurus Stealer will try to exfiltrate up to 10 times\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 35 of 39\n\nThe encrypted ZIP file is sent with Content-Type: application/octet-stream. The filename is a randomly generated string of\r\n16 bytes. However, earlier Taurus Stealer versions used the Bot Id as the .zip filename. Delete traces from networking\r\nactivity After exfiltration, it uses DeleteUrlCacheEntry with the C2 as a parameter for the API call, which deletes the cache\r\nentry for a given URL. This is the last step of the exfiltration process and is done to avoid leaving traces from the\r\nnetworking activity in the infected machine.\r\nLoader (optional)\r\nUpon exfiltration, the Loader module is executed. This module is optional and gets its configuration from the first C2\r\nrequest. If the module is enabled, it will load an URL from the Loader configuration and execute URLOpenBlockingStream\r\nto download a file. This file will then be dumped in %TEMP% folder using a random filename of 8 characters. Once the file\r\nhas been successfully dumped in the infected machine it will execute it using ShellExecuteA with the option nShowCmd as\r\n“SW_HIDE”, which hides the window and activates another one. If persistence is set in the Loader configuration, it will\r\nalso schedule a task in the infected machine to run the downloaded file every minute using:\r\nC:\\windows\\system32\\cmd.exe /c schtasks /create /F /sc minute /mo 1 /tn “\\WindowsAppPool\\AppP ool” /tr\r\n“C:\\Users\\User\\AppData\\Local\\Temp\\FfjDEIdA.exe”\r\nThe next figure shows the Schedule Task Manager from an infected machine where the task has been scheduled to run every\r\nminute indefinitely.\r\nFigure 41. Loader persistence is carried out by creating a scheduled task to run every minute indefinitely\r\nOnce the file is executed, a new POST request is made to the C2 to the resource /loader/complete/. The following figure\r\nsummarizes the main responsibilities of the Loader routine.\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 36 of 39\n\nFigure 42. Taurus Stealer Loader routine call graph\r\nSelf-Delete (optional)\r\nThis functionality is the last one being executed in the malware and is also optional, although it is enabled by default if no\r\nresponse from the C2 was received in the first request. It will use CreateProcessA to execute cmd.exe with the following\r\narguments:\r\ncmd.exe /c timeout /t 3 \u0026 del /f /q \u003cmalware_filepath\u003e\r\nMalware_filepath is the actual path of the binary being executed (itself). A small timeout is set to give time to the malware\r\nto finish its final tasks. After the creation of this process, only a clean-up routine is executed to delete strings from memory\r\nbefore finishing execution.\r\nYARA rule\r\nThis memory Yara rule detects both old and new Taurus Stealer versions. It targets some unique functionalities from this\r\nmalware family:\r\nHex2Dec: Routine used to convert from a Hexadecimal value to a Decimal value.\r\nBot Id/UUID generation routine.\r\ngetRandomString: Routine used to generate a random string using rand() over a static input buffer\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 37 of 39\n\ngetRandomString2: Routine used to generate a random string using rand() over an input buffer previously\r\n“randomized” with GetTickCount\r\ngetRandomBytes: Routine to generate “random” input buffers for getRandomString2\r\nHashing algorithm used to resolve APIs and Anti – C2 mod. feature.\r\nrule taurus_stealer_memory {\r\nmeta:\r\ndescription = “Detects Taurus Stealer”\r\nauthor = “Blueliv”\r\ndate = “27/04/2021”\r\nstrings:\r\n/* Hex2Dec */\r\n$op00 = { 33 D2 4E 6A 0A 59 F7 F1 80 C2 30 88 16 85 C0 75 EF 51 8D 45 FD 8B CF 50 56 E8 ?? ?? ?? ?? 8B C7 5F 5E\r\nC9 C3 }\r\n/* Bot Id/UUID Generation */\r\n$op01 = { 8D ?? ?? ?? ?? 8D [2-3] 7? ?? [4-5] 0F [3-4] 8A 04 ?? 04 40 EB }\r\n/* getRandomString */\r\n$op02 = { E8 ?? ?? ?? ?? 99 6A 17 59 F7 F9 (83 ?? ?? ?? 8D ?? ?? | 8D ?? ?? 83 ?? ?? ??) [0-3] 0F 43 ?? ?? }\r\n/* getRandomString2 */\r\n$op03 = { 33 D2 F7 36 8B 74 8E 08 8B 4D FC 6A 3F 03 74 91 08 33 D2 8B 41 4C F7 31 }\r\n/* getRandomBytes */\r\n$op04 = { C7 46 ?? ?? 42 0F 00 C7 46 ?? ?? 42 0F 00 C7 46 ?? ?? 42 0F 00 89 ?? ?? E8 ?? ?? ?? ?? FF D0 39 1E 76 0A 31\r\n07 43 8D 7F 04 3B 1E 72 F6 }\r\n/* Hashing algorithm */\r\n$op05 = { 0F BE [1-2] 33 C2 (C1 EA 08 0F B6 C0 | 0F B6 C0 C1 EA 08) 33 14 85 ?? ?? ?? ?? 4? }\r\ncondition:\r\n4 of them\r\n}\r\nMITRE ATT\u0026CK\r\nTactic  Technique ID  Technique \r\nExecution  T1059  Command and Scripting Interpreter \r\nExecution / Persistence  T1053  Scheduled Task/Job \r\nDefense Evasion  T1140  Deobfuscate/Decode Files or Information \r\nDefense Evasion  T1070  Indicator Removal on Host \r\nDefense Evasion  T1027  Obfuscated Files or Information \r\nDefense Evasion / Discovery  T1497  Virtualization/Sandbox Evasion \r\nCredential Access  T1539  Steal Web Session Cookie \r\nCredential Access  T1555  Credentials from Password Stores \r\nCredential Access  T1552  Unsecured Credentials \r\nDiscovery  T1087  Account Discovery \r\nDiscovery  T1010  Application Window Discovery \r\nDiscovery  T1083  File and Directory Discovery \r\nDiscovery  T1120  Peripheral Device Discovery \r\nDiscovery  T1012  Query Registry \r\nDiscovery  T1518  Software Discovery \r\nDiscovery  T1082  System Information Discovery \r\nDiscovery  T1016  System Network Configuration Discovery \r\nDiscovery  T1033  System Owner/User Discovery \r\nDiscovery  T1124  System Time Discovery \r\nCollection  T1560  Archive Collected Data \r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 38 of 39\n\nCollection  T1005  Data from Local System \r\nCollection  T1113  Screen Capture \r\nCommand and Control  T1071  Application Layer Protocol \r\nCommand and Control  T1132  Data Encoding \r\nCommand and Control  T1041  Exfiltration over C2 Channel \r\nConclusion\r\nInformation Stealers like Taurus Stealer are dangerous and can cause a lot of damage to individuals and organizations\r\n(privacy violation, leakage of confidential information, etc.). Consequences vary depending on the significance of the stolen\r\ndata. This goes from usernames and passwords (which could be targetted by threat actors to achieve privilege escalation\r\nand lateral movement, for example) to information that grants them immediate financial profit, such as cryptocurrency\r\nwallets. In addition, stolen email accounts can be used to send spam and/or distribute malware. As has been seen throughout\r\nthe analysis, Taurus Stealer looks like an evolving malware that is still being updated (improving its code by adding\r\nfeatures, more obfuscation and bugfixes) as well as it’s Panel, which keeps having updates with more improvements (such as\r\nadding filters for the results coming from the malware or adding statistics for the loader). The fact the malware is being\r\nactively used in the wild suggests that it will continue evolving and adding more features and protections in the future,\r\nespecially as customers have an open dialog channel to request new software to target or to suggest improvements to\r\nimprove functionality. For more details about how we reverse engineer and analyze malware, visit our targeted malware\r\nmodule page.\r\nIOCs\r\nHashes Taurus Stealer (earlier version):\r\nPacked: 4a30ef818603b0a0f2b8153d9ba6e9494447373e86599bcc7c461135732e64b2\r\nUnpacked: ddc7b1bb27e0ef8fb286ba2b1d21bd16420127efe72a4b7ee33ae372f21e1000\r\nTaurus Stealer (analyzed sample):\r\nPacked: 2fae828f5ad2d703f5adfacde1d21a1693510754e5871768aea159bbc6ad9775\r\nUnpacked: d6987aa833d85ccf8da6527374c040c02e8dfbdd8e4e4f3a66635e81b1c265c8\r\nC2 64[.]225[.]22[.]106 (earlier Taurus Stealer) dmpfdmserv275[.]xyz (analyzed Taurus Stealer)\r\nReferences\r\nCyber Intelligence Infoblox, “WordyThief: A Malicious Spammer”, October, 2020. [Online].\r\nAvailable: https://docs.apwg.org/ecrimeresearch/2020/56_Wordythief-AMaliciousSpammer_20201028.pdf [Accessed April\r\n25, 2021] \r\nfumik0, “Predator The Thief: In-depth analysis (v2.3.5)”, October, 2018. [Online].\r\nAvailable: https://fumik0.com/2018/10/15/predator-the-thief-in-depth-analysis-v2-3-5/ [Accessed April 25, 2021] \r\nfumik0, “Let’s play (again) with Predator the thief”, December, 2019. [Online].\r\nAvailable: https://fumik0.com/2019/12/25/lets-play-again-with-predator-the-thief/ [Accessed April 25, 2021] \r\nThreat Intelligence Team, “Taurus Project stealer now spreading via malvertising campaign”, September, 2020. [Online].\r\nAvailable: https://blog.malwarebytes.com/malwarebytes-news/2020/09/taurus-project-stealer-now-spreading-via-malvertising-campaign/ [Accessed April 25, 2021] \r\nAvinash Kumar, Uday Pratap Singh, “Taurus: The New Stealer in Town”, June, 2020. [Online]\r\nAvailable: https://www.zscaler.com/blogs/security-research/taurus-new-stealer-town [Accessed April 25, 2021] \r\nJoxean Koret, “Antiemulation Techniques (Malware Tricks II)”, February, 2010. [Online]\r\nAvailable: http://joxeankoret.com/blog/2010/02/23/antiemulation-techniques-malware-tricks-ii/ [Accessed April 25, 2021] \r\nAbout the Author\r\nAlberto leads the Reverse Engineering team at Outpost24's KrakenLabs department. He has been working in cybersecurity\r\nsince 2014, focusing on malware research, reverse engineering, and Sandbox development for automated malware analysis. \r\nSource: https://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nhttps://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/\r\nPage 39 of 39\n\n https://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/    \nFigure 20. Taurus Stealer core functionality call graph   \nResolving APIs The malware will resolve its API calls dynamically using hashes. It will first resolve LoadLibraryA and\nGetProcAddress from kernel32.dll to ease the resolution of further API calls. It does so by accessing the PEB of the process\n-more precisely to access the DllBase property of the third element from the InLoadOrderModuleList (which happens to\nbe “kernel32.dll”) -and then use this address to walk through the Export Directory information.  \n  Page 14 of 39",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://outpost24.com/blog/an-in-depth-analysis-of-the-new-taurus-stealer/"
	],
	"report_names": [
		"an-in-depth-analysis-of-the-new-taurus-stealer"
	],
	"threat_actors": [
		{
			"id": "9f101d9c-05ea-48b9-b6f1-168cd6d06d12",
			"created_at": "2023-01-06T13:46:39.396409Z",
			"updated_at": "2026-04-10T02:00:03.312816Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"CHROMIUM",
				"ControlX",
				"TAG-22",
				"BRONZE UNIVERSITY",
				"AQUATIC PANDA",
				"RedHotel",
				"Charcoal Typhoon",
				"Red Scylla",
				"Red Dev 10",
				"BountyGlad"
			],
			"source_name": "MISPGALAXY:Earth Lusca",
			"tools": [
				"RouterGod",
				"SprySOCKS",
				"ShadowPad",
				"POISONPLUG",
				"Barlaiy",
				"Spyder",
				"FunnySwitch"
			],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "8941e146-3e7f-4b4e-9b66-c2da052ee6df",
			"created_at": "2023-01-06T13:46:38.402513Z",
			"updated_at": "2026-04-10T02:00:02.959797Z",
			"deleted_at": null,
			"main_name": "Sandworm",
			"aliases": [
				"IRIDIUM",
				"Blue Echidna",
				"VOODOO BEAR",
				"FROZENBARENTS",
				"UAC-0113",
				"Seashell Blizzard",
				"UAC-0082",
				"APT44",
				"Quedagh",
				"TEMP.Noble",
				"IRON VIKING",
				"G0034",
				"ELECTRUM",
				"TeleBots"
			],
			"source_name": "MISPGALAXY:Sandworm",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "3a0be4ff-9074-4efd-98e4-47c6a62b14ad",
			"created_at": "2022-10-25T16:07:23.590051Z",
			"updated_at": "2026-04-10T02:00:04.679488Z",
			"deleted_at": null,
			"main_name": "Energetic Bear",
			"aliases": [
				"ATK 6",
				"Blue Kraken",
				"Crouching Yeti",
				"Dragonfly",
				"Electrum",
				"Energetic Bear",
				"G0035",
				"Ghost Blizzard",
				"Group 24",
				"ITG15",
				"Iron Liberty",
				"Koala Team",
				"TG-4192"
			],
			"source_name": "ETDA:Energetic Bear",
			"tools": [
				"Backdoor.Oldrea",
				"CRASHOVERRIDE",
				"Commix",
				"CrackMapExec",
				"CrashOverride",
				"Dirsearch",
				"Dorshel",
				"Fertger",
				"Fuerboos",
				"Goodor",
				"Havex",
				"Havex RAT",
				"Hello EK",
				"Heriplor",
				"Impacket",
				"Industroyer",
				"Karagany",
				"Karagny",
				"LightsOut 2.0",
				"LightsOut EK",
				"Listrix",
				"Oldrea",
				"PEACEPIPE",
				"PHPMailer",
				"PsExec",
				"SMBTrap",
				"Subbrute",
				"Sublist3r",
				"Sysmain",
				"Trojan.Karagany",
				"WSO",
				"Webshell by Orb",
				"Win32/Industroyer",
				"Wpscan",
				"nmap",
				"sqlmap",
				"xFrost"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "a66438a8-ebf6-4397-9ad5-ed07f93330aa",
			"created_at": "2022-10-25T16:47:55.919702Z",
			"updated_at": "2026-04-10T02:00:03.618194Z",
			"deleted_at": null,
			"main_name": "IRON VIKING",
			"aliases": [
				"APT44 ",
				"ATK14 ",
				"BlackEnergy Group",
				"Blue Echidna ",
				"CTG-7263 ",
				"ELECTRUM ",
				"FROZENBARENTS ",
				"Hades/OlympicDestroyer ",
				"IRIDIUM ",
				"Qudedagh ",
				"Sandworm Team ",
				"Seashell Blizzard ",
				"TEMP.Noble ",
				"Telebots ",
				"Voodoo Bear "
			],
			"source_name": "Secureworks:IRON VIKING",
			"tools": [
				"BadRabbit",
				"BlackEnergy",
				"GCat",
				"NotPetya",
				"PSCrypt",
				"TeleBot",
				"TeleDoor",
				"xData"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "18a7b52d-a1cd-43a3-8982-7324e3e676b7",
			"created_at": "2025-08-07T02:03:24.688416Z",
			"updated_at": "2026-04-10T02:00:03.734754Z",
			"deleted_at": null,
			"main_name": "BRONZE UNIVERSITY",
			"aliases": [
				"Aquatic Panda",
				"Aquatic Panda ",
				"CHROMIUM",
				"CHROMIUM ",
				"Charcoal Typhoon",
				"Charcoal Typhoon ",
				"Earth Lusca",
				"Earth Lusca ",
				"FISHMONGER ",
				"Red Dev 10",
				"Red Dev 10 ",
				"Red Scylla",
				"Red Scylla ",
				"RedHotel",
				"RedHotel ",
				"Tag-22",
				"Tag-22 "
			],
			"source_name": "Secureworks:BRONZE UNIVERSITY",
			"tools": [
				"Cobalt Strike",
				"Fishmaster",
				"FunnySwitch",
				"Spyder",
				"njRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "6abcc917-035c-4e9b-a53f-eaee636749c3",
			"created_at": "2022-10-25T16:07:23.565337Z",
			"updated_at": "2026-04-10T02:00:04.668393Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Bronze University",
				"Charcoal Typhoon",
				"Chromium",
				"G1006",
				"Red Dev 10",
				"Red Scylla"
			],
			"source_name": "ETDA:Earth Lusca",
			"tools": [
				"Agentemis",
				"AntSword",
				"BIOPASS",
				"BIOPASS RAT",
				"BadPotato",
				"Behinder",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"Doraemon",
				"FRP",
				"Fast Reverse Proxy",
				"FunnySwitch",
				"HUC Port Banner Scanner",
				"KTLVdoor",
				"Mimikatz",
				"NBTscan",
				"POISONPLUG.SHADOW",
				"PipeMon",
				"RbDoor",
				"RibDoor",
				"RouterGod",
				"SAMRID",
				"ShadowPad Winnti",
				"SprySOCKS",
				"WinRAR",
				"Winnti",
				"XShellGhost",
				"cobeacon",
				"fscan",
				"lcx",
				"nbtscan"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "d53593c3-2819-4af3-bf16-0c39edc64920",
			"created_at": "2022-10-27T08:27:13.212301Z",
			"updated_at": "2026-04-10T02:00:05.272802Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Earth Lusca",
				"TAG-22",
				"Charcoal Typhoon",
				"CHROMIUM",
				"ControlX"
			],
			"source_name": "MITRE:Earth Lusca",
			"tools": [
				"Mimikatz",
				"PowerSploit",
				"Tasklist",
				"certutil",
				"Cobalt Strike",
				"Winnti for Linux",
				"Nltest",
				"NBTscan",
				"ShadowPad"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "b3e954e8-8bbb-46f3-84de-d6f12dc7e1a6",
			"created_at": "2022-10-25T15:50:23.339976Z",
			"updated_at": "2026-04-10T02:00:05.27483Z",
			"deleted_at": null,
			"main_name": "Sandworm Team",
			"aliases": [
				"Sandworm Team",
				"ELECTRUM",
				"Telebots",
				"IRON VIKING",
				"BlackEnergy (Group)",
				"Quedagh",
				"Voodoo Bear",
				"IRIDIUM",
				"Seashell Blizzard",
				"FROZENBARENTS",
				"APT44"
			],
			"source_name": "MITRE:Sandworm Team",
			"tools": [
				"Bad Rabbit",
				"Mimikatz",
				"Exaramel for Linux",
				"Exaramel for Windows",
				"GreyEnergy",
				"PsExec",
				"Prestige",
				"P.A.S. Webshell",
				"AcidPour",
				"VPNFilter",
				"Neo-reGeorg",
				"Cyclops Blink",
				"SDelete",
				"Kapeka",
				"AcidRain",
				"Industroyer",
				"Industroyer2",
				"BlackEnergy",
				"Cobalt Strike",
				"NotPetya",
				"KillDisk",
				"PoshC2",
				"Impacket",
				"Invoke-PSImage",
				"Olympic Destroyer"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434711,
	"ts_updated_at": 1775826699,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/dfc81cba8b10a0899c74bbf8de1f9bfe2949cbd1.pdf",
		"text": "https://archive.orkl.eu/dfc81cba8b10a0899c74bbf8de1f9bfe2949cbd1.txt",
		"img": "https://archive.orkl.eu/dfc81cba8b10a0899c74bbf8de1f9bfe2949cbd1.jpg"
	}
}