The place in the attack chain: why reverse an iOS application
Reverse-engineering of iOS applications is not an end in itself. This is reconnaissance before attacking the server infrastructure. The acquatic examines binary for the sake of specific things: extract secrets (API keys, tokens, URL of internal services), understand business logic (endpoints, query parameters, client validation), bypass protective mechanisms (SS-pinning, jailbreak detection, biometrics) and prepare a server attack (ase-ups API, business logic).
In terms of MITRE ATT&CK, the chain looks like this: obtaining and deciphering an IPA file - Deobfuscate/Decode Files or Information (T1140, Defense Evasion) - call the native analysis functions through the Native API (T1106, Execution) - interception of methods through the Credential API Hooking (T1056.004, Collection / Credential Access) in runtime. When you modify and rewrite the application, Dylib Hijacking is added (T1574.004, Defense Evasion / Execution)

For SOC, the output is direct: iOS-app reversus is the preparatory stage for the attack on the backend. If the attacker extracts API key and endpoint - the next step is already in your server infrastructure.
Adjustments to the environment
To reproduce the technicians below (within the authorized audit):
• OS: macOS 13+ (Ventura or new) for class-dump, otool, Hopper
• Device: jailbreaked iPhone - checkra1n (chips A7-A11) or palera1n (checkm8-devices A8-A11, iOS 15-17). Minimum 3 GB of free memory
• Frida 16.x: pip install frida-toolson the host, frida-server of the corresponding version on the device
• class-dump: original class-dump (nygard) is outdated; for modern iOS, forks (class-dumpdyld, ICDump) or built-in features of Hopper/Ghidra. Swift class-dump extracts partially - you will need swift-demangle
• Disassembler: Hopper Disassembler v5 (Personal/Commercial license, current prices for hopperapp.com) or Ghidra (free)
• Proxy: Burp Suite to intercept traffic after bypassing pinning
• SSH: OpenSSH on the device via Cydia/Sileo
For Blue Team, which needs to assess the scale of the threat without the assembly of a full stand: macOS with class-dump and Hopper is enough for the eye - a static analysis of the IPA does not require a physical device.
Static analysis of iOS IPA files: what an attacker finds in the first hour
IPA and binary analysis Mach-O
IPA - ZIP-archive with a predictable structure. Inside Payload/<AppName>.app/ lies the main Mach-O binary (ARM64-code), next to - Info.plist, frameworks, resources. The first actions of the attacker take minutes:
Unpacking: unzip app.ipa -d output/. Definition of architecture: otool -hv <binary> - in the output will be ARM64 (modern devices), less often fat binary with armv7 + arm64. List of dependencies: otool -L <binary> - shows the linked frameworks. The presence of CryptoKit, Security.framework, CommonCrypto indicates work with cryptography. Non-standard .dylibs are potentially interesting third-party libraries.
Extracting lines: strings <binary> | grep -iE 'api|key|secret|token|http' - in unsecured applications gives out a backend URL, keys and sometimes passwords in plain text. The Alternative - rabin2 -zz <binary> from the radare2 set (current version 6.1.5, the project is actively supported).
According to the data OWASP MASVS (MASVS-CODE section), production-assembly should not contain debug symbols and unencrypted sensitive lines. In practice, a significant part of the audited applications fails this check.
class-dump iOS: reading Objective-C interfaces
class-dump extracts class headlines from the Mach-O binary. For Objective-C works almost perfectly: runtime stores all the names of classes, methods and properties. For pure Swift, the situation is worse - Swift symbols use name mangling and require swift-demangle or class-dump-swift. “The older version of class-dump won’t work if there is Swift code within the binary”“An older version of class-dump won’t work if the Binary File has a Swift code” - therefore, the architecture and language should be determined in advance through otool.
Typical output of class-dump for applications on Objective-C:
assword: - target for Frida-hook.
If in the Damp of the classes you can see the names of the validatePurchase, checkLicenseKey, bypassDetection - the application, in fact, comes with documentation for the attacker. OWASP MASSVS-RESILIENCE recommends obfuscation of symbols and strip debug information. In fact, few people do it.
Hopper disassembler iOS: business logic navigation
The Hopper Disassemble (and a free Ghidra alternative) allows you to move from a list of methods to understanding their internal logic. As Y-Security notes in the guide to OWASP MASTG, “no decompilers are available for iOS apps”“There is no decompiler for iOS apps” In a complete sense, a pseudocode from Ghidra/Hopper is close to the original, but not equivalent to it. For defenders, this means: obfuscation slows down the attacker, but does not stop.
On the ARM64-dysassembler, I usually look for three things.
The first is the branch in security checks. Methods isJailbroken, checkIntegrity. Typical pattern: a series of calls fileExistsAtPath: with ways /Applications/Cydia.app, /usr/sbin/sshd, /Library/MobileSubstrate/MobileSubstrate.dylib. If the method returns BOOL - in ARM64 is one cmp + b.newhich patches in seconds.
The second is crypto-stops. Lines transmitted to CCCrypt, SecKeyEncrypt or custom encryption functions. Keys are often cast as static strings in the section __cstring. Cross-references from these lines lead directly to encryption functions.
The third is network challenges. Xrefs from lines with URL to methods NSURLSession. This gives a complete map of API end-points, including internal, not publicly documented.
The difference between the analysis of Objective-C and Swift is fundamental: Objective-C binaries retain the full names of selectors in __objc_methname, which makes the discusable code almost readable. Swift-binders use name mangling (view names $s7MyApp14ViewControllerC), and Hopper/Ghidra restore them in part. The application on Swift receives the basic level of obfuscation "free", but rely on it as protection - an illusion.
Trendy tooling Frida iOS: interception in runtime
Detection and hardening: what to control on the protection side
Server Detection: What SOC Sees
The reverse of the application occurs on the device of the attacker - directly SOC will not see it. But the consequences are noticeable in server logs:
1. Anomalous User-Agent and Headlines - After bypassing the pinning, traffic goes through Burp Suite or mitmproxy. User-Agent may not match the valid application value. Correlation rule: analt to API-queries with non-standard UA with valid authorization token
2. Replay and parameter manipulation - if the attacker understood the API structure through the reverse, it substitutes someone else's ID, changes the amounts, overlaps the parameters. Correlation: surge 4xx/5xxx of errors from one token in a short period
3. Using the withdrawn or hardcoded keys - if there was a chirping API key in binaryk, which you rotated, and requests with it continue to come - this is a straight IOC
4. Geographical anomalies - requests from one user simultaneously from different geolocations
5. The Apple App Attestation option allows the server to verify that the request came from a legitimate device with an unchanged application. No attestation marker when checked on - IOC
Client checks and their limitations
Customer checks slow down the attacker, but do not stop. Frida bypasses any check - the question is only in the time spent:

For SOC, server-side detection rules are critical - client checks buy time, but do not give guarantees.
Hardening-checked by OWASP MASVS-RESILIENCE
The checklist for transferring to the team development - specific tasks, not abstract wishes:
1. Strip debug symbols before release - strip -S <binary>, enable Strip Debug Symbols in Xcode Build Settings
2. Encrypt sensitive lines in runtime: not let key = "abc123", and decryption from the encrypted array at the first request (MASVS-STORAGE)
3. Use finalfor critical classes in Swift - prevents swizzling through inheritance
4. Implement multi-layered jailbreak-detection: not only file check, but also sandbox integrity, fork() check, dyld-check
5. Implement ptrace(PT_DENY_ATTACH) and sysctl-check-tests - blocks lldb/gdb (walking requires hook syscal), but does not affect the Frida, which uses the Mach API (T1622, Debugger Evasion)
6. Connect the Apple App Attest for server confidence integrity is the only check with a high threshold
7. Implement a pinning certificate through NSURLSessionDelegatewith a test of SPKI-hash (MASVS-NETWORK)
8. Do not keep the secrets in bjinary: Keychain for tokens, runtime-receiving configuration from the server (MASVS-STORAGE)
9. Apply control flow obfuscation for critical methods - complicates the analysis in Hopper/Ghidra (protection against T1027)
10. Hold a self-audit of the IPA before the release: drive away class-dumpand stringson your own assembly - if you see secrets, the attacker will also see them
The cheat sheet covers the requirements of OWASP MASS-RESILIENCE and MASVS-CODE. Pass it on to developers with specific tickets - the abstract wording "improve security" does not work.
Conclusion
Two years ago, I started to include the “to-first secret” metric reports in the mobile application top test reports – how many minutes from receiving the IPA to retrieving the first sensitive value. The median for corporate iOS applications is 25 minutes. With basic obfuscation - 2-3 hours. With full protection of the level of MASSVS-RESIICE L2 - from 8 hours to "failed for the allotted time of the audit."
The problem is not the attacker’s tools: class-dump, Hopper and Frida are available to everyone. The problem is that most development teams perceive customer protection as a “after” task. The five-way Jailbreak detection to check the path to Cydia is not protection, but complacency. The attacker bypasses it faster than the developer wrote.
The only working strategy is not to trust the client at all: server validation of each parameter, App Attest, key rotation, API-anomaly monitoring. Client checks are a retarder, no barrier. And if SOC does not monitor the API on the opportunized application patterns (non-standard UA, replay, ID manipulation), you will learn about the incident from the client’s ticket, not an aerate.
Reverse-engineering of iOS applications is not an end in itself. This is reconnaissance before attacking the server infrastructure. The acquatic examines binary for the sake of specific things: extract secrets (API keys, tokens, URL of internal services), understand business logic (endpoints, query parameters, client validation), bypass protective mechanisms (SS-pinning, jailbreak detection, biometrics) and prepare a server attack (ase-ups API, business logic).
In terms of MITRE ATT&CK, the chain looks like this: obtaining and deciphering an IPA file - Deobfuscate/Decode Files or Information (T1140, Defense Evasion) - call the native analysis functions through the Native API (T1106, Execution) - interception of methods through the Credential API Hooking (T1056.004, Collection / Credential Access) in runtime. When you modify and rewrite the application, Dylib Hijacking is added (T1574.004, Defense Evasion / Execution)

For SOC, the output is direct: iOS-app reversus is the preparatory stage for the attack on the backend. If the attacker extracts API key and endpoint - the next step is already in your server infrastructure.
Adjustments to the environment
To reproduce the technicians below (within the authorized audit):
• OS: macOS 13+ (Ventura or new) for class-dump, otool, Hopper
• Device: jailbreaked iPhone - checkra1n (chips A7-A11) or palera1n (checkm8-devices A8-A11, iOS 15-17). Minimum 3 GB of free memory
• Frida 16.x: pip install frida-toolson the host, frida-server of the corresponding version on the device
• class-dump: original class-dump (nygard) is outdated; for modern iOS, forks (class-dumpdyld, ICDump) or built-in features of Hopper/Ghidra. Swift class-dump extracts partially - you will need swift-demangle
• Disassembler: Hopper Disassembler v5 (Personal/Commercial license, current prices for hopperapp.com) or Ghidra (free)
• Proxy: Burp Suite to intercept traffic after bypassing pinning
• SSH: OpenSSH on the device via Cydia/Sileo
For Blue Team, which needs to assess the scale of the threat without the assembly of a full stand: macOS with class-dump and Hopper is enough for the eye - a static analysis of the IPA does not require a physical device.
Static analysis of iOS IPA files: what an attacker finds in the first hour
IPA and binary analysis Mach-O
IPA - ZIP-archive with a predictable structure. Inside Payload/<AppName>.app/ lies the main Mach-O binary (ARM64-code), next to - Info.plist, frameworks, resources. The first actions of the attacker take minutes:
Unpacking: unzip app.ipa -d output/. Definition of architecture: otool -hv <binary> - in the output will be ARM64 (modern devices), less often fat binary with armv7 + arm64. List of dependencies: otool -L <binary> - shows the linked frameworks. The presence of CryptoKit, Security.framework, CommonCrypto indicates work with cryptography. Non-standard .dylibs are potentially interesting third-party libraries.
Extracting lines: strings <binary> | grep -iE 'api|key|secret|token|http' - in unsecured applications gives out a backend URL, keys and sometimes passwords in plain text. The Alternative - rabin2 -zz <binary> from the radare2 set (current version 6.1.5, the project is actively supported).
According to the data OWASP MASVS (MASVS-CODE section), production-assembly should not contain debug symbols and unencrypted sensitive lines. In practice, a significant part of the audited applications fails this check.
class-dump iOS: reading Objective-C interfaces
class-dump extracts class headlines from the Mach-O binary. For Objective-C works almost perfectly: runtime stores all the names of classes, methods and properties. For pure Swift, the situation is worse - Swift symbols use name mangling and require swift-demangle or class-dump-swift. “The older version of class-dump won’t work if there is Swift code within the binary”“An older version of class-dump won’t work if the Binary File has a Swift code” - therefore, the architecture and language should be determined in advance through otool.
Typical output of class-dump for applications on Objective-C:
What the attacker sees: the names of methods (isJailbroken, setupCertificatePinning) provide an accurate map of the protective mechanisms. Type Properties apiSecret - direct reference to hardcoded secret. Method loginWithUsernameCode:
@interface AuthenticationManager : NSObject
+ (BOOL)validateTokenNSString *)token;
- (void)loginWithUsernameNSString *)user password
NSString *)pass;
- (BOOL)isJailbroken;
- (void)setupCertificatePinning;
@property (nonatomic, copy) NSString *apiBaseURL;
@property (nonatomic, copy) NSString *apiSecret;
@end
If in the Damp of the classes you can see the names of the validatePurchase, checkLicenseKey, bypassDetection - the application, in fact, comes with documentation for the attacker. OWASP MASSVS-RESILIENCE recommends obfuscation of symbols and strip debug information. In fact, few people do it.
Hopper disassembler iOS: business logic navigation
The Hopper Disassemble (and a free Ghidra alternative) allows you to move from a list of methods to understanding their internal logic. As Y-Security notes in the guide to OWASP MASTG, “no decompilers are available for iOS apps”“There is no decompiler for iOS apps” In a complete sense, a pseudocode from Ghidra/Hopper is close to the original, but not equivalent to it. For defenders, this means: obfuscation slows down the attacker, but does not stop.
On the ARM64-dysassembler, I usually look for three things.
The first is the branch in security checks. Methods isJailbroken, checkIntegrity. Typical pattern: a series of calls fileExistsAtPath: with ways /Applications/Cydia.app, /usr/sbin/sshd, /Library/MobileSubstrate/MobileSubstrate.dylib. If the method returns BOOL - in ARM64 is one cmp + b.newhich patches in seconds.
The second is crypto-stops. Lines transmitted to CCCrypt, SecKeyEncrypt or custom encryption functions. Keys are often cast as static strings in the section __cstring. Cross-references from these lines lead directly to encryption functions.
The third is network challenges. Xrefs from lines with URL to methods NSURLSession. This gives a complete map of API end-points, including internal, not publicly documented.
The difference between the analysis of Objective-C and Swift is fundamental: Objective-C binaries retain the full names of selectors in __objc_methname, which makes the discusable code almost readable. Swift-binders use name mangling (view names $s7MyApp14ViewControllerC), and Hopper/Ghidra restore them in part. The application on Swift receives the basic level of obfuscation "free", but rely on it as protection - an illusion.
Trendy tooling Frida iOS: interception in runtime
Detection and hardening: what to control on the protection side
Server Detection: What SOC Sees
The reverse of the application occurs on the device of the attacker - directly SOC will not see it. But the consequences are noticeable in server logs:
1. Anomalous User-Agent and Headlines - After bypassing the pinning, traffic goes through Burp Suite or mitmproxy. User-Agent may not match the valid application value. Correlation rule: analt to API-queries with non-standard UA with valid authorization token
2. Replay and parameter manipulation - if the attacker understood the API structure through the reverse, it substitutes someone else's ID, changes the amounts, overlaps the parameters. Correlation: surge 4xx/5xxx of errors from one token in a short period
3. Using the withdrawn or hardcoded keys - if there was a chirping API key in binaryk, which you rotated, and requests with it continue to come - this is a straight IOC
4. Geographical anomalies - requests from one user simultaneously from different geolocations
5. The Apple App Attestation option allows the server to verify that the request came from a legitimate device with an unchanged application. No attestation marker when checked on - IOC
Client checks and their limitations
Customer checks slow down the attacker, but do not stop. Frida bypasses any check - the question is only in the time spent:

For SOC, server-side detection rules are critical - client checks buy time, but do not give guarantees.
Hardening-checked by OWASP MASVS-RESILIENCE
The checklist for transferring to the team development - specific tasks, not abstract wishes:
1. Strip debug symbols before release - strip -S <binary>, enable Strip Debug Symbols in Xcode Build Settings
2. Encrypt sensitive lines in runtime: not let key = "abc123", and decryption from the encrypted array at the first request (MASVS-STORAGE)
3. Use finalfor critical classes in Swift - prevents swizzling through inheritance
4. Implement multi-layered jailbreak-detection: not only file check, but also sandbox integrity, fork() check, dyld-check
5. Implement ptrace(PT_DENY_ATTACH) and sysctl-check-tests - blocks lldb/gdb (walking requires hook syscal), but does not affect the Frida, which uses the Mach API (T1622, Debugger Evasion)
6. Connect the Apple App Attest for server confidence integrity is the only check with a high threshold
7. Implement a pinning certificate through NSURLSessionDelegatewith a test of SPKI-hash (MASVS-NETWORK)
8. Do not keep the secrets in bjinary: Keychain for tokens, runtime-receiving configuration from the server (MASVS-STORAGE)
9. Apply control flow obfuscation for critical methods - complicates the analysis in Hopper/Ghidra (protection against T1027)
10. Hold a self-audit of the IPA before the release: drive away class-dumpand stringson your own assembly - if you see secrets, the attacker will also see them
The cheat sheet covers the requirements of OWASP MASS-RESILIENCE and MASVS-CODE. Pass it on to developers with specific tickets - the abstract wording "improve security" does not work.
Conclusion
Two years ago, I started to include the “to-first secret” metric reports in the mobile application top test reports – how many minutes from receiving the IPA to retrieving the first sensitive value. The median for corporate iOS applications is 25 minutes. With basic obfuscation - 2-3 hours. With full protection of the level of MASSVS-RESIICE L2 - from 8 hours to "failed for the allotted time of the audit."
The problem is not the attacker’s tools: class-dump, Hopper and Frida are available to everyone. The problem is that most development teams perceive customer protection as a “after” task. The five-way Jailbreak detection to check the path to Cydia is not protection, but complacency. The attacker bypasses it faster than the developer wrote.
The only working strategy is not to trust the client at all: server validation of each parameter, App Attest, key rotation, API-anomaly monitoring. Client checks are a retarder, no barrier. And if SOC does not monitor the API on the opportunized application patterns (non-standard UA, replay, ID manipulation), you will learn about the incident from the client’s ticket, not an aerate.