判断是否能打开越狱软件
利用URL Scheme来查看是否能够代开比如cydia这些越狱软件
//Check cydia URL hook canOpenURL 来绕过
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.avl.com"]])
{
return YES;
}
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]])
{
return YES;
}
frida-trace -U -f 包名 -m "+[NSURL URLWithString:]"
包名 可以用 frida-ps -Ua来查看, 然后更改生成的js路径脚本
/*
* Auto-generated by Frida. Please modify to match the signature of +[NSURL URLWithString:].
* This stub is currently auto-generated from manpages when available.
*
* For full API reference, see: https://frida.re/docs/javascript-api/
*/
{
/**
* Called synchronously when about to call +[NSURL URLWithString:].
*
* @this {object} - Object allowing you to store state for use in onLeave.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {array} args - Function arguments represented as an array of NativePointer objects.
* For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
* It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
* @param {object} state - Object allowing you to keep state across function calls.
* Only one JavaScript function will execute at a time, so do not worry about race-conditions.
* However, do not use this to store function arguments across onEnter/onLeave, but instead
* use "this" which is an object for keeping state local to an invocation.
*/
onEnter(log, args, state) {
var URLName = ObjC.Object(args[2]);
if(URLName.containsString_) {
if(URLName.containsString_("http://") ||
URLName.containsString_("https://") ||
URLName.containsString_("file://")
) {
} else {
if(URLName.containsString_("://")) {
log(`+[NSURL URLWithString:]` + URLName);
args[2] = ObjC.classes.NSString.stringWithString_("xxxxxx://");
}
}
}
},
/**
* Called synchronously when about to return from +[NSURL URLWithString:].
*
* See onEnter for details.
*
* @this {object} - Object allowing you to access state stored in onEnter.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {NativePointer} retval - Return value represented as a NativePointer object.
* @param {object} state - Object allowing you to keep state across function calls.
*/
onLeave(log, retval, state) {
}
}
判断是否可以访问一些越狱的文件
越狱后会产生额外的文件,通过判断是否存在这些文件来判断是否越狱了,可以用fopen和FileManager两个不同的方法去获取
BOOL fileExist(NSString* path)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = NO;
if([fileManager fileExistsAtPath:path isDirectory:&isDirectory]){
return YES;
}
return NO;
}
BOOL directoryExist(NSString* path)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL isDirectory = YES;
if([fileManager fileExistsAtPath:path isDirectory:&isDirectory]){
return YES;
}
return NO;
}
BOOL canOpen(NSString* path)
{
FILE *file = fopen([path UTF8String], "r");
if(file==nil){
return fileExist(path) || directoryExist(path);
}
fclose(file);
return YES;
}
NSArray* checks = [[NSArray alloc] initWithObjects:@"/Application/Cydia.app",
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
@"/bin/bash",
@"/usr/sbin/sshd",
@"/etc/apt",
@"/usr/bin/ssh",
@"/private/var/lib/apt",
@"/private/var/lib/cydia",
@"/private/var/tmp/cydia.log",
@"/Applications/WinterBoard.app",
@"/var/lib/cydia",
@"/private/etc/dpkg/origins/debian",
@"/bin.sh",
@"/private/etc/apt",
@"/etc/ssh/sshd_config",
@"/private/etc/ssh/sshd_config",
@"/Applications/SBSetttings.app",
@"/private/var/mobileLibrary/SBSettingsThemes/",
@"/private/var/stash",
@"/usr/libexec/sftp-server",
@"/usr/libexec/cydia/",
@"/usr/sbin/frida-server",
@"/usr/bin/cycript",
@"/usr/local/bin/cycript",
@"/usr/lib/libcycript.dylib",
@"/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
@"/System/Library/LaunchDaemons/com.ikey.bbot.plist",
@"/Applications/FakeCarrier.app",
@"/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
@"/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
@"/usr/libexec/ssh-keysign",
@"/usr/libexec/sftp-server",
@"/Applications/blackra1n.app",
@"/Applications/IntelliScreen.app",
@"/Applications/Snoop-itConfig.app"
@"/var/lib/dpkg/info", nil];
//Check installed app
for(NSString* check in checks)
{
if(canOpen(check))
{
return YES;
}
}
frida-trace -U -f 包名 -m "-[NSFileManager fileExistsAtPath:]"
/*
* Auto-generated by Frida. Please modify to match the signature of -[NSFileManager fileExistsAtPath:].
* This stub is currently auto-generated from manpages when available.
*
* For full API reference, see: https://frida.re/docs/javascript-api/
*/
{
/**
* Called synchronously when about to call -[NSFileManager fileExistsAtPath:].
*
* @this {object} - Object allowing you to store state for use in onLeave.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {array} args - Function arguments represented as an array of NativePointer objects.
* For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
* It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
* @param {object} state - Object allowing you to keep state across function calls.
* Only one JavaScript function will execute at a time, so do not worry about race-conditions.
* However, do not use this to store function arguments across onEnter/onLeave, but instead
* use "this" which is an object for keeping state local to an invocation.
*/
onEnter(log, args, state) {
var fileName = ObjC.Object(args[2]);
if(fileName.containsString_) {
if(fileName.containsString_("apt") ||
fileName.containsString_("MobileSubstrate") ||
fileName.containsString_("Cydia") ||
fileName.containsString_("bash") ||
fileName.containsString_("ssh") ||
fileName.containsString_("/bin/sh") ||
fileName.containsString_("Applications") ||
fileName.containsString_("/bin/su") ||
fileName.containsString_("dpkg")
) {
console.log('fileExistsAtPath called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
args[2] = ObjC.classes.NSString.stringWithString_("/xxxxxx");
log(`-[NSFileManager fileExistsAtPath: ${fileName}`);
}
}
//log(`-[NSFileManager fileExistsAtPath: ${fileName}`);
},
/**
* Called synchronously when about to return from -[NSFileManager fileExistsAtPath:].
*
* See onEnter for details.
*
* @this {object} - Object allowing you to access state stored in onEnter.
* @param {function} log - Call this function with a string to be presented to the user.
* @param {NativePointer} retval - Return value represented as a NativePointer object.
* @param {object} state - Object allowing you to keep state across function calls.
*/
onLeave(log, retval, state) {
}
}
关键词检测 :JailBroken 及 JailBreak 等;
使用frida脚本简单干掉:
在启动就注入进去, -f是通过spawn,也就是重启apk注入js文章来源:https://www.toymoban.com/news/detail-507347.html
frida -U -f 包名 --no-pause -l 过越狱检测.js文章来源地址https://www.toymoban.com/news/detail-507347.html
//越狱检测- 简单先将返回1的Nop掉
var resolver = new ApiResolver('objc');
resolver.enumerateMatches('*[* *Jailb*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr), {
onEnter: function (args) {
}, onLeave: function (retval) {
if (retval.toInt32() === 1) {
retval.replace(0);
}
console.log(funcName, retval);
}
});
}, onComplete: function () {
}
});
resolver.enumerateMatches('*[* *JailB*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr), {
onEnter: function (args) {
}, onLeave: function (retval) {
if (retval.toInt32() === 1) {
retval.replace(0);
}
console.log(funcName, retval);
}
});
}, onComplete: function () {
}
});
resolver.enumerateMatches('*[* *jailB*]', {
onMatch: function (match) {
let funcName = match.name;
let funcAddr = match.address;
Interceptor.attach(ptr(funcAddr), {
onEnter: function (args) {
}, onLeave: function (retval) {
if (retval.toInt32() === 1) {
retval.replace(0);
}
console.log(funcName, retval);
}
});
}, onComplete: function () {
}
});
到了这里,关于IOS - 越狱检测的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!