iOS Hacking with otool: A Step-by-Step Guide for Security Pros

Raj Prasad Kuiri

“Ever wondered how hackers extract secrets from iOS apps? Meet otool — the powerful tool for dissecting iOS binaries like a pro. If you’re into iOS security, this guide is a must-read!”

otool — Object File Display Tool for macOS/iOS

otool is a command-line utility on macOS and iOS used for analyzing object files, libraries, and executables. It’s useful for reverse engineering iOS applications, especially when inspecting binaries for security analysis and exploitation

📌 otool Checklist for iOS Pentesting

Open the terminal and take the ssh of your Iphone.

Command:- ssh root@<IP>

cd /var/containers/Bundle/Application/<APP_ID>/<app>

1️. Check Linked Libraries

otool -L <binary>

Findings:

Look for insecure or third-party libraries.

Identify dependencies on security-related libraries (e.g., libcrypto, libssl).

2️. Check Position Independent Executable (PIE)

otool -hv <binary>

Findings:

Look for PIE in the flags section.

If missing, the binary is vulnerable to memory corruption exploits.

3️. Check Stack Canary Protection (SSP)

otool -Iv <binary> | grep stack

Findings:

Look for _stack_chk_guard or _stack_chk_fail.

If missing, the binary lacks protection against stack overflow attacks.

4️. Check for ARC (Automatic Reference Counting)

otool -Iv <binary> | grep _objc_release

Findings:

Memory management vulnerabilities (e.g., use-after-free) might exist if ARC is missing.

5️. Check for Encryption (FairPlay DRM)

otool -l <binary> | grep crypt

Findings:

cryptid 1 → Encrypted (App Store binary).

cryptid 0 → Not encrypted (can be directly analyzed).

6️. Check for NX (No-Execute) Bit / DEP (Data Execution Prevention)

otool -lv <binary> | grep -A 5 LC_SEGMENT

Findings:

If __TEXT is r-x and __DATA is rw-, NX is enabled (good).

If disabled, memory corruption exploits become easier.

7️. Check for Code-Signing

codesign -dvvv <binary>

Findings:

Verifies whether the app is properly signed.

If unsigned or improperly signed, it may be modifiable.

8️. Check for Debug Symbols and Symbols Exposure

nm <binary> | grep “ U “

Findings:

Debug symbols expose function names useful for reverse engineering.

Look for sensitive function names like decrypt, password, etc.

9️. Check for RPATH and @rpath Usage (Dylib Hijacking Risk)

otool -l <binary> | grep -A 5 RPATH

Findings:

If @rpath is present, it could be abused for dylib injection attacks.

10. Check Objective-C Class and Method Names

otool -oV <binary>

Findings:

Extracts Objective-C class and method names.

Helps in identifying sensitive API calls.

11. Checking for Weak Hashing Algorithms

otool -Iv <app> | grep -w _CC_MD5

otool -Iv <app> | grep -w _CC_SHA1

otool -tv /path/to/binary | grep -iE “MD5|SHA1”

Findings:

Common Weak Hashing Functions to Look For:

CC_MD5

CC_SHA1

CC_SHA1_Init, CC_SHA1_Update, CC_SHA1_Final

If CC_MD5 or CC_SHA1 appears, the app is using weak hashing and should be replaced with SHA-256 or SHA-512.

12. Checking for Deprecated/Banned APIs

otool -Iv <app> | grep -w _stat

otool -Iv <app> | grep -w _sscanf

otool -Iv <app> | grep -w _strncpy

otool -Iv <app> | grep -w _strle

otool -tv /path/to/binary | grep -iE “system|exec|fork|dlopen|dlsym|getpw|strcpy|strcat|sprintf”

Findings:

Apple bans certain APIs due to security risks, such as:

system()

exec(), execve()

fork()

dlopen(), dlsym()

getpwuid(), getpwnam()

strcpy(), strcat(), sprintf()

If system() is present, the app is using command execution, which is risky.

13. Checking for Insecure Random Number Functions

otool -tv /path/to/binary | grep -iE “rand|srand|random”

Findings:

Insecure Functions:

rand()

srand()

random()

Secure Alternative:

SecRandomCopyBytes()

14. Checking for Insecure Memory Functions

otool -tv /path/to/binary | grep -iE “memcpy|memmove|strcpy|strcat|sprintf|gets”

Findings:

Insecure Functions:

strcpy()

strcat()

gets()

sprintf()

Secure Alternatives:

strncpy()

strlcpy()

snprintf()

memset_s()

📌 Bonus Checks

💡 Check Hardcoded Strings:

strings <binary> | grep -i “password\|token\|api”

Findings:

Look for hardcoded API keys, secrets, and sensitive info.

💡 Check App Entitlements:

codesign -d — entitlements — <binary>

Findings:

Look for excessive permissions (get-task-allow, com.apple.security.application-groups).

I have written a script which will automate all the above key security checks for iOS pentesting using otool

How to use this script

1️⃣ Save the script as otool_checker.sh

nano otool_checker.sh

Paste the script inside and save (CTRL+X, Y, Enter).

2️⃣ Give execution permission

chmod +x otool_checker.sh

3️⃣ Run the script on an iOS binary

./otool_checker.sh <binary_file>

#!/bin/bash

# Check if a binary file is provided
if [ $# -ne 1 ]; then
echo "Usage: $0 <binary>"
exit 1
fi

BINARY=$1

echo "======================================"
echo "🔍 Enhanced iOS Binary Security Check"
echo "======================================"

# 1️⃣ Check Linked Libraries
echo -e "\n📌 Checking Linked Libraries..."
otool -L "$BINARY"

# 2️⃣ Check Position Independent Executable (PIE)
echo -e "\n📌 Checking PIE Support..."
PIE_CHECK=$(otool -hv "$BINARY" | grep PIE)
if [ -z "$PIE_CHECK" ]; then
echo "❌ PIE is NOT enabled! Binary is vulnerable to memory corruption attacks."
else
echo "✅ PIE is enabled."
fi

# 3️⃣ Check Stack Canary Protection (SSP)
echo -e "\n📌 Checking Stack Canary Protection..."
STACK_CANARY=$(otool -Iv "$BINARY" | grep stack_chk)
if [ -z "$STACK_CANARY" ]; then
echo "❌ Stack Canary is NOT enabled! Binary is vulnerable to buffer overflow attacks."
else
echo "✅ Stack Canary is enabled."
fi

# 4️⃣ Check for ARC (Automatic Reference Counting)
echo -e "\n📌 Checking ARC (Automatic Reference Counting)..."
ARC_CHECK=$(otool -Iv "$BINARY" | grep _objc_release)
if [ -z "$ARC_CHECK" ]; then
echo "❌ ARC is NOT enabled! There may be memory management vulnerabilities."
else
echo "✅ ARC is enabled."
fi

# 5️⃣ Check for Encryption (FairPlay DRM)
echo -e "\n📌 Checking Encryption Status..."
CRYPTID=$(otool -l "$BINARY" | grep cryptid | awk '{print $2}')
if [ "$CRYPTID" == "1" ]; then
echo "🔒 The binary is encrypted (FairPlay DRM enabled)."
else
echo "✅ The binary is NOT encrypted. Ready for analysis."
fi

# 6️⃣ Check for NX (No-Execute) Bit / DEP
echo -e "\n📌 Checking NX (No-Execute) Bit..."
NX_CHECK=$(otool -lv "$BINARY" | grep -A 5 LC_SEGMENT | grep __TEXT)
if [[ "$NX_CHECK" == *"r-x"* ]]; then
echo "✅ NX (DEP) is enabled."
else
echo "❌ NX (DEP) is NOT enabled! Memory corruption exploits are possible."
fi

# 7️⃣ Check for RPATH and @rpath Usage (Dylib Hijacking Risk)
echo -e "\n📌 Checking RPATH (Dylib Hijacking Risk)..."
RPATH_CHECK=$(otool -l "$BINARY" | grep -A 5 RPATH)
if [ -z "$RPATH_CHECK" ]; then
echo "✅ No @rpath found. Safe from dylib hijacking."
else
echo "⚠️ @rpath found! There might be a risk of dylib hijacking."
echo "$RPATH_CHECK"
fi

# 8️⃣ Check for Debug Symbols
echo -e "\n📌 Checking for Debug Symbols..."
DEBUG_SYMBOLS=$(nm "$BINARY" | grep " U ")
if [ -z "$DEBUG_SYMBOLS" ]; then
echo "✅ No debug symbols found."
else
echo "⚠️ Debug symbols found! Could help in reverse engineering."
echo "$DEBUG_SYMBOLS"
fi

# 9️⃣ Check Objective-C Class and Method Names
echo -e "\n📌 Extracting Objective-C Class and Method Names..."
otool -oV "$BINARY" | grep "name ="

# 🔟 Check for Weak Hashing Algorithms
echo -e "\n📌 Checking for Weak Hashing Algorithms (MD5, SHA-1)..."
HASH_CHECK=$(otool -Iv "$BINARY" | grep -E 'CC_MD5|CC_SHA1')
if [ -z "$HASH_CHECK" ]; then
echo "✅ No weak hashing algorithms detected."
else
echo "❌ Weak hashing algorithms found! Consider using SHA-256 or better."
echo "$HASH_CHECK"
fi

# 🔟+1 Check for Deprecated/Banned APIs
echo -e "\n📌 Checking for Deprecated/Banned APIs..."
BANNED_APIS=$(otool -Iv "$BINARY" | grep -E 'gets|strcpy|strcat|getpwuid|getpwnam|system|popen|sprintf|vsprintf')
if [ -z "$BANNED_APIS" ]; then
echo "✅ No banned/deprecated APIs found."
else
echo "❌ Banned APIs found! These can lead to security vulnerabilities."
echo "$BANNED_APIS"
fi

# 🔟+2 Check for Random Functions
echo -e "\n📌 Checking for Random Number Generation Functions..."
RANDOM_FUNCTIONS=$(otool -Iv "$BINARY" | grep -E 'rand|srand|random')
if [ -z "$RANDOM_FUNCTIONS" ]; then
echo "✅ No weak random functions detected."
else
echo "⚠️ Weak random functions detected! Ensure strong randomness using arc4random()."
echo "$RANDOM_FUNCTIONS"
fi

# 🔟+3 Check for Unsafe Memory Functions
echo -e "\n📌 Checking for Unsafe Memory Functions..."
MEMORY_FUNCTIONS=$(otool -Iv "$BINARY" | grep -E 'malloc|free|memcpy|memmove|bzero')
if [ -z "$MEMORY_FUNCTIONS" ]; then
echo "✅ No unsafe memory functions detected."
else
echo "⚠️ Unsafe memory functions detected! Ensure secure memory management."
echo "$MEMORY_FUNCTIONS"
fi

echo -e "\n✅ Security Check Complete!"

Have you used otool before? Share your experience in the comments!

Do you want me to cover another iOS pentesting topic next? do comments!

Thank you for reading !!

Do follow and subscribe for new upcoming blogs via mail on Medium

connect with me over LinkedIn

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Written by Raj Prasad Kuiri

Offensive Security | Web, Mobile & API Pentesting | Network & Cloud Security | Red Teaming

Responses (1)

Write a response

Informational article

--