Unduh PDF: 2022_C00C00R00CON_jailbreak.pdf
Tanpa JailBreak
Dengan ptrace (lldb / frida) → aplikasi memerlukan hak get-task-allow
Dengan memasukkan kode frida → aplikasi perlu dikemas ulang
Dalam kedua kasus tersebut, Anda harus mengundurkan diri dari permohonan
tetapi memiliki banyak efek samping:
ID Tim yang Berbeda
File diubah
Dengan JailBreak
Mekanisme deteksi jailbreak ditambahkan untuk membalikkan pertahanan rekayasa agar menjalankan aplikasi pada perangkat yang sudah di-jailbreak menjadi lebih sulit. Hal ini menghalangi beberapa alat dan teknik yang sering digunakan oleh para reverse engineer. Seperti kebanyakan jenis pertahanan lainnya, deteksi jailbreak tidak terlalu efektif, namun pemeriksaan yang tersebar di seluruh kode sumber aplikasi dapat meningkatkan efektivitas skema anti-gangguan secara keseluruhan.
Resiko keamanan perusahaan yang ditimbulkan oleh senyawa jailbreak di hadapan alat yang dapat membantu pengguna dengan mudah menghindari metode deteksi jailbreak yang umum. Pengguna dapat mengunduh tweak aplikasi apa pun seperti Spotify++ langsung dari toko aplikasi pihak ketiga Cydia. Banyak aplikasi menyediakan deteksi jailbreak, begitu pula banyak aplikasi media dan layanan keuangan yang masing-masing ingin membatasi pembajakan konten dan penyusupan akun. Sayangnya, deteksi jailbreak ini bergantung pada kombinasi pengujian yang relatif mudah dan dapat dihindari, seperti:
Keterbatasan mendasar pada pengujian ini dan pengujian deteksi serupa adalah bahwa sebagai pengujian di sisi klien, pengujian tersebut dapat diakses, direkayasa ulang, dan dihindari oleh penyerang. Selain itu, aplikasi yang melakukan tes deteksi jailbreak ini (misalnya aplikasi MDM) harus melalui proses peninjauan aplikasi Apple, sehingga membatasi cakupan data yang dapat dikumpulkan untuk menganalisis status jailbreak perangkat. Mari kita lihat sekilas:
Periksa file dan direktori yang biasanya terkait dengan jailbreak, seperti:
//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 "
]
}
Paling sering, ini diperiksa menggunakan
-(BOOL)fileExistsAtPath:(NSString*)
metode jalur di NSFileManager atau FileManager.default.fileExists(atPath: path)
. Namun, ada juga aplikasi yang menggunakan fungsi C tingkat rendah seperti fopen(), stat(), atau access().
Cara lain untuk memeriksa mekanisme jailbreaking adalah dengan mencoba menulis ke lokasi yang berada di luar sandbox aplikasi. Anda dapat melakukan ini dengan meminta aplikasi mencoba membuat file, misalnya, di direktori /private
. Jika file berhasil dibuat, perangkat telah di-jailbreak.
Metode ini terdiri dari pemeriksaan izin file dan direktori tertentu pada sistem. Lebih banyak direktori yang memiliki akses tulis pada perangkat yang sudah di-jailbreak dibandingkan pada perangkat yang tidak dikompromikan. Salah satu contohnya adalah partisi root, yang awalnya hanya memiliki izin baca. Jika ditemukan memiliki izin baca dan tulis berarti perangkat sudah di-jailbreak. Ada berbagai cara untuk melakukan pemeriksaan ini seperti menggunakan fungsi NSFileManager dan C seperti statfs().
Cepat:
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
}
Tujuan-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 ];
}
Ada berbagai cara untuk melakukan pemeriksaan ini seperti menggunakan fungsi NSFileManager dan C seperti statfs(), open(), utimes(), stat(), pathconf(), stat64(), fopen().
Anda dapat memeriksa penangan protokol dengan mencoba membuka URL Cydia. Toko aplikasi Cydia, yang secara default diinstal oleh hampir semua alat jailbreaking, menginstal pengendali protokol cydia://.
Cepat:
if let url = URL ( string : " cydia://package/com.example.package " ) , UIApplication . shared . canOpenURL ( url ) {
// Device is jailbroken
}
Tujuan-C:
if ([[UIApplication sharedApplication ] canOpenURL: [ NSURL URLWithString: @" cydia://package/com.example.package " ]]){
// Device is jailbroken
}
Pemeriksaan sederhana ini dapat diakses, direkayasa ulang, dan dihindari oleh penyerang.
ptrace ( PT_DENY_ATTACH );
void try_kill () {
const int pid = getpid ();
int ret = kill (pid, 0 );
}
Menurut halaman manual kill ( man 2 kill
), sinyal 0
digunakan untuk memeriksa apakah pid
yang diberikan pada parameter pertama benar-benar ada.
[…] Nilai 0, bagaimanapun, akan menyebabkan dilakukannya pengecekan kesalahan (tanpa sinyal yang dikirim). Ini dapat digunakan untuk memeriksa validitas pid.
Operasi mematikan ini diikuti dengan pemeriksaan 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)
Kita dapat memeriksa integritas tanda tangan biner kita. Pemeriksaan ini dimulai dengan membuka biner aplikasi utama dari disk, mencari hingga urutan kSecCodeMagicEmbeddedSignature 0xfade0cc0
, membaca hak dan menghitung checksum.
Segmen penandatanganan kode berisi struktur superlob, yang berisi blob lain dengan tipe berbeda. Struktur keduanya didefinisikan dalam beberapa kode Apple sumber terbuka lainnya:
/*
* 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;
Super blob hanya berisi beberapa keajaiban, panjang seluruh bagian penandatanganan kode, jumlah blob, dan array indeks untuk blob tersebut. Berbagai sihir pengidentifikasi gumpalan didefinisikan dalam file ini:
/*
* 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 */
};
Misalnya, biner ps
iOS memiliki empat gumpalan konten yang mengikuti superlob awal:
Ini masing-masing adalah:
0xfade0c02
), yang dapat Anda temukan karena memiliki nama biner yang memenuhi syarat com.apple.ps
di dalamnya.0xfade0c01
).0xfade7171
).0xfade0b01
).Cobalah untuk menghentikan aplikasi setelah waktu tunggu yang lama dan jangan keluar langsung dari tempat deteksi jailbreak.
fork()
Proses fork. Sandboxd tidak menolak kemampuan aplikasi untuk menggunakan fork(), popen(), atau fungsi C lainnya untuk membuat proses anak pada perangkat yang sudah di-jailbreak. Namun, sandboxd secara eksplisit menolak proses forking pada perangkat yang tidak di-jailbreak. Oleh karena itu, dengan memeriksa pid yang dikembalikan pada fork(), aplikasi dapat mengetahui apakah suatu perangkat disusupi. Jika fork berhasil, aplikasi dapat menyimpulkan bahwa fork tersebut berjalan pada perangkat yang sudah di-jailbreak.
system()
Memanggil fungsi system() dengan argumen NULL pada perangkat yang tidak di-jailbreak akan menghasilkan 0. Melakukan hal yang sama pada perangkat yang sudah di-jailbreak akan menghasilkan 1. Ini karena fungsi tersebut akan memeriksa apakah /bin/sh ada, dan hanya ada di perangkat yang sudah di-jailbreak.
Koneksi loopback SSH. Karena sangat besarnya porsi perangkat yang di-jailbreak yang telah menginstal OpenSSH, beberapa aplikasi mencoba membuat koneksi ke 127.0.0.1 pada port 22. Jika koneksi berhasil, berarti OpenSSH telah diinstal dan dijalankan, yang membuktikan perangkat tersebut telah di-jailbreak.
Periksa loopback untuk 22 (OpenSSH) dan 44 (checkra1n) port yang terbuka.
Metode deteksi ini dimulai dengan memanggil fungsi seperti _dyld_image_count()
dan _dyld_get_image_name()
untuk melihat dylib apa yang sedang dimuat. Metode ini sangat sulit untuk ditambal secara dinamis karena tambalan itu sendiri adalah bagian dari dylib.
/usr/lib/substitute-inserter.dylib
misalnya
Dapat menggunakan dlopen / pemindaian memori / struktur internal dyld dll.
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
}
Periksa integritas kode
Cobalah untuk mendeteksi frida
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
}
Secara umum, semakin rumit pendeteksian jailbreak, semakin sulit untuk dideteksi dan dilewati. Kesalahan paling umum saat menerapkan deteksi jailbreak sering kali terletak pada implementasinya sendiri.
Kita sering menemukan aplikasi yang memiliki deteksi jailbreak yang bagus, tetapi implementasinya ada dalam satu fungsi yang mengembalikan nilai true atau false tergantung pada apakah perangkat tersebut sudah di-jailbreak. Dalam kasus ini, kami melewati deteksi jailbreak dengan menggunakan Cycript atau alat serupa untuk membalikkan nilai yang dikembalikan dari fungsi deteksi.
Dalam praktiknya, deteksi jailbreak terbaik menggabungkan beberapa teknik dan mengintegrasikannya ke dalam fungsi lain sehingga tidak dapat dilewati dengan mudah.
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/