[라이브러리] 탈옥 탐지하는 방법
ChatGPT의 말:
네, iOS(아이폰)와 Android(안드로이드) 폰에서 탈옥(Jailbreak, iOS) / 루팅(Rooting, Android) 탐지 기능을 앱이나 라이브러리 형태로 구현하려면 아래의 핵심 이론과 구현 방법을 반드시 이해해야 합니다.
1. 탈옥/루팅 탐지의 기본 원리
-
iOS: Jailbreak 탐지
-
시스템이 허용하지 않는 파일, 디렉토리, 권한 변경 등을 탐지
-
대표적 증거: Cydia, 탈옥툴 관련 바이너리, 권한상승 등
-
-
Android: Root 탐지
-
su 바이너리, 루팅 앱 설치 여부, 시스템 파티션 변경 등 확인
-
대표적 증거:
/system/xbin/su
, Magisk, Superuser 앱 등
-
2. 탐지 주요 방법 (OS별)
■ iOS 탈옥 탐지 주요 기법
-
파일 시스템 체크
탈옥툴에서 생성하는 경로 존재 여부 확인let jailbreakPaths = [
"/Applications/Cydia.app",
"/Library/MobileSubstrate/MobileSubstrate.dylib",
"/bin/bash",
"/usr/sbin/sshd",
"/etc/apt"
]
func isJailbroken() -> Bool {
for path in jailbreakPaths {
if FileManager.default.fileExists(atPath: path) {
return true
}
}
return false
} -
앱 샌드박스 탈출 여부
func canAccessOutsideSandbox() -> Bool {
let path = "/private/jailbreak.txt"
do {
try "test".write(toFile: path, atomically: true, encoding: .utf8)
return true
} catch {
return false
}
}
-
시스템 API 호출 탐지 (탈옥툴 흔적)
-
탈옥 환경에서만 동작하는 시스템 호출, dylib 주입 등
-
■ Android 루팅 탐지 주요 기법
-
su 바이너리 존재 확인
public boolean isDeviceRooted() {
String[] paths = {
"/system/app/Superuser.apk",
"/system/xbin/su",
"/system/bin/su",
"/system/sbin/su",
"/sbin/su",
"/su/bin/su"
};
for (String path : paths) {
if (new File(path).exists()) return true;
}
return false;
}
-
루팅 앱 설치 여부 (패키지명 체크)
javapublic boolean checkRootApps() {
String[] packages = {
"com.noshufou.android.su",
"eu.chainfire.supersu",
"com.koushikdutta.superuser",
"com.zachspong.temprootremovejb",
"com.ramdroid.appquarantine"
};
PackageManager pm = context.getPackageManager();
for (String pkg : packages) {
try {
pm.getPackageInfo(pkg, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
// 패키지 없음
}
}
return false;
}
-
명령어 실행으로 권한 확인
javapublic boolean canExecuteSu() {
try {
Process process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" });
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
return in.readLine() != null;
} catch (Throwable t) {
return false;
}
}
3. 라이브러리화 구현 방법
iOS (Swift, Objective-C)
-
프레임워크로 만들기
-
위에서 소개한 함수들을 모듈로 만들고, Swift Package, CocoaPods, XCFramework 형태로 배포
-
인터페이스 예시
swiftpublic class JailbreakDetector {
public static func isJailbroken() -> Bool {
// 파일 체크, 샌드박스 체크, dylib 주입 탐지 등 결합
}
}
-
사용 예시
swiftif JailbreakDetector.isJailbroken() {
// 탈옥된 기기
}
-
Android (Kotlin, Java)
-
AAR(Android Archive) 또는 Gradle 라이브러리로 만들기
-
루팅 탐지 함수들을
object RootDetector
또는class RootChecker
등으로 묶어서 모듈화 -
인터페이스 예시
kotlinobject RootDetector {
fun isRooted(context: Context): Boolean {
return checkSuFile() || checkRootApps(context) || canExecuteSu()
}
// 각각 함수는 위에서 설명한 기법 사용
}
-
사용 예시
kotlinif (RootDetector.isRooted(context)) {
// 루팅된 기기
}
-
4. 실제 라이브러리 제작 프로세스
-
공통 코드 작성 (C/C++로도 가능, JNI 활용)
-
내부적으로 보안 우회를 어렵게 하려면, 탐지 로직의 일부를 C/C++로 작성 후 Swift/Kotlin에서 JNI, FFI로 호출
-
-
테스트: 실제 탈옥/루팅 기기와 순정 기기에서 비교 테스트
-
문서화: 앱 개발자가 쉽게 사용할 수 있도록 README, 사용 예시, 보안상 주의사항 등 문서화
-
배포: iOS는 Swift Package, CocoaPods, Android는 JitPack/Gradle 등으로 배포
5. 실제 적용 예시
iOS Swift 라이브러리 예시
public final class JailbreakChecker {
public static func isJailbroken() -> Bool {
// 1. 파일 체크
// 2. 샌드박스 탈출 체크
// 3. 시스템 API 체크
return 파일체크() || 샌드박스체크() || 시스템API체크()
}
}
Android Kotlin 라이브러리 예시
object RootChecker {
fun isRooted(context: Context): Boolean {
return checkSuFiles() || checkRootPackages(context) || canExecuteSuCommand()
}
}
6. 주의사항
-
완벽한 탐지는 불가능: 보안 우회 방법이 계속 진화하므로 100% 탐지는 어렵다. 다양한 탐지 방법을 조합해야 한다.
-
실제 앱에서는 탐지 결과를 서버에 전송하여 조작/위조에 대응
-
탐지 로직을 난독화/암호화하여 공격자가 쉽게 우회하지 못하게 한다.
-
정책상 일부 앱스토어(특히 iOS)는 민감 정보 접근이나 탈옥 탐지에 제한이 있을 수 있음