Demo app used in “Hacking Marzipan” talk at Do iOS 2018
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
MarzipanDemoApp.xcodeproj
MarzipanDemoApp
images
README.md

README.md

Marzipan Demo App

This is the demo app used in the talk “Hacking Marzipan” by Tom Lokhorst at Do iOS 2018.

⚠️ This project is for demonstration purposes only, it is not meant to be used in production apps. Use at your own risk!

Build and tested on macOS 14.0 and 14.1 with Xcode 10.

Overview

This document explains how to create your own iOSMac (Marzipan) apps, using Steve Throughton Smith's marzipanify tool.

The demo application uses Swift, a storyboard, and calls private API's to display a segmented control in the window toolbar.

Disable macOS Security (Don't do this on your main device!)

To run a converted (marzipanified) app, you need to disable System Integrety Protection and AMFI:

  1. Restart you Mac in recovery mode by holding ⌘+R while booting
  2. In the Terminal, run csrutil disable
  3. In the Terminal, run nvram boot-args="amfi_get_out_of_my_way=0x1"
  4. Restart you Mac
  5. Your system is now vulnarable to malware and you can run marzipanified apps

Details: How to Disable System Integrity Protection on a Mac (and Why You Shouldn’t)

To re-able these security settings, reboot again in recovery mode and run: csrutil enable and nvram boot-args="amfi_get_out_of_my_way=0x0"

Marzipanify an iOS UIKit app

Use marzipanify to convert a iOS simulator binary to a macOS app:

marzipanify is an unsupported commandline tool to take an existing iOS Simulator binary (with minimum deployment target of iOS 12.0) and statically convert it and its embedded libraries & frameworks to run on macOS 10.14's UIKit runtime (Marzipan).

  1. Clone marzipanify and build the command line tool
  2. Create a new iOS app (with minimum deployment target of iOS 12)
  3. Build your app for the iOS Simulator
  4. Run marzipanify YourApp.app
    (make sure not to accidentaly add a slash at the end: marzipanify YourApp.app/ won't work)
  5. If your app uses Swift, whitelist by editing /System/iOSSupport/dyld/macOS-whitelist.txt and adding /path/to/YourApp.app/Contents/MacOS/
  6. Run the converted app with lldb to see output: lldb YourApp.app -o run
  7. The converted app must be deleted (or moved) to be able to build again in Xcode

Note: If your app uses Cocoapods, add this to your Podfile to make sure all pods also have a iOS 12 deployment target:

post_install do |installer|

   installer.pods_project.targets.each do |target|
     target.build_configurations.each do |config|
       config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
     end
   end

end

Marzipanify script

For a quick build-run-test cycle, this script cleans up the marzipanified app:

#!/bin/sh

appname=$1

if [[ $appname == *".app"* ]]; then
  echo "Argument shoudn't include .app"
  exit
fi

rm -rf $appname-mz.app
marzipanify $appname.app
mv $appname.app $appname-mz.app
lldb $appname-mz.app -o run

Segmented control in Window toolbar

To create a nice macOS-style segmented control in the window toolbar, we need to use some private APIs and Objective-C code.

  1. Use class-dump to look at all the private APIs in UIKit for the Mac
    Run: class-dump /System/iOSSupport/System/Library/PrivateFrameworks/UIKitCore.framework > UIKitCore.h
  2. Add new Objective-C .h and .m files to your project and include the header in your Swift code via a Briding header
  3. In the header file, include the private APIs from UIKitCore you which to use (see MarzipanHelper.h)
  4. In the implementation file, use those APIs (see MarzipanHelper.m)
  5. Add the private classes used to the linker flags, to weak link them: Other linker flags. Example: -Wl,-U,_OBJC_CLASS_$__UIWindowToolbarController

For more details, read Peter Steinberger's post on becoming a better Mac citizen, or see the example code in this repository.

Acknowledgements

This talk and repository have been made possible by the work of many people, a partial list:


Tom Lokhorst - @tomlokhorst
1 November 2018