Skip to main content
Ghidra is a free and open-source reverse engineering tool developed by the NSA. It provides excellent support for analyzing iOS Mach-O binaries and includes powerful scripting capabilities for automation.

Setting Up Ghidra for iOS

1

Install Ghidra

Download Ghidra from the official repository and install Java JDK 17 or later.
# Extract Ghidra
unzip ghidra_10.x_PUBLIC_*.zip
cd ghidra_10.x_PUBLIC
./ghidraRun
2

Install Swift Command-Line Tools

For Swift demangling support, ensure Swift is installed:
# Swift comes with Xcode Command Line Tools
xcode-select --install

# Verify installation
xcrun swift-demangle --help
3

Configure Ghidra Scripts

Copy the iOS reverse engineering scripts to your Ghidra scripts directory:
# Default Ghidra user scripts directory
cp SwiftNameDemangler.py ~/ghidra_scripts/
cp SwizzlingDetector.py ~/ghidra_scripts/

Loading Mach-O Binaries

1

Create a New Project

  1. Launch Ghidra
  2. File → New Project → Non-Shared Project
  3. Choose a project directory and name
2

Import the Binary

# Extract the IPA file
unzip YourApp.ipa

# Locate the binary
cd Payload/YourApp.app/
file YourApp  # Verify it's a Mach-O binary
Import Payload/YourApp.app/YourApp into Ghidra via File → Import File.
3

Analyze the Binary

  1. Double-click the imported file in the project window
  2. When prompted, click “Yes” to analyze
  3. In the Analysis Options dialog:
    • Enable “Objective-C” analyzer
    • Enable “Decompiler Parameter ID” for better decompilation
    • Click “Analyze”
Initial analysis may take several minutes for large iOS applications.

Using the Swift Demangler Script

The SwiftNameDemangler.py script automatically demangles Swift symbols in your Ghidra project, making the code much more readable.

How It Works

The script:
  • Iterates through all functions and labels in the binary
  • Calls swift-demangle on mangled Swift names
  • Renames symbols with human-readable names
  • Preserves original names in comments
# Demangles Swift class, function, and variable names
# @author LaurieWired
# @category Swift

# NOTES:
# Requires Swift to be installed on the machine
# Takes some time to run for larger applications

from ghidra.program.model.listing import Function
from ghidra.program.model.symbol import SymbolType
from java.lang import System
import subprocess

def demangle_swift_name(mangled_name):
    os_name = System.getProperty("os.name").lower()
    
    if "mac" in os_name:
        cmd = 'xcrun swift-demangle --simplified --compact'
        mangled_name = "'{}'".format(mangled_name)
    else:
        cmd = 'swift-demangle --simplified --compact'
    
    proc = subprocess.Popen(cmd, shell=True, 
                          stdout=subprocess.PIPE, 
                          stdin=subprocess.PIPE)
    proc.stdin.write(mangled_name)
    proc.stdin.close()
    demangled = proc.stdout.read().strip()
    proc.wait()
    
    return demangled

Running the Script

1

Open Script Manager

In Ghidra’s CodeBrowser window:
  • Window → Script Manager (or press Ctrl+Shift+S)
2

Locate the Script

  • Filter scripts by typing “Swift” in the search box
  • Find SwiftNameDemangler.py in the list
3

Execute the Script

  • Select the script and click the green “Run” button
  • Monitor progress in the Console window
  • The script will print each renamed symbol
The Swift demangler script can take 5-15 minutes on large applications with many Swift symbols. Be patient and monitor the Console for progress.

Example Output

Renaming functions
Original: _$s8MyApp12LoginManagerC13authenticateyyF, New: MyApp.LoginManager.authenticate
Original: _$s8MyApp4UserV5emailSSvg, New: MyApp.User.email.getter

Renaming labels. May take some time...
Original: _$s8MyApp9ConstantsV6apiURLSSvpZ, New: MyApp.Constants.apiURL

Detecting Method Swizzling

The SwizzlingDetector.py script identifies potential method swizzling, a common technique used in iOS malware and some legitimate apps for runtime method modification.

What It Detects

The script searches for calls to these Objective-C runtime functions:
  • method_exchangeImplementations - Swaps two method implementations
  • class_getInstanceMethod - Retrieves an instance method (often used before swizzling)
  • class_getClassMethod - Retrieves a class method
  • method_setImplementation - Directly sets a method’s implementation
# Detects whether an app is using swizzling and prints all references
# @author LaurieWired
# @category iOS

from ghidra.program.model.symbol import SymbolType

def find_swizzling():
    swizzling_methods = [
        "method_exchangeImplementations",
        "class_getInstanceMethod",
        "class_getClassMethod",
        "method_setImplementation"
    ]
    
    swizzling_symbols = []
    for symbol in currentProgram.getSymbolTable().getAllSymbols(True):
        if symbol.getSymbolType() == SymbolType.FUNCTION and \
           any(method in symbol.getName() for method in swizzling_methods):
            swizzling_symbols.append(symbol)
    
    if not swizzling_symbols:
        print("No swizzling found")
        return
    
    for swizzling_symbol in swizzling_symbols:
        references = list(currentProgram.getReferenceManager()
                        .getReferencesTo(swizzling_symbol.getAddress()))
        
        if not references:
            print("Swizzling method {} located at address {}, but had no references"
                  .format(swizzling_symbol.getName(), 
                         swizzling_symbol.getAddress()))
            continue
        
        print("Swizzling method {} located at address {}, with references:"
              .format(swizzling_symbol.getName(), 
                     swizzling_symbol.getAddress()))
        for ref in references:
            print("Address: {}".format(ref.getFromAddress()))

find_swizzling()

Running the Detection Script

1

Open Script Manager

Window → Script Manager in Ghidra CodeBrowser
2

Run SwizzlingDetector.py

  • Search for “Swizzling” in the filter
  • Run SwizzlingDetector.py
  • Check the Console for results
3

Investigate References

If swizzling is detected:
  1. Note the addresses printed in the Console
  2. Navigate to each address using Go → Go To (G key)
  3. Analyze the surrounding code to understand what’s being swizzled

Example Output

Swizzling method _method_exchangeImplementations located at address 001a2f40, with references:
Address: 001b3c88
Address: 001b4120

Swizzling method _class_getInstanceMethod located at address 001a2f60, with references:
Address: 001b3c80
Address: 001b4118
Method swizzling isn’t inherently malicious. Many legitimate apps and frameworks (like analytics SDKs) use it for hooking and monitoring. Always analyze the context.

Advanced Workflows

Analyzing Encrypted Binaries

1

Check for Encryption

otool -l YourApp | grep cryptid
# cryptid 1 = encrypted, cryptid 0 = decrypted
2

Decrypt Using Frida

Use tools like frida-ios-dump to decrypt the binary from a jailbroken device:
frida-ios-dump -H <device-ip> -u <bundle-id>
3

Import Decrypted Binary

Import the decrypted binary into Ghidra for analysis

Identifying Key Functions

  1. Search → For Strings (Ctrl+Shift+S)
  2. Filter for interesting strings (API endpoints, keys, etc.)
  3. Right-click → References → Show References to Address
  4. Navigate to the function using that string

Tips and Best Practices

  • Disable unused analyzers in Analysis Options to speed up initial analysis
  • For very large binaries, consider analyzing only specific sections
  • Close the Decompiler view when not needed to reduce memory usage
  • Run SwiftNameDemangler.py early in your analysis
  • Use File → Parse C Source to import header files for better type information
  • Enable the “Objective-C” analyzer for proper class and method detection
  • Use Ghidra Server for team-based reverse engineering
  • Export analysis as XML for sharing specific findings
  • Document findings using Bookmarks (Ctrl+D) and comments
  • Write custom scripts to automate repetitive tasks
  • Use the Flat Program API for simpler scripting
  • Check existing scripts in the Script Manager before writing new ones

IDA Pro

Commercial alternative with excellent iOS support

Hopper

macOS-native disassembler with great UI

Frida

Dynamic instrumentation for runtime analysis

LLDB

Debugging companion for Ghidra analysis

Resources

Build docs developers (and LLMs) love