{
	"id": "bd0d74ff-526b-451b-92e6-ad221da37210",
	"created_at": "2026-04-06T00:12:01.317495Z",
	"updated_at": "2026-04-10T13:12:14.747158Z",
	"deleted_at": null,
	"sha1_hash": "523807f90c606369f88d1e83987fda6f87a323ca",
	"title": "STRRAT (Strigoi) - Malware Analysis Lab",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 19731304,
	"plain_text": "STRRAT (Strigoi) - Malware Analysis Lab\r\nPublished: 2022-04-15 · Archived: 2026-04-05 16:25:08 UTC\r\nOverview\r\nPart 1: STRRAT Dropper and STRRAT Deobfuscation\r\nLet’s take a look at a recent sample of the Java-based malware known as STRRAT. We will cover some techniques\r\non how to identify the malware and reverse engineer it. We will start with a malicious JAR file being distributed\r\nthrough email malspam campaigns, and in this instance the file had the name INQUIRY______535262623.jpg.jar\r\nSource: Malshare.com\r\nExtra Public Reporting: Karsten Hahn - G Data\r\nExtra Public Reporting: Microsoft\r\nExtra Public Reporting: Brad Duncan\r\nFirst off we obtain a sample with a particular SHA256 hash:\r\nStarting Host IOC: ec48d708eb393d94b995eb7d0194bded701c456c666c7bb967ced016d9f1eff5\r\nGiven this is a Java-based RAT we can start by opening it using JD-GUI, a Java Decompiler.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 1 of 124\n\nIf we expand out the only class this contains, we immediately begin to see references to its resource section,\r\nwscript, and “user.home”. Given these references, and the lack of classes, this is a good indicator that the Java\r\nArchive will likely function as a dropper, placing a script with the name “loorqhustq.js” in the users home\r\ndirectory.\r\nTo understand the script being dropped to “loorqhustq.js”, we can take a look at the resource section by extracting\r\nthe Java Archive using 7-Zip.\r\nAt a glance this isn’t too large; however, it does have a Base64 blob which looks to be present and some data\r\nmanipulation to ensure this can’t easily be decoded. One way to tackle this is to replace references of “eval”\r\n(which is essentially telling JavaScript to execute and evaluate what it is being passed, and instead make this\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 2 of 124\n\n“console.log”. By doing this the malicious JavaScript will instead log what it is being presented, rather than\r\nprocessing and evaluating it.\r\nTo do this we still need a way to interpret the JavaScript in a safe setting. By opening up Google Chrome and\r\npressing “F12” we can view the console. At this point we can copy in our modified JavaScript and have Chrome\r\ninterpret it for us.\r\nThe end result is a variable being defined containing an object called lmao$$$_. This is an ActiveXObject storing\r\na Base64 encoded string; however, because we ran this inside of a browser and replaced the eval statements, we\r\nget an Uncaught ReferenceError. This is expected as we didn’t want the dropper to progress, and only wanted to\r\nextract this Base64 string.\r\nBy copying solely the string into CyberChef, we’re able to begin extracting what will be dropped.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 3 of 124\n\nExamining this decoded string reveals a variable which is being defined as “longText”, before being manipulated\r\nto make a valid Base64 string which is once again decoded to disk, this time in the user’s application data\r\ndirectory to a file called r.txt\r\nBefore we look into extracting ‘r.txt’, we can continue to look at what is happening when the dropper triggers.\r\nExamining the first part of the dropper, we find it is enumerating if the Java Runtime Environment is present, and\r\nwhere it is, it will attempt to execute the dropped “r.txt” as a Java Archive, if not, it will run a function called\r\n“GrabJreFromNet”.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 4 of 124\n\nLooking at the function GrabJreFromNet, we can see that it attempts to reach out to\r\nhxxp[://]wshsoft[.]company/jre7[.]zip to pull down a version of JRE. This is then saved to a zip file in the user’s\r\napplication data directory before it is extracted to disk, used to run r.txt, and a run key is setup for persistence to\r\nensure it always runs whenever that user logs on.\r\nNetwork IOC: hxxp[://]wshsoft[.]company/jre7[.]zip\r\nRegistry Run Key Persistence (Host IOC): HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ntfsmgr\r\nAt this point we can go ahead and take the first 4 lines of this second stage dropper, and add an entry to once again\r\nlog to the console the contents of “longText” which will be decoded to r.txt as a Java Archive and run.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 5 of 124\n\nThe output is a “PKZIP” archive, which we can identify through the presence of a MANIFEST.MF as a Java\r\nArchive.\r\nWe’re able to download this file to disk and retrieve the new hash of this Java Archive using PowerShell.\r\nget-filehash .\\STRRAT.jar\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 6 of 124\n\n0A6D2526077276F4D0141E9B4D94F373CC1AE9D6437A02887BE96A16E2D864CF\r\nHost IOC: 0A6D2526077276F4D0141E9B4D94F373CC1AE9D6437A02887BE96A16E2D864CF\r\nBy checking the hash against VirusTotal we can see it hasn’t been analysed and shared publicly yet.\r\nTo help ensure AV vendors are aware of this STRRAT sample, we can submit it to VirusTotal for scanning.\r\n27/60, not a bad rate of detection, noting this doesn’t represent all detection capabilities by vendors, and just\r\nbecause a vendor doesn’t flag it here, doesn’t mean they won’t detect or prevent it in production.\r\nOpening STRRAT in JD-GUI, we can take a look at the manifest file to find the ‘Main’ class which will be\r\nexecuted when the archive is run.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 7 of 124\n\nBy examining the main class we get a lot of obfuscated classes, and references to “StringBuilder” being leveraged.\r\nThe string ‘STRRAT” is also present once we deobfuscate this sample.\r\nAt this stage deobfuscating the code manually would be a bit of a challenge. Luckily we have java-deobfuscator\r\navailable to us which can perform a lot of the heavy lifting.\r\nTo use this we will first create a yaml file called detect.yml which will be used to detect what obfuscator is in use.\r\ninput: C:\\Users\\User\\Desktop\\STRRAT\\Stage 2\\STRRAT.jar\r\ndetect: true\r\nFrom here we can pass this as the configuration to deobfuscator, and find that this looks to be using “Allatori’s\r\nJava Obfuscator - String Encryption”.\r\njava -jar deobfuscator.jar --config detect.yml\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 8 of 124\n\nThe irony is that the website providing this tool is calling us a “hacker” for reverse engineering the Java Archive.\r\nFrom here we can create another file set to deobfuscate the Java Archive in question using the first recommended\r\ntransformer.\r\ninput: C:\\Users\\User\\Desktop\\STRRAT\\Stage 2\\STRRAT.jar\r\noutput: C:\\Users\\User\\Desktop\\STRRAT\\Stage 2\\STRRAT-Deobfuscated.jar\r\ntransformers:\r\n- com.javadeobfuscator.deobfuscator.transformers.allatori.StringEncryptionTransformer\r\nAfter executing the transformer in question we’re presented with a number of “decryption methods”, and\r\n“encrypted strings” being rectified. In this instance there’s some output errors also, but this isn’t of concern.\r\njava -jar deobfuscator.jar --config config.yml\r\nAt this point we can see a number of Java Archive files being referenced:\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 9 of 124\n\nOf these referenced includes a project “system-hook” which is essentially being used here as a Java-based key-logger.\r\nExamining the Main Class further we can now find reference to a pastebin URL being contacted. This gives us\r\nsome potential C2 infrastructure leveraged by this malware. It should be noted this can be modified by the\r\nPastebin user to point elsewhere.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 10 of 124\n\nDynamic Infrastructure (Network IOC): hxxps[://]pastebin[.]com/raw/Jdnx8jdg\r\nPastebin Actor Account (Network IOC): hxxps[://]pastebin[.]com/u/wshsoft\r\nAt the time of writeup this page had been visited 32,736 times, and pointed to the domain\r\npluginserver[.]duckdns[.]org\r\nCurrent Infrastructure (Network IOC): pluginserver[.]duckdns[.]org\r\nIn addition there’s a hardcoded URL mentioned which looks to contact the below:\r\nNetwork IOC: hxxp[://]str-master[.]pw/strigoi/server/ping[.]php?lid=\r\nTaking a look at the class cbnfdhn.class, we can get a feel for some potential functionality of STRRAT including\r\nshutting down an operating system, uploading and downloading files…\r\nEnumerating the OS, processes, key-logging, stealing saved credentials.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 11 of 124\n\nIn addition there’s a reference to “crimson_info.txt” which has been publicly reported as a fake ransomware\r\nmodule.\r\nPart 2: Extracting and Decrypting STRRAT Configuration\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 12 of 124\n\nTo perform more thorough analysis on the deobfuscated STRRAT, we’re going to leverage a tool called ‘Recaf’.\r\nThis will allow us to decompile Java classes in a more user-friendly way given the malware authors have reused\r\nclass and method names. Upon decompiling this we’re going to take a look at the primary entry point of the\r\nprogram in the “Main” class.\r\nAn easy way to find this class is to search for “void main” because the main class method isn’t intended to return\r\nany output. In the below we see a watermark added to the malware to show that “Allatori Obfuscator 7.3 DEMO”\r\nwas used to obfuscate it. In addition we can see it is checking for the number of arguments provided, and where\r\nthis isn’t provided it will run the Main.bsgshsbs method (which is returning an object to be created from the\r\n‘dfghrth’ class). Further to this we can see a message of “This PC is not supported” being returned after this if a\r\nstring isn’t able to be assigned from the output of Main.sdfsldf. To find the right method definition here we can\r\nsearch for “String sdfsldf()” given we know it is returning a string, and here we can see that it is simply looking\r\nfor the path the running JAR file is running from (likely taken from this StackOverflow post).\r\nExamining the object created from the “dfghrth” class reveals this is a file lock being created in the user’s home\r\ndirectory. If there are command-line arguments added this will create a file lock with the name “64578lock.file” in\r\nthe user’s home directory given this number is passed as a parameter when creating this lock object.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 13 of 124\n\nThis serves as the port that the RAT will connect back to.\r\nIn the case where no command-line arguments are provided, this will first create an object called “object2” from\r\nthe Main class method “bsgshsbs”. To make finding these references easier, we’ll begin right clicking them and\r\nusing “Goto definition”.\r\nWe can also reveal references to this particular method by instead clicking “Search references”.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 14 of 124\n\nExamining this method we can see that it looks to be taking in a stream from a file within its resources called\r\n‘config.txt’, Base64 decoding it, and then it passes this and the string “strigoi” to another method, this time within\r\nthe sabretb class called “dfhttegd”.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 15 of 124\n\nWithin this class and method we can see that STRRAT is performing an AES decryption routine based on the\r\nprovided AES encrypted stream from config.txt, and a “password” of “strigoi”.\r\nAlthough I’m no crypto expert, in short, the password is being used to derive a secret key via the “password-based\r\nkey derivation function 2” (PBKDF2), 65536 SHA1 hashing iterations, a key size of 128, using CBC mode, and a\r\nsalt which is the ‘nonce’ extracted from our AES encrypted string. In this instance the “salt” (nonce) functions as\r\nthe Initialisation Vector used with the AES Key to decrypt the string.\r\nMore reading around AES Encryption and Decryption in Java can be found created by baeldung\r\nTo decrypt this using CyberChef we would have to first get the salt (nonce) used, derive the PBKDF2 key, and\r\nthen use this with the appropriate IV to decrypt our content.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 16 of 124\n\nThis is a bit of work, and can quickly get confusing. Because STRRAT is implementing a decryption method, we\r\ncan go ahead and take the relevant parts of the decryption method to decrypt the config file ourselves. If we copy\r\n“sabretb” and “dfhttegd” from “sabretb”, and also “bsgshsbs” from Main, we’ve got the start of a decryption\r\nprogram (noting we will need to import the appropriate libraries in use).\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 17 of 124\n\nIn the above we’ve copied the core content in; however, there’s still some issues based on duplicate named\r\nvariable declarations, classes which aren’t throwing an exception, and an issue based on how it is reading the file\r\ninput. I’ve gone ahead and rectified this with the end result being a Decrypter which takes 2 arguments, (input file,\r\noutput file). Note: At present during our analysis there’s some unknown configuration values as we haven’t\r\ncompletely reveresed the malware.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 18 of 124\n\nThe decrypter as it stands so far can be found below:\r\nimport java.nio.ByteBuffer;\r\nimport java.io.File;\r\nimport java.nio.file.StandardOpenOption;\r\nimport java.nio.file.Files;\r\nimport java.nio.file.Path;\r\nimport java.nio.file.Paths;\r\nimport java.nio.charset.StandardCharsets;\r\nimport javax.crypto.Cipher;\r\nimport javax.crypto.SecretKey;\r\nimport javax.crypto.SecretKeyFactory;\r\nimport javax.crypto.spec.IvParameterSpec;\r\nimport javax.crypto.spec.PBEKeySpec;\r\nimport javax.crypto.spec.SecretKeySpec;\r\nimport java.util.Base64;\r\npublic class STRRATConfigDecrypt {\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 19 of 124\n\npublic static void main(String[] args) throws Exception {\r\n System.out.println(\"###################################################\");\r\n System.out.println(\"# STRRAT Malware (v.1.4) Decrypter by @CyberRaiju #\");\r\n System.out.println(\"###################################################\");\r\n if (args.length \u003c 1) {\r\n System.out.println();\r\n System.out.println(\"PEBCAK - Use this with 2 arguments, an input and output file\");\r\n System.out.println(\"Example:\");\r\n System.out.println(\r\n \"java -jar STRRATConfigDecrypt.jar \\'C:\\\\Users\\\\User\\\\config.txt\\' \\'C:\\\\Users\\\\User\\\\decryp\r\n } else {\r\n String inputdirectory = args[0].replace(\"\\\\\", \"\\\\\\\\\");\r\n String outputdirectory = args[1].replace(\"\\\\\", \"\\\\\\\\\");\r\n File configfile = new File(inputdirectory);\r\n byte[] config = Files.readAllBytes(configfile.toPath());\r\n byte[] parsedBytes = Base64.getDecoder().decode(config);\r\n byte[] decryptedConfig = DecryptAES(\"strigoi\", parsedBytes);\r\n String string[] = new String(decryptedConfig, StandardCharsets.UTF_8).split(\"\\\\|\");\r\n System.out.println(\"Network IOC: \" + string[0]);\r\n System.out.println(\"File Lock: \" + string[1] + \"lock.file\");\r\n System.out.println(\"Network IOC: \" + string[2]);\r\n System.out.println(\"Network IOC: \" + string[3]);\r\n System.out.println(\"Unknown Parameter: \" + string[4]);\r\n System.out.println(\"Unknown Parameter: \" + string[5]);\r\n System.out.println(\"Unknown Parameter: \" + string[6]);\r\n System.out.println(\"Unknown Parameter: \" + string[7]);\r\n System.out.println(\"Possible License/Campaign ID: \" + string[8]);\r\n Path output = Paths.get(outputdirectory);\r\n Files.write(output, \"# STRRAT Malware (v.1.4) Decrypter by @CyberRaiju #\\r\\n\".getBytes());\r\n for (String str : string) {\r\n str = str+\"\\r\\n\";\r\n Files.write(output, str.getBytes(),StandardOpenOption.APPEND);\r\n }\r\n \r\n }\r\n }\r\n public static SecretKey SecretKey(String password, byte[] data) throws Exception {\r\n PBEKeySpec a = new PBEKeySpec(password.toCharArray(), data, 65536, 128);\r\n byte[] b = SecretKeyFactory.getInstance(\"PBKDF2WithHmacSHA1\").generateSecret(a).getEncoded();\r\n return new SecretKeySpec(b, \"AES\");\r\n }\r\n public static byte[] DecryptAES(String password, byte[] bytes) throws Exception {\r\n ByteBuffer byteBuffer;\r\n int n;\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 20 of 124\n\nbyteBuffer = ByteBuffer.wrap(bytes);\r\n n = byteBuffer.getInt();\r\n if (n \u003c 12 || n \u003e 16) {\r\n throw new IllegalArgumentException(\r\n \"Nonce size is incorrect. Make sure that the incoming data is an AES encrypted file.\");\r\n }\r\n byte[] object3 = new byte[n];\r\n byteBuffer.get(object3);\r\n SecretKey key = SecretKey(password, object3);\r\n byte[] byArray2 = new byte[byteBuffer.remaining()];\r\n bytes = byArray2;\r\n byteBuffer.get(byArray2);\r\n Cipher crypto = Cipher.getInstance(\"AES/CBC/PKCS5PADDING\");\r\n IvParameterSpec IVSpec = new IvParameterSpec(object3);\r\n crypto.init(2, key, IVSpec);\r\n return crypto.doFinal(bytes);\r\n }\r\n}\r\nAfter ensuring the config file has been extracted, by running this using Visual Studio Code and the following\r\ncommand line:\r\ncd 'c:\\Users\\User\\Desktop\\STRRAT\\Stage 2\\STRRAT-Deobfuscated\\carLambo\\resources\\Decrypter\\STRRATConfigDecrypt';\r\nWe’re presented with a decrypted configuration output which has also been stored in a file called “decrypted.txt”.\r\nNetwork IOC: moregrace[.]duckdns[.]org\r\nHost IOC: 3219lock.file\r\nNetwork IOC: hxxp[://]jbfrost[.]live/strigoi/server/?hwid=1\u0026lid=m\u0026ht=5\r\nNetwork IOC: palaintermine[.]duckdns[.]org\r\nAlthough the config parameters have been extracted, it’s not clear on exactly what they’re used for. By looking\r\nback into the method “sdfsldf” in the Main class we can see it is checking arguments provided, and if an argument\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 21 of 124\n\nwas provided, it would only use the 3rd configuration parameter from the file (the jbfrost[.]live URL) in a call to\r\n“cbnfdhn.sabretb”.\r\nIn addition to this, the above mentioned method is all about making a GET request to the server and retrieving the\r\nresponse to return as a string.\r\nWe know that this string is being returned to cbnfdhn.dfhttegd which if we look into is holding a public string that\r\ncan be referenced from multiple classes, so we know it is being stored for later usage.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 22 of 124\n\nBy viewing references to this, we can see the different methods which either “PUT” a value into this variable, or\r\n“GET” the value from the variable.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 23 of 124\n\nAt this point we know that the variable is written to within 5 methods, and read from 5 methods. If we examine\r\nwhere it is being read from by right clicking and selecting “Edit with Assembler”, we can see that all of these\r\nmethods are creating sockets and using this as the callback address. In addition we can see reference to what\r\nappears to be “Reverse Proxy” and “HDRDP” debug/response messages.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 24 of 124\n\nBy performing some OSINT using urlscan.io we find that this URL used to just return\r\n‘pluginserver[.]duckdns[.]org’, which is the same domain we found linked to our pastebin URL.\r\nIt’s very likely that this domain was being used to fetch plugins for STRRAT. To tie most of this back together we\r\ncan return to method “sdfsldf” within the Main class and examine more closely what it is doing here.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 25 of 124\n\nIn the above we see it is defining a couple of variables, one for the primary plugins URL which is extracted from\r\nthe config file, and one which is pointing to the pastebin URL containing the same domain. We then see it is using\r\nthis to download the appropriate Java Archive files (plugins), before a request is made to a master server which\r\nlooks to have been registered to take a license ID. In this case the license ID would be “khonsari”.\r\nWe can also confirm that after this a file lock is being created in the user home directory by examining the object\r\ndefined within object9 which in this case is an instance of “dfghrth”.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 26 of 124\n\nAt this stage we can begin to update our decrypter to refine what we’re pulling in from the config file.\r\nIt should be noted that we’ve inferred this is STRRAT version 1.4 by examining the method “shshnfdn” within\r\n“cbnfdhn” which looks to be a check to see if STRRAT has been installed on this host or not.\r\nIf we move back to examining the main method which will continue to run, we can see that one of the parameters\r\npassed as “True” is used to determine if persistence will be setup using a scheduled task called “Skype”, with\r\nanother being used to determine if the configuration will be passed to a new array. This new array is then used\r\nwithin sstydgn.sdfsldf, where the stringArray3 7th parameter is also set to true.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 27 of 124\n\nHost IOC: Scheduled Task - \"Skype\"\r\nIf we once again examine references to this, it appears as if these values are also being used to determine if\r\npersistence is installed, only this time it is writing to the user’s startup directory.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 28 of 124\n\nAt this stage we have enough information and context to complete our STRRAT configuration decrypter and can\r\ncompile a Java Archive to extract the configuration from a given config.txt file.\r\n\"C:\\Program Files\\OpenJDK\\openjdk-11.0.9_11\\bin\\java.exe\" -jar STRRATConfigDecrypt.jar \"C:\\Users\\User\\Desktop\\S\r\nThe completed STRRAT Config Decrypter has been made available for use here. This takes a configuration file\r\nand decrypt’s it.\r\nAlternatively, after collaborating with some bright minds on Twitter (shoutout to Chaitanya - @CbGmanit who\r\nreached out with assistance on properly getting the salt (nonce) used), the following recipe has been devised to\r\nfully decrypt this using CyberChef here\r\nFrom_Base64('A-Za-z0-9+/=',true)\r\nTo_Hex('Space',0)\r\nRegister('([\\\\s\\\\S]{11}).([\\\\s\\\\S]{47})',true,false,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 29 of 124\n\nDerive_PBKDF2_key({'option':'UTF8','string':'strigoi'},128,65536,'SHA1',{'option':'Hex','string':'$R1'})\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R2',false,false,true,false)\r\nFind_/_Replace({'option':'Regex','string':'^([\\\\s\\\\S]{60})'},'',true,false,true,false)\r\nAES_Decrypt({'option':'Hex','string':'$R3'},{'option':'Hex','string':'$R1'},'CBC','Hex','Raw',{'option':'Hex','s\r\nFind_/_Replace({'option':'Regex','string':''},'',true,false,true,false)\r\nRegister('([a-zA-Z.]*).([a-zA-Z0-9.]*).([a-zA-Z0-9\\\\:?@=\\\\-\u0026%//.]*).([a-zA-Z.]*).([a-zA-Z0-9.]*).([a-zA-Z0-9.]*)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R4',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R4'},'C2: $R4',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R5',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R5'},'Primary Lock/Port: $R5',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R6',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R6'},'Plugins Download URL: $R6',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R7',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R7'},'Secondary C2: $R7',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R8',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R8'},'Secondary Lock/Port: $R8',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R9',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R9'},'Startup Folder Persistence: $R9',false,false,true,fals\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R10',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R10'},'Secondary Startup Folder Persistence: $R10',false,fal\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R11',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R11'},'Skype Scheduled Task Persistence: $R11',false,false,t\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R12',false,false,true,false)\r\nFind_/_Replace({'option':'Simple string','string':'$R12'},'License ID: $R12',false,false,true,false)\r\nRegister('([\\\\s\\\\S]*)',true,false,false)\r\nFind_/_Replace({'option':'Regex','string':'.*'},'$R13\\\\n$R14\\\\n$R15\\\\n$R16\\\\n$R17\\\\n$R18\\\\n$R19\\\\n$R20\\\\n$R21',f\r\nSimply put in the config file above, and receive your decrypted configuration file.\r\nUpdate: 6/4/2022 - This has also been ported to Python3 and improved upon for those who like to incorporate this\r\ninto their automation pipelines, or who just enjoy some ASCII artwork ;) and can be found here. This takes a jar\r\nfile (strrat) which contains the configuration file within its resources and automatically reads and decrypts this\r\nwithout the need to extract it first.\r\nUsage: python3 decrypt-strrat.py [PATH TO STRRAT]\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 30 of 124\n\nPart 3: Examining RAT Flow and Functionality\r\nTo drill into this a bit more, we need to know what Java classes are going to be most interesting. One way of doing\r\nthis is to extract the classes and filter based on their size, because a larger class may often be indicative of more\r\ncode making up more interesting functionality.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 31 of 124\n\nThe easiest way to view this code is to view it in Decompiler view rather than viewing them in the ‘Edit with\r\nAssembler’ view we used above.\r\nIf we’re having issues with using the Decompiler, it can often be useful to revisit previous steps. For example if\r\nwe’re unable to decompile a class, perhaps we should try to deobfuscate the malware using the second transformer\r\nrecommended by java-deobfuscator, or we could try a different decompiler within Recaf.\r\nIn this instance there doesn’t appear to be any issues, so let’s first look back at the references to our public static\r\nstring object ‘cbnfdhn.dfhttegd’ which is essentially holding the value “pluginserver[.]duckdns[.]org”. Within the\r\nfgfnbnc class we find this is referenced 3 times. In the first instance we see it is the method cbnfdhn.dfhttegd\r\nbeing run rather than the public string being accessed.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 32 of 124\n\nBecause this is a method, we disregard this hit, but make note that whenever the method fgfnbnc.dfhttegd is run, it\r\nwill attempt to run the method cbnfdhn.dfhttegd. Looking at the next method we can see the reference to HRDP-MGR we saw previously with a little more context.\r\nIn this instance we can see a new registry key being created which ensures that User Names are not shown at the\r\nlogin screen.\r\nHost IOC: HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v dontdisplaylastusername = 1\r\nThis is interesting as it immediately follows what looks to be ensuring that Terminal Services are enabled, and a\r\ncall to add a user account. To determine if there’s a hardcoded user account we can look out for we will need to\r\nexamine ‘object2’ which is being cast to a string here; however, before we do we’ll begin to rename some of these\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 33 of 124\n\nvariables to help keep track of what we’re looking at. To do this we will need to ensure we’ve highlighted the\r\ncorrect class reference, and right click \u003e rename. Using Recafe all associated class references will be updated.\r\nIn this instance I’ve renamed it to PluginsServerURL, and also renamed the other reference in this socket\r\nconnection to PluginsServerPort. Moving back to ‘object2’, we can see this is being assigned by\r\nfgfnbnc3.dfhttegd. By viewing the definition of this variable, we find it is defined in the same class we’re\r\ncurrently in.\r\nRenaming this variable and revisiting the call, we see that there’s an object definition of fgfnbnc3 from the class\r\nfgfnbnc which is why we didn’t see a class with the name fgfnbnc3.\r\nThe benefit of renaming the String is that now we can find all references to that easily. If we continue to examine\r\nthis class we find that there’s a definition of this variable within fgfnbnc’s fgsbdfgsb method.\r\nExamining this method reveals it is a small function used to build a random string to be used as a Username.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 34 of 124\n\nIt’s important to remember that because we’ve managed to get some decompiled code, string builders like this can\r\nbe replicated using VS Code to confirm what we’re reading. Although this is a basic method, we can still recreate\r\nit by making a class that spits out the output of this method.\r\nFrom this we can see this will create a random string with 5 characters.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 35 of 124\n\nTo get some structure behind analysing this malware flow, we’ll return to the main class that we know will be run\r\nas soon as this malware kicks off. First we’ll begin to rename any methods or variables we’ve found so far and\r\ngive them more descriptive names based on their perceived functionality. I won’t walk through all of the analysis\r\nbefore renaming the variables to assist with analysing the malware in a more meaningful way. We’ll continue to\r\nrename more as we determine their purpose; however to start off the following have been renamed:\r\ncbnfdhn.sabretb (Method) = cbnfdhn.MakeGetRetResponse\r\nMain.sdfsldf (Method) = Main.ObjMakeGetRetResponse\r\nMain.sdfsldf (Static String) = Main.STRPluginLocations\r\nMain.sabretb (Static String) = Main.STRFileSeparate\r\nMain.bsgshsbs (Object) = Main.ObjFileLock1\r\nMain.dfhttegd (Object) = Main.ObjFileLock2\r\ndfghrth (Class) = FileLock\r\nMain.sdfsldf (Method, no input) = Main.GetJarRunPath\r\ncbnfdhn.sdfsldf (Method, inputs) = cbnfdhn.C2ConnectAndRun\r\ncbnfdhn.mdgghtdsh (Static InputStream) = cbnfdhn.InStream1\r\ncbnfdhn.sgsfghhg (Static OutputStream) = cbnfdhn.OutStream1\r\ncbnfdhn.hghteerd (Method, no input) = cbnfdhn.ConnectToC2\r\ncbnfdhn.gsbthstgb (Static String) = cbnfdhn.Port1\r\nxbxcv (Class) = UserIdleObject\r\nMain.bsgshsbs (Method, no inputs) = Main.ExtractConfig\r\nsabretb.dfhttegd (Method, inputs) = sabretb.DecryptConfig\r\nsabretb.sdfsldf (Method, inputs) = sabretb.DeriveIV\r\nsabretb.sabretb (Method, inputs) = sabretb.CreateSecKey\r\nMain.dfhttegd (Method, no inputs) = Main.ConnectUnknownURL\r\ncbnfdhn.sdfsldf (Method, one int input) = cbnfdhn.GetFolderPath\r\ncbnfdhn.sdfsldf (Method, one string array input) = cbnfdhn.Uninstall\r\ncbnfdhn.bsgshsbs (Static String) = cbnfdhn.FolderPath\r\ncbnfdhn.sfsrgsbd (Static String) = cbnfdhn.STRLogsLocation\r\ncbnfdhn.sabretb (Static String) = cbnfdhn.STRBackupC2\r\ncbnfdhn.sdfsldf (Static Boolean) = cbnfdhn.ActiveConToC2\r\ncbnfdhn.thtyrths (Method, no input) = cbnfdhn.ParseNumOfCommands\r\ncbnfdhn.sabretb (Method, one int input) = cbnfdhn.ReceiveCommands\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 36 of 124\n\nIf we now examine the main method again we find the below:\r\nIf the malware is able to get the current malware run path and place dependency files in a folder called ‘lib’, it will\r\nthen attempt to get the AppData directory based on CSIDL 26. The malware will continue to extract/decrypt its\r\nconfig file and make requests to get any plugins from the URL configured. Finally after this we see it connect to\r\nthe C2 ready to execute commands received. It should be noted that our defined variables PluginsServerURL and\r\nPluginsServerPort are both being reused here as the C2 configuration from within the decrypted config file.\r\nIn the above we see the start of our C2ConnectAndRun method. In this instance it will check if a directory already\r\nexists called strlogs in the malware working directory, if not it will create one. It will also create an object\r\ncontaining information on whether the infected user is idle, and how long they’ve been idle for, before it\r\ninevitably connects to the C2.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 37 of 124\n\nThe ConnectToC2 method is pretty straight forward, based on the decrypted configuration file it will first close off\r\nany sockets if they already exist with the C2, next it will attempt to connect to the C2 server, and where that fails it\r\nwill fallback to its backup C2.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 38 of 124\n\nAt this point we can begin to see the different commands taken by this malware as they’re received into the array\r\n‘stringArray2’ from the designated C2, which is also placed into stringArray3.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 39 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 40 of 124\n\nBased on this we know that STRRAT 1.4 has the following commands available.\r\nreboot\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 41 of 124\n\nshutdown\r\nuninstall\r\ndisconnect\r\ndown-n-exec\r\nupdate\r\nup-n-exec\r\nremote-cmd\r\npower-shell\r\nfile-manager\r\nkeylogger\r\no-keylogger\r\nprocesses\r\nh-browser\r\nstartup-list\r\nremote-screen\r\nrev-proxy\r\nhrdp-new\r\nhrdp-res\r\nchrome-pass\r\nfoxmail-pass\r\noutlook-pass\r\nfox-pass\r\ntb-pass\r\nie-pass\r\nall-pass\r\nsave-all-pass\r\nchk-priv\r\nreq-priv\r\nrw-encrypt\r\nrw-decrypt\r\nshow-msg\r\nscreen-on\r\nLet’s examine these commands more in depth:\r\nCommand Functionality: reboot\r\nThis command simply runs the following:\r\nRuntime.getRuntime().exec(\"cmd.exe /c shutdown /r /t 0\");\r\nCommand Functionality: shutdown\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 42 of 124\n\nThis command simply runs the following:\r\nRuntime.getRuntime().exec(\"cmd.exe /c shutdown /s /t 0\");\r\nCommand Functionality: uninstall\r\nThis command runs the following (Noting we’ve renamed the method to “Uninstall”):\r\ncbnfdhn.Uninstall(stringArray);\r\nThe uninstall method will then proceed to delete the scheduled task persistence called skype regardless of if it\r\nexists, get the directory the malware is running from, delete it from the directory specified by CLSID 7 and 24\r\nListings can be found here, ping localhost to delay execution for a moment, and then delete the object passed to it,\r\nbefore what appears to be deletion of run keys.\r\nIt should be noted that the CLSID values are being passed as an integer (Decimal) rather than Hex and would need\r\nto be converted to get that 26 = AppData, and 7 = Users Startup Folder.\r\nCommand Functionality: disconnect\r\nThis command will set a boolean variable we’ve renamed as ActiveConToC2 to false, before closing any stream\r\ninputs that are being used in ertdbdth to log key pushes, and then calls exit for this process thus terminating the\r\nrunning STRRAT instance.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 43 of 124\n\nIn essence the disconnect method is terminating the process and disconnecting the C2 connection to STRRAT.\r\nCommand Functionality: down-n-exec\r\nThis command will call 2 more functions inside of cbnfdhn, sabretb (object, string), and dfhttegd (string) which\r\nwe’ll take a closer look at so they can be renamed.\r\nThe first passed parameter to sabretb is an object that will be containing a url from which to retrieve a remote file\r\nfrom. This takes the received file and stores it in object3 which is then launched using either java.exe, wscript.exe,\r\nor cmd.exe depending on its extension.\r\nFrom here we can rename this sabretb method DownloadAndExecute. Finally examining dfhttegd (string) we can\r\nsee this is just used to update the C2 on the STRRAT status, so we can name this and sdfsldf (string) StatusUpdate\r\nand StatusUpdateSend.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 44 of 124\n\nCommand Functionality: update\r\nThis command will create a new object as a file passed to it by running cbnfdhn.gsbthstgb, release the current\r\nfileLock with a method called sdfsldf, execute the object that was passed down to the malware, and then uninstall\r\nthe current STRRAT malware.\r\nThis seems to be a fairly hacked together (pun intended) update mechanism to send an updated version of\r\nSTRRAT to infect the system, and remove the existing version. There’s not a lot of error handling to ensure that\r\nthis is successful though, so if the update fails to execute the new version of STRRAT or the wrong number of\r\nparameters is sent, this can lead to STRRAT uninstalling itself without actually updating.\r\nWe will rename cbnfdhn.gsbthstgb to cbnfdhn.CreateFileObj for further analysis\r\nCommand Functionality: up-n-exec\r\nThis command will function similar to down-n-exec, only instead of it retrieving a file from a defined URL to run\r\n(download and execute) this is going to take an uploaded file directly from the C2 and execute it (upload and\r\nexecute)\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 45 of 124\n\nCommand Functionality: remote-cmd\r\nThis command has 2 primary components, a new object creation with cbnfdhn.sfsrgsbd (this is very similar to\r\nsdfsldf (string) we renamed to StatusUpdateSend, except it does so using a new socket that’s created to the C2),\r\nand a new instance of dgdfndnbcn which is created using the newly created socket, and a string array containing\r\n“cmd.exe”.\r\nWe’ll rename cbnfdhn.sfsrgsbd to cbnfdhn.StatusUpdateSendNewSock. Analysing the new instance of\r\ndgdfndnbcn, we can see that this is about 150 lines of decompiled code long, but we can start with the definition\r\nusing a socket object and a string array.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 46 of 124\n\nAlthough the obfuscation here makes things a little bit confusing, if we look at what we’re dealing with as a\r\nwhole, we can see there’s an input and output stream from the C2, a new process using ProcessBuilder, and new\r\nthreads that will be started for a given process.\r\nWhat’s interesting with this is that only a socket and cmd.exe is being passed to this process creation, and there’s\r\nno command-line parameters given. The reason for this is because it creates a new instance of sabretb, which in\r\nthis case is the process being run, and is redirecting input and output from cmd.exe directly to the established\r\nsocket connection to the C2.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 47 of 124\n\nIf an error occurs a boolean is switched and the socket is released. To this end, remote_cmd is a way of issuing\r\nremote commands to the endpoint in the form of a reverse shell.\r\nWe can rename dgdfndnbcn to ReverseShell for ease of analysis.\r\nCommand Functionality: power-shell\r\nThis command functions much the same as remote_cmd, only it is executing an instance of powershell.exe with\r\nthe command-line “-“ as opposed to running cmd.exe, which I assume is to support command-line arguments with\r\nPowerShell.\r\nCommand Functionality: file-manager\r\nThis command first creates connects to a new Socket on the C2 and sends a status update that the file-manager has\r\nbeen opened before creating a new instance of ‘ghdfdndfn’ using the created socket as a passed parameter.\r\nBy examining ‘ghdfdndfn’ we can see that a new object reference to itself is defined as ghdfdndfn2, before a\r\nvariable of sdfsldf is set to the passed Socket, dfhttegd is set as the input stream to this socket, and sabretb is set as\r\nthe output stream to this socket.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 48 of 124\n\nThe main functionality of this object is stored within the class dfhttegd where commands can be sent via the\r\nestablished socket connection once the file-manager command has been run.\r\nThe commands that can be sent are:\r\nnavigate\r\nnav-key-log\r\nopen\r\ndelete\r\nsavefile\r\nbringfile\r\nnavigate\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 49 of 124\n\nIf navigate is sent, a new call is made to dfhttegd, passing a string that is returned from a call to sabretb which\r\ntakes a passed string as a parameter. To figure out what is happening, we need to take a look at sabretb.\r\nTaking a provided string, sabretb creates an array of files (directories included) based on the given string and then\r\nformats the returned file information for ease of visibility for each given file in the array. In addition this will\r\ncheck if the file is a directory, and if so it will insert a ‘D’ into the returned response. If not it will insert a ‘F’, and\r\nperform calculations of the file size by dividing of 1024 to get the number of kilobytes for each file returned.\r\nThis means that “navigate” effectively functions as a command to “view inside this directory and show me the\r\ncontents”.\r\nnav-key-log\r\n“nav-key-log” performs the same call; however, instead of passing a string provided by the C2, it will\r\nautomatically pass, cbnfdhn.STRLogsLocation which is the location of STRRAT logs we’ve previously renamed,\r\nand thus we can infer this command is to navigate to the log directory and display contents.\r\nopen\r\nIf “open” is sent, STRRAT takes this as an instruction to execute the file using cmd.exe which will use the default\r\nCOM object for the particular file extension it is attempting to run.\r\nRuntime.getRuntime().exec(new StringBuilder().insert(0, \"cmd.exe /c \\\"\").append(stringArray[1]).append(\"\\\"\").to\r\ndelete\r\nIf “delete” is sent, STRRAT makes a call to sdfsldf (file) passing into it the output of a new file object being\r\ncreated with a given string passed to it. By examining sdfsldf we can see that this is a simple function designed to\r\nfirst determine if the object referenced by the string passed is a directory, if so then it will recursively delete all the\r\nfiles inside of this, and the directoy. If not, it will simply delete the file passed to it.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 50 of 124\n\nsavefile\r\nIf “savefile” is sent, STRRAT makes a call to sdfsldf (String) passing in a given file which is read into a\r\nFileOutputStream to allow it to be written to disk.\r\nbringfile\r\nFinally, if “bringfile” is sent, STRRAT creates a new file object and checks if the file object (handle) it now has is\r\na file or not, if not an error is sent back stating that “You cannot download a folder”. Where it is a file, it will make\r\na call to sabretb (file) passing it in this file.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 51 of 124\n\nsabretb (file) will send the bytes of the given file back through to a FileInputStream allowing the file to be\r\ndownloaded.\r\nFrom the above scenarios, although we’re not sure if these commands are sent manually or by an interactive file-manager hosted by the C2, we can conclude that “file-manager” provides a virtual file manager which allows the\r\nabove functionality.\r\nCommand Functionality: keylogger\r\nThis command focuses primarily around the class ghgmgf. If ghgmgf.sabretb is not true, this will create a new\r\nobject from the class ghgmgf, if it is true it will be set to false.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 52 of 124\n\nBy examining ghgmgf we see that sabretb is a simple static boolean being referenced. Further to this we can\r\nexamine the primary ghgmgf method to get an idea of what is happening.\r\nTaking into account the existing socket connection which is passed into this method, there’s also a null string\r\nbeing passed when creating the object, and due to this an entry at line 101 isn’t triggered until after a new ghgmgf\r\nobject has been instantiated and started. Examining line 101 reveals HTML text which is being passed to\r\n‘bsgshsbs’ for writing, which includes the terms ‘Keyboard Log’ and ‘Generated by Strigoi Master’\r\nThis is very basic HTML and winds up looking similar to the below, presumably appended with Keylogs as\r\nkeystrokes are logged, and it tells us that the author of this malware possibly favors a dark theme.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 53 of 124\n\nIt should be noted that if any failures occur an instance of ‘gsbthstgb()’ is called which looks to be closing any\r\nexisting sockets and logging that a Keylogger has been shutdown.\r\nTo understand what this command aims to do we need to look at the below line which runs when a new object of\r\nghgmgf is created after the null check above is performed.\r\nnew Thread(new xnxcxvb((ghgmgf)object)).start();\r\nBy decompiling ‘xnxcxvb’ we can see that it implements the Runnable class with an instance of ghgmgf it is being\r\npassed that is assigned to ‘sdfsldf’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 54 of 124\n\nThe key component here is that when a new thread is being created it will run ‘ghgmgf.sabretb(this.sdfsldf)’,\r\nwhich means we can take a look at the method inside ‘sabretb(ghgmgf)’ to determine what will happen.\r\nIt’s within this method that a GlobalKeyboardHook is registered, which we know is used by the System Hook\r\nPlugin that STRRAT relies on. By decompiling this class we can see a number of keycodes being registered for\r\nlistening, and a number of combination of keys to ensure that these are also logged.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 55 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 56 of 124\n\nGiven this context and because we previously saw the below line within ‘ghgmgf’\r\nthis.sfsrgsbd = ((Socket)object).getOutputStream();\r\nWe can infer that all keys logged are sent directly back to the established socket connection to the C2 in realtime,\r\nand that the command ‘keylogger’ functions as expected as a keylogger leveraging the low level library hook\r\nfreely available.\r\nCommand Functionality: o-keylogger\r\nThis command uses the same method as ‘keylogger’, only it instead passes in a string specifying the location to\r\nlog keys to disk instead of a socket. This file is a HTML file that takes the name “keylogs_.html\" and is stored in\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 57 of 124\n\nour previously discovered \"STRLogsLocation\".\r\nFrom this we can infer that o-keylogger starts an offline keylogger which writes its output to disk rather than\r\nsending over an established socket.\r\nCommand Functionality: processes\r\nThis command creates a new object of class ‘sbsgssdfg’, passing into it the existing socket connection.\r\nExamining ‘sbsgssdfg’ we find that this implements another class that uses the Runnable class ‘sbsbgsrg’, which if\r\nwe examine this can see that upon running it will execute the ‘sdfsldf (sbsgssdfg)’ method.\r\nExamining this method we can see that it is looking for parameters to have been passed, as either ‘reload’ or ‘kill’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 58 of 124\n\nWhere ‘reload’ is passed, it will run an instance of sdfsldf(), and where ‘kill’ is passed, it will use the inbuilt\r\nWindows ‘taskkill’ command to kill a process based on its PID passed to the kill command. Examining sdfsldf(),\r\nwe can see that this leverages the inbuilt Windows ‘wmic’ to enumerate process information.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 59 of 124\n\nFrom this we can infer that ‘processes’ is used to interact with running processes on a system to either enumerate\r\nand show them, or kill one specified by its PID.\r\nCommand Functionality: h-browser\r\nThis command primarily functions from within the ‘sgsfghhg’ class.\r\nThis leverages the ‘HBrowserNativeApis’ class to return appropriate bitmap representations for specific browser\r\nwindows running on the victim machine.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 60 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 61 of 124\n\nThere’s a lot of code in amongst here for drawing and sending over a socket the visual contents of essentially a\r\n‘virtual web browser’ to the adversary so we’ll hone in on some specific code. The first thing we can notice inside\r\n‘sgsfghhg’ is the presence of a number of commands being sent down the socket including ‘start’, ‘stop’, ‘mouse-event’, and ‘key-event’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 62 of 124\n\nWithin the above we also see that when ‘start’ is sent we get another new thread spawning for an object\r\n‘fdghdmh’.\r\nnew Thread(new fdghdmh(sgsfghhg2, (String)object3)).start();\r\nThis gives us a new method which will be run when this command is sent down which is\r\n‘sgsfghhg.sdfsldf(sgsfghhg, String)’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 63 of 124\n\nBy examining this method we can see this is largely based around creating a byte array that’s written down the\r\nSocket in the form of a rendered PNG.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 64 of 124\n\nAlthough in this instance there’s some broken decompiled code, we can see many instances of this referencing\r\nchrome.exe and firefox.exe within methods including sdfsldf().\r\nand sabretb().\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 65 of 124\n\nFinally if we cross reference any references to these we can see that a large proportion of this is facilitated in the\r\nmethod ‘dfhttegd(String)’ which contains references to a ‘Strigoi Browser’ which starts as either a chrome or\r\nfirefox process depending on what is on the victim computer.\r\nFrom this we can infer that ‘h-browser’ is used to spawn a virtual ‘HTML Browser’ dubbed ‘Strigoi Browser’\r\nusing either Firefox or Chrome as the host process for this.\r\nCommand Functionality: startup-list\r\nThis command creates a new object of class ‘sstydgn’, passing into it the existing socket connection.\r\nOnce again we see a familiar thread creation, this time defined within the class ‘ncgdfhbn’.\r\nOnce again implementing the runnable class this is set to kick off ‘sstydgn.sdfsldf(ssydgn)’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 66 of 124\n\nFrom here we see this takes one of 3 commands, ‘reload’, ‘delete’, or ‘add’.\r\nreload\r\nWhen ‘reload’ is sent this command will proceed to run an instance of ‘sstydgn.sdfsldf()’. This will first run\r\n‘wmic’ to enumerate current notable autostart entries on the system. When accounting for escape characters the\r\ncommand run is as follows.\r\nwmic /node:. /namespace:'\\\\root\\cimv2' path win32_startupcommand get name,location /format:list\r\nThis then performs data processing based on the way results are returned. An example of a returned entry is\r\nincluded below:\r\nLocation=HKU\\S-1-5-19\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 67 of 124\n\nName=OneDriveSetup\r\nIf we look at how this manifests in the code we see the following:\r\nFrom the above and example provided we can see this is splitting the results of the location and name results in\r\nwhat it is presenting based on the returned ‘=’. We can also see evidence that this is translating entries that simply\r\nsay ‘Startup’ to the CSIDL ordinal (Folder path) ‘7’ (CSIDL_STARTUP), ‘Common Startup’ to the CSIDL ordinal\r\n(Folder path) ‘24’ (CSIDL_COMMON_STARTUP), ‘HKU’ to the full string\r\n‘HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run’, and ‘HKLM’ to the full string\r\n‘HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run’.\r\nNote: More information on CSIDL Ordinals\r\nThe issue with the above approach is that it contains a logic bug. It assumes that every result returned will be that\r\nof the current user (HKCU) - HKEY Current User; however, when running this WMI command it will return\r\nresults from other user SIDs such as ‘.DEFAULT’, ‘S-1-5-18’ (NT AUTHORITY\\SYSTEM), and in the case of\r\nrunning as Admin, other users on the system. Because of this the results returned will state the run keys are always\r\nthat of the current user. Further to this it will also replace the key with the location of the standard ‘Run’ key;\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 68 of 124\n\nhowever, if this was instead a different key such as ‘RunOnce’, it would still resolve as the ‘Run’ key location\r\nbecause of this logic flaw. This demonstrates an oversight by the malware author.\r\nFrom this we can infer that ‘startup-list reload’ is used to show the current startup (autorun) items on this host.\r\ndelete\r\nWhen ‘delete’ is sent this command will proceed to run an instance of ‘sstydgn.sdfsldf(String)’. This will check\r\nwhat is being passed to it, and where it starts with either HKCU or HKLM it will attempt to delete it from registry\r\nusing the native ‘reg.exe’ command. Where this doesn’t start with either of these characters the malware will\r\nattempt to delete it as if it was a file or folder on the system.\r\nThis demonstrates another oversight where the malware only has support for deleting startup keys with this for the\r\ncurrent user or local machine, and not other user hives.\r\nFrom this we can infer that ‘startup-list delete’ is used to remove either the current user/local machine registry run\r\nkey, or a file present on the system.\r\nadd\r\nWhen ‘add’ is sent this command will proceed to run an instance of ‘sstydgn.sdfsldf(String, boolean, boolean)’.\r\nThis functions as a way to add persistence through both a registry run key, or a file written to either\r\nCSIDL_STARTUP or CSIDL_COMMON_STARTUP.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 69 of 124\n\nThis uses another method ‘sfsrgsbd.sdfsldf(int, String)’ to perform the registry additions. What’s interesting here is\r\nthat rather than using ‘reg add’ native commands as was done with the ‘delete’ command, this instead uses\r\nmethods defined in Java that leverage relevant Windows APIs.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 70 of 124\n\nThis difference highlights one of maybe 3 possible scenarios.\r\nThe malware author intentionally chose to not leverage reg.exe to add in persistence to evade some EDR\r\nsignatures.\r\nThe malware author is actually instead malware authors, all of whom focus on a different part of the RAT,\r\nor it has been adapted from code “borrowed” or “stolen” over time.\r\nThe malware author didn’t realise that there was an ‘add’ parameter for reg.exe.\r\nGiven the code quality inconsistencies I’d say it’s likely this was made by multiple people, or it has been chopped\r\nand changed/stolen over time.\r\nFrom this we can infer that ‘startup-list add’ is used to add either an entry to the current user/local machine\r\nregistry run key, or a file to one of 2 known startup directories on the system.\r\nCommand Functionality: remote-screen\r\nThis command primarily functions from within the ‘sabretb(Socket)’ class.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 71 of 124\n\nAt a glance we can see that this is importing a lot of classes to do with encryption and drawing pixels to the\r\nscreen.\r\nNote: To get a clean decompilation we’ll be switching to the FernFlower decompiler built into Recaf.\r\nTaking a look at the main class executed see 2 familiar thread creations in addition to some input and output\r\nstream declarations. This time the thread creations are defined within the classes ‘fgsbsfgsb’ and ‘hghteerd’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 72 of 124\n\nClass ‘fgsbsfgsb’ will be ensuring ‘sdfsldf(sabretb)’ is run.\r\npublic final void run() {\r\n sabretb.sdfsldf(this.sdfsldf);\r\n}\r\nClass ‘hghteerd’ will be ensuring ‘sabretb(sabretb)’ is run.\r\npublic final void run() {\r\n sabretb.sabretb(this.sdfsldf);\r\n}\r\nIf we compare these classes we see that ‘sdfsldf(sabretb)’ is expecting a successfully established socket so that it\r\ncan send bytes which are stored from an instance of sabretb.sdfsldf(BufferedImage). We can also see reference to\r\nRemote Desktop in a debug message.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 73 of 124\n\nExamining this method we can see that it looks to be sending a ByteArray Stream of the user’s screen down the\r\nsocket in the form of a continuous JPG.\r\nNow looking at ‘sabretb(sabretb)’ we see that this is looking for events indicating whether a mouse has been\r\nmoved, key pushed, mouse wheel scrolled, or mouse double clicked.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 74 of 124\n\nThese events directly cause events that are directly tied to updating the image being sent down the established\r\nsocket and sends commands through the java.awt.Robot class that has been imported here.\r\nFrom this we can infer that ‘remote-screen’ is used to spawn a ‘VNC’ or ‘RDP’ type connection to the system and\r\nallow control of the mouse and keyboard input.\r\nCommand Functionality: rev-proxy\r\nThis command primarily functions from within the ‘ncnndfg(String)’ class.\r\nExamining this we can see that this looks to be establishing a new Socket connection to the configured\r\n‘PluginsServerURL’ and ‘PluginsServerPort’ variables. From this we can begin to see this appears to function also\r\nas a facilitator for this ‘rev-proxy’ command.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 75 of 124\n\nSome key components with this stem from the definition of ncnndfg3.sdfsldf as a new ‘fgssdg’ object, passing in\r\nthe ‘ncnndfg’ object itself, before running this object, passing in a socket connection, and the object created\r\n(confusing I know).\r\nncnndfg3.sdfsldf = new fgssdg(this);\r\nncnndfg3.sdfsldf((Socket)object, ncnndfg3.sdfsldf);\r\nBreaking down the crux of this we need to look at the ‘fgssdg’ class, and we can see stark similarities with the\r\n‘ncnndfg(String)’ class.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 76 of 124\n\nThe difference here is that instead of the above mentioned implemenetations this is running\r\n‘ncnndfg.sabretb(ncnndfg, Socket, xbvcxnx)’, and examining this we find yet another invocation, this time of\r\n‘ncnndfg2.sdfsldf(socket)’\r\nRemaining cognizant that this is passing in an established socket and interface ‘xbvcxnx’ which references\r\n‘sdfsldf()’, we finally can see this starts a new thread implementing ‘ngdnbn(ncnndfg, Socket, xbvcxnx)’ which\r\nwe’re now well and truly familiar with thread runnable objects.\r\nPivoting back to ncnndfg we can now begin to see the main part of this command’s functionality.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 77 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 78 of 124\n\nSome important parts of this method occurs at lines 104-114 which is involved in receiving a CONNECT network\r\nrequest and sending back a 200 Connection Established message. This is only possible due to an instance of\r\nncnndfg (ncnndfg2) being defined as object3 at line 76.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 79 of 124\n\nHere we also see that when a socket is established a new instance of ‘ghsghnbn’ will be created at line 112 whilst\r\ninvoking a public method ‘sdfsldf(Socket, Socket)’. Examining what this method entails we can see it is largely\r\naround defining 2 socket connections passed in and then creating 2 new threads, one for the object ‘mdgghtdsh’\r\nand the other, ‘ndgdfhfh’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 80 of 124\n\nTaking a look at what these are used for, both once again are starting a thread using the Runnable class, and one\r\nwill execute the method ‘sdfsldf(ghsghnbn)’, whilst the other executes ‘sabretb(ghsghnbn)’, both inside of\r\n‘ghsghnbn’. Taking a look closer we can see that both of these are very similar except with some subtle\r\ndifferences.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 81 of 124\n\nIn the above we can see that the difference occurs with the input and output streams being used, and these are the\r\nexact same streams defined for each socket passed for ‘sdfsldf(Socket, Socket)’ as shown previously.\r\nThere’s really not a lot of further investigation or code to unravel in this command, and from this we can infer that\r\n‘rev-proxy’ is used to create a ‘reverse proxy’ or socks proxy on the host that would allow accessing an internal\r\nservice/port on the host by hitting an external domain on the correct port (in this case the plugins server).\r\nCommand Functionality: hrdp-new\r\nThis command primarily functions from within the ‘fgfnbnc(String)’ class. We’ve touched on some of the\r\nelements of this previously, but now we’ll go into a bit more depth. Decompiling once again using FernFlower we\r\ncan see that this gets reference to a hrdpinst.exe binary that will be stored within the Jar run path once\r\ndownloaded, before noting the appropriate browser in use on the system (x86 or x64 version of Firefox or\r\nChrome), and starting a new thread of ‘gmgmgmgm(fgfnbnc)’.\r\nExamining this we see ‘sdfsldf(fgfnbnc, String)’ being called which in turn runs\r\n‘cbnfdhn.StatusUpdate(“Initializing HRDP”)’ to update the C2. In addition this will run ‘sdfsldf(fgfnbnc)’ to\r\nensure that HRDP has been downloaded and initialised, and that a new user account has been created that can be\r\nused with this tool.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 82 of 124\n\nThe specific downloading of this tool is from within ‘ertdbdth()’ that is run within the if statement right before\r\n“HRDP Downloaded” is sent back to the C2.\r\nThis gives us another wshsoft.company IOC which is used to download the binary into the previously mentioned\r\nhrdpinst.exe binary, noting the mismatched extension here.\r\nNetwork IOC: hxxp[://]wshsoft[.]company/multrdp[.]jpg\r\nWe’ve mentioned some of this previously; however we can now see in more depth what is occurring when “hrdp-new” is sent. Of interest is a new instance of an agafhas object being created, and if we investigate this further we\r\nsee a message being sent to the C2 of “HRDP-SOC” before invoking ‘sdfsldf(fgfnbnc, Socket, dfhdfndfg)’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 83 of 124\n\nBased on what we’re seeing we can begin to believe that this is acting as a socket to support HRDP, and looking at\r\nthe invoked method we find it invokes another method ‘sdfsldf(Socket, dfhdfndfg)’ which finally kicks off another\r\nthread, this time of class ‘bmcvbmd(fgfnbnc, Socket, dfhdfndfg)’.\r\nThe above new thread creation is used on yet another class that implements the runnable class and invokes\r\n‘sabretb(fgfnbnc, Socket, dfhdfndfg)’\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 84 of 124\n\nBy examining this further we find that this looks to be reading in an inputstream and determining whether it is\r\nsending the command “CLONE”, “EXITS”, or “EXIT”. In addition to this we can see if none of these are being\r\nsent it will create a socket tunnelling port 3389 (default RDP) to the C2 to allow RDP directly to the system.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 85 of 124\n\nExamining the clone thread we see evidence that this is being used to clone a user’s browser session via the new\r\nthread of ‘thrhhrth(fgfnbnc)’ based on an update being sent to the C2, before running an invocation of\r\n‘dfhdfndfg.sdfsldf()’ which is defined within var2.\r\n(new Thread(new thrhhrth(var0))).start();\r\nvar2.sdfsldf();\r\nTaking a look at ‘fgfnbnc.sabretb(fgfnbnc)’ we can see that this is looking to determine if a file exists which is an\r\nobject holding the cloned Firefox profile.\r\nIf this profile exists it will check to see if a Firefox.bat file has been dropped to the created user’s desktop, and if it\r\nhas it will send a message that Firefox has been cloned. If it hasn’t, it will attempt to get a Firefox profile by\r\nrunning through ‘sbsbgrsg()’, and then from this attempt to clone the user’s Firefox profile by creating a launcher\r\n(a batch script, note the misspelling of launcher message also) which runs Firefox but uses the ‘–no-remote -\r\nprofile’ parameters to specify starting with this found user’s profile.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 86 of 124\n\nIf we instead look at the ‘EXITS’ flow, we see that this runs the below:\r\nLooking into this we find that it’s all about ‘cleaning up’ and covering tracks from running HRDP. In this instance\r\nit seeks to delete the temporary created account and restore visibility of the last logged on username at the logon\r\nscreen.\r\nLooking at the ‘EXIT’ flow, we see that this runs the below:\r\nvar0.gsbthstgb(var0.UserName);\r\nThe method takes in a String and then proceeds to load in Kernel32.dll so that it can check within sfsrgsbd()\r\nwhether this is running on a 64bit OS or not. This is done so that the Wow64DisableWow64FsRedirection\r\nwindows API function can be called to disable redicrections that occur on 32bit applications running on 64 bit\r\nOS’, before logging the user off and re-enabling this.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 87 of 124\n\nBased on this it’s inferred that ‘EXIT’ is used to logoff of the RDP session established. Finally if we examine the\r\nmethod ‘sdfsldf(String)’ within ‘fgfnbnc’, we find that this method is being embedded in checks performed\r\nwhenever a new ‘net’ command is being run from this malware, with the same occurring in ‘sabretb(String)’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 88 of 124\n\nWhat we can see here is that the malware seems to have some sort of checks in place for different “command\r\ncompleted successfully” messages which could be being resolved in the following languages.\r\nEnglish\r\nSpanish\r\nFrench\r\nGerman\r\nItalian\r\nThis may indicate that the intended targets of this malware or languages spoken of intended victims are that of the\r\nabove. Regardless, from this we can infer that ‘hrdp-new’ is used to invoke a ‘Hidden’ RDP session which can\r\nclone user’s Firefox and Chrome browser sessions.\r\nCommand Functionality: hrdp-res\r\nThis command primarily functions from within the ‘fgfnbnc(String)’ class much like the previous command;\r\nhowever the primary difference is that this takes in a variable which acts as the defined username rather than\r\nrandomly creating a new one after ‘null’ was previously passed in.\r\nNot far into the routine a variable var2 is set to the username passed in, and checks are made using net commands\r\nto see if the user exists already or not and if it is in the local administrators group. Where it is then all checks are\r\npassed and the re-initialisation of HRDP won’t occur, but the session will be allowed to run.\r\nFrom this we can infer that ‘hrdp-res’ is used to restore a ‘Hidden’ RDP session where a user was previously\r\nlogged off using the ‘EXIT’ command.\r\nCommand Functionality: chrome-pass\r\nThis command primarily functions from within the ‘thtyrths()’ class.\r\nAfter creating a new instance of this, it has the output of ‘sdfsldf()’ appended to the message sent to the C2. If we\r\nexamine this method, it first checks if it is running Windows or not, and if it isn’t a message is displayed saying it\r\nis not supported, if it is it will proceed to run ‘sabretb()’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 89 of 124\n\nIf the output of this method is nothing then the message “No passwords Found” will be sent back, if it contains\r\nsomething, that will instead be returned, so let’s investigate ‘sabretb()’.\r\nThis leverages the JDBC driver SQLite Wrapper to interface with the Google Chrome password SQL database.\r\nFrom here it proceeds to retrieve all columns from the “logins” table and extract their relevant elements. From\r\nhere STRRAT proceeds to use the DPAPI CryptUnprotectData function to decrypt the user’s stored Google\r\nChrome passwords on this system.\r\nIn the event that using DPAPI fails to retrieve credentials, STRRAT falls back to running the below.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 90 of 124\n\nWithin this function we see a number of operations occurring, but probably one of the best assumptions as to why\r\nthis occurs is made apparent from the below blog post.\r\nKirby Angell - Decrypting Browser Passwords \u0026 Other Secrets\r\nAs Kirby explains it, the the ‘Local State’ file which is being read in contains the DPAPI encrypted encryption\r\nkey, and whereas older versions of Chromium (and hence Chrome) used solely the Login Data file and DPAPI, all\r\npasswords could be revealed using solely these and the relevant API (CryptUnprotectData), which we saw just\r\nbefore. Nowadays browsers need to first extract the internal key which has been encrypted from within the Local\r\nState file, and then calls CryptUnprotectData to decrypt this key. From here the key is then changed to a byte array\r\nand is used to create a secret key via AES encryption from this byte array, which is subsequently then used to\r\ndecrypt the password given.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 91 of 124\n\nFrom this we can infer that ‘chrome-pass’ is used to decrypt usernames and passwords stored from within the\r\nlogged on user’s Google Chrome profile.\r\nCommand Functionality: foxmail-pass\r\nThis command primarily functions from within the ‘dsgsdfge()’ class, specifically what kicks off from the\r\n‘sdfsldf()’ function.\r\nLooking into this further we can see that it is using a registry class ‘Foxmail.url.mailto’, presumably to get the\r\ninstall path of Foxmail. From this it is then looking for the Account.rec0 file stored within aan ‘Accounts’\r\nsubdirectory, and this is then being read to decode the Email and Password from within it.\r\nThe actual decoding occurs from within the class ‘sdfsldf(int, String)’, and we can tell this is encoding as it is\r\nperforming permutations from fixed characters rather than any type of encryption using a schema such as AES.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 92 of 124\n\nThe operations here occur a lot against an array of characters, and although we could go into each entry, it’s\r\nsometimes useful to explore OSINT to see if we can infer what is happening. Whilst researching these methods I\r\nstumbled across the following foxDecode program on Github which I believe may have been used to heavily\r\ninfluence how this command works. It has been cloned on the off chance it changes over time and can be found\r\nbelow:\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 93 of 124\n\nJPMinty FoxDecode Fork\r\nComparing the first statement in this project we can see striking similarities in our decompiled code to that of the\r\nC Sharp program above, despite the differences in languages used.\r\nFollowing on from this we see almost a like-for-like identical comparison occurring, with one making\r\ncomparisons in decimal, whereas the other is checking the decimal hex equivalent value. For this to be a\r\ncoincidence is highly unlikely, it’s almost certainly that this code has been ripped off and ported to function as part\r\nof this Trojan, and it’s not uncommon to have malware authors steal code as a means to an end.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 94 of 124\n\nThe plus side to all of this is we have nicely annotated code and can understand what is happening… at this point I\r\ncan’t not put this here.\r\nExamining ‘sdfsldf(int, String)’ and how it applies to the rest of this code we find the following:\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 95 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 96 of 124\n\nBased on this we can infer that ‘foxmail-pass’ is used to retrieve email addresses and decode passwords stored\r\nfrom within the installed Foxmail user profiles using ported C# code which is almost certainly plagiarised from\r\n‘StarZHF’ and ‘Jacob Soo’.\r\nCommand Functionality: outlook-pass\r\nThis command primarily functions from within the ‘xncxbc()’ class, specifically what kicks off from the\r\n‘sdfsldf()’ method.\r\nExamining this method we can see that it looks to search through some specific registry keys for the current user\r\nwhich are associated with Outlook. In specifics this is searching for any entry which after being converted to\r\nlowercase simply contains the key “password”, if this is not found it will continue searching, but if it is found it\r\nwill add this to an array called ‘object5’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 97 of 124\n\nFurther on from this we find that it will examine any key which contains “IMAP Password”, “POP3 Password”,\r\n“HTTP Password”, or “SMTP Password”, and will then pull out the corresponding SMTP Server, Email, and\r\nPassword (after decrypting using ‘CryptUnprotectData’ which once again uses DPAPI).\r\nBased on this we can infer that ‘outlook-pass’ is used to retrieve the SMTP Server, Email, and Password values\r\nstored from within the appropriate Outlook registry keys if they exist on the system.\r\nCommand Functionality: fox-pass\r\nThis command primarily functions from within the ‘dncbnf(boolean)’ class, this time things are a bit different\r\nwhen creating an instance of this object as it uses variables ‘sabretb’, and ‘sdfsldf’ in determining what is\r\nhappening when this command is run, it also has an error message to indicate the command will be targeting\r\nFirefox.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 98 of 124\n\nExamining this class we find that upon being instantiated it will set a number of variables and run\r\n‘this.bsgshsbs()’. This method looks to have support for both ‘Thunderbird’ and ‘Firefox’ based on examined\r\nstrings; however, we need to take note that the object is being created with ‘false’ in this instance and as such will\r\nhave a variable ‘dfhttegd’ set to ‘false’ that plays a key part in determining whether this is looking at Firefox or\r\nThunderbird.\r\nIn the above we can see that this is specifically looking for a ‘profiles.ini’ file in the user’s roaming directory for\r\nFirefox to be used within a new object created from ‘nddfgndt(String)’, and is specifically looking for anything\r\nthat starts with the string ‘Profile’ in the list of returned objects. The gist of this is that it will be extracting the\r\nrelevant Firefox profile directory to then search for the files ‘logins.json’, ‘key4.db’, and ‘cert9.db’, prior to\r\nrunning the method ‘sdfsldf(File, File, File)’ over these 3 files.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 99 of 124\n\nThe above clears up what this is doing. After locating the above files they will attempt to be compressed into an\r\narchive called ‘rpack.zip’ which is sent as a serialized sequence of data. This differs from the previously seen\r\ncommands in that there are no attempts to decrypt or decode these files to retrieve the credentials in cleartext, but\r\nrather is exfiltrating 3 files ‘logins.json’, ‘key4.db’, ‘cert9.db’ in an attempt to clone the user’s Firefox profile. We\r\ncan see these files are useful in doing so by looking at an answer given by ‘cor-el’ here on a Mozilla Support\r\nForum, replicated below for convenience.\r\nFirefox 58+ versions use key4.db for the key file (default salt and master password).\r\nPrevious Firefox versions used the key3.db file although they can use key4.db (SQLite).\r\nSupport for SQLite databases (key4.db and cert9.db) exists since 2011.\r\nIf you copy logins.json and key4.db to the current profile folder then Firefox should be able to find the userna\r\nNote the logins.json and key4.db should match.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 100 of 124\n\nBased on this we can infer that ‘fox-pass’ is used to retrieve the user’s ‘logins.json’, ‘key4.db’, and ‘cert9.db’ files\r\nfrom their respective Firefox profile in order to later decrypt these or import these into a Firefox session to steal\r\ncredentials.\r\nCommand Functionality: tb-pass\r\nThis command primarily functions from within the ‘dncbnf(boolean)’ class much like the ‘fox-pass’ command,\r\nonly this time it is being run with a ‘true’ value rather than a ‘false’ value being passed.\r\nThe sole difference between this command being run and the ‘fox-pass’ command being run is that this is instead\r\nlooking for the common ‘Thunderbird’ working directories as opposed to the ‘Firefox’ ones. Examining this post\r\non MozillaZine, a Mozilla documentation website created by the user community, we find this also contains\r\n‘logins.json’, ‘key4.db’, and ‘cert9.db’ which can be used to recover stored passwords.\r\nBased on this we can infer that ‘tb-pass’ is used to retrieve the user’s ‘logins.json’, ‘key4.db’, and ‘cert9.db’ files\r\nfrom their respective Thunderbird profile in order to later decrypt these or import these into a Thunderbird session\r\nto steal credentials.\r\nCommand Functionality: ie-pass\r\nThis command primarily functions from within the ‘dhgdghd()’ class.\r\nExamining this class we find that this is actually one of the more simple classes. Upon being instantiated this\r\nobject will launch a new powershell process and create a new object of type\r\nWindows.Security.Credentials.PasswordVault. From here it will run the RetrieveAll method to quite literally\r\nretrieve all the credentials stored in the Credential Locker. This will generally bring back hidden passwords;\r\nhowever, a quick pipe to RetrievePassword successfully extracts these credentials.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 101 of 124\n\nOnce again if we weren’t sure about this we could do a search and wind up on Github with some code to retrieve\r\ncredentials from IE \u0026 Edge which is identical.\r\n# Content: Receive Credentials from IE \u0026 Edge\r\n# Author: Florian Hansemann | @CyberWarship | https://hansesecure.de\r\n# Date: 09/2020\r\n[void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime]\r\n$vault = New-Object Windows.Security.Credentials.PasswordVault\r\n$vault.RetrieveAll() | % { $_.RetrievePassword();$_ } | select username,resource,password\r\nBased on this we can infer that ‘ie-pass’ is used to retrieve all the credentials stored in the Credential Locker used\r\nby Edge and Internet Explorer…and that malware authors rip code off from others, who’d have thought?\r\nCommand Functionality: all-pass\r\nThis command begins to chain a number of the above credential harvesting techniques specifically called out in\r\n‘dhgdghd()’ (IE / Edge), ‘thtyrths()’ (Google Chrome), ‘dsgsdfge()’ (Foxmail), ‘xncxbc()’ (Outlook), before\r\nchecking if the command passed was ‘save-all-pass’, in the event it was, it will send these to the C2 before further\r\nprocessing occurs.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 102 of 124\n\nFrom the above we also see that if the command didn’t include ‘save-all-pass’, STRRAT will continue processing\r\n‘dncbnf(boolean)’ to get both Firefox and Thunderbird related files which will be sent to the C2.\r\nBased on this we can infer that ‘all-pass’ is used to harvest credentials for IE/Edge, Google Chrome, Foxmail, and\r\nOutlook. In the event that ‘save-all-pass’ is being sent instead as the command, this will send all of these to the\r\nC2. If not, it will go out and try to retrieve Firefox and Thunderbird files needed to decrypt or import passwords.\r\nCommand Functionality: save-all-pass\r\nThis command is actually a part of the ‘all-pass’ command mentioned above and determines if credentials will be\r\nsent to the C2 or not.\r\nCommand Functionality: chk-priv\r\nThis command functions by simply running cbnfdhn.ssdgsbh() and sending back your privileges as either ‘Admin’\r\nor ‘User’.\r\nJust when we thought commands couldn’t be more simple we find this. By examining ssdgsbh() we can see that\r\nthis is used to try and write a new file to ‘C:\\Windows\\System32\\config\\dummy.log’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 103 of 124\n\nBecause the location this file is being written to has a default Access Control List (ACL) which restricts it to\r\nAdministrators, this command takes a shortcut method of trying to write a dummy file, and if it can’t do it just\r\nassumes you’re not an Administrator, cute.\r\nBased on this we can infer that ‘chk-priv’ is used to try and write a dummy file to\r\nC:\\Windows\\System32\\config\\dummy.log as a way to check user privileges. Where it’s successful it will send\r\nback ‘Privilege: Admin’, and where it fails it will instead send back ‘Privilege: User’.\r\nCommand Functionality: req-priv\r\nThis command primarily functions from the ‘sstydgn()’ method inside of cbnfdhn which if the method returns\r\n‘true’ will cause this process to terminate via System.exit(0).\r\nThe reason this is occurring can be uncovered easily as we dive into ‘sstydgn()’. Looking at this method we can\r\nsee that it is attempting to launch PowerShell in order to use the ‘start-process’ commandlet to run STRRAT using\r\n‘-verb runAS’. As this happens STRRAT will be attempting to use PowerShell to launch STRRAT as\r\nadministrator which will generally function by sending a UAC prompt to the user asking if they want to run this.\r\nIf the user confirms this or UAC is not enabled then this will return true and kill the current STRRAT process as a\r\nnew one will have been spawned with Administrator rights.\r\nBased on this we can infer that ‘req-priv’ is used to use PowerShell in an attempt to run STRRAT with\r\nadministrator rights/privileges.\r\nCommand Functionality: rw-encrypt\r\nThis command primarily functions from a newly created object of ‘sdfsldf(string)’.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 104 of 124\n\nWhat’s important here is that the method is passed in an string when it is created that gets assigned to ‘dfhttegd’,\r\nthis will later be used as a passphrase.\r\nThere’s also a variable ‘sdfsldf’ which contains the string ‘.crimson’ and is used throughout this command being\r\nrun. In summary this will take a passed string as a password, and upon being instantiated will locate the user’s\r\nDownloads, Documents, and Desktop directory and store this in an array. From here STRRAT will iterate over the\r\narray, and if a file exists at that location it will read in the bytes of that file into another array. From this it will use\r\na passphrase stored in ‘dfhttegd’ and proceed to encrypt the bytes of the read in file one by one using AES-128\r\nencryption. The encrypted bytes are then written back to disk at the same location, except with the ‘.crimson’\r\nextension, and the original file is then deleted.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 105 of 124\n\nThis highlights the importance of examining malware revisions for changes and citing your sources given a\r\nnumber of companies copy work by other researchers or companies without giving proper credit or performing the\r\nanalysis themselves. At the time of writing I have identified at least 2 posts publicly which are still stating that this\r\nRAT doesn’t implement a ransomware routine and merely changes the extension of files on disk, and from what\r\nwe can see here, this is simply not the case. The posts go into no technical detail and despite showing version 1.4\r\nand 1.5 of STRRAT in the analysis, it’s mentioned this is a fake ransomware module. From at least version 1.4 this\r\nin fact does look to have a fully functioning ransomware routine as shown here, and I strongly believe anyone\r\nwho thinks otherwise is citing (or not citing) old research without analysing the samples themselves.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 106 of 124\n\nBased on this we can infer that ‘rw-encrypt’ is used as a ransomware module to encrypt the user’s Downloads,\r\nDocuments, and Desktop directory using AES-128.\r\nCommand Functionality: rw-decrypt\r\nThis command primarily functions from a newly created object of ‘sdfsldf(string)’ much like the ‘rw-encrypt’\r\ncommand, with the difference being that the new thread being created is instead occurring via ‘dfghdmc’.\r\nExamining this we can see that this will instead kickoff a method of ‘sabretb’ inside of ‘sdfsldf’.\r\nTaking a look into this we find it is much the same as ‘rw-encrypt’, except with a difference being it is using the\r\npreviously established object in ‘rw-encrypt’ and a passphrase down to decrypt the files of interest by reusing the\r\n‘DecryptConfig’ method which we previously renamed. This method is more broadly used as a decryption method\r\nnow, both for STRRAT’s configuration file, and also the ransomware decryption module.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 107 of 124\n\nBased on this we can infer that ‘rw-decrypt’ is used as the recovery method for STRRAT’s ransomware module\r\nand is used to decrypt the user’s Downloads, Documents, and Desktop directory using AES-128.\r\nCommand Functionality: show-msg\r\nThis command works as the message component of the executed ransomware and is very basic in how it works.\r\nFirst off it will get the location of the user’s desktop and create a file called ‘crimson_info.txt’ there. From here it\r\nwill take a passed string to the command and write it within that file, and finally it will execute notepad to display\r\nthe contents of this file to the user.\r\nThis is pretty unusual and bizarre to be honest, given most ransomware variants will encrypt a number of files and\r\ndo this not only in multiple threads, but with multiple files being dropped and a message which is modular but\r\nbaked into the ransomware sample. In comparison this seems to just give the functionality to either use this or not\r\ndepending on what the operator wishes to do.\r\nBased on this we can infer that ‘show-msg’ is used to create and display a ransomware (or arbitrary) message to a\r\nvictim by creating a text file on the user’s desktop and using notepad to open it.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 108 of 124\n\nCommand Functionality: screen-on\r\nThis command kicks off a new thread of object ‘fhjtjtg()’ which has been created.\r\nExamining this we find it kicks off the method ‘bsgshsbs()’ from within ‘cbnfdhn’.\r\nExamining this we can see that it is used to move the mouse ever so slightly as to keep the computer from falling\r\nasleep (prevent screensavers).\r\nBased on this we can infer that ‘screen-on’ is used to move the mouse ever so slightly as to keep the screen on and\r\nprevent any computer screensaver.\r\nWrapping up flow and functionality:\r\nAt this point there’s not much we haven’t covered off in this particular piece of malware, we’ve well and truly\r\nreversed it and showed how we came to every conclusion along the way. The standard beaconing of STRRAT can\r\nbe seen under the method ‘sbsgssdfg’ which we glossed over far earlier in this analysis piece. This sends certain\r\ninformation about the host that’s been infected back to the C2 in the form of a ‘ping’, which is actually a web\r\nrequest, and not an ICMP (ping) packet.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 109 of 124\n\nAs the cherry on top we can see one last evidence of this retrieving the user’s publicly facing IP address by\r\nmaking a request to ip-api[.]com which is referenced within the method ‘sbsgssdfg()’ and ‘fgssdg()’.\r\nNetwork IOC: ip-api[.]com/json/\r\nNetwork IOC (User Agen): Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome\r\nPart 4: Threat Intelligence and Detection Engineering\r\nDetection Engineering\r\nYara Rule\r\nTo build out a Yara rule we’ll take a look at some of the most common IOCs seen in this malware as analysed\r\nabove, and select a subset of these in addition to other commands seen embedded into the malware’s functionality:\r\nNetwork IOCs:\r\nhxxp[://]wshsoft[.]company/jre7[.]zip\r\nhxxps[://]pastebin[.]com/raw/Jdnx8jdg\r\nhxxps[://]pastebin[.]com/u/wshsoft\r\npluginserver[.]duckdns[.]org\r\nhxxp[://]str-master[.]pw/strigoi/server/ping[.]php?lid=\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 110 of 124\n\nmoregrace[.]duckdns[.]org\r\nhxxp[://]jbfrost[.]live/strigoi/server/?hwid=1\u0026lid=m\u0026ht=5\r\npalaintermine[.]duckdns[.]org\r\nip-api[.]com/json/\r\nhxxp[://]wshsoft[.]company/multrdp[.]jpg\r\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.\r\nHost IOCs:\r\nHKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ntfsmgr\r\n64578lock.file\r\n3219lock.file\r\nScheduled Task - \"Skype\"\r\nHKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v dontdisplaylastusername = 1\r\nSTRRAT/Dropper Specific IOCs:\r\ncarLambo\r\nHBrowserNativeApis\r\nconfig.txt\r\nloorqhustq\r\nUsing the above we can create a fairly flexible Yara rule to detect this malware.\r\n/*\r\n Author: @CyberRaiju\r\n Date: 2022-05-19\r\n Identifier: STRRAT-Identification\r\n Reference: https://www.jaiminton.com/reverse-engineering/strrat\r\n*/\r\nrule STRRAT_14 {\r\n meta:\r\n description = \"Detects components or the presence of STRRat used in eCrime operations\"\r\n license = \"Detection Rule License 1.1 https://github.com/Neo23x0/signature-base/blob/master/LICENSE\"\r\n author = \"@CyberRaiju\"\r\n reference = \"https://www.jaiminton.com/reverse-engineering/strrat\"\r\n date = \"2022-05-19\"\r\n hash1 = \"ec48d708eb393d94b995eb7d0194bded701c456c666c7bb967ced016d9f1eff5\"\r\n hash2 = \"0A6D2526077276F4D0141E9B4D94F373CC1AE9D6437A02887BE96A16E2D864CF\"\r\n strings:\r\n $ntwk1 = \"wshsoft.company\" fullword ascii\r\n $ntwk2 = \"str-master.pw\" fullword ascii\r\n $ntwk3 = \"jbfrost.live\" fullword ascii\r\n $ntwk4 = \"ip-api.com\" fullword ascii\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 111 of 124\n\n$ntwk5 = \"strigoi\" fullword ascii\r\n $host1 = \"ntfsmgr\" fullword ascii\r\n $host2 = \"Skype\" fullword ascii\r\n $host3 = \"lock.file\" fullword ascii\r\n $rat1 = \"HBrowserNativeApis\" fullword ascii\r\n $rat2 = \"carLambo\" fullword ascii\r\n $rat3 = \"config\" fullword ascii\r\n $rat4 = \"loorqhustq\" fullword ascii\r\n \r\n condition:\r\n filesize \u003c 2000KB and (2 of ($ntwk*) or all of ($host*) or 2 of ($rat*))\r\n}\r\nPerforming a hunt using Hybrid Analysis reveals a number of hits on this malware, making this a useful Yara rule\r\nfor finding samples. Of course this could be expanded out further, for example by adding checks for the\r\ndependencies STRRAT is known to use, but when creating these it’s always a balancing act of being broad enough\r\nto net new samples, but not get riddled with False Positives, but not too confined as to miss different variants.\r\nSnort Rule\r\nTo build out a Snort rule we’ll take a look at some of the network traffic described above, specifically zoning in on\r\nthe beacon STRRAT sends frequently, and look for any tcp traffic to or from a server that contains the content\r\n“ping”, a pipe, and then “STRRAT” (this is as simple as converting it to hexadecimal and looking for the content,\r\nand giving it a unique sid). This could be expanded further to detect commands being sent to/from the C2;\r\nhowever, this will be a task left for the reader.\r\nalert tcp any any -\u003e any any (msg:\"STRRAT C2 Beacon Detected\"; content:\"|70 69 6e 67 7c 53 54 52 52 41 54|\"; pr\r\nIn this example we’re going to use a pcap already captured previously from a system infected with a STRRAT\r\nvariant provided by Brad Duncan to test the rule.\r\nAfter setting up a few preprocessors for stream5_global, we’re good to test the rule over our pcap. By creating a\r\nsnort config with the below (stored in a file called strrat.rules).\r\npreprocessor stream5_global: track_tcp yes, \\\r\n track_udp yes, \\\r\n track_icmp no,\r\nalert tcp any any -\u003e any any (msg:\"STRRAT C2 Beacon Detected\"; content:\"|70 69 6e 67 7c 53 54 52 52 41 54|\"; pri\r\nWe can easily test this using snort on a linux VM. Specifying the pcap file and testing against our created rule..\r\nsudo snort -A fast --pcap-single=./pcap.pcap -c ./strrat.rules -l /var/log/snort\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 112 of 124\n\nWe can see this has 73 hits over the pcap, and has generated a number of alerts due to the consistent beaconing\r\nthis malware presents.\r\nSigma Rule\r\nBecause STRRAT leverages a lot of native Windows utilities to enable persistence and execute commands, we can\r\ndevelop a fairly basic Sigma rule to detect possible infections of STRRAT. This could be expanded further to pick\r\nup on individual registry key creations from a sysmon event, or look at the behaviour of file writes; however, this\r\nwill be a task left for the reader. This also hasn’t been confirmed for false positives which may need to be\r\nexcluded.\r\ntitle: STTRAT Child Process Spawning\r\nstatus: experimental\r\ndescription: Detects suspicious child processes of Java(w) possibly associated with a STRRAT infection.\r\nauthor: Jai Minton (@CyberRaiju)\r\nreferences: https://www.jaiminton.com/reverse-engineering/strrat\r\ndate: 2022/05/28\r\nmodified: 2022/05/28\r\ntags:\r\n - attack.initial_access\r\n - attack.persistence\r\nlogsource:\r\n category: process_creation\r\n product: windows\r\nlevel: high\r\ndetection:\r\n selection:\r\n - ParentImage|endswith:\r\n - '\\java.exe'\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 113 of 124\n\n- '\\javaw.exe'\r\n selection_2:\r\n - Image|endswith:\r\n - '\\hrdpinst.exe'\r\n - '\\cmd.exe'\r\n selection_cmd:\r\n CommandLine|contains:\r\n - 'schtasks /create /sc minute /mo 30 /tn Skype'\r\n - 'reg add'\r\n - 'shutdown /r /t 0'\r\n - 'shutdown /s /t 0'\r\n - 'wmic /node:. /namespace:'\r\n - 'hrdpinst.exe'\r\n condition: selection and selection_2 and selection_cmd\r\nfalsepositives:\r\n - Legitimate calls of various java applications to system binaries with specific command lines\r\nlevel: high\r\nUseful Windows Event Logs\r\nThe following event log identifiers will be useful to track this piece of malware:\r\nMicrosoft-Windows-TaskScheduler/Operational\r\n201 (Task registered)\r\n129 (Task Launched)\r\nSecurity\r\n4688 (Process Creation)\r\n4698 (Scheduled Task Creation)\r\n4700 (Scheduled Task Enabled)\r\nSysmon\r\n1 (Process Creation)\r\n11 (FileCreate)\r\n12 (Registry Create and Delete)\r\n13 (Registry Value Set)\r\n22 (DNS Query)\r\nThreat Intelligence - The Crimson Shadow\r\nNote: Threat intelligence is a broad term here which has been used to cover getting extended telemetry on the\r\nthreat this particular malware poses to organisations and people around the world, and potential victims.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 114 of 124\n\nDuring analysis I was presented with an interesting opportunity to track this malware on a global scale due to the\r\nway it functions. In late 2021, over the course of a month, infections of STRRAT around the world were tracked\r\nand plotted on a map based on the infected client’s IP address and Maxmind’s GeoLite2 Free Database. This\r\nclustered data is shown below.\r\nBy overlaying a heat map here we can see that although the numbers aren’t massive, the number of locations\r\nglobally which had seen this malware execute were quite diverse.\r\nFurther, each cluser point represents a single IP, and doesn’t take into consideration the number of hits from that\r\nparticular IP. To allow this to be easily navigated I overlayed IP address information along with ASN and count.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 115 of 124\n\nThe method to turn the gathered data into such a map was to take a carefully crafted spreadsheet containing the\r\ndata and plot it with Python3, pandas, and folium. The script created is show below (special thanks to umar-yusuf’s blog which helped get me started on this venture).\r\nimport pandas as pd\r\nfrom IPython.display import display\r\nimport folium\r\nfrom folium import plugins\r\nfrom folium.plugins import HeatMap\r\nimport branca.colormap\r\nfrom collections import defaultdict\r\nimport sys\r\nimport time\r\nsteps=5\r\ncolormap = branca.colormap.linear.YlOrRd_09.scale(0, 2).to_step(steps)\r\ngradient_map=defaultdict(dict)\r\n \r\nfor i in range(steps):\r\ngradient_map[1/steps*i] = colormap.rgb_hex_str(1/steps*i)\r\nlon, lat = 10.626065, 43.035950\r\nfor ii in range(1,33):\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 116 of 124\n\nm = folium.Map([lat, lon],tiles='cartodbdark_matter', zoom_start=2)\r\n sheet='Day'+str(ii);\r\n heatmap_df = pd.read_excel(open('MapDataDaily.xls','rb'),sheet_name=sheet)\r\n count=sheet+\" (\"+str(len(heatmap_df))+\")\"\r\n title_html = '''\r\n \u003ch3 align=\"center\" style=\"font-size:16px\"\u003e\u003cb\u003e{}\u003c/b\u003e\u003c/h3\u003e\r\n '''.format(count)\r\n# heatmap_df.head()\r\n for i in range(0,len(heatmap_df)):\r\n folium.CircleMarker(\r\n location=[heatmap_df.iloc[i][\"Latitude\"],heatmap_df.iloc[i][\"Longitude\"]],\r\n radius=heatmap_df.iloc[i][\"Value\"]*0.001,\r\n line_color='#fc0000',fill_color='#fc0000',color='#fc0000').add_to(m)\r\n m.get_root().html.add_child(folium.Element(title_html))\r\n m.save(sheet+\".html\")\r\nAfter running over the data I had an interactive HTML page for each and every day of data collection and quantity\r\nof infected, unique IPs on any given day. This was then turned into the below gif. Note: Day 5’s data got lost\r\nduring collection (call it user error).\r\nIn addition the most common hour period that hosts were seen to be infected (UTC) was also plotted over time.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 117 of 124\n\nStatistics\r\nFrom the data gathered during this one month period, the following became apparent:\r\nApproximately 5726 Unique IP addresses were seen to have been infected during this time.\r\n6 out of 7 continents had seen to have been infected during this time (Antarctica was the odd one out).\r\nAfrica: 589 IPs\r\nAsia: 2446 IPs\r\nEurope: 1454 IPs\r\nNorth America: 892 IPs\r\nOceania: 125 IPs\r\nSouth America: 220 IPs\r\nSystems in approximately 101 countries had seen to have been infected during this time.\r\nSystems in approximately 1005 cities had seen to have been infected during this time.\r\nApproximately 100 different license keys appeared to be in use by STRRAT globally during this time.\r\nLimitations and acknowledgements:\r\nGiven telemetry was captured from a network level, there could have been multiple systems resolving to\r\nthe same IP due to NAT which remains an unknown in the above figures.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 118 of 124\n\nSome of the above figures were likely sandboxes or testing devices and didn’t indicate a compromised\r\norganisation, a large subset was still found to have frequent enough telemetry and during likely business\r\nhours to assume a compromised system.\r\nWhere a system was likely to be infected as identified above, this was mostly attempted to be reported to\r\nthe relevant country Cyber Security / CERT Authority. Only a number of those contacted replied, and of\r\nthese fewer confirmed an investigation of a machine occurring (some is better than none right?).\r\nOSINT\r\nBy leveraging information known about this malware and the assumption it is likely being sold online or shared\r\namongst groups, I was able to use OSINT to find the website being used to sell this piece of malware. From this\r\nwe have a redacted screenshot which has the seller trying to give off the impression that this is “legitimate\r\nsoftware” which you need to pay for on a monthly or 3 monthly basis. Despite this it says it is for “educational use\r\nonly” which is a common theme amongst those developing tools they almost certainly know will be used for\r\nmalicious purposes, it has fake location information, and it’s marketed with skulls and the grim reaper, and it\r\naccepts payments in only Perfect Money or Bitcoin.\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 119 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 120 of 124\n\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 121 of 124\n\nAn interesting component of the above is that the author is selling this capability on a monthly ($80) or 3 monthly\r\n($200) basis, in addition it is touting the exact features of the malware which we’ve uncovered above and shown\r\nexactly how they work.\r\nPart 5: Miscellaneous Trivia\r\nStriogoi References\r\nThroughout this analysis we see numerous references to ‘Strigoi’. From a search of Wikipedia and Strigoi fandom\r\nwiki pages, it was found that ‘Strigoi’ is a term from Romanian mythology which is used to refer to an evil, or\r\ntroubled spirit, which can possess (or transform) into an animal. This has become synonymous with vampirism\r\nwhere a bat is said to have been posessed by a Strigoi, or are instead a Strigoi taking the form of a bat.\r\nConcept art for this creature which I find appropriate is below, created by DavyWagnarok.\r\nStrigoi artwork by DavyWagnarok:\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 122 of 124\n\nBased on this we may infer that the creators are of Romanian descent or are targeting Romanian customers/users;\r\nhowever, this would be too easy and it could very much be that this is used as a method of misdirection.\r\nNonetheless it does lead us to believe that the malware author felt ‘Strigoi’ to be a ‘cool’ enough term to be used\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 123 of 124\n\nfor the name of this malware, whether or not they’re happy with a shortened ‘STRRAT’ being used globally based\r\non the strings found in this malware is unknown.\r\nSource: https://www.jaiminton.com/reverse-engineering/strrat\r\nhttps://www.jaiminton.com/reverse-engineering/strrat\r\nPage 124 of 124\n\nAt this point we can begin to https://www.jaiminton.com/reverse-engineering/strrat see the different commands taken by this malware as they’re received into the array\n‘stringArray2’ from the designated C2, which is also placed into stringArray3.\n   Page 39 of 124\n\nSome important request and sending parts of this method back a 200 occurs at Connection Established lines 104-114 message. which is involved This is in receiving only possible a CONNECT due to an instance network of\nncnndfg (ncnndfg2) being defined as object3 at line 76. \n   Page 79 of 124",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.jaiminton.com/reverse-engineering/strrat"
	],
	"report_names": [
		"strrat"
	],
	"threat_actors": [
		{
			"id": "6f30fd35-b1c9-43c4-9137-2f61cd5f031e",
			"created_at": "2025-08-07T02:03:25.082908Z",
			"updated_at": "2026-04-10T02:00:03.744649Z",
			"deleted_at": null,
			"main_name": "NICKEL FOXCROFT",
			"aliases": [
				"APT37 ",
				"ATK4 ",
				"Group 123 ",
				"InkySquid ",
				"Moldy Pisces ",
				"Operation Daybreak ",
				"Operaton Erebus ",
				"RICOCHET CHOLLIMA ",
				"Reaper ",
				"ScarCruft ",
				"TA-RedAnt ",
				"Venus 121 "
			],
			"source_name": "Secureworks:NICKEL FOXCROFT",
			"tools": [
				"Bluelight",
				"Chinotto",
				"GOLDBACKDOOR",
				"KevDroid",
				"KoSpy",
				"PoorWeb",
				"ROKRAT",
				"final1stpy"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "aa73cd6a-868c-4ae4-a5b2-7cb2c5ad1e9d",
			"created_at": "2022-10-25T16:07:24.139848Z",
			"updated_at": "2026-04-10T02:00:04.878798Z",
			"deleted_at": null,
			"main_name": "Safe",
			"aliases": [],
			"source_name": "ETDA:Safe",
			"tools": [
				"DebugView",
				"LZ77",
				"OpenDoc",
				"SafeDisk",
				"TypeConfig",
				"UPXShell",
				"UsbDoc",
				"UsbExe"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"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": "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": "9b02c527-5077-489e-9a80-5d88947fddab",
			"created_at": "2022-10-25T16:07:24.103499Z",
			"updated_at": "2026-04-10T02:00:04.867181Z",
			"deleted_at": null,
			"main_name": "Reaper",
			"aliases": [
				"APT 37",
				"ATK 4",
				"Cerium",
				"Crooked Pisces",
				"G0067",
				"Geumseong121",
				"Group 123",
				"ITG10",
				"InkySquid",
				"Moldy Pisces",
				"Opal Sleet",
				"Operation Are You Happy?",
				"Operation Battle Cruiser",
				"Operation Black Banner",
				"Operation Daybreak",
				"Operation Dragon messenger",
				"Operation Erebus",
				"Operation Evil New Year",
				"Operation Evil New Year 2018",
				"Operation Fractured Block",
				"Operation Fractured Statue",
				"Operation FreeMilk",
				"Operation Golden Bird",
				"Operation Golden Time",
				"Operation High Expert",
				"Operation Holiday Wiper",
				"Operation Korean Sword",
				"Operation North Korean Human Right",
				"Operation Onezero",
				"Operation Rocket Man",
				"Operation SHROUDED#SLEEP",
				"Operation STARK#MULE",
				"Operation STIFF#BIZON",
				"Operation Spy Cloud",
				"Operation Star Cruiser",
				"Operation ToyBox Story",
				"Osmium",
				"Red Eyes",
				"Ricochet Chollima",
				"Ruby Sleet",
				"ScarCruft",
				"TA-RedAnt",
				"TEMP.Reaper",
				"Venus 121"
			],
			"source_name": "ETDA:Reaper",
			"tools": [
				"Agentemis",
				"BLUELIGHT",
				"Backdoor.APT.POORAIM",
				"CARROTBALL",
				"CARROTBAT",
				"CORALDECK",
				"Cobalt Strike",
				"CobaltStrike",
				"DOGCALL",
				"Erebus",
				"Exploit.APT.RICECURRY",
				"Final1stSpy",
				"Freenki Loader",
				"GELCAPSULE",
				"GOLDBACKDOOR",
				"GreezeBackdoor",
				"HAPPYWORK",
				"JinhoSpy",
				"KARAE",
				"KevDroid",
				"Konni",
				"MILKDROP",
				"N1stAgent",
				"NavRAT",
				"Nokki",
				"Oceansalt",
				"POORAIM",
				"PoohMilk",
				"PoohMilk Loader",
				"RICECURRY",
				"RUHAPPY",
				"RokRAT",
				"SHUTTERSPEED",
				"SLOWDRIFT",
				"SOUNDWAVE",
				"SYSCON",
				"Sanny",
				"ScarCruft",
				"StarCruft",
				"Syscon",
				"VeilShell",
				"WINERACK",
				"ZUMKONG",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434321,
	"ts_updated_at": 1775826734,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/523807f90c606369f88d1e83987fda6f87a323ca.pdf",
		"text": "https://archive.orkl.eu/523807f90c606369f88d1e83987fda6f87a323ca.txt",
		"img": "https://archive.orkl.eu/523807f90c606369f88d1e83987fda6f87a323ca.jpg"
	}
}