一、背景 & 场景
1.1 环境
设备型号:iphone 14、iOS 版本:16.4.1、越狱方案:Dopamine
工具链:Frida16.1.4、IDA pro 9.2
1.2 引言
对于大多数互联网风控攻防业务来说,真正棘手的往往不是单个请求本身,而是背后那一整套“批量造设备、批量刷行为”的自动化体系。正是在这样的背景下,从最初的简单模拟请求,到如今的设备指纹伪造、群控刷量,攻防对抗从未停止。在这一背景下,Apple 推出的 DeviceCheck(以及后续的 App Attest)成为了 iOS 平台上反作弊与反爬虫的重要防线。
DeviceCheck 的核心目标是在保护用户隐私的前提下,为开发者提供一种持久化的设备标记能力。即使 App 被卸载重装,甚至设备被恢复出厂设置(在某些条件下),DeviceCheck 存储的 2-bit 状态依然可以被保留。这使得它成为了对抗“新用户薅羊毛”、“设备封禁”等场景的利器。
然而,对于安全研究人员和黑灰产从业者而言,DeviceCheck 也是一个必须攻克的堡垒。本文将基于逆向工程视角,简单剖析 DeviceCheck 的底层实现,揭示其加密流程,并探讨在越狱环境下进行攻防对抗的可行性。
1.3、研究动机与目标
-
验证通过改机(UniqueChipID / ECID/SerialNumber等)为什么不能激活设备?
-
想搞清楚:苹果到底在检验什么?哪些字段是“硬绑定”的?
-
从攻击与防护视角学习如何应用好DeviceCheck?
1.4、整体流程与框架
- 激活流程
1
- Device Token生成流程
2
二、mobileactivationd 激活流程分析
2.1、什么时候会激活?
这里说的激活,就是由 mobileactivationd + Apple 服务器 参与的那种“和苹果聊一聊,我是谁、能不能用”的流程,而不是普通 App 级别的登录。
首次开箱 / 刷机之后第一次开机
-
全新 iPhone、刚刷完原版 IPSW、DFU 恢复之后第一次进开机向导。
-
这时候本地没任何“激活凭据”,系统必须:
-
收集硬件指纹(ECID、ChipID、BoardId、SerialNumber…)
-
跟 Apple 服务器谈一轮,生成 / 刷新 uik.pem / ucrt.pem、设备证书等。
-
你能看到的表现就是:
- 屏幕上显示 “正在激活 iPhone,需要几分钟”
恢复出厂设置 / 抹掉所有内容之后
-
在设置 → 通用 → 传输或还原 iPhone → 抹掉所有内容和设置,或者用 Finder/iTunes 恢复。
-
抹掉后再次启动,和第一次开箱本质一样,也要重新激活。
-
这时 mobileactivationd 会:
-
检查旧的激活票据是否还有效
-
一般还是会重新向服务器请求新的激活证书(你抓到的 RKCertification 就是这类东西)。
硬件变化比较大时(换本板 / 基带 / 改机)
-
主板更换、严重“硬改机”、某些基带相关硬件变化,会导致:
-
UniqueChipID(ECID)、ChipID、BoardId、SecurityDomain 组合发生改变。
-
Apple 服务器视角:这是“另一台设备”,必须重新审查:
-
有没有被报失
-
有没有被运营商锁 / 黑名单
-
所以一旦检测到这种变化,系统会强制重新走激活流程。
-
你的 hook 里如果把 UniqueChipID 换成别的机器的 ECID,就会看到服务器直接回:
某些大版本升级 / 本地激活证书过期异常
和运营商 / 区域相关的情况
小结一句:
只要 Apple 觉得“我有理由重新确认你这台机器的身份/状态”,就会触发 mobileactivationd 跑激活。
2.2、为什么要激活?
从苹果的角度,这一整套“激活”设计,主要是为了解决三大问题:防伪造、防偷盗、统一发证。DeviceCheck / AppAttest 其实都是站在这套基础设施上实现的。
确认“这是一台真机,而不是山寨/模拟设备”
-
激活时上传的 RKCertification 里,包含:
-
从 Secure Enclave 拿到的真·硬件密钥的 attestation
-
ECID / ChipID / BoardId / SerialNumber / SecurityDomain 等指纹
-
苹果在服务器上用自己的 CA 体系校验证书链:
-
证书是不是 Apple 自己签出来的
-
硬件签名是不是由安全芯片里那把私钥算出来的
-
结论:
防丢失、防盗机、控制设备生命周期
激活是苹果“设备生命周期管理”的关键环节:
-
防盗 / 查找我的 iPhone:
-
被“查找”绑定过的机器,如果被抹掉再激活,Apple 会要求输入原 Apple ID 才能继续。
-
黑名单 / 封禁:
-
被判定为重大违规(盗刷、欺诈)的 ECID/序列号,可以在服务器侧直接标记,下一次激活就直接拒绝。
-
区域控制:
-
比如某些功能/频段只在特定地区开放,也可以通过激活阶段写入策略。
为上层安全服务“铺路”(你现在在玩的部分)
激活完成后,mobileactivationd 会产出一套“设备根身份”:
-
系统组文件:uik.pem / ucrt.pem
-
Keychain 里的:
-
这些东西后面会被谁用?
-
devicecheckd 生成 DeviceCheck Token
-
AppAttest 做应用级 attestation
-
各种安全相关 daemon(FairPlay、Apple Pay、Find My…)
2.3、激活流程逆向分析
主要通过copyAnswer:方法采集设备唯一性相关信息
UniqueChipID: "6871544955xxxxxx",
ChipID: "33040",
BoardId: "24",
SecurityDomain: "1",
SerialNumber: "F6X439xxxxxx",
BuildVersion: "20E252",
UniqueDeviceID: "00008110-303C30C91A0xxxxxx"
// 获取设备信息
void __fastcall create_baa_info_sub_1000EEDCC(__SecKey *a1, id a2, _QWORD *a3)
{
id v4; // x25
id v5; // x20
void *v6; // x21
id v7; // x20
int v8; // w5
int v9; // w6
int v10; // w7
id v11; // x19
NSArray *v12; // x21
void *v13; // x27
NSNumber *v14; // x0
int v15; // w5
int v16; // w6
int v17; // w7
NSNumber *v18; // x24
void *v19; // x22
id v20; // x23
void *v21; // x27
void *v22; // x22
char *v23; // x0
char *v24; // x23
__int64 v25; // x25
char *i; // x28
__SecKey *v27; // x24
int v28; // w5
int v29; // w6
int v30; // w7
const void *v31; // x9
void *v32; // x27
void *v33; // x26
void *v34; // x23
void *v35; // x19
_BOOL4 v36; // w9
__SecKey *v37; // x20
void *v38; // x23
_BOOL4 v39; // w24
_BOOL4 v40; // w19
NSNumber *v41; // x26
id v42; // x22
int v43; // w1
__SecKey *v44; // x21
int v45; // w5
int v46; // w6
int v47; // w7
id v48; // x20
__SecKey *v49; // x0
int v50; // w5
int v51; // w6
int v52; // w7
CFDataRef v53; // x21
int v54; // w5
int v55; // w6
int v56; // w7
__int64 v57; // x0
int v58; // w5
int v59; // w6
int v60; // w7
char v61; // w22
int v62; // w24
int v63; // w5
int v64; // w6
int v65; // w7
__SecKey *v66; // x19
int v67; // w5
int v68; // w6
int v69; // w7
unsigned int v70; // w28
void *v71; // x21
__SecKey *v72; // x22
int v73; // w5
int v74; // w6
int v75; // w7
int v76; // w5
int v77; // w6
int v78; // w7
id v79; // x19
int v80; // w5
int v81; // w6
int v82; // w7
void *v83; // x21
id v84; // x22
NSNumber *v85; // x25
NSNumber *v86; // x19
NSNumber *v87; // x21
unsigned __int8 v88; // w22
int v89; // w5
int v90; // w6
int v91; // w7
NSNumber *v92; // x19
unsigned int v93; // w20
int v94; // w5
int v95; // w6
int v96; // w7
const __CFString *v97; // x4
int v98; // w1
int v99; // w2
id v100; // x20
int v101; // w5
int v102; // w6
int v103; // w7
__SecKey *v104; // x0
int v105; // w5
int v106; // w6
int v107; // w7
NSFileManager *v108; // x20
NSFileManager *v109; // x21
void *v110; // x22
unsigned __int8 v111; // w23
int v112; // w5
int v113; // w6
int v114; // w7
id v115; // x20
id v116; // x20
int v117; // w5
int v118; // w6
int v119; // w7
id v120; // x20
void *v121; // x21
id v122; // x20
int v123; // w5
int v124; // w6
int v125; // w7
id v126; // x20
void *v127; // x21
id v128; // x20
int v129; // w5
int v130; // w6
int v131; // w7
id v132; // x20
__SecKey *v133; // x21
id v134; // x20
int v135; // w5
int v136; // w6
int v137; // w7
id v138; // x20
__SecKey *v139; // x21
id v140; // x20
int v141; // w5
int v142; // w6
int v143; // w7
id v144; // x21
void *v145; // x26
int v146; // w5
int v147; // w6
int v148; // w7
__SecKey *v149; // x0
int v150; // w5
int v151; // w6
int v152; // w7
CFDataRef v153; // x0
int v154; // w5
int v155; // w6
int v156; // w7
CFDataRef v157; // x24
int v158; // w1
id v159; // x26
id v160; // x21
int v161; // w5
int v162; // w6
int v163; // w7
__SecKey *v164; // x19
__CFString **v165; // x8
CFDataRef v166; // x26
CFDataRef v167; // x2
void *v168; // x20
id v169; // x21
void *v170; // x20
void *v171; // x21
void *v172; // x0
void *v173; // x23
int v174; // w5
int v175; // w6
int v176; // w7
void *v177; // x20
int v178; // w5
int v179; // w6
int v180; // w7
void *v181; // x20
void *v182; // x21
void *v183; // x0
void *v184; // x20
int v185; // w5
int v186; // w6
int v187; // w7
void *v188; // x20
int v189; // w5
int v190; // w6
int v191; // w7
void *v192; // x20
void *v193; // x21
void *v194; // x0
void *v195; // x20
int v196; // w5
int v197; // w6
int v198; // w7
int v199; // w5
int v200; // w6
int v201; // w7
int v202; // w5
int v203; // w6
int v204; // w7
__SecKey *v205; // x0
void *v206; // x20
id v207; // x21
void *v208; // x20
void *v209; // x21
id v210; // x22
void *v211; // x21
unsigned int v212; // w19
void *v213; // x22
id v214; // x23
void *v215; // x21
void *v216; // x22
id v217; // x23
void *v218; // x21
void *v219; // x22
id v220; // x23
void *v221; // x21
void *v222; // x22
id v223; // x23
void *v224; // x23
int v225; // w5
int v226; // w6
int v227; // w7
void *v228; // x22
id v229; // x23
__SecKey *v230; // x21
__SecKey *v231; // x24
void *v232; // x28
id v233; // x27
void *v234; // x25
void *v235; // x26
__SecKey *v236; // x23
void *v237; // x22
id v238; // x19
const void *v239; // x20
__SecKey *v240; // x21
__SecKey *v241; // x0
id v242; // x19
NSDictionary *v243; // x22
void *v244; // x24
__CFString **v245; // x8
void *v246; // x0
id v247; // x0
void *v248; // x22
char v249; // w23
id v250; // x19
id v251; // x23
int v252; // w5
int v253; // w6
int v254; // w7
id v255; // x19
id v256; // x24
int v257; // w5
int v258; // w6
int v259; // w7
char is_darwinos; // w0
id v261; // x19
id v262; // x21
int v263; // w5
int v264; // w6
int v265; // w7
id v266; // x24
NSData *v267; // x24
int v268; // w5
int v269; // w6
int v270; // w7
CFDataRef v271; // x2
int v272; // w5
int v273; // w6
int v274; // w7
char v275; // [xsp+0h] [xbp-3B0h]
char v276; // [xsp+0h] [xbp-3B0h]
void *v277; // [xsp+8h] [xbp-3A8h]
__SecKey *v278; // [xsp+18h] [xbp-398h]
__SecKey *v279; // [xsp+20h] [xbp-390h]
void *v280; // [xsp+28h] [xbp-388h]
void *v281; // [xsp+30h] [xbp-380h]
void *v282; // [xsp+38h] [xbp-378h]
__SecKey *v283; // [xsp+40h] [xbp-370h]
__SecKey *v284; // [xsp+48h] [xbp-368h]
__SecKey *cf; // [xsp+50h] [xbp-360h]
id v286; // [xsp+58h] [xbp-358h]
id v287; // [xsp+58h] [xbp-358h]
char v288[8]; // [xsp+60h] [xbp-350h]
__SecKey *v289; // [xsp+68h] [xbp-348h]
__SecKey *v290; // [xsp+70h] [xbp-340h]
const void *v291; // [xsp+78h] [xbp-338h]
id v292; // [xsp+80h] [xbp-330h]
id v293; // [xsp+80h] [xbp-330h]
__SecKey *v294; // [xsp+88h] [xbp-328h]
__SecKey *v295; // [xsp+88h] [xbp-328h]
CFDataRef v296; // [xsp+90h] [xbp-320h]
unsigned int v297; // [xsp+98h] [xbp-318h]
NSData *v298; // [xsp+98h] [xbp-318h]
CFDataRef v299; // [xsp+A0h] [xbp-310h]
id v300; // [xsp+A8h] [xbp-308h]
id v301; // [xsp+B0h] [xbp-300h]
id v302; // [xsp+B8h] [xbp-2F8h]
_BOOL4 v303; // [xsp+C0h] [xbp-2F0h]
_BOOL4 v304; // [xsp+C0h] [xbp-2F0h]
id v305; // [xsp+C0h] [xbp-2F0h]
id v306; // [xsp+C8h] [xbp-2E8h]
id v307; // [xsp+D0h] [xbp-2E0h]
NSNumber *v308; // [xsp+D8h] [xbp-2D8h]
NSNumber *v309; // [xsp+E0h] [xbp-2D0h]
id v310; // [xsp+E8h] [xbp-2C8h]
id v311; // [xsp+F0h] [xbp-2C0h]
id v312; // [xsp+F8h] [xbp-2B8h]
NSNumber *v313; // [xsp+100h] [xbp-2B0h]
id v314; // [xsp+108h] [xbp-2A8h]
id v315; // [xsp+110h] [xbp-2A0h]
__SecKey *v316; // [xsp+118h] [xbp-298h]
unsigned int v317; // [xsp+118h] [xbp-298h]
id v318; // [xsp+120h] [xbp-290h]
id v319; // [xsp+128h] [xbp-288h]
CFDataRef v320; // [xsp+130h] [xbp-280h]
id v321; // [xsp+138h] [xbp-278h]
NSNumber *v322; // [xsp+140h] [xbp-270h]
__SecKey *v323; // [xsp+148h] [xbp-268h]
id v324; // [xsp+148h] [xbp-268h]
id v325; // [xsp+148h] [xbp-268h]
id v327; // [xsp+158h] [xbp-258h] BYREF
id v328; // [xsp+160h] [xbp-250h] BYREF
id v329; // [xsp+168h] [xbp-248h] BYREF
id v330[2]; // [xsp+170h] [xbp-240h] BYREF
id v331; // [xsp+180h] [xbp-230h] BYREF
id v332; // [xsp+188h] [xbp-228h] BYREF
id v333; // [xsp+190h] [xbp-220h] BYREF
id v334[3]; // [xsp+198h] [xbp-218h] BYREF
id v335[2]; // [xsp+1B0h] [xbp-200h] BYREF
id v336[2]; // [xsp+1C0h] [xbp-1F0h]
id v337[2]; // [xsp+1D0h] [xbp-1E0h]
id v338[2]; // [xsp+1E0h] [xbp-1D0h]
CFErrorRef error; // [xsp+1F0h] [xbp-1C0h] BYREF
id v340[12]; // [xsp+1F8h] [xbp-1B8h] BYREF
_QWORD v341[12]; // [xsp+258h] [xbp-158h] BYREF
char v342[8]; // [xsp+2B8h] [xbp-F8h] BYREF
_QWORD v343[3]; // [xsp+338h] [xbp-78h] BYREF
__int64 vars8; // [xsp+3B8h] [xbp+8h]
v4 = objc_retain(a2);
error = 0;
v5 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v6 = objc_msgSend(v5, "copyAnswer:", CFSTR("s7nuHoZIYNoOHCqT9iyZkQ"));
objc_release(v5);
v319 = v6;
v7 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v6));
objc_release(v7);
if ( !v7 )
{
v322 = 0;
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
244,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v8,
v9,
v10,
(char)CFSTR("s7nuHoZIYNoOHCqT9iyZkQ")));
v302 = 0;
v31 = 0;
v306 = 0;
v307 = 0;
v315 = 0;
v299 = 0;
v300 = 0;
v310 = 0;
v311 = 0;
v313 = 0;
v308 = 0;
v309 = 0;
v318 = 0;
v321 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v35 = 0;
LABEL_18:
v320 = 0;
v316 = 0;
LABEL_46:
v296 = 0;
v298 = 0;
v312 = 0;
v314 = 0;
v44 = 0;
LABEL_47:
v72 = 0;
v301 = 0;
v305 = 0;
goto LABEL_180;
}
v11 = objc_alloc((Class)&OBJC_CLASS___NSMutableArray);
v343[0] = CFSTR("1.2.840.113635.100.8.4");
v343[1] = CFSTR("1.2.840.113635.100.8.5");
v343[2] = CFSTR("1.2.840.113635.100.8.7");
v12 = objc_retainAutoreleasedReturnValue(+[NSArray arrayWithObjects:count:](&OBJC_CLASS___NSArray, "arrayWithObjects:count:", v343, 3));
v13 = objc_msgSend(v11, "initWithArray:", v12);
objc_release(v12);
v14 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 0));
v322 = v14;
if ( !v4 )
{
v36 = 0;
v297 = 0;
v37 = 0;
v320 = 0;
v38 = 0;
v310 = 0;
v311 = 0;
v300 = 0;
v315 = 0;
v306 = 0;
v39 = 0;
v40 = 1;
v41 = (NSNumber *)&off_100E66CB8;
v308 = (NSNumber *)&off_100E66CB8;
v309 = (NSNumber *)&off_100E66CA0;
goto LABEL_20;
}
v18 = v14;
v323 = a1;
v19 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v20 = objc_retainAutoreleasedReturnValue((id)isKindOfClass());
objc_release(v20);
objc_release(v19);
if ( v20 )
{
v321 = v13;
*(_OWORD *)v337 = 0u;
*(_OWORD *)v338 = 0u;
*(_OWORD *)v335 = 0u;
*(_OWORD *)v336 = 0u;
v21 = v4;
v22 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v23 = (char *)objc_msgSend(v22, "countByEnumeratingWithState:objects:count:", v335, v342, 16);
if ( v23 )
{
v24 = v23;
v25 = *(_QWORD *)v336[0];
while ( 2 )
{
for ( i = 0; i != v24; ++i )
{
if ( *(_QWORD *)v336[0] != v25 )
objc_enumerationMutation(v22);
v27 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(*((_QWORD *)v335[1] + (_QWORD)i)));
objc_release(v27);
if ( !v27 )
{
v4 = v21;
v277 = objc_retainAutoreleasedReturnValue(objc_msgSend(v21, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
263,
-2,
0,
(int)CFSTR("Invalid options (%@): %@"),
v76,
v77,
v78,
(char)CFSTR("OIDSToInclude")));
objc_release(v277);
objc_release(v22);
v302 = 0;
v31 = 0;
v306 = 0;
v307 = 0;
v315 = 0;
v300 = 0;
v310 = 0;
v311 = 0;
v318 = 0;
goto LABEL_93;
}
}
v24 = (char *)objc_msgSend(v22, "countByEnumeratingWithState:objects:count:", v335, v342, 16);
if ( v24 )
continue;
break;
}
}
objc_release(v22);
v4 = v21;
v13 = objc_retainAutoreleasedReturnValue(objc_msgSend(v21, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
objc_release(v321);
v18 = v322;
}
v321 = v13;
if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.1"))
&& ((sub_100C87320() & 1) != 0 || (unsigned int)sub_100C87330()) )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
276,
-2,
0,
(int)CFSTR("Boot manifest not available in rOS or diagnosticsOS."),
v28,
v29,
v30,
v275));
v302 = 0;
v31 = 0;
v306 = 0;
v315 = 0;
v300 = 0;
v310 = 0;
v311 = 0;
v318 = 0;
goto LABEL_92;
}
v304 = ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.1")) & 1) != 0
|| ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.7")) & 1) != 0
|| ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.1")) & 1) != 0
|| ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.2")) & 1) != 0
|| (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.3"));
v70 = (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.7"));
if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.2")) & 1) != 0
|| (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.11.1")) )
{
v71 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("nonce")));
v72 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
objc_release(v72);
objc_release(v71);
if ( !v72 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
295,
-2,
0,
(int)CFSTR("Missing required option: %@"),
v73,
v74,
v75,
(char)CFSTR("nonce")));
v302 = 0;
v31 = 0;
v306 = 0;
v307 = 0;
v315 = 0;
v316 = 0;
v299 = 0;
v300 = 0;
v310 = 0;
v311 = 0;
v318 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v35 = 0;
v7 = 0;
v320 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v314 = 0;
v44 = 0;
LABEL_96:
v301 = 0;
v305 = 0;
v313 = (NSNumber *)&off_100E66CB8;
v308 = (NSNumber *)&off_100E66CB8;
v309 = (NSNumber *)&off_100E66CA0;
goto LABEL_180;
}
v318 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("nonce")));
}
else
{
v318 = 0;
}
v83 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CertType")));
v84 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v83));
objc_release(v84);
objc_release(v83);
v293 = v4;
if ( v84 )
{
v85 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CertType")));
objc_release(v18);
v86 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 0));
if ( -[NSNumber isEqualToNumber:](v85, "isEqualToNumber:", v86) )
{
objc_release(v86);
v18 = v85;
}
else
{
v87 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 1));
v88 = -[NSNumber isEqualToNumber:](v85, "isEqualToNumber:", v87);
objc_release(v87);
objc_release(v86);
v18 = v85;
if ( (v88 & 1) == 0 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
306,
-2,
0,
(int)CFSTR("Invalid value for option (%@): %@"),
v89,
v90,
v91,
(char)CFSTR("CertType")));
v302 = 0;
v31 = 0;
v306 = 0;
v307 = 0;
v315 = 0;
v316 = 0;
v299 = 0;
v300 = 0;
v310 = 0;
v311 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v35 = 0;
v7 = 0;
v320 = 0;
v296 = 0;
v298 = 0;
v314 = 0;
v44 = 0;
v72 = 0;
v301 = 0;
v305 = 0;
v322 = v85;
v312 = 0;
v313 = (NSNumber *)&off_100E66CB8;
v308 = (NSNumber *)&off_100E66CB8;
v309 = (NSNumber *)&off_100E66CA0;
v4 = v293;
goto LABEL_180;
}
}
}
v92 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 1));
v93 = -[NSNumber isEqualToNumber:](v18, "isEqualToNumber:", v92);
objc_release(v92);
v322 = v18;
if ( v93 )
{
v4 = v293;
if ( ((unsigned int)objc_msgSend(v319, "boolValue") & 1) == 0 )
{
v97 = CFSTR("Certificate type not supported on this platform: %@");
v276 = (char)v18;
v98 = 313;
v99 = -3;
goto LABEL_89;
}
if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1")) & 1) == 0 )
{
v97 = CFSTR("Missing required OID for certificate type (%@): %@");
v276 = (char)v18;
v98 = 318;
LABEL_66:
v99 = -2;
LABEL_89:
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
v98,
v99,
0,
(int)v97,
v94,
v95,
v96,
v276));
LABEL_90:
v302 = 0;
v31 = 0;
v306 = 0;
v315 = 0;
v300 = 0;
v311 = 0;
LABEL_91:
v310 = 0;
LABEL_92:
v307 = 0;
v27 = 0;
LABEL_93:
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v299 = 0;
v35 = 0;
goto LABEL_94;
}
}
else
{
v4 = v293;
if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1")) & 1) != 0
|| ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.2")) & 1) != 0
|| (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.3")) )
{
v97 = CFSTR("Invalid OID(s) for requested certificate type: %@");
v276 = (char)v18;
v98 = 325;
goto LABEL_66;
}
}
if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1"))
&& (v168 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties"))),
v169 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_2()),
objc_release(v169),
objc_release(v168),
v169) )
{
v170 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties")));
v171 = objc_msgSend(v170, "length");
objc_release(v170);
v172 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties")));
v173 = v172;
if ( v171 != (void *)32 )
{
objc_msgSend(v172, "length");
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
333,
-2,
0,
(int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
v174,
v175,
v176,
(char)CFSTR("MFiProperties")));
objc_release(v173);
goto LABEL_90;
}
}
else
{
v173 = 0;
}
v311 = v173;
if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.2")) )
{
v177 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v177));
objc_release(v44);
objc_release(v177);
if ( !v44 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
343,
-2,
0,
(int)CFSTR("Missing required option: %@"),
v178,
v179,
v180,
(char)CFSTR("MFiPPUID")));
v302 = 0;
v31 = 0;
v306 = 0;
v315 = 0;
v300 = 0;
LABEL_135:
v310 = 0;
v307 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v298 = 0;
v299 = 0;
v35 = 0;
v7 = 0;
v320 = 0;
v316 = 0;
v296 = 0;
v312 = 0;
v314 = 0;
goto LABEL_95;
}
v181 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
v182 = objc_msgSend(v181, "length");
objc_release(v181);
v183 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
v184 = v183;
if ( (unsigned __int64)v182 >= 0x25 )
{
objc_msgSend(v183, "length");
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
348,
-2,
0,
(int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
v185,
v186,
v187,
(char)CFSTR("MFiPPUID")));
objc_release(v184);
v302 = 0;
v31 = 0;
v306 = 0;
v315 = 0;
v300 = 0;
goto LABEL_91;
}
v35 = objc_retainAutoreleasedReturnValue(objc_msgSend(v183, "stringByPaddingToLength:withString:startingAtIndex:", 36, &stru_100E61E50, 0));
objc_release(v184);
if ( !v35 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
357,
-2,
0,
(int)CFSTR("Failed to pad string."),
v199,
v200,
v201,
v275));
v302 = 0;
v31 = 0;
v306 = 0;
v307 = 0;
v315 = 0;
v299 = 0;
v300 = 0;
v310 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
LABEL_94:
v7 = 0;
v320 = 0;
v316 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v314 = 0;
v44 = 0;
LABEL_95:
v72 = 0;
goto LABEL_96;
}
v315 = objc_retainAutoreleasedReturnValue(objc_msgSend(v35, "dataUsingEncoding:", 4));
if ( !v315 )
{
v300 = v35;
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
363,
-2,
0,
(int)CFSTR("Failed to convert string to data."),
v202,
v203,
v204,
v275));
v302 = 0;
v31 = 0;
v306 = 0;
v315 = 0;
goto LABEL_91;
}
}
else
{
v35 = 0;
v315 = 0;
}
v300 = v35;
if ( !(unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.3")) )
{
v306 = 0;
goto LABEL_137;
}
v188 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
objc_release(v44);
objc_release(v188);
if ( !v44 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
370,
-2,
0,
(int)CFSTR("Missing required option: %@"),
v189,
v190,
v191,
(char)CFSTR("MFiData")));
v302 = 0;
v31 = 0;
v306 = 0;
goto LABEL_135;
}
v192 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
v193 = objc_msgSend(v192, "length");
objc_release(v192);
v194 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
v195 = v194;
if ( (unsigned __int64)v193 >= 0x4B0 )
{
objc_msgSend(v194, "length");
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
375,
-2,
0,
(int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
v196,
v197,
v198,
(char)CFSTR("MFiData")));
objc_release(v195);
v302 = 0;
v31 = 0;
v306 = 0;
goto LABEL_91;
}
v306 = v194;
LABEL_137:
v206 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseRKSigningInterface")));
v207 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v206));
objc_release(v207);
objc_release(v206);
if ( v207 )
{
v208 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseRKSigningInterface")));
v317 = (unsigned int)objc_msgSend(v208, "boolValue");
objc_release(v208);
}
else
{
v317 = 0;
}
v209 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
v210 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v209));
objc_release(v210);
objc_release(v209);
if ( v210 )
{
v211 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
v212 = (unsigned int)objc_msgSend(v211, "boolValue");
objc_release(v211);
}
else
{
v212 = 1;
}
v213 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("Validity")));
v214 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v213));
objc_release(v214);
objc_release(v213);
if ( v214 )
{
v215 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("Validity")));
v309 = objc_retainAutoreleasedReturnValue(
+[NSNumber numberWithUnsignedInteger:](
&OBJC_CLASS___NSNumber,
"numberWithUnsignedInteger:",
objc_msgSend(v215, "unsignedIntegerValue")));
objc_release(v215);
}
else
{
v309 = (NSNumber *)&off_100E66CA0;
}
v216 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CACert")));
v217 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v216));
objc_release(v217);
objc_release(v216);
if ( v217 )
{
v218 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CACert")));
v308 = objc_retainAutoreleasedReturnValue(
+[NSNumber numberWithUnsignedInteger:](
&OBJC_CLASS___NSNumber,
"numberWithUnsignedInteger:",
objc_msgSend(v218, "unsignedIntegerValue")));
objc_release(v218);
}
else
{
v308 = (NSNumber *)&off_100E66CB8;
}
v219 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
v220 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v219));
objc_release(v220);
objc_release(v219);
if ( v220 )
{
v221 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
v41 = objc_retainAutoreleasedReturnValue(
+[NSNumber numberWithUnsignedInteger:](
&OBJC_CLASS___NSNumber,
"numberWithUnsignedInteger:",
objc_msgSend(v221, "unsignedIntegerValue")));
objc_release(v221);
}
else
{
v41 = (NSNumber *)&off_100E66CB8;
}
v222 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v223 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
objc_release(v223);
objc_release(v222);
if ( !v223 )
{
v37 = 0;
v320 = 0;
goto LABEL_156;
}
v224 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
v27 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
objc_release(v27);
objc_release(v224);
if ( !v27 )
{
v313 = v41;
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
412,
-2,
0,
(int)CFSTR("Missing required option for %@."),
v225,
v226,
v227,
(char)CFSTR("ClientAttestationPublicKey")));
v302 = 0;
v31 = 0;
v310 = 0;
v307 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v299 = 0;
v35 = 0;
v7 = 0;
goto LABEL_18;
}
v37 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v320 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
LABEL_156:
v297 = v70;
v228 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("AppID")));
v229 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v228));
objc_release(v229);
objc_release(v228);
v39 = v317 != 0;
v40 = v212 != 0;
if ( v229 )
v310 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("AppID")));
else
v310 = 0;
v38 = v318;
a1 = v323;
v36 = v304;
LABEL_20:
v321 = v13;
v318 = v38;
v313 = v41;
if ( !a1 )
{
v316 = v37;
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
467,
-2,
0,
(int)CFSTR("Invalid input."),
v15,
v16,
v17,
v275));
v302 = 0;
v31 = 0;
v307 = 0;
v27 = 0;
LABEL_45:
v32 = 0;
v33 = 0;
v34 = 0;
v299 = 0;
v35 = 0;
v7 = 0;
goto LABEL_46;
}
v42 = 0;
v303 = v36;
if ( !v39 || v37 )
{
v291 = 0;
v289 = 0;
v294 = 0;
LABEL_49:
v316 = v37;
v333 = v42;
v334[0] = 0;
v27 = security_copy_system_key(0, v334, &v333);
v7 = objc_retain(v334[0]);
v79 = objc_retain(v333);
objc_release(v42);
if ( !v27 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
519,
-1,
error,
(int)CFSTR("Failed to copy SIK attestation key."),
v80,
v81,
v82,
v275));
objc_release(v79);
v302 = 0;
v305 = 0;
v301 = 0;
v72 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v35 = 0;
v299 = 0;
v34 = 0;
v33 = 0;
v32 = 0;
a1 = 0;
v307 = 0;
v290 = 0;
goto LABEL_173;
}
*(_QWORD *)v288 = v7;
if ( -[NSNumber boolValue](v41, "boolValue") )
{
v292 = v4;
v286 = 0;
v284 = 0;
}
else
{
v331 = v79;
v332 = 0;
v72 = security_copy_system_key(2, &v332, &v331);
v286 = objc_retain(v332);
v100 = objc_retain(v331);
objc_release(v79);
if ( !v72 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
528,
-1,
v100,
(int)CFSTR("Failed to copy UIK attestation key."),
v101,
v102,
v103,
v275));
objc_release(v100);
CFRelease(v27);
v302 = 0;
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v34 = 0;
v33 = 0;
v32 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v35 = v286;
v7 = *(id *)v288;
goto LABEL_173;
}
v284 = v72;
v292 = v4;
v79 = v100;
v7 = *(id *)v288;
}
cf = v27;
v104 = (__SecKey *)objc_alloc_init((Class)&OBJC_CLASS___NSMutableDictionary);
v72 = v104;
if ( !v104 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
536,
-1,
0,
(int)CFSTR("Failed to allocate dictionary."),
v105,
v106,
v107,
v275));
objc_release(v79);
v302 = 0;
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v34 = 0;
v33 = 0;
v32 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v4 = v292;
v35 = v286;
goto LABEL_171;
}
v283 = v104;
if ( -[NSNumber boolValue](v41, "boolValue")
|| (v108 = objc_retainAutoreleasedReturnValue(+[NSFileManager defaultManager](&OBJC_CLASS___NSFileManager, "defaultManager")),
v109 = objc_retainAutoreleasedReturnValue(objc_retainAutoreleaseReturnValue(v108)),
v110 = objc_retainAutoreleasedReturnValue(
-[NSFileManager stringByAppendingPathComponent:](
v109,
"stringByAppendingPathComponent:",
CFSTR("ucrt.pem"))),
v111 = -[NSFileManager fileExistsAtPath:](v108, "fileExistsAtPath:", v110),
objc_release(v110),
objc_release(v109),
objc_release(v108),
(v111 & 1) != 0) )
{
v115 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v34 = objc_msgSend(v115, "copyAnswer:", CFSTR("UniqueChipID"));
objc_release(v115);
v116 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v34));
objc_release(v116);
if ( v116 )
{
v281 = v34;
v120 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v121 = objc_msgSend(v120, "copyAnswer:", CFSTR("ChipID"));
objc_release(v120);
v282 = v121;
v122 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v121));
objc_release(v122);
if ( !v122 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
588,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v123,
v124,
v125,
(char)CFSTR("ChipID")));
objc_release(v79);
v302 = 0;
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v32 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v4 = v292;
v35 = v286;
v7 = *(id *)v288;
v33 = v282;
v72 = v283;
goto LABEL_171;
}
v126 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v127 = objc_msgSend(v126, "copyAnswer:", CFSTR("BoardId"));
objc_release(v126);
v280 = v127;
v128 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v127));
objc_release(v128);
if ( !v128 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
594,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v129,
v130,
v131,
(char)CFSTR("BoardId")));
objc_release(v79);
v302 = 0;
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v4 = v292;
v35 = v286;
v7 = *(id *)v288;
v33 = v282;
v72 = v283;
v32 = v280;
goto LABEL_171;
}
v132 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v133 = (__SecKey *)objc_msgSend(v132, "copyAnswer:", CFSTR("SecurityDomain"));
objc_release(v132);
v279 = v133;
v134 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v133));
objc_release(v134);
if ( !v134 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
600,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v135,
v136,
v137,
(char)CFSTR("SecurityDomain")));
objc_release(v79);
v302 = 0;
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v4 = v292;
v35 = v286;
v7 = *(id *)v288;
v33 = v282;
v72 = v283;
v32 = v280;
LABEL_133:
a1 = v279;
goto LABEL_171;
}
v138 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v139 = (__SecKey *)objc_msgSend(v138, "copyAnswer:", CFSTR("SerialNumber"));
objc_release(v138);
v278 = v139;
v140 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v139));
objc_release(v140);
if ( v140 )
{
v144 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
v145 = objc_msgSend(v144, "copyAnswer:", CFSTR("BuildVersion"));
objc_release(v144);
v307 = v145;
v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v145));
objc_release(v44);
if ( v44 )
{
v149 = SecKeyCopyPublicKey(a1);
if ( v149 )
{
v290 = v149;
v153 = SecKeyCopyExternalRepresentation(v149, &error);
v7 = *(id *)v288;
if ( v153 )
{
v157 = v153;
if ( -[NSNumber boolValue](v313, "boolValue") )
v158 = 0;
else
v158 = 2;
v330[1] = v79;
v159 = objc_retainAutoreleasedReturnValue((id)security_create_system_key_attestation(
(int)a1,
v158,
v318));
v160 = objc_retain(v79);
objc_release(v79);
v312 = v159;
v299 = v157;
if ( v159 )
{
v325 = v160;
if ( v316 )
{
v164 = v283;
-[__SecKey setObject:forKeyedSubscript:](
v283,
"setObject:forKeyedSubscript:",
v316,
CFSTR("RKCertification"));
-[__SecKey setObject:forKeyedSubscript:](
v283,
"setObject:forKeyedSubscript:",
v159,
CFSTR("RKSigning"));
v165 = off_100E52138;
v166 = v157;
v167 = v157;
}
else
{
v165 = off_100E51E10;
v167 = (CFDataRef)v159;
v164 = v283;
v166 = v157;
}
-[__SecKey setObject:forKeyedSubscript:](v164, "setObject:forKeyedSubscript:", v167, *v165);
v242 = objc_alloc((Class)&OBJC_CLASS___NSMutableDictionary);
v340[0] = CFSTR("UniqueChipID");
v340[1] = CFSTR("ChipID");
v341[0] = v34;
v341[1] = v282;
v340[2] = CFSTR("BoardId");
v340[3] = CFSTR("SecurityDomain");
v341[2] = v280;
v341[3] = v279;
v340[4] = CFSTR("SerialNumber");
v340[5] = CFSTR("OsBuildVersion");
v341[4] = v278;
v341[5] = v307;
v340[6] = CFSTR("scrtAttestation");
v340[7] = CFSTR("CertType");
v341[6] = v313;
v341[7] = v322;
v340[8] = CFSTR("Validity");
v340[9] = CFSTR("CACert");
v341[8] = v309;
v341[9] = v308;
v340[10] = CFSTR("OIDSToInclude");
v340[11] = CFSTR("SIKPub");
v341[10] = v13;
v341[11] = *(_QWORD *)v288;
v243 = objc_retainAutoreleasedReturnValue(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
v341,
v340,
12));
v244 = objc_msgSend(v242, "initWithDictionary:", v243);
objc_release(v243);
v245 = off_100E52130;
if ( v316 )
{
objc_msgSend(v244, "setObject:forKeyedSubscript:", v320, CFSTR("RKCertificationPub"));
v245 = off_100E52138;
}
v35 = v286;
v246 = objc_msgSend(v244, "setObject:forKeyedSubscript:", v166, *v245);
if ( v286 )
v246 = objc_msgSend(v244, "setObject:forKeyedSubscript:", v286, CFSTR("UIKPub"));
v247 = objc_retainAutoreleasedReturnValue((id)IORegistryEntry_sub_10052290C(v246));
v314 = v244;
if ( !v247 )
goto LABEL_201;
v248 = v247;
if ( (sub_100C87330() & 1) != 0 )
{
objc_release(v248);
LABEL_201:
v302 = 0;
LABEL_207:
if ( v303 && (sub_100C87320() & 1) == 0 )
{
if ( (sub_100C87330() & 1) != 0 )
{
v301 = 0;
}
else
{
v329 = v325;
v255 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(2, &v329));
v256 = objc_retain(v329);
objc_release(v325);
v301 = v255;
if ( !v255 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
735,
-1,
v256,
(int)CFSTR("Failed to load boot manifest."),
v257,
v258,
v259,
v275));
objc_release(v256);
v305 = 0;
v301 = 0;
LABEL_240:
v44 = 0;
v296 = 0;
v298 = 0;
goto LABEL_168;
}
objc_msgSend(v314, "setObject:forKeyedSubscript:", v255, CFSTR("Image4Manifest"));
v325 = v256;
}
v35 = v286;
v7 = *(id *)v288;
v34 = v281;
}
else
{
v301 = 0;
}
if ( (sub_100C87330() & 1) != 0 )
{
v305 = 0;
LABEL_221:
v4 = v292;
v266 = v306;
v72 = v283;
LABEL_222:
v33 = v282;
v262 = v325;
goto LABEL_223;
}
is_darwinos = os_variant_is_darwinos(objc_msgSend(CFSTR("com.apple.mobileactivationd"), "UTF8String"));
v305 = 0;
if ( !v297 )
goto LABEL_221;
if ( (is_darwinos & 1) != 0 )
{
v4 = v292;
v266 = v306;
v35 = v286;
v7 = *(id *)v288;
v72 = v283;
v34 = v281;
goto LABEL_222;
}
v328 = v325;
v261 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(10, &v328));
v262 = objc_retain(v328);
objc_release(v325);
v305 = v261;
if ( v261 )
{
objc_msgSend(v314, "setObject:forKeyedSubscript:", v261, CFSTR("Cryptex1Image4Manifest"));
v4 = v292;
v266 = v306;
v35 = v286;
v7 = *(id *)v288;
v33 = v282;
v72 = v283;
v34 = v281;
LABEL_223:
v32 = v280;
if ( v310 )
objc_msgSend(v314, "setObject:forKeyedSubscript:", v310, CFSTR("AppID"));
if ( v311 )
objc_msgSend(v314, "setObject:forKeyedSubscript:", v311, CFSTR("MFiProperties"));
if ( v315 )
objc_msgSend(v314, "setObject:forKeyedSubscript:", v315, CFSTR("MFiPPUID"));
if ( v266 )
objc_msgSend(v314, "setObject:forKeyedSubscript:", v266, CFSTR("MFiData"));
v327 = 0;
v267 = objc_retainAutoreleasedReturnValue(
+[NSPropertyListSerialization dataWithPropertyList:format:options:error:](
&OBJC_CLASS___NSPropertyListSerialization,
"dataWithPropertyList:format:options:error:",
v314,
100,
0,
&v327));
v287 = objc_retain(v327);
objc_release(v262);
if ( v267 )
{
-[__SecKey setObject:forKeyedSubscript:](
v72,
"setObject:forKeyedSubscript:",
v267,
CFSTR("RKProperties"));
v298 = v267;
v271 = SecKeyCreateSignature(
a1,
kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
(CFDataRef)v267,
&error);
v27 = v278;
if ( v271 )
{
v296 = v271;
-[__SecKey setObject:forKeyedSubscript:](
v72,
"setObject:forKeyedSubscript:",
v271,
CFSTR("RKPropertiesSignature"));
v44 = objc_retain(v72);
v324 = v287;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
810,
-1,
error,
(int)CFSTR("Failed to sign data with ref key."),
v272,
v273,
v274,
v275));
objc_release(v287);
v44 = 0;
v296 = 0;
}
goto LABEL_133;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
799,
-1,
v287,
(int)CFSTR("Could not convert dictionary to xml data."),
v268,
v269,
v270,
v275));
objc_release(v287);
v44 = 0;
v296 = 0;
v298 = 0;
LABEL_170:
v27 = v278;
a1 = v279;
LABEL_171:
CFRelease(cf);
if ( v284 )
CFRelease(v284);
LABEL_173:
if ( v289 )
CFRelease(v289);
v205 = v294;
if ( !v294 )
goto LABEL_177;
goto LABEL_176;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
770,
-1,
v262,
(int)CFSTR("Failed to load cryptex1 manifest."),
v263,
v264,
v265,
v275));
objc_release(v262);
v305 = 0;
goto LABEL_240;
}
v249 = os_variant_is_darwinos(objc_msgSend(CFSTR("com.apple.mobileactivationd"), "UTF8String"));
objc_release(v248);
if ( (v249 & 1) != 0 )
{
v302 = 0;
LABEL_206:
v34 = v281;
goto LABEL_207;
}
v330[0] = v160;
v250 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(9, v330));
v251 = objc_retain(v330[0]);
objc_release(v160);
v302 = v250;
if ( v250 )
{
objc_msgSend(v244, "setObject:forKeyedSubscript:", v250, CFSTR("LocalPolicy"));
v325 = v251;
v35 = v286;
v7 = *(id *)v288;
goto LABEL_206;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
719,
-1,
v251,
(int)CFSTR("Failed to load cryptex1 local policy."),
v252,
v253,
v254,
v275));
objc_release(v251);
v305 = 0;
v301 = 0;
v44 = 0;
v296 = 0;
v298 = 0;
LABEL_167:
v302 = 0;
LABEL_168:
v4 = v292;
v7 = *(id *)v288;
LABEL_169:
v35 = v286;
v33 = v282;
v72 = v283;
v32 = v280;
v34 = v281;
goto LABEL_170;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
637,
-1,
v160,
(int)CFSTR("Failed to create reference key attestation (nonce: %@)."),
v161,
v162,
v163,
(char)v318));
objc_release(v160);
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
628,
-1,
0,
(int)CFSTR("Failed to encode RK public key as data."),
v154,
v155,
v156,
v275));
objc_release(v79);
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
}
v302 = 0;
v4 = v292;
goto LABEL_169;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
622,
-1,
0,
(int)CFSTR("Failed to copy RK public key."),
v150,
v151,
v152,
v275));
objc_release(v79);
v305 = 0;
v301 = 0;
v44 = 0;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
612,
-1,
v79,
(int)CFSTR("Failed to retrieve %@."),
v146,
v147,
v148,
(char)CFSTR("BuildVersion")));
objc_release(v79);
v305 = 0;
v301 = 0;
}
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
606,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v141,
v142,
v143,
(char)CFSTR("SerialNumber")));
objc_release(v79);
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v307 = 0;
}
v290 = 0;
goto LABEL_167;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
582,
-1,
0,
(int)CFSTR("Failed to retrieve %@."),
v117,
v118,
v119,
(char)CFSTR("UniqueChipID")));
objc_release(v79);
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
543,
-4,
0,
(int)CFSTR("UCRT is unavailable."),
v112,
v113,
v114,
v275));
objc_release(v79);
v305 = 0;
v301 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v299 = 0;
v34 = 0;
}
v33 = 0;
v32 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v302 = 0;
v4 = v292;
v35 = v286;
v7 = *(id *)v288;
v72 = v283;
goto LABEL_171;
}
if ( -[NSNumber boolValue](v41, "boolValue") )
v43 = 0;
else
v43 = 2;
v334[2] = 0;
v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)security_create_system_key_attestation((int)a1, v43, v38));
v48 = objc_retain(0);
if ( !v44 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
477,
-1,
v48,
(int)CFSTR("Failed to create reference key attestation."),
v45,
v46,
v47,
v275));
objc_release(v48);
v302 = 0;
v31 = 0;
v307 = 0;
v27 = 0;
a1 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v298 = 0;
v299 = 0;
v35 = 0;
v7 = 0;
v316 = 0;
v296 = 0;
v312 = 0;
v314 = 0;
goto LABEL_47;
}
v316 = v44;
v49 = SecKeyCopyPublicKey(a1);
if ( !v49 )
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
483,
-1,
0,
(int)CFSTR("Failed to copy RK public key."),
v50,
v51,
v52,
v275));
objc_release(v48);
v302 = 0;
v31 = 0;
v307 = 0;
v27 = 0;
a1 = 0;
goto LABEL_45;
}
v294 = v49;
v53 = SecKeyCopyExternalRepresentation(v49, &error);
objc_release(v320);
if ( v53 )
{
v57 = SecAccessControlCreate(0, &error);
if ( v57 )
{
v61 = kSecAttrAccessibleUntilReboot;
v62 = v57;
v291 = (const void *)v57;
if ( (SecAccessControlSetProtection(v57, kSecAttrAccessibleUntilReboot, &error) & 1) != 0 )
{
v334[1] = v48;
v66 = (__SecKey *)sub_100C6E934(v62, v40, v4);
v42 = objc_retain(v48);
objc_release(v48);
if ( v66 )
{
v320 = v53;
a1 = v66;
v289 = v66;
v37 = v316;
goto LABEL_49;
}
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
508,
-1,
v42,
(int)CFSTR("Failed to create reference key."),
v67,
v68,
v69,
v275));
v48 = v42;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
502,
-1,
error,
(int)CFSTR("Failed to set ACL protection to %@."),
v63,
v64,
v65,
v61));
}
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
497,
-1,
error,
(int)CFSTR("Failed to create access control."),
v58,
v59,
v60,
v275));
v291 = 0;
}
v320 = v53;
}
else
{
v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
(int)"create_baa_info",
489,
-1,
error,
(int)CFSTR("Failed to encode RK public key as data."),
v54,
v55,
v56,
v275));
v320 = 0;
v291 = 0;
}
objc_release(v48);
v302 = 0;
v305 = 0;
v301 = 0;
v72 = 0;
v44 = 0;
v314 = 0;
v296 = 0;
v298 = 0;
v312 = 0;
v7 = 0;
v35 = 0;
v299 = 0;
v34 = 0;
v33 = 0;
v32 = 0;
a1 = 0;
v27 = 0;
v307 = 0;
v290 = 0;
v205 = v294;
LABEL_176:
CFRelease(v205);
LABEL_177:
if ( v290 )
CFRelease(v290);
v31 = v291;
LABEL_180:
if ( error )
{
v295 = v44;
v230 = v27;
v231 = a1;
v232 = v32;
v233 = v4;
v234 = v33;
v235 = v34;
v236 = v72;
v237 = v35;
v238 = v7;
v239 = v31;
CFRelease(error);
v31 = v239;
v7 = v238;
v35 = v237;
v72 = v236;
v34 = v235;
v33 = v234;
v4 = v233;
v32 = v232;
a1 = v231;
v27 = v230;
v44 = v295;
}
error = 0;
if ( v31 )
CFRelease(v31);
if ( a3 && !v44 )
*a3 = objc_retainAutorelease(v324);
v240 = objc_retain(v44);
objc_release(v302);
objc_release(v324);
objc_release(v306);
objc_release(v315);
objc_release(v300);
objc_release(v311);
objc_release(v310);
objc_release(v322);
objc_release(v313);
objc_release(v308);
objc_release(v309);
objc_release(v318);
objc_release(v321);
objc_release(v307);
objc_release(v27);
objc_release(a1);
objc_release(v32);
objc_release(v33);
objc_release(v34);
objc_release(v299);
objc_release(v35);
objc_release(v7);
objc_release(v320);
objc_release(v316);
objc_release(v296);
objc_release(v312);
objc_release(v298);
objc_release(v314);
objc_release(v240);
objc_release(v72);
objc_release(v301);
objc_release(v319);
objc_release(v305);
objc_release(v4);
if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
v241 = objc_autoreleaseReturnValue(v240);
}
用 SE 里封装的密钥 + 苹果预置的证书链,生成了一份 attestation(证明)blob,这个 blob 里面带着证书和签名,对“某些设备硬件字段 + 公钥”做了绑定。
这个“证书/attestation blob”是 依赖安全硬件(Secure Enclave / Apple KeyStore)生成的,而且签名覆盖了与这台硬件绑定的一些信息。
格式如下:
SEQUENCE
INTEGER 02
SEQUENCE
OCTETSTRING xxxxdeca90b4fd52da1c016730a81dcb281f6c4dbb973e6b8438e6827530a177
OCTETSTRING xxxx980ea0e8b0211cc342dc42067f1b..(total 65bytes)..2c8c482afb33b9e84221b49ffd1d81fa
OCTETSTRING xxxx730da8259089a9b9b02bd4a455fd
OCTETSTRING xxxxce59b8232b317ff32beb21237051
OCTETSTRING xxxx56c0b70138d40071067ee100013f..(total 1074bytes)..4b70f5283c1085f6a8d25107d6b9a94b
将采集的硬件信息与证书签名信信息组合成 plist格式数据上报到服务器端
0 : User-Agent = {contents = "iOS Device Activator (MobileActivation-834.100.27) - devicecheckd"}
3 : Content-Type = {contents = "application/xml"}
4 : Content-Length = 9822
6 : x-jmet-deviceid = {contents = "00008110-303C30C91A06484E"}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>RKCertification</key>
<data>
MIIExQIBAjxxxxxxxxP4C3sqQtP1S2hwBZzCoHcsoH2xNu5c+a4Q45oJ1MKF3BEEEiTxl
3JiRx7vW49DhREeRVU04QQBLnB7Lm7nI8+D2ayS/PMZ7rcmhC89px3xHSlAvDl2MQopT
SHXxnC/0Bs/6KgQQ1SciqWRdHp3U/vxi/S1O/wQQNpOm/5v25ojsX99XACzgpwSCBDHO
l9izvodcLU0pQSlaNXHlIp7nMLqh/QkyEI+a/YlGFaqTR/PgZbq4o37Rw6SCZQ+MjU2F
uzuq9O6sTaKVBcw4aDW0oPDmZgH5m1ZlDwvUqQFAy+OvNrO8L4D4zSo2lW8BRqR89jkx
WAixq12iERj/4+orIFAFGG86P/PnRRUsC8uR1tkqM4NpjXiLNUlO/X7VF1iY7g3nf5JS
uxAqGMNZ8eEXXHJ9I5XuPDC/B1BvpoM/Pk65CPRbaw5ojMr+McZ+IsuWQBb21dxMldAy
MMg5sFEt5+uIqWFaVyjFMfFCqYTfSofsyFQO8woaPegrmqFBVJRTGbbPkEDEVaWgLprd
VuoE8hkSvecWaBwsyNH0UmTLMOwrMHF12RLVPc6qChr4ki0FkIP9crLHhQwxVYeXgRpA
ClcA6uNFFa412RdhRhv5T88NBVRNu9ewCm3gWBnhMF10PltNVGJ1ZRjhZS0ghaVnqHpj
DA+2pnObaocLzgC9bOl0RExDwVwxLp7/hD/0jqZ+GqGSPgXYGY3FxnIB9n1e35KNjWaV
ur1WgHps5TEdi9LHxur2iqv5IkmxXNojxUoWprRc36RCBkurDLJiCM6Es8/63z1mZQ9h
a4iA5+u0PStVpCSjOJ/0gn01pIxxxeppomCsT6980+l1HYi7zsD/tBkOznpFwGS5Ki9h
RErTaCc2/9YGjgWVOBv1w5dEnBnwb1P59Qgpmnx3k9eyczaxt3OXOnKVwzYKtowI0OeD
F9jM1yN9KZVtAqQJM4H8N+W3f0w8x+PwYHUf/0AHdAK/WyUHObDkoPzZOY+N7aFvkSf8
aVcxC5MMCM6YFGpeDN9yoroti2mxxxelwDYx7Q8wuIeBBDiJfHRMWXxQEbej2XoYxGs4
tz8Qh0z5p0kL5bb5MERKHPkaIg+slVxEpoCAxCnNHiTHjK3gEXhgyxkiBmLO4ENSGDTp
+5PX64sez9Sb95ua6PhFFJYRXFgnp2IqffOoxx9Pxtxf7aKvpmlhPu+YGfbpz+mF+BSQ
Y0a/ybU0xySRCKfTlepT8J+3HGNGl6HmjKPMDgj1SIloAoNR+VATnMs0THe7ZZTYLI+m
bghSAHqDcjZCOWbRp19gSbUz71WU/sDAbN477biemxOYszVzS6cckGmmoDSLuav8RCSH
9h254xTGB5VzEjT5lqpsWJ0u+IJUW7gfCbkq1IGer5PdmVrzAluNTS4G85iHnXi3EKJB
wJ1upCRMjwlQRFlKP/SDo1TTQUa1kX0x+o1bFjvroyNKq+wL56PRQex22FzN00gsursF
dstdB+WPHde2jfeVmielZ+wxw59wEuE2CLeS5D1CLIEGYgsTyoLxl6QQ80UjaphhAuVA
A7HqcmXNe/6AOGdL42LHUhF23K5Fd55i8yaJP0sMwzY1e3nPbeunZmIiL1KiAFcKLzpm
cg==
</data>
<key>RKProperties</key>
<data>
ff94bfwgfmVyc2lvbjxxxxxwIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBs
aXN0IFBVQkxJQyAiLSxxxxxwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3
dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJz
aW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+QXBwSUQ8L2tleT4KCTxzdHJpbmc+Y29tLmFw
cGxlLmRldmljZWNoZWNrZDwvf3RyaW5nPgoJPGtleT5Cb2FyZElkPC9rZXk+Cgk8aW50
ZWdlcj4yNDwvaW50ZWdlcj4KffxrZXk+QfFfZXffPC9rZXk+Cgk8aW50ZWdlcj4wPC9p
bnRlZ2VyPgoJPGtleT5DZXJ0VHlwZTwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4K
CTxrZXk+Q2hpcElEPC9rZXk+Cgk8aW50ZWdlcj4zMzA0MDwvaW50ZWdlcj4KCTxrZXk+
TG9jYWxQb2xpY3k8L2tleT4KCTxkYXRhPgoJTUlJTVFCWUVTVTFITkRBVUZnUkpUVFJR
RmdSc2NHOXNGZ014TGpBRUFRQ2dnZfdfTUfJfUhCWUVTVTAwVFFJQkFER0MKCUFpUC9o
T3FGbkVLQ0Fob3dnZ0lXRmdSTlFxxUNNWUlDRFArRTZvV2NVSUlCbnpDQ0Fac1dCRTFC
VGxBeGdnR1IvNFNTCgl2YVJFQ3pBSkZnUkNUMUpFQWdFWS80U2FsYUJQQ3pBSkZnUkRS
VkJQQWdFQi80U2FvWkpRRFRBTEZnUkRTRWxRQWdNQQoJZ1JEL2hKckJwRThMTUFrV0JF
TlFVazhCQWYvL2hKck5pa01MTUFrV0JFTlRxVU1CQfWYvL2hLcU5ra1FSTUE4V0JFVkQK
CVNVUUNCeGhwb2p3Z0lCNy9oWnFSbmswTE1Ba1dCRk5FVDAwQ0FRSC9odU85eEc4TE1B
a1dCR3h2WW04QkFmLy9odlBOCgkwbWc2TURnV0JHNXphV2dFTUlQc0gwYlAybmtaaDNo
NVF3U2RXUU1CL0NoekZrWlMyczE0SxlWxnJTdDZwR2RlaDIvSgoJd3VnR2V4dFU5cWNm
Uy8rSGs3M2NhQ293S0JZRWNtOXVhQVFnU2srUmVVVnd1QWlCeEw0cWM5WmlZZUFFQ3Y1
OVN2dmwKCXk4SWhTM2ZaK2k3L2g1dkIwbWc2TURnV0JITndhV2dFTUo3V1ZSSWhWNU13
ZXlXa2VHdVo5STVSbUFSNGQycm9aZnFQCglmOE92aXljRkFjUEs0cHJDUXVTN3BSa3lB
WDQxVi8rSG04bnNiaDR3SEJZRWMzSjJiZ1FVRzIrWkp3aXFselVHSUkzQQoJVmZMcklJ
L3RkMGYvaDdQVjBtUWFNQmdXQkhaMWFXUUVFQUFBQUFBQUFBQUFBQUFBQUFBQUFBRC9o
dVBCM214ZE1Gc1cKCUJHeHdiMnd4VS8rRW9wMm1WRG93T0JZRVJFZFRWQVF3MFFGVU9N
U29rWEtqQkkxZXJyeXkzbVYzZGNacStHaVJhcWVXCglHUUk5Z29haFJoREhKZVNSem1m
MERMMVl0M2h5LzRTcXJZcFpDekFKRmdSRlMwVlpBUUgvQklJQ0FFRmdqK1krQkpheAoJ
MU1jS3dGQkdFMHpvcElKZkJWY2dKcG5MeDV2MFA2L1VsbG1jWmZYcnVYK2t1K2xRYm9H
UXBkQ3ZZcnp6K3l4bXVjS00KCWtDOXlJdlpzMndjMldrMzdDeHl4a1lXZ2UvckZmSERC
WFpQS3hTc1hIRFpkVXVjanFQbGlqVkJGV1pXekJjc0hQd2M3CgkyOFJUcTNWQU9aeG0x
RXo3RVFlVHRmUDFocDN0WEdic0xaMlZ0aVcyWG12VDFDeCsvajNCbnhnNGNtQy9EUjJW
SmpZaQoJUUx2V0dJSTNSVUY5cUEwL3BBeGcvQ3JCeXI4Zkx3Uk5QV2haOGMwRW04eVhi
U2MxZ1h2K0NlUnJJcVBNZXFWU1o3cGoKCXdGamlhTWlwRXEwRUJhQkcyOG9xNkNCZE9E
K1ZDUWxYSzBNOEdqUXZXc3FpcS9UVDRlQkVGV0NQTzRKLzU2bzE4WkxpCgk5OFdZaTQy
RVBLb0RHM0ZyTFhreWNWR0E0QTdnVlhIczBnS25TeWJEKzZmYlk0SGF5cWtpUEM4ZHl1
QWlUNXF5WThwUwoJdVp5TTY5aEs4dEJleFpiWDdiOFdEd29HVElzd3RST0d1SGZJbEpS
bXBIVXF2YnRUcWs4Qk42cFBwaHlNMlJqb1p4QmgKCXlBdzdEQ0M5Y0tuTkpnamhQTE91
aFRaUlU0aCtqMXo5WnY2UmdpSU44L21wTkxZV2pNMmtFWEw1eVRKbVhYVnBOcThICgll
UGx5VUF4TnF6dkFLVFpZQjMrODROOFF4ekF4bVk4eFFBcUpVb1ROWWVZSjZnSWZXcnFM
VktsRFdDcy9kUE5kc2xndwoJNHN4ci9xS09kcDI1cm5ST1hyK21Kc080Qm4rNkI2Vmhm
WndWWnpmT2VkN0toZ3dMaGxrSXRYY25UbEN0TUlJSDVEQ0MKCUIrQXdnZ1hJb0FNQ0FR
SUNFRDM5ajV5cU5WOXZVQ0xzTjAyRWRCOHdEUVlKS29aSWh2Y05BUUVNQlFBd1N6RW5N
Q1VHCglBMVVFQXd3ZVFYQndiR1VnVTJWamRYSmxJRUp2YjNRZ1VtOXZkQ0JEUVNBdElF
YzJNUk13RVFZRFZRUUtEQXBCY0hCcwoJWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpB
ZUZ3MHlNREEzTWpJeE9EQTJORGhhRncwek1EQTNNak14T0RBMk5EaGEKCU1GSXhMakFz
QmdOVkJBTU1KVlE0TVRFd0xWTkVUMDB4TFZKbFkyOTJaWEo1UW05dmRDMVNaWFpCTFVa
aFkzUnZjbmt4CglFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlU
QWxWVE1JSUNJakFOQmdrcWhraUc5dzBCQVFFRgoJQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF5
aVFHMk1leXZJeFlCQThJdis1bVd0cG83SHJ6ZUdvdU1sSlR1SHFqbmNUYzdDVEYKCUlp
WlUvT1RMaVRoT2FsdS85L29rQnBqY2MyY0hVdXV6NFlMeUhRYkNFYzllam5MdTFhY2lY
Q3MvVHZaZmoyTFpScnZsCgk4Tk1xaTBrNUE5RHlUVGxzYnZWRDhXQmdIZ3VUN2MySjh2
N0tpUnM5MkZUWjZ6OGROK0ZPa1VjM3dTUnRiOFBaQ2QrWgoJREdXblpDYzZyZFlkOFRJ
WDhNK0dCYzhGeUVEaXFhUmNONmpNNzJkRkRDL0NCQjZxcmFKZDlEQ1VzRTdDVXJ5Zk02
VWYKCXpqbVNyTGNnSkZYSjhZK3k0N2VjaGcrY2RDTytOQThBYjQzL2E1N0xJaTBtT0JI
V2FIUytHTkExR3c3WkpqdHdNQXcvCgllbW9heXVNYXB6d1RlRjFNTW1qKzNTa0h2WEdT
T0JtcU5SYVBoT2hRd1p3bkpsaEhpSkNzaVl1dWJ3N3Bxa0MycytiYgoJekx3MkxNakEy
UUppQWdDOHJmU3VYb2RUT2EzRkxhK1RmSlJ4TjhoL3p2aEU5Wmk0RDNBeC8xQ2dBS1Qx
bTNXT3JtQ1AKCURVZDZKOXZ5c3plTWdlZ3RTWldHdU9oL1o1OGFDR1lROTFoMVdpYSt5
VHdvU1J4c1lYdTR5ZldkT0ZlelpYQjlzMmFqCglWUEFRKzI2eE8xWlRsR29CWXVHcU1y
TGEvaUV5S1J1UHpzZDVzcC9uU29wdE43dDQwS0h5Uy9KL1luT2RoZTltREdqUwoJMTZE
aFJBSjRWdHBubDFmeHhubFdNcXpJeUNTMWxtTDdWeWxMdkF1YkpKZTF6MGtaTm9CNWln
SFB5Q3V2ZW5FUVpSVkQKCUlBcFJ5YlpqSk9Pc1FoVUY3dGFYVUQwQ0F3RUFBYU9DQXJj
d2dnS3pNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqCglCQmd3Rm9BVVU3ZUV0TEhv
T0R5Vzc2UldMdm96M1BFUWtPQXdIUVlxxlIwT0JCWUVGRlhYTkNqTWlaMzlYVFlGU3B0
TgoJTXFNRlNwcWNNQTRHQTFVZER3RUIvd1FFQXdJSGdEQ0NBbEVHQ2lxR1NJYjNZMlFH
QVE4QkFmOEVnZ0krTVlJQ092K0UKCTZvV2NVSUlCd1RDQ0FiMFdCRTFCVGxBeGdnR3ov
NFNTdVlaSUREQUtGZ1JDVGtOSW9RSUZBUCtFa3Iya1JBd3dDaFlFCglRazlTUktBQ0JR
RC9oSnFWb0U4TE1Ba1dCRU5GVUU4Q0FRSC9oSnFoa2xBTk1Bc1dCRU5JU1ZBQ0F3Q0JF
UCtFbXNHawoJVHd3d0NoWUVRMUJTVDZBQ0JxRCxxSnJxxWtNTU1Bb1dCRU5UUlVPZ0Fn
VUEvNFNxalpKRUREQUtGZ1JGUTBsRW9BSUYKCUFQK0ZtcEdlVFFzd0NSWUVVMFJQVFFJ
QkFmK0dpOVh3YVF3d0NoWUVZWFY0YWFFQ0JRRC9ob3ZWOEhBTU1Bb1dCR0YxCgllSENo
QWdVQS80Ymp2Y1J2Q3pBSkZnUnNiMkp2QVFILy80Ymp3ZHhvRERBS0ZnUnNjRzVvb1FJ
RkFQK0c4ODNTYUF3dwoJQ2hZRWJxxxBxS0FDQlFEL2g1TzkzR2dNTUFvV0JISnZibWln
QWdVQS80ZVR3ZHhvRERBS0ZnUnljRzVvb1FJRkFQK0gKCW02WGdNQXd3Q2hZRWMybHdN
S0VDQlFEL2g1dWw0REVNTUFvV0JITnBjREdoQWdVQS80ZWJwZUF5RERBS0ZnUnphWEF5
CglvUUlGQVArSG02WGdNd3d3Q2hZRWMybHdNNkVDQlFEL2g1dTF4REFNTUFvV0JITnRZ
akNoQWdVQS80ZWJ0Y1F4RERBSwoJRmdSemJXSXhvUUlGQVArSG03WEVNZ3d3Q2hZRWMy
MWlNcUVDQlFEL2g3UFYwbVFNTUFvV0JIWjFhV1NnQWdVQS80VDYKCWlaUlFhVEJuRmdS
UFFrcFFNVi8vaEtLZHBsUU1NQW9XQkVSSFUxU2dBZ1VBLzRTaXdhUlBEREFLRmdSRVVG
SlBvUUlGCglBUCtFb3MyS1F3d3dDaFlFUkZORlE2RUNCUUQvaEtyQnBFOE1NQW9XQkVW
UVVrK2hBZ1VBLzRTcXpZcEREREFLRmdSRgoJVTBWRG9RSUZBREFOQmdrcWhraUc5dzBC
QVF3RkFBT0NBZ0VBalRUWGVyeE9pMnRWbkNUdXBYR3ZJZW5FQWRLNnZKZ28KCVJaTFNo
TFo0NGFqNnYySS93V1NKblE1T1VBdGJaNEdiL1RSblZIOUV1dEtZZks0cC9GVlJOZVUv
c0w2UjRHZEI2TGV0CgkwbWNKWkpSN2xtaUtUQmtMaFBYcnZsaU9qM2hQRlMxWHhCNDBT
YzU2SlJ6L3REMlpjM1VPSmFNZDZza2YxR3FRd3BUaQoJUzgxVU5zS3JNVmtpc0R5YXYv
VWxTQmpKM1hyazBCMmN1YVNpVjRaUXhZaSs0ZjRaSXUyZDQ2Y3lBMEJ3YXhBd0UwNFkK
CU1OdDZVUXl2Y0R4VUxrMU5oUzhUbEtvMVJLczM3UWJxY2k4bUdMOU52M2N4NThjN3B4
czBNT2VKMVY1UmNtRGxxZWVLCgliTEtTc3BnUTRLNkFHaTJwL3VsckI0YWsxU3lZZGky
UVlMUUw5TmU3dHhlMXE3c0Zlcmw0RnluOVZGZ2F1aVIreGlvQgoJaXpMcFZWblNPa1RR
SGgzVEtNbVpEUS9MUDdscUNrcnVCOHZPRGYxV3dITzNOQityVTRXZlBZeERyazJqOWln
a1pDdzEKCStjVFdWMmozU2lIekk1WUQ5WGRWZmNpZklOTktiNnhhckhuODdpQkh2Rmgv
M3hKekVqUzZTclI2WEpRTi9RU0FTTXpMCglnVkZRUXFxaHM0N1ZRNmlOS0NjZnZpR21U
aXFoOE5vWVh1ZXUrME1Rdm5kb3NtcjUzelQzMEFTVWt0TTJnNFBKeDBuawoJUHN1dTVy
SVVaK3pKeWd6YjVmKzlhSXRHYkNUZEdwajM4YldYR0U3aWRXYTJuQlh6bnBVbDgyd3Fh
MlpWMHE1OFp2N20KCTBXY09ZWlRxcnVOSTcxRTVXd1duMWFCdzZQRlFOeG0xQlBOcFhS
MD0KCTwvZGF0YT4KCTxrZXk+T0lEU1RvSW5jbHVkZTwva2V5PgoJPGFycmF5PgoJCTxz
dHJpbmc+MS4yLjg0MC4xMTM2MzUuMTAwLjEwLjE8L3N0cmluZz4KCTwvYXJyYXk+Cgk8
a2V5Pk9zQnVpbGRWZXJzaW9uPC9rZXk+Cgk8c3RyaW5nPjIwRTI1Mjwvc3RyaW5nPgoJ
PGtleT5SS0NlcnRpZmljYXRpb25QdWI8L2tleT4KCTxkYXRhPgoJQkgvL3VxQ1FzNEE0
VElCdm1ZTWNJQkhiaGo1d0ZURkJaaDU3d2JkL0hTU25aSi9ZeE5YandIZ1FhZzlkandM
Vk84VjkKCS9DUHk2dDhmbURvbXM1TFpmYVE9Cgk8L2RhdGE+Cgk8a2V5PlNJS1B1Yjwv
a2V5PgoJPGRhdGE+CglCUHpXTnFSZk1MYmZCNTE0ZXorMWdXNG5vRzZxWGRMa3VySTYz
Y0NXSlRaall5cHVQVWIvUVZnNmJySUg5M2VUREd3QwoJMFJHTERuYjF3VjlPOHhSWkxM
ODVSNGdZMVJMeGw0ZnlmYkxLbzUrVHNoQk01bkYyckRlU0hMOG43cEFVOGc9PQoJPC9k
YXRhPgoJPGtleT5TZWN1cml0eURvbWFpbjwva2V5PgoJPGludGVnZXI+MTwvaW50ZWdl
cj4KCTxrZXk+U2VyaWFsTnVtYmVyPC9rZXk+Cgk8c3RyaW5nPkY2WDQzOU5IRjk8L3N0
cmluZz4KCTxrZXk+VUlLUHViPC9rZXk+Cgk8ZGF0YT4KCUJEOHVOckcvaWJvL1RzbVg5
a3JlVHZvS1N5WW1pZ2Z4UTJzTndTODVSb20rNy90TDBUM2toMlByTVlhWithZTlidWdq
CglNVWxFTkxFOHBGUTFaTjdmSkprPQoJPC9kYXRhPgoJPGtleT5VbmlxdWVDaGlwSUQ8
L2tleT4KCTxpbnRlZ2VyPjY4NzE1NDQ5NTU0MTI1MTA8L2ludGVnZXI+Cgk8a2V5PlZh
bGlkaXR5PC9rZXk+Cgk8aW50ZWdlcj40NDExODY8L2ludGVnZXI+Cgk8a2V5PnNjcnRB
dHRlc3RhdGlvbjwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4KPC9kaWN0Pgo8L3Bs
aXN0Pgo=
</data>
<key>RKPropertiesSignature</key>
<data>
MEYCIQD6alE5at+gOBxxxxxxYAIVZ6QwFJb7Q5lWdv/s95rSZAIhALu+7s0YPJu8LtN9
O19Svcb46Vhw2CKF9Txv7GNheg+6
</data>
</dict>
</plist>
即使hook伪造 MGCopyAnswer获取的的设备 ID,也不能伪造成另一台真机,因为底层 attestation 必须由那台真机的 SE 自签。单纯在软件层面篡改 UniqueChipID 时,服务器端会发现 “你上报的设备 ID 和 attestation 里的(或服务器已有记录里的)设备硬件身份对不上”。
服务验签没问题后会返回正常的激活两本证书
-----BEGIN CERTIFICATE-----
MIIDQTCCAuagAwIBAgIGAZrdcv7/MAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh
c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j
LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTEyMDEwNTA0NTJaFw0yNjA3MzEx
MTMzNTJaMIGRMUkwRwYDVQQDDEA4YmQzNmIxNWZkNGViODgxZjZlYzNlYzE1MjJh
NjlhNzE2ZGY1YTIxNzAxZmZlNTc1NWUwMmQ0MmVjZWRhYTVjMRowGAYDVQQLDBFC
QUEgQ2VydGlmaWNhdGlvbjETMBEGx1xECgwKQXBwbGUgSW5jLjETMBEGA1UECAwK
Q2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZRvBj8pkr4rDSb
r4x137hYn/JvpfSXJpuvcTL0XXwhvK5s/TDrhpp07/n3Vo/1GDz3DyDjGbOdIci2
6U4h54GjggFlMIIBYTAMBgNVHRMBAf8EAxxAMA4GA1UdDwEB/wQEAwIE8DCCAT8G
CSqGSIb3Y2QKAQSCATAEggEsMYIBKP+EmqGsUA0wCxYEQ0hJUAIDAIEQ/4SqjZJE
ETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRi
bWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1
MDY4NTU1/4ebydxtFDASFgRzcm5tBApGNlg0MzlOSEY5/4erkdJkIzAhFgR1ZGlk
BBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF/4e7tcJjGzAZFgR3bWFjBBFhYzox
NjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2VpZAQwMDQyRDI3QzU4QTE2OTAwMjIz
MzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VFQzdCMAoGCCqGSM49BAMCA0kAMEYC
IQCkVmdn5P6/mipbxpLOX7j9tTZ0ob4x2GzYsMeNF7mnwAIhAJgrskCv3xq9xR/Q
CaBYl+b8Ju0i2Jk5xxxxxxxxxx=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCxxIKxZIzj0EAwIwUzEnMCUGA1UEAwwe
QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy
MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg
Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3
StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD
VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj
8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG
MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv
W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ
/hgok/34jr93nhS87tOQNdxDS8xxxx=
-----END CERTIFICATE-----
这两本证书就是后面用于计算DeviceCheck Token的,格式解析如下:
3
验证证书有效后缓存在本地keychain,后面计算DeviceCheck Token时会有用到。
2.4、修改设备硬件信息激活验证测试
// ========= 0. Hook MGCopyAnswer =========
var g_mgCopyAnswerHooked = false;
var mgJsCache = {
UniqueChipID: null,
ChipID: null,
BoardId: null,
SecurityDomain: null,
SerialNumber: null,
BuildVersion: null,
UniqueDeviceID: null
};
function hookGestatcopyAnswer() {
try {
if (g_mgCopyAnswerHooked) {
console.log(" MGCopyAnswer already hooked");
return;
}
var mgCopyAnswer = Module.findExportByName(null, "MGCopyAnswer");
if (!mgCopyAnswer) {
console.error("[-] MGCopyAnswer not found");
return;
}
console.log("[+] MGCopyAnswer =", mgCopyAnswer);
Interceptor.attach(mgCopyAnswer, {
onEnter: function (args) {
this.keyStr = null;
try {
var keyObj = new ObjC.Object(args[0]);
var ks = keyObj.toString();
this.keyStr = ks;
console.log("[MGCopyAnswer] key =", ks);
} catch (e) {
console.log("[MGCopyAnswer] key (raw) =", args[0], "err:", e);
}
},
onLeave: function (retval) {
var keyStr = this.keyStr;
var origDesc;
try {
var origObj = new ObjC.Object(retval);
origDesc = origObj.toString();
} catch (e) {
origDesc = "<raw> " + retval;
}
console.log("[MGCopyAnswer] orig =>", origDesc);
if (!CONFIG.patchMGCopyAnswer || !keyStr) {
return;
}
try {
var NSString = ObjC.classes.NSString;
var NSNumber = ObjC.classes.NSNumber;
var NSUUID = ObjC.classes.NSUUID;
var fakeObj = null;
var fixed = CONFIG.fixedMG || {};
var useFixed = CONFIG.useFixedMGValues === true;
switch (keyStr) {
case "UniqueChipID":
case "Uniquechipid": {
var v;
if (useFixed && fixed.UniqueChipID !== undefined) {
v = Number(fixed.UniqueChipID);
} else {
if (mgJsCache.UniqueChipID === null) {
mgJsCache.UniqueChipID = (Math.floor(Math.random() * 0xFFFFFFFF) >>> 0);
}
v = mgJsCache.UniqueChipID;
}
fakeObj = NSNumber.numberWithLongLong_(v);
fakeObj.retain();
console.log(" override UniqueChipID =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "ChipID":
case "Chipid": {
var cVal;
if (useFixed && fixed.ChipID !== undefined) {
cVal = Number(fixed.ChipID);
} else {
if (mgJsCache.ChipID === null) {
mgJsCache.ChipID = (0x2000 + Math.floor(Math.random() * 0x1000)) >>> 0;
}
cVal = mgJsCache.ChipID;
}
fakeObj = NSNumber.numberWithUnsignedInt_(cVal >>> 0);
fakeObj.retain();
console.log(" override ChipID =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "BoardId":
case "BoardID": {
var bVal;
if (useFixed && fixed.BoardId !== undefined) {
bVal = Number(fixed.BoardId);
} else {
if (mgJsCache.BoardId === null) {
mgJsCache.BoardId = 10 + Math.floor(Math.random() * 20);
}
bVal = mgJsCache.BoardId;
}
fakeObj = NSNumber.numberWithUnsignedInt_(bVal >>> 0);
fakeObj.retain();
console.log(" override BoardId =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "SecurityDomain":
case "Securitydomain": {
var sVal;
if (useFixed && fixed.SecurityDomain !== undefined) {
sVal = Number(fixed.SecurityDomain);
} else {
if (mgJsCache.SecurityDomain === null) {
mgJsCache.SecurityDomain = 1;
}
sVal = mgJsCache.SecurityDomain;
}
fakeObj = NSNumber.numberWithUnsignedInt_(sVal >>> 0);
fakeObj.retain();
console.log(" override SecurityDomain =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "SerialNumber":
case "Serialnumber": {
var sn;
if (useFixed && fixed.SerialNumber) {
sn = fixed.SerialNumber.toString();
} else {
if (mgJsCache.SerialNumber === null) {
mgJsCache.SerialNumber = "F" + randHex(11);
}
sn = mgJsCache.SerialNumber;
}
var snCStr = Memory.allocUtf8String(sn);
fakeObj = NSString.stringWithUTF8String_(snCStr);
fakeObj.retain();
console.log(" override SerialNumber =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "BuildVersion":
case "Buildversion": {
var bv;
if (useFixed && fixed.BuildVersion) {
bv = fixed.BuildVersion.toString();
} else {
if (mgJsCache.BuildVersion === null) {
mgJsCache.BuildVersion = "20" + randHex(4);
}
bv = mgJsCache.BuildVersion;
}
var bvCStr = Memory.allocUtf8String(bv);
fakeObj = NSString.stringWithUTF8String_(bvCStr);
fakeObj.retain();
console.log(" override BuildVersion =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
case "UniqueDeviceID": {
var udid;
if (useFixed && fixed.UniqueDeviceID) {
udid = fixed.UniqueDeviceID.toString();
} else {
if (mgJsCache.UniqueDeviceID === null) {
var uuidObj = NSUUID.UUID();
mgJsCache.UniqueDeviceID = uuidObj.UUIDString().toString();
}
udid = mgJsCache.UniqueDeviceID;
}
var udidCStr = Memory.allocUtf8String(udid);
fakeObj = NSString.stringWithUTF8String_(udidCStr);
fakeObj.retain();
console.log(" override UniqueDeviceID =>", fakeObj.toString());
retval.replace(fakeObj.handle);
break;
}
default:
break;
}
} catch (e) {
console.log("[-] MGCopyAnswer patch error:", e);
}
}
});
g_mgCopyAnswerHooked = true;
console.log("[+] Hooked MGCopyAnswer (patch =", CONFIG.patchMGCopyAnswer,
", useFixed =", CONFIG.useFixedMGValues, ")");
} catch (e) {
console.error("[-] hookGestatcopyAnswer failed:", e.stack || e);
}
}
全部更改设备信息服务器会返回错误
-----BEGIN ERROR-----
93:UCRT SCRT SEAL from tabasco is null.
-----END ERROR-----
站在苹果服务器的角度,它收到这些东西之后,大概会做这样几步检测:
1. 验证 SE attestation(由 Apple 根证书/中间证书链签的):
- 检查证书链是否正确、未过期、签名有效
- 从 attestation blob 里取出:
* 这个 key 所在的“安全硬件身份”:比如 Secure Enclave 的某个 ID
* 跟这一块硬件绑定的标识:UniqueChipID/ChipID/SecurityDomain/...(以某种形式存在)
2. 验证 RKPropertiesSignature:
- 用 attestation 里证明的那把 refKey 的 “公钥” 去验签 RKPropertiesSignature
- 确认:RKProperties 确实是 **同一个 SE 里那把 refKey** 签出来的,
而不是你在用户态自己随便弄的 key。
3. 一致性检查:
- 从 attestation / 后端数据库里得到的“真实硬件 ID” 记为 H = {U_real, ChipID_real, ...}
- 从 RKProperties 里解析出你上报的 ID 记为 S = {U_reported, ChipID_reported, ...}
然后做类似:
if U_reported != U_real or ChipID_reported != ChipID_real ...
=> 认为这是“篡改 / 不一致”,直接拒绝,后面的 UCRT/SCRT/SEAL 都不下发
其它字段随机、只保留UniqueChipID、ChipID不改,正常返回证书;
将A手机的UniqueChipID、ChipID替换到B手机,返回如下:
-----BEGIN ERROR-----
29:ECC signature verification failed: signature incorrect.
-----END ERROR-----
-
整体流程与修改信息验证流程
4
-
修改设备信息验证流程
5
-
结论
从上面验证情况来看,硬ID与SE 里的证书是绑定的。SE 里的“根密钥”和“设备证书”是在出厂生产 / 校准阶段由 Apple 写入硬件安全区的,属于“出厂级”的东西。
我改的 MobileGestalt 层(UniqueChipID/ChipID)只是“软件视角的 ID”,并不会改变 SE 里真实的密钥和它生成的签名,所以软改实现激活大概率是不可行的。
三、DeviceCheck 架构与正向流程
DeviceCheck 的工作流程涉及三方交互:客户端 App、系统守护进程 devicecheckd 以及 Apple 服务器。整体流程如下:
6
3.1 核心组件
-
客户端 (App):通过 DCDevice 类发起 Token 生成请求。
-
守护进程 (devicecheckd):iOS 系统内置的守护进程,负责与硬件安全模块(Secure Enclave)通信,执行核心加密操作。
-
Apple Server:接收 Token,验证其合法性,并根据 Token 更新或查询设备的 2-bit 状态。
3.2 bit 状态存储机制
DeviceCheck 允许开发者为每个设备-App 组合存储两个二进制位(00, 01, 10, 11)。
3.3 正向调用流程
-
App 调用 [DCDevice generateTokenWithCompletionHandler:]。
-
请求通过 XPC(跨进程通信)被转发给系统的 com.apple.devicecheckd 服务。
-
devicecheckd 调用底层硬件接口生成加密的 Base64 Token。
-
App 将 Token 发送给开发者的业务服务器。
-
业务服务器调用 Apple API(update_two_bits 或 query_two_bits),验证 Token 并读写状态。
四、逆向分析:揭秘 devicecheckd
通过对 devicecheckd 二进制文件的静态分析与动态调试,分析其核心加密流程。
4.1 关键函数定位
在 App 二进制中搜索客户端获取DeviceCheckenToken调用的api,定位到 [DCDevice generateTokenWithCompletionHandler:]
然后再一步调试到关键方法,但这种方式比较慢,还有一种更方便的方式,根据日志输出字符串定位,下面是生成token过程中输出的日志:
Generating certificate...
Fetched remote public key...
Encrypting data...
Certificate issued, processing..
Using synced timestamp
Returning cached certificates
-[MAAssetQuery getResultsFromMessage:]: Got the query meta data reply for: com.apple.MobileAsset.DeviceCheck, response: 0
Falling back to locally cached key... Asset fetch failed: Error Domain=com.apple.twobit.fetcherror Code=-3100
- 搜索“Generating certificate...”定位到获取公钥的方法,这个密钥后面加密时会用到。
void __fastcall __37__DCCryptoProxyImpl__fetchPublicKey___block_invoke(__int64 a1, void *a2, void *a3)
{
id v5; // x19
id v6; // x20
void *v7; // x23
__int64 v8; // x0
__int64 v9; // x0
NSObject *v10; // x22
_BOOL4 v11; // w0
__int64 v12; // x22
__int64 v13; // x0
void *v14; // x21
int v15; // [xsp+0h] [xbp-50h] BYREF
id v16; // [xsp+4h] [xbp-4Ch]
v5 = objc_retain(a2);
v6 = objc_retain(a3);
v7 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v5, "publicKey"));
objc_release(v7);
v9 = _DCLogSystem(v8);
v10 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v9);
v11 = os_log_type_enabled_1518(v10, OS_LOG_TYPE_DEFAULT);
if ( v7 )
{
if ( v11 )
{
LOWORD(v15) = 0;
_os_log_impl_1398(&dword_446A2E000, v10, OS_LOG_TYPE_DEFAULT, "Fetched remote public key...", (uint8_t *)&v15, 2u);
}
objc_release(v10);
v12 = *(_QWORD *)(a1 + 32);
v13 = objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v5, "publicKey"));
}
else
{
if ( v11 )
{
v15 = 138412290;
v16 = v6;
_os_log_impl_1398(
&dword_446A2E000,
v10,
OS_LOG_TYPE_DEFAULT,
"Falling back to locally cached key... Asset fetch failed: %@",
(uint8_t *)&v15,
0xCu);
}
objc_release(v10);
v12 = *(_QWORD *)(a1 + 32);
v13 = objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSData, "dataWithBytes:length:", &fallback_server_pubkey, 65));
}
v14 = (void *)v13;
(*(void (__fastcall **)(__int64, __int64))(v12 + 16))(v12, v13);
objc_release(v14);
objc_release(v6);
objc_release(v5);
}
尝试用 DCAssetFetcher/MobileAsset 拉最新的远程公钥,如果成功就用它;失败就用代码中默认密钥fallback_server_pubkey 常量,然后把选出来的公钥交回后续逻辑(DCCertificateGenerator 那边去做 ECDH)。
pub key
0000000A9700B010 04 50 D9 34 FA 67 BC F6 F2 DF BF 96
0000000A9700B020 62 9E 0A 72 38 E9 20 5D 75 F2 8C FC D8 4F 35 A6
0000000A9700B030 59 2B BE 05 8A 9C 0F 8E DB CA 2A CB 67 EF B7 74
0000000A9700B040 97 1C A4 5F 7D 85 6A 69 4F B1 B9 C4 0B 94 FB 2E
0000000A9700B050 7A 5A 94 98 B0
**这张证书属于哪一类身份 & 存在哪个抽屉**
KeychainLabel = "2bit-identity"
KeychainAccessGroup = "2bit-identity"
//生成配置信息
id +[DCCryptoUtilities identityCertificateOptions]()
{
void *v0; // x19
__int64 v1; // x0
NSObject *v2; // x20
void *v3; // x22
void *v4; // x23
void *v5; // x24
void *v6; // x21
void *v7; // x22
__CFString *v9; // [xsp+0h] [xbp-A0h] BYREF
_QWORD v10[6]; // [xsp+8h] [xbp-98h] BYREF
_QWORD v11[6]; // [xsp+38h] [xbp-68h] BYREF
__int64 vars8; // [xsp+A8h] [xbp+8h]
v0 = objc_msgSend(&OBJC_CLASS___DCCryptoUtilities, "generateTTL");
v1 = _DCLogSystem(v0);
v2 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v1);
if ( os_log_type_enabled_1518(v2, OS_LOG_TYPE_DEBUG) )
+[DCCryptoUtilities identityCertificateOptions].cold.1(v0, v2);
objc_release(v2);
v10[0] = CFSTR("Validity");
v3 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", v0));
v11[0] = v3;
v11[1] = &__kCFBooleanFalse;
v10[1] = CFSTR("scrtAttestation");
v10[2] = CFSTR("KeychainLabel");
v11[2] = CFSTR("2bit-identity");
v11[3] = CFSTR("2bit-identity");
v10[3] = CFSTR("KeychainAccessGroup");
v10[4] = CFSTR("IgnoreExistingKeychainItems");
v11[4] = &__kCFBooleanFalse;
v10[5] = CFSTR("OIDSToInclude");
v9 = CFSTR("1.2.840.113635.100.10.1");
v4 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSArray, "arrayWithObjects:count:", &v9, 1));
v11[5] = v4;
v5 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSDictionary, "dictionaryWithObjects:forKeys:count:", v11, v10, 6));
v6 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionaryWithDictionary:", v5));
objc_release(v5);
objc_release(v4);
objc_release(v3);
if ( (unsigned int)os_variant_allows_internal_security_policies_55(0) )
{
v7 = objc_msgSend(
objc_alloc((Class)&OBJC_CLASS___NSUserDefaults),
"initWithSuiteName:",
CFSTR("com.apple.DeviceCheck"));
if ( (unsigned int)objc_msgSend(v7, "boolForKey:", CFSTR("DCIgnoreExistingKeychainItems")) )
objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("IgnoreExistingKeychainItems"));
objc_release(v7);
}
if ( (DeviceIdentityUCRTAttestationSupported_1() & 1) == 0 )
objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("scrtAttestation"));
objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("ReturnReferenceDate"));
if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
return objc_autoreleaseReturnValue(v6);
}
//开始读取
void __fastcall __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke(__int64 a1)
{
__int64 v2; // x5
__int64 v3; // x6
__int64 v4; // x7
NSObject *v5; // x20
dispatch_queue_global_t global_queue_364; // x0
__int64 v7; // x19
__int64 v8; // x5
__int64 v9; // x6
__int64 v10; // x7
__SecTask *v11; // x0
__int64 v12; // x5
__int64 v13; // x6
__int64 v14; // x7
__SecTask *v15; // x23
__int64 v16; // x5
__int64 v17; // x6
__int64 v18; // x7
__int64 v19; // x0
void *v20; // x21
unsigned __int8 v21; // w22
void *v22; // x0
id *v23; // x28
void *v24; // x21
__int64 v25; // x0
void *v26; // x22
void *v27; // x21
void *v28; // x22
__int64 v29; // x0
void *v30; // x22
unsigned __int8 v31; // w25
id MobileActivationError_0; // x0
__int64 v33; // x0
id v34; // x0
id v35; // x21
CFDictionaryRef v36; // x25
CFDataRef v37; // x28
void *v38; // x22
void *v39; // x27
__int64 v40; // x8
void *v41; // x26
void *v42; // x9
__int64 *v43; // x8
const void *v44; // x0
__int64 *v45; // x8
const void *v46; // x0
__int64 *v47; // x8
const void *v48; // x0
__int64 *v49; // x8
const void *v50; // x0
__int64 *v51; // x8
const void *v52; // x0
id v53; // x26
id *v54; // x19
id v55; // x0
CFErrorRef v56; // x21
__int64 v57; // x5
__int64 v58; // x6
__int64 v59; // x7
id v60; // x0
__int64 v61; // x0
__int64 v62; // x8
void *v63; // x9
id v64; // x0
bool v65; // w25
__int64 v66; // x5
__int64 v67; // x6
__int64 v68; // x7
char v69; // w26
__int64 v70; // x0
__int64 v71; // x5
__int64 v72; // x6
__int64 v73; // x7
__int64 v74; // x0
__int64 v75; // x5
__int64 v76; // x6
__int64 v77; // x7
__int64 v78; // x21
__int64 v79; // x0
__int64 v80; // x5
__int64 v81; // x6
__int64 v82; // x7
const __CFData *v83; // x21
SecCertificateRef v84; // x0
__int64 v85; // x5
__int64 v86; // x6
__int64 v87; // x7
const __CFData *v88; // x21
SecCertificateRef v89; // x0
__int64 v90; // x5
__int64 v91; // x6
__int64 v92; // x7
id v93; // x0
CFErrorRef v94; // x19
__int64 v95; // x5
__int64 v96; // x6
__int64 v97; // x7
id v98; // x0
__int64 v99; // x0
__int64 v100; // x8
void *v101; // x9
__int64 v102; // x19
__int64 v103; // x5
__int64 v104; // x6
__int64 v105; // x7
__int64 v106; // x19
void *v107; // x3
id *v108; // x19
void *v109; // t1
id v110; // x0
double v111; // d8
__int64 v112; // x5
__int64 v113; // x6
__int64 v114; // x7
__int64 v115; // x19
void *v116; // x3
id *v117; // x19
void *v118; // t1
id v119; // x0
void *v120; // x25
unsigned __int8 v121; // w26
void *v122; // x21
void *v123; // x22
void *v124; // x25
void *v125; // x26
void *v126; // x27
__int64 v127; // x5
__int64 v128; // x6
__int64 v129; // x7
id v130; // x0
int v131; // w21
void *v132; // x3
id v133; // x0
id v134; // x0
id v135; // x0
id v136; // x0
__int64 v137; // x5
__int64 v138; // x6
__int64 v139; // x7
__int64 v140; // x5
__int64 v141; // x6
__int64 v142; // x7
id v143; // x0
void *v144; // x9
__int64 v145; // x5
__int64 v146; // x6
__int64 v147; // x7
__int64 v148; // x5
__int64 v149; // x6
__int64 v150; // x7
CFDataRef v151; // x21
__int64 v152; // x5
__int64 v153; // x6
__int64 v154; // x7
__int64 v155; // x0
__int64 v156; // x21
char v157; // w22
__int64 v158; // x5
__int64 v159; // x6
__int64 v160; // x7
id v161; // x0
void *v162; // x22
__int64 v163; // x0
void *v164; // x21
__int64 v165; // x22
void *v166; // x21
__int64 v167; // x0
void *v168; // x19
void *v169; // x22
__int64 v170; // x5
__int64 v171; // x6
__int64 v172; // x7
id v173; // x0
__int64 v174; // x0
__int64 v175; // x0
void *v176; // x9
__int64 v177; // x5
__int64 v178; // x6
__int64 v179; // x7
void *v180; // x0
__int64 v181; // x0
__int64 v182; // x0
void *v183; // x9
__int64 v184; // x5
__int64 v185; // x6
__int64 v186; // x7
void *v187; // x0
__int64 v188; // x0
__int64 v189; // x0
void *v190; // x9
void *v191; // x0
id v192; // x0
void *v193; // x0
void *v194; // x9
id v195; // x0
id v196; // x0
id v197; // x0
id v198; // x0
id v199; // x0
void *v200; // x21
__int64 v201; // x0
void *v202; // x22
__int64 v203; // x5
__int64 v204; // x6
__int64 v205; // x7
id v206; // x0
void *v207; // x21
__int64 v208; // x0
void *v209; // x22
__int64 v210; // x0
__CFString *v211; // x0
void *v212; // x21
__int64 v213; // x0
void *v214; // x22
void *v215; // x21
unsigned int v216; // w19
void *v217; // x22
__int64 v218; // x5
__int64 v219; // x6
__int64 v220; // x7
id v221; // x0
void *v222; // x22
__int64 v223; // x0
void *v224; // x25
__int64 v225; // x5
__int64 v226; // x6
__int64 v227; // x7
id v228; // x0
void *v229; // x25
__int64 v230; // x0
void *v231; // x26
__int64 v232; // x5
__int64 v233; // x6
__int64 v234; // x7
id v235; // x0
void *v236; // x22
CFTypeID v237; // x25
CFTypeID TypeID_4; // x26
void *v239; // x22
__int64 v240; // x0
void *v241; // x25
void *v242; // x21
void *v243; // x22
__int64 v244; // x0
void *v245; // x25
void *v246; // x21
void *v247; // x25
__int64 v248; // x0
void *v249; // x26
void *v250; // x21
void *v251; // x21
__int64 v252; // x0
void *v253; // x26
void *v254; // x21
__int64 v255; // x0
void *v256; // x26
__int64 v257; // x5
__int64 v258; // x6
__int64 v259; // x7
void *v260; // x25
__int64 v261; // x0
void *v262; // x26
void *v263; // x21
unsigned int v264; // w27
void *v265; // x25
__int64 v266; // x0
void *v267; // x26
void *v268; // x21
unsigned int v269; // w22
void *v270; // x25
__int64 v271; // x0
void *v272; // x26
void *v273; // x19
__int64 v274; // x26
__int64 v275; // x27
__int64 v276; // x22
__int64 v277; // x19
__int64 v278; // x0
id v279; // x0
void *v280; // x21
__int64 v281; // x0
__int64 v282; // x5
__int64 v283; // x6
__int64 v284; // x7
__int64 v285; // x5
__int64 v286; // x6
__int64 v287; // x7
id v288; // x0
id v289; // x0
id v290; // x0
id v291; // x0
__int64 v292; // x0
__int64 v293; // x8
void *v294; // x9
__int64 v295; // x0
__int64 v296; // x25
__int64 v297; // x21
int valid; // w28
__int64 v299; // x0
__int64 v300; // x21
int v301; // w28
__int64 v302; // x21
char v303; // w28
id v304; // x0
__int64 v305; // x0
__int64 v306; // x8
void *v307; // x9
id v308; // x0
void *v309; // x8
__int64 *v310; // x8
const void *v311; // x0
__int64 *v312; // x8
const void *v313; // x0
__int64 *v314; // x8
const void *v315; // x0
__int64 v316; // x8
void *v317; // x9
double v318; // d0
void *v319; // x0
__int64 v320; // x0
char v321; // w19
void *v322; // x8
__int64 v323; // x0
__int64 v324; // x21
__int64 v325; // x21
double v326; // d8
double v327; // d9
double v328; // d0
int v329; // w25
int v330; // w8
id v331; // x0
__int64 v332; // x0
const void *v333; // x0
__SecKey *v334; // x25
__int64 v335; // x2
__int64 v336; // x26
__int64 v337; // x5
__int64 v338; // x6
__int64 v339; // x7
__SecKey *v340; // x0
__int64 v341; // x5
__int64 v342; // x6
__int64 v343; // x7
__int64 v344; // x5
__int64 v345; // x6
__int64 v346; // x7
CFDictionaryRef v347; // x0
__int64 v348; // x5
__int64 v349; // x6
__int64 v350; // x7
__int64 v351; // x5
__int64 v352; // x6
__int64 v353; // x7
void *v354; // x26
dispatch_queue_global_t v355; // x0
__CFString *v356; // x0
__int64 v357; // x8
id v358; // x0
id v359; // x0
id v360; // x0
id v361; // x0
__int64 v362; // x9
void *v363; // x8
const void *v364; // x0
CFTypeRef v365; // x0
id v366; // x0
void *v367; // x0
void *v368; // x0
void *v369; // x0
__int64 v370; // x19
void *v371; // x0
id v372; // x0
__int64 v373; // x8
id v374; // x19
id v375; // x0
id v376; // x0
id v377; // x0
id v378; // x0
id v379; // x0
id v380; // x0
__int64 v381; // x9
__int64 *v382; // x8
__int64 *v383; // x9
char v384; // [xsp+0h] [xbp-680h]
void *v385; // [xsp+18h] [xbp-668h]
id v386; // [xsp+20h] [xbp-660h]
void *v387; // [xsp+28h] [xbp-658h]
id v388; // [xsp+30h] [xbp-650h]
__int64 v389; // [xsp+38h] [xbp-648h]
void *v390; // [xsp+38h] [xbp-648h]
int v391; // [xsp+40h] [xbp-640h]
unsigned int v392; // [xsp+40h] [xbp-640h]
__int64 v393; // [xsp+40h] [xbp-640h]
void *v394; // [xsp+40h] [xbp-640h]
_BOOL4 v395; // [xsp+48h] [xbp-638h]
void *v396; // [xsp+48h] [xbp-638h]
_BOOL4 v397; // [xsp+50h] [xbp-630h]
void *v398; // [xsp+50h] [xbp-630h]
_BOOL4 v399; // [xsp+58h] [xbp-628h]
id v400; // [xsp+58h] [xbp-628h]
void *queue; // [xsp+60h] [xbp-620h]
_BOOL4 queuea; // [xsp+60h] [xbp-620h]
unsigned int queueb; // [xsp+60h] [xbp-620h]
NSObject *queuec; // [xsp+60h] [xbp-620h]
id queued; // [xsp+60h] [xbp-620h]
id v406; // [xsp+68h] [xbp-618h]
void *v407; // [xsp+70h] [xbp-610h]
id v408; // [xsp+78h] [xbp-608h]
void *v409; // [xsp+80h] [xbp-600h]
id v410; // [xsp+88h] [xbp-5F8h]
id v411; // [xsp+90h] [xbp-5F0h]
void *v412; // [xsp+98h] [xbp-5E8h]
id v413; // [xsp+A0h] [xbp-5E0h]
CFDataRef v414; // [xsp+A8h] [xbp-5D8h]
unsigned int v415; // [xsp+A8h] [xbp-5D8h]
unsigned int v416; // [xsp+A8h] [xbp-5D8h]
id v417; // [xsp+B0h] [xbp-5D0h]
id v418; // [xsp+B8h] [xbp-5C8h]
id v419; // [xsp+C0h] [xbp-5C0h]
unsigned __int8 v420; // [xsp+C0h] [xbp-5C0h]
void *v421; // [xsp+C8h] [xbp-5B8h]
__CFString *v422; // [xsp+D0h] [xbp-5B0h]
void *cf; // [xsp+D8h] [xbp-5A8h]
void *cfa; // [xsp+D8h] [xbp-5A8h]
id v425; // [xsp+E0h] [xbp-5A0h]
_QWORD block[4]; // [xsp+E8h] [xbp-598h] BYREF
_QWORD v427[4]; // [xsp+108h] [xbp-578h] BYREF
_QWORD v428[4]; // [xsp+128h] [xbp-558h] BYREF
id v429; // [xsp+148h] [xbp-538h] BYREF
__CFString *v430; // [xsp+150h] [xbp-530h]
id v431; // [xsp+158h] [xbp-528h]
id v432; // [xsp+160h] [xbp-520h]
id v433; // [xsp+168h] [xbp-518h]
id v434; // [xsp+170h] [xbp-510h]
id v435; // [xsp+178h] [xbp-508h]
id v436; // [xsp+180h] [xbp-500h]
id v437; // [xsp+188h] [xbp-4F8h]
id v438; // [xsp+190h] [xbp-4F0h]
id v439; // [xsp+198h] [xbp-4E8h]
id v440; // [xsp+1A0h] [xbp-4E0h]
id v441; // [xsp+1A8h] [xbp-4D8h]
NSObject *v442; // [xsp+1B0h] [xbp-4D0h]
id v443; // [xsp+1B8h] [xbp-4C8h]
__int64 v444; // [xsp+1C0h] [xbp-4C0h]
_QWORD *v445; // [xsp+1C8h] [xbp-4B8h]
__int64 *v446; // [xsp+1D0h] [xbp-4B0h]
__int64 *v447; // [xsp+1D8h] [xbp-4A8h]
__int64 *v448; // [xsp+1E0h] [xbp-4A0h]
__int64 *v449; // [xsp+1E8h] [xbp-498h]
__int64 *v450; // [xsp+1F0h] [xbp-490h]
__int64 *v451; // [xsp+1F8h] [xbp-488h]
__int64 *v452; // [xsp+200h] [xbp-480h]
__int64 *v453; // [xsp+208h] [xbp-478h]
__int64 *v454; // [xsp+210h] [xbp-470h]
__int64 *v455; // [xsp+218h] [xbp-468h]
__int64 *v456; // [xsp+220h] [xbp-460h]
__int64 *v457; // [xsp+228h] [xbp-458h]
__int64 *v458; // [xsp+230h] [xbp-450h]
__int64 *v459; // [xsp+238h] [xbp-448h]
__int64 *v460; // [xsp+240h] [xbp-440h]
__int64 *v461; // [xsp+248h] [xbp-438h]
bool v462; // [xsp+250h] [xbp-430h]
id v463; // [xsp+258h] [xbp-428h] BYREF
id v464; // [xsp+260h] [xbp-420h]
id v465; // [xsp+268h] [xbp-418h] BYREF
id v466; // [xsp+270h] [xbp-410h] BYREF
id v467; // [xsp+278h] [xbp-408h] BYREF
id obj; // [xsp+280h] [xbp-400h] BYREF
id v469; // [xsp+288h] [xbp-3F8h] BYREF
id v470; // [xsp+290h] [xbp-3F0h] BYREF
id v471; // [xsp+298h] [xbp-3E8h] BYREF
__int64 v472; // [xsp+2A0h] [xbp-3E0h] BYREF
double *v473; // [xsp+2A8h] [xbp-3D8h]
__int64 v474; // [xsp+2B0h] [xbp-3D0h]
__int64 v475; // [xsp+2B8h] [xbp-3C8h]
__int64 v476; // [xsp+2C0h] [xbp-3C0h] BYREF
__int64 *v477; // [xsp+2C8h] [xbp-3B8h]
__int64 v478; // [xsp+2D0h] [xbp-3B0h]
int v479; // [xsp+2D8h] [xbp-3A8h]
int v480; // [xsp+2E4h] [xbp-39Ch] BYREF
double v481; // [xsp+2E8h] [xbp-398h] BYREF
__int64 v482; // [xsp+2F0h] [xbp-390h] BYREF
double *v483; // [xsp+2F8h] [xbp-388h]
__int64 v484; // [xsp+300h] [xbp-380h]
__int64 v485; // [xsp+308h] [xbp-378h]
__int64 v486; // [xsp+310h] [xbp-370h] BYREF
__int64 *v487; // [xsp+318h] [xbp-368h]
__int64 v488; // [xsp+320h] [xbp-360h]
__int64 (__fastcall *v489)(); // [xsp+328h] [xbp-358h]
__int64 (__fastcall *v490)(); // [xsp+330h] [xbp-350h]
id v491; // [xsp+338h] [xbp-348h]
__int64 v492; // [xsp+340h] [xbp-340h] BYREF
__int64 *v493; // [xsp+348h] [xbp-338h]
__int64 v494; // [xsp+350h] [xbp-330h]
__int64 (__fastcall *v495)(); // [xsp+358h] [xbp-328h]
__int64 (__fastcall *v496)(); // [xsp+360h] [xbp-320h]
id v497; // [xsp+368h] [xbp-318h]
__int64 v498; // [xsp+370h] [xbp-310h] BYREF
__int64 *v499; // [xsp+378h] [xbp-308h]
__int64 v500; // [xsp+380h] [xbp-300h]
__int64 (__fastcall *v501)(); // [xsp+388h] [xbp-2F8h]
__int64 (__fastcall *v502)(); // [xsp+390h] [xbp-2F0h]
id v503; // [xsp+398h] [xbp-2E8h]
__int64 v504; // [xsp+3A0h] [xbp-2E0h] BYREF
__int64 *v505; // [xsp+3A8h] [xbp-2D8h]
__int64 v506; // [xsp+3B0h] [xbp-2D0h]
__int64 (__fastcall *v507)(); // [xsp+3B8h] [xbp-2C8h]
__int64 (__fastcall *v508)(); // [xsp+3C0h] [xbp-2C0h]
id v509; // [xsp+3C8h] [xbp-2B8h]
__int64 v510; // [xsp+3D0h] [xbp-2B0h] BYREF
__int64 *v511; // [xsp+3D8h] [xbp-2A8h]
__int64 v512; // [xsp+3E0h] [xbp-2A0h]
__int64 (__fastcall *v513)(); // [xsp+3E8h] [xbp-298h]
__int64 (__fastcall *v514)(); // [xsp+3F0h] [xbp-290h]
id v515; // [xsp+3F8h] [xbp-288h]
__int64 v516; // [xsp+400h] [xbp-280h] BYREF
__int64 *v517; // [xsp+408h] [xbp-278h]
__int64 v518; // [xsp+410h] [xbp-270h]
__int64 (__fastcall *v519)(); // [xsp+418h] [xbp-268h]
__int64 (__fastcall *v520)(); // [xsp+420h] [xbp-260h]
id v521; // [xsp+428h] [xbp-258h]
int v522; // [xsp+434h] [xbp-24Ch] BYREF
__int64 v523; // [xsp+438h] [xbp-248h] BYREF
__int64 *v524; // [xsp+440h] [xbp-240h]
__int64 v525; // [xsp+448h] [xbp-238h]
__int64 v526; // [xsp+450h] [xbp-230h]
__int64 v527; // [xsp+458h] [xbp-228h] BYREF
__int64 *v528; // [xsp+460h] [xbp-220h]
__int64 v529; // [xsp+468h] [xbp-218h]
__int64 v530; // [xsp+470h] [xbp-210h]
CFErrorRef error; // [xsp+478h] [xbp-208h] BYREF
__int64 v532; // [xsp+480h] [xbp-200h] BYREF
__int64 *v533; // [xsp+488h] [xbp-1F8h]
__int64 v534; // [xsp+490h] [xbp-1F0h]
__int64 v535; // [xsp+498h] [xbp-1E8h]
__int64 v536; // [xsp+4A0h] [xbp-1E0h] BYREF
__int64 *v537; // [xsp+4A8h] [xbp-1D8h]
__int64 v538; // [xsp+4B0h] [xbp-1D0h]
__int64 v539; // [xsp+4B8h] [xbp-1C8h]
__int64 v540; // [xsp+4C0h] [xbp-1C0h] BYREF
__int64 *v541; // [xsp+4C8h] [xbp-1B8h]
__int64 v542; // [xsp+4D0h] [xbp-1B0h]
__int64 v543; // [xsp+4D8h] [xbp-1A8h]
__int64 v544; // [xsp+4E0h] [xbp-1A0h] BYREF
__int64 *v545; // [xsp+4E8h] [xbp-198h]
__int64 v546; // [xsp+4F0h] [xbp-190h]
__int64 v547; // [xsp+4F8h] [xbp-188h]
__int64 v548; // [xsp+500h] [xbp-180h] BYREF
id *v549; // [xsp+508h] [xbp-178h]
__int64 v550; // [xsp+510h] [xbp-170h]
__int64 (__fastcall *v551)(); // [xsp+518h] [xbp-168h]
__int64 (__fastcall *v552)(); // [xsp+520h] [xbp-160h]
id v553; // [xsp+528h] [xbp-158h]
_QWORD v554[5]; // [xsp+530h] [xbp-150h] BYREF
id v555; // [xsp+558h] [xbp-128h]
uint8_t buf[4]; // [xsp+560h] [xbp-120h] BYREF
void *v557; // [xsp+564h] [xbp-11Ch]
__int16 v558; // [xsp+56Ch] [xbp-114h]
id v559; // [xsp+56Eh] [xbp-112h]
__int16 v560; // [xsp+576h] [xbp-10Ah]
id v561; // [xsp+578h] [xbp-108h]
__int16 v562; // [xsp+580h] [xbp-100h]
void *v563; // [xsp+582h] [xbp-FEh]
__int16 v564; // [xsp+58Ah] [xbp-F6h]
id v565; // [xsp+58Ch] [xbp-F4h]
__int16 v566; // [xsp+594h] [xbp-ECh]
id v567; // [xsp+596h] [xbp-EAh]
__int16 v568; // [xsp+59Eh] [xbp-E2h]
__int64 v569; // [xsp+5A0h] [xbp-E0h]
__int64 v570; // [xsp+5B0h] [xbp-D0h]
_QWORD v571[3]; // [xsp+5B8h] [xbp-C8h] BYREF
__int64 v572; // [xsp+5D0h] [xbp-B0h] BYREF
__CFString *v573; // [xsp+5D8h] [xbp-A8h] BYREF
void *v574; // [xsp+5E0h] [xbp-A0h] BYREF
__CFString *v575; // [xsp+5E8h] [xbp-98h] BYREF
void *v576; // [xsp+5F0h] [xbp-90h] BYREF
v554[0] = 0;
v554[1] = v554;
v554[2] = 0x3032000000LL;
v554[3] = __Block_byref_object_copy__4684;
v554[4] = __Block_byref_object_dispose__4684;
v555 = 0;
v548 = 0;
v549 = (id *)&v548;
v550 = 0x3032000000LL;
v551 = __Block_byref_object_copy__4684;
v552 = __Block_byref_object_dispose__4684;
v553 = 0;
v544 = 0;
v545 = &v544;
v546 = 0x2020000000LL;
v547 = 0;
v540 = 0;
v541 = &v540;
v542 = 0x2020000000LL;
v543 = 0;
v536 = 0;
v537 = &v536;
v538 = 0x2020000000LL;
v539 = 0;
v532 = 0;
v533 = &v532;
v534 = 0x2020000000LL;
v535 = 0;
error = 0;
v527 = 0;
v528 = &v527;
v529 = 0x2020000000LL;
v530 = 0;
v523 = 0;
v524 = &v523;
v525 = 0x2020000000LL;
v526 = 0;
v522 = -1;
v516 = 0;
v517 = &v516;
v518 = 0x3032000000LL;
v519 = __Block_byref_object_copy__4684;
v520 = __Block_byref_object_dispose__4684;
v521 = 0;
v510 = 0;
v511 = &v510;
v512 = 0x3032000000LL;
v513 = __Block_byref_object_copy__4684;
v514 = __Block_byref_object_dispose__4684;
v515 = 0;
v504 = 0;
v505 = &v504;
v506 = 0x3032000000LL;
v507 = __Block_byref_object_copy__4684;
v508 = __Block_byref_object_dispose__4684;
v509 = 0;
v498 = 0;
v499 = &v498;
v500 = 0x3032000000LL;
v501 = __Block_byref_object_copy__4684;
v502 = __Block_byref_object_dispose__4684;
v503 = 0;
v492 = 0;
v493 = &v492;
v494 = 0x3032000000LL;
v495 = __Block_byref_object_copy__4684;
v496 = __Block_byref_object_dispose__4684;
v497 = 0;
v486 = 0;
v487 = &v486;
v488 = 0x3032000000LL;
v489 = __Block_byref_object_copy__4684;
v490 = __Block_byref_object_dispose__4684;
v491 = 0;
v482 = 0;
v483 = (double *)&v482;
v484 = 0x2020000000LL;
v485 = 0;
v481 = 0.0;
v480 = 0;
v476 = 0;
v477 = &v476;
v478 = 0x2020000000LL;
v479 = 0;
v472 = 0;
v473 = (double *)&v472;
v474 = 0x2020000000LL;
v475 = 0;
v5 = (NSObject *)objc_retain(*(id *)(a1 + 32));
if ( !v5 )
{
global_queue_364 = j__dispatch_get_global_queue_364(0, 0);
v7 = objc_claimAutoreleasedReturnValue_556(global_queue_364);
objc_release(0);
v5 = (NSObject *)v7;
}
if ( !*(_QWORD *)(a1 + 48) )
{
MobileActivationError_0 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
989,
-1,
0,
CFSTR("Invalid input."),
v2,
v3,
v4,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(MobileActivationError_0);
LABEL_20:
v425 = 0;
LABEL_21:
v35 = 0;
v421 = 0;
v422 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
v417 = 0;
v408 = 0;
v409 = 0;
v410 = 0;
v411 = 0;
v412 = 0;
v413 = 0;
v418 = 0;
v419 = 0;
cf = 0;
v15 = 0;
LABEL_22:
v406 = 0;
v407 = 0;
LABEL_23:
v40 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v41 = *(void **)(v40 + 40);
*(_QWORD *)(v40 + 40) = v33;
goto LABEL_24;
}
v425 = objc_alloc_init((Class)off_41CEDE910);
if ( !v425 )
{
v34 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
995,
-1,
0,
CFSTR("Failed to allocate array."),
v8,
v9,
v10,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v34);
goto LABEL_20;
}
v11 = SecTaskCreateFromSelf_87(0);
v15 = v11;
if ( !v11 )
{
v55 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1003,
-1,
0,
CFSTR("Failed to create task."),
v12,
v13,
v14,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v55);
goto LABEL_21;
}
v422 = (__CFString *)SecTaskCopySigningIdentifier_25(v11, &error);
if ( !v422 )
{
v64 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1009,
-1,
error,
CFSTR("Failed to query code signing identifier."),
v16,
v17,
v18,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v64);
v35 = 0;
v421 = 0;
v422 = 0;
LABEL_47:
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
v417 = 0;
v408 = 0;
v409 = 0;
v410 = 0;
v411 = 0;
v412 = 0;
v413 = 0;
v418 = 0;
v419 = 0;
LABEL_48:
cf = 0;
goto LABEL_22;
}
v421 = (void *)SecTaskCopyValueForEntitlement_98(v15, CFSTR("com.apple.mobileactivationd.spi"), &error);
v19 = isNSNumber_0(v421);
v20 = (void *)objc_claimAutoreleasedReturnValue_556(v19);
if ( !v20 || (v21 = (unsigned __int8)objc_msgSend(v421, "boolValue"), objc_release(v20), (v21 & 1) == 0) )
{
v56 = error;
v575 = CFSTR("com.apple.mobileactivationd.spi");
v576 = &__kCFBooleanTrue;
v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE908, "dictionaryWithObjects:forKeys:count:", &v576, &v575, 1));
v60 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1015,
-7,
v56,
CFSTR("Missing required entitlement: %@"),
v57,
v58,
v59,
(char)v41);
v61 = objc_claimAutoreleasedReturnValue_556(v60);
LABEL_45:
v62 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v63 = *(void **)(v62 + 40);
*(_QWORD *)(v62 + 40) = v61;
objc_release(v63);
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
v417 = 0;
v408 = 0;
v409 = 0;
v410 = 0;
v411 = 0;
v412 = 0;
v413 = 0;
v418 = 0;
v419 = 0;
cf = 0;
v406 = 0;
v407 = 0;
goto LABEL_24;
}
v23 = (id *)(a1 + 40);
v22 = *(void **)(a1 + 40);
if ( !v22 )
{
queuea = 0;
v395 = 0;
v418 = 0;
v419 = 0;
v65 = 0;
v399 = 0;
v406 = 0;
v407 = 0;
v412 = 0;
v413 = 0;
v409 = 0;
v410 = 0;
v417 = 0;
v411 = 0;
v408 = 0;
cf = 0;
v397 = 1;
goto LABEL_50;
}
v24 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v22, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v25 = isNSArray();
v26 = (void *)objc_claimAutoreleasedReturnValue_556(v25);
objc_release(v26);
objc_release(v24);
if ( v26 )
{
v27 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v27, "containsObject:", CFSTR("1.2.840.113635.100.10.1")) & 1) == 0 )
{
v28 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( !(unsigned int)objc_msgSend(v28, "containsObject:", CFSTR("1.2.840.113635.100.8.1")) )
{
v120 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v121 = (unsigned __int8)objc_msgSend(v120, "containsObject:", CFSTR("1.2.840.113635.100.8.3"));
objc_release(v120);
objc_release(v28);
objc_release(v27);
if ( (v121 & 1) == 0 )
goto LABEL_71;
goto LABEL_15;
}
objc_release(v28);
}
objc_release(v27);
LABEL_15:
queue = (void *)SecTaskCopyValueForEntitlement_98(
v15,
CFSTR("com.apple.mobileactivationd.device-identifiers"),
&error);
objc_release(v421);
v29 = isNSNumber_0(queue);
v30 = (void *)objc_claimAutoreleasedReturnValue_556(v29);
if ( !v30 || (v31 = (unsigned __int8)objc_msgSend(queue, "boolValue"), objc_release(v30), (v31 & 1) == 0) )
{
v94 = error;
v573 = CFSTR("com.apple.mobileactivationd.device-identifiers");
v574 = &__kCFBooleanTrue;
v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE908, "dictionaryWithObjects:forKeys:count:", &v574, &v573, 1));
v98 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1028,
-7,
v94,
CFSTR("Missing required entitlement: %@"),
v95,
v96,
v97,
(char)v41);
v99 = objc_claimAutoreleasedReturnValue_556(v98);
v100 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v101 = *(void **)(v100 + 40);
*(_QWORD *)(v100 + 40) = v99;
objc_release(v101);
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
v417 = 0;
v408 = 0;
v409 = 0;
v410 = 0;
v411 = 0;
v412 = 0;
v413 = 0;
v418 = 0;
v419 = 0;
cf = 0;
v406 = 0;
v407 = 0;
v421 = queue;
goto LABEL_24;
}
v421 = queue;
LABEL_71:
v122 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v122, "containsObject:", CFSTR("1.2.840.113635.100.8.9.1")) & 1) != 0 )
{
LABEL_80:
objc_release(v122);
LABEL_81:
v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v130 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1039,
-2,
0,
CFSTR("This API does not support Enterprise Device Attestation OIDs: %@"),
v127,
v128,
v129,
(char)v41);
v61 = objc_claimAutoreleasedReturnValue_556(v130);
goto LABEL_45;
}
v123 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v123, "containsObject:", CFSTR("1.2.840.113635.100.8.9.2")) & 1) != 0 )
{
LABEL_79:
objc_release(v123);
goto LABEL_80;
}
v124 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v124, "containsObject:", CFSTR("1.2.840.113635.100.8.10.1")) & 1) != 0 )
{
LABEL_78:
objc_release(v124);
goto LABEL_79;
}
v125 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v125, "containsObject:", CFSTR("1.2.840.113635.100.8.10.2")) & 1) != 0 )
{
LABEL_77:
objc_release(v125);
goto LABEL_78;
}
v126 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v126, "containsObject:", CFSTR("1.2.840.113635.100.8.10.3")) & 1) != 0 )
{
objc_release(v126);
goto LABEL_77;
}
cfa = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v420 = (unsigned __int8)objc_msgSend(cfa, "containsObject:", CFSTR("1.2.840.113635.100.8.11.1"));
objc_release(cfa);
objc_release(v126);
objc_release(v125);
objc_release(v124);
objc_release(v123);
objc_release(v122);
if ( (v420 & 1) != 0 )
goto LABEL_81;
v168 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
if ( ((unsigned int)objc_msgSend(v168, "containsObject:", CFSTR("1.2.840.113635.100.8.6")) & 1) != 0 )
{
v169 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
objc_release(v169);
objc_release(v168);
if ( !v169 )
{
v173 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1044,
-2,
0,
CFSTR("Missing required option: %@"),
v170,
v171,
v172,
(char)CFSTR("AccessControls"));
v33 = objc_claimAutoreleasedReturnValue_556(v173);
LABEL_139:
v35 = 0;
goto LABEL_47;
}
}
else
{
objc_release(v168);
}
}
v200 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainLabel")));
v201 = isNSString_0();
v202 = (void *)objc_claimAutoreleasedReturnValue_556(v201);
objc_release(v202);
objc_release(v200);
if ( v202 )
{
if ( (isRunningInRootLaunchdContext() & 1) != 0
|| (isRunningInRecovery() & 1) != 0
|| (unsigned int)isRunningInDiagnosticsMode() )
{
v206 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1058,
-2,
0,
CFSTR("Option (%@) not allowed for processes running in the system context or diagnostics mode."),
v203,
v204,
v205,
(char)CFSTR("KeychainLabel"));
v33 = objc_claimAutoreleasedReturnValue_556(v206);
goto LABEL_139;
}
v222 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v223 = isNSData_0();
v224 = (void *)objc_claimAutoreleasedReturnValue_556(v223);
objc_release(v224);
objc_release(v222);
if ( v224 )
{
v228 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1063,
-2,
0,
CFSTR("Keychain (%@) not supported with %@."),
v225,
v226,
v227,
(char)CFSTR("KeychainLabel"));
v33 = objc_claimAutoreleasedReturnValue_556(v228);
goto LABEL_139;
}
v418 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainLabel")));
v417 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-rk"), v418));
v412 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-leaf"), v418));
v409 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-intermediate"), v418));
v413 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-combined"), v418));
v411 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-monotonic-clock"), v418));
v408 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-server-timestamp"), v418));
v384 = (char)v418;
v410 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-rtc-reset-count")));
}
else
{
v417 = 0;
v418 = 0;
v412 = 0;
v413 = 0;
v409 = 0;
v410 = 0;
v411 = 0;
v408 = 0;
}
v207 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainAccessGroup")));
v208 = isNSString_0();
v209 = (void *)objc_claimAutoreleasedReturnValue_556(v208);
objc_release(v209);
objc_release(v207);
if ( v209 )
v210 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainAccessGroup")));
else
v210 = 0;
if ( v418 && !v210 )
{
v211 = objc_retain(v422);
v210 = (__int64)v422;
}
v419 = (id)v210;
v212 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("IgnoreExistingKeychainItems")));
v213 = isNSNumber_0(v212);
v214 = (void *)objc_claimAutoreleasedReturnValue_556(v213);
objc_release(v214);
objc_release(v212);
if ( v214 )
{
v215 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("IgnoreExistingKeychainItems")));
v216 = (unsigned int)objc_msgSend(v215, "boolValue");
objc_release(v215);
}
else
{
v216 = 0;
}
v217 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
objc_release(v217);
if ( !v217 )
goto LABEL_163;
if ( (isRunningInRootLaunchdContext() & 1) != 0
|| (isRunningInRecovery() & 1) != 0
|| (unsigned int)isRunningInDiagnosticsMode() )
{
v221 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1092,
-2,
0,
CFSTR("Option (%@) not allowed for processes running in the system context or diagnostics mode."),
v218,
v219,
v220,
(char)CFSTR("AccessControls"));
v33 = objc_claimAutoreleasedReturnValue_556(v221);
LABEL_155:
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
goto LABEL_48;
}
v229 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v230 = isNSData_0();
v231 = (void *)objc_claimAutoreleasedReturnValue_556(v230);
objc_release(v231);
objc_release(v229);
if ( v231 )
{
v235 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1097,
-2,
0,
CFSTR("ACLs (%@) not supported with %@."),
v232,
v233,
v234,
(char)CFSTR("AccessControls"));
v33 = objc_claimAutoreleasedReturnValue_556(v235);
goto LABEL_155;
}
v236 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
v237 = CFGetTypeID_254(v236);
TypeID_4 = SecAccessControlGetTypeID_4();
objc_release(v236);
if ( v237 == TypeID_4 )
{
cf = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
objc_release(cf);
CFRetain_262(cf);
}
else
{
LABEL_163:
cf = 0;
}
v239 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("reuseExistingKey")));
v240 = isNSNumber_0(v239);
v241 = (void *)objc_claimAutoreleasedReturnValue_556(v240);
objc_release(v241);
objc_release(v239);
if ( v241 )
{
v242 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("reuseExistingKey")));
v415 = (unsigned int)objc_msgSend(v242, "boolValue");
objc_release(v242);
}
else
{
v415 = 0;
}
v243 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
v244 = isNSNumber_0(v243);
v245 = (void *)objc_claimAutoreleasedReturnValue_556(v244);
objc_release(v245);
objc_release(v243);
if ( v245 )
{
v246 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
queueb = (unsigned int)objc_msgSend(v246, "boolValue");
objc_release(v246);
}
else
{
queueb = 1;
}
v247 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
v248 = isNSNumber_0(v247);
v249 = (void *)objc_claimAutoreleasedReturnValue_556(v248);
objc_release(v249);
objc_release(v247);
if ( v249 )
{
v250 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
v392 = (unsigned int)objc_msgSend(v250, "boolValue");
objc_release(v250);
}
else
{
v392 = 0;
}
v251 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v252 = isNSData_0();
v253 = (void *)objc_claimAutoreleasedReturnValue_556(v252);
objc_release(v253);
objc_release(v251);
if ( v253 )
{
v254 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
v255 = isNSData_0();
v256 = (void *)objc_claimAutoreleasedReturnValue_556(v255);
objc_release(v256);
objc_release(v254);
if ( !v256 )
{
v279 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1121,
-2,
0,
CFSTR("Missing required option for %@."),
v257,
v258,
v259,
(char)CFSTR("ClientAttestationPublicKey"));
v33 = objc_claimAutoreleasedReturnValue_556(v279);
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
goto LABEL_22;
}
v407 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
v406 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
}
else
{
v406 = 0;
v407 = 0;
}
v260 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ReturnReferenceDate")));
v261 = isNSNumber_0(v260);
v262 = (void *)objc_claimAutoreleasedReturnValue_556(v261);
objc_release(v262);
objc_release(v260);
if ( v262 )
{
v263 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ReturnReferenceDate")));
v264 = (unsigned int)objc_msgSend(v263, "boolValue");
objc_release(v263);
}
else
{
v264 = 0;
}
v265 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("SkipNetworkRequest")));
v266 = isNSNumber_0(v265);
v267 = (void *)objc_claimAutoreleasedReturnValue_556(v266);
objc_release(v267);
objc_release(v265);
if ( v267 )
{
v268 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("SkipNetworkRequest")));
v269 = (unsigned int)objc_msgSend(v268, "boolValue");
objc_release(v268);
}
else
{
v269 = 0;
}
v270 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("DeleteExistingKeysAndCerts")));
v271 = isNSNumber_0(v270);
v272 = (void *)objc_claimAutoreleasedReturnValue_556(v271);
objc_release(v272);
objc_release(v270);
v399 = v415 != 0;
v65 = v216 != 0;
v397 = queueb != 0;
v395 = v264 != 0;
queuea = v269 != 0;
if ( v272 )
{
v273 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("DeleteExistingKeysAndCerts")));
v416 = (unsigned int)objc_msgSend(v273, "boolValue");
objc_release(v273);
if ( !v417 )
{
v417 = 0;
if ( !v416 )
goto LABEL_199;
LABEL_194:
v35 = 0;
if ( v418 && v419 )
{
delete_keychain_data(v419, v411, 0);
delete_keychain_data(v419, v410, 0);
delete_keychain_data(v419, v408, 0);
delete_keychain_data(v419, v413, 0);
delete_keychain_item(v419, v417, 0);
delete_certificate(v419, v412, 0);
delete_certificate(v419, v409, 0);
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
}
else
{
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
}
goto LABEL_25;
}
}
else
{
if ( !v417 )
{
v417 = 0;
goto LABEL_199;
}
LOBYTE(v416) = 0;
}
if ( v392 )
{
v393 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v417, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v417);
v389 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v412, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v412);
v274 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v409, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v409);
v275 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v413, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v413);
v276 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v411, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v411);
v277 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v408, "stringByAppendingString:", CFSTR("-scrt")));
objc_release(v408);
v278 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v410, "stringByAppendingString:", CFSTR("-scrt")));
}
else
{
v393 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v417, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v417);
v389 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v412, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v412);
v274 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v409, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v409);
v275 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v413, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v413);
v276 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v411, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v411);
v277 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v408, "stringByAppendingString:", CFSTR("-ucrt")));
objc_release(v408);
v278 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v410, "stringByAppendingString:", CFSTR("-ucrt")));
}
v280 = (void *)v278;
objc_release(v410);
v408 = (id)v277;
v409 = (void *)v274;
v410 = v280;
v411 = (id)v276;
v417 = (id)v393;
v412 = (void *)v389;
v413 = (id)v275;
if ( (v416 & 1) != 0 )
goto LABEL_194;
LABEL_199:
if ( v407 )
{
if ( cf )
CFRelease_438(cf);
v281 = SecAccessControlCreate_3(0, &error);
cf = (void *)v281;
if ( !v281 )
{
v289 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1195,
-1,
error,
CFSTR("Failed to create access control."),
v282,
v283,
v284,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v289);
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
cf = 0;
goto LABEL_23;
}
if ( (SecAccessControlSetProtection_3(v281, CFSTR("f"), &error) & 1) == 0 )
{
v288 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1200,
-1,
error,
CFSTR("Failed to set ACL protection to %@."),
v285,
v286,
v287,
(char)CFSTR("f"));
v33 = objc_claimAutoreleasedReturnValue_556(v288);
goto LABEL_86;
}
}
else
{
v407 = 0;
}
LABEL_50:
if ( (isRunningInRecovery() & 1) != 0 )
{
v69 = 0;
}
else
{
v102 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v471 = *(id *)(v102 + 40);
v69 = isAutomaticTimeEnabledWithError(&v471);
j__objc_storeStrong_550((id *)(v102 + 40), v471);
v106 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v109 = *(void **)(v106 + 40);
v108 = (id *)(v106 + 40);
v107 = v109;
if ( (v69 & 1) == 0 && v107 )
{
v110 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1212,
-1,
v107,
CFSTR("Failed to query automatic time state."),
v103,
v104,
v105,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v110);
goto LABEL_86;
}
v470 = v107;
v111 = copyMonotonicClock(&v470);
j__objc_storeStrong_550(v108, v470);
v483[3] = v111;
v115 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v118 = *(void **)(v115 + 40);
v117 = (id *)(v115 + 40);
v116 = v118;
if ( v111 == 0.0 )
{
v119 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1218,
-1,
v116,
CFSTR("Failed to query monotonic clock."),
v112,
v113,
v114,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v119);
goto LABEL_86;
}
v469 = v116;
v131 = copyRTCResetCountWithError(&v469);
j__objc_storeStrong_550(v117, v469);
*((_DWORD *)v477 + 6) = v131;
if ( !v131 )
{
v132 = *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL);
if ( v132 )
{
v133 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1224,
-1,
v132,
CFSTR("Failed to query RTC reset count."),
v66,
v67,
v68,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v133);
goto LABEL_86;
}
}
}
v35 = 0;
v414 = 0;
v39 = 0;
v38 = 0;
if ( v65 || !v418 )
goto LABEL_248;
v70 = copy_keychain_item(v419, v417, *v23, &v522, 0);
v533[3] = v70;
if ( v522 != -25300 && v522 )
{
v134 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1234,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing reference key (%@/%@): %d"),
v71,
v72,
v73,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v134);
goto LABEL_86;
}
v74 = copy_keychain_data(v419, v413, &v522, 0);
v414 = (CFDataRef)objc_claimAutoreleasedReturnValue_556(v74);
if ( v522 != -25300 && v522 )
{
v135 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1240,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing leaf/intermediate certificates (%@/%@): %d"),
v75,
v76,
v77,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v135);
goto LABEL_88;
}
if ( !v414 )
{
load_certificate(v528 + 3, v419, v412, &v522, 0);
if ( v522 != -25300 && v522 )
{
v161 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1272,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing leaf certificate (%@/%@): %d"),
v137,
v138,
v139,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v161);
}
else
{
load_certificate(v524 + 3, v419, v409, &v522, 0);
if ( v522 != -25300 && v522 )
{
v196 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1278,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing intermediate certificate (%@/%@): %d"),
v140,
v141,
v142,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v196);
}
else
{
if ( !v528[3] || !v524[3] )
{
v414 = 0;
goto LABEL_104;
}
v143 = objc_alloc_init((Class)off_41CEDE9A8);
v144 = (void *)v517[5];
v517[5] = (__int64)v143;
objc_release(v144);
if ( v517[5] )
{
v151 = SecCertificateCopyData_23((SecCertificateRef)v528[3]);
if ( !v151 )
{
v377 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1291,
-1,
0,
CFSTR("Failed to copy certificate data."),
v148,
v149,
v150,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v377);
goto LABEL_86;
}
objc_msgSend((id)v517[5], "appendData:", v151);
v414 = SecCertificateCopyData_23((SecCertificateRef)v524[3]);
objc_release(v151);
if ( !v414 )
{
v379 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1299,
-1,
0,
CFSTR("Failed to copy certificate data."),
v152,
v153,
v154,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v379);
goto LABEL_86;
}
objc_msgSend((id)v517[5], "appendData:", v414);
v155 = v517[5];
v156 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v467 = *(id *)(v156 + 40);
v157 = store_keychain_data(v155, v419, v413, &v467);
j__objc_storeStrong_550((id *)(v156 + 40), v467);
if ( (v157 & 1) != 0 )
{
delete_certificate(v419, v412, 0);
delete_certificate(v419, v409, 0);
LABEL_104:
v39 = 0;
goto LABEL_105;
}
v380 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1306,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to store leaf/intermediate certificates."),
v158,
v159,
v160,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v380);
LABEL_88:
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
goto LABEL_23;
}
v199 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1285,
-1,
0,
CFSTR("Failed to allocate data."),
v145,
v146,
v147,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v199);
}
}
LABEL_86:
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
v39 = 0;
v414 = 0;
goto LABEL_23;
}
v78 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
obj = *(id *)(v78 + 40);
v79 = parseDERCertificatesFromChain_0(v414, &obj);
v39 = (void *)objc_claimAutoreleasedReturnValue_556(v79);
j__objc_storeStrong_550((id *)(v78 + 40), obj);
if ( !v39 || objc_msgSend(v39, "count") != (void *)2 )
{
v136 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1251,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to parse DER certificate chain."),
v80,
v81,
v82,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v136);
goto LABEL_90;
}
v83 = (const __CFData *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v39, "objectAtIndexedSubscript:", 0));
v84 = SecCertificateCreateWithData_33(0, v83);
v528[3] = (__int64)v84;
objc_release(v83);
if ( !v528[3] )
{
v197 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1257,
-1,
0,
CFSTR("Failed to create certificate from DER data."),
v85,
v86,
v87,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v197);
goto LABEL_90;
}
v88 = (const __CFData *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v39, "objectAtIndexedSubscript:", 1));
v89 = SecCertificateCreateWithData_33(0, v88);
v524[3] = (__int64)v89;
objc_release(v88);
if ( !v524[3] )
{
v93 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1263,
-1,
0,
CFSTR("Failed to create certificate from DER data."),
v90,
v91,
v92,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v93);
LABEL_90:
v35 = 0;
v36 = 0;
v37 = 0;
v38 = 0;
goto LABEL_23;
}
LABEL_105:
if ( (isRunningInRecovery() & 1) == 0 )
{
v174 = copy_keychain_data(v419, v411, &v522, 0);
v175 = objc_claimAutoreleasedReturnValue_556(v174);
v176 = (void *)v487[5];
v487[5] = v175;
objc_release(v176);
if ( v522 != -25300 && v522 )
{
v198 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1318,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing motononic time (%@/%@): %d"),
v177,
v178,
v179,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v198);
goto LABEL_90;
}
v180 = (void *)v487[5];
if ( v180 )
objc_msgSend(v180, "getBytes:length:", &v481, 8);
v181 = copy_keychain_data(v419, v410, &v522, 0);
v182 = objc_claimAutoreleasedReturnValue_556(v181);
v183 = (void *)v511[5];
v511[5] = v182;
objc_release(v183);
if ( v522 != -25300 && v522 )
{
v290 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1328,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing RTC reset count (%@/%@): %d"),
v184,
v185,
v186,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v290);
goto LABEL_90;
}
v187 = (void *)v511[5];
if ( v187 )
objc_msgSend(v187, "getBytes:length:", &v480, 4);
v188 = copy_keychain_data(v419, v408, &v522, 0);
v189 = objc_claimAutoreleasedReturnValue_556(v188);
v190 = (void *)v505[5];
v505[5] = v189;
objc_release(v190);
if ( v522 != -25300 && v522 )
{
v378 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1338,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to query existing server timestamp (%@/%@): %d"),
v66,
v67,
v68,
(char)v419);
v33 = objc_claimAutoreleasedReturnValue_556(v378);
goto LABEL_90;
}
v191 = (void *)v505[5];
if ( v191 )
{
objc_msgSend(v191, "getBytes:length:", v473 + 3, 8);
v192 = objc_alloc((Class)off_41CEDE958);
v193 = objc_msgSend(v192, "initWithTimeIntervalSinceReferenceDate:", v473[3]);
v194 = (void *)v493[5];
v493[5] = (__int64)v193;
objc_release(v194);
if ( !v493[5] )
{
v195 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1347,
-1,
0,
CFSTR("Failed to create date from server timestamp."),
v66,
v67,
v68,
v384);
v33 = objc_claimAutoreleasedReturnValue_556(v195);
goto LABEL_90;
}
}
}
if ( !v533[3] || !v528[3] )
{
v38 = 0;
LABEL_130:
v391 = 0;
goto LABEL_211;
}
v162 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v163 = isNSArray();
v164 = (void *)objc_claimAutoreleasedReturnValue_556(v163);
objc_release(v164);
objc_release(v162);
if ( v164 )
{
v165 = v528[3];
v166 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
v167 = copyCertificateOIDsThatDiffer(v165, v166);
v38 = (void *)objc_claimAutoreleasedReturnValue_556(v167);
objc_release(v166);
}
else
{
v38 = 0;
}
if ( !objc_msgSend(v38, "count") )
goto LABEL_130;
v291 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1365,
-1,
0,
CFSTR("Mismatch in requested OIDs and existing certificate's OIDs (%@)."),
v66,
v67,
v68,
(char)v38);
v292 = objc_claimAutoreleasedReturnValue_556(v291);
v293 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v294 = *(void **)(v293 + 40);
*(_QWORD *)(v293 + 40) = v292;
objc_release(v294);
v391 = 1;
LABEL_211:
if ( v533[3] )
{
if ( (unsigned int)isFactoryMFiCertificate(v419, v528[3]) )
{
v295 = v533[3];
v296 = a1 + 56;
v297 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v466 = *(id *)(v297 + 40);
valid = validSecureEnclaveReferenceKey(v295, 1, 0, &v466);
j__objc_storeStrong_550((id *)(v297 + 40), v466);
if ( !valid )
goto LABEL_221;
}
}
v299 = v533[3];
if ( !v299 )
goto LABEL_219;
v296 = a1 + 56;
v300 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v465 = *(id *)(v300 + 40);
v301 = validSecureEnclaveReferenceKey(v299, 0, 0, &v465);
j__objc_storeStrong_550((id *)(v300 + 40), v465);
if ( !v301
|| v533[3]
&& v528[3]
&& (v302 = *(_QWORD *)(*(_QWORD *)v296 + 8LL),
v464 = *(id *)(v302 + 40),
v303 = certificatePublicKeyMatchesBIKPublicKey(),
j__objc_storeStrong_550((id *)(v302 + 40), v464),
(v303 & 1) == 0) )
{
LABEL_221:
v304 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1385,
-2,
*(void **)(*(_QWORD *)(*(_QWORD *)v296 + 8LL) + 40LL),
CFSTR("Invalid reference key."),
v66,
v67,
v68,
v384);
v305 = objc_claimAutoreleasedReturnValue_556(v304);
v306 = *(_QWORD *)(*(_QWORD *)v296 + 8LL);
v307 = *(void **)(v306 + 40);
*(_QWORD *)(v306 + 40) = v305;
objc_release(v307);
}
else
{
LABEL_219:
if ( !v391 )
goto LABEL_231;
}
v308 = objc_retain(&_os_log_default_0);
if ( os_log_type_enabled_632((os_log_t)&_os_log_default_0, OS_LOG_TYPE_DEFAULT) )
{
v309 = *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL);
*(_DWORD *)buf = 138412290;
v557 = v309;
_os_log_impl_600(
&dword_40E4FC000,
(os_log_t)&_os_log_default_0,
OS_LOG_TYPE_DEFAULT,
"Deleting invalid keys/certificates: %@",
buf,
0xCu);
}
objc_release(&_os_log_default_0);
delete_keychain_data(v419, v411, 0);
delete_keychain_data(v419, v410, 0);
delete_keychain_data(v419, v408, 0);
delete_keychain_data(v419, v413, 0);
delete_keychain_item(v419, v417, 0);
delete_certificate(v419, v412, 0);
delete_certificate(v419, v409, 0);
v310 = v533;
v311 = (const void *)v533[3];
if ( v311 )
{
CFRelease_438(v311);
v310 = v533;
}
v310[3] = 0;
v312 = v528;
v313 = (const void *)v528[3];
if ( v313 )
{
CFRelease_438(v313);
v312 = v528;
}
v312[3] = 0;
v314 = v524;
v315 = (const void *)v524[3];
if ( v315 )
{
CFRelease_438(v315);
v314 = v524;
}
v314[3] = 0;
v316 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v317 = *(void **)(v316 + 40);
*(_QWORD *)(v316 + 40) = 0;
objc_release(v317);
LABEL_231:
if ( !v533[3] || !v528[3] || !v524[3] )
goto LABEL_247;
if ( (isRunningInRecovery() & 1) != 0 || (v69 & 1) != 0 || (v318 = v481, v481 == 0.0) || (v319 = (void *)v493[5]) == 0 )
{
v323 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE958, "date", v318));
v322 = (void *)v499[5];
v499[5] = v323;
v321 = 1;
}
else
{
v320 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v319, "dateByAddingTimeInterval:", v483[3] - v481));
v321 = 0;
v322 = (void *)v499[5];
v499[5] = v320;
}
objc_release(v322);
v324 = v528[3];
objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate");
if ( !(unsigned int)SecCertificateIsValid_2(v324)
|| (v325 = v524[3],
objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate"),
!(unsigned int)SecCertificateIsValid_2(v325)) )
{
v330 = 0;
v329 = 0;
if ( (v321 & 1) == 0 )
goto LABEL_276;
goto LABEL_246;
}
v326 = SecCertificateNotValidAfter_8(v528[3]);
v327 = SecCertificateNotValidBefore_7(v528[3]);
objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate");
if ( v328 - SecCertificateNotValidBefore_7(v528[3]) >= (v326 - v327) * 0.9 )
{
v330 = 1;
v329 = 1;
if ( (v321 & 1) == 0 )
goto LABEL_276;
LABEL_246:
if ( v330 )
goto LABEL_277;
LABEL_247:
v35 = 0;
goto LABEL_248;
}
v329 = 0;
v330 = 1;
if ( (v321 & 1) != 0 )
goto LABEL_246;
LABEL_276:
if ( ((unsigned __int8)v330 & (*((_DWORD *)v477 + 6) == v480)) == 0 )
goto LABEL_247;
LABEL_277:
if ( v395 )
{
v381 = v524[3];
v571[1] = v528[3];
v571[2] = v381;
v382 = &v572;
v383 = v499 + 5;
}
else
{
v570 = v528[3];
v382 = v571;
v383 = v524 + 3;
}
*v382 = *v383;
v35 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE918, "arrayWithObjects:count:"));
if ( v329 )
{
LABEL_248:
if ( queuea )
{
v331 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1470,
-1,
0,
CFSTR("Missing or expired certificates, and network request explictly not attempted."),
v66,
v67,
v68,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v331);
}
else
{
if ( v399 && (v333 = (const void *)v533[3]) != 0 )
{
v334 = (__SecKey *)CFRetain_262(v333);
v541[3] = (__int64)v334;
}
else
{
v335 = *(_QWORD *)(a1 + 40);
v336 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v463 = *(id *)(v336 + 40);
v334 = (__SecKey *)createReferenceKeyBlob(cf, v397, v335, &v463);
j__objc_storeStrong_550((id *)(v336 + 40), v463);
v541[3] = (__int64)v334;
if ( !v334 )
{
v360 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1481,
-1,
*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
CFSTR("Failed to create reference key."),
v337,
v338,
v339,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v360);
goto LABEL_262;
}
}
v340 = SecKeyCopyPublicKey_11(v334);
v537[3] = (__int64)v340;
if ( v340 )
{
v37 = SecKeyCopyExternalRepresentation_13(v340, &error);
if ( v37 )
{
v347 = SecKeyCopyAttributes_8((SecKeyRef)v541[3]);
v36 = v347;
if ( v347 )
{
v354 = (void *)objc_claimAutoreleasedReturnValue_556(-[__CFDictionary objectForKeyedSubscript:](v347, "objectForKeyedSubscript:", CFSTR("toid")));
if ( v354 )
{
v355 = j__dispatch_get_global_queue_364(0, 0);
queuec = (NSObject *)objc_claimAutoreleasedReturnValue_556(v355);
v428[0] = &_NSConcreteStackBlock_0;
v428[1] = 3221225472LL;
v428[2] = __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke_2;
v428[3] = &unk_41974FD50;
v54 = &v429;
v429 = objc_retain(*(id *)(a1 + 40));
v356 = objc_retain(v422);
v357 = *(_QWORD *)(a1 + 56);
v430 = v356;
v444 = v357;
v53 = objc_retain(v354);
v431 = v53;
v445 = v554;
v446 = &v498;
v358 = objc_retain(v425);
v462 = v395;
v425 = v358;
v432 = v358;
v447 = &v516;
v448 = &v540;
v406 = objc_retain(v406);
v433 = v406;
v418 = objc_retain(v418);
v434 = v418;
v419 = objc_retain(v419);
v435 = v419;
v413 = objc_retain(v413);
v436 = v413;
v417 = objc_retain(v417);
v437 = v417;
v411 = objc_retain(v411);
v438 = v411;
v410 = objc_retain(v410);
v439 = v410;
v408 = objc_retain(v408);
v440 = v408;
v449 = &v486;
v450 = &v482;
v451 = &v510;
v452 = &v476;
v453 = &v472;
v454 = &v504;
v455 = &v544;
v456 = &v548;
v457 = &v532;
v458 = &v527;
v459 = &v523;
v35 = objc_retain(v35);
v441 = v35;
v460 = &v492;
v442 = objc_retain(v5);
v443 = objc_retain(*(id *)(a1 + 48));
v461 = &v536;
j__dispatch_async_488(queuec, v428);
objc_release(queuec);
objc_release(v443);
objc_release(v442);
objc_release(v441);
objc_release(v440);
objc_release(v439);
objc_release(v438);
objc_release(v437);
objc_release(v436);
objc_release(v435);
objc_release(v434);
objc_release(v433);
objc_release(v432);
objc_release(v431);
objc_release(v430);
goto LABEL_36;
}
v376 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1532,
-1,
error,
CFSTR("Failed to encode RK as data."),
v351,
v352,
v353,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v376);
goto LABEL_264;
}
v375 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1526,
-1,
error,
CFSTR("Failed to copy RK attributes."),
v348,
v349,
v350,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v375);
LABEL_263:
v36 = 0;
LABEL_264:
v362 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
v363 = *(void **)(v362 + 40);
*(_QWORD *)(v362 + 40) = v332;
objc_release(v363);
goto LABEL_265;
}
v361 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1494,
-1,
error,
CFSTR("Failed to encode RK public key as data."),
v344,
v345,
v346,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v361);
}
else
{
v359 = createMobileActivationError_0(
(__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
1488,
-1,
0,
CFSTR("Failed to copy RK public key."),
v341,
v342,
v343,
v384);
v332 = objc_claimAutoreleasedReturnValue_556(v359);
}
}
LABEL_262:
v37 = 0;
goto LABEL_263;
}
v37 = 0;
v36 = 0;
LABEL_265:
v364 = (const void *)v533[3];
if ( !v364 || !v35 )
goto LABEL_25;
v365 = CFRetain_262(v364);
v545[3] = (__int64)v365;
j__objc_storeStrong_550(v549 + 5, v35);
v41 = &_os_log_default_0;
v366 = objc_retain(&_os_log_default_0);
if ( os_log_type_enabled_632((os_log_t)&_os_log_default_0, OS_LOG_TYPE_DEFAULT) )
{
v394 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
v398 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
v367 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidBefore_7(v398));
v388 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v367));
v396 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
v368 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidAfter_8(v396));
queued = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v368));
v387 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
v390 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
v369 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidBefore_7(v390));
v400 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v369));
v370 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
v371 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidAfter_8(v370));
v372 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v371));
v373 = v493[5];
*(_DWORD *)buf = 138544898;
v557 = v394;
v558 = 2114;
v559 = v388;
v560 = 2114;
v561 = queued;
v562 = 2114;
v385 = (void *)v370;
v386 = v372;
v563 = v387;
v564 = 2114;
v565 = v400;
v566 = 2114;
v567 = v372;
v374 = v372;
v568 = 2114;
v569 = v373;
v41 = &_os_log_default_0;
_os_log_impl_600(
&dword_40E4FC000,
(os_log_t)&_os_log_default_0,
OS_LOG_TYPE_DEFAULT,
"Returning cached certificates:\n"
"* %{public}@\n"
" Not Valid Before: %{public}@\n"
" Not Valid After: %{public}@\n"
"* %{public}@\n"
" Not Valid Before: %{public}@\n"
" Not Valid After: %{public}@\n"
"* Server Timestamp: %{public}@\n",
buf,
0x48u);
objc_release(v374);
objc_release(v385);
objc_release(v400);
objc_release(v390);
objc_release(v387);
objc_release(queued);
objc_release(v396);
objc_release(v388);
objc_release(v398);
objc_release(v394);
objc_release(v386);
objc_release(v400);
objc_release(queued);
objc_release(v388);
}
LABEL_24:
objc_release(v41);
LABEL_25:
block[0] = &_NSConcreteStackBlock_0;
block[1] = 3221225472LL;
block[2] = __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke_309;
block[3] = &unk_41974FD00;
v42 = *(void **)(a1 + 48);
v427[1] = *(_QWORD *)(a1 + 56);
v427[0] = objc_retain(v42);
v427[2] = &v544;
v427[3] = &v548;
j__dispatch_async_488(v5, block);
v43 = v541;
v44 = (const void *)v541[3];
if ( v44 )
{
CFRelease_438(v44);
v43 = v541;
}
v43[3] = 0;
v45 = v537;
v46 = (const void *)v537[3];
if ( v46 )
{
CFRelease_438(v46);
v45 = v537;
}
v45[3] = 0;
v47 = v533;
v48 = (const void *)v533[3];
if ( v48 )
{
CFRelease_438(v48);
v47 = v533;
}
v47[3] = 0;
v49 = v528;
v50 = (const void *)v528[3];
if ( v50 )
{
CFRelease_438(v50);
v49 = v528;
}
v49[3] = 0;
v51 = v524;
v52 = (const void *)v524[3];
if ( v52 )
{
CFRelease_438(v52);
v51 = v524;
}
v53 = 0;
v54 = (id *)v427;
v51[3] = 0;
LABEL_36:
objc_release(*v54);
if ( v15 )
CFRelease_438(v15);
if ( error )
CFRelease_438(error);
error = 0;
if ( cf )
CFRelease_438(cf);
_Block_object_dispose_549(&v472, 8);
_Block_object_dispose_549(&v476, 8);
_Block_object_dispose_549(&v482, 8);
objc_release(v5);
objc_release(v38);
objc_release(v422);
_Block_object_dispose_549(&v486, 8);
objc_release(v491);
_Block_object_dispose_549(&v492, 8);
objc_release(v497);
_Block_object_dispose_549(&v498, 8);
objc_release(v503);
_Block_object_dispose_549(&v504, 8);
objc_release(v509);
_Block_object_dispose_549(&v510, 8);
objc_release(v515);
_Block_object_dispose_549(&v516, 8);
objc_release(v521);
objc_release(v39);
objc_release(v414);
objc_release(v408);
objc_release(v411);
objc_release(v410);
objc_release(v417);
objc_release(v409);
objc_release(v412);
objc_release(v413);
objc_release(v419);
objc_release(v418);
_Block_object_dispose_549(&v523, 8);
_Block_object_dispose_549(&v527, 8);
_Block_object_dispose_549(&v532, 8);
_Block_object_dispose_549(&v536, 8);
_Block_object_dispose_549(&v540, 8);
_Block_object_dispose_549(&v544, 8);
objc_release(v406);
objc_release(v407);
objc_release(v37);
objc_release(v36);
objc_release(v53);
objc_release(v421);
_Block_object_dispose_549(&v548, 8);
objc_release(v553);
objc_release(v35);
objc_release(v425);
_Block_object_dispose_549(v554, 8);
objc_release(v555);
}
identityCertificateOptions 用来构造“我想要一张什么样的 identity 证书”;
DeviceIdentityIssueClientCertificateWithCompletion 则负责根据这些参数检查调用方权限、复用或重新签发 attestation 证书链,并在 keychain 中维护一整套“证书 + SE key + 时间防回拨信息”的档案。流程如下:
7
读取激活证书后准备加密生成token。
组合参数
_SecCertificateCopyData
id __fastcall __66__DCCertificateGenerator__generateCertificateChainWithCompletion___block_invoke(
__int64 a1,
__int64 a2)
{
void *v2; // x27
__int64 v3; // x0
__int64 v4; // x0
__int64 v5; // x21
__int64 v6; // x0
__int64 v7; // x0
__int64 v8; // x23
unsigned __int64 v9; // x0
void *v10; // x28
char v11; // w9
__int64 v12; // x2
char v13; // w8
char v14; // w19
char v15; // w26
__int64 v16; // x20
__int64 v17; // x0
void *v18; // x21
void *v19; // x26
void *v20; // x24
char *v21; // x22
int v22; // w28
int v23; // w27
char *v24; // x25
char *v25; // x0
char *v26; // x20
char *v27; // x28
void *v28; // x25
NSError *v29; // x0
NSError *v30; // x0
NSError *v31; // x0
__int64 v32; // x0
__int64 v33; // x0
__int64 v34; // x0
void *v35; // x0
__int64 v36; // x21
int v37; // w19
__int64 v38; // x0
__int64 v39; // x0
__int64 v40; // x0
__int64 v41; // x20
__int64 v42; // x0
void *v43; // x0
__int64 v44; // x0
__int64 v45; // x0
__int64 v46; // x0
__int64 v47; // x0
__int64 v48; // x0
__int64 v49; // x0
__int64 v50; // x0
__int64 v51; // x0
id result; // x0
NSError *v53; // x0
__int64 v54; // x0
unsigned int v55; // w20
__int64 v56; // x20
__int64 v57; // x0
__int64 v58; // x0
__int64 v59; // x22
__int64 v60; // x0
__int64 v61; // x0
__int64 v62; // x20
__int64 v63; // x0
NSError *v64; // x0
__int64 v65; // x20
__int64 v66; // x0
DCCertificateGenerator *v67; // x0
SEL v68; // x1
id v69; // x2
id v70; // x3
id *v71; // x4
__int64 v72; // [xsp+0h] [xbp-180h]
unsigned __int64 v73; // [xsp+10h] [xbp-170h]
void *v75; // [xsp+20h] [xbp-160h]
void *v77; // [xsp+30h] [xbp-150h]
void *v78; // [xsp+40h] [xbp-140h]
char v79; // [xsp+48h] [xbp-138h]
char v80; // [xsp+4Ch] [xbp-134h]
__int64 v81; // [xsp+50h] [xbp-130h] BYREF
__CFString *v82; // [xsp+58h] [xbp-128h] BYREF
__int64 v83; // [xsp+60h] [xbp-120h] BYREF
__CFString *v84; // [xsp+68h] [xbp-118h] BYREF
__int64 v85; // [xsp+70h] [xbp-110h] BYREF
__CFString *v86; // [xsp+78h] [xbp-108h] BYREF
char __src[16]; // [xsp+80h] [xbp-100h] BYREF
__int128 v88; // [xsp+90h] [xbp-F0h]
__int128 v89; // [xsp+A0h] [xbp-E0h]
__int128 v90; // [xsp+B0h] [xbp-D0h]
__int128 v91; // [xsp+C0h] [xbp-C0h]
char __str[16]; // [xsp+D0h] [xbp-B0h] BYREF
__int128 v93; // [xsp+E0h] [xbp-A0h]
__int128 v94; // [xsp+F0h] [xbp-90h]
__int128 v95; // [xsp+100h] [xbp-80h]
__int128 v96; // [xsp+110h] [xbp-70h]
unsigned __int64 v97; // [xsp+120h] [xbp-60h]
v97 = 0x8FCA7F6773E200E4LL;
v2 = (void *)objc_retain_x2_1310();
v3 = ((__int64 (*)(void))MEMORY[0x243ECC210])();
v4 = _DCLogSystem(v3);
v5 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v4);
v6 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v5, 0);
if ( (_DWORD)v6 )
{
*(_WORD *)__str = 0;
v6 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
&dword_24150F000,
v5,
0,
"Certificate issued, processing..",
__str,
2);
}
v7 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v6);
v8 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC210])(v7);
v75 = (void *)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(+[NSDate date](&OBJC_CLASS___NSDate, "date"));
if ( v2 && (v9 = (unsigned __int64)objc_msgSend(v2, "count"), (v9 & 0xFFFFFFFFFFFFFFFELL) == 2) )
{
v73 = v9;
v79 = 0;
v10 = 0;
v11 = 0;
v12 = 0;
v13 = 1;
v77 = v2;
while ( 1 )
{
v14 = v13;
v15 = v11;
v16 = ((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", v12));
MEMORY[0x243ECC120]();
v17 = ((__int64 (__fastcall *)(__int64))unk_243ECBDF0)(v16);
v18 = (void *)((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC1B0])(v17);
v95 = 0u;
v96 = 0u;
v93 = 0u;
v94 = 0u;
*(_OWORD *)__str = 0u;
v90 = 0u;
v91 = 0u;
v88 = 0u;
v89 = 0u;
*(_OWORD *)__src = 0u;
if ( v18 )
{
v80 = v15;
v19 = (void *)((__int64 (*)(void))MEMORY[0x243ECC080])();
v20 = (void *)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v18, "base64EncodedDataWithOptions:", 1));
v21 = (char *)objc_msgSend(v20, "length");
if ( v21 )
{
v78 = v10;
v22 = snprintf(__str, 0x50u, "-----BEGIN %s-----\n", "CERTIFICATE");
v23 = snprintf(__src, 0x50u, "\n-----END %s-----", "CERTIFICATE");
v24 = &v21[v22 + v23];
v25 = (char *)malloc((size_t)(v24 + 1));
if ( v25 )
{
v26 = v25;
v27 = &strncpy(v25, __str, v22)[v22];
objc_msgSend(v20, "getBytes:range:", v27, 0, v21);
strncpy(&v21[(_QWORD)v27], __src, v23);
v28 = (void *)((__int64 (__fastcall *)(NSData *))MEMORY[0x243ECC0A0])(
+[NSData(NSData) dataWithBytesNoCopy:length:](
&OBJC_CLASS___NSData,
"dataWithBytesNoCopy:length:",
v26,
v24));
if ( !v28 )
{
v85 = 0x21AEAF128LL;
v86 = CFSTR("Failed to create pem data.");
v31 = +[NSError errorWithDomain:code:userInfo:](
&OBJC_CLASS___NSError,
"errorWithDomain:code:userInfo:",
CFSTR("com.apple.devicecheck.cryptoerror"),
0,
((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
&v86,
&v85,
1)));
((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v31);
((void (*)(void))unk_243ECC180)();
free(v26);
}
}
else
{
v85 = 0x21AEAF128LL;
v86 = CFSTR("Failed to allocate buffer.");
v30 = +[NSError errorWithDomain:code:userInfo:](
&OBJC_CLASS___NSError,
"errorWithDomain:code:userInfo:",
CFSTR("com.apple.devicecheck.cryptoerror"),
0,
((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
&v86,
&v85,
1)));
((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v30);
((void (*)(void))unk_243ECC170)();
v28 = 0;
}
v2 = v77;
v10 = v78;
}
else
{
v28 = 0;
}
((void (*)(void))MEMORY[0x243ECC160])();
objc_autoreleasePoolPop(v19);
v15 = v80;
}
else
{
v85 = 0x21AEAF128LL;
v86 = CFSTR("Invalid inputs.");
v29 = +[NSError errorWithDomain:code:userInfo:](
&OBJC_CLASS___NSError,
"errorWithDomain:code:userInfo:",
CFSTR("com.apple.devicecheck.cryptoerror"),
0,
((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
&v86,
&v85,
1)));
((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v29);
((void (*)(void))MEMORY[0x243ECC160])();
v28 = 0;
}
v32 = ((__int64 (*)(void))MEMORY[0x243ECC140])();
v33 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v32);
v34 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC150])(v33);
((void (__fastcall *)(__int64))MEMORY[0x243ECC130])(v34);
if ( !v28 )
break;
if ( v10 )
objc_msgSend(v10, "appendBytes:length:", "\n", 1);
else
v10 = objc_msgSend(
(id)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC040])(&OBJC_CLASS___NSMutableData),
"initWithCapacity:",
objc_msgSend(v28, "length"));
v35 = objc_msgSend(v10, "appendData:", v28);
v13 = 0;
v11 = 1;
v79 = v15;
v12 = 1;
if ( (v14 & 1) == 0 )
{
v36 = v8;
goto LABEL_36;
}
}
v83 = 0x21AEAF128LL;
v84 = CFSTR("Failed to create PEM data from cert.");
v53 = +[NSError errorWithDomain:code:userInfo:](
&OBJC_CLASS___NSError,
"errorWithDomain:code:userInfo:",
CFSTR("com.apple.devicecheck.cryptoerror"),
0,
((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
&v84,
&v83,
1)));
v36 = ((__int64 (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v53);
v54 = ((__int64 (*)(void))MEMORY[0x243ECC150])();
v35 = (void *)((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC140])(v54);
v15 = v79;
LABEL_36:
if ( v73 == 3 )
{
v55 = (unsigned int)objc_msgSend(
*(id *)(a1 + 32),
"_isNSDate:",
((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", 2)));
((void (*)(void))MEMORY[0x243ECC140])();
if ( v55 )
{
v56 = ((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", 2));
v57 = MEMORY[0x243ECC1A0]();
v58 = _DCLogSystem(v57);
v59 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v58);
v60 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v59, 0);
if ( (_DWORD)v60 )
{
*(_WORD *)__str = 0;
v60 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
&dword_24150F000,
v59,
0,
"Using synced timestamp...",
__str,
2);
}
((void (__fastcall *)(__int64))MEMORY[0x243ECC140])(v60);
v37 = v15 & 1;
v75 = (void *)v56;
}
else
{
v81 = 0x21AEAF128LL;
v82 = CFSTR("Expected date field, failing...");
v64 = +[NSError errorWithDomain:code:userInfo:](
&OBJC_CLASS___NSError,
"errorWithDomain:code:userInfo:",
CFSTR("com.apple.devicecheck.cryptoerror"),
0,
((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
+[NSDictionary dictionaryWithObjects:forKeys:count:](
&OBJC_CLASS___NSDictionary,
"dictionaryWithObjects:forKeys:count:",
&v82,
&v81,
1)));
v65 = ((__int64 (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v64);
v66 = MEMORY[0x243ECC130]();
((void (__fastcall *)(__int64))MEMORY[0x243ECC140])(v66);
v37 = 0;
v36 = v65;
}
}
else
{
v61 = _DCLogSystem(v35);
v62 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v61);
v63 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v62, 0);
if ( (_DWORD)v63 )
{
*(_WORD *)__str = 0;
v63 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
&dword_24150F000,
v62,
0,
"Using device timestamp...",
__str,
2);
}
((void (__fastcall *)(__int64))MEMORY[0x243ECC120])(v63);
v37 = v15 & 1;
}
}
else
{
v10 = 0;
v37 = 0;
v36 = v8;
}
v38 = a2;
if ( a2 )
v38 = ((__int64 (*)(void))unk_243ECBD30)();
v39 = _DCLogSystem(v38);
v40 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v39);
v41 = v40;
if ( v37 )
{
v42 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v40, 0);
if ( (_DWORD)v42 )
{
v43 = objc_msgSend(v10, "length");
*(_DWORD *)__str = 134217984;
*(_QWORD *)&__str[4] = v43;
v42 = ((__int64 (*)(int *, __int64, _QWORD, const char *, ...))MEMORY[0x243ECBE60])(
&dword_24150F000,
v41,
0,
"Certificate processed... (%lu)",
v72);
}
((void (__fastcall *)(__int64))MEMORY[0x243ECC120])(v42);
v44 = (*(__int64 (__fastcall **)(_QWORD, void *, void *))(*(_QWORD *)(a1 + 40) + 16LL))(
*(_QWORD *)(a1 + 40),
objc_msgSend(v10, "copy"),
objc_msgSend(v75, "copy"));
v45 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC160])(v44);
}
else
{
if ( (unsigned int)((__int64 (__fastcall *)(__int64, __int64))MEMORY[0x243ECC2A0])(v40, 16) )
__66__DCCertificateGenerator__generateCertificateChainWithCompletion___block_invoke_cold_1(v36, v41);
MEMORY[0x243ECC120]();
v45 = (*(__int64 (__fastcall **)(_QWORD, _QWORD, void *))(*(_QWORD *)(a1 + 40) + 16LL))(
*(_QWORD *)(a1 + 40),
0,
objc_msgSend(v75, "copy"));
}
v46 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC120])(v45);
v47 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC110])(v46);
v48 = ((__int64 (__fastcall *)(__int64))unk_243ECC190)(v47);
v49 = ((__int64 (__fastcall *)(__int64))unk_243ECC170)(v48);
v50 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v49);
v51 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC150])(v50);
result = (id)((__int64 (__fastcall *)(__int64))unk_243ECC180)(v51);
if ( v97 != 0x8FCA7F6773E200E4LL )
{
v67 = (DCCertificateGenerator *)((__int64 (__fastcall *)(id))unk_243ECBE30)(result);
return -[DCCertificateGenerator _encryptData:serverSyncedDate:error:](v67, v68, v69, v70, v71);
}
return result;
}
将组合后的两个激活证传给加密方法
- 搜索“Encrypting data...”定位关键加密算法。
id __fastcall -[DCCertificateGenerator _encryptData:serverSyncedDate:error:](id *a1, __int64 a2, void *a3, void *a4)
{
id v6; // x21
__int64 v7; // x0
NSObject *v8; // x19
void *v9; // x19
void *v10; // x20
unsigned int v11; // w27
const void *v12; // x28
unsigned int v13; // w25
id v14; // x21
const void *v15; // x19
__int64 v16; // x23
size_t v17; // x24
_DWORD *v18; // x0
_DWORD *v19; // x22
char *v20; // x23
void *v21; // x27
void *v22; // x0
__int64 v23; // d0
__int64 v24; // x0
NSObject *v25; // x19
__int64 v26; // x8
__int64 v27; // x0
__int64 v28; // x19
__int64 v29; // x0
NSObject *v30; // x24
__int64 v31; // x0
void *v32; // x25
_OWORD *public_key_1; // x0
__int128 v34; // q0
__int128 v35; // q1
__int128 v36; // q2
__int64 i; // x20
__int64 v38; // x0
__int64 v39; // x19
__int64 v40; // x0
__int64 v41; // x0
char *v43; // x19
__int64 v44; // x20
unsigned __int8 *v45; // x25
int v46; // t1
__int64 v47; // x0
__int64 v48; // x19
__int64 v49; // x0
__int64 v50; // x0
__int64 v51; // x25
__int64 v52; // x0
__int64 v53; // x0
__int64 v54; // [xsp+28h] [xbp-D8h]
id v55; // [xsp+30h] [xbp-D0h]
id v56; // [xsp+38h] [xbp-C8h]
size_t __n; // [xsp+40h] [xbp-C0h] BYREF
__int64 v58; // [xsp+48h] [xbp-B8h] BYREF
void *v59; // [xsp+50h] [xbp-B0h] BYREF
__int64 v60; // [xsp+58h] [xbp-A8h] BYREF
uint8_t v61[4]; // [xsp+60h] [xbp-A0h] BYREF
__int64 time; // [xsp+64h] [xbp-9Ch]
uint8_t buf[16]; // [xsp+70h] [xbp-90h] BYREF
_DWORD v64[8]; // [xsp+80h] [xbp-80h] BYREF
__int64 vars8; // [xsp+108h] [xbp+8h]
v6 = objc_retain(a3);
v56 = objc_retain(a4);
v7 = _DCLogSystem(v56);
v8 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v7);
if ( os_log_type_enabled_1518(v8, OS_LOG_TYPE_DEFAULT) )
{
*(_WORD *)buf = 0;
_os_log_impl_1398(&dword_446A2E000, v8, OS_LOG_TYPE_DEFAULT, "Encrypting data...", buf, 2u);
}
objc_release(v8);
v9 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(a1[2], "clientAppID"));
v10 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v9, "dataUsingEncoding:", 4));
objc_release(v9);
v11 = (unsigned int)objc_msgSend(v10, "length");
v55 = objc_retainAutorelease(v10);
v12 = objc_msgSend(v55, "bytes");
v13 = (unsigned int)objc_msgSend(v6, "length");
v14 = objc_retainAutorelease(v6);
v15 = objc_msgSend(v14, "bytes");
v59 = 0;
v60 = 0;
v58 = 0;
v16 = ccaes_gcm_encrypt_mode_18();
*(_OWORD *)buf = 0u;
memset(v64, 0, 28);
v17 = v13 + v11 + 235LL;
v18 = j__calloc_516(1u, v17);
v19 = v18;
if ( v18 )
{
v54 = v16;
*(_DWORD *)((char *)v18 + 150) = v13 + v11 + 81;
*v18 = 2;
j__memcpy_1002(v18 + 5, objc_msgSend(a1[1], "bytes"), (size_t)objc_msgSend(a1[1], "length"));
v20 = (char *)j__calloc_516(1u, *(unsigned int *)((char *)v19 + 150));
*(_DWORD *)(v20 + 73) = v13;
j__memcpy_1002(v20 + 81, v15, v13);
*(_DWORD *)(v20 + 77) = v11;
j__memcpy_1002(&v20[*(unsigned int *)(v20 + 73) + 81], v12, v11);
v21 = v56;
v22 = objc_msgSend(v56, "timeIntervalSince1970");
*(_QWORD *)(v20 + 65) = v23;
v24 = _DCLogSystem(v22);
v25 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v24);
if ( os_log_type_enabled_1518(v25, OS_LOG_TYPE_DEFAULT) )
{
v26 = *(_QWORD *)(v20 + 65);
*(_DWORD *)v61 = 134217984;
time = v26;
_os_log_impl_1398(&dword_446A2E000, v25, OS_LOG_TYPE_DEFAULT, "Token timestamp: %f", v61, 0xCu);
}
objc_release(v25);
v27 = aks_ref_key_create_1(objc_msgSend(a1, "keybagHandle"), 11, 4, 0, 0, &v60);
if ( (_DWORD)v27 )
{
v28 = v27;
v29 = _DCLogSystem(v27);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v29);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.6(v28, v30);
LABEL_20:
v32 = 0;
goto LABEL_21;
}
__n = 0;
public_key_1 = (_OWORD *)aks_ref_key_get_public_key_1(v60, &__n);
if ( __n != 65 )
{
v41 = _DCLogSystem(public_key_1);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v41);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.5(&__n, v30);
goto LABEL_20;
}
*(_OWORD *)((char *)v19 + 85) = *public_key_1;
v34 = public_key_1[1];
v35 = public_key_1[2];
v36 = public_key_1[3];
*((_BYTE *)v19 + 149) = *((_BYTE *)public_key_1 + 64);
*(_OWORD *)((char *)v19 + 133) = v36;
*(_OWORD *)((char *)v19 + 117) = v35;
*(_OWORD *)((char *)v19 + 101) = v34;
j__memcpy_1002(v20, public_key_1, __n);
j__printf_200("%-25.25s = ", "random_pubkey");
for ( i = 85; i != 150; ++i )
j__printf_200("%02x", *((unsigned __int8 *)v19 + i));
putchar_75(10);
v38 = aks_ref_key_compute_key_0(v60, 0, 0, objc_msgSend(a1[1], "bytes"), objc_msgSend(a1[1], "length"), &v59, &v58);
if ( (_DWORD)v38 )
{
v39 = v38;
v40 = _DCLogSystem(v38);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v40);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.4(v39, v30);
goto LABEL_20;
}
v43 = (char *)v59;
v44 = v58 - 2;
j__printf_200("%-25.25s = ", "ECDH shared key");
if ( v44 )
{
v45 = (unsigned __int8 *)(v43 + 2);
do
{
v46 = *v45++;
j__printf_200("%02x", v46);
--v44;
}
while ( v44 );
}
putchar_75(10);
v47 = cchkdf_19(&ccsha256_ltc_di, v58 - 2, (char *)v59 + 2, 0, 0, 0, 0, 44, buf);
if ( (_DWORD)v47 )
{
v48 = v47;
v49 = _DCLogSystem(v47);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v49);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.3(v48, v30);
goto LABEL_20;
}
hex_2((std::ios_base *)"HKDF derived key");
hex_2((std::ios_base *)"HKDF derived iv");
v50 = ccgcm_one_shot_10(
v54,
32,
buf,
12,
&v64[4],
0,
0,
*(unsigned int *)((char *)v19 + 150),
v20,
(char *)v19 + 154,
16,
v19 + 1);
if ( (_DWORD)v50 )
{
v51 = v50;
v52 = _DCLogSystem(v50);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v52);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.2(v51, v30);
goto LABEL_20;
}
hex_2((std::ios_base *)"tag");
j__fprintf_285((FILE *)__stderrp_0, "encrypted_data_len: %d\n", *(_DWORD *)((char *)v19 + 150));
v32 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSData, "dataWithBytes:length:", v19, v17));
v53 = _DCLogSystem(v32);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v53);
_DCLogDebugBinary_0(v30, CFSTR("Token"), v32);
}
else
{
v31 = _DCLogSystem(0);
v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v31);
if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
-[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.1(v30);
v20 = 0;
v32 = 0;
v21 = v56;
}
LABEL_21:
objc_release(v30);
if ( v60 )
aks_ref_key_free_1(&v60);
if ( v19 )
j__free_1273(v19);
if ( v20 )
j__free_1273(v20);
if ( v59 )
j__free_1273(v59);
objc_release(v55);
objc_release(v21);
objc_release(v14);
if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
__break(0xC471u);
return objc_autoreleaseReturnValue(v32);
}
这个方法用 Secure Enclave 生成一个临时 EC 密钥 → 和服务器公钥做 ECDH → HKDF 派生 AES-256-GCM key+IV →把「[ephemeral 公钥 + 时间戳 + 激活证书 + appID]」打包加密 → 和各种公钥 / 长度 / tag 一起封装成 Token。流程如下:
8
4.2 加密算法流程
整个加密流程是一个变种的 ECIES (Elliptic Curve Integrated Encryption Scheme),具体步骤如下:
Payload 构建: 系统将 App ID (如 com.example.app)、设备证书链(包含 App Attest 证书和 Device CA 证书)以及 时间戳 拼接成一段二进制数据。
硬件密钥生成 (AKS): 调用私有 API aks_ref_key_create。这一步是在 Secure Enclave (SE) 安全芯片内部生成一个临时的 P-256 椭圆曲线密钥对。
- 关键点:私钥 (Private Key) 永远停留在硬件安全区内,外部无法读取,只能通过句柄引用。
ECDH 密钥协商: 调用 aks_ref_key_compute_key。系统使用刚才生成的硬件临时私钥,与代码中硬编码的 Apple 服务器公钥 进行 ECDH (Elliptic-curve Diffie–Hellman) 运算,计算出一个 共享密钥 (Shared Secret)。
HKDF 密钥派生: 调用 cchkdf (基于 HMAC 的密钥派生函数)。使用共享密钥作为输入,派生出用于后续对称加密的 AES 密钥 和 IV (初始化向量)。
AES-GCM 加密: 调用 ccgcm_one_shot。使用派生出的 AES 密钥,采用 AES-GCM 模式对第一步构建的 Payload 进行加密。GCM 模式不仅加密数据,还生成一个 Tag (认证标签),用于防止数据被篡改。
最终封装: 最终的 Token 结构大致为:
#pragma pack(push, 1)
typedef struct {
uint8_t ec_pubkey[65]; // 04 + X(32) + Y(32)
double timestamp; // 小端 double
uint32_t cert_len; // 激活证书pme
uint32_t bundle_len; // app包名长度
// 下面是可变部分:
uint8_t cert_pem[cert_len];
char bundle[bundle_len]; // "xxC6HB646H.com.beeasy.xxopee.xx"
} TokenPlainHeader;
#pragma pack(pop)
4.3 算法还原及为什么不建议生成纯算法?
import base64
import time
import struct
from typing import Tuple
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
class DeviceCheckTokenBuilder:
*"""*
* - server_pub: 固定“服务器公钥”(65 字节,0x04 开头)*
* - ephemeral_pub: 固定“设备临时公钥”(65 字节,0x04 开头)*
* - ikm: 固定的“ECDH shared secret”*
* - AES key / IV 通过 HKDF(SHA256, L=44) 从 IKM 导出*
* """*
* *def __init__(self):
# ==== 1. 固定服务器公钥 // fallback_server_pubkey ====
self.server_pub = bytes.fromhex(
"04 50 D9 34 FA 67 BC F6 F2 DF BF 96 62 9E 0A 72"
" 38 E9 20 5D 75 F2 8C FC D8 4F 35 A6 59 2B BE 05"
" 8A 9C 0F 8E DB CA 2A CB 67 EF B7 74 97 1C A4 5F"
" 7D 85 6A 69 4F B1 B9 C4 0B 94 FB 2E 7A 5A 94 98"
" B0"
)
# ==== 2. 固定设备临时公钥 _aks_ref_key_get_public_key_1 ====
self.ephemeral_pub = bytes.fromhex(
"04 79 5B C4 54 FF 9D 34 1E D8 11 CE CC"
" 73 C4 AF 32 1E 81 27 6D A0 BE F0 BF F6 B5 D6 3C"
" 5B AC 9F 09 2D 45 90 1B 6C A1 DA BF D9 8B 63 EF"
" 7E 3B 9D 14 3D 14 4D FE 70 85 7C 0A 4E 07 88 40"
" 4F 92 87 D0"
)
# ==== 3. 固定 IKM(ECDH shared secret)====
self.ikm = bytes.fromhex(
"fe3cb482384079c224225f476244d7c7"
"4031a41bf09ea60e27f9ede0861bf42e"
)
# 通过 HKDF 推导 AES key & IV(仿 cchkdf_19)
self.aes_key, self.aes_iv = self._hkdf_derive_key_iv(self.ikm)
# ------------------ 核心加密相关 ------------------ #
@staticmethod
def _hkdf_derive_key_iv(ikm: bytes) -> Tuple[bytes, bytes]:
*"""*
* 从 IKM 导出 44 字节 OKM,前 32 字节做 AES key,后 12 字节做 GCM IV*
* 相当于:*
* cchkdf_19(sha256, ikm, outLen=44, salt=NULL, info=NULL)*
* """*
* *hkdf = HKDF(
algorithm=hashes.SHA256(),
length=44,
salt=None,
info=None,
)
okm = hkdf.derive(ikm)
key = okm[:32]
iv = okm[32:44]
return key, iv
@staticmethod
def _gcm_encrypt(plaintext: bytes, key: bytes, iv: bytes) -> Tuple[bytes, bytes]:
*"""*
* AES-GCM 加密:*
* 返回 (ciphertext_without_tag, tag_16B)*
* """*
* *aesgcm = AESGCM(key)
ct_with_tag = aesgcm.encrypt(iv, plaintext, None)
tag = ct_with_tag[-16:]
ciphertext_only = ct_with_tag[:-16]
return ciphertext_only, tag
def build_dc_token(
self,
appname: str = None,
appcert: str = None,
devicecert: str = None,
) -> str:
*"""*
* Token Layout:*
* u32 version = 2*
* u8 tag[16]*
* u8 server_pub[65]*
* u8 ephemeral_pub[65]*
* u32 ciphertext_len*
* u8 ciphertext[ciphertext_len]*
* """*
* *# ---- 1. 默认 appname / 证书 ---- #
if appname is None:
appname = "T7C6HB646H.com.beeasy.shoppe.tw"
if appcert is None:
appcert = """-----BEGIN CERTIFICATE-----
MIIDJjCCAsugAwIBAgIGAZrJqz2xMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh
c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j
LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTExMjcwODUzNTRaFw0yNjEwMTQx
ODIwNTRaMIGRMUkwRwYDVQQDDEBiNjdjMGY3ZWM4OWJiOTZlZmU3ZGY5OTIzNDVl
NDIxNjdiMjU3ODQyZGQyZWM5MjdkZjE5MWVjYmQwYzM0YmI5MRowGAYDVQQLDBFC
QUEgQ2VydGlmaWNhdGlvbjETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwK
Q2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKoJsFk1GR/rs/Jj
+3iFqwYNnMZCB/0/s40hCTNSr5iooEkoAg8Apue/liWQrcVLYvknsfpRDZ74cKnp
cRI/8+ejggFKMIIBRjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DCCASQG
CSqGSIb3Y2QKAQSCARUEggERMYIBDf+EmqGSUA0wCxYEQ0hJUAIDAIEQ/4SqjZJE
ETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRi
bWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1
MDY4NTU1/4erkdJkIzAhFgR1ZGlkBBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF
/4e7tcJjGzAZFgR3bWFjBBFhYzoxNjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2Vp
ZAQwMDQyRDI3QzU4QTE2OTAwMjIzMzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VF
QzdCMAoGCCqGSM49BAMCA0kAMEYCIQCytP7jpU3xbaRHvXyvqCcum2F/kkDBSv1x
/RFAUXLJQwIhALeFnzR9R9BFlTjLS+nql3Cb6FqxywwJfCvf9v+JJTJl
-----END CERTIFICATE-----"""
if devicecert is None:
devicecert = """-----BEGIN CERTIFICATE-----
MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwwe
QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy
MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg
Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3
StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD
VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj
8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG
MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv
W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ
/hgok/34jr93nhS87tOQNdxDS8zyiqw=
-----END CERTIFICATE-----"""
# ---- 2. 拼接证书 + appname ---- #
cert_bytes = bytearray()
cert_bytes.extend(appcert.encode("utf-8"))
cert_bytes.append(0x0A) # 额外换行
cert_bytes.extend(devicecert.encode("utf-8"))
app_bytes = appname.encode("utf-8")
cert_len = len(cert_bytes)
app_len = len(app_bytes)
# ---- 3. 构造明文 ---- #
# ---- 4. AES-GCM 加密(key/iv 来自 HKDF) ---- #
# ---- 5. 组装最终 Token ---- #
result = bytearray()
result.extend(struct.pack("<I", 2)) # version = 2 (小端 u32)
result.extend(tag) # 16B tag
result.extend(self.server_pub) # 服务器公钥
result.extend(self.ephemeral_pub) # 设备临时公钥
result.extend(struct.pack("<I", len(ciphertext)))
result.extend(ciphertext)
# Base64 输出
return base64.b64encode(bytes(result)).decode("ascii")
if __name__ == "__main__":
builder = DeviceCheckTokenBuilder()
token = builder.build_dc_token()
print("Demo DC Token (base64):")
print(token)
- 不建议生成纯算法原因在于:私钥不可导出。 我们在外部代码中只能看到 Apple 的公钥,但无法获取在那一瞬间硬件生成的临时私钥。没有私钥,就无法在外部环境中计算出与硬件一致的 ECDH 共享密钥,也就无法生成能被 Apple 服务器解密的 Token,写死一份是有风险的,不确定Apple服务器端是否有检测。RPC调用可能真实性会更高一些。
4.4 证书替换的可行性分析
除了伪造 ID,我们还可以通过 Hook _encryptData 的入参来伪造设备信息生成我们想要的token。
-
伪造证书:
(function () {
if (!ObjC.available) {
console.error("[-] ObjC runtime not available");
return;
}
const NULL = ptr(0);
// ========= 通用符号解析工具 =========
function resolveSymbol(moduleHint, name) {
var addr = null;
try { addr = Module.findExportByName(moduleHint, name); } catch (e) {}
if (!addr) {
try { addr = Module.findExportByName(null, name); } catch (e) {}
}
if (addr) {
console.log(" Resolved " + name + " @ " + addr);
} else {
console.error("[-] Failed to resolve symbol: " + name);
}
return addr;
}
// ====== 导出 C 函数(允许部分缺失) ======
const func_create = resolveSymbol("Security", "SecCertificateCreateWithData");
const func_summary = resolveSymbol("Security", "SecCertificateCopySubjectSummary");
const func_copyData = resolveSymbol("Security", "SecCertificateCopyData");
const func_copyVals = resolveSymbol("Security", "SecCertificateCopyValues");
const func_release = resolveSymbol("CoreFoundation", "CFRelease");
// 这三个必须要有,否则没法干活
if (!func_create || !func_copyData || !func_release) {
console.error("[-] Critical symbols missing, abort.");
return;
}
const SecCertificateCreateWithData = new NativeFunction(func_create, 'pointer', ['pointer', 'pointer']);
const SecCertificateCopyData = new NativeFunction(func_copyData, 'pointer', ['pointer']);
const CFRelease = new NativeFunction(func_release, 'void', ['pointer']);
var SecCertificateCopySubjectSummary = null;
if (func_summary) {
SecCertificateCopySubjectSummary = new NativeFunction(func_summary, 'pointer', ['pointer']);
}
var SecCertificateCopyValues = null;
if (func_copyVals) {
SecCertificateCopyValues = new NativeFunction(func_copyVals, 'pointer', ['pointer', 'pointer', 'pointer']);
}
// ====== 小工具函数 ======
function cfToObj(ref) {
if (!ref || ref.isNull()) return null;
try { return new ObjC.Object(ref); }
catch (e) { return null; }
}
// 按标准 PEM 格式打印证书(每行 64 字符)
function printPemFromDerNSData(derNSData) {
if (!derNSData) return;
var b64 = derNSData.base64EncodedStringWithOptions_(0).toString();
console.log("-----BEGIN CERTIFICATE-----");
for (var i = 0; i < b64.length; i += 64) {
console.log(b64.substr(i, 64));
}
console.log("-----END CERTIFICATE-----");
}
// 打印 NSData (返回 token 用)
function dumpNSData(nsdata, label, maxHexBytes) {
if (!nsdata) {
console.log("[" + label + "] <NSData is null>");
return;
}
var len = nsdata.length();
console.log("[" + label + "] length: " + len + " bytes");
// 1) Base64(全部)
var b64 = nsdata.base64EncodedStringWithOptions_(0).toString();
console.log("[" + label + "] base64:");
for (var i = 0; i < b64.length; i += 64) {
console.log(" " + b64.substr(i, 64));
}
// 2) Hex(前 maxHexBytes)
var limit = Math.min(len, maxHexBytes || 256);
var bytesPtr = nsdata.bytes();
var hex = "";
for (var j = 0; j < limit; j++) {
var b = Memory.readU8(bytesPtr.add(j));
var h = ("0" + b.toString(16)).slice(-2);
hex += h + ((j + 1) % 16 === 0 ? "\n " : " ");
}
console.log("[" + label + "] hex (first " + limit + " bytes):\n " + hex);
}
function printCertDetail(certRef, label) {
if (!certRef || certRef.isNull()) {
console.log("[" + label + "] ❌ CertRef is NULL");
return;
}
console.log("\n========== [" + label + "] ==========");
// 1. Subject Summary(如果符号存在)
if (SecCertificateCopySubjectSummary) {
var summaryRef = SecCertificateCopySubjectSummary(certRef);
var summaryObj = cfToObj(summaryRef);
if (summaryObj) {
console.log("SubjectSummary : " + summaryObj.toString());
} else {
console.log("SubjectSummary : <null>");
}
if (summaryRef && !summaryRef.isNull()) CFRelease(summaryRef);
} else {
console.log("SubjectSummary : <unavailable>");
}
// 2. DER -> PEM
var derRef = SecCertificateCopyData(certRef);
var derObj = cfToObj(derRef);
if (derObj) {
printPemFromDerNSData(derObj);
} else {
console.log("[!] SecCertificateCopyData failed");
}
if (derRef && !derRef.isNull()) CFRelease(derRef);
// 3. 详细 values(如果符号存在)
if (SecCertificateCopyValues) {
var valuesRef = SecCertificateCopyValues(certRef, NULL, NULL);
var valuesObj = cfToObj(valuesRef);
if (valuesObj) {
console.log("Values (raw NSDictionary):");
console.log(" " + valuesObj.toString());
} else {
console.log("[!] SecCertificateCopyValues returned NULL");
}
if (valuesRef && !valuesRef.isNull()) CFRelease(valuesRef);
} else {
console.log("Values : <SecCertificateCopyValues unavailable>");
}
console.log("========== [END] ==========\n");
}
// ====== Hook DCCertificateGenerator ======
console.log("\n Script Loaded. Waiting...");
try {
var className = "DCCertificateGenerator";
var methodName = "- _encryptData:serverSyncedDate:error:";
if (!ObjC.classes[className]) {
console.error("[-] Class " + className + " not found");
return;
}
if (!ObjC.classes[className][methodName]) {
console.error("[-] Method " + methodName + " not found on " + className);
return;
}
var hook = ObjC.classes[className][methodName];
Interceptor.attach(hook.implementation, {
onEnter: function (args) {
console.warn("\n[+] 🟢 Intercepted Encryption Request");
// args[2] = _encryptData: (NSData*)
var dataObj = cfToObj(args[2]);
if (!dataObj) {
console.log(" [Payload Info] dataObj is NULL or invalid");
return;
}
var len = dataObj.length();
console.log(" [Payload Info] Raw Length: " + len + " bytes");
// 先直接当 DER 证书试
var certRef = SecCertificateCreateWithData(NULL, dataObj.handle);
if (!certRef.isNull()) {
printCertDetail(certRef, "Original (DER)");
CFRelease(certRef);
} else {
console.log(" [Info] SecCertificateCreateWithData failed, trying PEM path...");
var pemStrObj = ObjC.classes.NSString
.alloc()
.initWithData_encoding_(dataObj, 4); // UTF8
if (pemStrObj) {
var strContent = pemStrObj.toString();
if (strContent.indexOf("BEGIN CERTIFICATE") !== -1) {
console.log(" [Original Cert] Format: PEM (Base64 Text)");
var matches = strContent.match(/-----BEGIN CERTIFICATE-----([\s\S]+?)-----END CERTIFICATE-----/g);
if (matches) {
for (var i = 0; i < matches.length; i++) {
var block = matches[i];
var cleanBase64 = block
.replace(/-----BEGIN CERTIFICATE-----/g, "")
.replace(/-----END CERTIFICATE-----/g, "")
.replace(/[\r\n]/g, "");
var derData = ObjC.classes.NSData
.alloc()
.initWithBase64EncodedString_options_(cleanBase64, 0);
if (derData) {
var certRef2 = SecCertificateCreateWithData(NULL, derData.handle);
if (!certRef2.isNull()) {
printCertDetail(certRef2, "Parsed PEM Cert #" + (i + 1));
CFRelease(certRef2);
} else {
console.log(" [Parsed PEM Cert #" + (i + 1) + "] ❌ SecCertificateCreateWithData failed");
}
} else {
console.log(" [Parsed PEM Cert #" + (i + 1) + "] ❌ initWithBase64EncodedString failed");
}
}
} else {
console.log(" [Original Cert] PEM markers found but no blocks matched");
}
} else {
console.log(" [Original Cert] Format: Unknown Binary / Non-PEM text");
}
} else {
console.log(" [Original Cert] Cannot decode as UTF-8 string");
}
}
},
onLeave: function (retval) {
if (retval.isNull()) {
console.log("[+] Return value is NULL");
return;
}
try {
var retObj = new ObjC.Object(retval);
var clsName = retObj.$className || "<unknown>";
console.log("[+] Return ObjC class: " + clsName);
if (retObj.isKindOfClass_(ObjC.classes.NSData)) {
// 返回 NSData(大概率是加密后的 token)
dumpNSData(retObj, "Return NSData", 256);
} else if (retObj.isKindOfClass_(ObjC.classes.NSString)) {
console.log("[+] Return NSString:");
console.log(" " + retObj.toString());
} else {
console.log("[+] Return object description:");
console.log(" " + retObj.toString());
}
} catch (e) {
console.log("[!] onLeave: cannot wrap retval as ObjC.Object -> " + e.message);
}
}
});
console.log(" Hook Success");
} catch (e) {
console.error("[!] Hook Error: " + e.message);
}
})();
// frida -U -n devicecheckd -l devicecheckd1.js
五、在爬虫 / 群控场景中的实战应用
在理解了底层加密原理和 基本流程后,我们需要将视角拉回到业务对抗的一线。在黑灰产(爬虫方)与风控(防守方)的博弈中,DeviceCheck 不仅仅是一个 API,而是判定设备“生死”的判官。
5.1、爬虫方怎么用真机 + DeviceCheck 规避风控”
由于 DeviceCheck 的核心密钥(ECDH 协商用的临时私钥)被锁在 Secure Enclave 硬件中,纯算法还原(脱机算法)的路径已被彻底堵死。目前的黑灰产已全面转向“真机群控”与“底层 Hook”相结合的模式。
“借尸还魂”:证书与身份的批量伪造
攻击者建立一个庞大的“白名单设备库”,这些设备是真实存在的、干净的 iPhone。
-
采集阶段:使用越狱设备或硬改工具,批量提取白名单设备的 Device Certificate (PEM) 和 UniqueChipID 等硬件指纹。
-
攻击阶段:在被封禁的设备(或专门用于攻击的“脏”设备)上运行 Frida 脚本(如我们之前编写的脚本)。
-
运行时篡改:
“RPC 签名节点”:群控架构的演进
为了规模化作业,攻击者不再在每台手机上跑业务逻辑,而是将其改造为签名节点。
5.2、防守方怎么用 DeviceCheck 收拾真机爬虫”
面对上述攻击,防守方并非束手无策。正确使用 DeviceCheck 的服务端能力,可以对真机群控造成降维打击。
强制开启“双重验证”
绝不能仅仅依赖“Token 能否被解码”来判断请求合法性。必须调用 Apple 的 Query/Update API 并检查返回值。
- 检查报错:如果 Apple校验token API 返回错误,直接封禁该请求。这说明攻击者试图在 A 设备上使用 B 设备的证书(移花接木攻击),这是目前 Hook 方案无法解决的死穴。
善用 2-bit 状态标记(持久化封禁)
DeviceCheck 最强大的地方在于状态的硬件绑定性。
时间戳与频率风控
六、总结
iOS DeviceCheck(及 App Attest)代表了移动安全领域的一个重要转折点:从“软件对抗”走向“硬件对抗”。
通过本次逆向分析,我们得出以下核心结论:
-
硬件是信任的基石:DeviceCheck 的不可伪造性完全依赖于 Secure Enclave。私钥不出安全区,使得纯软件层面的算法还原(如 Python 脚本生成 Token)在理论上和工程上都成为不可能。
-
攻防的不对称性:
-
未来的趋势:随着 Apple 在 iOS 14+ 引入 DCAppAttestService,将密钥的绑定粒度从“设备”细化到了“设备 + App 实例”,并且支持对关键业务数据(Assertion)进行签名。这意味着未来的风控将更加精准,留给黑灰产“撞库”和“伪造”的空间将进一步被压缩。
对于安全从业者而言,理解 DeviceCheck 的底层逻辑,不仅有助于在红蓝对抗中制定更有效的策略,也提醒我们:在零信任架构下,基于硬件的可信证明(Hardware-backed Attestation)将是移动端身份认证的终极解决方案。
参考资料:
https://bbs.kanxue.com/thread-281819.htm
https://iosre.com/t/%E8%BD%AC%E8%BD%BD%E6%9F%90dd%E6%9F%90%E9%9F%B3-ios-devicecheck-token-%E6%AD%A3%E5%90%91%E7%A0%94%E5%8F%91%E4%B8%8E%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E4%B9%8B%E8%B7%AF%E6%80%9D%E8%80%83/24569/1
致谢: yuzhouheike addhaloka 感谢两位大佬提供的指导与帮助