IOS逆向之破解某知名抓包APP

0x00 前言

本文的测试目标是一个******APP,可以使用hook或者代理的方式来获取高级功能,如解密HTTPS流量、重写HTTP请求以及重放等功能。本文主要提供一些思路以及介绍一下数据之间的转换。


0x01 分析

运行后发现高级功能都需要付费才可以,抓包发现请求和返回都加密了。

IOS逆向之破解某知名抓包APP

使用frida-ios-dump将ipa文件dump出来,之后用ida打开,发现该程序是用到了OC和swift。而且http请求采用了Alamofire,它是一个用 Swift 编写的 HTTP 网络库。

该程序较小,猜测加密函数中有encrypt关键字,于是在函数中搜索encrypt

当然也可以根据http请求的一些内容搜索进而去定位加密的算法,在这里就不演示了。

IOS逆向之破解某知名抓包APP

可以看到有一些,可以使用frida-trace来追踪一下是调用了哪个方法。

frida-trace -U -f com.stormtech.sniffer -m "*[* *encrypt*]"

IOS逆向之破解某知名抓包APP

经过进一步验证发现是调用了类XMXXTEA相关的加密函数。一般这样同个类存在多个加(解)密,大多数都是简单的调用复杂的。

从上图就可以看出来

encryptStringToBase64String:arg1 stringKey:arg2

调用了

encryptToBase64String:arg1 stringKey:arg2。

所以我们看

+[XMXXTEA encryptStringToBase64String:arg1 stringKey:arg2]

即可。

命令如下:

frida-trace -U -f com.stormtech.sniffer -m "+[XMXXTEA encryptStringToBase64String:stringKey:]"

执行后可以发现与抓包的内容一致。

IOS逆向之破解某知名抓包APP

接下来我们看一下是否有数据的解密,同样在ida中搜decrypt

根据上面的经验,猜测解密的是

+[XMXXTEA decryptBase64StringToString:stringKey:]

结果进行追踪后发现并没调用,这里解密采用的是

+[XMXXTEA decryptBase64String:stringKey:]

可以看到解密数据。

IOS逆向之破解某知名抓包APP

返回的json中有几个关键的键值可以猜出其含义。

例如isVip应该是判断是否为会员,expire_on表示到期时间,auth_quantity是授权数量,function_list应该是拥有的功能,比如非会员用户只有一个抓包功能,如果要拥有解密HTTPS、重写等功能,则function_list应该是[1,2,3]

当然这些不是我的猜测了,因为我前年就借了正版账号。

尝试修改一下isVip的值为1,看是否有反应。首先看一下

+[XMXXTEA decryptBase64String:stringKey:]

解密返回值的类型是什么。

主要代码:

onLeave(log, retval, state) {
    var ret = ObjC.Object(retval);
    log(`ret type is -->`+ret.$className);
  }

执行后返回的结果:

ret type is -->NSConcreteData

返回值是NSConcreteData类型的,可以看作为是NSData

修改返回值有两种方法,第一种是将NSData转化为NSString,然后利用字符串替换来修改,修改完毕后转化NSData并替换;

第二种是将NSData转化为可变数组NSMutableDictionary,然后修改键的值,最后再转化NSData并替换。

方法一:使用NSString替换

对应的主要OC代码如下:

 NSString *str =@"{"uid": "b07b6ee3a93a44ae8d3cf80a3c6f47f5", "userID": "502456", "isVip": 0, "member_type": 0, "member_title": "\u57fa\u7840\u7248", "expire_on": "\u6682\u672a\u5f00\u901aVIP", "auth_quantity": 0, "auth_mail": null, "is_primary": 0, "trail_status": 0, "function_list": [1], "timestamp": 1666080682, "ts": 0}";
NSData* data =[str dataUsingEncoding:NSUTF8StringEncoding];//NSString转换为NSData
NSString*oldString =[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];//NSData转换为NSString
NSString* newString =[str stringByReplacingOccurrencesOfString:@""isVip": 0" withString:@""isVip": 1"];//替换字符串
NSLog(@"旧字符串是:n%@",oldString);
NSLog(@"新字符串是:n%@",newString);

这里为了使用NSData数据,采用的是NSString转换而来的,当然也可以采用byte来生成。主要代码:

Byte byte[] = {0x7B,..., 0x7D};
NSData *byteData = [[NSData alloc] initWithBytes:byte length:sizeof(byte)/sizeof(Byte)];

OC代码执行的结果如下:

IOS逆向之破解某知名抓包APP

可以成功替换,翻译成frida的js实现如下:

  onLeave(log, retval, state) {
    var ret = ObjC.Object(retval);
    var oldNSStr = ObjC.classes.NSString.alloc().initWithData_encoding_(ret, 4);//NSData转换为NSString
    log(`www.apibug.com旧-->`+ oldNSStr);
    var newNSStr = oldNSStr.stringByReplacingOccurrencesOfString_withString_('"isVip": 0','"isVip": 1');//替换字符串
    log(`www.apibug.com新-->`+ newNSStr);
    retval.replace(newNSStr.dataUsingEncoding_(4));//NSString转换为NSData,并替换返回值
  }

执行结果(同时查看我的账号界面可以看到PRO标志):

IOS逆向之破解某知名抓包APP

但是点击解密HTTPS流量、重写等功能还是跳转到会员开通界面,这是因为这些功能是从function_list中获取的,所以想要解锁功能还需修改这里。主要代码:

              var newNSStr = oldNSStr
.stringByReplacingOccurrencesOfString_withString_('"isVip": 0','"isVip": 1')
.stringByReplacingOccurrencesOfString_withString_('"is_vip": 0','"is_vip": 1')
.stringByReplacingOccurrencesOfString_withString_('"member_type": 0','"member_type": 3')
.stringByReplacingOccurrencesOfString_withString_('\u57fa\u7840\u7248','无敌牛逼版')
.stringByReplacingOccurrencesOfString_withString_('"can_deauthorize": false','"can_deauthorize": true')
.stringByReplacingOccurrencesOfString_withString_('"auth_quantity": 0','"auth_quantity": 99')
.stringByReplacingOccurrencesOfString_withString_('"auth_mail": null','"auth_mail": "[email protected]"')
.stringByReplacingOccurrencesOfString_withString_('"function_list": [1]','"function_list": [1,2,3,4,5]')
.stringByReplacingOccurrencesOfString_withString_('"function_list": "[1]"','"function_list": "[1,2,3,4,5]"')
.stringByReplacingOccurrencesOfString_withString_('"trail_status": 0','"trail_status": 1')
.stringByReplacingOccurrencesOfString_withString_('"ts": 0','"ts": 1')
.stringByReplacingOccurrencesOfString_withString_('\u6682\u672a\u5f00\u901aVIP','无敌破解永久有效');

log(`新--> ${newNSStr.toString()}`);

//将新NSString转换回NSData在替换返回值
          var newData = newNSStr.dataUsingEncoding_(4);
          retval.replace(newData);
} catch (e){
log(`Error: ${e.message}`);
      }

再次执行:

IOS逆向之破解某知名抓包APP

看到用户界面也成功变化了,高级功能也全部可以使用

IOS逆向之破解某知名抓包APP

方法二:使用NSMutableDictionary修改

对应的主要OC代码如下:

    NSData * data =[str dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary* result =[NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];//NSData转NSMutableDictionary
[result setValue:[NSNumber numberWithInt:1] forKey:@"isVip"];//设置isVip为1
[result setValue:@"[email protected]" forKey:@"auth_mail"];//这个无所谓
[result setValue:@"[1,2,3,4,5]" forKey:@"function_list"];//设置function_list
[result setValue:@"2099-09-09 14:22" forKey:@"expire_on"];//设置expire_on
NSLog(@"旧:%@",str);
NSLog(@"改变之后:%@",result);

执行的结果

IOS逆向之破解某知名抓包APP

这里翻译成frida的js实现时,有一个问题,生成NSMutableDictionary时,由于需要传入nil,而frida中无法生成,导致这种方法不能使用。

根据GPT给出的方法var nil=ObjC.Object(ptr("0x0"));,测试代码如下:

var data = ObjC.classes.NSString.stringWithString_('{"aa":11,"bb":2}') ;
var NSJSONSerialization = ObjC.classes.NSJSONSerialization;
var nil=ObjC.Object(ptr("0x0"));
NSJSONSerialization.JSONObjectWithData_options_error_(data,1,nil);

运行后直接崩溃,导致无法使用,因此在frida下,暂时放弃第二种方法。

分析的话到这里就结束了,但借助frida来获取高级版,不方便使用,而且无法在非越狱手机上使用,如果想在非越狱手机上使用的话,就需要编写插件来运行在非越狱手机上。


0x02 编写非越狱插件

编写插件采用了非越狱插件开发集成神器MonkeyDev,已经在论坛内发布过了,不会安装直接搜索MonkeyDev即可,MonkeyDev集成了theos+Tweaks+Reveal.framework +Cycript +class-dump+CaptainHook。

安装完成后新建MonkeyApp

File->New->Project->MonkeyApp

项目建立后将砸壳后的APP拖入到TargetApp目录下。

这里使用Logos进行Hook代码,HOOK 某个类里面的某个对象方法语法:

%hook 类名
- (返回值)方法名:(id)arg1 ....
{
       ...
}
%end

根据上面的分析,这里我们需要对XMXXTEA类的方法decryptBase64String:stringKey:进行HOOK,修改返回值,完整代码如下:

%hook XMXXTEA
+(id)decryptBase64String:(NSString*)stringData stringKey:(NSString*)key {
NSData*data =%orig;
NSMutableDictionary*result =[NSJSONSerializationJSONObjectWithData:modifiedData options:NSJSONReadingMutableContainers error:&error];
if(error){
NSLog(@"解析JSON出错: %@", error);
return modifiedData;//返回原始数据以防JSON解析失败
}
[result setValue:[NSNumber numberWithInt:1] forKey:@"isVip"];
[result setValue:[NSNumber numberWithInt:1] forKey:@"is_vip"];
[result setValue:[NSNumber numberWithInt:3] forKey:@"member_type"];
[result setValue:[NSNumber numberWithInt:99] forKey:@"auth_quantity"];
//[result setValue:@"[1,2,3,4,5]" forKey:@"function_list"];
[result setValue:@"无敌破解永久有效" forKey:@"expire_on"];
[result setValue:@"无敌牛逼版" forKey:@"member_title"];
[result setValue:@"[email protected]" forKey:@"auth_mail"];
[result setValue:[NSNumber numberWithBool:YES] forKey:@"can_deauthorize"];
[result setValue:[NSNumber numberWithInt:1] forKey:@"trail_status"];
[result setValue:[NSNumber numberWithInt:1] forKey:@"ts"];

//处理"function_list"字段
id functionList =[result objectForKey:@"function_list"];
if([functionList isKindOfClass:[NSArray class]]){
//如果 function_list 是数组,则直接修改
[result setValue:@[@1,@2,@3,@4,@5] forKey:@"function_list"];
}elseif([functionList isKindOfClass:[NSString class]]){
//如果 function_list 是字符串,则处理字符串值
NSString*functionListStr =(NSString*)functionList;
if([functionListStr isEqualToString:@"[1]"]){
[result setValue:@"[1,2,3,4,5]" forKey:@"function_list"];
}elseif([functionListStr isEqualToString:@""[1]""]){
[result setValue:@"[1,2,3,4,5]" forKey:@"function_list"];
}
}
NSData*data_result=[NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingPrettyPrinted error:nil];
NSLog(@"www.apibug.com : %@", data_result);
return data_result;
}
%end

因为开启抓包需要开通网络访问权限以及VPN的相关权限,由于账号不是苹果开发者账号,因此这些权限无法使用,所以需要Trollstore安装才有效果,ok,教程到此结束

原文链接

https://www.t00ls.com/articles-72262.html


原文始发于微信公众号(T00ls安全):IOS逆向之破解某知名抓包APP

版权声明:admin 发表于 2024年8月26日 上午10:35。
转载请注明:IOS逆向之破解某知名抓包APP | CTF导航

相关文章