Bored BeaverTail & InvisibleFerret Yacht Club – A Lazarus Lure Pt.2 By eSentire Threat Response Unit (TRU) Archived: 2026-04-05 18:38:33 UTC Adversaries don’t work 9-5 and neither do we. At eSentire, our 24/7 SOCs are staffed with Elite Threat Hunters and Cyber Analysts who hunt, investigate, contain and respond to threats within minutes. We have discovered some of the most dangerous threats and nation state attacks in our space – including the Kaseya MSP breach and the more_eggs malware. Our Security Operations Centers are supported with Threat Intelligence, Tactical Threat Response and Advanced Threat Analytics driven by our Threat Response Unit – the TRU team. In TRU Positives, eSentire’s Threat Response Unit (TRU) provides a summary of a recent threat investigation. We outline how we responded to the confirmed threat and what recommendations we have going forward. Here’s the latest from our TRU Team… What did we find? In October 2024, the eSentire Threat Response Unit (TRU) responded to an incident where a software developer downloaded a JavaScript project that contained BeaverTail malware. Upon installing the project through the Node Package Manager (NPM) command, it executed malicious JavaScript files and subsequently deployed the InvisibleFerret malware to the host. The InvisibleFerret malware was executed through a Python command, which fingerprinted the host's information and stole the browser's credentials. In response, our team of 24/7 SOC Cyber Analysts responded by isolating the impacted host and alerting the customer with the relevant details. Upon further investigation by eSentire’s TRU team, it was determined that the observed Tactics, Techniques, and Procedures (TTPs) were consistent with those reported to be used by North Korea threat actors, also tracked as Contagious Interview. Initial Access A ZIP file named 'task-space-eshop-aeea6cc51a7c.zip' was found in the user's download directory. eSentire Threat Intelligence team assesses the chances as probable that the victim downloaded the zip from a BitBucket project named “eshop” (Figure 1). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 1 of 20 Figure 1 eshop project hosted on Bitbucket. The malicious “eshop” repository was committed by the user “francesco zaid” (Figure 2). Figure 2 Author “francesco zaid” (screenshot taken October 24th, 2024). The commits to eshop occurred roughly five days after a job posting for a freelancer was published on a freelance job board. The job was posted by a user named “francesco zaid” on the “www.freelancermap[.]com” (Figure 3). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 2 of 20 Figure 3 Possible Fake Job posting associated with the Contagious Interview Campaign. It should be noted that the eSentire Threat Intelligence team reviewed the job posting and was unable to find a direct link to the eshop repository from the posting; however, given the contact person’s name being the same name used to upload content to the repository, it is a notable finding and is consistent with the Contagious Interview campaign Tactics, Techniques and Procedures (TTPs) of luring software developers with fraudulent jobs. The victim in the incident eSentire responded to appears to be a software developer, which aligns with the TTPs of previously reported on campaigns by North Korean threat actors where software developers were targeted. Execution Chain The ZIP file downloaded by the victim contained a malicious NPM package that once installed by the victim, executed “server.js” file that is defined in the “package.json” and subsequently, loads a malicious JavaScript file (error.js) (Figure 4). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 3 of 20 Figure 4 “server.js” file was defined to be executed in the “package.json” file The “server.js” file is used as an entry point to load the file located in “backend/middlewares/helpers/error.js”, which facilitates further malicious activities on the victim machine such as: steal saved login credentials in the browsers; collect system information; enumerates crypto wallet extensions in the targeted browsers; and, steal configuration data from crypto wallets like Exodus and Solana. This JavaScript file (error.js) is highly obfuscated and after analysis it was determined to be a component for the Beavertail malware (Figure 5). Figure 5 Screenshot of ‘error.js’ found on the BitBucket Repository that is a component of BeaverTail. After the JavaScript file is loaded, it uses a cURL command to download InvisibleFerret malware components from a command and control (C2) server; in this case the C2 was located at 185[.]235[.]241[.]208[:]1224. BeaverTail then downloads the initial Python script of InvisibleFerret. It is saved on the victim machine as “.sysinfo” file in the victim’s home directory (Figure 6). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 4 of 20 Figure 6 Initial BeaverTail Python Script that Fetches InvisibleFerret. Once the file “.sysinfo” is downloaded onto the machine, InvisibleFerret’s loader file “.sysinfo” is then executed with the command “C:\Users\{username}\.pyp\python.exe" "C:\Users\{username}/.sysinfo”. It’s worth noting that this observation is different from what was reported by Unit 42 where the initial Python script was named “.npl”. It’s also worth noting that a total of 21 crypto extensions were targeted by the BeaverTail in our observed sample; the full list can be found in the Appendix at the end of the blog (Figure 7). Figure 7 Crypto Wallet Browser Extensions Targeted by BeaverTail. Analysis of InvisibleFerret Python Files The eSentire Threat Intelligence team conducted analysis of four Python files that were dropped in the incident; one loader (.sysinfo in this instance) and three payloads stored under “\.n2” folder in the user’s home directory (Figure 8). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 5 of 20 Table 1: Observed Invisible Ferret Python File Locations Request URL Note Destination File Path (Windows) hxxp[://]185[.]235[.]241[.]208:1224/client/99/29 HTTP request for InvisibleFerret Python Loader (client) %USERPROFILE%\.sysinfo hxxp[://]185[.]235[.]241[.]208:1224/payload/99/29 HTTP GET request for InvisibleFerret Component (Fingerprint, Remote Control, and Information Stealer Component) %USERPROFILE%\.n2\pay hxxp[://]185[.]235[.]241[.]208:1224/brow/99/29 HTTP GET request for InvisibleFerret Component (Browser Stealer Component) %USERPROFILE%\.n2\bow hxxp[://]185[.]235[.]241[.]208:1224/mclip/99/29 HTTP GET request for InvisibleFerret Component (Clipboard Stealer Component) %USERPROFILE%\.n2\mlip Loader Component Overview Figure 8 Python Loader (.sysinfo) Parameters (commented line was included). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 6 of 20 It's worth noting that the internal IP address (10.10.51.212) was excluded from the initial loader script, but still reappears in the various InvisibleFerret python payloads (Figure 8). This suggests that the IP address may be used for testing purposes. Furthermore, our analysis revealed that excluded or commented-out code sections are a common trait of these scripts, potentially indicative of the malware's development or testing stages. The sample downloads three distinct payloads which are appended with a campaign ID and sub ID (sType and gType respectively, as seen in Figure 8 above and Figure 9 below): pay_campaignid_subid.py; brow_campaignid_subid.py; and, mlip_campaignid_subid.py. On disk these files are saved to the %USERPROFILE%\.n2 path without these identifiers or file extensions (Figure 9). Figure 9 InvisibleFerret Python Files. Some of these files are obfuscated with a combination of zlib, base64 and reverse string order (Figure 10). The script loops through the lambda function continuously until the final cleartext payload is executed. Figure 10 Payload Retrieval An overview of the three InvisibleFerret components can be found in the table below. Table 2: InvisibleFerret Components https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 7 of 20 InvisibleFerret Component Purpose Notable Network Indicators pay Host Fingerprinting File Stealer Browser Credential Stealer Remote Access Deploys AnyDesk hxxp://185.235.241[.]208:1224/uploads hxxp://185.235.241[.]208:1224/keys hxxp://185.235.241[.]208:1224/brow hxxp://185.235.241[.]208:1224/adc 185.235.241[.]208:2245 brow Browser credential stealer hxxp://:185.235.241[.]208:1224/keys mlip Standalone clipboard stealer and keylogger targeting web browsers. hxxp://95.164.7[.]171:8637/api/clip “Pay” Component Overview The pay component conducts various host fingerprinting activities including the internal IP, external IP, OS version, username and a number of other parameters (Figure 11). It also initiates a backdoor session with the C2 server and scans and uploads sensitive files from the infected host. Figure 11 Host Fingerprinting functionality. Once the fingerprinting activity is concluded, it is packaged up and exfiltrated via HTTP POST request to hxxp://185.235.241[.]208:1224/keys (Figure 12). The C2 IP address is de-obfuscated by shifting the first nine characters to the end of the string then base64 decoding the set. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 8 of 20 Figure 12 Partial screenshot of pay_campaignid_subid.py exfil process (the commented line was left in by the author of the script) On non-Windows systems, the script attempts to run the client instance by calling client.run(). On Windows systems, the main backdoor client is initiated alongside a keylogger and clipboard stealer which utilizes the pyHook, pythoncom and pyperclip Python libraries (Figure 13) Figure 13 Initializing the backdoor and keylogger/clipboard stealer. Captured keystrokes and clipboard data are written to the global “e_buf” variable then sent back to the C2 (via TCP connection to 185.235.241[.]208:2245) when the ssh_clip command is called within the backdoor session. The backdoor session is defined within the Client (Figure 14), Session and Shell classes. It initiates a network connection over port 2245 to the C2 server using sockets and accepts JSON-formatted messages containing various commands shown below. Notably, it also calls an auto_up() function which in this sample initiates an automatic file upload. This sample also contained placeholder code for automatically dropping AnyDesk (as opposed to manually via the backdoor). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 9 of 20 Figure 14 Client class which manages the overall connection logic and initiates a file upload (code formatting and inline comments added for clarity) InvisibleFerret contains logic to scan for and upload files of interest from multiple operating systems. Various functions in the script expedite identification of noteworthy files: in_pk: Checks if a string contains a private key by searching for specific hexadecimal patterns that match typical private key lengths. ismnemonic: Determines if a string contains a valid mnemonic phrase by checking for typical word counts and validating the phrase. is_exceptFile: Checks if a file name has an extension that should be excluded from processing. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 10 of 20 is_exceptPath: Checks if a path name matches any directories that should be excluded. is_pat: Checks if a file name contains specific patterns related to environment variables and other sensitive files As each file is processed, the script checks if the file name contains any of these patterns: [ '.env', 'config.js', 'secret', 'metamask', 'wallet', 'private', 'mnemonic', 'password', 'account', '.xls', '.xlsx', '.doc', '.docx', '.rtf', '.txt', 'recovery' ] If the file is not a common document type, additional filtering is performed using ismnemonic and in_pk to target sensitive file content such as private keys. This is noteworthy given developers (likely those involved in blockchain/crypto applications) are targeted. Any system found infected with InvisibleFerret should assume these keys are compromised and take appropriate action. Files are uploaded to hxxp://185.235.241[.]208:1224/uploads. Filenames are prepended with the current time and the hostname is prepended with the subid “29”, as seen in Figure 15. Figure 15 Example HTTP headers from auto_upload activity. A record of uploaded files is kept within the flist file contained within the .n2 directory. While it’s a notable forensic artifact, since this file can be arbitrarily cleared, it should not be considered a reliable record of exfiltrated files. As has been documented by other researchers, the backdoor component contains 8 commands which are briefly outlined below. ssh_obj Change directories, execute arbitrary commands via subprocess.Popen. Results/errors are reported back[PC18] via the shell. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 11 of 20 ssh_cmd Terminates the Python process, likely to terminate the session. ssh_clip Sends captured keystrokes and clipboard data to the C2. ssh_run Downloads and runs the browser stealer component. ssh_upload Upload specific files, all files from a directory or search for files with specific patterns. ssh_kill Kills Chrome and Brave browser processes. ssh_any Downloads and runs AnyDesk. ssh_env Scans for environment (.env) files similar to the auto-upload function described above. If they match certain conditions (not in exception lists, contains private keys/phrases etc) the files are uploaded. “Brow” Component Overview This InvisibleFerret component is a cross-platform browser infostealer targeting Windows, Linux and MacOS operating systems. It targets Chrome, Brave, Opera, Yandex and MsEdge browsers, uploading sensitive data to hxxp://:185.235.241[.]208:1224/keys (Figure 16). Each OS type initializes its own class, which is inherited[BZ19] from the ChromeBase class. Each class provides instructions for decrypting browser-stored passwords on Windows, Linux and MacOS operating systems. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 12 of 20 Figure 16 Browser infostealer. Comments from original author. The script contains functionality to retrieve, decrypt and upload stored browser passwords, credit cards using methods commonly found in infostealing malware (Figure 17). Figure 17 Snippet of credential stealing code. Original comments are from the script author(s). “Mlip” (Mclip) Component Overview The third payload contains a standalone keylogger and clipboard stealer implemented in Python using the pyWinhook, psutil, pywin32 and wx libraries. The sample analyzed targeted Chrome and Brave browsers, uploading stolen data to hxxp://95.164.7[.]171:8637/api/clip (Figure 18). https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 13 of 20 Figure 18 Data upload structure in Mlip Python script. The primary function OnKeyBoardEvent (Figure 19) is triggered by a keyboard event handler via the HookManager from the pyWinhook library. When a keypress is detected, this function is called and will check the active window process pid, process name and window name via the act_win_pn() function using the win32gui library. If the process name matches a browser ("chrome.exe", "brave.exe"), it proceeds. Figure 19 OnKeyboardEvent funtion in mlip file. If the caption of the active window is empty (indicating no specific page title or a blank tab), the function then proceeds to handle individual keystrokes for logging purposes. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 14 of 20 The function checks for printable ASCII characters [PC20] and uses several modifiers to handle special keypresses such as CTL or enter. For example, when enter is pressed, it’s formatted as a newline character to break up the text and make it easier to process by the operator. If CTL + V is detected (signifying data being pasted into the browser), the GetTextFromClipboard() function is triggered. Data is appended to the key_log variable until a newline character is detected. If a newline character is detected (“\n”) and the key_log is not empty, the save_log() function is triggered, uploading the data to the C2 and clearing the log. If the window caption changes, the accumulated logs are also uploaded and cleared. GetTextFromClipboard Function The script appears to use the the wx (wxPython) library to handle clipboard operations. It initializes a new instance of wx.Clipboard, checks that the clipboard data is text (to avoid images or binaries) then uploads it to the C2 using the save_log() function shown in Figure 20. Interestingly, it can check the clipboard for private keys and mnemonic phrases, but that line was commented out in this sample. Figure 20 GetTextFromClipboard function. A quick test with the wx library shows clipboard data can be extracted with a simple Python script: https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 15 of 20 Figure 21 Screenshot testing whether clipboard data can be extracted through a python script What did we do? Our team of 24/7 SOC Cyber Analysts isolated the affected host to contain the infection. We alerted the customer of the incident and supported them through the remediation process. What can you learn from this TRU Positive? The case showcases the importance of endpoint security solutions, such as Endpoint Detection and Response (EDR), and the implementation of security training programs to educate users about such sophisticated threats. Using company-issued computers for personal activities outside of work, such as job interviews, can put corporate networks at risk. Developers should exercise caution when engaging with public code repositories that have a sparse portfolio – typically a single repository with minimal activity. This behavior can be a red flag, as threat actors often misuse free platforms like GitHub or BitBucket to host malicious code or distribute malware. https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 16 of 20 Recommendations from the Threat Response Unit (TRU): Assume compromise of sensitive keys, passwords and files on infected hosts and take appropriate action such as rotating keys, passwords etc. Confirm that all devices are protected with Endpoint Detection and Response (EDR) solutions. Implement a Phishing and Security Awareness Training (PSAT) program that educates and informs your employees on emerging threats in the threat landscape. Ensure your organization has a corporate policy for acceptable use of corporate devices. Indicators of Compromise You can access the indicators of compromise here. References https://www.esentire.com/blog/bored-beavertail-yacht-club-a-lazarus-lure https://www.group-ib.com/blog/apt-lazarus-python-scripts/ https://unit42.paloaltonetworks.com/two-campaigns-by-north-korea-bad-actors-target-job-hunters/ https://unit42.paloaltonetworks.com/north-korean-threat-actors-lure-tech-job-seekers-as-fake-recruiters/ https://www.microsoft.com/en-us/security/blog/2024/05/28/moonstone-sleet-emerges-as-new-north-korean-threat-actor-with-new-bag-of-tricks/ Appendix – Crypto Wallet Extensions Targeted by BeaverTail Browser Extension ID Browser Extesion Name Target Browser nkbihfbeogaeaoehlefnkodbefgpgknn MetaMask Chrome ejbalbakoplchlghecdalmeeeajnimhm MetaMask Edge fhbohimaelbohpjbbldcngcnapndodjp BNB Chain Walle Chrome ibnejdfjmmkpcnlpebklmnkoeoihofec TronLink Chrome bfnaelmomeimhlpmgjnjophhpkkoljpa Phantom Chrome https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 17 of 20 aeachknmefphepccionboohckonoeemg Coin98 Wallet Chrome hifafgmccdpekplomjjkcfgodnhcellj Crypto[.]com Chrome jblndlipeogpafnldhgmapagcccfchpi Kaia Wallet Chrome acmacodkjbdgmoleebolmdjonilkdbch Rabby Wallet Chrome dlcobpjiigpikoobohmabehhmhfoodbb Argent X Chrome mcohilncbfahbmgdjkbpemcciiolgcge OKX Wallet Chrome agoakfejjabomempkjlepdflaleeobhb Core Chrome omaabbefbmiijedngplfjmnooppbclkk Tonkeeper Chrome aholpfdialjgjfhomihkjbmgjidlcdno Exodus Web3 Wallet Chrome nphplpgoakhhjchkkhmiggakijnkhfnd TON Wallet Chrome penjlddjkjgpnkllboccdgccekpkcbin OpenMask Chrome lgmpcpglpngdoalbgeoldeajfclnhafa SafePal Chrome fldfpgipfncgndfolcbkdeeknbbbnhcc MyTonWallet Chrome bhhhlbepdkbapadjdnnojkbgioiodbic Solflare Wallet Chrome gjnckgkfmgmibbkoficdidcljeaaaheg Atomic Wallet Chrome https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 18 of 20 afbcbjpbpfadlkmhmclhkeeodmamcflc Math Wallet Chrome To learn how your organization can build cyber resilience and prevent business disruption with eSentire’s Next Level MDR, connect with an eSentire Security Specialist now. GET STARTED ABOUT ESENTIRE’S THREAT RESPONSE UNIT (TRU) The eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your organization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7 https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 19 of 20 Security Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and works as an extension of your security team to continuously improve our Managed Detection and Response service. By providing complete visibility across your attack surface and performing global threat sweeps and proactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending your organization against known and unknown threats. Source: https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 https://www.esentire.com/blog/bored-beavertail-invisibleferret-yacht-club-a-lazarus-lure-pt-2 Page 20 of 20