<aside> 🌟
安全检测有很多类型,但现在越狱大多采用root-hide方式,故一些类型检测已失效。
</aside>
root-hide 环境被检测的有如下类型:
详细代码参照
SecuScope项目
GitHub - cheng-ren/SecuScope: iOS 逆向安全桩App
internal class EmulatorChecker {
static func runInEmulator() -> Bool {
return checkCompile() || checkRuntime()
}
private static func checkRuntime() -> Bool {
return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil
}
private static func checkCompile() -> Bool {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}
}
typealias CheckResult = (passed: Bool, failMessage: String)
private static func canOpenUrlFromList(urlSchemes: [String]) -> CheckResult {
for urlScheme in urlSchemes {
if let url = URL(string: urlScheme) {
if UIApplication.shared.canOpenURL(url) {
return(false, "\\(urlScheme) URL scheme detected")
}
}
}
return (true, "")
}
static func checkURLSchemes() -> CheckResult {
let urlSchemes = [
"cydia://",
"activator://",
"undecimus://",
"sileo://",
"zbra://",
"filza://"
]
return canOpenUrlFromList(urlSchemes: urlSchemes)
}
private static func checkExistenceOfSuspiciousFiles() -> CheckResult {
var paths = [
"/var/mobile/Library/Preferences/ABPattern", // A-Bypass
"/usr/lib/ABDYLD.dylib", // A-Bypass,
"/usr/lib/ABSubLoader.dylib", // A-Bypass
"/usr/sbin/frida-server", // frida
"/etc/apt/sources.list.d/electra.list", // electra
"/etc/apt/sources.list.d/sileo.sources", // electra
"/.bootstrapped_electra", // electra
"/usr/lib/libjailbreak.dylib", // electra
"/jb/lzma", // electra
"/.cydia_no_stash", // unc0ver
"/.installed_unc0ver", // unc0ver
"/jb/offsets.plist", // unc0ver
"/usr/share/jailbreak/injectme.plist", // unc0ver
"/etc/apt/undecimus/undecimus.list", // unc0ver
"/var/lib/dpkg/info/mobilesubstrate.md5sums", // unc0ver
"/Library/MobileSubstrate/MobileSubstrate.dylib",
"/jb/jailbreakd.plist", // unc0ver
"/jb/amfid_payload.dylib", // unc0ver
"/jb/libjailbreak.dylib", // unc0ver
"/usr/libexec/cydia/firmware.sh",
"/var/lib/cydia",
"/etc/apt",
"/private/var/lib/apt",
"/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/Sileo.app",
"/var/binpack",
"/Library/PreferenceBundles/LibertyPref.bundle",
"/Library/PreferenceBundles/ShadowPreferences.bundle",
"/Library/PreferenceBundles/ABypassPrefs.bundle",
"/Library/PreferenceBundles/FlyJBPrefs.bundle",
"/Library/PreferenceBundles/Cephei.bundle",
"/Library/PreferenceBundles/SubstitutePrefs.bundle",
"/Library/PreferenceBundles/libhbangprefs.bundle",
"/usr/lib/libhooker.dylib",
"/usr/lib/libsubstitute.dylib",
"/usr/lib/substrate",
"/usr/lib/TweakInject",
"/var/binpack/Applications/loader.app", // checkra1n
"/Applications/FlyJB.app", // Fly JB X
"/Applications/Zebra.app", // Zebra
"/Library/BawAppie/ABypass", // ABypass
"/Library/MobileSubstrate/DynamicLibraries/SSLKillSwitch2.plist", // SSL Killswitch
"/Library/MobileSubstrate/DynamicLibraries/PreferenceLoader.plist", // PreferenceLoader
"/Library/MobileSubstrate/DynamicLibraries/PreferenceLoader.dylib", // PreferenceLoader
"/Library/MobileSubstrate/DynamicLibraries", // DynamicLibraries directory in general
"/var/mobile/Library/Preferences/me.jjolano.shadow.plist"
]
// These files can give false positive in the emulator
if !EmulatorChecker.runInEmulator() {
paths += [
"/bin/bash",
"/usr/sbin/sshd",
"/usr/libexec/ssh-keysign",
"/bin/sh",
"/etc/ssh/sshd_config",
"/usr/libexec/sftp-server",
"/usr/bin/ssh"
]
}
for path in paths {
if FileManager.default.fileExists(atPath: path) {
return (false, "Suspicious file exists: \\(path)")
} else if let result = FileChecker.checkExistenceOfSuspiciousFilesViaStat(path: path) {
return result
} else if let result = FileChecker.checkExistenceOfSuspiciousFilesViaFOpen(
path: path,
mode: .readable
) {
return result
} else if let result = FileChecker.checkExistenceOfSuspiciousFilesViaAccess(
path: path,
mode: .readable
) {
return result
}
}
return (true, "")
static func checkSuspiciousFilesCanBeOpened() -> CheckResult {
var paths = [
"/.installed_unc0ver",
"/.bootstrapped_electra",
"/Applications/Cydia.app",
"/Library/MobileSubstrate/MobileSubstrate.dylib",
"/etc/apt",
"/var/log/apt"
]
// These files can give false positive in the emulator
if !EmulatorChecker.runInEmulator() {
paths += [
"/bin/bash",
"/usr/sbin/sshd",
"/usr/bin/ssh"
]
}
for path in paths {
if FileManager.default.isReadableFile(atPath: path) {
return (false, "Suspicious file can be opened: \\(path)")
} else if let result = FileChecker.checkExistenceOfSuspiciousFilesViaFOpen(
path: path,
mode: .writable
) {
return result
} else if let result = FileChecker.checkExistenceOfSuspiciousFilesViaAccess(
path: path,
mode: .writable
) {
return result
}
}
return (true, "")
}
static func checkRestrictedDirectoriesWriteable() -> CheckResult {
let paths = [
"/",
"/root/",
"/private/",
"/jb/"
]
if FileChecker.checkRestrictedPathIsReadonlyViaStatvfs(path: "/") == false {
return (false, "Restricted path '/' is not Read-Only")
} else if FileChecker.checkRestrictedPathIsReadonlyViaStatfs(path: "/") == false {
return (false, "Restricted path '/' is not Read-Only")
} else if FileChecker.checkRestrictedPathIsReadonlyViaGetfsstat(name: "/") == false {
return (false, "Restricted path '/' is not Read-Only")
}
// If library won't be able to write to any restricted directory the return(false, ...) is never reached
// because of catch{} statement
for path in paths {
do {
let pathWithSomeRandom = path + UUID().uuidString
try "Jailbroken?".write(
toFile: pathWithSomeRandom,
atomically: true,
encoding: String.Encoding.utf8
)
// clean if succesfully written
try FileManager.default.removeItem(atPath: pathWithSomeRandom)
return (false, "Wrote to restricted path: \\(path)")
} catch {}
}
return (true, "")
}