爱伪装(AWZ)爱立思(ALS)改机改串一键新机原理分析
爱伪装(AWZ)爱⽴思(ALS)改机改串⼀键新机原理分析爱伪装(AWZ)/爱⽴思(ALS)改机改串⼀键新机原理分析
简介
  爱伪装(AWZ)/爱⽴思(ALS)是⼀款iOS越狱系统上的改机⼯具,可以修改多种系统参数达到伪装设备型号及各种软硬件属性的⽬的,同时提供了防越狱检测机制,常⽤于iOS上的推⼴刷量,配合代理/VPN使⽤。除了AWZ以外,该软件商还有类似⼯具
ALS/IGG/LRN/NZT/AXJ等,功能⼤体⼀致。AWZ/ALS⽀持iOS 7/8/9/10/11/12的全息备份,⼀键新机功能
AWZ伪装哪些参数?
IDFA
IDFV
⽤户名
系统版本
设备型号,固件版本
User-Agent
移动⽹络运营商信息
地理位置
uname / sysctl等参数
WIFI SSID BSSID
IMEI
序列号
MAC地址
AWZ有哪些屏蔽刷机检测的⼿段?
VPN隐藏
代理隐藏
WIFI隐藏
反越狱检测,越狱⽂件检测/模块检测/APP检测等
AWZ的Cydia源
1 2 3 4 5 6 7 8 9als.ucydia      ALS    11.0.5 awz.ucydia      AWZ    10.0.5 awz.itouchgo    AWZ    10.0.5 apt.awzcn      ALS    11.6.5 apt.awzcn      AWZ    8.2.5 apt.awzcn      AWZ    10.5.7 apt.abogeek    ALS    11.6.5 apt.abogeek    AWZ    8.2.5 apt.abogeek    AWZ    10.5.7
分析要点
这⾥只做学习讨论改机原理及ALS⾃⾝反逆向机制。ALS安装后,有如下⽂件:
/Applications/ALS.app 主程序,⽤于⽣成改机参数,参数保存在
/Library/LaunchDaemons/dhpdaemon.plist ⽤于daemon⽅式执⾏DHPDaemon,⽤于帮助ALS实现⼀些隐藏操作/usr/bin/DHPDaemon
梦见已故同事/MobileSubstrate/DynamicLibraries/ALS.{dylib,plist},该tweak通过hook⼀些可以获取系统属性和app属
性的C函数和ObjC函数实现的修改app参数
第⼀阶段
ALS属性2755防⽌加载tweak
存在restrict段,防⽌被加载tweak
存在syscall函数进⾏ptrace系统调⽤,存在ptrace函数,以及svc汇编指令实现的ptrace,防⽌调试器附加
对于restrict段和汇编指令反调试的处理,解法就是patch⽂件然后重签名,但是要写⼀个通⽤的命令是⽐较困难的,慢慢收集吧,这⾥提供的⽅式如下:
sed -i 's/RESTRICT/RXSTRICT/g' ALS
sed -i 's/\x80\x52\x01\x10\x00\xd4/\x80\x52\x1f\x20\x03\xd5/g' ALS
对于⽂件属性和函数级的反调试,⽅法不再赘述,写tweak即可
第⼆阶段
在第⼀阶段破解后,仍然是闪退的,此时反调试已经去除,所以可以加调试器看检测点
-[NSBundle executablePath]检测主进程⽂件是否被修改
_dyld_get_image_name检测tweak模块
sysctl检测进程的p_flag是否有调试器flag
isatty检测终端
ioctl(TIOCGWINSZ)检测终端
fopen检测主进程⽂件是否被修改(在DHPDaemon中)
posix_spawn检测/Application/ALS.app下是否存在超过3M的⽂件(补丁啊)
注意
在IFMagicMainVC的⼏个按钮handler函数中,存在⼤量检测代码,这⾥建议直接⾃⼰实现,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23void (*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];
}
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];
}
第三阶段
在第⼆阶段后,不闪退了,但是显⽰注册码过期
解密栈字符串,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 {
1 2 3 4 5 6STATE_LOCKED =0,        //已锁定STATE_NORMAL =1,        //已激活STATE_INACTIVE1 =2,    //未激活STATE_OUTDATE =3,        //激活码过期STATE_INACTIVE2 =4,    //未激活STATE_LOGOFF =5,        //已注销
};
对于栈字符串的处理,见:github/lich4/personal_script/blob/master/IDA_Script/
parse_stack_string.py
对于ObjC函数调⽤关系还原,见:github/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/
bile.ifalscommon.plist,解密后仍然是json数据,要修改的字段如下:
{
1 2 3 4"authInfo": {
"status": @0,
浙江有哪些旅游景点"expiry_date": @"21000101080000000" }
}
mapapi.bundle模块存在⼀些⼲扰,在hook函数的时候要注意
第四阶段
a. 捕获按钮触发的功能函数
b. 分析ALS和DHPDaemon的notify通信,有些重要函数是ALS调⽤DHPDaemon执⾏b. 下⾯是⼀些分析结果:
清理safari逻辑在函数中-[IFMagicMainVC cleanSafariClick:]
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41//杀死进程
BKSTerminateApplicationForReasonAndReportWithDescription(__bridge CFStringRef)@"bilesafari", 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/bile.installation.plist";
if([man fileExistsAtPath:]) {
NSDictionary*plist =[NSDictionary dictionaryWithContentsOfFile:installplist];
id obj =plist[@"User"][@"bilesafari"];
if(obj ==nil) {
天津市加成信息咨询有限公司
obj =plist[@"System"][@"bilesafari"];
}
在家兼职工作if(obj !=nil) {
safaricontainer =obj[@"Container"];
}
} else{
Class*LSApplicationProxy =NSClassFromString(@"LSApplicationProxy");
id obj =[LSApplicationProxy performSelector:applicationProxyForIdentifier: withObject:@"bilesafari"]);
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];
1清理keychain逻辑在函数中-[IFMagicMainVC cleanKeychainClick:]
2 3 4 5 6 7 8 9 10 11 12 13 14NSFileManager*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/");
}
1清理pasteboard逻辑在函数中-[IFMagicMainVC cleanPastboardClick:] 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53UIPasteboard*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有如下操作:
⽣成设备参数并保存到⽂件
1 2 3/private/var/mobile/Library/Preferences/
bile.ifalscommon.plist  保存伪造设备参数数据
bile.ifalslocation.plist 保存伪造位置数据
将应⽤沙盒⽬录下的数据备份,同时为新环境创建沙盒⽬录结构
备份的数据存放在/private/var/mobile/alsdata下
应⽤启动后,ALS.dylib会hook关键函数,并根据plist⽂件修改函数返回的数据在这⼀步,ALS还会根据情况清理keychain,同时做简单的反越狱检测
我该如何保护⾃⼰的App,防⽌被改机软件篡改设备信息?
可以将⼀些重要检测使⽤汇编指令(SVC)代替函数调⽤完成,同时使⽤内存校验来检测汇编代码是否被篡改。这样AWZ这种通⽤⼯具便⽆能为⼒,因为hook框架只能做到函数级别的hook。
ALS都修改了哪些参数
checktweak可以⽤来对⽐使⽤ALS前和使⽤ALS后,App中检测到的参数变化;当然如果你不⽤ALS的话,也可以⽤来获取机器本⾝的参数了。此外该⼯具可以看到ALS已经设置好的参数和历史参数信息。
通过分析ALS.dylib可以发现其hook了如下函数(注意这⾥只做技术探讨,不要⽤于商业⽤途):
1
2
3
4
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25sysctl                                  修改设备名,设备型号,iOS版本等
sysctlbyname                            修改设备名,设备型号,iOS版本等
uname                                  修改设备名,设备型号,iOS版本等SCNetworkReachabilityGetFlags          修改⽹络类型,WIFI/2G/3G/4G CNCopySupportedInterfaces              修改WIFI名和BSSID CNCopyCurrentNetworkInfo                修改WIFI名和BSSID IORegistryEntrySearchCFProperty        修改设备串号,IMEI IORegistryEntryCreateCFProperty        修改设备串号,IMEI
_CTServerConnectionCopyMobileIdentity  修改IMEI
UIDevice                                修改设备型号,iOS版本,设备名,IDFV ASIdentifierManager                    修改IDFA
CTCarrier                              修改运营商信息,包括运营商名,MCC,MNC,ICC CTTelephonyNetworkInfo                  修改运营商信息,包括运营商名,MCC,MNC,ICC NSProcessInfo                          修改设备名,iOS版本
NSBundle                                修改App版本号
CLLocationManager                      修改位置参数,包括经纬度,海拔,速度等MKUserLocation                          修改位置参数,包括经纬度,海拔,速度等ChromeViewController                    修改位置参数,包括经纬度,海拔,速度等MapsMainModeController                  修改位置参数,包括经纬度,海拔,速度等LocationShare                          修改位置参数,包括经纬度,海拔,速度等SAKCLLocationDelegateProxy              修改位置参数,包括经纬度,海拔,速度等MOARegionalMonitoring                  修改位置参数,包括经纬度,海拔,速度等CLLocationManagerBlocks                修改位置参数,包括经纬度,海拔,速度等QMLocationManager                      修改位置参数,包括经纬度,海拔,速度等TDLocationInfo                          修改位置参数,包括经纬度,海拔,速度等TaxiCancelOrderViewController          修改位置参数,包括经纬度,海拔,速度等

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。