0x00 本文缘起:
此App用来给ios越狱机器清理系统垃圾,用了的人都感觉良好。之前不懂iOS应用破解时就是找别人修改好的版本用,导致不能及时用上新版,后来通过学习了解iOS破解后有了自己破解的想法,当时信心满满咨询了C版,等我还没回过神来,C版已经分析写好注册机形式的插件直接注册了,但存在一个联网就注册失效的问题,之前的做法就是断网使用,这是去年之前的小经历,出于工作忙的原因我也没再分析,直到今天又想起此事,又重新捡起这个问题用软件,发现注册也失效了,然后跟C版要了之前注册插件的源进行参考分析,在此感谢C版。
0x01 所需工具:
MacBook Pro(或虚拟机)
iPhone7(iOS13.5)
IDA Pro
Theos
0x02 探测敌情:
分析一款应用之前,先是进行探测,看看应用有什么限制之类。下载最新版v7.9.0进入App,需要注册、广告开启等等…,如下图所示。
0x03 寻找入口:
使用爱思助手导出相关文件(越狱软件一般都没有加壳)。如下图所示。
然后把主文件拖到IDA进行分析,我的习惯就是对函数窗口进行关键字搜索。这里用License关键字试试,果不然奇然,有结果,如下图所示。
第一个方法存在checkLicense这种敏感字眼,进去看看伪代码(F5),幸福来得有点突然,貌似这里就是检查注册与广告处理。如下图所示。
至此,切入点就找到了,此处的sub_1000A8124应该是注册控制流程的关键了。接下来进行详细分析。
0x04 网络验证:
进入sub_1000A8124(),流程由qword_100648CB0全局变量控制,继续对其查找交叉引用,如下图所示。
找到两处赋值方法调用!666啊,进展非常顺利,如下图片所示。
先看sub_100066740函数并对其查找交叉引用,如下图所示。
结果如下图所示。
sub_100065D50``函数伪代码如下:
void __fastcall sub_100065D50(double a1)
{
double v1;
//为了文章好看,略掉
void *v27;
__int64 v28;
dispatch_time_t v29;
if ( !(byte_100647680 & 1) )
{
v1 = a1;
byte_100647681 = 0;
byte_100647680 = 1;
objc_msgSend(&OBJC_CLASS___NSNotificationCenter, "defaultCenter");
v2 = (void *)objc_retainAutoreleasedReturnValue();
objc_msgSend(v2, "postNotificationName:object:", CFSTR("FILETYPEMSG"), 0LL);
objc_release(v2);
if ( v1 <= 0.0 )
v1 = 60.0;
v4 = (void *)objc_alloc(&OBJC_CLASS___NSString, v3);
sub_100065A00((__int64)v4, v5);
v6 = objc_retainAutoreleasedReturnValue();
v7 = objc_msgSend(v4, "initWithFormat:", CFSTR("%c%@%s%@"), 0x75LL, CFSTR("di"), "d=", v6);// did机器码
objc_release(v6);
objc_msgSend(
&OBJC_CLASS___NSString,
"stringWithFormat:",
CFSTR("%s%c%s%c%c%@%c%s%@%c%s%c%c%@%s%c%s%@%s%c%@%s%c%s%c"),
"ht",
0x74LL,
"ps:",
0x2FLL,
0x2FLL,
CFSTR("ib"), // 呵呵,作者有心了,防字符串搜索快速定位
0x2DLL,
"so",
CFSTR("ft"),
0x2ELL,
"ne",
0x74LL,
0x2FLL,
CFSTR("icle"),
"aner",
0x2FLL,
"che",
CFSTR("ckRe"),
"gist",
0x72LL,
CFSTR("ati"),
"on",
0x2ELL,
"ph",
0x70LL); //https://ib-soft.net/icleaner/checkRegistration.php
v8 = objc_retainAutoreleasedReturnValue();
objc_msgSend(CFSTR("PO"), "stringByAppendingString:", CFSTR("ST"));// POST 请求
v9 = objc_retainAutoreleasedReturnValue();