Vector35 / binaryninja-api

Public API, examples, documentation and issues for Binary Ninja
https://binary.ninja/
MIT License
944 stars 213 forks source link

Support for iOS 18 Objective-C Optimizations in dyld_shared_cache #6054

Open WeiN76LQh opened 1 month ago

WeiN76LQh commented 1 month ago

Version and Platform (required):

Bug Description: Sometimes loading a certain image from DSC results in Binary Ninja getting caught in what appears to be an infinite loop (probably finite bound to a very large number). During this time BN prints the following to the log view:

[SharedCache.ObjC] Failed to process an ivar at offset 0x180ded9a8

The address value at the end is an example. This line will keep being printed over and over, and the address value will increment by 0x20 each time. I'm guessing there's something wrong with the metadata parsing causing it to think there's a huge number of ivars to process.

Steps To Reproduce:

  1. Open a copy of DSC extracted from an iOS 18.0 beta 4 ipsw (22A5316j) for an iPhone 15 Pro Max (iPhone16,2) in Binary Ninja
  2. Wait for the initial analysis to complete
  3. Load the image /System/Library/Frameworks/Contacts.framework/Contacts

Binary: Extract the DSC from an iOS 18.0 beta 4 ipsw (22A5316j) for an iPhone 15 Pro Max (iPhone16,2). This has been a problem with other copies of DSC and other images within DSC, this is just one I know to be problematic with the contacts framework.

Additional Information: I believe this is a back trace for the thread thats doing the Objective-C metadata parsing. Hopefully its helpful without symbols given the version and platform information above.

* thread #39, name = 'Worker PRI '
  * frame #0: 0x000000018b2116dc dyld`invocation function for block in dyld3::MachOFile::forEachSegment(void (dyld3::MachOFile::SegmentInfo const&, bool&) block_pointer) const + 40
    frame #1: 0x000000018b1c42dc dyld`dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 300
    frame #2: 0x000000018b211688 dyld`dyld3::MachOFile::forEachSegment(void (dyld3::MachOFile::SegmentInfo const&, bool&) block_pointer) const + 172
    frame #3: 0x000000018b1e4e90 dyld`dyld4::JustInTimeLoader::contains(dyld4::RuntimeState&, void const*, void const**, unsigned long long*, unsigned char*) const + 260
    frame #4: 0x000000018b1f6fa4 dyld`invocation function for block in dyld4::APIs::findImageMappedAt(void const*, dyld3::MachOLoaded const**, bool*, char const**, void const**, unsigned long long*, unsigned char*, dyld4::Loader const**) + 144
    frame #5: 0x000000018b1d0404 dyld`dyld4::RuntimeLocks::withLoadersReadLock(void () block_pointer) + 100
    frame #6: 0x000000018b1f6da4 dyld`dyld4::APIs::findImageMappedAt(void const*, dyld3::MachOLoaded const**, bool*, char const**, void const**, unsigned long long*, unsigned char*, dyld4::Loader const**) + 756
    frame #7: 0x000000018b1fa6a4 dyld`dyld4::APIs::_dyld_find_unwind_sections(void*, dyld_unwind_sections*) + 124
    frame #8: 0x0000000198f7ddf0 libunwind.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::setInfoBasedOnIPRegister(bool) + 140
    frame #9: 0x0000000198f82288 libunwind.dylib`unw_set_reg + 636
    frame #10: 0x000000018b50436c libc++abi.dylib`__gxx_personality_v0 + 384
    frame #11: 0x0000000198f83080 libunwind.dylib`unwind_phase2 + 596
    frame #12: 0x0000000198f82e14 libunwind.dylib`_Unwind_RaiseException + 804
    frame #13: 0x000000018b503c7c libc++abi.dylib`__cxa_throw + 84
    frame #14: 0x000000011df0f6e4 libsharedcache.dylib`___lldb_unnamed_symbol3202 + 412
    frame #15: 0x000000011deb4d58 libsharedcache.dylib`___lldb_unnamed_symbol2785 + 424
    frame #16: 0x000000011deb2a5c libsharedcache.dylib`___lldb_unnamed_symbol2782 + 2312
    frame #17: 0x000000011dec5e14 libsharedcache.dylib`___lldb_unnamed_symbol2801 + 33316
    frame #18: 0x000000011deeafbc libsharedcache.dylib`___lldb_unnamed_symbol2952 + 4844
    frame #19: 0x000000011def8814 libsharedcache.dylib`BNDSCViewLoadImageWithInstallName + 168
    frame #20: 0x0000000310098070 libsharedcacheui.dylib`___lldb_unnamed_symbol3814 + 48
    frame #21: 0x00000003100aeb64 libsharedcacheui.dylib`___lldb_unnamed_symbol4472 + 36
    frame #22: 0x00000001156af22c libbinaryninjacore.1.dylib`___lldb_unnamed_symbol29525 + 2160
    frame #23: 0x00000001156ae6e4 libbinaryninjacore.1.dylib`___lldb_unnamed_symbol29520 + 12
    frame #24: 0x000000018b54b2e4 libsystem_pthread.dylib`_pthread_start + 136
0cyn commented 3 weeks ago

Resolved in dev builds >= 4.2.6359

This is 100% an iOS 18 cache issue (which we do not fully support yet) however I've added a sanity check for ivars so it should hopefully not get stuck in this anymore.

0cyn commented 3 weeks ago

Leaving this open to track iOS 18 support for new objective-c optimizations