Reverse Engineering
forge analysis: class-dump, strings, symbols, security posture, and version diffing for any decrypted IPA.
General-purpose, read-only static analysis of any .ipa — not tied to a
specific patch set or app. Built on the same Mach-O/ObjC analysis engine
(ipa_forge/machO/objc.py) that forge hooks uses to verify hook targets;
see Architecture for how the two relate. Every
command accepts --app-dir <Payload/App.app> in place of --ipa to skip
re-extraction while iterating, same as forge hooks.
Scope boundary
Two things are deliberately not implemented, by design rather than oversight:
- FairPlay/App Store DRM decryption. Every command here assumes an
already-decrypted
.ipa, exactly like the rest of ipa-forge. - Instruction-level disassembly/decompilation. Static metadata (classes, strings, symbols) only — no capstone/Ghidra-style disassembly.
forge analysis classdump
Dumps the app's Objective-C runtime metadata as .h-style class-dump text:
every class (superclass, protocol conformance, ivars, properties, full
method signatures reconstructed from type encodings), protocol
declarations, and categories.
Prop
Type
forge analysis classdump --ipa App.ipa
forge analysis classdump --ipa App.ipa --class MainPlayerViewController
forge analysis classdump --ipa App.ipa --search '^App' --output dump.h--class/--search restrict output to matching classes only (protocols
and categories are omitted in that case, matching forge hooks extract's
--class/--search). A class/superclass defined in another image (system
frameworks, or a framework you didn't point the tool at) is reported as
«external» — the same honest-reporting convention forge hooks uses,
rather than guessing.
The type-encoding decoder (ipa_forge/analysis/type_encoding.py) is
best-effort: structs/unions render as just their tag name (no field
expansion), and truly exotic encodings fall back to the raw string. Good
enough to read; not good enough to regenerate a compilable header.
forge analysis strings
Printable-ASCII string extraction across every executable in the bundle (main + frameworks + dylibs + extensions), tagged with which binary each string came from.
Prop
Type
forge analysis strings --ipa App.ipa --min-len 6
forge analysis strings --ipa App.ipa --search 'https?://' --binary MainExecutablePipe to grep for anything --search doesn't cover directly — no output
cap (unlike the GUI's /analysis page, which caps at 2000 matches for
browser sanity).
forge analysis symbols
Linked libraries and imported/exported symbols for one executable in the
bundle (otool -L + nm, backed by LIEF's structured symbol table instead
of parsing text).
Prop
Type
forge analysis symbols --ipa App.ipa
forge analysis symbols --ipa App.ipa --binary SomeFrameworkforge analysis security
Read-only build/security posture for one executable: PIE, an
encryption-flag check (LC_ENCRYPTION_INFO's cryptid — detection
only, never decryption), stack protector, an ARC heuristic
(_objc_storeStrong/_objc_release imported — not definitive), min-OS,
and platform.
Prop
Type
forge analysis security --ipa App.ipaforge analysis diff
Survey of what changed between two builds of the same app: classes and
protocols added/removed, per-class method churn, and Info.plist key
changes. Purely informational — exit code is always 0 regardless of
findings.
Prop
Type
forge analysis diff --old App_1.0.ipa --new App_2.0.ipaforge analysis diff vs. forge hooks diff
This is broader but shallower than forge hooks diff
(see Usage): forge hooks diff only re-checks one patch definition's declared hook targets
and is a pass/fail gate (exit 1 on a required-hook regression); forge analysis diff surveys everything that changed, independent of any patch
set, and never fails the exit code. Use forge hooks diff to gate a patch
set's CI; use forge analysis diff to understand what changed before
writing the patch set in the first place.
Entitlements are intentionally not diffed here: reading them requires
shelling out to codesign/security, and signing/backend.py is the only
module allowed to do that (Architecture's hard
constraint) — a real entitlements diff belongs in that subsystem, not in
this read-only, signing-independent package.
The web GUI (forge gui → /analysis)
The same four views (class-dump, strings, security, diff), browsable
without installing the CLI: forge gui → open the link in the main
patcher page's subtitle, or navigate directly to
http://127.0.0.1:8765/analysis. Unlike the main patcher page, /analysis
needs no patch-set setup and works on any IPA — upload it and pick an
action. Strings output is capped at 2000 matches in the browser (the CLI has
no such cap). Single-user, local-only, same as the
patch-flow page — see Usage.