M9: Reverse Engineering
M9: Reverse Engineering
Mobile apps can be reverse engineered to understand logic, extract secrets, or find vulnerabilities.
// iOS - Anti-reverse engineering techniques
class AntiReverseEngineering {
// Obfuscation techniques
class CodeObfuscation {
// String obfuscation
private let obfuscatedAPIKey = [0x41, 0x42, 0x43, 0x44, 0x45] // "ABCDE" obfuscated
func getAPIKey() -> String {
return obfuscatedAPIKey.map { Character(UnicodeScalar($0)) }.map(String.init).joined()
}
// Control flow obfuscation
func performSensitiveOperation(input: Int) -> Int {
var result = input
// Confuse static analysis
for i in 0..<10 {
if i % 2 == 0 {
result = complexCalculation1(result)
} else {
result = complexCalculation2(result)
}
// Add dummy operations
let dummy = Int.random(in: 0...100)
_ = dummy * 2 + 1
}
return result ^ 0xDEADBEEF
}
// Symbol stripping (done at build time)
// Use Xcode build settings:
// - Strip Debug Symbols During Copy: YES
// - Strip Linked Product: YES
// - Strip Style: All Symbols
// Binary packing (using external tools)
// - UPX
// - Custom packers
}
// Runtime protection
class RuntimeProtection {
// Detect common reverse engineering tools
func detectReverseEngineeringTools() -> Bool {
let suspiciousLibraries = [
"FridaGadget",
"cynject",
"libcycript",
"SubstrateLoader"
]
for i in 0..<_dyld_image_count() {
if let name = _dyld_get_image_name(i) {
let imageName = String(cString: name)
for lib in suspiciousLibraries {
if imageName.contains(lib) {
return true
}
}
}
}
return false
}
// Anti-debugging with ptrace
func enableAntiDebugging() {
#if !DEBUG
// Prevent debugging
ptrace(PT_DENY_ATTACH, 0, 0, 0)
// Additional check using sysctl
var info = kinfo_proc()
var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var size = MemoryLayout<kinfo_proc>.stride
if sysctl(&mib, u_int(mib.count), &info, &size, nil, 0) == 0 {
if (info.kp_proc.p_flag & P_TRACED) != 0 {
exit(0)
}
}
#endif
}
// Method swizzling detection
func detectMethodSwizzling() -> Bool {
let originalMethod = class_getInstanceMethod(
UIApplication.self,
#selector(UIApplication.sendAction(_:to:from:for:))
)
let originalImplementation = method_getImplementation(originalMethod!)
// Store original implementation address
let expectedAddress = unsafeBitCast(
UIApplication.sendAction(_:to:from:for:),
to: IMP.self
)
return originalImplementation != expectedAddress
}
}
}