Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SharedCache] Fix DSCObjCProcessor::PostProcessObjCSections and improve Objective-C processing #6198

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

WeiN76LQh
Copy link

This pull request provides 3 commits that do the following:

  1. The function DSCObjCProcessor::PostProcessObjCSections never does anything because it doesn't use the correct names to get the Objective-C sections of the recently loaded library. In fact it never does anything because the DSC never has sections with the names its searching for. This commit passes the baseName (the name of the library that was loaded), which is what other Objective-C section processing code does. Combining the base name with the section names it will now find them and process them as intended. This was resulting in alot of Objective-C related stuff being missed.
  2. Modifies the DSC API so that there is an additional boolean argument for load_image_containing_address or load_image_with_install_name called skipObjC which defaults to False. If True in SharedCache::LoadImageWithInstallName the code that launches the Objective-C processor will be skipped. This provides users a way to manually defer Objective-C processing.
  3. This commit provides a way for users to manually trigger Objective-C parsing against sections for a specific library or all libraries, via the API. 2 new API functions are added; process_objc_sections_for_image_with_install_name for processing the Objective-C sections of single DSC library that has been loaded, and process_all_objc_sections which will process Objective-C sections for all loaded libraries, even if they are only partially loaded.

The C++ API was also updated to support the API changes.

The purpose of the API changes comes down to the fact that there is a problem with processing Objective-C sections. At the time a library is loaded some of the references within those sections may refer to unload sections. This results in things like selectors not being correctly typed and named. There is currently no way for a user to trigger re-processing of Objective-C sections once the required sections have also been loaded. This pull request solves that and in addition allows the user to defer Objective-C processing until all the images they want to load have been loaded. This is more performant than processing Objective-C sections after each image is loaded and then against once they've all been loaded.

The following Python code can be used to demonstrate the new API changes:

# 10 random libraries to load
libs = [
    "/System/Library/Frameworks/Foundation.framework/Foundation",
    "/usr/lib/libobjc.A.dylib",
    "/System/Library/Frameworks/AVFoundation.framework/AVFoundation",
    "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation",
    "/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics",
    "/System/Library/Frameworks/CoreMedia.framework/CoreMedia",
    "/System/Library/Frameworks/CoreVideo.framework/CoreVideo",
    "/System/Library/PrivateFrameworks/AudioToolboxCore.framework/AudioToolboxCore",
    "/System/Library/PrivateFrameworks/AvatarKit.framework/AvatarKit",
    "/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore",
]

import binaryninja.sharedcache
dsc = binaryninja.sharedcache.SharedCache(bv)

bv.set_analysis_hold(True) # hold analysis until all libraries are loaded
for lib in libs:
    print(f"Loading DSC library '{lib}'")
    dsc.load_image_with_install_name(lib, True) # skip ObjC processing

print("Processing Objective-C sections")
dsc.process_all_objc_sections() # process all the Objective-C sections of the libraries just loaded

bv.set_analysis_hold(False)
print("Running auto analysis")
bv.update_analysis_and_wait() # trigger analysis now everything is loaded and processed

WeiN76LQh added 3 commits November 25, 2024 19:43
Prior to this commit the function `DSCObjCProcessor::PostProcessObjCSections` never does anything because it doesn't use the correct names to get the Objective-C sections of the recently loaded library. In fact it never does anything because the DSC never has sections with the names its searching for.

This commit passes the `baseName` (the name of the library that was loaded), which is what other Objective-C section processing code does. Combining the base name with the section names it will now find them and process them as intended. This was resulting in alot of Objective-C related stuff being missed.

There is however still an issue of the fact that the way this DSC plugin works means it only analyzes Objective-C sections once. This catches alot of things but there are a number of cases where other libraries need to be loaded first due to information being referenced in another library. For instance errors like `Failed to determine base classname for category` can be caused by the class reference in the category being to a class outside of the loaded library. Once the library containing the class has been loaded, the section containing the category should be re-proccessed.
…ding a library

This is useful when batch loading libraries to avoid extra processing (once the next commit has landed).
A problem with processing Objective-C sections at the time a library is loaded is that some of the references within those sections may refer to unload sections. This results in things like selectors not being correctly typed and named.

This commit provides a way for users to manually trigger Objective-C parsing against sections for a specific library or all libraries, via the API. Combined with the previous commit a user can use the API to batch load a number of libraries and skip Objective-C processing for each one and then run it across the entire of the DSC once they are all loaded.

Further improvement would be to provide a way to trigger Objective-C processing through the UI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant