{
	"id": "c0a4e7c6-bb21-49f5-87cb-dfc80ba119a3",
	"created_at": "2026-04-06T00:19:07.060077Z",
	"updated_at": "2026-04-10T03:20:32.700016Z",
	"deleted_at": null,
	"sha1_hash": "10af21de012c6433f81895e45c9f26d2b3524bbe",
	"title": "Analyzing Lu0Bot: A Node.js Malware with Vast Capabilities",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 4040133,
	"plain_text": "Analyzing Lu0Bot: A Node.js Malware with Vast Capabilities\r\nBy Jane\r\nArchived: 2026-04-02 12:11:25 UTC\r\nIn this article, we’ll examine a Lu0Bot malware sample we stumbled upon while tracking malicious activity in ANY.RUN’s\r\npublic tasks. \r\nWhat caught our interest is that the sample is written in Node.js. While initially, it appeared to be a regular bot for DDOS\r\nattacks, things turned out to be a lot more complex. \r\nNode.js malware is intriguing because it targets a runtime environment commonly used in modern web applications.\r\nThe runtime’s platform-agnostic nature depends on the specific code and libraries used, but it often allows for greater\r\nversatility. Typically, this kind of malware employs multi-layer obfuscation techniques using JavaScript. It combines\r\ntraditional malware characteristics with web technologies, making it a unique challenge for detection and analysis. \r\nDue to the extensive scope of the article, we’ve decided to split it into two parts: \r\nPart 1: core analysis: In the first part, we’ll explore the malware’s architecture and what’s stored inside of it. \r\nPart 2: traffic analysis: In the second part, we’ll dive into a real-world instance where the sample communicates\r\nwith a C2 server. \r\nWhat is Lu0Bot Malware?\r\nBefore diving into the analysis, let’s do a quick overview of Lu0Bot and talk about what makes it particularly interesting. \r\nLu0bot initially appeared in February 2021 as a second-stage payload in GCleaner attacks. Now, it serves as a bot, waiting\r\nfor commands from a C2 server and sending encrypted basic system information back to that server.  \r\nIt is worth noting that the bot’s activity level remains relatively low, averaging 5-8 new samples on Bazaar each month. As\r\nof this writing, only one new sample was uploaded in August. However, it is possible that the real popularity of this malware\r\nis higher than the activity level shows, with many samples lying dormant and awaiting C2 commands — though, this is just\r\na speculation on our part. \r\nRegardless, even with this limited activity, Lu0bot is interesting as it demonstrates a creative approach to malware\r\ndesign — written in Node.js its capabilities are restricted only by what’s possible in this programming language. \r\nWhile we couldn’t locate a live sample receiving commands — likely due to the bot’s inability to find an IP address — a\r\npublic sample did successfully connect. In this instance, the server responded with JavaScript code, initiated a new domain,\r\nand proceeded with encrypted code exchange. The decryption process is hard-coded within the bot — but we’ll dive deeper\r\ninto the decryption algorithm in part 2 of our analysis.\r\nStatic analysis of the source file \r\nLet’s begin our breakdown of Lu0Bot by analyzing it statically. \r\nLink to the task: https://app.any.run/tasks/4696b947-92f0-4413-95dc-644c45ca99a6\r\nSHA256 FB808BE98B583A2004B0AF7B6F4BF5E3419D8B6A385C5CE4E8FAB4DDC0B48428\r\nThe first thing we noticed is that the file uses an SFX packer (see Fig 1) — this is a self-extracting archive that can be\r\nopened with any archive utility.  \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 1 of 16\n\nSFX-packer\r\nInside the archive, there was a BAT file and several other contents (see the screenshot below). Let’s break down what they\r\ndo one by one: \r\nArchive contents\r\n1. BAT-file  \r\nThe content of the BAT file \r\nThe first line contains a comment, but its meaning remains unclear—it wasn’t referenced later in our analysis. \r\nNext, multiple files are bundled into an EXE file, specifically a Node interpreter named fjlpexyjauf.exe.\r\nOn the third line, this interpreter receives a file containing bytes and a number (in place-holder terms, %1%, as seen in the\r\nscreenshot above), but the real number in our case is 3991425476. This number probably acts as an encryption key for the\r\nbyte file. \r\n2. Files eqnyiodbs.dat \r\nThis one file is split into different byte blocks. These blocks are later combined to form the Node interpreter.\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 2 of 16\n\nContents of eqnyiodbs files \r\n3. lknidtnqmg.dat file \r\nThis file contains bytes encrypted in Base64. It is likely decrypted using the number provided as input. \r\nContents of the lknidtnqmg.dat file\r\n4. gyvdcniwvlu.dat file \r\nThis is a driver designed to let 32-bit programs on x64 systems convert key scan codes into Unicode characters. The main\r\nprocess relies on it, most likely to enable keylogging functionality. \r\nDynamic malware analysis of Lu0Bot in ANY.RUN \r\nStatic analysis points to the EXE file and lknidtnqmg.dat as noteworthy. The next step is to examine dynamic behavior and\r\nattempt to either decrypt the bytes or find them decrypted in the process memory.\r\nWe’ll use ANY.RUN interactive malware sandbox to perform the dynamic analysis. \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 3 of 16\n\nProcess Tree \r\nProcesses and activity \r\nThe screenshot of the process tree above displays the process tree during sample execution. The main process initiates a\r\nfamiliar BAT file, which in turn launches the EXE file. Post-analysis verifies that this is a Node.js interpreter, accepting\r\nencrypted JS code as input. \r\nAlongside attempting connections, the JS code fetches system data using WMIC. It specifically gathers information about\r\nprocesses and the execution location, aligning with Tactic T1047. \r\nWMIC\r\nDynamic analysis revealed that the interpreter gets copied to the startup folder. After a system restart, the connection to the\r\ndomain continues (this is seen in the screenshot of the process tree above) — reference the process number 5252 (Tactic\r\nT1053.005). This ensures the bot remains operational post-restart.  \r\nStartup directory\r\nNetwork and traffic\r\nA unique characteristic of this malware is its approach to domain connection. The domain is constructed from various parts,\r\nassembled into a single entity within the JS code:\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 4 of 16\n\n59c58bb 3 170 1693221099 118 0308a04a642894b53635018356690221232f .hsh.juz09.cfd\r\nDNS-requests\r\nAbove is a small preview into Lu0Bot’s traffic — we will break it down in more detail in Part 2 of our analysis.\r\nTechnical analysis of Lu0Bot malware using a disassembler and debugger \r\nIn our case, the dump — or script — is both packed and encrypted. To access the main JS code, we’ll need to: \r\nUnpack the SFX archive \r\nRun a command to collect the Node.js file \r\nLaunch fjlpexyjauf.exe in x32dbg?, entering the incoming data into the command line \r\nGet to the point where JS code execution starts \r\nLocate the code in memory and save a dump \r\nSteps for unpacking and byte collection \r\nTo unpack the archive, we can use any standard archiver tool. For byte collection, we will focus on the second line of the\r\nBAT script — let’s execute it. \r\nByte collection\r\nExtracting the dump \r\nLet’s run the file in the debugger and write the input data to the command line.\r\nCommand Line \r\nWe’re looking for the spot where JS code execution kicks off, marked by the call to the uv_run function. After this call, the\r\nprogram starts domain connection attempts and hangs indefinitely. Let’s navigate to this function and search for the code. To\r\nmake it easier, we can use syntax cues and variable attributes — like the word ini(), which is unique to JS syntax. \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 5 of 16\n\nuv_run function\r\nJS code\r\nOnce we spot the decrypted code, let’s head to Memory Map and save that section. This is what our dump should look like: \r\nDump\r\nAnalyzing the JS code\r\nThe JavaScript code we are presented with is heavily obfuscated and unreadable:\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 6 of 16\n\nThis code is unreadable, but we can fix it \r\nWe can transform the code into a readable form by removing extra bytes and using a JavaScript deobfuscator (Here’s a link\r\nto a handy script you can use). After the transformation, this is what the result should look like: \r\nResult of code transformation\r\nNote the following: \r\n1. The code starts with an array containing encrypted strings. \r\n2. Right after, the array undergoes manipulation, moving specific elements to the end. \r\n3. Next, there’s a function dedicated to decrypting the array strings. It first uses an alternative form of BASE64\r\n(T1132.002), followed by URL encode-decode, and then applies RC4. \r\nThis function is called with two variables: the first is an element from the array, and the second is the RC4 key. \r\nTo simplify the task of parsing this code, we wrote a small script that decrypts these lines automatically. You can download\r\nit from our GitHub.  \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 7 of 16\n\nRunning the script gives us the following before-and-after:\r\nBefore code deobfuscation\r\nAfter code deobfuscation\r\nThe decrypted lines reveal that portions of the domains are hard-coded into the sample (see Fig. 16). Following that, you’ll\r\nfind the section of the code responsible for assembling the domain:\r\nDomain construction \r\nDebugging the JavaScript code\r\nFor debugging, we’ll use Node.js along with its inspect-brk parameter (node.exe –inspect-brk *obfuscate dump without\r\ngarbage bytes*). Let’s place a breakpoint on the “var” keyword and observe the output generated by each line: \r\nThe first function, ginf, handles information gathering. It outputs an array with 15 elements, all of which are details\r\nabout the system. \r\nginf function \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 8 of 16\n\nAn array containing the output of the ginf function \r\nThe hwco function takes the 15-element array from the ginf function as input. The output is the tail-end portion of\r\nthe domain, up to the dot. Analysis shows that this output is actually a hash of the collected system data. \r\nhwco function \r\nString output from the hwco function \r\nNext, elements like the port, number, and the domain segment following the dot are extracted from the acc array and\r\nassigned to variables. \r\nExtracting elements from the acc array\r\nThe variable acc is added with 3, rns, and bt. Rns is generated randomly, and bt represents the current time. \r\nPart of domain: addition acc, 3, rns, bt\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 9 of 16\n\nMore about rns and bt \r\nAfter that, a variable containing a random number is appended to the domain segment before the dot. The next line\r\nhandles domain selection after the dot: if certain conditions are met, an alternative domain is chosen, if available. \r\nChoise domain after the point \r\nThe full domain gets assembled and all required elements are packed into a JSON object: \r\n{“gttk”,”59c58bb5327116933080087040012a04a641e14b536350088dba00221232f.hsh.juz09.cfd”,18223,”59c58bb5″,”331c90″,16933080087\r\n[“win32″,”ia32″,32,”10.0.19044″,6386.265,3220688896,1396203520,4,”Intel(R) Core(TM) i5-6400 CPU @\r\n2.70GHz”,3094,”PC”,”admin”,”C:\\\\Users\\\\admin\\\\Desktop\\\\node-v20.5.0-win-x86″,”C:\\\\Users\\\\admin\\\\AppData\\\\Local\\\\Temp”,”20.5.0″],”0012a04a641e14b536350088dba00221232f”} \r\nLet’s summarize, then — what does our domain consist of?\r\nBeginning\r\nA\r\nnumber\r\nRandom\r\nnum\r\nTime Hashes\r\nDomain\r\nending\r\n59c58bb5 3 271 1693308008704 0012a04a641e14b536350088dba00221232f hsh.juz09.cfd\r\nThe final function on the screen employs aes-128-cbc encryption. The output is a 435-element array, consisting of 1 byte,\r\nfollowed by a 16-byte IV, then 2 bytes, and finally the encrypted data (Tactic T1573). \r\nEncrypted JSON object \r\nWe also discovered a key: becfe83392d83ef8c743ea00711a25c8, which aligned with all live tasks identified by our team. \r\nPost-execution, the malware continuously attempts to locate an address for data transmission. When traffic successfully\r\nreaches the server, data exchange occurs, involving the C2 server sending JS code. More on this in Part 2 of our analysis. \r\nHow to Identify Lu0Bot\r\nSIGMA RULE: \r\ntitle: Lu0Bot detect\r\n status: experimental\r\n description: Detects Lu0Bot activity\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 10 of 16\n\nauthor: ANY.RUN\r\n date: 2023/09/26\r\n tags:\r\n - Lu0Bot\r\n detection:\r\n parent_process:\r\n ParentImage|endswith: '\\cmd.exe'\r\n CommandLine|re: '\\/d \\/c [A-z0-9]+\\.bat \\d+$'\r\n child_process:\r\n OriginalFileName: 'node.exe'\r\n CommandLine|re: '\\.dat \\d+$'\r\n condition: parent_process and child_process\r\nYARA RULE: \r\nrule Lu0Bot_detection {\r\n meta:\r\n \r\n description = \"Detection of Lu0Bot\"\r\n date = \"2023-09-26\"\r\n family = \"Lu0Bot\"\r\n \r\nstrings:\r\n \r\n $start_code = /var \\_0x[a-f0-9]{4,6}/\r\n $altBase64 = \"'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='\" ascii\r\n $domain = \"var acc=\" ascii\r\n $end_code = \"}ini();\" ascii\r\n $func = “ginf” ascii\r\n \r\n condition:\r\n \r\n all of them and #start_code \u003e= 50\r\n}\r\nWriting Suricata rules for Lu0Bot\r\nFor effective Suricata network rules, content is key. DNS queries are a big part of all network protocol requests. Lu0bot, as\r\nmentioned earlier, doesn’t offer much stable content in its DNS queries—mostly random bytes or hashes. But there’s a small\r\npart of the domain name that includes a Unix-format timestamp. We’ll use that for network detection. \r\nTo capture three bytes of this timestamp in the rule, we limited the rule’s active timeframe. We pinpointed five periods tied\r\nto the initial bytes 169, 170, 171, 172, and 173 in the timestamp. This gave us five rules targeting the malware’s activity\r\nwithin specific windows.\r\nGMT activity end date Timestamp Rule Message\r\nNov 14 2023 22:13:20 \u003c1700000000\r\nBOTNET [ANY.RUN] Lu0bot\r\nDNS Query M1\r\nMar 09 2024 15:59:59 \u003c1709999999\r\nBOTNET [ANY.RUN] Lu0bot\r\nDNS Query M2\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 11 of 16\n\nGMT activity end date Timestamp Rule Message\r\nJul 03 2024 09:46:39 \u003c1719999999\r\nBOTNET [ANY.RUN] Lu0bot\r\nDNS Query M3\r\nOct 27 2024 03:33:19 \u003c1729999999\r\nBOTNET [ANY.RUN] Lu0bot\r\nDNS Query M4\r\nFeb 19 2025 21:19:59 \u003c1739999999\r\nBOTNET [ANY.RUN] Lu0bot\r\nDNS Query M5\r\nIn real-world scenarios, some Lu0bot DNS requests lack hashes altogether, ending just at the timestamp. Because of this, the\r\nregular expression should account for both hashed and non-hashed query versions. \r\nThe regular expression below is part of the BOTNET [ANY.RUN] Lu0bot DNS Query M1 network rule. It reflects the\r\nvariables obtained from our analysis and is tailored for timestamps starting with the number 169. Note that this rule will\r\nexpire in November 2023, when the timestamp transitions to starting with 170.\r\nA regular expression targetting the DNS request. \r\nSchematic representation of the regular expression. \r\nNetwork rule text Description\r\nalert dns any any -\u003e any any\r\n(msg: \"BOTNET [ANY.RUN] Lu0bot\r\nDNS Query M1\";\r\nflow: to_server;\r\nIndicates the protocol, the direction of data transfer and the message if the\r\nrule is triggered.\r\ndns.query; Targets an inspected buffer containing a DNS query\r\ncontent: \"169\"; offset:12; depth:3; Content check for the M1 rule range\r\npcre:\"/^(?:[a-f0-9]\r\n{8}\\d\\d{3}169\\d{10})(?:[0-9a-z]\r\n{36})?\\./\";\r\nRegular expression describing the structure of a DNS request\r\nthreshold:\r\nclasstype: trojan-activity;\r\nreference:\r\nmetadata: malware_family Lu0bot\r\nsid: 8000603; rev: 2;\r\nThe rule's service fields provide essential information: they describe the\r\nmalware family, set the trigger threshold, and offer a list of links for further\r\nreading on this threat.\r\nDetecting Lu0bot in ANY RUN \r\nWe’ve already implemented Lu0bot detection in ANY.RUN — our service can automatically decrypt strings and C2\r\ndomains are now visible in our service. \r\nThese tasks show Lu0bot detection in ANY.RUN: \r\nhttps://app.any.run/tasks/4696b947-92f0-4413-95dc-644c45ca99a6 \r\nhttps://app.any.run/tasks/c068028b-ce61-46a7-b12d-aef39a033bdd \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 12 of 16\n\nhttps://app.any.run/tasks/4888f835-d2c3-4d89-9dc8-ac6cecf96409 \r\nWrapping up\r\nIn this article, we delved into Lu0bot, a malware incorporating NODE JS and executable JS code. Based on our analysis, we\r\narrive at these key conclusions: \r\n1. All data is obfuscated. The code primarily focuses on gathering basic info and awaiting C2 commands. \r\n2. The malware’s functionality is constrained only by what its JS code can do. \r\n3. The domain structure of the malware is unique. \r\n4. Custom encryption methods are used for strings. \r\nGiven these factors, Lu0bot could pose significant risk if its campaign scales and the server start actively responding. Its\r\nunique implementation using NODE JS makes it a highly interesting subject for analysis. \r\nShould the server become operational, the malware could potentially have capabilities like: \r\nRecording keystrokes \r\nIdentity theft \r\nNear-total control of the victim’s computer \r\nFunctioning as a DDOS bot \r\nConducting illegal activities using the compromised system \r\nIf you found this article informative, make sure to also read our technical breakdown of XWorm, as well as an in-depth\r\nanalysis of a new LaplasClipper sample. And, of course, we will break down the traffic structure of Lu0bot in much greater\r\ndetail in an upcoming Part 2 of this analysis — stay tuned. \r\nAppendix 1\r\nMITRE\r\nTactics Techniques Description\r\nTA0011: Command and\r\nControl \r\nT1071.001: Application Layer\r\n Protocol \r\nSending collected data  to the control server \r\nT1132.002 - Data Encoding: Standard\r\nEncoding \r\nencode data with alternative BASE64 \r\nT1573 - Encrypted Channel \r\nUse Symmetric and Asymmetric\r\nCryptography in traffic \r\nTA0005: Defense Evasion \r\nT1027 - Obfuscated Files or\r\nInformation \r\nattempt to make an executable or file difficult\r\nto discover or analyze \r\nTA0002: Execution \r\nT1053.005 - Scheduled Task/Job:\r\nScheduled Task \r\nabuse the Windows Task Scheduler to create\r\nfile in statup \r\nT1047 - Windows Management\r\nInstrumentation \r\nuse wmic to gather information from a\r\nsystem \r\nAppendix 2: IOCs\r\nTitle  Description \r\nName  Fb808be98b583a2004b0af7b6f4bf5e3419d8b6a385c5ce4e8fab4ddc0b48428.exe \r\nMD5  6181206d06ce28c1bcdb887e547193fe \r\nSHA1  8eb65b4895a90d343f23f9228e0d53af62de3dab \r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 13 of 16\n\nTitle  Description \r\nSHA256  fb808be98b583a2004b0af7b6f4bf5e3419d8b6a385c5ce4e8fab4ddc0b48428 \r\nDropped executable file\r\nName  SHA256 \r\nC:\\Users\\admin\\AppData\\Local\\Temp\\IXP000.TMP\\fjlpexyjauf.exe  9c5898b1b354b139794f10594e84e94e991971a54d179b2e9f74631\r\nC:\\Users\\admin\\AppData\\Local\\Temp\\IXP000.TMP\\gyvdcniwvlu.dat  7c37b8dd32365d41856692584f4c8e943610cda04c16fe06b47ed2d\r\nDNS requests \r\n59c58bb5317016932210991180008a04a642894b53635018356690221232f.hsh.juz09.cfd \r\n59c58bb5317016932210991180108a04a642894b53635018356690221232f.hsh.juz09.cfd \r\n59c58bb5317016932210991180208a04a642894b53635018356690221232f.hsh.juz09.cfd \r\n59c58bb5317016932210991180209a04a642894b53635018356690221232f.hsh.juz09.cfd \r\nMore submissions: \r\nhttps://app.any.run/tasks/4888f835-d2c3-4d89-9dc8-ac6cecf96409/\r\nhttps://app.any.run/tasks/c068028b-ce61-46a7-b12d-aef39a033bdd/\r\nhttps://app.any.run/tasks/e13d4388-8f32-4182-aff2-a85c89aeaa35\r\nkhr0x\r\nI'm 21 years old and I work as a malware analyst for more than a year. I like finding out what kind of malware got on my\r\ncomputer. In my spare time I do sports and play video games.\r\nJane\r\nI'm ANY.RUN ambassador and a real network traffic numismatist. I also love penguins and tortoises. My motto is to do\r\ngood and throw it into the sea.\r\nI'm 21 years old and I work as a malware analyst for more than a year. I like finding out what kind of malware got on my\r\ncomputer. In my spare time I do sports and play video games.\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 14 of 16\n\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 15 of 16\n\nJane\r\nLeading network traffic analysis expert at ANY.RUN\r\nI'm ANY.RUN ambassador and a real network traffic numismatist. I also love penguins and tortoises. My motto is to do\r\ngood and throw it into the sea.\r\nSource: https://any.run/cybersecurity-blog/lu0bot-analysis/\r\nhttps://any.run/cybersecurity-blog/lu0bot-analysis/\r\nPage 16 of 16",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://any.run/cybersecurity-blog/lu0bot-analysis/"
	],
	"report_names": [
		"lu0bot-analysis"
	],
	"threat_actors": [],
	"ts_created_at": 1775434747,
	"ts_updated_at": 1775791232,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/10af21de012c6433f81895e45c9f26d2b3524bbe.pdf",
		"text": "https://archive.orkl.eu/10af21de012c6433f81895e45c9f26d2b3524bbe.txt",
		"img": "https://archive.orkl.eu/10af21de012c6433f81895e45c9f26d2b3524bbe.jpg"
	}
}