Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Disassembly for Fun and Profit

Disassembly for Fun and Profit

Alexsander Akers

September 14, 2017
Tweet

More Decks by Alexsander Akers

Other Decks in Technology

Transcript

  1. Why disassemble? — ! To see how methods are implemented

    — " To debug arcane exceptions — # To call functionality that shouldn't be called
  2. Agenda As developers of apps or frameworks, we decide which

    classes, methods, and properties to expose. Apple does this too. If something is private, it signals an implementation detail that should not normally be called directly. Private does not mean "do not call me."
  3. OSS dependencies — NSCalendar, NSFormatter, NSLocale, NSTimeZone ↪ icucore —

    Auto Layout ↪ Cassowary constraint solver — Core Data ↪ SQLite — Swift, Grand Central Dispatch, WebKit, Bonjour — And more... opensource.apple.com
  4. Call me maybe? GitHub a2/touch-baer @interface NSTouchBarItem () + (void)addSystemTrayItem:(NSTouchBarItem

    *)item; @end @interface NSTouchBar () + (void)presentSystemModalFunctionBar:(NSTouchBar *)touchBar systemTrayItemIdentifier:(NSString *)identifier; @end
  5. Call me maybe? #import <Foundation/Foundation.h> Class klass = NSClassFromString(@"SFAirDropActivityViewController") #import

    <objc/funtime.h> Class otherKlass = objc_getClass("SFAirDropActivityViewController")
  6. Call me maybe? #import <Foundation/Foundation.h> Class klass = NSClassFromString(@"SFAirDropActivityViewController") #import

    <objc/runtime.h> Class otherKlass = objc_getClass("SFAirDropActivityViewController") Runtime is funtime!
  7. Call me maybe? Class klass = NSClassFromString(@"SFAirDropActivityViewController"); id airDropThang =

    [[klass alloc] init]; [airDropThang performSelector: NSSelectorFromString(@"startBrowsing")];
  8. Call me maybe? #import <dlfcn.h> void *handle = dlopen("/System/Library/PrivateFrameworks" "/Sharing.framework/Sharing",

    RTLD_NOW); CFTypeRef (*createBrowser)(CFAllocatorRef, CFStringRef) = dlsym(handle, "SFBrowserCreate"); CFTypeRef browser = createBrowser(NULL, CFSTR("AirDrop"));
  9. Call me maybe? GitHub a2/TrollDropPlayground let path = "/System/Library" +

    \ "/PrivateFrameworks/Sharing.framework" let bundleURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, path as CFString, .cfurlposixPathStyle, false) let bundle = CFBundleCreate(nil, bundleURL)
  10. Call me maybe? GitHub a2/TrollDropPlayground var destination: UnsafeMutableRawPointer? = nil

    CFBundleGetDataPointersForNames(bundle, ["kSFBrowserKindAirDrop"] as CFArray, &destination) let airDropKind = destination .assumingMemoryBound(to: CFString.self) .pointee
  11. Call me maybe? GitHub a2/TrollDropPlayground var destination: UnsafeMutableRawPointer? = nil

    CFBundleGetFunctionPointersForNames(bundle, ["SFBrowserCreate"] as CFArray, &destination) typealias CreateBrowserType = @convention(c) (CFAllocator?, CFString?) -> Browser let createBrowser = unsafeBitCast( destination!, to: CreateBrowserType.self)
  12. How to disassemble — We had a starting point, UIKit

    — We disassembled UIKit — We searched for "AirDrop" to see which private API were called — We disassembled the Sharing framework — We created a way to call the API methods and functions
  13. ⚠ Caution — Private API use is grounds for App

    Store rejection. — Just because you can, doesn't mean you should. — With great power comes great responsibility.
  14. Where to go from here? — hopperapp.com — github.com/a2/touch-baer —

    github.com/a2/TrollDropKit — github.com/a2/TrollDropPlayground (Swift, Playgrounds.app)