Working with macOS DMG and PKG files on Linux


macos Linux dmg pkg

At my day job I’ve been diving into macOS malware, and it turns out that quite a lot of macOS malware gets distributed through installer packages like DMG images and PKG archives. I work on malware using REMnux or a Pop!_OS Linux system, so I wanted to share how I work with these files to analyze them on Linux.

Ripping open PKG files

PKG files are xar archive files you can open with bsdtar. I tried to use tar, but bsdtar actually did the trick where tar didn’t. To get bsdtar I ran sudo apt update && sudo apt install libarchive-tools because it didn’t exist on my system by default. To show how it works, in this post I unpack the legitimate AnonymousVPN client PKG.

To get started, make a folder for the contents of the PKG file and unpack it.

$ mkdir anonymous-vpn
$ bsdtar xvf AnonymousVPN.pkg -C anonymous-vpn/

x Bom
x Payload
x Scripts
x PackageInfo

$ cd anonymous-vpn/
$ ls -lah

total 13M
drwxrwxr-x 2 forensicitguy forensicitguy 4.0K Jan 31 20:54 .
drwxrwxr-x 5 forensicitguy forensicitguy 4.0K Jan 31 20:54 ..
-rw-r--r-- 1 forensicitguy forensicitguy  43K Nov 10 10:04 Bom
-rw-r--r-- 1 forensicitguy forensicitguy  347 Nov 10 10:04 PackageInfo
-rw-r--r-- 1 forensicitguy forensicitguy  13M Nov 10 10:04 Payload
-rw-r--r-- 1 forensicitguy forensicitguy  46K Nov 10 10:04 Scripts

Within the folder you should find multiple files, including a Bill of Materials (BOM) file, a PackageInfo file, a Payload archive, and a Scripts archive. The last two archive files are gzipped CPIO archives. To unpack the contents of the archives you can execute these commands.

$ cat Payload | gunzip | cpio -i
62475 blocks

$ cat Scripts | gunzip | cpio -i
294 blocks

$ ls -lah

total 13M
drwxrwxr-x 4 forensicitguy forensicitguy 4.0K Jan 31 20:58 .
drwxrwxr-x 5 forensicitguy forensicitguy 4.0K Jan 31 20:54 ..
drwxrwxr-x 3 forensicitguy forensicitguy 4.0K Jan 31 20:57 Applications
-rw-r--r-- 1 forensicitguy forensicitguy  43K Nov 10 10:04 Bom
drwxr-xr-x 6 forensicitguy forensicitguy 4.0K Jan 31 20:57 Library
-rw-r--r-- 1 forensicitguy forensicitguy  347 Nov 10 10:04 PackageInfo
-rw-r--r-- 1 forensicitguy forensicitguy  13M Nov 10 10:04 Payload
-rwxr-xr-x 1 forensicitguy forensicitguy  178 Jan 31 20:58 postinstall*
-rwxr-xr-x 1 forensicitguy forensicitguy 147K Jan 31 20:58 preinstall*
-rw-r--r-- 1 forensicitguy forensicitguy  46K Nov 10 10:04 Scripts

After unpacking Payload, you may find one or more folders that include MACH-O binaries and other data for an application. If the Payload doesn’t unpack into anything, it means that you have an empty, payload-free package. In these packages, the installation relies on the contents of the Scripts archive.

After unpacking Scripts, you may find a preinstall and postinstall file. As their names suggest, these files contain content run before the PKG installer runs and then after. While they live within the Scripts archive, they can be any form of executable content for macOS. They may exist as Bash shell scripts, Python or Ruby scripts, or even MACH-O binaries. We can observe the file types by executing file.

$ file *

Applications: directory
Bom:          Mac OS X bill of materials (BOM) file
Library:      directory
PackageInfo:  ASCII text
Payload:      gzip compressed data, from Unix, original size modulo 2^32 31987200
postinstall:  Bourne-Again shell script, ASCII text executable
preinstall:   Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|WEAK_DEFINES|BINDS_TO_WEAK|PIE>
Scripts:      gzip compressed data, from Unix, original size modulo 2^32 150528

From here you can dive into analyzing the scripts and binaries as you please.

Ripping open DMG files

DMG files are like ISO/IMG/VHD files on Windows platforms. They contain a filesystem that house multiple files and folders. DMGs can be compressed or not, and they can contain one of multiple filesystem types. To show opening a DMG, I’ll open up a DMG containing a cracked version of Little Snitch you can find passed around pirated app sites.

$ 7z x Little_Snitch_4.0.3_CR2_\[TNT\].dmg 

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz (806EA),ASM,AES-NI)

Scanning the drive for archives:
1 file, 52963974 bytes (51 MiB)

Extracting archive: Little_Snitch_4.0.3_CR2_[TNT].dmg
--
Path = Little_Snitch_4.0.3_CR2_[TNT].dmg
Type = Dmg
Physical Size = 52963974
Method = Copy Zero2 CRC
Blocks = 15
----
Path = 4.hfs
Size = 59727872
Packed Size = 52920832
Comment = disk image (Apple_HFS : 4)
Method = Copy Zero2 CRC
--
Path = 4.hfs
Type = HFS
Physical Size = 59727872
Method = HFS+
Cluster Size = 4096
Free Space = 6807552
Created = 2017-10-02 07:19:41
Modified = 2017-10-01 23:19:58

Everything is Ok

Folders: 5
Files: 6
Size:       50799922
Compressed: 52963974

$ ls -lah

total 51M
drwxrwxr-x 3 forensicitguy forensicitguy 4.0K Jan 31 21:08  .
drwxrwxr-x 3 forensicitguy forensicitguy 4.0K Jan 31 21:08  ..
drwx------ 6 forensicitguy forensicitguy 4.0K Oct  2  2017 'Little Snitch 4.0.3 CR2'
-rw-rw-r-- 1 forensicitguy forensicitguy  51M Feb  9  2019 'Little_Snitch_4.0.3_CR2_[TNT].dmg'

$ cd Little\ Snitch\ 4.0.3\ CR2/
$ ls -lah

total 424K
drwx------ 6 forensicitguy forensicitguy 4.0K Oct  2  2017  .
drwxrwxr-x 3 forensicitguy forensicitguy 4.0K Jan 31 21:08  ..
drwx------ 2 forensicitguy forensicitguy 4.0K Sep 22  2017  .background
-rw-rw-r-- 1 forensicitguy forensicitguy  11K Sep 22  2017  .DS_Store
-rw-rw-r-- 1 forensicitguy forensicitguy 1.6K Sep 22  2017  Help.txt
drwx------ 2 forensicitguy forensicitguy 4.0K Oct  2  2017 '[HFS+ Private Data]'
drwx------ 2 forensicitguy forensicitguy 4.0K Oct  2  2017 '.HFS+ Private Directory Data'$'\r'
drwx------ 2 forensicitguy forensicitguy 4.0K Sep 22  2017 'Manual install'
-rw-rw-r-- 1 forensicitguy forensicitguy 1.6K Sep 22  2017 'Open Gatekeeper friendly'
-rw-rw-r-- 1 forensicitguy forensicitguy 377K Sep 22  2017  .VolumeIcon.icns

Sometimes DMGs get maddening and you can’t unpack them easily with 7z. In these cases I recommend dmg2img, which this blog post talks about. When looking at DMGs, keep in mind they can contain any form of content needed for an application, including PKG installer files, scripts, folders, and more.

Good hunting!