SlideShare a Scribd company logo
Advanced Mac Software
Deployment and Configuration:
Just Make It Work!
Tim Sutton
Concordia University, Faculty of Fine Arts
Montréal, Quebec
“We’ve decided to move to Maya 2016 for the fall.
Would you be able to install that in the production suites for the start
of classes next week?”
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
$ packages/autodesk tree
.
!"" autodesk-esec2012-settings
#   !"" Makefile
#   !"" com.autodesk.MC3Framework.plist
#   $"" postflight
!"" autodesk2015-adlmreg
#   $"" adlmreg2015
!"" maya2012-license
#   !"" Makefile
#   $"" postflight
!"" maya2012-nuke-semaphore-hook
#   !"" Makefile
#   $"" maya2012_logout.hook
!"" maya2013-license
#   !"" Makefile
#   $"" postflight
!"" maya2014-license-cinema
#   !"" Makefile
#   $"" postflight
!"" maya2015-license
#   !"" Makefile
#   !"" adlmreg2015 -> ../autodesk2015-adlmreg/adlmreg2015
#   !"" munkiimport.sh
#   $"" postinstall
!"" maya2015-settings
#   !"" Makefile
!"" mudbox2013-license
#   !"" Makefile
#   $"" postflight
!"" mudbox2014-license-cinema
#   !"" Makefile
#   $"" postflight
!"" mudbox2015-fix-volume-permissions
#   !"" installcheck_script
#   !"" munkiimport.sh
#   $"" postinstall_script
!"" mudbox2015-license
#   !"" Makefile
#   $"" postinstall
$"" mudbox2015-settings
!"" Makefile
!"" Mudbox
#   $"" 2015
#   !"" paths
#   $"" settings
#   !"" ImageBrowser.txt
#   !"" brushes.sav
#   !"" hotkeys.txt
#   !"" recent.sav
#   !"" settings.sav
#   $"" ui.sav
!"" munkiimport.sh
!"" postflight
$"" setup_mudbox2015_prefs.sh
This job would be great if it
wasn’t for the f*$&@* customers.
This job would be great if it
wasn’t for the f*$&@* customers software.
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
# /Library/Preferences/com.panopto.Panopto_Recorder.plist
<plist version="1.0">
<dict>
<key>recordAudioVideo</key>
<true/>
<key>recordKeynote</key>
<true/>
<key>recordPowerpoint</key>
<true/>
<key>recordScreenCapture</key>
<true/>
<!-- ScreenCaptureFrameRate can only be set to a maximum of
12 in the GUI -->
<key>ScreenCaptureFrameRate</key>
<real>12</real>
<key>Server</key>
<string>lecturecapture.concordia.ca</string>
<key>VideoCompressionOption</key>
<string>QTCompressionOptionsHD720SizeH264Video</string>
<key>VideoFrameRate</key>
<real>24</real>
</dict>
</plist>
Advanced Mac Software Deployment and Configuration: Just Make It Work!
How could this be so hard?
• Automated install contexts
• Multi-user (and network) user environments
• Non-admin users
User experience
Consistency
Avoid duplication of effort
“Installer”
Drag and
drop bundle
Installer
package
Installer app
Pacifist
Suspicious
Package
/usr/bin/pkgutil
/usr/bin/lsbom
/usr/sbin/installer
(Office 2011, viewed with Suspicious Package QuickLook plugin)
$USER
$HOME or ~
(tim root)
(/Users/tim /var/root)
(sudo -u $USER? !)
defaults read/write
launchctl load/unload
osascript
/usr/sbin/installer -pkg /tmp/the.pkg -target /
Skype for Business
#!/bin/sh
# postinstall from https://go.microsoft.com/fwlink/?linkid=831677
parent_dir=`/usr/bin/dirname "$0"`
/bin/cp -R MeetingJoinPlugin.plugin /Library/Internet Plug-Ins/
/usr/bin/osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Skype for Business.app", hidden:false}'
/usr/bin/osascript -e 'tell application "Dock" to quit' -e 'delay 0.25'
/usr/bin/sudo -u $USER "$parent_dir/register_default_app"
/usr/bin/sudo -u $USER "$parent_dir/set_dock_tiles" add "/Applications/Skype for Business.app"
/usr/bin/killall -HUP Dock &> /dev/null
/usr/bin/osascript -e 'delay 1.0' -e 'tell application "Dock" to activate'
exit 0
# /var/log/install.log (no user logged in)
PackageKit: Executing script "./postinstall" in /private/tmp/PKInstallSandbox.ChKgiE/Scripts/com.microsoft.SkypeForBusiness.duPdd2
./postinstall: 36:134: execution error: An error of type -10810 has occurred. (-10810)
./postinstall: 2017-01-26 15:34:20.513 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:20.515 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:20.516 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:20.526 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:20.952 set_dock_tiles[5947:203716] Adding Dock item (/Applications/Skype for Business.app)
./postinstall: 2017-01-26 15:34:22.103 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:22.372 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:22.384 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
./postinstall: 2017-01-26 15:34:22.388 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
if ! [[ $COMMAND_LINE_INSTALL && $COMMAND_LINE_INSTALL != 0 ]]
then
domain="com.microsoft.autoupdate2"
defaults_cmd="/usr/bin/sudo -u $USER /usr/bin/defaults"
application="/Applications/Microsoft Outlook.app"
application_info_plist="$application/Contents/Info.plist"
lcid="1033"
if /bin/test -f "$application_info_plist"
then
application_bundle_signature=`$defaults_cmd read "$application_info_plist" CFBundleSignature`
application_bundle_version=`$defaults_cmd read "$application_info_plist" CFBundleVersion`
application_id=`printf "%s%02s" $application_bundle_signature ${application_bundle_version%%.*}`
$defaults_cmd write $domain Applications -dict-add "$application" "{ 'Application ID' = $application_id; LCID = $lcid ; }"
fi
<snip>
Outlook 2016
MOTU Pro Audio
#! /bin/sh
# postinstall
KEXT="MOTUProAudio.kext"
# 10.9+ install kext in /Library/Extensions
cd /Library/Extensions
chown -R root:wheel $KEXT
chmod -R u=rw,go=r,+X $KEXT
touch .
# if we're in 10.8, move the kext to /System
OSVER=`sw_vers | grep 'ProductVersion:' | grep -o '[0-9]*.[0-9]*.[0-9]*'`
if [[ $OSVER =~ ^10.8. ]]
then
mv /Library/Extensions/$KEXT /System/Library/Extensions/$KEXT
touch /System/Library/Extensions/
fi
# load our http server daemon
/bin/launchctl load /Library/LaunchDaemons/com.motu.proaudio.HTTPServer.launchd
# restart coreaudiod
/bin/launchctl unload /System/Library/LaunchDaemons/com.apple.audio.coreaudiod.
/bin/launchctl load /System/Library/LaunchDaemons/com.apple.audio.coreaudiod.pl
# open the discovery app
open "/Applications/MOTU Discovery.app"
MOTU Pro Audio
installd[338]: PackageKit: Executing script "./postinstall" in /tmp/PKInstallSandbox.Zxqser/Scripts/com.motu.pkg.proaudio.lq3hf9
installd[338]: ./postinstall: LSOpenURLsWithRole() failed with error -10810 for the file /Applications/MOTU Discovery.app.
installd[338]: PackageKit: Install Failed: Error Domain=PKInstallErrorDomain Code=112 "An error occurred while running scripts from
the package “MOTU Pro Audio Installer 2.0 (71418).pkg”.”
Terminal/SSH:
sudo installer -pkg
<pkg> -tgt /
Munki
User logged in Successful Unsuccessful
At loginwindow Unsuccessful Unsuccessful
Install method
Context
#!/usr/bin/perl
# Avid AIR Music Instruments for Pro Tools
sub get_user_id
{
my $homedir = $ENV{'HOME'};
my $userid = basename($homedir);
return $userid;
}
my $pluginPlist = "/Users/$userid/Library/Preferences/com.airmusictech.Structure";
if ((-e "$structurePlugIn") && $pluginBundleName eq "Structure Free") {
# No plist file. Install the content to the default location.
logIt("Clean install. Installing to $installDestination");
create_dir($installDestination, "777", "$userid:admin");
copy_dir($installerPatches, $installDestination, "777", "$userid:admin");
copy_dir($installerQuickStart, $installDestination, "777", "$userid:admin");
execute_command("mv "$installDestination$plugInPatchesWin" "$installDestination$plugInPatches"");
execute_command("mv "$installDestination$plugInQuickStartWin" "$installDestination$plugInQuickStart"");
execute_command("defaults write "$pluginPlist" "content" "$installDestination$plugInPatches/"");
execute_command("defaults write "$pluginPlist" "common content" "/Applications/AIR Music Technology/Common
execute_command("defaults write "$pluginPlist" "common binary" "/Applications/AIR Music Technology/Common/
execute_command("defaults write "$pluginPlist" "effects" "/Applications/AIR Music Technology/Structure/Set
execute_command("defaults write "$pluginPlist" "favorites" "/Applications/AIR Music Technology/Structure/F
execute_command("sudo chmod 755 "$pluginPlist.plist"");
execute_command("sudo chown $userid:staff "$pluginPlist.plist"");
Advanced Mac Software Deployment and Configuration: Just Make It Work!
#!/bin/sh
# Munki postinstall_script
defaults write /Library/Preferences/com.airmusictech.Boom "Content" "/Applications/AIR Music Technology/Boom"
defaults write /Library/Preferences/com.airmusictech.Mini Grand "Content" "/Applications/AIR Music Technology/Mini Grand"
defaults write /Library/Preferences/com.airmusictech.Structure "common binary" "/Applications/AIR Music Technology/Common/AIR/bin/"
defaults write /Library/Preferences/com.airmusictech.Structure "common content" "/Applications/AIR Music Technology/Common/AIR/Content/"
defaults write /Library/Preferences/com.airmusictech.Structure "content" "/Applications/AIR Music Technology/Structure/Content/Patch
defaults write /Library/Preferences/com.airmusictech.Structure "effects" "/Applications/AIR Music Technology/Structure/Settings/"
defaults write /Library/Preferences/com.airmusictech.Structure "favorites" "/Applications/AIR Music Technology/Structure/Favorites/"
Permissions
$ sudo installer –pkg ~/Desktop/AdobeAnimateCC2015.2.pkg –target /
$ whoami
test
$ ls ~/Library/Application Support/Adobe
total 0
drwxrwxrwx 5 root staff 170 Jul 7 15:48 .
drwx------+ 14 test staff 476 Jul 7 15:44 ..
drwxr-xr-x 2 root staff 68 Jul 7 15:48 Animate CC 2015.2
<key>IFPkgFlagDefaultLocation</key>
<string>/usr/local/lib</string>
<key>IFPkgFlagDefaultLocation</key>
<string>/usr/local/lib</string>
➜ ls -lan /usr/local/
drwxr-xr-x 8 0 0 272 26 Jan 14:21 .
drwxr-xr-x@ 13 0 0 442 6 Oct 2015 ..
drwxr-xr-x 69 0 0 2346 26 Jan 09:20 bin
drwx------ 3 501 0 102 26 Jan 14:21 lib
drwxr-xr-x 22 0 0 748 23 Jan 14:34 munki
drwxr-xr-x 7 0 0 238 6 Oct 2015 share
<key>IFPkgFlagDefaultLocation</key>
<string>/usr/local/lib</string>
➜ ~ lsbom "Lame v3.98.2 for Audacity.pkg/Contents/Archive.bom"
. 40700 501/0
./audacity 40775 0/0
./audacity/libmp3lame.dylib 100775 0/0 754564 2289255777
Test with your
management tools
$ tail -f /var/log/install.log
$ ls -la /var/root/Library/{Preferences,Application Support}
Installer as an app
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
#!/bin/bash -e
‘/tmp/Sophos Installer.app/Contents/MacOS/tools/InstallationDeployer’ —
install
rm -rf '/tmp/Sophos Installer.app'
#!/bin/bash -e
'/Library/Application Support/Sophos/opm-sa/Installer.app/Contents/MacOS/
tools/InstallationDeployer' --remove
/usr/sbin/pkgutil --forget com.myorg.Sophos
Use AutoPkg
Improve user
experience
(github.com/timsutton/make-adobe-cc-
license-pkg)
AdobeCC_Enterprise_License.pkg
Photoshop CC 2017
(18.0.0)
Premiere Pro CC 2017
(11.0.2)
Photoshop CC 2017
(18.0.1)
Illustrator CC 2017
(21.0.2)
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Advanced Mac Software Deployment and Configuration: Just Make It Work!
# SLCache/*.slc
$ cat Rmxhc2hCdWlsZGVy.slc | xmllint -format -
<?xml version="1.0"?>
<SLCInfo>
<node id="__SLCMeta__">
<key id="VERSION">2</key>
<key id="IsValid">1</key>
<key id="TimeStamp">1486072931</key>
</node>
<node id="FlashBuilder-CS5.5-Mac-GM{|}">
<key id="AXFBLicensedBy">V7{}CreativeCloudEnt-1.0-Mac-GM{|}ALL{|}9098502183747020261510079</key>
<key id="FLMap">V7{}CreativeCloudEnt-1.0-Mac-GM</key>
<key id="TestKey">TestValue</key>
</node>
<node id="__slcps__">
<key id="sig">7DxJr8jUpTEGTC4y2K-f=o=w</key>
# OOBE/opm.db
$ sqlite3 opm.db -cmd '.dump'
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE opm_data ( domain varchar(25), subDomain varchar(25), key varchar(100), value TEXT, PRIMARY KEY (domain, subDomain, key) );
CREATE TABLE opm_meta ( key varchar(25), value TEXT, constraint pk PRIMARY KEY (key) );
INSERT INTO "opm_meta" VALUES('schema_version','1');
INSERT INTO "opm_meta" VALUES('schema_compatibility_version','1');
COMMIT;
Advanced Mac Software Deployment and Configuration: Just Make It Work!
/Library/Application Support/Adobe/PCF/{ILST-21.0.2-64-ADBEADBEADBEADBEADBEA}.V7{}Illustrator-21-Mac-GM.xml
#!/usr/bin/python
from __future__ import print_function
import os
import re
import sys
from glob import glob
from xml.etree import ElementTree
def main():
pcf_root = '/Library/Application Support/Adobe/PCF'
if sys.platform == 'win32':
pcf_root = 'C:Program Files (x86)Common FilesAdobePCF'
xmls = glob(os.path.join(pcf_root, '*.xml'))
for xml_file in xmls:
# Sanity-check the filename and basic XML structure
# (ADBE.. string is only present for HyperDrive-installed products)
match = re.match(r'^({.*?ADBE.*?}).*$', os.path.basename(xml_file))
if not match:
sys.stderr.write("Skipping file '%s', does not match a PCF file patternn" % xml_file)
continue
adbe_code = match.groups()[0]
root = ElementTree.parse(xml_file)
payload = root.find("./Payload[@adobeCode='%s']" % adbe_code)
if payload is None:
sys.stderr.write("Didn't find expected Adobe code %s in any 'Payload' element"
" in file %sn" % (adbe_code, xml_file))
continue
# Check and skip if the serial override key already exists
if payload.find("Data[@key='REG_SERIAL_OVERRIDE']") is not None:
continue
# Finally, make a new element and append it to the Payload element
new_element = ElementTree.Element('Data', attrib={'key': 'REG_SERIAL_OVERRIDE'})
new_element.text = 'Suppress'
payload.append(new_element)
try:
root.write(xml_file, encoding='utf-8', xml_declaration=True)
print("Wrote modified PCF XML file: '%s'" % xml_file)
except IOError:
sys.stderr.write("ERROR: Can't write to file '%s'. Make sure you have "
"sufficient privileges to write to this location. "
% xml_file)
root = ElementTree.parse(xml_file)
payload = root.find("./Payload[@adobeCode='%s']" % adbe_code)
if payload is None:
sys.stderr.write("Didn't find expected Adobe code %s in any 'Payload' element"
" in file %sn" % (adbe_code, xml_file))
continue
# Check and skip if the serial override key already exists
if payload.find("Data[@key='REG_SERIAL_OVERRIDE']") is not None:
continue
# Finally, make a new element and append it to the Payload element
new_element = ElementTree.Element('Data', attrib={'key': 'REG_SERIAL_OVERRIDE'})
new_element.text = 'Suppress'
payload.append(new_element)
try:
root.write(xml_file, encoding='utf-8', xml_declaration=True)
print("Wrote modified PCF XML file: '%s'" % xml_file)
except IOError:
sys.stderr.write("ERROR: Can't write to file '%s'. Make sure you have "
"sufficient privileges to write to this location. "
% xml_file)
Application
preferences
Disable automatic
updates
Sparkle
Advanced Mac Software Deployment and Configuration: Just Make It Work!
$ defaults write /Library/Preferences/com.panic.Transmit SUEnableAutomaticChecks -bool false
NSUserDefaults
CFPreferences
Configuration
Profilesdefaults
Managing “non-native” preferences
• Depends on the application, sometimes there are options supported
for mass deployment:
• e.g. /Library/Application Support/Macromedia/mms.cfg
• For everything else, run scripts at login time to create or modify user
preferences:
• github.com/chilcote/outset (Joseph Chilcote)
• github.com/MagerValp/LoginScriptPlugin (Per Olofsson)
# ~/Library/Application Support/Google/Chrome/Default/Preferences
{
"browser": {
"check_default_browser": false,
"show_update_promotion_info_bar": false
},
"distribution": {
"make_chrome_default": false,
"show_welcome_page": false,
"skip_first_run_ui": true
},
"first_run_tabs":["http://www.mcvities.co.uk/"],
"homepage": "http://www.mcvities.co.uk/",
"sync_promo": {
"user_skipped": true
}
}
Managing “non-native” preferences
#!/bin/sh
prefs_src="/Library/MyOrg/Files/google_chrome_preferences"
prefs_tgt_dir="$HOME/Library/Application Support/Google/Chrome/Default"
prefs_tgt_file="$prefs_tgt_dir/Preferences"
# make our user's chrome profile dir if one doesn't already exist
[ -d "$prefs_tgt_dir" ] || mkdir -p "$prefs_tgt_dir"
# if prefs file doesn't already exist, copy it
[ -e "$prefs_tgt_file" ] || cp "$PREFS_SRC" "$prefs_tgt_file"
# create the special 'first run' file
touch "$prefs_tgt_dir/../First Run"
Managing “non-native” preferences
• Common locations:
• ~/Library/Application Support
• ~/Library/Preferences
• ~/Library/Preferences/App
• ~/.app, ~/Documents/App
• Experimentation and testing necessary!
Managing “non-native” preferences
Advanced Mac Software Deployment and Configuration: Just Make It Work!
Hopper Disassembler
int _main() {
var_140 = objc_autoreleasePoolPush();
rax = [NSArray arrayWithObjects:intrinsic_movdqa(var_50, intrinsic_punpcklqdq(zero_extend_64(@"conf"), zero_extend_64(@"x-
mspresence"))) count:0x3];
rax = [rax retain];
var_138 = rax;
xmm0 = intrinsic_pxor(zero_extend_64(@"x-mspresence"), zero_extend_64(@"x-mspresence"));
intrinsic_movdqa(var_F0, xmm0);
intrinsic_movdqa(var_100, xmm0);
var_110 = intrinsic_movdqa(var_110, xmm0);
var_120 = intrinsic_movdqa(var_120, xmm0);
rbx = [rax countByEnumeratingWithState:var_120 objects:var_D0 count:0x10];
if (rbx != 0x0) {
r12 = *var_110;
do {
r13 = 0x0;
do {
if (*var_110 != r12) {
objc_enumerationMutation(var_138);
}
r14 = *(var_118 + r13 * 0x8);
r15 = [LSCopyDefaultHandlerForURLScheme(r14) retain];
if ([r15 isEqualToString:@"com.microsoft.SkypeForBusiness"] == 0x0) {
rcx = LSSetDefaultHandlerForURLScheme(r14, @"com.microsoft.SkypeForBusiness");
if (rcx != 0x0) {
NSLog(@"LSSetDefaultHandlerForURLScheme failed with error code: %d", rcx);
}
}
[r15 release];
r13 = r13 + 0x1;
} while (r13 < rbx);
rbx = [var_138 countByEnumeratingWithState:var_120 objects:var_D0 count:0x10];
[r15 release];
r13 = r13 + 0x1;
} while (r13 < rbx);
rbx = [var_138 countByEnumeratingWithState:var_120 objects:var_D0 count:0x10];
} while (rbx != 0x0);
}
r15 = CFPreferencesCopyAppValue(@"Applications", @"com.microsoft.autoupdate2");
rbx = [[r15 objectForKey:@"/Applications/Skype for Business.app"] retain];
[rbx release];
if (rbx == 0x0) {
r13 = [[NSMutableDictionary alloc] initWithDictionary:r15];
var_130 = intrinsic_movdqa(var_130, intrinsic_punpcklqdq(zero_extend_64(@"Application ID"),
zero_extend_64(@"LCID")));
rbx = [@(0x409) retain];
r14 = [[NSDictionary dictionaryWithObjects:@"MSFB16" forKeys:var_130 count:0x2] retain];
[r13 setObject:r14 forKeyedSubscript:@"/Applications/Skype for Business.app"];
[r14 release];
[rbx release];
CFPreferencesSetAppValue(@"Applications", r13, @"com.microsoft.autoupdate2");
CFPreferencesAppSynchronize(@"com.microsoft.autoupdate2");
[r13 release];
}
[r15 release];
[var_138 release];
objc_autoreleasePoolPop(var_140);
if (*___stack_chk_guard == *___stack_chk_guard) {
rax = 0x0;
}
else {
rax = __stack_chk_fail();
}
return rax;
Thank you!
@timsutton
@tvsutton
https://macops.ca/macaduk2017

More Related Content

PDF
Search and play more than 50 clips
PPTX
Os dev tool box
PDF
Puppeteer can automate that! - HolyJS Piter 2020
PDF
State of Web APIs 2017
PDF
Firefox OS workshop, Colombia
PDF
Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
PDF
PDF
Android code puzzlers + tips & tricks
Search and play more than 50 clips
Os dev tool box
Puppeteer can automate that! - HolyJS Piter 2020
State of Web APIs 2017
Firefox OS workshop, Colombia
Bringing the open web and APIs to mobile devices with Firefox OS - Whisky W...
Android code puzzlers + tips & tricks

What's hot (13)

PDF
Puppet Camp Berlin 2015: Pedro Pessoa | Puppet at the center of everything - ...
PDF
[drupalcampatx] Adaptive Images in Responsive Web Design
PDF
[psuweb] Adaptive Images in Responsive Web Design
PDF
The MetaCPAN VM Part II (Using the VM)
ODP
Mangling
PDF
Synack at ShmooCon 2015
PDF
More android code puzzles
PDF
Cocoaheads Stockholm 2014-02: Writing your own jailbreak tweak
ODP
Deploy MediaWiki usgin Fiware Lab Facilities
PDF
Chrome Devtools Protocol via Selenium/Appium (English)
PDF
Macdoored
PDF
PuppetConf 2016: Docker, Mesos, Kubernetes and...Puppet? Don't Panic! – Deep...
PDF
Antons Kranga Building Agile Infrastructures
Puppet Camp Berlin 2015: Pedro Pessoa | Puppet at the center of everything - ...
[drupalcampatx] Adaptive Images in Responsive Web Design
[psuweb] Adaptive Images in Responsive Web Design
The MetaCPAN VM Part II (Using the VM)
Mangling
Synack at ShmooCon 2015
More android code puzzles
Cocoaheads Stockholm 2014-02: Writing your own jailbreak tweak
Deploy MediaWiki usgin Fiware Lab Facilities
Chrome Devtools Protocol via Selenium/Appium (English)
Macdoored
PuppetConf 2016: Docker, Mesos, Kubernetes and...Puppet? Don't Panic! – Deep...
Antons Kranga Building Agile Infrastructures
Ad

More from Timothy Sutton (8)

PDF
Jenkins CI for MacDevOps
PDF
Tools and Process for Streamlining Mac Deployment
PDF
Managing the User Experience
PDF
Python for Mac Admins
PDF
How Do I Contribute?
PDF
Why Mac Sysadmins Love Python
PDF
AutoPkg: Crowd-sourcing Mac packaging and deployment
PDF
MacSysAdmin Tools Smörgåsbord
Jenkins CI for MacDevOps
Tools and Process for Streamlining Mac Deployment
Managing the User Experience
Python for Mac Admins
How Do I Contribute?
Why Mac Sysadmins Love Python
AutoPkg: Crowd-sourcing Mac packaging and deployment
MacSysAdmin Tools Smörgåsbord
Ad

Recently uploaded (20)

PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Electronic commerce courselecture one. Pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPT
Teaching material agriculture food technology
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Spectroscopy.pptx food analysis technology
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Approach and Philosophy of On baking technology
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Machine learning based COVID-19 study performance prediction
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Big Data Technologies - Introduction.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
The AUB Centre for AI in Media Proposal.docx
The Rise and Fall of 3GPP – Time for a Sabbatical?
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Electronic commerce courselecture one. Pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Teaching material agriculture food technology
NewMind AI Weekly Chronicles - August'25 Week I
Spectroscopy.pptx food analysis technology
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
20250228 LYD VKU AI Blended-Learning.pptx
Approach and Philosophy of On baking technology
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Machine learning based COVID-19 study performance prediction
Diabetes mellitus diagnosis method based random forest with bat algorithm
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Empathic Computing: Creating Shared Understanding
Big Data Technologies - Introduction.pptx
Unlocking AI with Model Context Protocol (MCP)
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton

Advanced Mac Software Deployment and Configuration: Just Make It Work!

  • 1. Advanced Mac Software Deployment and Configuration: Just Make It Work! Tim Sutton Concordia University, Faculty of Fine Arts Montréal, Quebec
  • 2. “We’ve decided to move to Maya 2016 for the fall. Would you be able to install that in the production suites for the start of classes next week?”
  • 5. $ packages/autodesk tree . !"" autodesk-esec2012-settings #   !"" Makefile #   !"" com.autodesk.MC3Framework.plist #   $"" postflight !"" autodesk2015-adlmreg #   $"" adlmreg2015 !"" maya2012-license #   !"" Makefile #   $"" postflight !"" maya2012-nuke-semaphore-hook #   !"" Makefile #   $"" maya2012_logout.hook !"" maya2013-license #   !"" Makefile #   $"" postflight !"" maya2014-license-cinema #   !"" Makefile #   $"" postflight !"" maya2015-license #   !"" Makefile #   !"" adlmreg2015 -> ../autodesk2015-adlmreg/adlmreg2015 #   !"" munkiimport.sh #   $"" postinstall !"" maya2015-settings #   !"" Makefile
  • 6. !"" mudbox2013-license #   !"" Makefile #   $"" postflight !"" mudbox2014-license-cinema #   !"" Makefile #   $"" postflight !"" mudbox2015-fix-volume-permissions #   !"" installcheck_script #   !"" munkiimport.sh #   $"" postinstall_script !"" mudbox2015-license #   !"" Makefile #   $"" postinstall $"" mudbox2015-settings !"" Makefile !"" Mudbox #   $"" 2015 #   !"" paths #   $"" settings #   !"" ImageBrowser.txt #   !"" brushes.sav #   !"" hotkeys.txt #   !"" recent.sav #   !"" settings.sav #   $"" ui.sav !"" munkiimport.sh !"" postflight $"" setup_mudbox2015_prefs.sh
  • 7. This job would be great if it wasn’t for the f*$&@* customers.
  • 8. This job would be great if it wasn’t for the f*$&@* customers software.
  • 12. # /Library/Preferences/com.panopto.Panopto_Recorder.plist <plist version="1.0"> <dict> <key>recordAudioVideo</key> <true/> <key>recordKeynote</key> <true/> <key>recordPowerpoint</key> <true/> <key>recordScreenCapture</key> <true/> <!-- ScreenCaptureFrameRate can only be set to a maximum of 12 in the GUI --> <key>ScreenCaptureFrameRate</key> <real>12</real> <key>Server</key> <string>lecturecapture.concordia.ca</string> <key>VideoCompressionOption</key> <string>QTCompressionOptionsHD720SizeH264Video</string> <key>VideoFrameRate</key> <real>24</real> </dict> </plist>
  • 14. How could this be so hard? • Automated install contexts • Multi-user (and network) user environments • Non-admin users
  • 18. (Office 2011, viewed with Suspicious Package QuickLook plugin)
  • 19. $USER $HOME or ~ (tim root) (/Users/tim /var/root) (sudo -u $USER? !) defaults read/write launchctl load/unload osascript /usr/sbin/installer -pkg /tmp/the.pkg -target /
  • 20. Skype for Business #!/bin/sh # postinstall from https://go.microsoft.com/fwlink/?linkid=831677 parent_dir=`/usr/bin/dirname "$0"` /bin/cp -R MeetingJoinPlugin.plugin /Library/Internet Plug-Ins/ /usr/bin/osascript -e 'tell application "System Events" to make login item at end with properties {path:"/Applications/Skype for Business.app", hidden:false}' /usr/bin/osascript -e 'tell application "Dock" to quit' -e 'delay 0.25' /usr/bin/sudo -u $USER "$parent_dir/register_default_app" /usr/bin/sudo -u $USER "$parent_dir/set_dock_tiles" add "/Applications/Skype for Business.app" /usr/bin/killall -HUP Dock &> /dev/null /usr/bin/osascript -e 'delay 1.0' -e 'tell application "Dock" to activate' exit 0 # /var/log/install.log (no user logged in) PackageKit: Executing script "./postinstall" in /private/tmp/PKInstallSandbox.ChKgiE/Scripts/com.microsoft.SkypeForBusiness.duPdd2 ./postinstall: 36:134: execution error: An error of type -10810 has occurred. (-10810) ./postinstall: 2017-01-26 15:34:20.513 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:20.515 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:20.516 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:20.526 osascript[5942:203610] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:20.952 set_dock_tiles[5947:203716] Adding Dock item (/Applications/Skype for Business.app) ./postinstall: 2017-01-26 15:34:22.103 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:22.372 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:22.384 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data ./postinstall: 2017-01-26 15:34:22.388 osascript[5949:203741] CFPasteboardRef CFPasteboardCreate(CFAllocatorRef, CFStringRef) : failed to create global data
  • 21. if ! [[ $COMMAND_LINE_INSTALL && $COMMAND_LINE_INSTALL != 0 ]] then domain="com.microsoft.autoupdate2" defaults_cmd="/usr/bin/sudo -u $USER /usr/bin/defaults" application="/Applications/Microsoft Outlook.app" application_info_plist="$application/Contents/Info.plist" lcid="1033" if /bin/test -f "$application_info_plist" then application_bundle_signature=`$defaults_cmd read "$application_info_plist" CFBundleSignature` application_bundle_version=`$defaults_cmd read "$application_info_plist" CFBundleVersion` application_id=`printf "%s%02s" $application_bundle_signature ${application_bundle_version%%.*}` $defaults_cmd write $domain Applications -dict-add "$application" "{ 'Application ID' = $application_id; LCID = $lcid ; }" fi <snip> Outlook 2016
  • 22. MOTU Pro Audio #! /bin/sh # postinstall KEXT="MOTUProAudio.kext" # 10.9+ install kext in /Library/Extensions cd /Library/Extensions chown -R root:wheel $KEXT chmod -R u=rw,go=r,+X $KEXT touch . # if we're in 10.8, move the kext to /System OSVER=`sw_vers | grep 'ProductVersion:' | grep -o '[0-9]*.[0-9]*.[0-9]*'` if [[ $OSVER =~ ^10.8. ]] then mv /Library/Extensions/$KEXT /System/Library/Extensions/$KEXT touch /System/Library/Extensions/ fi # load our http server daemon /bin/launchctl load /Library/LaunchDaemons/com.motu.proaudio.HTTPServer.launchd # restart coreaudiod /bin/launchctl unload /System/Library/LaunchDaemons/com.apple.audio.coreaudiod. /bin/launchctl load /System/Library/LaunchDaemons/com.apple.audio.coreaudiod.pl # open the discovery app open "/Applications/MOTU Discovery.app"
  • 23. MOTU Pro Audio installd[338]: PackageKit: Executing script "./postinstall" in /tmp/PKInstallSandbox.Zxqser/Scripts/com.motu.pkg.proaudio.lq3hf9 installd[338]: ./postinstall: LSOpenURLsWithRole() failed with error -10810 for the file /Applications/MOTU Discovery.app. installd[338]: PackageKit: Install Failed: Error Domain=PKInstallErrorDomain Code=112 "An error occurred while running scripts from the package “MOTU Pro Audio Installer 2.0 (71418).pkg”.” Terminal/SSH: sudo installer -pkg <pkg> -tgt / Munki User logged in Successful Unsuccessful At loginwindow Unsuccessful Unsuccessful Install method Context
  • 24. #!/usr/bin/perl # Avid AIR Music Instruments for Pro Tools sub get_user_id { my $homedir = $ENV{'HOME'}; my $userid = basename($homedir); return $userid; } my $pluginPlist = "/Users/$userid/Library/Preferences/com.airmusictech.Structure"; if ((-e "$structurePlugIn") && $pluginBundleName eq "Structure Free") { # No plist file. Install the content to the default location. logIt("Clean install. Installing to $installDestination"); create_dir($installDestination, "777", "$userid:admin"); copy_dir($installerPatches, $installDestination, "777", "$userid:admin"); copy_dir($installerQuickStart, $installDestination, "777", "$userid:admin"); execute_command("mv "$installDestination$plugInPatchesWin" "$installDestination$plugInPatches""); execute_command("mv "$installDestination$plugInQuickStartWin" "$installDestination$plugInQuickStart""); execute_command("defaults write "$pluginPlist" "content" "$installDestination$plugInPatches/""); execute_command("defaults write "$pluginPlist" "common content" "/Applications/AIR Music Technology/Common execute_command("defaults write "$pluginPlist" "common binary" "/Applications/AIR Music Technology/Common/ execute_command("defaults write "$pluginPlist" "effects" "/Applications/AIR Music Technology/Structure/Set execute_command("defaults write "$pluginPlist" "favorites" "/Applications/AIR Music Technology/Structure/F execute_command("sudo chmod 755 "$pluginPlist.plist""); execute_command("sudo chown $userid:staff "$pluginPlist.plist"");
  • 26. #!/bin/sh # Munki postinstall_script defaults write /Library/Preferences/com.airmusictech.Boom "Content" "/Applications/AIR Music Technology/Boom" defaults write /Library/Preferences/com.airmusictech.Mini Grand "Content" "/Applications/AIR Music Technology/Mini Grand" defaults write /Library/Preferences/com.airmusictech.Structure "common binary" "/Applications/AIR Music Technology/Common/AIR/bin/" defaults write /Library/Preferences/com.airmusictech.Structure "common content" "/Applications/AIR Music Technology/Common/AIR/Content/" defaults write /Library/Preferences/com.airmusictech.Structure "content" "/Applications/AIR Music Technology/Structure/Content/Patch defaults write /Library/Preferences/com.airmusictech.Structure "effects" "/Applications/AIR Music Technology/Structure/Settings/" defaults write /Library/Preferences/com.airmusictech.Structure "favorites" "/Applications/AIR Music Technology/Structure/Favorites/"
  • 28. $ sudo installer –pkg ~/Desktop/AdobeAnimateCC2015.2.pkg –target / $ whoami test $ ls ~/Library/Application Support/Adobe total 0 drwxrwxrwx 5 root staff 170 Jul 7 15:48 . drwx------+ 14 test staff 476 Jul 7 15:44 .. drwxr-xr-x 2 root staff 68 Jul 7 15:48 Animate CC 2015.2
  • 30. <key>IFPkgFlagDefaultLocation</key> <string>/usr/local/lib</string> ➜ ls -lan /usr/local/ drwxr-xr-x 8 0 0 272 26 Jan 14:21 . drwxr-xr-x@ 13 0 0 442 6 Oct 2015 .. drwxr-xr-x 69 0 0 2346 26 Jan 09:20 bin drwx------ 3 501 0 102 26 Jan 14:21 lib drwxr-xr-x 22 0 0 748 23 Jan 14:34 munki drwxr-xr-x 7 0 0 238 6 Oct 2015 share
  • 31. <key>IFPkgFlagDefaultLocation</key> <string>/usr/local/lib</string> ➜ ~ lsbom "Lame v3.98.2 for Audacity.pkg/Contents/Archive.bom" . 40700 501/0 ./audacity 40775 0/0 ./audacity/libmp3lame.dylib 100775 0/0 754564 2289255777
  • 33. $ tail -f /var/log/install.log $ ls -la /var/root/Library/{Preferences,Application Support}
  • 41. (github.com/timsutton/make-adobe-cc- license-pkg) AdobeCC_Enterprise_License.pkg Photoshop CC 2017 (18.0.0) Premiere Pro CC 2017 (11.0.2) Photoshop CC 2017 (18.0.1) Illustrator CC 2017 (21.0.2)
  • 45. # SLCache/*.slc $ cat Rmxhc2hCdWlsZGVy.slc | xmllint -format - <?xml version="1.0"?> <SLCInfo> <node id="__SLCMeta__"> <key id="VERSION">2</key> <key id="IsValid">1</key> <key id="TimeStamp">1486072931</key> </node> <node id="FlashBuilder-CS5.5-Mac-GM{|}"> <key id="AXFBLicensedBy">V7{}CreativeCloudEnt-1.0-Mac-GM{|}ALL{|}9098502183747020261510079</key> <key id="FLMap">V7{}CreativeCloudEnt-1.0-Mac-GM</key> <key id="TestKey">TestValue</key> </node> <node id="__slcps__"> <key id="sig">7DxJr8jUpTEGTC4y2K-f=o=w</key>
  • 46. # OOBE/opm.db $ sqlite3 opm.db -cmd '.dump' PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE opm_data ( domain varchar(25), subDomain varchar(25), key varchar(100), value TEXT, PRIMARY KEY (domain, subDomain, key) ); CREATE TABLE opm_meta ( key varchar(25), value TEXT, constraint pk PRIMARY KEY (key) ); INSERT INTO "opm_meta" VALUES('schema_version','1'); INSERT INTO "opm_meta" VALUES('schema_compatibility_version','1'); COMMIT;
  • 49. #!/usr/bin/python from __future__ import print_function import os import re import sys from glob import glob from xml.etree import ElementTree def main(): pcf_root = '/Library/Application Support/Adobe/PCF' if sys.platform == 'win32': pcf_root = 'C:Program Files (x86)Common FilesAdobePCF' xmls = glob(os.path.join(pcf_root, '*.xml')) for xml_file in xmls: # Sanity-check the filename and basic XML structure # (ADBE.. string is only present for HyperDrive-installed products) match = re.match(r'^({.*?ADBE.*?}).*$', os.path.basename(xml_file)) if not match: sys.stderr.write("Skipping file '%s', does not match a PCF file patternn" % xml_file) continue adbe_code = match.groups()[0] root = ElementTree.parse(xml_file) payload = root.find("./Payload[@adobeCode='%s']" % adbe_code) if payload is None: sys.stderr.write("Didn't find expected Adobe code %s in any 'Payload' element" " in file %sn" % (adbe_code, xml_file)) continue # Check and skip if the serial override key already exists if payload.find("Data[@key='REG_SERIAL_OVERRIDE']") is not None: continue # Finally, make a new element and append it to the Payload element new_element = ElementTree.Element('Data', attrib={'key': 'REG_SERIAL_OVERRIDE'}) new_element.text = 'Suppress' payload.append(new_element) try: root.write(xml_file, encoding='utf-8', xml_declaration=True) print("Wrote modified PCF XML file: '%s'" % xml_file) except IOError: sys.stderr.write("ERROR: Can't write to file '%s'. Make sure you have " "sufficient privileges to write to this location. " % xml_file)
  • 50. root = ElementTree.parse(xml_file) payload = root.find("./Payload[@adobeCode='%s']" % adbe_code) if payload is None: sys.stderr.write("Didn't find expected Adobe code %s in any 'Payload' element" " in file %sn" % (adbe_code, xml_file)) continue # Check and skip if the serial override key already exists if payload.find("Data[@key='REG_SERIAL_OVERRIDE']") is not None: continue # Finally, make a new element and append it to the Payload element new_element = ElementTree.Element('Data', attrib={'key': 'REG_SERIAL_OVERRIDE'}) new_element.text = 'Suppress' payload.append(new_element) try: root.write(xml_file, encoding='utf-8', xml_declaration=True) print("Wrote modified PCF XML file: '%s'" % xml_file) except IOError: sys.stderr.write("ERROR: Can't write to file '%s'. Make sure you have " "sufficient privileges to write to this location. " % xml_file)
  • 55. $ defaults write /Library/Preferences/com.panic.Transmit SUEnableAutomaticChecks -bool false
  • 57. Managing “non-native” preferences • Depends on the application, sometimes there are options supported for mass deployment: • e.g. /Library/Application Support/Macromedia/mms.cfg • For everything else, run scripts at login time to create or modify user preferences: • github.com/chilcote/outset (Joseph Chilcote) • github.com/MagerValp/LoginScriptPlugin (Per Olofsson)
  • 58. # ~/Library/Application Support/Google/Chrome/Default/Preferences { "browser": { "check_default_browser": false, "show_update_promotion_info_bar": false }, "distribution": { "make_chrome_default": false, "show_welcome_page": false, "skip_first_run_ui": true }, "first_run_tabs":["http://www.mcvities.co.uk/"], "homepage": "http://www.mcvities.co.uk/", "sync_promo": { "user_skipped": true } } Managing “non-native” preferences
  • 59. #!/bin/sh prefs_src="/Library/MyOrg/Files/google_chrome_preferences" prefs_tgt_dir="$HOME/Library/Application Support/Google/Chrome/Default" prefs_tgt_file="$prefs_tgt_dir/Preferences" # make our user's chrome profile dir if one doesn't already exist [ -d "$prefs_tgt_dir" ] || mkdir -p "$prefs_tgt_dir" # if prefs file doesn't already exist, copy it [ -e "$prefs_tgt_file" ] || cp "$PREFS_SRC" "$prefs_tgt_file" # create the special 'first run' file touch "$prefs_tgt_dir/../First Run" Managing “non-native” preferences
  • 60. • Common locations: • ~/Library/Application Support • ~/Library/Preferences • ~/Library/Preferences/App • ~/.app, ~/Documents/App • Experimentation and testing necessary! Managing “non-native” preferences
  • 63. int _main() { var_140 = objc_autoreleasePoolPush(); rax = [NSArray arrayWithObjects:intrinsic_movdqa(var_50, intrinsic_punpcklqdq(zero_extend_64(@"conf"), zero_extend_64(@"x- mspresence"))) count:0x3]; rax = [rax retain]; var_138 = rax; xmm0 = intrinsic_pxor(zero_extend_64(@"x-mspresence"), zero_extend_64(@"x-mspresence")); intrinsic_movdqa(var_F0, xmm0); intrinsic_movdqa(var_100, xmm0); var_110 = intrinsic_movdqa(var_110, xmm0); var_120 = intrinsic_movdqa(var_120, xmm0); rbx = [rax countByEnumeratingWithState:var_120 objects:var_D0 count:0x10]; if (rbx != 0x0) { r12 = *var_110; do { r13 = 0x0; do { if (*var_110 != r12) { objc_enumerationMutation(var_138); } r14 = *(var_118 + r13 * 0x8); r15 = [LSCopyDefaultHandlerForURLScheme(r14) retain]; if ([r15 isEqualToString:@"com.microsoft.SkypeForBusiness"] == 0x0) { rcx = LSSetDefaultHandlerForURLScheme(r14, @"com.microsoft.SkypeForBusiness"); if (rcx != 0x0) { NSLog(@"LSSetDefaultHandlerForURLScheme failed with error code: %d", rcx); } } [r15 release]; r13 = r13 + 0x1; } while (r13 < rbx); rbx = [var_138 countByEnumeratingWithState:var_120 objects:var_D0 count:0x10];
  • 64. [r15 release]; r13 = r13 + 0x1; } while (r13 < rbx); rbx = [var_138 countByEnumeratingWithState:var_120 objects:var_D0 count:0x10]; } while (rbx != 0x0); } r15 = CFPreferencesCopyAppValue(@"Applications", @"com.microsoft.autoupdate2"); rbx = [[r15 objectForKey:@"/Applications/Skype for Business.app"] retain]; [rbx release]; if (rbx == 0x0) { r13 = [[NSMutableDictionary alloc] initWithDictionary:r15]; var_130 = intrinsic_movdqa(var_130, intrinsic_punpcklqdq(zero_extend_64(@"Application ID"), zero_extend_64(@"LCID"))); rbx = [@(0x409) retain]; r14 = [[NSDictionary dictionaryWithObjects:@"MSFB16" forKeys:var_130 count:0x2] retain]; [r13 setObject:r14 forKeyedSubscript:@"/Applications/Skype for Business.app"]; [r14 release]; [rbx release]; CFPreferencesSetAppValue(@"Applications", r13, @"com.microsoft.autoupdate2"); CFPreferencesAppSynchronize(@"com.microsoft.autoupdate2"); [r13 release]; } [r15 release]; [var_138 release]; objc_autoreleasePoolPop(var_140); if (*___stack_chk_guard == *___stack_chk_guard) { rax = 0x0; } else { rax = __stack_chk_fail(); } return rax;