Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ members = [
"plugins/idb_import",
"plugins/pdb-ng",
"plugins/pdb-ng/demo",
"plugins/warp",
"plugins/svd",
"plugins/svd/demo"
"plugins/svd/demo",
"plugins/warp",
"plugins/workflow_objc",
]

[workspace.dependencies]
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,18 @@ This repository contains all of our Binary View Type plugins available here:

## Other Plugins

* [SVD Loader](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/svd/)
* [Objective-C](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/workflow_objc/)
* [RTTI Analysis](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/rtti/)
* [WARP Integration](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/warp/)
* [Stack Render Layer](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/stack_render_layer/)
* [SVD Loader](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/svd/)
* [Triage View](https://github.com/Vector35/binaryninja-api/tree/dev/examples/triage/)
* [WARP Integration](https://github.com/Vector35/binaryninja-api/tree/dev/plugins/warp/)

## Related Repositories

In addition to this main API repository being open source Vector35 also has open sourced the Debugger and the Objective-C plugins open source as well:
In addition to this main API repository being open source Vector35 also has open sourced the Debugger plugin as well:

* [Debugger](https://github.com/Vector35/debugger)
* [workflow_objc](https://github.com/Vector35/workflow_objc)

## Licensing

Expand Down
41 changes: 23 additions & 18 deletions docs/guide/objectivec.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
# Objective-C

Binary Ninja ships with [an additional plugin](https://github.com/Vector35/workflow_objc) for assisting with Objective-C analysis.
Binary Ninja ships with built-in functionality for assisting with Objective-C analysis.
A brief summary of the features offered is as follows:

- **Function Call Cleanup.** When using the Objective-C workflow, calls to
`objc_msgSend` can be replaced with direct calls to the relevant function's
implementation.

- **Name and Type Recovery.** Using runtime information embedded in the
binary, Binary Ninja can automatically apply names and type information to
binary, Binary Ninja automatically applies names and type information to
Objective-C functions.

- **Structure Markup.** Data variables are automatically created for Objective-C
structures such as classes and method lists to enable easy navigation.

- **Data Renderers.** Formatting of Objective-C types such as tagged and/or
(image-)relative pointers is improved via custom data renderers.
- **String Literal Handling.** Data variables are automatically created for all
`CFString` or `NSString` instances present in the binary.

- **CFString Handling.** Data variables are automatically created for all
`CFString` instances present in the binary.
- **Automatic Call Type Adjustments.** Binary Ninja automatically infers the number of arguments and their names
for individual calls to `objc_msgSend` and `objc_msgSendSuper2`. Argument names are derived from the selector
components, and argument types are inferred in limited cases.

## Usage
- **Pseudo Objective-C Language.** Decompiled code can be displayed using a _Pseudo Objective-C_
language syntax. This renders `objc_msgSend` and other Objective-C runtime calls using the
`[receiver message:argument other:argument2]` syntax found in Objective-C source code.
Additionally, literals such as `CFString` or `NSString` are displayed inline as `@"string"`.

If you have an Objective-C binary opening in Binary Ninja should automatically process
the information. This is handled by the view, e.g. MACH-O & Shared Cache.
- **Direct Call Rewriting.** Calls to `objc_msgSend` can be rewritten to be direct calls to
the first known method implementation for that selector.

This is disabled by default as it will give potentially confusing results for any selector
that has more than one implementation or for common selector names. That said, some users may
still find it to be useful. It can be enabled via `analysis.objectiveC.resolveDynamicDispatch`
setting.

## Usage

### Workflow
Objective-C metadata will be automatically processed when you open a Mach-O or DYLD shared cache binary in Binary Ninja.

To utilize function call cleanup, the Objective-C workflow must be chosen when loading a binary for analysis.
The Pseudo Objective-C Language representation is available via the language pop-up menu at the top of Linear and Graph views:

![](../img/objc-workflow-selected.png)
![](../img/pseudo-objc-menu-item.png)

This will automatically apply structure analysis as the binary is analyzed and
also translate `objc_msgSend` calls to direct method calls, where possible.
Binary file removed docs/img/objc-workflow-selected.png
Binary file not shown.
Binary file added docs/img/pseudo-objc-menu-item.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 1 addition & 7 deletions plugins/warp/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use binaryninja::background_task::BackgroundTask;
use binaryninja::command::{
register_command, register_command_for_function, register_command_for_project,
};
use binaryninja::is_ui_enabled;
use binaryninja::logger::Logger;
use binaryninja::settings::Settings;
use binaryninja::{add_optional_plugin_dependency, is_ui_enabled};
use log::LevelFilter;
use reqwest::StatusCode;

Expand Down Expand Up @@ -200,9 +200,3 @@ pub extern "C" fn CorePluginInit() -> bool {

true
}

#[unsafe(no_mangle)]
pub extern "C" fn CorePluginDependencies() {
// TODO: Remove this once the objectivec workflow is registered on the meta workflow.
add_optional_plugin_dependency("workflow_objc");
}
4 changes: 0 additions & 4 deletions plugins/workflow_objc/.clang-format

This file was deleted.

7 changes: 0 additions & 7 deletions plugins/workflow_objc/.gitignore

This file was deleted.

21 changes: 0 additions & 21 deletions plugins/workflow_objc/BinaryNinja.h

This file was deleted.

133 changes: 96 additions & 37 deletions plugins/workflow_objc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,47 +1,106 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)

project(workflow_objc)


if((NOT BN_API_PATH) AND (NOT BN_INTERNAL_BUILD))
set(BN_API_PATH $ENV{BN_API_PATH})
if(NOT BN_API_PATH)
message(FATAL_ERROR "Provide path to Binary Ninja API source in BN_API_PATH")
endif()
if(NOT BN_API_BUILD_EXAMPLES AND NOT BN_INTERNAL_BUILD)
if(NOT BN_API_PATH)
# If we have not already defined the API source directory try and find it.
find_path(
BN_API_PATH
NAMES binaryninjaapi.h
# List of paths to search for the clone of the api
HINTS ../../.. ../../binaryninja/api/ binaryninjaapi binaryninja-api $ENV{BN_API_PATH}
REQUIRED
)
endif()
set(CARGO_STABLE_VERSION 1.83.0)
add_subdirectory(${BN_API_PATH} binaryninjaapi)
endif()
if(NOT BN_INTERNAL_BUILD)
set(HEADLESS ON CACHE BOOL "")
add_subdirectory(${BN_API_PATH} ${PROJECT_BINARY_DIR}/api)

file(GLOB_RECURSE PLUGIN_SOURCES CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/Cargo.toml
${PROJECT_SOURCE_DIR}/src/*.rs)

file(GLOB_RECURSE API_SOURCES CONFIGURE_DEPENDS
${PROJECT_SOURCE_DIR}/../../binaryninjacore.h
${PROJECT_SOURCE_DIR}/../../rust/binaryninjacore-sys/build.rs
${PROJECT_SOURCE_DIR}/../../rust/binaryninjacore-sys/Cargo.toml
${PROJECT_SOURCE_DIR}/../../rust/binaryninjacore-sys/src/*.rs
${PROJECT_SOURCE_DIR}/../../rust/Cargo.toml
${PROJECT_SOURCE_DIR}/../../rust/src/*/*.rs)

if(CMAKE_BUILD_TYPE MATCHES Debug)
set(TARGET_DIR ${PROJECT_BINARY_DIR}/target/debug)
set(CARGO_OPTS --target-dir=${PROJECT_BINARY_DIR}/target)
else()
set(TARGET_DIR ${PROJECT_BINARY_DIR}/target/release)
set(CARGO_OPTS --target-dir=${PROJECT_BINARY_DIR}/target --release)
set(OUTPUT_PDB_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}workflow_objc.pdb)
endif()

# Binary Ninja plugin ----------------------------------------------------------

set(PLUGIN_SOURCE
GlobalState.h
GlobalState.cpp
MessageHandler.cpp
MessageHandler.h
Plugin.cpp
Workflow.h
Workflow.cpp)

add_library(workflow_objc SHARED ${PLUGIN_SOURCE})
target_link_libraries(workflow_objc binaryninjaapi)
target_compile_features(workflow_objc PRIVATE cxx_std_20 c_std_99)
plugin_rpath(workflow_objc)

# Library targets linking against the Binary Ninja API need to be compiled with
# position-independent code on Linux.
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_compile_options(workflow_objc PRIVATE "-fPIC")
set(OUTPUT_FILE ${CMAKE_STATIC_LIBRARY_PREFIX}workflow_objc${CMAKE_SHARED_LIBRARY_SUFFIX})
set(PLUGIN_PATH ${TARGET_DIR}/${OUTPUT_FILE})

add_custom_target(workflow_objc ALL DEPENDS ${PLUGIN_PATH})
add_dependencies(workflow_objc binaryninjaapi)

find_program(RUSTUP_PATH rustup REQUIRED HINTS ~/.cargo/bin)
if(CARGO_API_VERSION)
set(RUSTUP_COMMAND ${RUSTUP_PATH} run ${CARGO_API_VERSION} cargo build)
else()
set(RUSTUP_COMMAND ${RUSTUP_PATH} run ${CARGO_STABLE_VERSION} cargo build)
endif()

# Configure plugin output directory for internal builds, otherwise configure
# plugin installation for public builds.
if(BN_INTERNAL_BUILD)
set_target_properties(workflow_objc PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}
RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR})
if(APPLE)
if(UNIVERSAL)
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(AARCH64_LIB_PATH ${PROJECT_BINARY_DIR}/target/aarch64-apple-darwin/debug/${OUTPUT_FILE})
set(X86_64_LIB_PATH ${PROJECT_BINARY_DIR}/target/x86_64-apple-darwin/debug/${OUTPUT_FILE})
else()
set(AARCH64_LIB_PATH ${PROJECT_BINARY_DIR}/target/aarch64-apple-darwin/release/${OUTPUT_FILE})
set(X86_64_LIB_PATH ${PROJECT_BINARY_DIR}/target/x86_64-apple-darwin/release/${OUTPUT_FILE})
endif()

add_custom_command(
OUTPUT ${PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E env
MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR}
${RUSTUP_COMMAND} --target=aarch64-apple-darwin ${CARGO_OPTS}
COMMAND ${CMAKE_COMMAND} -E env
MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR}
${RUSTUP_COMMAND} --target=x86_64-apple-darwin ${CARGO_OPTS}
COMMAND mkdir -p ${TARGET_DIR}
COMMAND lipo -create ${AARCH64_LIB_PATH} ${X86_64_LIB_PATH} -output ${PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E copy ${PLUGIN_PATH} ${BN_CORE_PLUGIN_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES})
else()
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(LIB_PATH ${PROJECT_BINARY_DIR}/target/debug/${OUTPUT_FILE})
else()
set(LIB_PATH ${PROJECT_BINARY_DIR}/target/release/${OUTPUT_FILE})
endif()

add_custom_command(
OUTPUT ${PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E env MACOSX_DEPLOYMENT_TARGET=10.14 BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS}
COMMAND ${CMAKE_COMMAND} -E copy ${PLUGIN_PATH} ${BN_CORE_PLUGIN_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES})
endif()
elseif(WIN32)
add_custom_command(
OUTPUT ${PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS}
COMMAND ${CMAKE_COMMAND} -E copy ${PLUGIN_PATH} ${BN_CORE_PLUGIN_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${TARGET_DIR}/${OUTPUT_PDB_NAME} ${BN_CORE_PLUGIN_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES})
else()
bn_install_plugin(workflow_objc)
add_custom_command(
OUTPUT ${PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E env BINARYNINJADIR=${BN_CORE_OUTPUT_DIR} ${RUSTUP_COMMAND} ${CARGO_OPTS}
COMMAND ${CMAKE_COMMAND} -E copy ${PLUGIN_PATH} ${BN_CORE_PLUGIN_DIR}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
DEPENDS ${PLUGIN_SOURCES} ${API_SOURCES})
endif()
26 changes: 0 additions & 26 deletions plugins/workflow_objc/CONTRIBUTING.md

This file was deleted.

16 changes: 16 additions & 0 deletions plugins/workflow_objc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "workflow_objc"
version = "0.1.0"
edition = "2021"
license = "BSD-3-Clause"

[lib]
crate-type = ["staticlib", "cdylib"]

[dependencies]
binaryninja = { workspace = true }
binaryninjacore-sys.workspace = true
log = "0.4"
dashmap = { version = "6.1", features = ["rayon"]}
once_cell = "1.20"
thiserror = "2.0"
10 changes: 0 additions & 10 deletions plugins/workflow_objc/Constants.h

This file was deleted.

Loading
Loading