iOS DeviceCheck:苹果设备身份链与黑灰产对抗的攻防博弈
原创 矛和盾的故事 2026-01-13 19:00 北京

DeviceCheck 的核心目标是在保护用户隐私的前提下,为开发者提供一种持久化的设备标记能力。即使 App 被卸载重装,甚至设备被恢复出厂设置,DeviceCheck 存储的 2-bit 状态依然可以被保留。这使得它成为了对抗“新用户薅羊毛”、“设备封禁”等场景的利器。
一、背景 & 场景
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、整体流程与框架
还是老规矩,先上整体框架图以方便理解整体,激活流程:

Device Token生成流程

二、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,就会看到服务器直接回:
ECC signature verification failed
说明硬件指纹和之前那套证书对不上,激活不通过。
某些大版本升级 / 本地激活证书过期异常
iOS 大版本升级、系统内部结构变动,有时会触发:
重签发部分证书
重新校验激活状态
如果本地激活缓存损坏(文件坏了、权限错了,或者你乱动 system volume),系统也可能判定无效,要求重新激活。
和运营商 / 区域相关的情况
有运营商锁(有锁机)、合约机、某些地区政策机型(比如中国/欧盟特定版本),激活时会把:
运营商信息
区域/国家代码
一起发给 Apple,
服务器会根据政策决定:
是否允许在当前运营商/区域激活
是否切换锁状态(从未激活变成“锁到某运营商”)
小结一句:
只要 Apple 觉得“我有理由重新确认你这台机器的身份/状态”,就会触发 mobileactivationd 跑激活。
2.2、为什么要激活?
从苹果的角度,这一整套“激活”设计,主要是为了解决三大问题:防伪造、防偷盗、统一发证。DeviceCheck / AppAttest 其实都是站在这套基础设施上实现的。
确认“这是一台真机,而不是山寨/模拟设备”
激活时上传的 RKCertification 里,包含:
从 Secure Enclave 拿到的真·硬件密钥的 attestation
ECID / ChipID / BoardId / SerialNumber / SecurityDomain 等指纹
苹果在服务器上用自己的 CA 体系校验证书链:
证书是不是 Apple 自己签出来的
硬件签名是不是由安全芯片里那把私钥算出来的
结论:
你光在软件层面“改 MGCopyAnswer 值”是骗不过的;
没有 SE + 正规证书链,服务器不会把你当成一台合法 iPhone。
防丢失、防盗机、控制设备生命周期
激活是苹果“设备生命周期管理”的关键环节:
防盗 / 查找我的 iPhone:
被“查找”绑定过的机器,如果被抹掉再激活,Apple 会要求输入原 Apple ID 才能继续。
黑名单 / 封禁:
被判定为重大违规(盗刷、欺诈)的 ECID/序列号,可以在服务器侧直接标记,下一次激活就直接拒绝。
区域控制:
比如某些功能/频段只在特定地区开放,也可以通过激活阶段写入策略。
为上层安全服务“铺路”(你现在在玩的部分)
激活完成后,mobileactivationd 会产出一套“设备根身份”:
系统组文件:uik.pem / ucrt.pem
Keychain 里的:
2bit-identity-rk
2bit-identity-leaf / intermediate / combined
2bit-identity-monotonic-clock / rtc-reset-count / server-timestamp 等
这些东西后面会被谁用?
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; // x25id v5; // x20void *v6; // x21id v7; // x20int v8; // w5int v9; // w6int v10; // w7id v11; // x19NSArray *v12; // x21void *v13; // x27NSNumber *v14; // x0int v15; // w5int v16; // w6int v17; // w7NSNumber *v18; // x24void *v19; // x22id v20; // x23void *v21; // x27void *v22; // x22char *v23; // x0char *v24; // x23__int64 v25; // x25char *i; // x28__SecKey *v27; // x24int v28; // w5int v29; // w6int v30; // w7const void *v31; // x9void *v32; // x27void *v33; // x26void *v34; // x23void *v35; // x19_BOOL4 v36; // w9__SecKey *v37; // x20void *v38; // x23_BOOL4 v39; // w24_BOOL4 v40; // w19NSNumber *v41; // x26id v42; // x22int v43; // w1__SecKey *v44; // x21int v45; // w5int v46; // w6int v47; // w7id v48; // x20__SecKey *v49; // x0int v50; // w5int v51; // w6int v52; // w7CFDataRef v53; // x21int v54; // w5int v55; // w6int v56; // w7__int64 v57; // x0int v58; // w5int v59; // w6int v60; // w7char v61; // w22int v62; // w24int v63; // w5int v64; // w6int v65; // w7__SecKey *v66; // x19int v67; // w5int v68; // w6int v69; // w7unsigned int v70; // w28void *v71; // x21__SecKey *v72; // x22int v73; // w5int v74; // w6int v75; // w7int v76; // w5int v77; // w6int v78; // w7id v79; // x19int v80; // w5int v81; // w6int v82; // w7void *v83; // x21id v84; // x22NSNumber *v85; // x25NSNumber *v86; // x19NSNumber *v87; // x21unsigned __int8 v88; // w22int v89; // w5int v90; // w6int v91; // w7NSNumber *v92; // x19unsigned int v93; // w20int v94; // w5int v95; // w6int v96; // w7const __CFString *v97; // x4int v98; // w1int v99; // w2id v100; // x20int v101; // w5int v102; // w6int v103; // w7__SecKey *v104; // x0int v105; // w5int v106; // w6int v107; // w7NSFileManager *v108; // x20NSFileManager *v109; // x21void *v110; // x22unsigned __int8 v111; // w23int v112; // w5int v113; // w6int v114; // w7id v115; // x20id v116; // x20int v117; // w5int v118; // w6int v119; // w7id v120; // x20void *v121; // x21id v122; // x20int v123; // w5int v124; // w6int v125; // w7id v126; // x20void *v127; // x21id v128; // x20int v129; // w5int v130; // w6int v131; // w7id v132; // x20__SecKey *v133; // x21id v134; // x20int v135; // w5int v136; // w6int v137; // w7id v138; // x20__SecKey *v139; // x21id v140; // x20int v141; // w5int v142; // w6int v143; // w7id v144; // x21void *v145; // x26int v146; // w5int v147; // w6int v148; // w7__SecKey *v149; // x0int v150; // w5int v151; // w6int v152; // w7CFDataRef v153; // x0int v154; // w5int v155; // w6int v156; // w7CFDataRef v157; // x24int v158; // w1id v159; // x26id v160; // x21int v161; // w5int v162; // w6int v163; // w7__SecKey *v164; // x19__CFString **v165; // x8CFDataRef v166; // x26CFDataRef v167; // x2void *v168; // x20id v169; // x21void *v170; // x20void *v171; // x21void *v172; // x0void *v173; // x23int v174; // w5int v175; // w6int v176; // w7void *v177; // x20int v178; // w5int v179; // w6int v180; // w7void *v181; // x20void *v182; // x21void *v183; // x0void *v184; // x20int v185; // w5int v186; // w6int v187; // w7void *v188; // x20int v189; // w5int v190; // w6int v191; // w7void *v192; // x20void *v193; // x21void *v194; // x0void *v195; // x20int v196; // w5int v197; // w6int v198; // w7int v199; // w5int v200; // w6int v201; // w7int v202; // w5int v203; // w6int v204; // w7__SecKey *v205; // x0void *v206; // x20id v207; // x21void *v208; // x20void *v209; // x21id v210; // x22void *v211; // x21unsigned int v212; // w19void *v213; // x22id v214; // x23void *v215; // x21void *v216; // x22id v217; // x23void *v218; // x21void *v219; // x22id v220; // x23void *v221; // x21void *v222; // x22id v223; // x23void *v224; // x23int v225; // w5int v226; // w6int v227; // w7void *v228; // x22id v229; // x23__SecKey *v230; // x21__SecKey *v231; // x24void *v232; // x28id v233; // x27void *v234; // x25void *v235; // x26__SecKey *v236; // x23void *v237; // x22id v238; // x19const void *v239; // x20__SecKey *v240; // x21__SecKey *v241; // x0id v242; // x19NSDictionary *v243; // x22void *v244; // x24__CFString **v245; // x8void *v246; // x0id v247; // x0void *v248; // x22char v249; // w23id v250; // x19id v251; // x23int v252; // w5int v253; // w6int v254; // w7id v255; // x19id v256; // x24int v257; // w5int v258; // w6int v259; // w7char is_darwinos; // w0id v261; // x19id v262; // x21int v263; // w5int v264; // w6int v265; // w7id v266; // x24NSData *v267; // x24int v268; // w5int v269; // w6int v270; // w7CFDataRef v271; // x2int v272; // w5int v273; // w6int v274; // w7char 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] BYREFid v328; // [xsp+160h] [xbp-250h] BYREFid v329; // [xsp+168h] [xbp-248h] BYREFid v330[2]; // [xsp+170h] [xbp-240h] BYREFid v331; // [xsp+180h] [xbp-230h] BYREFid v332; // [xsp+188h] [xbp-228h] BYREFid v333; // [xsp+190h] [xbp-220h] BYREFid v334[3]; // [xsp+198h] [xbp-218h] BYREFid v335[2]; // [xsp+1B0h] [xbp-200h] BYREFid 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] BYREFid v340[12]; // [xsp+1F8h] [xbp-1B8h] BYREF_QWORD v341[12]; // [xsp+258h] [xbp-158h] BYREFchar 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")));elsev310 = 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;elsev158 = 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;elsev43 = 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)生成的,而且签名覆盖了与这台硬件绑定的一些信息。
格式如下:
SEQUENCEINTEGER 02SEQUENCEOCTETSTRING xxxxdeca90b4fd52da1c016730a81dcb281f6c4dbb973e6b8438e6827530a177OCTETSTRING xxxx980ea0e8b0211cc342dc42067f1b..(total 65bytes)..2c8c482afb33b9e84221b49ffd1d81faOCTETSTRING xxxx730da8259089a9b9b02bd4a455fdOCTETSTRING xxxxce59b8232b317ff32beb21237051OCTETSTRING xxxx56c0b70138d40071067ee100013f..(total 1074bytes)..4b70f5283c1085f6a8d25107d6b9a94b
上报激活信息
将采集的硬件信息与证书签名信信息组合成 plist格式数据上报到服务器端
Headers
[*] URL : https://humb.apple.com/humbug/baa[*] Method : POST0 : User-Agent = {contents = "iOS Device Activator (MobileActivation-834.100.27) - devicecheckd"}3 : Content-Type = {contents = "application/xml"}4 : Content-Length = 98226 : x-jmet-deviceid = {contents = "00008110-303C30C91A06484E"}}
body
<plistversion="1.0"><dict><key>RKCertification</key><data>MIIExQIBAjxxxxxxxxP4C3sqQtP1S2hwBZzCoHcsoH2xNu5c+a4Q45oJ1MKF3BEEEiTxl3JiRx7vW49DhREeRVU04QQBLnB7Lm7nI8+D2ayS/PMZ7rcmhC89px3xHSlAvDl2MQopTSHXxnC/0Bs/6KgQQ1SciqWRdHp3U/vxi/S1O/wQQNpOm/5v25ojsX99XACzgpwSCBDHOl9izvodcLU0pQSlaNXHlIp7nMLqh/QkyEI+a/YlGFaqTR/PgZbq4o37Rw6SCZQ+MjU2Fuzuq9O6sTaKVBcw4aDW0oPDmZgH5m1ZlDwvUqQFAy+OvNrO8L4D4zSo2lW8BRqR89jkxWAixq12iERj/4+orIFAFGG86P/PnRRUsC8uR1tkqM4NpjXiLNUlO/X7VF1iY7g3nf5JSuxAqGMNZ8eEXXHJ9I5XuPDC/B1BvpoM/Pk65CPRbaw5ojMr+McZ+IsuWQBb21dxMldAyMMg5sFEt5+uIqWFaVyjFMfFCqYTfSofsyFQO8woaPegrmqFBVJRTGbbPkEDEVaWgLprdVuoE8hkSvecWaBwsyNH0UmTLMOwrMHF12RLVPc6qChr4ki0FkIP9crLHhQwxVYeXgRpAClcA6uNFFa412RdhRhv5T88NBVRNu9ewCm3gWBnhMF10PltNVGJ1ZRjhZS0ghaVnqHpjDA+2pnObaocLzgC9bOl0RExDwVwxLp7/hD/0jqZ+GqGSPgXYGY3FxnIB9n1e35KNjWaVur1WgHps5TEdi9LHxur2iqv5IkmxXNojxUoWprRc36RCBkurDLJiCM6Es8/63z1mZQ9ha4iA5+u0PStVpCSjOJ/0gn01pIxxxeppomCsT6980+l1HYi7zsD/tBkOznpFwGS5Ki9hRErTaCc2/9YGjgWVOBv1w5dEnBnwb1P59Qgpmnx3k9eyczaxt3OXOnKVwzYKtowI0OeDF9jM1yN9KZVtAqQJM4H8N+W3f0w8x+PwYHUf/0AHdAK/WyUHObDkoPzZOY+N7aFvkSf8aVcxC5MMCM6YFGpeDN9yoroti2mxxxelwDYx7Q8wuIeBBDiJfHRMWXxQEbej2XoYxGs4tz8Qh0z5p0kL5bb5MERKHPkaIg+slVxEpoCAxCnNHiTHjK3gEXhgyxkiBmLO4ENSGDTp+5PX64sez9Sb95ua6PhFFJYRXFgnp2IqffOoxx9Pxtxf7aKvpmlhPu+YGfbpz+mF+BSQY0a/ybU0xySRCKfTlepT8J+3HGNGl6HmjKPMDgj1SIloAoNR+VATnMs0THe7ZZTYLI+mbghSAHqDcjZCOWbRp19gSbUz71WU/sDAbN477biemxOYszVzS6cckGmmoDSLuav8RCSH9h254xTGB5VzEjT5lqpsWJ0u+IJUW7gfCbkq1IGer5PdmVrzAluNTS4G85iHnXi3EKJBwJ1upCRMjwlQRFlKP/SDo1TTQUa1kX0x+o1bFjvroyNKq+wL56PRQex22FzN00gsursFdstdB+WPHde2jfeVmielZ+wxw59wEuE2CLeS5D1CLIEGYgsTyoLxl6QQ80UjaphhAuVAA7HqcmXNe/6AOGdL42LHUhF23K5Fd55i8yaJP0sMwzY1e3nPbeunZmIiL1KiAFcKLzpmcg==</data><key>RKProperties</key><data>ff94bfwgfmVyc2lvbjxxxxxwIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLSxxxxxwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+QXBwSUQ8L2tleT4KCTxzdHJpbmc+Y29tLmFwcGxlLmRldmljZWNoZWNrZDwvf3RyaW5nPgoJPGtleT5Cb2FyZElkPC9rZXk+Cgk8aW50ZWdlcj4yNDwvaW50ZWdlcj4KffxrZXk+QfFfZXffPC9rZXk+Cgk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJPGtleT5DZXJ0VHlwZTwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4KCTxrZXk+Q2hpcElEPC9rZXk+Cgk8aW50ZWdlcj4zMzA0MDwvaW50ZWdlcj4KCTxrZXk+TG9jYWxQb2xpY3k8L2tleT4KCTxkYXRhPgoJTUlJTVFCWUVTVTFITkRBVUZnUkpUVFJRRmdSc2NHOXNGZ014TGpBRUFRQ2dnZfdfTUfJfUhCWUVTVTAwVFFJQkFER0MKCUFpUC9oT3FGbkVLQ0Fob3dnZ0lXRmdSTlFxxUNNWUlDRFArRTZvV2NVSUlCbnpDQ0Fac1dCRTFCVGxBeGdnR1IvNFNTCgl2YVJFQ3pBSkZnUkNUMUpFQWdFWS80U2FsYUJQQ3pBSkZnUkRSVkJQQWdFQi80U2FvWkpRRFRBTEZnUkRTRWxRQWdNQQoJZ1JEL2hKckJwRThMTUFrV0JFTlFVazhCQWYvL2hKck5pa01MTUFrV0JFTlRxVU1CQfWYvL2hLcU5ra1FSTUE4V0JFVkQKCVNVUUNCeGhwb2p3Z0lCNy9oWnFSbmswTE1Ba1dCRk5FVDAwQ0FRSC9odU85eEc4TE1Ba1dCR3h2WW04QkFmLy9odlBOCgkwbWc2TURnV0JHNXphV2dFTUlQc0gwYlAybmtaaDNoNVF3U2RXUU1CL0NoekZrWlMyczE0SxlWxnJTdDZwR2RlaDIvSgoJd3VnR2V4dFU5cWNmUy8rSGs3M2NhQ293S0JZRWNtOXVhQVFnU2srUmVVVnd1QWlCeEw0cWM5WmlZZUFFQ3Y1OVN2dmwKCXk4SWhTM2ZaK2k3L2g1dkIwbWc2TURnV0JITndhV2dFTUo3V1ZSSWhWNU13ZXlXa2VHdVo5STVSbUFSNGQycm9aZnFQCglmOE92aXljRkFjUEs0cHJDUXVTN3BSa3lBWDQxVi8rSG04bnNiaDR3SEJZRWMzSjJiZ1FVRzIrWkp3aXFselVHSUkzQQoJVmZMcklJL3RkMGYvaDdQVjBtUWFNQmdXQkhaMWFXUUVFQUFBQUFBQUFBQUFBQUFBQUFBQUFBRC9odVBCM214ZE1Gc1cKCUJHeHdiMnd4VS8rRW9wMm1WRG93T0JZRVJFZFRWQVF3MFFGVU9NU29rWEtqQkkxZXJyeXkzbVYzZGNacStHaVJhcWVXCglHUUk5Z29haFJoREhKZVNSem1mMERMMVl0M2h5LzRTcXJZcFpDekFKRmdSRlMwVlpBUUgvQklJQ0FFRmdqK1krQkpheAoJMU1jS3dGQkdFMHpvcElKZkJWY2dKcG5MeDV2MFA2L1VsbG1jWmZYcnVYK2t1K2xRYm9HUXBkQ3ZZcnp6K3l4bXVjS00KCWtDOXlJdlpzMndjMldrMzdDeHl4a1lXZ2UvckZmSERCWFpQS3hTc1hIRFpkVXVjanFQbGlqVkJGV1pXekJjc0hQd2M3CgkyOFJUcTNWQU9aeG0xRXo3RVFlVHRmUDFocDN0WEdic0xaMlZ0aVcyWG12VDFDeCsvajNCbnhnNGNtQy9EUjJWSmpZaQoJUUx2V0dJSTNSVUY5cUEwL3BBeGcvQ3JCeXI4Zkx3Uk5QV2haOGMwRW04eVhiU2MxZ1h2K0NlUnJJcVBNZXFWU1o3cGoKCXdGamlhTWlwRXEwRUJhQkcyOG9xNkNCZE9EK1ZDUWxYSzBNOEdqUXZXc3FpcS9UVDRlQkVGV0NQTzRKLzU2bzE4WkxpCgk5OFdZaTQyRVBLb0RHM0ZyTFhreWNWR0E0QTdnVlhIczBnS25TeWJEKzZmYlk0SGF5cWtpUEM4ZHl1QWlUNXF5WThwUwoJdVp5TTY5aEs4dEJleFpiWDdiOFdEd29HVElzd3RST0d1SGZJbEpSbXBIVXF2YnRUcWs4Qk42cFBwaHlNMlJqb1p4QmgKCXlBdzdEQ0M5Y0tuTkpnamhQTE91aFRaUlU0aCtqMXo5WnY2UmdpSU44L21wTkxZV2pNMmtFWEw1eVRKbVhYVnBOcThICgllUGx5VUF4TnF6dkFLVFpZQjMrODROOFF4ekF4bVk4eFFBcUpVb1ROWWVZSjZnSWZXcnFMVktsRFdDcy9kUE5kc2xndwoJNHN4ci9xS09kcDI1cm5ST1hyK21Kc080Qm4rNkI2VmhmWndWWnpmT2VkN0toZ3dMaGxrSXRYY25UbEN0TUlJSDVEQ0MKCUIrQXdnZ1hJb0FNQ0FRSUNFRDM5ajV5cU5WOXZVQ0xzTjAyRWRCOHdEUVlKS29aSWh2Y05BUUVNQlFBd1N6RW5NQ1VHCglBMVVFQXd3ZVFYQndiR1VnVTJWamRYSmxJRUp2YjNRZ1VtOXZkQ0JEUVNBdElFYzJNUk13RVFZRFZRUUtEQXBCY0hCcwoJWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpBZUZ3MHlNREEzTWpJeE9EQTJORGhhRncwek1EQTNNak14T0RBMk5EaGEKCU1GSXhMakFzQmdOVkJBTU1KVlE0TVRFd0xWTkVUMDB4TFZKbFkyOTJaWEo1UW05dmRDMVNaWFpCTFVaaFkzUnZjbmt4CglFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlUQWxWVE1JSUNJakFOQmdrcWhraUc5dzBCQVFFRgoJQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF5aVFHMk1leXZJeFlCQThJdis1bVd0cG83SHJ6ZUdvdU1sSlR1SHFqbmNUYzdDVEYKCUlpWlUvT1RMaVRoT2FsdS85L29rQnBqY2MyY0hVdXV6NFlMeUhRYkNFYzllam5MdTFhY2lYQ3MvVHZaZmoyTFpScnZsCgk4Tk1xaTBrNUE5RHlUVGxzYnZWRDhXQmdIZ3VUN2MySjh2N0tpUnM5MkZUWjZ6OGROK0ZPa1VjM3dTUnRiOFBaQ2QrWgoJREdXblpDYzZyZFlkOFRJWDhNK0dCYzhGeUVEaXFhUmNONmpNNzJkRkRDL0NCQjZxcmFKZDlEQ1VzRTdDVXJ5Zk02VWYKCXpqbVNyTGNnSkZYSjhZK3k0N2VjaGcrY2RDTytOQThBYjQzL2E1N0xJaTBtT0JIV2FIUytHTkExR3c3WkpqdHdNQXcvCgllbW9heXVNYXB6d1RlRjFNTW1qKzNTa0h2WEdTT0JtcU5SYVBoT2hRd1p3bkpsaEhpSkNzaVl1dWJ3N3Bxa0MycytiYgoJekx3MkxNakEyUUppQWdDOHJmU3VYb2RUT2EzRkxhK1RmSlJ4TjhoL3p2aEU5Wmk0RDNBeC8xQ2dBS1QxbTNXT3JtQ1AKCURVZDZKOXZ5c3plTWdlZ3RTWldHdU9oL1o1OGFDR1lROTFoMVdpYSt5VHdvU1J4c1lYdTR5ZldkT0ZlelpYQjlzMmFqCglWUEFRKzI2eE8xWlRsR29CWXVHcU1yTGEvaUV5S1J1UHpzZDVzcC9uU29wdE43dDQwS0h5Uy9KL1luT2RoZTltREdqUwoJMTZEaFJBSjRWdHBubDFmeHhubFdNcXpJeUNTMWxtTDdWeWxMdkF1YkpKZTF6MGtaTm9CNWlnSFB5Q3V2ZW5FUVpSVkQKCUlBcFJ5YlpqSk9Pc1FoVUY3dGFYVUQwQ0F3RUFBYU9DQXJjd2dnS3pNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqCglCQmd3Rm9BVVU3ZUV0TEhvT0R5Vzc2UldMdm96M1BFUWtPQXdIUVlxxlIwT0JCWUVGRlhYTkNqTWlaMzlYVFlGU3B0TgoJTXFNRlNwcWNNQTRHQTFVZER3RUIvd1FFQXdJSGdEQ0NBbEVHQ2lxR1NJYjNZMlFHQVE4QkFmOEVnZ0krTVlJQ092K0UKCTZvV2NVSUlCd1RDQ0FiMFdCRTFCVGxBeGdnR3ovNFNTdVlaSUREQUtGZ1JDVGtOSW9RSUZBUCtFa3Iya1JBd3dDaFlFCglRazlTUktBQ0JRRC9oSnFWb0U4TE1Ba1dCRU5GVUU4Q0FRSC9oSnFoa2xBTk1Bc1dCRU5JU1ZBQ0F3Q0JFUCtFbXNHawoJVHd3d0NoWUVRMUJTVDZBQ0JxRCxxSnJxxWtNTU1Bb1dCRU5UUlVPZ0FnVUEvNFNxalpKRUREQUtGZ1JGUTBsRW9BSUYKCUFQK0ZtcEdlVFFzd0NSWUVVMFJQVFFJQkFmK0dpOVh3YVF3d0NoWUVZWFY0YWFFQ0JRRC9ob3ZWOEhBTU1Bb1dCR0YxCgllSENoQWdVQS80Ymp2Y1J2Q3pBSkZnUnNiMkp2QVFILy80Ymp3ZHhvRERBS0ZnUnNjRzVvb1FJRkFQK0c4ODNTYUF3dwoJQ2hZRWJxxxBxS0FDQlFEL2g1TzkzR2dNTUFvV0JISnZibWlnQWdVQS80ZVR3ZHhvRERBS0ZnUnljRzVvb1FJRkFQK0gKCW02WGdNQXd3Q2hZRWMybHdNS0VDQlFEL2g1dWw0REVNTUFvV0JITnBjREdoQWdVQS80ZWJwZUF5RERBS0ZnUnphWEF5CglvUUlGQVArSG02WGdNd3d3Q2hZRWMybHdNNkVDQlFEL2g1dTF4REFNTUFvV0JITnRZakNoQWdVQS80ZWJ0Y1F4RERBSwoJRmdSemJXSXhvUUlGQVArSG03WEVNZ3d3Q2hZRWMyMWlNcUVDQlFEL2g3UFYwbVFNTUFvV0JIWjFhV1NnQWdVQS80VDYKCWlaUlFhVEJuRmdSUFFrcFFNVi8vaEtLZHBsUU1NQW9XQkVSSFUxU2dBZ1VBLzRTaXdhUlBEREFLRmdSRVVGSlBvUUlGCglBUCtFb3MyS1F3d3dDaFlFUkZORlE2RUNCUUQvaEtyQnBFOE1NQW9XQkVWUVVrK2hBZ1VBLzRTcXpZcEREREFLRmdSRgoJVTBWRG9RSUZBREFOQmdrcWhraUc5dzBCQVF3RkFBT0NBZ0VBalRUWGVyeE9pMnRWbkNUdXBYR3ZJZW5FQWRLNnZKZ28KCVJaTFNoTFo0NGFqNnYySS93V1NKblE1T1VBdGJaNEdiL1RSblZIOUV1dEtZZks0cC9GVlJOZVUvc0w2UjRHZEI2TGV0CgkwbWNKWkpSN2xtaUtUQmtMaFBYcnZsaU9qM2hQRlMxWHhCNDBTYzU2SlJ6L3REMlpjM1VPSmFNZDZza2YxR3FRd3BUaQoJUzgxVU5zS3JNVmtpc0R5YXYvVWxTQmpKM1hyazBCMmN1YVNpVjRaUXhZaSs0ZjRaSXUyZDQ2Y3lBMEJ3YXhBd0UwNFkKCU1OdDZVUXl2Y0R4VUxrMU5oUzhUbEtvMVJLczM3UWJxY2k4bUdMOU52M2N4NThjN3B4czBNT2VKMVY1UmNtRGxxZWVLCgliTEtTc3BnUTRLNkFHaTJwL3VsckI0YWsxU3lZZGkyUVlMUUw5TmU3dHhlMXE3c0Zlcmw0RnluOVZGZ2F1aVIreGlvQgoJaXpMcFZWblNPa1RRSGgzVEtNbVpEUS9MUDdscUNrcnVCOHZPRGYxV3dITzNOQityVTRXZlBZeERyazJqOWlna1pDdzEKCStjVFdWMmozU2lIekk1WUQ5WGRWZmNpZklOTktiNnhhckhuODdpQkh2RmgvM3hKekVqUzZTclI2WEpRTi9RU0FTTXpMCglnVkZRUXFxaHM0N1ZRNmlOS0NjZnZpR21UaXFoOE5vWVh1ZXUrME1Rdm5kb3NtcjUzelQzMEFTVWt0TTJnNFBKeDBuawoJUHN1dTVySVVaK3pKeWd6YjVmKzlhSXRHYkNUZEdwajM4YldYR0U3aWRXYTJuQlh6bnBVbDgyd3FhMlpWMHE1OFp2N20KCTBXY09ZWlRxcnVOSTcxRTVXd1duMWFCdzZQRlFOeG0xQlBOcFhSMD0KCTwvZGF0YT4KCTxrZXk+T0lEU1RvSW5jbHVkZTwva2V5PgoJPGFycmF5PgoJCTxzdHJpbmc+MS4yLjg0MC4xMTM2MzUuMTAwLjEwLjE8L3N0cmluZz4KCTwvYXJyYXk+Cgk8a2V5Pk9zQnVpbGRWZXJzaW9uPC9rZXk+Cgk8c3RyaW5nPjIwRTI1Mjwvc3RyaW5nPgoJPGtleT5SS0NlcnRpZmljYXRpb25QdWI8L2tleT4KCTxkYXRhPgoJQkgvL3VxQ1FzNEE0VElCdm1ZTWNJQkhiaGo1d0ZURkJaaDU3d2JkL0hTU25aSi9ZeE5YandIZ1FhZzlkandMVk84VjkKCS9DUHk2dDhmbURvbXM1TFpmYVE9Cgk8L2RhdGE+Cgk8a2V5PlNJS1B1Yjwva2V5PgoJPGRhdGE+CglCUHpXTnFSZk1MYmZCNTE0ZXorMWdXNG5vRzZxWGRMa3VySTYzY0NXSlRaall5cHVQVWIvUVZnNmJySUg5M2VUREd3QwoJMFJHTERuYjF3VjlPOHhSWkxMODVSNGdZMVJMeGw0ZnlmYkxLbzUrVHNoQk01bkYyckRlU0hMOG43cEFVOGc9PQoJPC9kYXRhPgoJPGtleT5TZWN1cml0eURvbWFpbjwva2V5PgoJPGludGVnZXI+MTwvaW50ZWdlcj4KCTxrZXk+U2VyaWFsTnVtYmVyPC9rZXk+Cgk8c3RyaW5nPkY2WDQzOU5IRjk8L3N0cmluZz4KCTxrZXk+VUlLUHViPC9rZXk+Cgk8ZGF0YT4KCUJEOHVOckcvaWJvL1RzbVg5a3JlVHZvS1N5WW1pZ2Z4UTJzTndTODVSb20rNy90TDBUM2toMlByTVlhWithZTlidWdqCglNVWxFTkxFOHBGUTFaTjdmSkprPQoJPC9kYXRhPgoJPGtleT5VbmlxdWVDaGlwSUQ8L2tleT4KCTxpbnRlZ2VyPjY4NzE1NDQ5NTU0MTI1MTA8L2ludGVnZXI+Cgk8a2V5PlZhbGlkaXR5PC9rZXk+Cgk8aW50ZWdlcj40NDExODY8L2ludGVnZXI+Cgk8a2V5PnNjcnRBdHRlc3RhdGlvbjwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4KPC9kaWN0Pgo8L3BsaXN0Pgo=</data><key>RKPropertiesSignature</key><data>MEYCIQD6alE5at+gOBxxxxxxYAIVZ6QwFJb7Q5lWdv/s95rSZAIhALu+7s0YPJu8LtN9O19Svcb46Vhw2CKF9Txv7GNheg+6</data></dict></plist>
即使hook伪造 MGCopyAnswer获取的的设备 ID,也不能伪造成另一台真机,因为底层 attestation 必须由那台真机的 SE 自签。单纯在软件层面篡改 UniqueChipID 时,服务器端会发现 “你上报的设备 ID 和 attestation 里的(或服务器已有记录里的)设备硬件身份对不上”。
返回激活证书
服务验签没问题后会返回正常的激活两本证书
-----BEGIN CERTIFICATE-----MIIDQTCCAuagAwIBAgIGAZrdcv7/MAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJhc2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTEyMDEwNTA0NTJaFw0yNjA3MzExMTMzNTJaMIGRMUkwRwYDVQQDDEA4YmQzNmIxNWZkNGViODgxZjZlYzNlYzE1MjJhNjlhNzE2ZGY1YTIxNzAxZmZlNTc1NWUwMmQ0MmVjZWRhYTVjMRowGAYDVQQLDBFCQUEgQ2VydGlmaWNhdGlvbjETMBEGx1xECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZRvBj8pkr4rDSbr4x137hYn/JvpfSXJpuvcTL0XXwhvK5s/TDrhpp07/n3Vo/1GDz3DyDjGbOdIci26U4h54GjggFlMIIBYTAMBgNVHRMBAf8EAxxAMA4GA1UdDwEB/wQEAwIE8DCCAT8GCSqGSIb3Y2QKAQSCATAEggEsMYIBKP+EmqGsUA0wCxYEQ0hJUAIDAIEQ/4SqjZJEETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRibWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1MDY4NTU1/4ebydxtFDASFgRzcm5tBApGNlg0MzlOSEY5/4erkdJkIzAhFgR1ZGlkBBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF/4e7tcJjGzAZFgR3bWFjBBFhYzoxNjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2VpZAQwMDQyRDI3QzU4QTE2OTAwMjIzMzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VFQzdCMAoGCCqGSM49BAMCA0kAMEYCIQCkVmdn5P6/mipbxpLOX7j9tTZ0ob4x2GzYsMeNF7mnwAIhAJgrskCv3xq9xR/QCaBYl+b8Ju0i2Jk5xxxxxxxxxx=-----END CERTIFICATE----------BEGIN CERTIFICATE-----MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCxxIKxZIzj0EAwIwUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMyMjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIgQ0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqvW+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ/hgok/34jr93nhS87tOQNdxDS8xxxx=-----END CERTIFICATE-----
这两本证书就是后面用于计算DeviceCheck Token的,格式解析如下:

验证证书有效后缓存在本地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不改,正常返回证书;
说明SE中对UniqueChipID、ChipID进行了签名,服务器端做检验。
A手机信息替换为B手机
将A手机的UniqueChipID、ChipID替换到B手机,返回如下:
-----BEGIN ERROR-----29:ECC signature verification failed: signature incorrect.-----END ERROR-----整体流程与修改信息验证流程

修改设备信息验证流程

结论
从上面验证情况来看,硬ID与SE 里的证书是绑定的。SE 里的“根密钥”和“设备证书”是在出厂生产 / 校准阶段由 Apple 写入硬件安全区的,属于“出厂级”的东西。
我改的 MobileGestalt 层(UniqueChipID/ChipID)只是“软件视角的 ID”,并不会改变 SE 里真实的密钥和它生成的签名,所以软改实现激活大概率是不可行的。
三、DeviceCheck 架构与正向流程
DeviceCheck 的工作流程涉及三方交互:客户端 App、系统守护进程 devicecheckd 以及 Apple 服务器。整体流程如下:

3.1 核心组件
客户端 (App):通过
DCDevice类发起 Token 生成请求。守护进程 (devicecheckd):iOS 系统内置的守护进程,负责与硬件安全模块(Secure Enclave)通信,执行核心加密操作。
Apple Server:接收 Token,验证其合法性,并根据 Token 更新或查询设备的 2-bit 状态。
3.2 bit 状态存储机制
DeviceCheck 允许开发者为每个设备-App 组合存储两个二进制位(00, 01, 10, 11)。
Bit 0:通常用于标记“是否已领取新人优惠”。
Bit 1:通常用于标记“是否为违规设备”或“是否被封禁”。 由于这两个位是存储在 Apple 服务器上的,且与硬件强绑定,因此单纯的重置 IDFA 或卸载 App 无法清除这些标记。
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 关键函数定位
API 定位:
在 App 二进制中搜索客户端获取DeviceCheckenToken调用的api,定位到 [DCDevice generateTokenWithCompletionHandler:]
然后再一步调试到关键方法,但这种方式比较慢,还有一种更方便的方式,根据日志输出字符串定位,下面是生成token过程中输出的日志:
Generating certificate...Fetched remote public key...Encrypting data...Certificate issued, processing..Using synced timestampReturning cached certificates-[MAAssetQuery getResultsFromMessage:]: Got the query meta data reply for: com.apple.MobileAsset.DeviceCheck, response: 0Falling 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; // x19id v6; // x20void *v7; // x23__int64 v8; // x0__int64 v9; // x0NSObject *v10; // x22_BOOL4 v11; // w0__int64 v12; // x22__int64 v13; // x0void *v14; // x21int v15; // [xsp+0h] [xbp-50h] BYREFid 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 key0000000A9700B010 04 50 D9 34 FA 67 BC F6 F2 DF BF 960000000A9700B020 62 9E 0A 72 38 E9 20 5D 75 F2 8C FC D8 4F 35 A60000000A9700B030 59 2B BE 05 8A 9C 0F 8E DB CA 2A CB 67 EF B7 740000000A9700B040 97 1C A4 5F 7D 85 6A 69 4F B1 B9 C4 0B 94 FB 2E0000000A9700B050 7A 5A 94 98 B0
准备读取本地缓存的激活证书
这张证书属于哪一类身份 & 存在哪个抽屉KeychainLabel = "2bit-identity"KeychainAccessGroup = "2bit-identity"//生成配置信息id +[DCCryptoUtilities identityCertificateOptions](){void *v0; // x19__int64 v1; // x0NSObject *v2; // x20void *v3; // x22void *v4; // x23void *v5; // x24void *v6; // x21void *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; // x7NSObject *v5; // x20dispatch_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; // x0void *v20; // x21unsigned __int8 v21; // w22void *v22; // x0id *v23; // x28void *v24; // x21__int64 v25; // x0void *v26; // x22void *v27; // x21void *v28; // x22__int64 v29; // x0void *v30; // x22unsigned __int8 v31; // w25id MobileActivationError_0; // x0__int64 v33; // x0id v34; // x0id v35; // x21CFDictionaryRef v36; // x25CFDataRef v37; // x28void *v38; // x22void *v39; // x27__int64 v40; // x8void *v41; // x26void *v42; // x9__int64 *v43; // x8const void *v44; // x0__int64 *v45; // x8const void *v46; // x0__int64 *v47; // x8const void *v48; // x0__int64 *v49; // x8const void *v50; // x0__int64 *v51; // x8const void *v52; // x0id v53; // x26id *v54; // x19id v55; // x0CFErrorRef v56; // x21__int64 v57; // x5__int64 v58; // x6__int64 v59; // x7id v60; // x0__int64 v61; // x0__int64 v62; // x8void *v63; // x9id v64; // x0bool v65; // w25__int64 v66; // x5__int64 v67; // x6__int64 v68; // x7char 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; // x7const __CFData *v83; // x21SecCertificateRef v84; // x0__int64 v85; // x5__int64 v86; // x6__int64 v87; // x7const __CFData *v88; // x21SecCertificateRef v89; // x0__int64 v90; // x5__int64 v91; // x6__int64 v92; // x7id v93; // x0CFErrorRef v94; // x19__int64 v95; // x5__int64 v96; // x6__int64 v97; // x7id v98; // x0__int64 v99; // x0__int64 v100; // x8void *v101; // x9__int64 v102; // x19__int64 v103; // x5__int64 v104; // x6__int64 v105; // x7__int64 v106; // x19void *v107; // x3id *v108; // x19void *v109; // t1id v110; // x0double v111; // d8__int64 v112; // x5__int64 v113; // x6__int64 v114; // x7__int64 v115; // x19void *v116; // x3id *v117; // x19void *v118; // t1id v119; // x0void *v120; // x25unsigned __int8 v121; // w26void *v122; // x21void *v123; // x22void *v124; // x25void *v125; // x26void *v126; // x27__int64 v127; // x5__int64 v128; // x6__int64 v129; // x7id v130; // x0int v131; // w21void *v132; // x3id v133; // x0id v134; // x0id v135; // x0id v136; // x0__int64 v137; // x5__int64 v138; // x6__int64 v139; // x7__int64 v140; // x5__int64 v141; // x6__int64 v142; // x7id v143; // x0void *v144; // x9__int64 v145; // x5__int64 v146; // x6__int64 v147; // x7__int64 v148; // x5__int64 v149; // x6__int64 v150; // x7CFDataRef v151; // x21__int64 v152; // x5__int64 v153; // x6__int64 v154; // x7__int64 v155; // x0__int64 v156; // x21char v157; // w22__int64 v158; // x5__int64 v159; // x6__int64 v160; // x7id v161; // x0void *v162; // x22__int64 v163; // x0void *v164; // x21__int64 v165; // x22void *v166; // x21__int64 v167; // x0void *v168; // x19void *v169; // x22__int64 v170; // x5__int64 v171; // x6__int64 v172; // x7id v173; // x0__int64 v174; // x0__int64 v175; // x0void *v176; // x9__int64 v177; // x5__int64 v178; // x6__int64 v179; // x7void *v180; // x0__int64 v181; // x0__int64 v182; // x0void *v183; // x9__int64 v184; // x5__int64 v185; // x6__int64 v186; // x7void *v187; // x0__int64 v188; // x0__int64 v189; // x0void *v190; // x9void *v191; // x0id v192; // x0void *v193; // x0void *v194; // x9id v195; // x0id v196; // x0id v197; // x0id v198; // x0id v199; // x0void *v200; // x21__int64 v201; // x0void *v202; // x22__int64 v203; // x5__int64 v204; // x6__int64 v205; // x7id v206; // x0void *v207; // x21__int64 v208; // x0void *v209; // x22__int64 v210; // x0__CFString *v211; // x0void *v212; // x21__int64 v213; // x0void *v214; // x22void *v215; // x21unsigned int v216; // w19void *v217; // x22__int64 v218; // x5__int64 v219; // x6__int64 v220; // x7id v221; // x0void *v222; // x22__int64 v223; // x0void *v224; // x25__int64 v225; // x5__int64 v226; // x6__int64 v227; // x7id v228; // x0void *v229; // x25__int64 v230; // x0void *v231; // x26__int64 v232; // x5__int64 v233; // x6__int64 v234; // x7id v235; // x0void *v236; // x22CFTypeID v237; // x25CFTypeID TypeID_4; // x26void *v239; // x22__int64 v240; // x0void *v241; // x25void *v242; // x21void *v243; // x22__int64 v244; // x0void *v245; // x25void *v246; // x21void *v247; // x25__int64 v248; // x0void *v249; // x26void *v250; // x21void *v251; // x21__int64 v252; // x0void *v253; // x26void *v254; // x21__int64 v255; // x0void *v256; // x26__int64 v257; // x5__int64 v258; // x6__int64 v259; // x7void *v260; // x25__int64 v261; // x0void *v262; // x26void *v263; // x21unsigned int v264; // w27void *v265; // x25__int64 v266; // x0void *v267; // x26void *v268; // x21unsigned int v269; // w22void *v270; // x25__int64 v271; // x0void *v272; // x26void *v273; // x19__int64 v274; // x26__int64 v275; // x27__int64 v276; // x22__int64 v277; // x19__int64 v278; // x0id v279; // x0void *v280; // x21__int64 v281; // x0__int64 v282; // x5__int64 v283; // x6__int64 v284; // x7__int64 v285; // x5__int64 v286; // x6__int64 v287; // x7id v288; // x0id v289; // x0id v290; // x0id v291; // x0__int64 v292; // x0__int64 v293; // x8void *v294; // x9__int64 v295; // x0__int64 v296; // x25__int64 v297; // x21int valid; // w28__int64 v299; // x0__int64 v300; // x21int v301; // w28__int64 v302; // x21char v303; // w28id v304; // x0__int64 v305; // x0__int64 v306; // x8void *v307; // x9id v308; // x0void *v309; // x8__int64 *v310; // x8const void *v311; // x0__int64 *v312; // x8const void *v313; // x0__int64 *v314; // x8const void *v315; // x0__int64 v316; // x8void *v317; // x9double v318; // d0void *v319; // x0__int64 v320; // x0char v321; // w19void *v322; // x8__int64 v323; // x0__int64 v324; // x21__int64 v325; // x21double v326; // d8double v327; // d9double v328; // d0int v329; // w25int v330; // w8id v331; // x0__int64 v332; // x0const 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; // x7CFDictionaryRef v347; // x0__int64 v348; // x5__int64 v349; // x6__int64 v350; // x7__int64 v351; // x5__int64 v352; // x6__int64 v353; // x7void *v354; // x26dispatch_queue_global_t v355; // x0__CFString *v356; // x0__int64 v357; // x8id v358; // x0id v359; // x0id v360; // x0id v361; // x0__int64 v362; // x9void *v363; // x8const void *v364; // x0CFTypeRef v365; // x0id v366; // x0void *v367; // x0void *v368; // x0void *v369; // x0__int64 v370; // x19void *v371; // x0id v372; // x0__int64 v373; // x8id v374; // x19id v375; // x0id v376; // x0id v377; // x0id v378; // x0id v379; // x0id v380; // x0__int64 v381; // x9__int64 *v382; // x8__int64 *v383; // x9char 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] BYREFid 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] BYREFid v464; // [xsp+260h] [xbp-420h]id v465; // [xsp+268h] [xbp-418h] BYREFid v466; // [xsp+270h] [xbp-410h] BYREFid v467; // [xsp+278h] [xbp-408h] BYREFid obj; // [xsp+280h] [xbp-400h] BYREFid v469; // [xsp+288h] [xbp-3F8h] BYREFid v470; // [xsp+290h] [xbp-3F0h] BYREFid v471; // [xsp+298h] [xbp-3E8h] BYREF__int64 v472; // [xsp+2A0h] [xbp-3E0h] BYREFdouble *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] BYREFdouble v481; // [xsp+2E8h] [xbp-398h] BYREF__int64 v482; // [xsp+2F0h] [xbp-390h] BYREFdouble *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] BYREFid *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] BYREFid v555; // [xsp+558h] [xbp-128h]uint8_t buf[4]; // [xsp+560h] [xbp-120h] BYREFvoid *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] BYREFvoid *v574; // [xsp+5E0h] [xbp-A0h] BYREF__CFString *v575; // [xsp+5E8h] [xbp-98h] BYREFvoid *v576; // [xsp+5F0h] [xbp-90h] BYREFv554[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")));elsev210 = 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 + 时间防回拨信息”的档案。流程如下:

读取激活证书后准备加密生成token。
加密证书
组合参数
_SecCertificateCopyDataid __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; // x23unsigned __int64 v9; // x0void *v10; // x28char v11; // w9__int64 v12; // x2char v13; // w8char v14; // w19char v15; // w26__int64 v16; // x20__int64 v17; // x0void *v18; // x21void *v19; // x26void *v20; // x24char *v21; // x22int v22; // w28int v23; // w27char *v24; // x25char *v25; // x0char *v26; // x20char *v27; // x28void *v28; // x25NSError *v29; // x0NSError *v30; // x0NSError *v31; // x0__int64 v32; // x0__int64 v33; // x0__int64 v34; // x0void *v35; // x0__int64 v36; // x21int v37; // w19__int64 v38; // x0__int64 v39; // x0__int64 v40; // x0__int64 v41; // x20__int64 v42; // x0void *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; // x0id result; // x0NSError *v53; // x0__int64 v54; // x0unsigned 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; // x0NSError *v64; // x0__int64 v65; // x20__int64 v66; // x0DCCertificateGenerator *v67; // x0SEL v68; // x1id v69; // x2id v70; // x3id *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] BYREFchar __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);elsev10 = 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; // x0NSObject *v8; // x19void *v9; // x19void *v10; // x20unsigned int v11; // w27const void *v12; // x28unsigned int v13; // w25id v14; // x21const void *v15; // x19__int64 v16; // x23size_t v17; // x24_DWORD *v18; // x0_DWORD *v19; // x22char *v20; // x23void *v21; // x27void *v22; // x0__int64 v23; // d0__int64 v24; // x0NSObject *v25; // x19__int64 v26; // x8__int64 v27; // x0__int64 v28; // x19__int64 v29; // x0NSObject *v30; // x24__int64 v31; // x0void *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; // x0char *v43; // x19__int64 v44; // x20unsigned __int8 *v45; // x25int 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] BYREFvoid *v59; // [xsp+50h] [xbp-B0h] BYREF__int64 v60; // [xsp+58h] [xbp-A8h] BYREFuint8_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。流程如下:

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 结构大致为:
typedef struct {uint8_t ec_pubkey[65]; // 04 + X(32) + Y(32)double timestamp; // 小端 doubleuint32_t cert_len; // 激活证书pmeuint32_t bundle_len; // app包名长度// 下面是可变部分:uint8_t cert_pem[cert_len];char bundle[bundle_len]; // "xxC6HB646H.com.beeasy.xxopee.xx"} TokenPlainHeader;
4.3 算法还原及为什么不建议生成纯算法?
还原算法
import base64import timeimport structfrom typing import Tuplefrom cryptography.hazmat.primitives.ciphers.aead import AESGCMfrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.primitives.kdf.hkdf import HKDFclass 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)# ------------------ 核心加密相关 ------------------ #@staticmethoddef _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@staticmethoddef _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, tagdef build_dc_token(self,appname: str = None,appcert: str = None,devicecert: str = None,) -> str:"""Token Layout:u32 version = 2u8 tag[16]u8 server_pub[65]u8 ephemeral_pub[65]u32 ciphertext_lenu8 ciphertext[ciphertext_len]"""# ---- 1. 默认 appname / 证书 ---- #if appname is None:appname = "T7C6HB646H.com.beeasy.shoppe.tw"if appcert is None:appcert = """-----BEGIN CERTIFICATE-----MIIDJjCCAsugAwIBAgIGAZrJqz2xMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJhc2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTExMjcwODUzNTRaFw0yNjEwMTQxODIwNTRaMIGRMUkwRwYDVQQDDEBiNjdjMGY3ZWM4OWJiOTZlZmU3ZGY5OTIzNDVlNDIxNjdiMjU3ODQyZGQyZWM5MjdkZjE5MWVjYmQwYzM0YmI5MRowGAYDVQQLDBFCQUEgQ2VydGlmaWNhdGlvbjETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKoJsFk1GR/rs/Jj+3iFqwYNnMZCB/0/s40hCTNSr5iooEkoAg8Apue/liWQrcVLYvknsfpRDZ74cKnpcRI/8+ejggFKMIIBRjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DCCASQGCSqGSIb3Y2QKAQSCARUEggERMYIBDf+EmqGSUA0wCxYEQ0hJUAIDAIEQ/4SqjZJEETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRibWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1MDY4NTU1/4erkdJkIzAhFgR1ZGlkBBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF/4e7tcJjGzAZFgR3bWFjBBFhYzoxNjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2VpZAQwMDQyRDI3QzU4QTE2OTAwMjIzMzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VFQzdCMAoGCCqGSM49BAMCA0kAMEYCIQCytP7jpU3xbaRHvXyvqCcum2F/kkDBSv1x/RFAUXLJQwIhALeFnzR9R9BFlTjLS+nql3Cb6FqxywwJfCvf9v+JJTJl-----END CERTIFICATE-----"""if devicecert is None:devicecert = """-----BEGIN CERTIFICATE-----MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMyMjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIgQ0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqvW+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 tagresult.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。
伪造证书:
逆向分析发现
_encryptData的data参数本质上是 PEM 格式证书的 Base64 编码。可以预先收集一批“白名单设备”的证书。
在 Hook 点将当前的“黑名单证书”替换为“白名单证书”。frida脚本如下:
(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 -> PEMvar 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); // UTF8if (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 脚本(如我们之前编写的脚本)。
运行时篡改:
服务器端爬虫:负责跑业务逻辑(HTTP 请求),遇到需要 DeviceToken 的接口时,向手机发送 RPC 请求。
手机端(Agent):运行在后台,接收 RPC 指令,调用
DCDevice生成 Token(配合上述的 Hook 伪造策略),然后将 Token 返回给服务器端。Hook
devicecheckd进程。在生成 Token 前,将内存中的“脏证书”替换为采集来的“白证书”。
核心突破:虽然硬件签名(SE)使用的是脏设备的私钥,但只要 Hook 了
DCContext伪造 AppID,生成的 Token 在逻辑格式上是合法的。“RPC 签名节点”:群控架构的演进
为了规模化作业,攻击者不再在每台手机上跑业务逻辑,而是将其改造为签名节点。
架构:
优势:一台真机可以为十几个线程提供签名服务,极大地降低了硬件成本。
5.2、防守方怎么用 DeviceCheck 收拾真机爬虫”
面对上述攻击,防守方并非束手无策。正确使用 DeviceCheck 的服务端能力,可以对真机群控造成降维打击。
强制开启“双重验证”
绝不能仅仅依赖“Token 能否被解码”来判断请求合法性。必须调用 Apple 的 Query/Update API 并检查返回值。
检查报错:如果 Apple校验token API 返回错误,直接封禁该请求。这说明攻击者试图在 A 设备上使用 B 设备的证书(移花接木攻击),这是目前 Hook 方案无法解决的死穴。
善用 2-bit 状态标记(持久化封禁)
DeviceCheck 最强大的地方在于状态的硬件绑定性。
策略:当风控系统检测到某账号存在异常行为(如高频请求、脚本操作)时,不要仅仅封禁账号(UID),而是立即调用 DeviceCheck 的
update_two_bits接口,将该设备的 Bit 1 置为 1(标记为“黑名单设备”)。效果:
攻击者即使卸载 App、重装 App,Bit 1 的状态依然是 1。
攻击者即使抹掉 iPhone 恢复出厂设置(在未更换主板的情况下),Apple 服务器上的 Bit 1 状态依然保留。
击杀点:这迫使攻击者必须更换物理硬件(硬改)/或更激活证书才能清洗设备状态,极大地拉高了攻击成本。
时间戳与频率风控
时间窗口:严格校验 Token 内部解密出的
timestamp。如果时间戳是 2 天前的,或者与当前服务器时间偏差超过 5 分钟,直接拒绝。频率限制:对同一个 Device Token(即使它是合法的)的提交频率做限制。正常的真机用户不会在 1 秒内生成 10 次 Token。
六、总结
iOS DeviceCheck(及 App Attest)代表了移动安全领域的一个重要转折点:从“软件对抗”走向“硬件对抗”。
通过本次逆向分析,我们得出以下核心结论:
硬件是信任的基石:DeviceCheck 的不可伪造性完全依赖于 Secure Enclave。私钥不出安全区,使得纯软件层面的算法还原(如 Python 脚本生成 Token)在理论上和工程上都成为不可能。
攻防的不对称性:
攻击者不得不通过昂贵的真机群控、复杂的系统级 Hook(注入
devicecheckd)以及硬改(更换基带/闪存芯片/激活证书)来绕过防护,成本呈指数级上升。防守方只需在服务端接入 Apple 的验证 API,并制定合理的 2-bit 状态标记策略,即可获得一个难以被清洗的设备指纹。
未来的趋势:随着 Apple 在 iOS 14+ 引入
DCAppAttestService,将密钥的绑定粒度从“设备”细化到了“设备 + App 实例”,并且支持对关键业务数据(Assertion)进行签名。这意味着未来的风控将更加精准,留给黑灰产“撞库”和“伪造”的空间将进一步被压缩。
对于安全从业者而言,理解 DeviceCheck 的底层逻辑,不仅有助于在红蓝对抗中制定更有效的策略,也提醒我们:在零信任架构下,基于硬件的可信证明(Hardware-backed Attestation)将是移动端身份认证的终极解决方案。
欢迎加我微信与我交朋友(公众号输入框回复“wx”即可)
参考资料:
https://bbs.kanxue.com/thread-281819.htm
致谢: yuzhouheike addhaloka 感谢两位大佬提供的指导与帮助