泰宁新闻网

爱伪装,爱伪装苹果必须越狱吗

鞋

泰宁新闻网 http://www.tainingxinwen.cn 2020-06-30 09:47 出处:网络
爱伪装,爱伪装苹果必须越狱吗,爱伪装(AWZ)/爱立思(ALS)改机改串一键新机原理分析

爱伪装,爱伪装苹果必须越狱吗,爱伪装(AWZ)/爱立思(ALS)改机改串一键新机原理分析

在第一阶段破解后,仍然是闪退的,此时反调试已经去除,所以可以加调试器看检测点

-[NSBundle executablePath]检测主进程文件是否被修改 _dyld_get_image_name检测tweak模块 sysctl检测进程的p_flag是否有调试器flag isatty检测终端 ioctl(TIOCGWINSZ)检测终端 fopen检测主进程文件是否被修改(在DHPDaemon中) posix_spawn检测/Application/ALS.app下是否存在超过3M的文件(补丁啊)

在IFMagicMainVC的几个按钮handler函数中,存在大量检测代码,这里建议直接自己实现,例如:

void (*old_IFMagicMainVC_appListClick)(Class cls, SEL sel, void* click);
void new_IFMagicMainVC_appListClick(Class cls, SEL sel, void* click) {
 UIStoryboard* board = [UIStoryboard storyboardWithName:@ Main bundle:nil];
 UIViewController* newcontrol = [board instantiateViewControllerWithIdentifier:@ IFApplicationSelectorVC 
 UIViewController* control = (UIViewController*)cls;
 [[control navigationController] pushViewController:newcontrol animated:YES];
void (*old_IFMagicMainVC_backupRecordClick)(Class cls, SEL sel, void* click);
void new_IFMagicMainVC_backupRecordClick(Class cls, SEL sel, void* click) {
 UIStoryboard* board = [UIStoryboard storyboardWithName:@ Main bundle:nil];
 UIViewController* newcontrol = [board instantiateViewControllerWithIdentifier:@ IFMagicBackupVC 
 UIViewController* control = (UIViewController*)cls;
 [[control navigationController] pushViewController:newcontrol animated:YES];
void (*old_IFMagicMainVC_doGoMagicSetting)(Class cls, SEL sel, void* click);
void new_IFMagicMainVC_doGoMagicSetting(Class cls, SEL sel, void* click) {
 UIStoryboard* board = [UIStoryboard storyboardWithName:@ Main bundle:nil];
 UIViewController* newcontrol = [board instantiateViewControllerWithIdentifier:@ IFMagicSettingVC 
 UIViewController* control = (UIViewController*)cls;
 [[control navigationController] pushViewController:newcontrol animated:YES];
void (*old_IFMagicMainVC_paramSettingClick)(Class cls, SEL sel, void* click);
void new_IFMagicMainVC_paramSettingClick(Class cls, SEL sel, void* click) {
 UIStoryboard* board = [UIStoryboard storyboardWithName:@ Main bundle:nil];
 UIViewController* newcontrol = [board instantiateViewControllerWithIdentifier:@ IFMagicDeviceSettingVC 
 UIViewController* control = (UIViewController*)cls;
 [[control navigationController] pushViewController:newcontrol animated:YES];

在第二阶段后,不闪退了,但是显示注册码过期

解密栈字符串,ALS和DHPDaemon几乎全用的栈字符串混淆,蛮体力活的 定位到注册的函数,一方面通过socket通信,用加密本机信息获取软件激活状态,另一方面通过cjson反序列化回写注册状态。 定位get_json_value函数,该函数为c层cjson解析函数,用于从json数据的到key对应的value,该函数刚好位于socket网络通信,解密响应得到json数据后。其中必要重要的key有:ps,vs,hs,ts,as,aes 还原ObjC函数调用关系 system函数会独立向服务器验证激活码,如果校验不过会删除backup文件,这样操作记录都没了,但是并没实际删除,可通过fopen检测绕过 控制软件注册状态的主要字段是status和expiry_date,分别对应注册状态及过期时间字符串,其中status字段含义为:
enum {
STATE_LOCKED = 0, // 已锁定
STATE_NORMAL = 1, // 已激活
STATE_INACTIVE1 = 2, // 未激活
STATE_OUTDATE = 3, // 激活码过期
STATE_INACTIVE2 = 4, // 未激活
STATE_LOGOFF = 5, // 已注销
对于栈字符串的处理,见:https://github.com/lich4/personal_script/blob/master/IDA_Script/
parse_stack_string.py 对于ObjC函数调用关系还原,见:https://github.com/lich4/personal_script/blob/master/IDA_Script/
add_xref_for_macho.py 使用网络请求方式更新注册状态的响应中,get_json_value获取的as键对应status,aes键对应于expiry_date
另外一些字段用于激活码验证,如果不通过则结束进程,可以自行在newAppEnvClick函数中研究。 使用cjson反序列化回写注册状态逻辑存在于文件/private/var/mobile/Library/Preferences/
com.app1e.mobile.ifalscommon.plist,解密后仍然是json数据,要修改的字段如下:
{
authInfo : {
status : @0,
expiry_date : @ 21000101080000000
}
mapapi.bundle模块存在一些干扰,在hook函数的时候要注意

a. 捕获按钮触发的功能函数
b. 分析ALS和DHPDaemon的notify通信,有些重要函数是ALS调用DHPDaemon执行

a. 捕获按钮触发,利用frida脚本,https://github.com/lich4/personal_script/blob/master/
Frida_script/utils.js,这里tranverse_view用于检测当前呈现的界面可以获取的元素,以及对应的响应
selector,如果找按钮的回调,又不想触发,可以用这个。另外更通用的得是trace_view函数,可以拦截到
所有界面消息以及响应selector,在执行点击等操作后可以得到更全的信息

b. 下面是一些分析结果:
清理safari逻辑在函数中-[IFMagicMainVC cleanSafariClick:]

 // 杀死进程
 BKSTerminateApplicationForReasonAndReportWithDescription(__bridge CFStringRef)@ com.apple.mobilesafari , 5, 0, NULL);
 NSFileManager* man = [NSFileManager defaultManager];
 // 清理cookie
 NSString cookiepath = @ /var/mobile/Library/Cookies 
 if ([man fileExistsAtPath:cookiepath]) {
 NSString* cmd = [NSString stringWithFormat:@ rm -rf %@/* , cookiepath];
 system(cmd);
 cookiepath = @ /private/var/root/Library/Cookies 
 if ([man fileExistsAtPath:cookiepath]) {
 NSString* cmd = [NSString stringWithFormat:@ rm -rf %@/* , cookiepath];
 system(cmd);
 // 获取safari的沙盒路径
 NSString* safaricontainer = nil;
 NSString* installplist = @ /var/mobile/Library/Caches/com.apple.mobile.installation.plist 
 if ([man fileExistsAtPath:]) {
 NSDictionary* plist = [NSDictionary dictionaryWithContentsOfFile:installplist];
 id obj = plist[@ User ][@ com.apple.mobilesafari 
 if (obj == nil) {
 obj = plist[@ System ][@ com.apple.mobilesafari 
 if (obj != nil) {
 safaricontainer = obj[@ Container 
 } else {
 Class* LSApplicationProxy = NSClassFromString(@ LSApplicationProxy 
 id obj = [LSApplicationProxy performSelector:applicationProxyForIdentifier: withObject:@ com.apple.mobilesafari ]);
 if (obj != nil [obj respondsToSelector:@selector(dataContainerURL)]) {
 safaricontainer = [[obj performSelector:@selector(dataContainerURL)] path];
 // 清理library
 NSString* libpath = [safaricontainer stringByAppendingPathComponent:@ Library 
 NSString* libcachepath = [libpath stringByAppendingPathComponent:@ Caches 
 if ([man fileExistsAtPath:libcachepath]) {
 NSString* cmd = [NSString stringWithFormat:@ rm -rf %@/* , libcachepath];

清理keychain逻辑在函数中-[IFMagicMainVC cleanKeychainClick:]

 NSFileManager* man = [NSFileManager defaultManager];
 if ([man fileExistsAtPath:@ /var/Keychains/keychain-2.db ]) {
 system( cp /var/Keychains/keychain-2.db /tmp/ 
 void* ppDb = 0;
 char cmd[256];
 if (0 == sqlite3_open( /tmp/keychain-2.db , ppDb)) {
 strcpy(cmd, DELETE FROM cert WHERE agrp 'apple' and agrp not like '%apple%' and agrp 'ichat' and agrp 'lockdown-identities' 
 sqlite3_exec(ppDb, cmd, 0, 0, 0);
 strcpy(cmd, DELETE FROM keys WHERE agrp 'apple' and agrp not like '%apple%' and agrp 'ichat' and agrp 'lockdown-identities' 
 sqlite3_exec(ppDb, cmd, 0, 0, 0);
 strcpy(cmd, DELETE FROM inet WHERE agrp 'apple' and agrp not like '%apple%' and agrp 'ichat' and agrp 'lockdown-identities' 
 sqlite3_exec(ppDb, cmd, 0, 0, 0);
 system( cp /tmp/keychain-2.* /var/Keychains/ 

清理pasteboard逻辑在函数中-[IFMagicMainVC cleanPastboardClick:]

 UIPasteboard* pb = [UIPasteboard generalPasteboard];
 if (pb != nil) {
 NSArray* items = [pb items];
 if (items != nil) {
 [items removeAllObjects];
 [pb setItems:items];
 NSFileManager* man = [NSFileManager defaultManager];
 NSProcessInfo* proc = [NSProcessInfo processInfo];
 BOOL isbe8 = FALSE;
 NSOperatingSystemVersion ver;
 ver.majorVersion = 8;
 ver.minorVersion = 0;
 ver.patchVersion = 0;
 if ([proc respondsToSelector:@selector(isOperatingSystemAtLeastVersion: ver)]) {
 isbe8 = [proc isOperatingSystemAtLeastVersion: ver];
 NSString* pbplist = nil;
 NSString* pbbundle = nil;
 if ([man fileExistsAtPath:@ /System/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist ]) {
 pbplist = @ /System/Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist 
 pbbundle = @ com.apple.UIKit.pasteboardd 
 else if ([man fileExistsAtPath:@ /Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist ]) {
 pbplist = @ /Library/LaunchDaemons/com.apple.UIKit.pasteboardd.plist 
 pbbundle = @ com.apple.UIKit.pasteboardd 
 else if ([man fileExistsAtPath:@ /System/Library/LaunchDaemons/com.apple.pasteboard.pasted.plist ]) {
 pbplist = @ /System/Library/LaunchDaemons/com.apple.pasteboard.pasted.plist 
 pbbundle = @ com.apple.pasteboard.pasted 
 BOOL pbdbexist = [man fileExistsAtPath:@ /var/mobile/Library/Caches/com.apple.UIKit.pboard/pasteboardDB 
 NSString* pbcontainer = nil;
 if ([man fileExistsAtPath:@ /var/mobile/Library/Caches/com.apple.UIKit.pboard ]) {
 pbcontainer = @ /var/mobile/Library/Caches/com.apple.UIKit.pboard 
 } else if ([man fileExistsAtPath:@ /var/mobile/Library/Caches/com.apple.Pasteboard ]) {
 pbcontainer = @ /var/mobile/Library/Caches/com.apple.Pasteboard 
 if (!isbe8 [man fileExistsAtPath:pbplist]) {
 system( launchctl unload -w 
 if (pbcontainer != nil [man fileExistsAtPath:pbcontainer]) {
 NSString* cmd = [NSString stringWithFormat:@ rm -rf %@/* , pbcontainer];
 system([cmd UTF8String]);
 if (pbdbexist) {
 NSString* cmd = [NSString stringWithFormat:@ cp %@ %@ , @ /Applications/ALS.app/pb.dat , @ /var/mobile/Library/Caches/com.apple.UIKit.pboard/pasteboardDB 
 system([cmd UTF8String]);
改机原理是什么

在iOS上目前所有流行的改机工具,本质上是利用substrate框架对某些用来获取设备和系统参数函数进行hook,从而欺骗App达到修改的目的,具体的如下:

用作获取设备参数的函数,无论是C函数,还是Objective-C/Swift函数,可以使用hook框架来修改其返回值 屏蔽VPN/HTTP代理检测 屏蔽越狱检测 一键新机怎么实现的

在用户进行一键新机时,ALS有如下操作:

生成设备参数并保存到文件
/private/var/mobile/Library/Preferences/
com.app1e.mobile.ifalscommon.plist 保存伪造设备参数数据
com.app1e.mobile.ifalslocation.plist 保存伪造位置数据

本文标题:爱伪装,爱伪装苹果必须越狱吗
http://www.tainingxinwen.cn/qitaxinxi/408939.html

0

精彩评论

暂无评论...
验证码 换一张
取 消