MobileCraft

Oct 14 2014

Time Machine exclusion list

OSX’s time machine is pretty handy to make backups. Unfortunately, the exclusion list in its preference pane can be hard to use, especially because it is not alphabetically sorted.

It is possible to manually change the exclusion list by editing the file /Library/Preferences/com.apple.TimeMachine.plist. The file might be in binary plist format by default , so we first convert it to an xml plist:

sudo plutil -convert xml1 /Library/Preferences/com.apple.TimeMachine.plist

You can then change the exclusion paths. For example:

...
<key>SkipPaths</key>
  <array>
    <string>/System</string>
    <string>/Library</string>
    <string>/Applications</string>
    <string>~acoomans/Dropbox</string>
    <string>~acoomans/Downloads</string>
    <string>~acoomans/Library/Application Support/Steam</string>
    <string>~acoomans/Library/Application Support/MobileSync</string>
    <string>~acoomans/Library/Application Support/Dash</string>
    <string>~acoomans/Library/Caches</string>
    <string>~acoomans/Library/Developer/Xcode</string>
    <string>~acoomans/Movies</string>
    <string>~acoomans/Music</string>
    <string>~acoomans/Pictures</string>
    <string>~acoomans/src</string>
    <string>~acoomans/VirtualBox VMs</string>
  </array>
...

backup macosx
May 12 2014

Joining Facebook

A lot has been going on this last year: apps have been released, code was open sourced, binaries have been disassembled, frameworks have been reversed, a house flew over Paris, new friends were made, and old friends were kept.

I am now glad to announce that I am joining Facebook!

By the time you will be reading this, I will be in Menlo Park. Thank you all for your help and your support. I am looking forward to face new exciting challenges!

2 notes

May 08 2014

Per-app environment variables

If you want to set environment variables for an app, you can open a terminal, set the variables and run the binary:

export DYLD_INSERT_LIBRARIES=a.dylib
./binary

or, alternatively,

DYLD_INSERT_LIBRARIES=a.dylib ./binary

Now, how do you do the same, without the terminal, for an app? Previously, MacOSX let you define environment variables for a specific app by adding a dictionary under the LSEnvironment key in the app’s Info.plist. Unfortunately, and despite what the documentation still says, this feature has apparently been removed.

One way is to rename the binary (let’s say to binary_real) and to make a trampoline executable, with the original binary name, that changes the environment and then replace its image with the real binary. In python, this can be done with:

#!/usr/bin/python
import os
import sys

path = os.path.join(os.path.dirname(__file__), "binary_real")

os.environ["DYLD_INSERT_LIBRARIES"] = "a.dylib"
os.execv(path, sys.argv)

Note that this hasn’t been tested for signed binaries and may not work for them.

1 note

environment
May 06 2014

Loading dynamic code

When loading a dynamic library or a bundle, we sometimes want to have code executed at load.

In a C dylib, an initializer function can be defined by decorating it with the constructor attribute:

__attribute__((constructor))
static void initializer() { ... }

and correspondingly, a finalizer with the destructor attribute:

__attribute__((destructor))
static void finalizer() { ... }

In Objective-C, a class can have a +load method. This method is called early on, when the code is loaded. It is a good place to do method swizzling for instance.

@implementation MyClass
+ (void)load {...}

Note that a class can also have a +initialize method, but it is called lazily (or even not at all), only if, and when, the class is actually used.

1 note

dylib library
May 01 2014

Making dynamic libraries for iOS

By default, it is not possible to make dynamic libraries for iOS. However, by changing Xcode’s build specifications for packages and product types, dylibs can be build.

There are instructions on how to build and use dylib on iOS, by manually copying the corresponding spec from OSX specs to iOS specs.

I also made a script to crudely merge the specs:

Of course, as you know, apps containing dylibs are not allowed on the app store. You may then wonder how this can be useful. Well, for instance, dynamic libraries can be injected in the iOS simulator with DYLD_INSERT_LIBRARIES.

Why not add missing features to the simulator?

1 note

simulator library xcode dylib
Mar 28 2014

Making a cross-platform binary executable

iOS applications can run on multiple flavours of the ARM platform (armv7, armv7s, arm64). This is because they contain a fat binary, a file containing multiple binaries, one for each platform. There are plenty of tutorials explaining how to make (static) fat libraries, containing code for both the simulator (x86) and iOS (ARM).

Now, to what extend can we have different codes (as in: very different implementations) in a fat binary? Can we make the code aware of its target platform? And ultimately, would it be possible to make a fat binary executable (not a library), that runs on both iOS and on OSX?

I made Janus, a proof-of-concept of a “multiversal” fat binary.

Awareness of the target platform is simply done by exposing the CURRENT_ARCH Xcode environment variable as a macro definition.

To make the binary cross-platform, like fat libraries, the platform-specific binaries are merged together with lipo.

The resulting app contains a binary for both ARM and x86 code:

$ lipo -info ./Debug-iphoneos/Janus-iOS.app/Janus-iOS
Architectures in the fat file: ./Debug-iphoneos/Janus-iOS.app/Janus-iOS are: x86_64 armv7 armv7s arm64

The app runs on iOS:

And its binary runs on OSX, from the console:

$ ./Debug-iphoneos/Janus-iOS.app/Janus-iOS
x86_64
2014-03-27 15:29:31.160 Janus-iOS[73947:507] hello world, I'm an OSX binary running on x86_64

See Janus for all the dirty details.

The next step is to investigate if it would be possible to merge not only the binaries, but the apps.

1 note

x86_64 arm fat binary macosx ios
Mar 17 2014

Visiting the Apple campus

2 notes

apple
Mar 14 2014

Making a Xcode plugin

I recently made a Xcode plugin to synchronize code snippets with a git repository. Here’s what I learned.

Xcode supports plugins, but not officially. That means Apple does not provide any documentation. Fortunately, there’s documentation on the internet to figure out how to make one.

A plugin

A Xcode plugin is a bundle with the .xcplugin extension and a few specific settings. The best is to start with this highly recommended Xcode plugin template.

Plugins are installed under the ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins directory.

When Xcode starts, it loads the plugin bundle and calls pluginDidLoad: on your NSPrincipalClass:

+ (void)pluginDidLoad:(NSBundle*)plugin {
	NSLog(@"Xcode plugin did load");
}

Now let’s see how to add functionality.

Knowing Xcode internals

The first thing is to analyze Xcode, and to know its objects and their behavior.

Xcode is located at /Applications/Xcode.app/Contents/MacOS/Xcode. Xcode’s architecture is actually… made out of more than 50 plugins! (XCode 5.0.1)
The Xcode plugins (prefixed with IDE) are located under /Applications/Xcode.app/Contents/PlugIns.

Now, two tools come handy to analyze the binary and plugins: class-dump and a disassembler.

Class-dump outputs the headers (interface, struct definitions, …) from the binary code (executable or library):

class-dump IDECodeSnippetLibrary.ideplugin/Contents/MacOS/IDECodeSnippetLibrary 
generates:
//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
[...]
@interface IDECodeSnippetLibrary : DVTLibraryController
{
	DVTObservingToken *_kvoSnippetRepositoryToken;
	NSMapTable *_strongSnippetToAssetMap;
	NSArray *_orderedPlatformFamilies;
	BOOL _isAddingUserCodeSnippet;
	NSSet *_lastSnippets;
}
- (id)codeDetailController:(id)arg1 contentsForAsset:(id)arg2 representedObject:(id)arg3;
- (id)codeDetailController:(id)arg1 languageForAsset:(id)arg2 representedObject:(id)arg3;
- (id)editorViewControllerForAsset:(id)arg1;
- (BOOL)canRemoveAsset:(id)arg1;
[...]

The class-dumped header can be included in your project after some cleanup, probably involving some @class or by commenting out a few parts. I do, however, recommend doing it the clean way: making a IDE directory with .h header files only for the classes you are really interested in.

Sometimes you need to know more about the exact behavior of a method and that’s where the disassembler comes into play. Popular disassemblers include IDA pro (5.0 freeware) and the more user-friendly Hopper. I already covered some Intel assembly before and if you know how the Objective-C runtime works, you can read assembly code and figure what a method does.

The most important to understand are the objc_msgSend references:

call       qword [ds:imp___got__objc_msgSend]

Parameters are passed through registers %rdi, %rsi, %rdx, %rcx, %r8, %r9 (in that order) and return value is in %rax.

Adding functionality to Xcode

The second thing to do, after analyzing Xcode, is to add functionality.

To access an object, you can get a singleton from its class method, like NSApplication:

[NSApplication sharedApplication];

You can then access its related objects and go down the object hierarchy, to add your functionality.

Another technique is to modify Xcode objects’ behavior. Unfortunately, you cannot subclass, because Xcode will not know about, nor use, your subclass. You cannot use a category either because it makes original implementations unaccessible. And in both cases, the compiler will complain anyways because it cannot find the binary object, only its class-dumped header.

The solution to this is swizzling. Swizzling consists of changing a method implementation with another:

class_addMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types);
class_replaceMethod(__unsafe_unretained Class cls, SEL name, IMP imp, const char *types);

Sometimes you need to get access to a class. This can be done at runtime, thus fooling the compiler, with NSClassFromString:

IDECodeSnippet *codeSnippet = [[NSClassFromString(@"IDECodeSnippet") alloc] init];

Debugging Xcode plugins

The simplest (but limited and cumbersome) technique is using NSLog. Messages are then forwarded to syslog. You see the messages with the console.app or in a terminal with:

tail -f /var/log/system.log

Another way is to attach lldb to Xcode when it is running.

Distributing plugins

Alcatraz is a package manager for plugins, templates and color schemes for Xcode. Dispite being somewhat buggy, it is a good tool to not only manage your plugins but also to distribute your own.

To distribute your plugin, fork the Alcatraz package list and make a pull request. Hopefully, soon the world will have access to your newly made plugin.

Maintaining your plugin

(Un)fortunately, the fun doesn’t stop here. As I said in the beginning, Apple does not officially support Xcode plugins. This also means that they may break compatibility any time. In practice, we’ve seen plugins being broken mostly at major XCode releases.

I hope this helps to understand how to make a plugin for Xcode. Don’t forget to check the source of ACCodeSnippetRepositoryPlugin for a complete example of plugin.

2 notes

xcode plugin
Mar 07 2014

C Pre-processor macro Stringification

Convert a macro argument into a string constant:

source: GCC Stringification

1 note

macro preprocessor
Mar 06 2014

(Dis)Assembly

Let me explain some basics on assembly. Note that the following is about x86 Mac assembly; it differs ARM assembly used for iOS app.

On the x86 family, assembly can access both the processor registers and memory. 32 bits general registers are rax, rbx, rcx, rdx; index registers are rdi (destination) and rsi (source); and pointer registers are rbp (base) and rsp (stack). The registers can also be addressed as 8 bit (ah and al), 16 bit (ax) and 64 bits (eax — x86_64). There are also flags like CF (carry) and ZF (zero) to hold the state of the processor.

The function is declared with a label

methImpl_UIView_initWithFrame_:

The function usually starts with a standard entry sequence, setting up a new stack frame:

	push       rbp		; save the value of rbp
	mov        rbp, rsp	; rbp now points to the top of the stack
	push       r14 		; saving some variable
	sub        rsp, 0x30	; space allocated on the stack for the local variables

A function call is done with the call opcode. In Objective-C, method calls are done through the runtime's objc_msgSend function. Parameters are passed in the rdi, rsi, rdx, rcx, r8, r9 registers (in that order). In Objective-C, rdi points to the receiver, rsi to the selector, rdx to the first argument, and so on.

	mov        rsi, qword [ds:objc_sel_containsValueForKey_] 	; @selector(containsValueForKey:)
	lea        rdx, qword [ds:cfstring_UIFrame] 			; @"UIFrame"
	mov        rdi, rbx
	call       qword [ds:imp___got__objc_msgSend]

Jump instructions go straight to a memory address. Unlike call, they do not save the program counter. Jump opcodes are usually associated with a test opcode to make a if or a loop statement. Testing a register with itself is a trick to check if the register is equal to zero, like when checking if a pointer is nil.

	test       al, al
	je         0x5831c

Another trick is to xor a register with itself to make it zero

	xor	rax, rax

Note that sometimes, you’ll notice a set of instructions whose net result is noop (no operation — nothing is really achieved). It might be the compiler messing up, or, as some speculate, a form of optimization taking advantage of the pipelining of the processor. I haven’t investigated so I’m not really sure why this is happening. Either case, don’t be surprised if you encounter this.

	mov rdx, rax
	mov rax, rdx

Returning from a function usually happens with a standard exit sequence, removing the stack frame. Return values are passed through rax.

	add        rsp, 0x20		; remove space for local variables 
	pop        rbp			; restore rbp to its old value
	ret				; return to the calling function

This certainly not a comprehensive tutorial on assembly but I hope it helps getting started.

1 note

asm
Mar 04 2014

Reversing Frameworks

A while ago, in a project I inherited, I wanted to get rid of its storyboard. Being able to programmatically create segues would really have helped me. Unfortunately, the UIKit storyboard runtime does not allow that. So I re-implemented the storyboard segue logic and made a library.

Let me explain how we can analyze a framework in order to re-implement it. Frameworks for the the iOS 7.0 simulator are located under

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/
Being the simulator’s frameworks, they are Intel x86 32bits and 64bits binaries.

Now there are different tools to extract information from the binary.

Class-dump

Class-dump comes in many different flavours: the original class-dump (also available on homebrew), class-dump-x, class-dump-z. While they offer minor different level of details and performance, they all output the headers extracted from the binary code (executable or library). Those headers contain the interfaces, protocols, categories, structs, typedefs, and unions.

cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks/
class-dump UIKit.framework/UIKit
generates:
//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

#pragma mark Function Pointers and Blocks

typedef void (*CDUnknownFunctionPointerType)(void); // return type and parameters are unknown
typedef void (^CDUnknownBlockType)(void); // return type and parameters are unknown

#pragma mark Named Structures

struct CATransform3D {
	double m11;
	double m12;
	double m13;
	double m14;
	double m21;
	double m22;
	double m23;
	double m24;
	double m31;
	double m32;
	double m33;
	double m34;
	double m41;
	double m42;
	double m43;
	double m44;
};

[...]

#pragma mark Named Unions

union _GLKQuaternion {
	struct {
		union _GLKVector3 v;
		float s;
	} ;
	struct {
		float x;
		float y;
		float z;
		float w;
	} ;
	float q[4];
};

[...]

@interface UIView : UIResponder <_uiscrollnotification uitexteffectsordering nsisvariabledelegate nslayoutitem nsisenginedelegate nscoding uiappearance uiappearancecontainer uidynamicitem>
{
	CALayer *_layer;
	id _gestureInfo;
	NSMutableArray *_gestureRecognizers;
	NSArray *_subviewCache;
	float _charge;
	long long _tag;
	UIViewController *_viewDelegate;
	[...]
	NSISEngine *_layoutEngine;
	NSISVariable *_boundsWidthVariable;
	NSISVariable *_boundsHeightVariable;
	NSISVariable *_minXVariable;
	NSISVariable *_minYVariable;
	NSMutableArray *_internalConstraints;
	NSArray *_constraintsExceptingSubviewAutoresizingConstraints;
}

+ (void)_setShouldEnableUIKitParallaxEffects:(_Bool)arg1;
+ (_Bool)_shouldEnableUIKitDefaultParallaxEffects;
+ (void)_recenterMotionEffects;
+ (_Bool)_motionEffectsEnabled;
+ (_Bool)_motionEffectsSupported;
+ (void)_endSuspendingMotionEffectsForReason:(id)arg1;
+ (void)_beginSuspendingMotionEffectsForReason:(id)arg1;
+ (id)_motionEffectEngine;
+ (Class)layerClass;
+ (_Bool)_preventsAppearanceProxyCustomization;
+ (void)_performCustomizableAppearanceModifications:(CDUnknownBlockType)arg1;
+ (id)appearanceMatchingProperties:(id)arg1 whenContainedIn:(Class)arg2;
+ (id)_appearanceRecorderWhenContainedIn:(Class)arg1;
+ (id)appearanceWhenContainedIn:(Class)arg1;
+ (id)_appearanceWhenContainedIn:(id)arg1;
+ (id)_appearanceRecorder;
+ (id)appearance;
+ (void)throttledFlush;
+ (void)flush;
[...]

Private classes are decorated with the visibility attribute set to hidden:

__attribute__((visibility("hidden")))
and private methods are usually prefixed with and underscore _ :
 + (_Bool)_motionEffectsEnabled;

If you intend to publish on the app store any code accessing those private methods, your app may be rejected. Per the App store review guidelines (needs login in the ADC):

2.5 Apps that use non-public APIs will be rejected

There are some ways to circumvent Apple’s (static) code check for private APIs, but I really recommend against doing that. Accessing private classes/methods is not only forbidden by Apple’s guidelines, but is also a bad practice.

On the other hand, if you are developing for yourself or if you distribute your binary on the web only (like an mac app or xcode plugin), you should probably be fine. However, be warned those private classes and methods may change any time without any warning from Apple.

You can import the class-dumped headers in your project, probably involving the use of some @class or by commenting out a few parts.

otool

otool, the object file displaying tool, comes with MacOSX. It retrieves different informations from a binary, including Mach headers, load commands, segments, relocation entries and symbols table. It can also disassemble a binary with symbolic operands:

otool -tV UIKit
generates:
[...]
-[UIView initWithFrame:]:
	pushq   %rbp
	movq    %rsp, %rbp
	pushq   %r14
	pushq   %rbx
	subq    $0x30, %rsp
	movq    %rdi, 0xffffffffffffffe0(%rbp)
	movq    0xabb92d(%rip), %rax
	movq    %rax, 0xffffffffffffffe8(%rbp)
	movq    0xa9561a(%rip), %rsi
	leaq    0xffffffffffffffe0(%rbp), %rdi
	callq   0x68aa72 ## symbol stub for: _objc_msgSendSuper2
	movq    %rax, %rbx
	testq   %rbx, %rbx
	je      0x57f8d
	leaq    0x10(%rbp), %rax
[...]

One of the limitations of otool is that does not derefence all adresses, making the assembly code hard to follow.

IDA

Hex-rays’ IDA pro is probably the most popular multi-platform assembler and debugger. There are a commercial, evaluation and freeware version. It is a really powerful tool, but unfortunately, its power is tarnished by its lack of user-friendliness. Explaining how to use IDA would require a whole article in itself.

Hopper

Hopper is another, more user-friendly, multi-platform disassembler, decompiler and debugger. Compared to otool, it as a better support for cross-references (XREFs) when disassembling.

Hopper can also decompile the code but I have found that in practice, it sometimes “misses” some parts and isn’t accurate. I usually only use the decompiler to get a general sense of what a method is doing, then resort to assembly for the exact instructions.

Those are the tools I use for reversing. In a next article, I’ll explain how to read the disassembled code.

1 note

reverse engineering
Mar 03 2014
interface
+

Why mobile web apps are slow

Here is an article I read but apparently forgot to mention when it was released in summer 2013. Why mobile web apps are slow explains how hardware limitations, performance issues with garbage collection, and javascript are keeping html app behind native code.

To be fair, here is also Sencha’s answer: 5 Myths About Mobile Web Performance.

performance html5 native
+
llvm
Mar 01 2014
xcode plugin
Page 1 of 12