PDF 다운로드: 2022_C00C00R00CON_jailbreak.pdf
JailBreak 없이
ptrace(lldb / frida) 사용 → 앱에 get-task-allow 자격이 필요합니다.
frida 코드 삽입 → 앱을 다시 패키징해야 함
두 경우 모두 신청을 취소해야 합니다.
하지만 부작용이 너무 많아요:
다른 팀 ID
파일이 수정되었습니다.
JailBreak으로
탈옥 감지 메커니즘이 리버스 엔지니어링 방어에 추가되어 탈옥된 장치에서 앱을 실행하기가 더 어려워졌습니다. 이는 리버스 엔지니어가 사용하기를 좋아하는 일부 도구와 기술을 차단합니다. 대부분의 다른 유형의 방어와 마찬가지로 탈옥 감지는 그 자체로는 그다지 효과적이지 않지만 앱 소스 코드 전체에 분산 검사를 수행하면 전반적인 변조 방지 체계의 효율성을 향상시킬 수 있습니다.
사용자가 일반적인 탈옥 탐지 방법을 쉽게 회피할 수 있도록 도와주는 도구에 직면하여 탈옥 화합물로 인해 발생하는 기업 보안 위험. 사용자는 타사 앱 스토어 Cydia에서 직접 Spotify++와 같은 앱 조정을 다운로드할 수 있습니다. 콘텐츠 불법 복제 및 계정 손상을 각각 제한하려는 많은 미디어 및 금융 서비스 앱과 마찬가지로 많은 애플리케이션이 탈옥 감지 기능을 제공합니다. 불행하게도 이러한 탈옥 탐지는 다음과 같이 상대적으로 간단하고 회피 가능한 테스트의 조합에 의존합니다.
이러한 탐지 테스트와 유사한 탐지 테스트의 근본적인 한계는 클라이언트 측 테스트로서 공격자가 액세스하고, 역엔지니어링하고, 회피할 수 있다는 것입니다. 또한 이러한 탈옥 감지 테스트를 수행하는 앱(예: MDM 앱)은 Apple의 앱 검토 프로세스를 거쳐야 하며, 기기의 탈옥 상태를 분석하기 위해 수집할 수 있는 데이터의 범위를 제한합니다. 그것들을 간단히 살펴보겠습니다:
다음과 같이 일반적으로 탈옥과 관련된 파일 및 디렉터리를 확인하세요.
//suspicious system and app paths to check
private static var suspicousAppandSystemPaths : [ String ] {
return [
" /usr/sbin/frida-server " ,
" /etc/apt/sources.list.d/electra.list " ,
" /etc/apt/sources.list.d/sileo.sources " ,
" /.bootstrapped_electra " ,
" /usr/lib/libjailbreak.dylib " ,
" /jb/lzma " ,
" /.cydia_no_stash " ,
" /.installed_unc0ver " ,
" /jb/offsets.plist " ,
" /usr/share/jailbreak/injectme.plist " ,
" /etc/apt/undecimus/undecimus.list " ,
" /var/lib/dpkg/info/mobilesubstrate.md5sums " ,
" /Library/MobileSubstrate/MobileSubstrate.dylib " ,
" /jb/jailbreakd.plist " ,
" /jb/amfid_payload.dylib " ,
" /jb/libjailbreak.dylib " ,
" /usr/libexec/cydia/firmware.sh " ,
" /var/lib/cydia " ,
" /etc/apt " ,
" /private/var/lib/apt " ,
" /private/var/Users/ " ,
" /var/log/apt " ,
" /Applications/Cydia.app " ,
" /private/var/stash " ,
" /private/var/lib/apt/ " ,
" /private/var/lib/cydia " ,
" /private/var/cache/apt/ " ,
" /private/var/log/syslog " ,
" /private/var/tmp/cydia.log " ,
" /Applications/Icy.app " ,
" /Applications/MxTube.app " ,
" /Applications/RockApp.app " ,
" /Applications/blackra1n.app " ,
" /Applications/SBSettings.app " ,
" /Applications/FakeCarrier.app " ,
" /Applications/WinterBoard.app " ,
" /Applications/IntelliScreen.app " ,
" /private/var/mobile/Library/SBSettings/Themes " ,
" /Library/MobileSubstrate/CydiaSubstrate.dylib " ,
" /System/Library/LaunchDaemons/com.ikey.bbot.plist " ,
" /Library/MobileSubstrate/DynamicLibraries/Veency.plist " ,
" /Library/MobileSubstrate/DynamicLibraries/LiveClock.plist " ,
" /System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist " ,
" /Applications/Cydia.app " ,
" /Applications/blackra1n.app " ,
" /Applications/FakeCarrier.app " ,
" /Applications/Icy.app " ,
" /Applications/IntelliScreen.app " ,
" /Applications/MxTube.app " ,
" /Applications/RockApp.app " ,
" /Applications/SBSettings.app " ,
" /Applications/WinterBoard.app "
]
}
대부분의 경우 이러한 사항은 다음을 사용하여 확인됩니다.
-(BOOL)fileExistsAtPath:(NSString*)
NSFileManager 또는 FileManager.default.fileExists(atPath: path)
의 경로 메서드. 그러나 fopen(), stat() 또는 access()와 같은 하위 수준 C 함수를 사용하는 응용 프로그램도 있습니다.
탈옥 메커니즘을 확인하는 또 다른 방법은 애플리케이션의 샌드박스 외부에 있는 위치에 쓰기를 시도하는 것입니다. 예를 들어 응용 프로그램이 /private
디렉터리에 파일을 생성하도록 하여 이를 수행할 수 있습니다. 파일이 성공적으로 생성되면 장치가 탈옥된 것입니다.
이 방법은 시스템의 특정 파일 및 디렉터리에 대한 권한을 확인하는 것으로 구성됩니다. 탈옥된 장치에서는 손상되지 않은 장치보다 더 많은 디렉터리에 쓰기 액세스 권한이 있습니다. 이에 대한 한 가지 예는 원래 읽기 권한만 있는 루트 파티션입니다. 읽기 및 쓰기 권한이 있는 것으로 확인되면 장치가 탈옥되었음을 의미합니다. NSFileManager 및 statfs()와 같은 C 함수를 사용하는 등 이러한 검사를 수행하는 다양한 방법이 있습니다.
스위프트:
do {
let pathToFileInRestrictedDirectory = " /private/jailbreak.txt "
try " This is a test. " . write ( toFile : pathToFileInRestrictedDirectory , atomically : true , encoding : String . Encoding . utf8 )
try FileManager . default . removeItem ( atPath : pathToFileInRestrictedDirectory )
// Device is jailbroken
} catch {
// Device is not jailbroken
}
목표-C:
NSError *error;
NSString *stringToBeWritten = @" This is a test. " ;
[stringToBeWritten writeToFile: @" /private/jailbreak.txt " atomically: YES
encoding: NSUTF8StringEncoding error: &error];
if (error == nil ) {
// Device is jailbroken
return YES ;
} else {
// Device is not jailbroken
[[ NSFileManager defaultManager ] removeItemAtPath: @" /private/jailbreak.txt " error: nil ];
}
NSFileManager 및 statfs(), open(), utimes(), stat(), pathconf(), stat64(), fopen()과 같은 C 함수를 사용하는 등 이러한 검사를 수행하는 다양한 방법이 있습니다.
Cydia URL을 열려고 시도하여 프로토콜 핸들러를 확인할 수 있습니다. 거의 모든 탈옥 도구가 기본적으로 설치되는 Cydia 앱 스토어는 cydia:// 프로토콜 핸들러를 설치합니다.
스위프트:
if let url = URL ( string : " cydia://package/com.example.package " ) , UIApplication . shared . canOpenURL ( url ) {
// Device is jailbroken
}
목표-C:
if ([[UIApplication sharedApplication ] canOpenURL: [ NSURL URLWithString: @" cydia://package/com.example.package " ]]){
// Device is jailbroken
}
이 간단한 검사는 공격자가 액세스하고, 리버스 엔지니어링하고, 회피할 수 있습니다.
ptrace ( PT_DENY_ATTACH );
void try_kill () {
const int pid = getpid ();
int ret = kill (pid, 0 );
}
kill 맨 페이지( man 2 kill
)에 따르면 신호 0
은 첫 번째 매개변수에 제공된 pid
실제로 존재하는지 확인하는 데 사용됩니다.
[...] 그러나 값이 0이면 오류 검사가 수행됩니다(신호가 전송되지 않음). 이는 pid의 유효성을 확인하는 데 사용될 수 있습니다.
이 종료 작업 뒤에는 PTRACE
확인이 이어집니다.
inline bool ptrace_detect () {
int32_t opt[ 4 ] = {
CTL_KERN,
KERN_PROC,
KERN_PROC_PID,
getpid (),
};
kinfo_proc info;
sysctl (opt, 4 , &info, sizeof (kinfo_proc), nullptr , 0 );
return info. kp_proc . p_flag & P_TRACED;
}
getppid() == 1
getfsstat64(), statvfs()
fcntl(F_ADDSIGS)
csops(CS_OPS_MARKKILL)
바이너리 서명의 무결성을 확인할 수 있습니다. 이 검사는 디스크에서 기본 앱 바이너리를 열고 kSecCodeMagicEmbeddedSignature 시퀀스 0xfade0cc0
까지 검색하여 자격을 읽고 체크섬을 계산하는 것으로 시작됩니다.
코드 서명 세그먼트에는 슈퍼블롭 구조가 포함되어 있으며, 이 구조 자체에는 다양한 유형의 다른 블롭이 포함되어 있습니다. 두 가지의 구조는 좀 더 오픈 소스 Apple 코드에 정의되어 있습니다.
/*
* Structure of an embedded-signature SuperBlob
*/
typedef struct __BlobIndex {
uint32_t type; /* type of entry */
uint32_t offset; /* offset of entry */
} CS_BlobIndex;
typedef struct __SuperBlob {
uint32_t magic; /* magic number */
uint32_t length; /* total length of SuperBlob */
uint32_t count; /* number of index entries following */
CS_BlobIndex index[]; /* (count) entries */
/* followed by Blobs in no particular order as indicated by offsets in index */
} CS_SuperBlob;
슈퍼 블롭에는 몇 가지 마법, 전체 코드 서명 섹션의 길이, 블롭 수 및 해당 블롭에 대한 인덱스 배열이 포함됩니다. 다양한 식별 blob 매직이 이 파일에 정의되어 있습니다.
/*
* Magic numbers used by Code Signing
*/
enum {
kSecCodeMagicRequirement = 0xfade0c00 , /* single requirement */
kSecCodeMagicRequirementSet = 0xfade0c01 , /* requirement set */
kSecCodeMagicCodeDirectory = 0xfade0c02 , /* CodeDirectory */
kSecCodeMagicEmbeddedSignature = 0xfade0cc0 , /* single-architecture embedded signature */
kSecCodeMagicDetachedSignature = 0xfade0cc1 , /* detached multi-architecture signature */
kSecCodeMagicEntitlement = 0xfade7171 , /* entitlement blob */
};
예를 들어, iOS ps
바이너리에는 초기 슈퍼블롭 다음에 4개의 콘텐츠 블롭이 있습니다.
이는 각각 다음과 같습니다.
0xfade0c02
). 여기에는 정규화된 바이너리 이름 com.apple.ps
포함되어 있으므로 찾을 수 있습니다.0xfade0c01
)0xfade7171
)가 포함된 자격 blob.0xfade0b01
).시간이 많이 초과되면 앱을 중지하고 탈옥 감지 위치에서 직접 종료하지 마십시오.
fork()
프로세스 포크. Sandboxd는 애플리케이션이 fork(), popen() 또는 기타 C 함수를 사용하여 탈옥된 장치에서 하위 프로세스를 생성하는 기능을 거부하지 않습니다. 그러나 sandboxd는 탈옥되지 않은 장치에서 프로세스 분기를 명시적으로 거부합니다. 따라서 애플리케이션은 fork()에서 반환된 pid를 확인하여 장치가 손상되었는지 알 수 있습니다. 포크가 성공하면 앱은 탈옥된 장치에서 실행되고 있다고 추론할 수 있습니다.
system()
탈옥되지 않은 장치에서 NULL 인수를 사용하여 system() 함수를 호출하면 0이 반환됩니다. 탈옥된 장치에서 동일한 작업을 수행하면 1이 반환됩니다. 이는 함수가 /bin/sh가 존재하는지 확인하고 해당 장치에만 존재하기 때문입니다. 탈옥된 장치.
SSH 루프백 연결. OpenSSH가 설치된 탈옥된 장치의 상당 부분으로 인해 일부 응용 프로그램은 포트 22에서 127.0.0.1에 연결을 시도합니다. 연결에 성공하면 OpenSSH가 설치되어 실행 중임을 의미하며 이는 장치가 탈옥되었음을 증명합니다.
22(OpenSSH) 및 44(checkra1n) 열린 포트에 대한 루프백을 확인합니다.
이 감지 방법은 _dyld_image_count()
및 _dyld_get_image_name()
과 같은 함수를 호출하여 현재 로드된 dylib를 확인하는 것으로 시작됩니다. 이 방법은 패치 자체가 dylib의 일부이기 때문에 동적으로 패치하기가 매우 어렵습니다.
예를 들어 /usr/lib/substitute-inserter.dylib
dlopen / 메모리 스캐닝 / dyld 내부 구조 등을 사용할 수 있습니다.
private static func checkDYLD ( ) -> Bool {
let suspiciousLibraries = [
" FridaGadget " ,
" frida " ,
" cynject " ,
" libcycript "
]
for libraryIndex in 0 ..< _dyld_image_count ( ) {
guard let loadedLibrary = String ( validatingUTF8 : _dyld_get_image_name ( libraryIndex ) ) else { continue }
for suspiciousLibrary in suspiciousLibraries {
if loadedLibrary . lowercased ( ) . contains ( suspiciousLibrary . lowercased ( ) ) {
return true
}
}
}
return false
}
코드 무결성 확인
프리다를 감지해 보세요
private static func isFridaRunning ( ) -> Bool {
func swapBytesIfNeeded ( port : in_port_t ) -> in_port_t {
let littleEndian = Int ( OSHostByteOrder ( ) ) == OSLittleEndian
return littleEndian ? _OSSwapInt16 ( port ) : port
}
var serverAddress = sockaddr_in ( )
serverAddress . sin_family = sa_family_t ( AF_INET )
serverAddress . sin_addr . s_addr = inet_addr ( " 127.0.0.1 " )
serverAddress . sin_port = swapBytesIfNeeded ( port : in_port_t ( 27042 ) )
let sock = socket ( AF_INET , SOCK_STREAM , 0 )
let result = withUnsafePointer ( to : & serverAddress ) {
$0 . withMemoryRebound ( to : sockaddr . self , capacity : 1 ) {
connect ( sock , $0 , socklen_t ( MemoryLayout < sockaddr_in > . stride ) )
}
}
if result != - 1 {
return true
}
return false
}
일반적으로 탈옥 감지가 복잡할수록 감지 및 우회가 더 어려워집니다. 탈옥 감지를 구현할 때 가장 흔히 발생하는 실수는 구현 자체에 있는 경우가 많습니다.
우리는 탈옥 감지 기능이 뛰어난 앱을 자주 접하지만, 장치의 탈옥 여부에 따라 true 또는 false를 반환하는 하나의 함수로 구현됩니다. 이러한 경우 Cycript 또는 유사한 도구를 사용하여 탐지 기능의 반환 값을 반전시켜 탈옥 탐지를 우회합니다.
실제로 최고의 탈옥 탐지는 여러 기술을 결합하고 이를 다른 기능에 통합하여 쉽게 우회할 수 없도록 합니다.
https://github.com/mehrankmlf/SecurityKit
https://www.synacktiv.com/sites/default/files/2021-10/2021_sthack_jailbreak.pdf
https://www.romainthomas.fr/post/21-07-pokemongo-anti-frida-jailbreak-bypass/
https://aeonlucid.com/Snapchat-Detection-on-iOS/
https://github.com/AeonLucid/SnapHide
https://redmaple.tech/blogs/macho-files/