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

EXC_BAD_ACCESS in <redacted>. Now what?

EXC_BAD_ACCESS in <redacted>. Now what?

Swizzling your way around proprietary code bugs and crashes.

Sash Zats

July 08, 2015
Tweet

More Decks by Sash Zats

Other Decks in Technology

Transcript

  1. #!/usr/bin/ruby
    developers_dir = `xcode-select -p`.chomp
    frameworks_dir = "#{developers_dir}/Platforms/iPhoneSimulator.platform"
    frameworks_dir += "/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/*"
    swift_frameworks_count = 0
    Dir[frameworks_dir].each { |file|
    framework = "#{file}/#{File.basename(file, ".*")}"
    next unless File.exist?(framework)
    puts framework unless `otool -l #{framework} | grep -i swift`.empty?
    }

    View full-size slide

  2. System frameworks built with Swift1
    1 This slide is intentionally left blank

    View full-size slide

  3. It's not my fault

    View full-size slide

  4. Demo: UIKitty

    View full-size slide

  5. if let cls = NSClassFromString("UIPrinterSearchingView") {
    let block: @objc_block (AspectInfo) -> Void = { (aspectInfo) in
    if let view = aspectInfo.instance() as? UIView {
    view.frame.size.height = view.superview!.frame.height - 44
    }
    }
    let blockObject = unsafeBitCast(block, AnyObject.self)
    cls.aspect_hookSelector(
    Selector("layoutSubviews"),
    withOptions: .PositionAfter,
    usingBlock: blockObject,
    error: nil
    )
    }

    View full-size slide

  6. Swizzling
    1. Swizzling is still possible in Swift.
    2. Set applicable OS versions for the patch.
    3. Test extensively. On device!
    4. Aspect oriented programming.

    View full-size slide

  7. Demo: Organizer

    View full-size slide

  8. Hopper Disassembler

    View full-size slide

  9. diffArrays(var_24, eax, edi->_changedItems, nil, nil, nil, nil, nil);
    void diffArrays(NSArray *arg0,
    NSArray *arg1,
    NSArray *arg2,
    NSIndexSet **arg3,
    NSIndexSet **arg4,
    NSIndexSet **arg5,
    NSArray **arg6,
    NSIndexSet **arg7);

    View full-size slide

  10. The easiest part

    View full-size slide

  11. // Internal structures
    struct swift_func_wrapper {
    var trampolinePtr: UnsafeMutablePointer
    var functionObject: UnsafeMutablePointer
    }
    struct swift_func_object {
    var original_type_ptr: UnsafeMutablePointer
    var unknown: UnsafeMutablePointer
    var address: uintptr_t
    var selfPtr: UnsafeMutablePointer
    }
    // Method we want to call
    func hello(world: String) -> Void
    typedef helloFn = (String) -> Void
    // C function pointer
    let fn = UnsafeMutablePointer.alloc(1)
    fn.initialize(hello)
    let fnWrapper = UnsafeMutablePointer(fn)
    let opaque = COpaquePointer(bitPattern: fnWrapper.memory.functionObject.memory.address)
    let cFunction = CFunctionPointer(opaque)

    View full-size slide

  12. // Internal structures
    struct swift_func_wrapper {
    var trampolinePtr: UnsafeMutablePointer
    var functionObject: UnsafeMutablePointer
    }
    struct swift_func_object {
    var original_type_ptr: UnsafeMutablePointer
    var unknown: UnsafeMutablePointer
    var address: uintptr_t
    var selfPtr: UnsafeMutablePointer
    }

    View full-size slide

  13. // Method we want to call
    func hello(world: String) -> Void {
    print("Hello, \(world)")
    }
    typedef helloFn = (String) -> Void

    View full-size slide

  14. // C function pointer
    let fn = UnsafeMutablePointer.alloc(1)
    fn.initialize(hello)
    let fnWrapper = UnsafeMutablePointer(fn)
    let address = fnWrapper.memory.functionObject.memory.address
    let opaque = COpaquePointer(bitPattern: address)
    let cFunction = CFunctionPointer(opaque)

    View full-size slide

  15. C-functions patching
    · Find the goddamn thing.
    · Patch implementation.
    · Fishhook - dynamically rebinding symbols in
    Mach-O binaries.
    · Call the original implementation maybe?

    View full-size slide

  16. Conclusions
    · Objective-C + swizzling = !
    · C functions2 + fishhook = "
    · Swift + optimization -O = #
    2 calling IMP directly from Swift might be possible with @convention syntax

    View full-size slide

  17. Credits
    · Perceptual Debugging @kendalldevdiary
    · Reverse Engineering @Dirk_Gently
    · Unsafe Swift: For Fun & Profit @xenadu02
    · Peter Steinberger's blog by @steipete
    · All WWDC sessions about debugging by @apple
    · Aspects by @steipete, fishhook by @facebook

    View full-size slide