[Rev] 리버싱 · 작성: 2026-07-19 19:34:18 · 조회 4
iOS는 안드로이드보다 분석 진입 장벽이 조금 더 높다. 앱스토어 배포 바이너리는 애플의 FairPlay DRM으로 암호화되어 있고, 탈옥(Jailbreak)되지 않은 정상 기기에서는 Frida 같은 동적 계측 도구를 붙이는 것 자체가 제한된다. 그래서 iOS 리버싱은 사실상 탈옥된 기기(또는 탈옥 이미지를 쓸 수 있는 시뮬레이터/에뮬레이터)를 전제로 한다.
앱스토어에서 받은 IPA는 실행 파일이 암호화되어 있다. 탈옥된 기기에서 앱을 한 번 실행시키면 iOS가 메모리에 복호화해서 올리는데, 이 시점의 메모리를 덤프하면 복호화된 바이너리를 얻을 수 있다.
python3 dump.py com.example.app
복호화된 바이너리는 Mach-O 포맷이다.
otool -L ./app_binary # 링크된 라이브러리 목록
otool -tv ./app_binary # 디스어셈블 (텍스트 섹션)
class-dump ./app_binary # Objective-C 클래스/메서드 시그니처 덤프
Objective-C로 작성된 부분은 class-dump나 class-dump-z로 클래스/메서드 목록이 거의 헤더 파일 수준으로 복원된다. Swift는 이름이 맹글링(mangling)되어 있고 메타데이터도 달라서 상대적으로 분석이 더 까다롭다 — Hopper나 IDA의 Swift 디맹글링 기능, 또는 swift-demangle 도구를 활용한다.
IDA Pro나 Ghidra, Hopper Disassembler로 디컴파일해서 로직을 읽는 흐름은 다른 플랫폼과 동일하다.
탈옥 기기에 frida-server를 올리면 안드로이드와 거의 같은 방식으로 후킹할 수 있다.
// Objective-C 메서드 후킹
if (ObjC.available) {
const RootCheck = ObjC.classes.SecurityChecker;
Interceptor.attach(RootCheck["- isJailbroken"].implementation, {
onLeave(retval) {
retval.replace(0x0); // NO로 강제
}
});
}
안드로이드와 마찬가지로 Burp를 프록시로 잡고 트래픽을 확인한다. iOS도 NSURLSession의 TrustManager격인 delegate에서 인증서를 검증하는 Pinning이 흔하므로, objection의 iOS용 명령어로 우회를 시도한다.
objection -g com.example.app explore
> ios sslpinning disable
앱이 탈옥 여부를 확인하는 방법은 다양하다 — /Applications/Cydia.app 같은 특정 경로 존재 확인, fork() 성공 여부(샌드박스 우회 가능한지), URL 스킴(cydia://) 오픈 가능 여부 등. objection의 ios jailbreak disable이 흔한 패턴을 커버하고, 안 되면 class-dump로 찾은 탐지 함수를 직접 Frida로 후킹한다.
| 안드로이드 | iOS | |
|---|---|---|
| 배포 파일 암호화 | 없음 (APK 자체는 평문) | 있음 (앱스토어 바이너리, 탈옥 기기에서 덤프 필요) |
| 진입 장벽 | 에뮬레이터로도 대부분 가능 | 탈옥 기기가 사실상 필수 |
| 주요 언어 | Java/Kotlin → DEX (디컴파일 품질 높음) | Objective-C(복원 잘 됨) / Swift(맹글링으로 더 까다로움) |
| 코드 영구 수정 | smali 패치 + 재서명 | 훨씬 까다로움 (코드 서명 정책) — 대부분 Frida 동적 후킹으로 대체 |
iOS는 환경 구축(탈옥 기기 확보, frida-ios-dump 세팅) 자체가 진입 장벽이라, 처음이라면 안드로이드 쪽을 먼저 연습하고 넘어오는 걸 권한다.