吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4839|回复: 26
收起左侧

[iOS 原创] iOS DeviceCheck:苹果设备身份链与黑灰产对抗的攻防博弈

  [复制链接]
我是小三 发表于 2026-6-24 17:00
本帖最后由 我是小三 于 2026-6-24 16:55 编辑

一、背景 & 场景

1.1 环境

设备型号:iphone 14、iOS 版本:16.4.1、越狱方案:Dopamine

工具链:Frida16.1.4、IDA pro 9.2

1.2 引言

对于大多数互联网风控攻防业务来说,真正棘手的往往不是单个请求本身,而是背后那一整套“批量造设备、批量刷行为”的自动化体系。正是在这样的背景下,从最初的简单模拟请求,到如今的设备指纹伪造、群控刷量,攻防对抗从未停止。在这一背景下,Apple 推出的 DeviceCheck(以及后续的 App Attest)成为了 iOS 平台上反作弊与反爬虫的重要防线。

DeviceCheck 的核心目标是在保护用户隐私的前提下,为开发者提供一种持久化的设备标记能力。即使 App 被卸载重装,甚至设备被恢复出厂设置(在某些条件下),DeviceCheck 存储的 2-bit 状态依然可以被保留。这使得它成为了对抗“新用户薅羊毛”、“设备封禁”等场景的利器。

然而,对于安全研究人员和黑灰产从业者而言,DeviceCheck 也是一个必须攻克的堡垒。本文将基于逆向工程视角,简单剖析 DeviceCheck 的底层实现,揭示其加密流程,并探讨在越狱环境下进行攻防对抗的可行性。

1.3、研究动机与目标

  • 验证通过改机(UniqueChipID / ECID/SerialNumber等)为什么不能激活设备?

  • 想搞清楚:苹果到底在检验什么?哪些字段是“硬绑定”的?

  • 从攻击与防护视角学习如何应用好DeviceCheck?

1.4、整体流程与框架

  • 激活流程

    1

    1
  • Device Token生成流程

    2

    2

    二、mobileactivationd 激活流程分析

2.1、什么时候会激活?

这里说的激活,就是由 mobileactivationd + Apple 服务器 参与的那种“和苹果聊一聊,我是谁、能不能用”的流程,而不是普通 App 级别的登录。

首次开箱 / 刷机之后第一次开机

  • 全新 iPhone、刚刷完原版 IPSW、DFU 恢复之后第一次进开机向导。

  • 这时候本地没任何“激活凭据”,系统必须:

  • 收集硬件指纹(ECID、ChipID、BoardId、SerialNumber…)

  • 跟 Apple 服务器谈一轮,生成 / 刷新 uik.pem / ucrt.pem、设备证书等。

  • 你能看到的表现就是:

  • 屏幕上显示  “正在激活 iPhone,需要几分钟”

恢复出厂设置 / 抹掉所有内容之后

  • 设置 → 通用 → 传输或还原 iPhone → 抹掉所有内容和设置,或者用 Finder/iTunes 恢复。

  • 抹掉后再次启动,和第一次开箱本质一样,也要重新激活。

  • 这时 mobileactivationd 会:

  • 检查旧的激活票据是否还有效

  • 一般还是会重新向服务器请求新的激活证书(你抓到的 RKCertification 就是这类东西)。

硬件变化比较大时(换本板 / 基带 / 改机)

  • 主板更换、严重“硬改机”、某些基带相关硬件变化,会导致:

  • UniqueChipID(ECID)、ChipID、BoardId、SecurityDomain 组合发生改变。

  • Apple 服务器视角:这是“另一台设备”,必须重新审查:

  • 有没有被报失

  • 有没有被运营商锁 / 黑名单

  • 所以一旦检测到这种变化,系统会强制重新走激活流程。

  • 你的 hook 里如果把 UniqueChipID 换成别的机器的 ECID,就会看到服务器直接回:

  • 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; // x25
  id v5; // x20
  void *v6; // x21
  id v7; // x20
  int v8; // w5
  int v9; // w6
  int v10; // w7
  id v11; // x19
  NSArray *v12; // x21
  void *v13; // x27
  NSNumber *v14; // x0
  int v15; // w5
  int v16; // w6
  int v17; // w7
  NSNumber *v18; // x24
  void *v19; // x22
  id v20; // x23
  void *v21; // x27
  void *v22; // x22
  char *v23; // x0
  char *v24; // x23
  __int64 v25; // x25
  char *i; // x28
  __SecKey *v27; // x24
  int v28; // w5
  int v29; // w6
  int v30; // w7
  const void *v31; // x9
  void *v32; // x27
  void *v33; // x26
  void *v34; // x23
  void *v35; // x19
  _BOOL4 v36; // w9
  __SecKey *v37; // x20
  void *v38; // x23
  _BOOL4 v39; // w24
  _BOOL4 v40; // w19
  NSNumber *v41; // x26
  id v42; // x22
  int v43; // w1
  __SecKey *v44; // x21
  int v45; // w5
  int v46; // w6
  int v47; // w7
  id v48; // x20
  __SecKey *v49; // x0
  int v50; // w5
  int v51; // w6
  int v52; // w7
  CFDataRef v53; // x21
  int v54; // w5
  int v55; // w6
  int v56; // w7
  __int64 v57; // x0
  int v58; // w5
  int v59; // w6
  int v60; // w7
  char v61; // w22
  int v62; // w24
  int v63; // w5
  int v64; // w6
  int v65; // w7
  __SecKey *v66; // x19
  int v67; // w5
  int v68; // w6
  int v69; // w7
  unsigned int v70; // w28
  void *v71; // x21
  __SecKey *v72; // x22
  int v73; // w5
  int v74; // w6
  int v75; // w7
  int v76; // w5
  int v77; // w6
  int v78; // w7
  id v79; // x19
  int v80; // w5
  int v81; // w6
  int v82; // w7
  void *v83; // x21
  id v84; // x22
  NSNumber *v85; // x25
  NSNumber *v86; // x19
  NSNumber *v87; // x21
  unsigned __int8 v88; // w22
  int v89; // w5
  int v90; // w6
  int v91; // w7
  NSNumber *v92; // x19
  unsigned int v93; // w20
  int v94; // w5
  int v95; // w6
  int v96; // w7
  const __CFString *v97; // x4
  int v98; // w1
  int v99; // w2
  id v100; // x20
  int v101; // w5
  int v102; // w6
  int v103; // w7
  __SecKey *v104; // x0
  int v105; // w5
  int v106; // w6
  int v107; // w7
  NSFileManager *v108; // x20
  NSFileManager *v109; // x21
  void *v110; // x22
  unsigned __int8 v111; // w23
  int v112; // w5
  int v113; // w6
  int v114; // w7
  id v115; // x20
  id v116; // x20
  int v117; // w5
  int v118; // w6
  int v119; // w7
  id v120; // x20
  void *v121; // x21
  id v122; // x20
  int v123; // w5
  int v124; // w6
  int v125; // w7
  id v126; // x20
  void *v127; // x21
  id v128; // x20
  int v129; // w5
  int v130; // w6
  int v131; // w7
  id v132; // x20
  __SecKey *v133; // x21
  id v134; // x20
  int v135; // w5
  int v136; // w6
  int v137; // w7
  id v138; // x20
  __SecKey *v139; // x21
  id v140; // x20
  int v141; // w5
  int v142; // w6
  int v143; // w7
  id v144; // x21
  void *v145; // x26
  int v146; // w5
  int v147; // w6
  int v148; // w7
  __SecKey *v149; // x0
  int v150; // w5
  int v151; // w6
  int v152; // w7
  CFDataRef v153; // x0
  int v154; // w5
  int v155; // w6
  int v156; // w7
  CFDataRef v157; // x24
  int v158; // w1
  id v159; // x26
  id v160; // x21
  int v161; // w5
  int v162; // w6
  int v163; // w7
  __SecKey *v164; // x19
  __CFString **v165; // x8
  CFDataRef v166; // x26
  CFDataRef v167; // x2
  void *v168; // x20
  id v169; // x21
  void *v170; // x20
  void *v171; // x21
  void *v172; // x0
  void *v173; // x23
  int v174; // w5
  int v175; // w6
  int v176; // w7
  void *v177; // x20
  int v178; // w5
  int v179; // w6
  int v180; // w7
  void *v181; // x20
  void *v182; // x21
  void *v183; // x0
  void *v184; // x20
  int v185; // w5
  int v186; // w6
  int v187; // w7
  void *v188; // x20
  int v189; // w5
  int v190; // w6
  int v191; // w7
  void *v192; // x20
  void *v193; // x21
  void *v194; // x0
  void *v195; // x20
  int v196; // w5
  int v197; // w6
  int v198; // w7
  int v199; // w5
  int v200; // w6
  int v201; // w7
  int v202; // w5
  int v203; // w6
  int v204; // w7
  __SecKey *v205; // x0
  void *v206; // x20
  id v207; // x21
  void *v208; // x20
  void *v209; // x21
  id v210; // x22
  void *v211; // x21
  unsigned int v212; // w19
  void *v213; // x22
  id v214; // x23
  void *v215; // x21
  void *v216; // x22
  id v217; // x23
  void *v218; // x21
  void *v219; // x22
  id v220; // x23
  void *v221; // x21
  void *v222; // x22
  id v223; // x23
  void *v224; // x23
  int v225; // w5
  int v226; // w6
  int v227; // w7
  void *v228; // x22
  id v229; // x23
  __SecKey *v230; // x21
  __SecKey *v231; // x24
  void *v232; // x28
  id v233; // x27
  void *v234; // x25
  void *v235; // x26
  __SecKey *v236; // x23
  void *v237; // x22
  id v238; // x19
  const void *v239; // x20
  __SecKey *v240; // x21
  __SecKey *v241; // x0
  id v242; // x19
  NSDictionary *v243; // x22
  void *v244; // x24
  __CFString **v245; // x8
  void *v246; // x0
  id v247; // x0
  void *v248; // x22
  char v249; // w23
  id v250; // x19
  id v251; // x23
  int v252; // w5
  int v253; // w6
  int v254; // w7
  id v255; // x19
  id v256; // x24
  int v257; // w5
  int v258; // w6
  int v259; // w7
  char is_darwinos; // w0
  id v261; // x19
  id v262; // x21
  int v263; // w5
  int v264; // w6
  int v265; // w7
  id v266; // x24
  NSData *v267; // x24
  int v268; // w5
  int v269; // w6
  int v270; // w7
  CFDataRef v271; // x2
  int v272; // w5
  int v273; // w6
  int v274; // w7
  char v275; // [xsp+0h] [xbp-3B0h]
  char v276; // [xsp+0h] [xbp-3B0h]
  void *v277; // [xsp+8h] [xbp-3A8h]
  __SecKey *v278; // [xsp+18h] [xbp-398h]
  __SecKey *v279; // [xsp+20h] [xbp-390h]
  void *v280; // [xsp+28h] [xbp-388h]
  void *v281; // [xsp+30h] [xbp-380h]
  void *v282; // [xsp+38h] [xbp-378h]
  __SecKey *v283; // [xsp+40h] [xbp-370h]
  __SecKey *v284; // [xsp+48h] [xbp-368h]
  __SecKey *cf; // [xsp+50h] [xbp-360h]
  id v286; // [xsp+58h] [xbp-358h]
  id v287; // [xsp+58h] [xbp-358h]
  char v288[8]; // [xsp+60h] [xbp-350h]
  __SecKey *v289; // [xsp+68h] [xbp-348h]
  __SecKey *v290; // [xsp+70h] [xbp-340h]
  const void *v291; // [xsp+78h] [xbp-338h]
  id v292; // [xsp+80h] [xbp-330h]
  id v293; // [xsp+80h] [xbp-330h]
  __SecKey *v294; // [xsp+88h] [xbp-328h]
  __SecKey *v295; // [xsp+88h] [xbp-328h]
  CFDataRef v296; // [xsp+90h] [xbp-320h]
  unsigned int v297; // [xsp+98h] [xbp-318h]
  NSData *v298; // [xsp+98h] [xbp-318h]
  CFDataRef v299; // [xsp+A0h] [xbp-310h]
  id v300; // [xsp+A8h] [xbp-308h]
  id v301; // [xsp+B0h] [xbp-300h]
  id v302; // [xsp+B8h] [xbp-2F8h]
  _BOOL4 v303; // [xsp+C0h] [xbp-2F0h]
  _BOOL4 v304; // [xsp+C0h] [xbp-2F0h]
  id v305; // [xsp+C0h] [xbp-2F0h]
  id v306; // [xsp+C8h] [xbp-2E8h]
  id v307; // [xsp+D0h] [xbp-2E0h]
  NSNumber *v308; // [xsp+D8h] [xbp-2D8h]
  NSNumber *v309; // [xsp+E0h] [xbp-2D0h]
  id v310; // [xsp+E8h] [xbp-2C8h]
  id v311; // [xsp+F0h] [xbp-2C0h]
  id v312; // [xsp+F8h] [xbp-2B8h]
  NSNumber *v313; // [xsp+100h] [xbp-2B0h]
  id v314; // [xsp+108h] [xbp-2A8h]
  id v315; // [xsp+110h] [xbp-2A0h]
  __SecKey *v316; // [xsp+118h] [xbp-298h]
  unsigned int v317; // [xsp+118h] [xbp-298h]
  id v318; // [xsp+120h] [xbp-290h]
  id v319; // [xsp+128h] [xbp-288h]
  CFDataRef v320; // [xsp+130h] [xbp-280h]
  id v321; // [xsp+138h] [xbp-278h]
  NSNumber *v322; // [xsp+140h] [xbp-270h]
  __SecKey *v323; // [xsp+148h] [xbp-268h]
  id v324; // [xsp+148h] [xbp-268h]
  id v325; // [xsp+148h] [xbp-268h]
  id v327; // [xsp+158h] [xbp-258h] BYREF
  id v328; // [xsp+160h] [xbp-250h] BYREF
  id v329; // [xsp+168h] [xbp-248h] BYREF
  id v330[2]; // [xsp+170h] [xbp-240h] BYREF
  id v331; // [xsp+180h] [xbp-230h] BYREF
  id v332; // [xsp+188h] [xbp-228h] BYREF
  id v333; // [xsp+190h] [xbp-220h] BYREF
  id v334[3]; // [xsp+198h] [xbp-218h] BYREF
  id v335[2]; // [xsp+1B0h] [xbp-200h] BYREF
  id v336[2]; // [xsp+1C0h] [xbp-1F0h]
  id v337[2]; // [xsp+1D0h] [xbp-1E0h]
  id v338[2]; // [xsp+1E0h] [xbp-1D0h]
  CFErrorRef error; // [xsp+1F0h] [xbp-1C0h] BYREF
  id v340[12]; // [xsp+1F8h] [xbp-1B8h] BYREF
  _QWORD v341[12]; // [xsp+258h] [xbp-158h] BYREF
  char v342[8]; // [xsp+2B8h] [xbp-F8h] BYREF
  _QWORD v343[3]; // [xsp+338h] [xbp-78h] BYREF
  __int64 vars8; // [xsp+3B8h] [xbp+8h]

  v4 = objc_retain(a2);
  error = 0;
  v5 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
  v6 = objc_msgSend(v5, "copyAnswer:", CFSTR("s7nuHoZIYNoOHCqT9iyZkQ"));
  objc_release(v5);
  v319 = v6;
  v7 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v6));
  objc_release(v7);
  if ( !v7 )
  {
    v322 = 0;
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    244,
                                                    -1,
                                                    0,
                                                    (int)CFSTR("Failed to retrieve %@."),
                                                    v8,
                                                    v9,
                                                    v10,
                                                    (char)CFSTR("s7nuHoZIYNoOHCqT9iyZkQ")));
    v302 = 0;
    v31 = 0;
    v306 = 0;
    v307 = 0;
    v315 = 0;
    v299 = 0;
    v300 = 0;
    v310 = 0;
    v311 = 0;
    v313 = 0;
    v308 = 0;
    v309 = 0;
    v318 = 0;
    v321 = 0;
    v27 = 0;
    a1 = 0;
    v32 = 0;
    v33 = 0;
    v34 = 0;
    v35 = 0;
LABEL_18:
    v320 = 0;
    v316 = 0;
LABEL_46:
    v296 = 0;
    v298 = 0;
    v312 = 0;
    v314 = 0;
    v44 = 0;
LABEL_47:
    v72 = 0;
    v301 = 0;
    v305 = 0;
    goto LABEL_180;
  }
  v11 = objc_alloc((Class)&OBJC_CLASS___NSMutableArray);
  v343[0] = CFSTR("1.2.840.113635.100.8.4");
  v343[1] = CFSTR("1.2.840.113635.100.8.5");
  v343[2] = CFSTR("1.2.840.113635.100.8.7");
  v12 = objc_retainAutoreleasedReturnValue(+[NSArray arrayWithObjects:count:](&OBJC_CLASS___NSArray, "arrayWithObjects:count:", v343, 3));
  v13 = objc_msgSend(v11, "initWithArray:", v12);
  objc_release(v12);
  v14 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 0));
  v322 = v14;
  if ( !v4 )
  {
    v36 = 0;
    v297 = 0;
    v37 = 0;
    v320 = 0;
    v38 = 0;
    v310 = 0;
    v311 = 0;
    v300 = 0;
    v315 = 0;
    v306 = 0;
    v39 = 0;
    v40 = 1;
    v41 = (NSNumber *)&off_100E66CB8;
    v308 = (NSNumber *)&off_100E66CB8;
    v309 = (NSNumber *)&off_100E66CA0;
    goto LABEL_20;
  }
  v18 = v14;
  v323 = a1;
  v19 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
  v20 = objc_retainAutoreleasedReturnValue((id)isKindOfClass());
  objc_release(v20);
  objc_release(v19);
  if ( v20 )
  {
    v321 = v13;
    *(_OWORD *)v337 = 0u;
    *(_OWORD *)v338 = 0u;
    *(_OWORD *)v335 = 0u;
    *(_OWORD *)v336 = 0u;
    v21 = v4;
    v22 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    v23 = (char *)objc_msgSend(v22, "countByEnumeratingWithState:objects:count:", v335, v342, 16);
    if ( v23 )
    {
      v24 = v23;
      v25 = *(_QWORD *)v336[0];
      while ( 2 )
      {
        for ( i = 0; i != v24; ++i )
        {
          if ( *(_QWORD *)v336[0] != v25 )
            objc_enumerationMutation(v22);
          v27 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(*((_QWORD *)v335[1] + (_QWORD)i)));
          objc_release(v27);
          if ( !v27 )
          {
            v4 = v21;
            v277 = objc_retainAutoreleasedReturnValue(objc_msgSend(v21, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
            v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                            (int)"create_baa_info",
                                                            263,
                                                            -2,
                                                            0,
                                                            (int)CFSTR("Invalid options (%@): %@"),
                                                            v76,
                                                            v77,
                                                            v78,
                                                            (char)CFSTR("OIDSToInclude")));
            objc_release(v277);
            objc_release(v22);
            v302 = 0;
            v31 = 0;
            v306 = 0;
            v307 = 0;
            v315 = 0;
            v300 = 0;
            v310 = 0;
            v311 = 0;
            v318 = 0;
            goto LABEL_93;
          }
        }
        v24 = (char *)objc_msgSend(v22, "countByEnumeratingWithState:objects:count:", v335, v342, 16);
        if ( v24 )
          continue;
        break;
      }
    }
    objc_release(v22);
    v4 = v21;
    v13 = objc_retainAutoreleasedReturnValue(objc_msgSend(v21, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    objc_release(v321);
    v18 = v322;
  }
  v321 = v13;
  if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.1"))
    && ((sub_100C87320() & 1) != 0 || (unsigned int)sub_100C87330()) )
  {
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    276,
                                                    -2,
                                                    0,
                                                    (int)CFSTR("Boot manifest not available in rOS or diagnosticsOS."),
                                                    v28,
                                                    v29,
                                                    v30,
                                                    v275));
    v302 = 0;
    v31 = 0;
    v306 = 0;
    v315 = 0;
    v300 = 0;
    v310 = 0;
    v311 = 0;
    v318 = 0;
    goto LABEL_92;
  }
  v304 = ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.1")) & 1) != 0
      || ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.7")) & 1) != 0
      || ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.1")) & 1) != 0
      || ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.2")) & 1) != 0
      || (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.10.3"));
  v70 = (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.7"));
  if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.2")) & 1) != 0
    || (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.8.11.1")) )
  {
    v71 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("nonce")));
    v72 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
    objc_release(v72);
    objc_release(v71);
    if ( !v72 )
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      295,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Missing required option: %@"),
                                                      v73,
                                                      v74,
                                                      v75,
                                                      (char)CFSTR("nonce")));
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v307 = 0;
      v315 = 0;
      v316 = 0;
      v299 = 0;
      v300 = 0;
      v310 = 0;
      v311 = 0;
      v318 = 0;
      v27 = 0;
      a1 = 0;
      v32 = 0;
      v33 = 0;
      v34 = 0;
      v35 = 0;
      v7 = 0;
      v320 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v314 = 0;
      v44 = 0;
LABEL_96:
      v301 = 0;
      v305 = 0;
      v313 = (NSNumber *)&off_100E66CB8;
      v308 = (NSNumber *)&off_100E66CB8;
      v309 = (NSNumber *)&off_100E66CA0;
      goto LABEL_180;
    }
    v318 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("nonce")));
  }
  else
  {
    v318 = 0;
  }
  v83 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CertType")));
  v84 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v83));
  objc_release(v84);
  objc_release(v83);
  v293 = v4;
  if ( v84 )
  {
    v85 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CertType")));
    objc_release(v18);
    v86 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 0));
    if ( -[NSNumber isEqualToNumber:](v85, "isEqualToNumber:", v86) )
    {
      objc_release(v86);
      v18 = v85;
    }
    else
    {
      v87 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 1));
      v88 = -[NSNumber isEqualToNumber:](v85, "isEqualToNumber:", v87);
      objc_release(v87);
      objc_release(v86);
      v18 = v85;
      if ( (v88 & 1) == 0 )
      {
        v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                        (int)"create_baa_info",
                                                        306,
                                                        -2,
                                                        0,
                                                        (int)CFSTR("Invalid value for option (%@): %@"),
                                                        v89,
                                                        v90,
                                                        v91,
                                                        (char)CFSTR("CertType")));
        v302 = 0;
        v31 = 0;
        v306 = 0;
        v307 = 0;
        v315 = 0;
        v316 = 0;
        v299 = 0;
        v300 = 0;
        v310 = 0;
        v311 = 0;
        v27 = 0;
        a1 = 0;
        v32 = 0;
        v33 = 0;
        v34 = 0;
        v35 = 0;
        v7 = 0;
        v320 = 0;
        v296 = 0;
        v298 = 0;
        v314 = 0;
        v44 = 0;
        v72 = 0;
        v301 = 0;
        v305 = 0;
        v322 = v85;
        v312 = 0;
        v313 = (NSNumber *)&off_100E66CB8;
        v308 = (NSNumber *)&off_100E66CB8;
        v309 = (NSNumber *)&off_100E66CA0;
        v4 = v293;
        goto LABEL_180;
      }
    }
  }
  v92 = objc_retainAutoreleasedReturnValue(+[NSNumber numberWithUnsignedInt:](&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", 1));
  v93 = -[NSNumber isEqualToNumber:](v18, "isEqualToNumber:", v92);
  objc_release(v92);
  v322 = v18;
  if ( v93 )
  {
    v4 = v293;
    if ( ((unsigned int)objc_msgSend(v319, "boolValue") & 1) == 0 )
    {
      v97 = CFSTR("Certificate type not supported on this platform: %@");
      v276 = (char)v18;
      v98 = 313;
      v99 = -3;
      goto LABEL_89;
    }
    if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1")) & 1) == 0 )
    {
      v97 = CFSTR("Missing required OID for certificate type (%@): %@");
      v276 = (char)v18;
      v98 = 318;
LABEL_66:
      v99 = -2;
LABEL_89:
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      v98,
                                                      v99,
                                                      0,
                                                      (int)v97,
                                                      v94,
                                                      v95,
                                                      v96,
                                                      v276));
LABEL_90:
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v315 = 0;
      v300 = 0;
      v311 = 0;
LABEL_91:
      v310 = 0;
LABEL_92:
      v307 = 0;
      v27 = 0;
LABEL_93:
      a1 = 0;
      v32 = 0;
      v33 = 0;
      v34 = 0;
      v299 = 0;
      v35 = 0;
      goto LABEL_94;
    }
  }
  else
  {
    v4 = v293;
    if ( ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1")) & 1) != 0
      || ((unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.2")) & 1) != 0
      || (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.3")) )
    {
      v97 = CFSTR("Invalid OID(s) for requested certificate type: %@");
      v276 = (char)v18;
      v98 = 325;
      goto LABEL_66;
    }
  }
  if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.1"))
    && (v168 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties"))),
        v169 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_2()),
        objc_release(v169),
        objc_release(v168),
        v169) )
  {
    v170 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties")));
    v171 = objc_msgSend(v170, "length");
    objc_release(v170);
    v172 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiProperties")));
    v173 = v172;
    if ( v171 != (void *)32 )
    {
      objc_msgSend(v172, "length");
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      333,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
                                                      v174,
                                                      v175,
                                                      v176,
                                                      (char)CFSTR("MFiProperties")));
      objc_release(v173);
      goto LABEL_90;
    }
  }
  else
  {
    v173 = 0;
  }
  v311 = v173;
  if ( (unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.2")) )
  {
    v177 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
    v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v177));
    objc_release(v44);
    objc_release(v177);
    if ( !v44 )
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      343,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Missing required option: %@"),
                                                      v178,
                                                      v179,
                                                      v180,
                                                      (char)CFSTR("MFiPPUID")));
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v315 = 0;
      v300 = 0;
LABEL_135:
      v310 = 0;
      v307 = 0;
      v27 = 0;
      a1 = 0;
      v32 = 0;
      v33 = 0;
      v34 = 0;
      v298 = 0;
      v299 = 0;
      v35 = 0;
      v7 = 0;
      v320 = 0;
      v316 = 0;
      v296 = 0;
      v312 = 0;
      v314 = 0;
      goto LABEL_95;
    }
    v181 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
    v182 = objc_msgSend(v181, "length");
    objc_release(v181);
    v183 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiPPUID")));
    v184 = v183;
    if ( (unsigned __int64)v182 >= 0x25 )
    {
      objc_msgSend(v183, "length");
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      348,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
                                                      v185,
                                                      v186,
                                                      v187,
                                                      (char)CFSTR("MFiPPUID")));
      objc_release(v184);
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v315 = 0;
      v300 = 0;
      goto LABEL_91;
    }
    v35 = objc_retainAutoreleasedReturnValue(objc_msgSend(v183, "stringByPaddingToLength:withString:startingAtIndex:", 36, &stru_100E61E50, 0));
    objc_release(v184);
    if ( !v35 )
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      357,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Failed to pad string."),
                                                      v199,
                                                      v200,
                                                      v201,
                                                      v275));
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v307 = 0;
      v315 = 0;
      v299 = 0;
      v300 = 0;
      v310 = 0;
      v27 = 0;
      a1 = 0;
      v32 = 0;
      v33 = 0;
      v34 = 0;
LABEL_94:
      v7 = 0;
      v320 = 0;
      v316 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v314 = 0;
      v44 = 0;
LABEL_95:
      v72 = 0;
      goto LABEL_96;
    }
    v315 = objc_retainAutoreleasedReturnValue(objc_msgSend(v35, "dataUsingEncoding:", 4));
    if ( !v315 )
    {
      v300 = v35;
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      363,
                                                      -2,
                                                      0,
                                                      (int)CFSTR("Failed to convert string to data."),
                                                      v202,
                                                      v203,
                                                      v204,
                                                      v275));
      v302 = 0;
      v31 = 0;
      v306 = 0;
      v315 = 0;
      goto LABEL_91;
    }
  }
  else
  {
    v35 = 0;
    v315 = 0;
  }
  v300 = v35;
  if ( !(unsigned int)objc_msgSend(v13, "containsObject:", CFSTR("1.2.840.113635.100.6.71.3")) )
  {
    v306 = 0;
    goto LABEL_137;
  }
  v188 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
  v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
  objc_release(v44);
  objc_release(v188);
  if ( !v44 )
  {
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    370,
                                                    -2,
                                                    0,
                                                    (int)CFSTR("Missing required option: %@"),
                                                    v189,
                                                    v190,
                                                    v191,
                                                    (char)CFSTR("MFiData")));
    v302 = 0;
    v31 = 0;
    v306 = 0;
    goto LABEL_135;
  }
  v192 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
  v193 = objc_msgSend(v192, "length");
  objc_release(v192);
  v194 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("MFiData")));
  v195 = v194;
  if ( (unsigned __int64)v193 >= 0x4B0 )
  {
    objc_msgSend(v194, "length");
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    375,
                                                    -2,
                                                    0,
                                                    (int)CFSTR("Invalid value for option (%@): unexpected size (%lu)"),
                                                    v196,
                                                    v197,
                                                    v198,
                                                    (char)CFSTR("MFiData")));
    objc_release(v195);
    v302 = 0;
    v31 = 0;
    v306 = 0;
    goto LABEL_91;
  }
  v306 = v194;
LABEL_137:
  v206 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseRKSigningInterface")));
  v207 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v206));
  objc_release(v207);
  objc_release(v206);
  if ( v207 )
  {
    v208 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseRKSigningInterface")));
    v317 = (unsigned int)objc_msgSend(v208, "boolValue");
    objc_release(v208);
  }
  else
  {
    v317 = 0;
  }
  v209 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
  v210 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v209));
  objc_release(v210);
  objc_release(v209);
  if ( v210 )
  {
    v211 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
    v212 = (unsigned int)objc_msgSend(v211, "boolValue");
    objc_release(v211);
  }
  else
  {
    v212 = 1;
  }
  v213 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("Validity")));
  v214 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v213));
  objc_release(v214);
  objc_release(v213);
  if ( v214 )
  {
    v215 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("Validity")));
    v309 = objc_retainAutoreleasedReturnValue(
             +[NSNumber numberWithUnsignedInteger:](
               &OBJC_CLASS___NSNumber,
               "numberWithUnsignedInteger:",
               objc_msgSend(v215, "unsignedIntegerValue")));
    objc_release(v215);
  }
  else
  {
    v309 = (NSNumber *)&off_100E66CA0;
  }
  v216 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CACert")));
  v217 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v216));
  objc_release(v217);
  objc_release(v216);
  if ( v217 )
  {
    v218 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("CACert")));
    v308 = objc_retainAutoreleasedReturnValue(
             +[NSNumber numberWithUnsignedInteger:](
               &OBJC_CLASS___NSNumber,
               "numberWithUnsignedInteger:",
               objc_msgSend(v218, "unsignedIntegerValue")));
    objc_release(v218);
  }
  else
  {
    v308 = (NSNumber *)&off_100E66CB8;
  }
  v219 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
  v220 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v219));
  objc_release(v220);
  objc_release(v219);
  if ( v220 )
  {
    v221 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
    v41 = objc_retainAutoreleasedReturnValue(
            +[NSNumber numberWithUnsignedInteger:](
              &OBJC_CLASS___NSNumber,
              "numberWithUnsignedInteger:",
              objc_msgSend(v221, "unsignedIntegerValue")));
    objc_release(v221);
  }
  else
  {
    v41 = (NSNumber *)&off_100E66CB8;
  }
  v222 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
  v223 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
  objc_release(v223);
  objc_release(v222);
  if ( !v223 )
  {
    v37 = 0;
    v320 = 0;
    goto LABEL_156;
  }
  v224 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
  v27 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_2());
  objc_release(v27);
  objc_release(v224);
  if ( !v27 )
  {
    v313 = v41;
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    412,
                                                    -2,
                                                    0,
                                                    (int)CFSTR("Missing required option for %@."),
                                                    v225,
                                                    v226,
                                                    v227,
                                                    (char)CFSTR("ClientAttestationPublicKey")));
    v302 = 0;
    v31 = 0;
    v310 = 0;
    v307 = 0;
    a1 = 0;
    v32 = 0;
    v33 = 0;
    v34 = 0;
    v299 = 0;
    v35 = 0;
    v7 = 0;
    goto LABEL_18;
  }
  v37 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
  v320 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
LABEL_156:
  v297 = v70;
  v228 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("AppID")));
  v229 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v228));
  objc_release(v229);
  objc_release(v228);
  v39 = v317 != 0;
  v40 = v212 != 0;
  if ( v229 )
    v310 = objc_retainAutoreleasedReturnValue(objc_msgSend(v4, "objectForKeyedSubscript:", CFSTR("AppID")));
  else
    v310 = 0;
  v38 = v318;
  a1 = v323;
  v36 = v304;
LABEL_20:
  v321 = v13;
  v318 = v38;
  v313 = v41;
  if ( !a1 )
  {
    v316 = v37;
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    467,
                                                    -2,
                                                    0,
                                                    (int)CFSTR("Invalid input."),
                                                    v15,
                                                    v16,
                                                    v17,
                                                    v275));
    v302 = 0;
    v31 = 0;
    v307 = 0;
    v27 = 0;
LABEL_45:
    v32 = 0;
    v33 = 0;
    v34 = 0;
    v299 = 0;
    v35 = 0;
    v7 = 0;
    goto LABEL_46;
  }
  v42 = 0;
  v303 = v36;
  if ( !v39 || v37 )
  {
    v291 = 0;
    v289 = 0;
    v294 = 0;
LABEL_49:
    v316 = v37;
    v333 = v42;
    v334[0] = 0;
    v27 = security_copy_system_key(0, v334, &v333);
    v7 = objc_retain(v334[0]);
    v79 = objc_retain(v333);
    objc_release(v42);
    if ( !v27 )
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      519,
                                                      -1,
                                                      error,
                                                      (int)CFSTR("Failed to copy SIK attestation key."),
                                                      v80,
                                                      v81,
                                                      v82,
                                                      v275));
      objc_release(v79);
      v302 = 0;
      v305 = 0;
      v301 = 0;
      v72 = 0;
      v44 = 0;
      v314 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v35 = 0;
      v299 = 0;
      v34 = 0;
      v33 = 0;
      v32 = 0;
      a1 = 0;
      v307 = 0;
      v290 = 0;
      goto LABEL_173;
    }
    *(_QWORD *)v288 = v7;
    if ( -[NSNumber boolValue](v41, "boolValue") )
    {
      v292 = v4;
      v286 = 0;
      v284 = 0;
    }
    else
    {
      v331 = v79;
      v332 = 0;
      v72 = security_copy_system_key(2, &v332, &v331);
      v286 = objc_retain(v332);
      v100 = objc_retain(v331);
      objc_release(v79);
      if ( !v72 )
      {
        v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                        (int)"create_baa_info",
                                                        528,
                                                        -1,
                                                        v100,
                                                        (int)CFSTR("Failed to copy UIK attestation key."),
                                                        v101,
                                                        v102,
                                                        v103,
                                                        v275));
        objc_release(v100);
        CFRelease(v27);
        v302 = 0;
        v305 = 0;
        v301 = 0;
        v44 = 0;
        v314 = 0;
        v296 = 0;
        v298 = 0;
        v312 = 0;
        v299 = 0;
        v34 = 0;
        v33 = 0;
        v32 = 0;
        a1 = 0;
        v27 = 0;
        v307 = 0;
        v290 = 0;
        v35 = v286;
        v7 = *(id *)v288;
        goto LABEL_173;
      }
      v284 = v72;
      v292 = v4;
      v79 = v100;
      v7 = *(id *)v288;
    }
    cf = v27;
    v104 = (__SecKey *)objc_alloc_init((Class)&OBJC_CLASS___NSMutableDictionary);
    v72 = v104;
    if ( !v104 )
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      536,
                                                      -1,
                                                      0,
                                                      (int)CFSTR("Failed to allocate dictionary."),
                                                      v105,
                                                      v106,
                                                      v107,
                                                      v275));
      objc_release(v79);
      v302 = 0;
      v305 = 0;
      v301 = 0;
      v44 = 0;
      v314 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v299 = 0;
      v34 = 0;
      v33 = 0;
      v32 = 0;
      a1 = 0;
      v27 = 0;
      v307 = 0;
      v290 = 0;
      v4 = v292;
      v35 = v286;
      goto LABEL_171;
    }
    v283 = v104;
    if ( -[NSNumber boolValue](v41, "boolValue")
      || (v108 = objc_retainAutoreleasedReturnValue(+[NSFileManager defaultManager](&OBJC_CLASS___NSFileManager, "defaultManager")),
          v109 = objc_retainAutoreleasedReturnValue(objc_retainAutoreleaseReturnValue(v108)),
          v110 = objc_retainAutoreleasedReturnValue(
                   -[NSFileManager stringByAppendingPathComponent:](
                     v109,
                     "stringByAppendingPathComponent:",
                     CFSTR("ucrt.pem"))),
          v111 = -[NSFileManager fileExistsAtPath:](v108, "fileExistsAtPath:", v110),
          objc_release(v110),
          objc_release(v109),
          objc_release(v108),
          (v111 & 1) != 0) )
    {
      v115 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
      v34 = objc_msgSend(v115, "copyAnswer:", CFSTR("UniqueChipID"));
      objc_release(v115);
      v116 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v34));
      objc_release(v116);
      if ( v116 )
      {
        v281 = v34;
        v120 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
        v121 = objc_msgSend(v120, "copyAnswer:", CFSTR("ChipID"));
        objc_release(v120);
        v282 = v121;
        v122 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v121));
        objc_release(v122);
        if ( !v122 )
        {
          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                          (int)"create_baa_info",
                                                          588,
                                                          -1,
                                                          0,
                                                          (int)CFSTR("Failed to retrieve %@."),
                                                          v123,
                                                          v124,
                                                          v125,
                                                          (char)CFSTR("ChipID")));
          objc_release(v79);
          v302 = 0;
          v305 = 0;
          v301 = 0;
          v44 = 0;
          v314 = 0;
          v296 = 0;
          v298 = 0;
          v312 = 0;
          v299 = 0;
          v32 = 0;
          a1 = 0;
          v27 = 0;
          v307 = 0;
          v290 = 0;
          v4 = v292;
          v35 = v286;
          v7 = *(id *)v288;
          v33 = v282;
          v72 = v283;
          goto LABEL_171;
        }
        v126 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
        v127 = objc_msgSend(v126, "copyAnswer:", CFSTR("BoardId"));
        objc_release(v126);
        v280 = v127;
        v128 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v127));
        objc_release(v128);
        if ( !v128 )
        {
          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                          (int)"create_baa_info",
                                                          594,
                                                          -1,
                                                          0,
                                                          (int)CFSTR("Failed to retrieve %@."),
                                                          v129,
                                                          v130,
                                                          v131,
                                                          (char)CFSTR("BoardId")));
          objc_release(v79);
          v302 = 0;
          v305 = 0;
          v301 = 0;
          v44 = 0;
          v314 = 0;
          v296 = 0;
          v298 = 0;
          v312 = 0;
          v299 = 0;
          a1 = 0;
          v27 = 0;
          v307 = 0;
          v290 = 0;
          v4 = v292;
          v35 = v286;
          v7 = *(id *)v288;
          v33 = v282;
          v72 = v283;
          v32 = v280;
          goto LABEL_171;
        }
        v132 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
        v133 = (__SecKey *)objc_msgSend(v132, "copyAnswer:", CFSTR("SecurityDomain"));
        objc_release(v132);
        v279 = v133;
        v134 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_0(v133));
        objc_release(v134);
        if ( !v134 )
        {
          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                          (int)"create_baa_info",
                                                          600,
                                                          -1,
                                                          0,
                                                          (int)CFSTR("Failed to retrieve %@."),
                                                          v135,
                                                          v136,
                                                          v137,
                                                          (char)CFSTR("SecurityDomain")));
          objc_release(v79);
          v302 = 0;
          v305 = 0;
          v301 = 0;
          v44 = 0;
          v314 = 0;
          v296 = 0;
          v298 = 0;
          v312 = 0;
          v299 = 0;
          v27 = 0;
          v307 = 0;
          v290 = 0;
          v4 = v292;
          v35 = v286;
          v7 = *(id *)v288;
          v33 = v282;
          v72 = v283;
          v32 = v280;
LABEL_133:
          a1 = v279;
          goto LABEL_171;
        }
        v138 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
        v139 = (__SecKey *)objc_msgSend(v138, "copyAnswer:", CFSTR("SerialNumber"));
        objc_release(v138);
        v278 = v139;
        v140 = objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v139));
        objc_release(v140);
        if ( v140 )
        {
          v144 = objc_retainAutoreleasedReturnValue(+[GestaltHlpr getSharedInstance](&OBJC_CLASS___GestaltHlpr, "getSharedInstance"));
          v145 = objc_msgSend(v144, "copyAnswer:", CFSTR("BuildVersion"));
          objc_release(v144);
          v307 = v145;
          v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)isKindOfClass_1(v145));
          objc_release(v44);
          if ( v44 )
          {
            v149 = SecKeyCopyPublicKey(a1);
            if ( v149 )
            {
              v290 = v149;
              v153 = SecKeyCopyExternalRepresentation(v149, &error);
              v7 = *(id *)v288;
              if ( v153 )
              {
                v157 = v153;
                if ( -[NSNumber boolValue](v313, "boolValue") )
                  v158 = 0;
                else
                  v158 = 2;
                v330[1] = v79;
                v159 = objc_retainAutoreleasedReturnValue((id)security_create_system_key_attestation(
                                                                (int)a1,
                                                                v158,
                                                                v318));
                v160 = objc_retain(v79);
                objc_release(v79);
                v312 = v159;
                v299 = v157;
                if ( v159 )
                {
                  v325 = v160;
                  if ( v316 )
                  {
                    v164 = v283;
                    -[__SecKey setObject:forKeyedSubscript:](
                      v283,
                      "setObject:forKeyedSubscript:",
                      v316,
                      CFSTR("RKCertification"));
                    -[__SecKey setObject:forKeyedSubscript:](
                      v283,
                      "setObject:forKeyedSubscript:",
                      v159,
                      CFSTR("RKSigning"));
                    v165 = off_100E52138;
                    v166 = v157;
                    v167 = v157;
                  }
                  else
                  {
                    v165 = off_100E51E10;
                    v167 = (CFDataRef)v159;
                    v164 = v283;
                    v166 = v157;
                  }
                  -[__SecKey setObject:forKeyedSubscript:](v164, "setObject:forKeyedSubscript:", v167, *v165);
                  v242 = objc_alloc((Class)&OBJC_CLASS___NSMutableDictionary);
                  v340[0] = CFSTR("UniqueChipID");
                  v340[1] = CFSTR("ChipID");
                  v341[0] = v34;
                  v341[1] = v282;
                  v340[2] = CFSTR("BoardId");
                  v340[3] = CFSTR("SecurityDomain");
                  v341[2] = v280;
                  v341[3] = v279;
                  v340[4] = CFSTR("SerialNumber");
                  v340[5] = CFSTR("OsBuildVersion");
                  v341[4] = v278;
                  v341[5] = v307;
                  v340[6] = CFSTR("scrtAttestation");
                  v340[7] = CFSTR("CertType");
                  v341[6] = v313;
                  v341[7] = v322;
                  v340[8] = CFSTR("Validity");
                  v340[9] = CFSTR("CACert");
                  v341[8] = v309;
                  v341[9] = v308;
                  v340[10] = CFSTR("OIDSToInclude");
                  v340[11] = CFSTR("SIKPub");
                  v341[10] = v13;
                  v341[11] = *(_QWORD *)v288;
                  v243 = objc_retainAutoreleasedReturnValue(
                           +[NSDictionary dictionaryWithObjects:forKeys:count:](
                             &OBJC_CLASS___NSDictionary,
                             "dictionaryWithObjects:forKeys:count:",
                             v341,
                             v340,
                             12));
                  v244 = objc_msgSend(v242, "initWithDictionary:", v243);
                  objc_release(v243);
                  v245 = off_100E52130;
                  if ( v316 )
                  {
                    objc_msgSend(v244, "setObject:forKeyedSubscript:", v320, CFSTR("RKCertificationPub"));
                    v245 = off_100E52138;
                  }
                  v35 = v286;
                  v246 = objc_msgSend(v244, "setObject:forKeyedSubscript:", v166, *v245);
                  if ( v286 )
                    v246 = objc_msgSend(v244, "setObject:forKeyedSubscript:", v286, CFSTR("UIKPub"));
                  v247 = objc_retainAutoreleasedReturnValue((id)IORegistryEntry_sub_10052290C(v246));
                  v314 = v244;
                  if ( !v247 )
                    goto LABEL_201;
                  v248 = v247;
                  if ( (sub_100C87330() & 1) != 0 )
                  {
                    objc_release(v248);
LABEL_201:
                    v302 = 0;
LABEL_207:
                    if ( v303 && (sub_100C87320() & 1) == 0 )
                    {
                      if ( (sub_100C87330() & 1) != 0 )
                      {
                        v301 = 0;
                      }
                      else
                      {
                        v329 = v325;
                        v255 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(2, &v329));
                        v256 = objc_retain(v329);
                        objc_release(v325);
                        v301 = v255;
                        if ( !v255 )
                        {
                          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                          (int)"create_baa_info",
                                                                          735,
                                                                          -1,
                                                                          v256,
                                                                          (int)CFSTR("Failed to load boot manifest."),
                                                                          v257,
                                                                          v258,
                                                                          v259,
                                                                          v275));
                          objc_release(v256);
                          v305 = 0;
                          v301 = 0;
LABEL_240:
                          v44 = 0;
                          v296 = 0;
                          v298 = 0;
                          goto LABEL_168;
                        }
                        objc_msgSend(v314, "setObject:forKeyedSubscript:", v255, CFSTR("Image4Manifest"));
                        v325 = v256;
                      }
                      v35 = v286;
                      v7 = *(id *)v288;
                      v34 = v281;
                    }
                    else
                    {
                      v301 = 0;
                    }
                    if ( (sub_100C87330() & 1) != 0 )
                    {
                      v305 = 0;
LABEL_221:
                      v4 = v292;
                      v266 = v306;
                      v72 = v283;
LABEL_222:
                      v33 = v282;
                      v262 = v325;
                      goto LABEL_223;
                    }
                    is_darwinos = os_variant_is_darwinos(objc_msgSend(CFSTR("com.apple.mobileactivationd"), "UTF8String"));
                    v305 = 0;
                    if ( !v297 )
                      goto LABEL_221;
                    if ( (is_darwinos & 1) != 0 )
                    {
                      v4 = v292;
                      v266 = v306;
                      v35 = v286;
                      v7 = *(id *)v288;
                      v72 = v283;
                      v34 = v281;
                      goto LABEL_222;
                    }
                    v328 = v325;
                    v261 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(10, &v328));
                    v262 = objc_retain(v328);
                    objc_release(v325);
                    v305 = v261;
                    if ( v261 )
                    {
                      objc_msgSend(v314, "setObject:forKeyedSubscript:", v261, CFSTR("Cryptex1Image4Manifest"));
                      v4 = v292;
                      v266 = v306;
                      v35 = v286;
                      v7 = *(id *)v288;
                      v33 = v282;
                      v72 = v283;
                      v34 = v281;
LABEL_223:
                      v32 = v280;
                      if ( v310 )
                        objc_msgSend(v314, "setObject:forKeyedSubscript:", v310, CFSTR("AppID"));
                      if ( v311 )
                        objc_msgSend(v314, "setObject:forKeyedSubscript:", v311, CFSTR("MFiProperties"));
                      if ( v315 )
                        objc_msgSend(v314, "setObject:forKeyedSubscript:", v315, CFSTR("MFiPPUID"));
                      if ( v266 )
                        objc_msgSend(v314, "setObject:forKeyedSubscript:", v266, CFSTR("MFiData"));
                      v327 = 0;
                      v267 = objc_retainAutoreleasedReturnValue(
                               +[NSPropertyListSerialization dataWithPropertyList:format:options:error:](
                                 &OBJC_CLASS___NSPropertyListSerialization,
                                 "dataWithPropertyList:format:options:error:",
                                 v314,
                                 100,
                                 0,
                                 &v327));
                      v287 = objc_retain(v327);
                      objc_release(v262);
                      if ( v267 )
                      {
                        -[__SecKey setObject:forKeyedSubscript:](
                          v72,
                          "setObject:forKeyedSubscript:",
                          v267,
                          CFSTR("RKProperties"));
                        v298 = v267;
                        v271 = SecKeyCreateSignature(
                                 a1,
                                 kSecKeyAlgorithmECDSASignatureMessageX962SHA256,
                                 (CFDataRef)v267,
                                 &error);
                        v27 = v278;
                        if ( v271 )
                        {
                          v296 = v271;
                          -[__SecKey setObject:forKeyedSubscript:](
                            v72,
                            "setObject:forKeyedSubscript:",
                            v271,
                            CFSTR("RKPropertiesSignature"));
                          v44 = objc_retain(v72);
                          v324 = v287;
                        }
                        else
                        {
                          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                          (int)"create_baa_info",
                                                                          810,
                                                                          -1,
                                                                          error,
                                                                          (int)CFSTR("Failed to sign data with ref key."),
                                                                          v272,
                                                                          v273,
                                                                          v274,
                                                                          v275));
                          objc_release(v287);
                          v44 = 0;
                          v296 = 0;
                        }
                        goto LABEL_133;
                      }
                      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                      (int)"create_baa_info",
                                                                      799,
                                                                      -1,
                                                                      v287,
                                                                      (int)CFSTR("Could not convert dictionary to xml data."),
                                                                      v268,
                                                                      v269,
                                                                      v270,
                                                                      v275));
                      objc_release(v287);
                      v44 = 0;
                      v296 = 0;
                      v298 = 0;
LABEL_170:
                      v27 = v278;
                      a1 = v279;
LABEL_171:
                      CFRelease(cf);
                      if ( v284 )
                        CFRelease(v284);
LABEL_173:
                      if ( v289 )
                        CFRelease(v289);
                      v205 = v294;
                      if ( !v294 )
                        goto LABEL_177;
                      goto LABEL_176;
                    }
                    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                    (int)"create_baa_info",
                                                                    770,
                                                                    -1,
                                                                    v262,
                                                                    (int)CFSTR("Failed to load cryptex1 manifest."),
                                                                    v263,
                                                                    v264,
                                                                    v265,
                                                                    v275));
                    objc_release(v262);
                    v305 = 0;
                    goto LABEL_240;
                  }
                  v249 = os_variant_is_darwinos(objc_msgSend(CFSTR("com.apple.mobileactivationd"), "UTF8String"));
                  objc_release(v248);
                  if ( (v249 & 1) != 0 )
                  {
                    v302 = 0;
LABEL_206:
                    v34 = v281;
                    goto LABEL_207;
                  }
                  v330[0] = v160;
                  v250 = objc_retainAutoreleasedReturnValue((id)sub_100C75830(9, v330));
                  v251 = objc_retain(v330[0]);
                  objc_release(v160);
                  v302 = v250;
                  if ( v250 )
                  {
                    objc_msgSend(v244, "setObject:forKeyedSubscript:", v250, CFSTR("LocalPolicy"));
                    v325 = v251;
                    v35 = v286;
                    v7 = *(id *)v288;
                    goto LABEL_206;
                  }
                  v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                  (int)"create_baa_info",
                                                                  719,
                                                                  -1,
                                                                  v251,
                                                                  (int)CFSTR("Failed to load cryptex1 local policy."),
                                                                  v252,
                                                                  v253,
                                                                  v254,
                                                                  v275));
                  objc_release(v251);
                  v305 = 0;
                  v301 = 0;
                  v44 = 0;
                  v296 = 0;
                  v298 = 0;
LABEL_167:
                  v302 = 0;
LABEL_168:
                  v4 = v292;
                  v7 = *(id *)v288;
LABEL_169:
                  v35 = v286;
                  v33 = v282;
                  v72 = v283;
                  v32 = v280;
                  v34 = v281;
                  goto LABEL_170;
                }
                v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                (int)"create_baa_info",
                                                                637,
                                                                -1,
                                                                v160,
                                                                (int)CFSTR("Failed to create reference key attestation (nonce: %@)."),
                                                                v161,
                                                                v162,
                                                                v163,
                                                                (char)v318));
                objc_release(v160);
                v305 = 0;
                v301 = 0;
                v44 = 0;
                v314 = 0;
                v296 = 0;
                v298 = 0;
                v312 = 0;
              }
              else
              {
                v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                                (int)"create_baa_info",
                                                                628,
                                                                -1,
                                                                0,
                                                                (int)CFSTR("Failed to encode RK public key as data."),
                                                                v154,
                                                                v155,
                                                                v156,
                                                                v275));
                objc_release(v79);
                v305 = 0;
                v301 = 0;
                v44 = 0;
                v314 = 0;
                v296 = 0;
                v298 = 0;
                v312 = 0;
                v299 = 0;
              }
              v302 = 0;
              v4 = v292;
              goto LABEL_169;
            }
            v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                            (int)"create_baa_info",
                                                            622,
                                                            -1,
                                                            0,
                                                            (int)CFSTR("Failed to copy RK public key."),
                                                            v150,
                                                            v151,
                                                            v152,
                                                            v275));
            objc_release(v79);
            v305 = 0;
            v301 = 0;
            v44 = 0;
          }
          else
          {
            v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                            (int)"create_baa_info",
                                                            612,
                                                            -1,
                                                            v79,
                                                            (int)CFSTR("Failed to retrieve %@."),
                                                            v146,
                                                            v147,
                                                            v148,
                                                            (char)CFSTR("BuildVersion")));
            objc_release(v79);
            v305 = 0;
            v301 = 0;
          }
          v314 = 0;
          v296 = 0;
          v298 = 0;
          v312 = 0;
          v299 = 0;
        }
        else
        {
          v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                          (int)"create_baa_info",
                                                          606,
                                                          -1,
                                                          0,
                                                          (int)CFSTR("Failed to retrieve %@."),
                                                          v141,
                                                          v142,
                                                          v143,
                                                          (char)CFSTR("SerialNumber")));
          objc_release(v79);
          v305 = 0;
          v301 = 0;
          v44 = 0;
          v314 = 0;
          v296 = 0;
          v298 = 0;
          v312 = 0;
          v299 = 0;
          v307 = 0;
        }
        v290 = 0;
        goto LABEL_167;
      }
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      582,
                                                      -1,
                                                      0,
                                                      (int)CFSTR("Failed to retrieve %@."),
                                                      v117,
                                                      v118,
                                                      v119,
                                                      (char)CFSTR("UniqueChipID")));
      objc_release(v79);
      v305 = 0;
      v301 = 0;
      v44 = 0;
      v314 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v299 = 0;
    }
    else
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      543,
                                                      -4,
                                                      0,
                                                      (int)CFSTR("UCRT is unavailable."),
                                                      v112,
                                                      v113,
                                                      v114,
                                                      v275));
      objc_release(v79);
      v305 = 0;
      v301 = 0;
      v44 = 0;
      v314 = 0;
      v296 = 0;
      v298 = 0;
      v312 = 0;
      v299 = 0;
      v34 = 0;
    }
    v33 = 0;
    v32 = 0;
    a1 = 0;
    v27 = 0;
    v307 = 0;
    v290 = 0;
    v302 = 0;
    v4 = v292;
    v35 = v286;
    v7 = *(id *)v288;
    v72 = v283;
    goto LABEL_171;
  }
  if ( -[NSNumber boolValue](v41, "boolValue") )
    v43 = 0;
  else
    v43 = 2;
  v334[2] = 0;
  v44 = (__SecKey *)objc_retainAutoreleasedReturnValue((id)security_create_system_key_attestation((int)a1, v43, v38));
  v48 = objc_retain(0);
  if ( !v44 )
  {
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    477,
                                                    -1,
                                                    v48,
                                                    (int)CFSTR("Failed to create reference key attestation."),
                                                    v45,
                                                    v46,
                                                    v47,
                                                    v275));
    objc_release(v48);
    v302 = 0;
    v31 = 0;
    v307 = 0;
    v27 = 0;
    a1 = 0;
    v32 = 0;
    v33 = 0;
    v34 = 0;
    v298 = 0;
    v299 = 0;
    v35 = 0;
    v7 = 0;
    v316 = 0;
    v296 = 0;
    v312 = 0;
    v314 = 0;
    goto LABEL_47;
  }
  v316 = v44;
  v49 = SecKeyCopyPublicKey(a1);
  if ( !v49 )
  {
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    483,
                                                    -1,
                                                    0,
                                                    (int)CFSTR("Failed to copy RK public key."),
                                                    v50,
                                                    v51,
                                                    v52,
                                                    v275));
    objc_release(v48);
    v302 = 0;
    v31 = 0;
    v307 = 0;
    v27 = 0;
    a1 = 0;
    goto LABEL_45;
  }
  v294 = v49;
  v53 = SecKeyCopyExternalRepresentation(v49, &error);
  objc_release(v320);
  if ( v53 )
  {
    v57 = SecAccessControlCreate(0, &error);
    if ( v57 )
    {
      v61 = kSecAttrAccessibleUntilReboot;
      v62 = v57;
      v291 = (const void *)v57;
      if ( (SecAccessControlSetProtection(v57, kSecAttrAccessibleUntilReboot, &error) & 1) != 0 )
      {
        v334[1] = v48;
        v66 = (__SecKey *)sub_100C6E934(v62, v40, v4);
        v42 = objc_retain(v48);
        objc_release(v48);
        if ( v66 )
        {
          v320 = v53;
          a1 = v66;
          v289 = v66;
          v37 = v316;
          goto LABEL_49;
        }
        v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                        (int)"create_baa_info",
                                                        508,
                                                        -1,
                                                        v42,
                                                        (int)CFSTR("Failed to create reference key."),
                                                        v67,
                                                        v68,
                                                        v69,
                                                        v275));
        v48 = v42;
      }
      else
      {
        v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                        (int)"create_baa_info",
                                                        502,
                                                        -1,
                                                        error,
                                                        (int)CFSTR("Failed to set ACL protection to %@."),
                                                        v63,
                                                        v64,
                                                        v65,
                                                        v61));
      }
    }
    else
    {
      v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                      (int)"create_baa_info",
                                                      497,
                                                      -1,
                                                      error,
                                                      (int)CFSTR("Failed to create access control."),
                                                      v58,
                                                      v59,
                                                      v60,
                                                      v275));
      v291 = 0;
    }
    v320 = v53;
  }
  else
  {
    v324 = objc_retainAutoreleasedReturnValue((id)com_apple_MobileActivation_ErrorDomain(
                                                    (int)"create_baa_info",
                                                    489,
                                                    -1,
                                                    error,
                                                    (int)CFSTR("Failed to encode RK public key as data."),
                                                    v54,
                                                    v55,
                                                    v56,
                                                    v275));
    v320 = 0;
    v291 = 0;
  }
  objc_release(v48);
  v302 = 0;
  v305 = 0;
  v301 = 0;
  v72 = 0;
  v44 = 0;
  v314 = 0;
  v296 = 0;
  v298 = 0;
  v312 = 0;
  v7 = 0;
  v35 = 0;
  v299 = 0;
  v34 = 0;
  v33 = 0;
  v32 = 0;
  a1 = 0;
  v27 = 0;
  v307 = 0;
  v290 = 0;
  v205 = v294;
LABEL_176:
  CFRelease(v205);
LABEL_177:
  if ( v290 )
    CFRelease(v290);
  v31 = v291;
LABEL_180:
  if ( error )
  {
    v295 = v44;
    v230 = v27;
    v231 = a1;
    v232 = v32;
    v233 = v4;
    v234 = v33;
    v235 = v34;
    v236 = v72;
    v237 = v35;
    v238 = v7;
    v239 = v31;
    CFRelease(error);
    v31 = v239;
    v7 = v238;
    v35 = v237;
    v72 = v236;
    v34 = v235;
    v33 = v234;
    v4 = v233;
    v32 = v232;
    a1 = v231;
    v27 = v230;
    v44 = v295;
  }
  error = 0;
  if ( v31 )
    CFRelease(v31);
  if ( a3 && !v44 )
    *a3 = objc_retainAutorelease(v324);
  v240 = objc_retain(v44);
  objc_release(v302);
  objc_release(v324);
  objc_release(v306);
  objc_release(v315);
  objc_release(v300);
  objc_release(v311);
  objc_release(v310);
  objc_release(v322);
  objc_release(v313);
  objc_release(v308);
  objc_release(v309);
  objc_release(v318);
  objc_release(v321);
  objc_release(v307);
  objc_release(v27);
  objc_release(a1);
  objc_release(v32);
  objc_release(v33);
  objc_release(v34);
  objc_release(v299);
  objc_release(v35);
  objc_release(v7);
  objc_release(v320);
  objc_release(v316);
  objc_release(v296);
  objc_release(v312);
  objc_release(v298);
  objc_release(v314);
  objc_release(v240);
  objc_release(v72);
  objc_release(v301);
  objc_release(v319);
  objc_release(v305);
  objc_release(v4);
  if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
    __break(0xC471u);
  v241 = objc_autoreleaseReturnValue(v240);
}
  • 采集验签证书

用 SE 里封装的密钥 + 苹果预置的证书链,生成了一份 attestation(证明)blob,这个 blob 里面带着证书和签名,对“某些设备硬件字段 + 公钥”做了绑定。

这个“证书/attestation blob”是 依赖安全硬件(Secure Enclave / Apple KeyStore)生成的,而且签名覆盖了与这台硬件绑定的一些信息。

格式如下:

SEQUENCE
  INTEGER 02
  SEQUENCE
    OCTETSTRING xxxxdeca90b4fd52da1c016730a81dcb281f6c4dbb973e6b8438e6827530a177
    OCTETSTRING xxxx980ea0e8b0211cc342dc42067f1b..(total 65bytes)..2c8c482afb33b9e84221b49ffd1d81fa
    OCTETSTRING xxxx730da8259089a9b9b02bd4a455fd
    OCTETSTRING xxxxce59b8232b317ff32beb21237051
    OCTETSTRING xxxx56c0b70138d40071067ee100013f..(total 1074bytes)..4b70f5283c1085f6a8d25107d6b9a94b
  • 上报激活信息

将采集的硬件信息与证书签名信信息组合成 plist格式数据上报到服务器端

  • Headers
        0 : User-Agent = {contents = "iOS Device Activator (MobileActivation-834.100.27) - devicecheckd"}
        3 : Content-Type = {contents = "application/xml"}
        4 : Content-Length = 9822
        6 : x-jmet-deviceid = {contents = "00008110-303C30C91A06484E"}
}
  • body
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>RKCertification</key>
        <data>
        MIIExQIBAjxxxxxxxxP4C3sqQtP1S2hwBZzCoHcsoH2xNu5c+a4Q45oJ1MKF3BEEEiTxl
        3JiRx7vW49DhREeRVU04QQBLnB7Lm7nI8+D2ayS/PMZ7rcmhC89px3xHSlAvDl2MQopT
        SHXxnC/0Bs/6KgQQ1SciqWRdHp3U/vxi/S1O/wQQNpOm/5v25ojsX99XACzgpwSCBDHO
        l9izvodcLU0pQSlaNXHlIp7nMLqh/QkyEI+a/YlGFaqTR/PgZbq4o37Rw6SCZQ+MjU2F
        uzuq9O6sTaKVBcw4aDW0oPDmZgH5m1ZlDwvUqQFAy+OvNrO8L4D4zSo2lW8BRqR89jkx
        WAixq12iERj/4+orIFAFGG86P/PnRRUsC8uR1tkqM4NpjXiLNUlO/X7VF1iY7g3nf5JS
        uxAqGMNZ8eEXXHJ9I5XuPDC/B1BvpoM/Pk65CPRbaw5ojMr+McZ+IsuWQBb21dxMldAy
        MMg5sFEt5+uIqWFaVyjFMfFCqYTfSofsyFQO8woaPegrmqFBVJRTGbbPkEDEVaWgLprd
        VuoE8hkSvecWaBwsyNH0UmTLMOwrMHF12RLVPc6qChr4ki0FkIP9crLHhQwxVYeXgRpA
        ClcA6uNFFa412RdhRhv5T88NBVRNu9ewCm3gWBnhMF10PltNVGJ1ZRjhZS0ghaVnqHpj
        DA+2pnObaocLzgC9bOl0RExDwVwxLp7/hD/0jqZ+GqGSPgXYGY3FxnIB9n1e35KNjWaV
        ur1WgHps5TEdi9LHxur2iqv5IkmxXNojxUoWprRc36RCBkurDLJiCM6Es8/63z1mZQ9h
        a4iA5+u0PStVpCSjOJ/0gn01pIxxxeppomCsT6980+l1HYi7zsD/tBkOznpFwGS5Ki9h
        RErTaCc2/9YGjgWVOBv1w5dEnBnwb1P59Qgpmnx3k9eyczaxt3OXOnKVwzYKtowI0OeD
        F9jM1yN9KZVtAqQJM4H8N+W3f0w8x+PwYHUf/0AHdAK/WyUHObDkoPzZOY+N7aFvkSf8
        aVcxC5MMCM6YFGpeDN9yoroti2mxxxelwDYx7Q8wuIeBBDiJfHRMWXxQEbej2XoYxGs4
        tz8Qh0z5p0kL5bb5MERKHPkaIg+slVxEpoCAxCnNHiTHjK3gEXhgyxkiBmLO4ENSGDTp
        +5PX64sez9Sb95ua6PhFFJYRXFgnp2IqffOoxx9Pxtxf7aKvpmlhPu+YGfbpz+mF+BSQ
        Y0a/ybU0xySRCKfTlepT8J+3HGNGl6HmjKPMDgj1SIloAoNR+VATnMs0THe7ZZTYLI+m
        bghSAHqDcjZCOWbRp19gSbUz71WU/sDAbN477biemxOYszVzS6cckGmmoDSLuav8RCSH
        9h254xTGB5VzEjT5lqpsWJ0u+IJUW7gfCbkq1IGer5PdmVrzAluNTS4G85iHnXi3EKJB
        wJ1upCRMjwlQRFlKP/SDo1TTQUa1kX0x+o1bFjvroyNKq+wL56PRQex22FzN00gsursF
        dstdB+WPHde2jfeVmielZ+wxw59wEuE2CLeS5D1CLIEGYgsTyoLxl6QQ80UjaphhAuVA
        A7HqcmXNe/6AOGdL42LHUhF23K5Fd55i8yaJP0sMwzY1e3nPbeunZmIiL1KiAFcKLzpm
        cg==
        </data>
        <key>RKProperties</key>
        <data>
        ff94bfwgfmVyc2lvbjxxxxxwIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBs
        aXN0IFBVQkxJQyAiLSxxxxxwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3
        dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJz
        aW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+QXBwSUQ8L2tleT4KCTxzdHJpbmc+Y29tLmFw
        cGxlLmRldmljZWNoZWNrZDwvf3RyaW5nPgoJPGtleT5Cb2FyZElkPC9rZXk+Cgk8aW50
        ZWdlcj4yNDwvaW50ZWdlcj4KffxrZXk+QfFfZXffPC9rZXk+Cgk8aW50ZWdlcj4wPC9p
        bnRlZ2VyPgoJPGtleT5DZXJ0VHlwZTwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4K
        CTxrZXk+Q2hpcElEPC9rZXk+Cgk8aW50ZWdlcj4zMzA0MDwvaW50ZWdlcj4KCTxrZXk+
        TG9jYWxQb2xpY3k8L2tleT4KCTxkYXRhPgoJTUlJTVFCWUVTVTFITkRBVUZnUkpUVFJR
        RmdSc2NHOXNGZ014TGpBRUFRQ2dnZfdfTUfJfUhCWUVTVTAwVFFJQkFER0MKCUFpUC9o
        T3FGbkVLQ0Fob3dnZ0lXRmdSTlFxxUNNWUlDRFArRTZvV2NVSUlCbnpDQ0Fac1dCRTFC
        VGxBeGdnR1IvNFNTCgl2YVJFQ3pBSkZnUkNUMUpFQWdFWS80U2FsYUJQQ3pBSkZnUkRS
        VkJQQWdFQi80U2FvWkpRRFRBTEZnUkRTRWxRQWdNQQoJZ1JEL2hKckJwRThMTUFrV0JF
        TlFVazhCQWYvL2hKck5pa01MTUFrV0JFTlRxVU1CQfWYvL2hLcU5ra1FSTUE4V0JFVkQK
        CVNVUUNCeGhwb2p3Z0lCNy9oWnFSbmswTE1Ba1dCRk5FVDAwQ0FRSC9odU85eEc4TE1B
        a1dCR3h2WW04QkFmLy9odlBOCgkwbWc2TURnV0JHNXphV2dFTUlQc0gwYlAybmtaaDNo
        NVF3U2RXUU1CL0NoekZrWlMyczE0SxlWxnJTdDZwR2RlaDIvSgoJd3VnR2V4dFU5cWNm
        Uy8rSGs3M2NhQ293S0JZRWNtOXVhQVFnU2srUmVVVnd1QWlCeEw0cWM5WmlZZUFFQ3Y1
        OVN2dmwKCXk4SWhTM2ZaK2k3L2g1dkIwbWc2TURnV0JITndhV2dFTUo3V1ZSSWhWNU13
        ZXlXa2VHdVo5STVSbUFSNGQycm9aZnFQCglmOE92aXljRkFjUEs0cHJDUXVTN3BSa3lB
        WDQxVi8rSG04bnNiaDR3SEJZRWMzSjJiZ1FVRzIrWkp3aXFselVHSUkzQQoJVmZMcklJ
        L3RkMGYvaDdQVjBtUWFNQmdXQkhaMWFXUUVFQUFBQUFBQUFBQUFBQUFBQUFBQUFBRC9o
        dVBCM214ZE1Gc1cKCUJHeHdiMnd4VS8rRW9wMm1WRG93T0JZRVJFZFRWQVF3MFFGVU9N
        U29rWEtqQkkxZXJyeXkzbVYzZGNacStHaVJhcWVXCglHUUk5Z29haFJoREhKZVNSem1m
        MERMMVl0M2h5LzRTcXJZcFpDekFKRmdSRlMwVlpBUUgvQklJQ0FFRmdqK1krQkpheAoJ
        MU1jS3dGQkdFMHpvcElKZkJWY2dKcG5MeDV2MFA2L1VsbG1jWmZYcnVYK2t1K2xRYm9H
        UXBkQ3ZZcnp6K3l4bXVjS00KCWtDOXlJdlpzMndjMldrMzdDeHl4a1lXZ2UvckZmSERC
        WFpQS3hTc1hIRFpkVXVjanFQbGlqVkJGV1pXekJjc0hQd2M3CgkyOFJUcTNWQU9aeG0x
        RXo3RVFlVHRmUDFocDN0WEdic0xaMlZ0aVcyWG12VDFDeCsvajNCbnhnNGNtQy9EUjJW
        SmpZaQoJUUx2V0dJSTNSVUY5cUEwL3BBeGcvQ3JCeXI4Zkx3Uk5QV2haOGMwRW04eVhi
        U2MxZ1h2K0NlUnJJcVBNZXFWU1o3cGoKCXdGamlhTWlwRXEwRUJhQkcyOG9xNkNCZE9E
        K1ZDUWxYSzBNOEdqUXZXc3FpcS9UVDRlQkVGV0NQTzRKLzU2bzE4WkxpCgk5OFdZaTQy
        RVBLb0RHM0ZyTFhreWNWR0E0QTdnVlhIczBnS25TeWJEKzZmYlk0SGF5cWtpUEM4ZHl1
        QWlUNXF5WThwUwoJdVp5TTY5aEs4dEJleFpiWDdiOFdEd29HVElzd3RST0d1SGZJbEpS
        bXBIVXF2YnRUcWs4Qk42cFBwaHlNMlJqb1p4QmgKCXlBdzdEQ0M5Y0tuTkpnamhQTE91
        aFRaUlU0aCtqMXo5WnY2UmdpSU44L21wTkxZV2pNMmtFWEw1eVRKbVhYVnBOcThICgll
        UGx5VUF4TnF6dkFLVFpZQjMrODROOFF4ekF4bVk4eFFBcUpVb1ROWWVZSjZnSWZXcnFM
        VktsRFdDcy9kUE5kc2xndwoJNHN4ci9xS09kcDI1cm5ST1hyK21Kc080Qm4rNkI2Vmhm
        WndWWnpmT2VkN0toZ3dMaGxrSXRYY25UbEN0TUlJSDVEQ0MKCUIrQXdnZ1hJb0FNQ0FR
        SUNFRDM5ajV5cU5WOXZVQ0xzTjAyRWRCOHdEUVlKS29aSWh2Y05BUUVNQlFBd1N6RW5N
        Q1VHCglBMVVFQXd3ZVFYQndiR1VnVTJWamRYSmxJRUp2YjNRZ1VtOXZkQ0JEUVNBdElF
        YzJNUk13RVFZRFZRUUtEQXBCY0hCcwoJWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpB
        ZUZ3MHlNREEzTWpJeE9EQTJORGhhRncwek1EQTNNak14T0RBMk5EaGEKCU1GSXhMakFz
        QmdOVkJBTU1KVlE0TVRFd0xWTkVUMDB4TFZKbFkyOTJaWEo1UW05dmRDMVNaWFpCTFVa
        aFkzUnZjbmt4CglFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlU
        QWxWVE1JSUNJakFOQmdrcWhraUc5dzBCQVFFRgoJQUFPQ0FnOEFNSUlDQ2dLQ0FnRUF5
        aVFHMk1leXZJeFlCQThJdis1bVd0cG83SHJ6ZUdvdU1sSlR1SHFqbmNUYzdDVEYKCUlp
        WlUvT1RMaVRoT2FsdS85L29rQnBqY2MyY0hVdXV6NFlMeUhRYkNFYzllam5MdTFhY2lY
        Q3MvVHZaZmoyTFpScnZsCgk4Tk1xaTBrNUE5RHlUVGxzYnZWRDhXQmdIZ3VUN2MySjh2
        N0tpUnM5MkZUWjZ6OGROK0ZPa1VjM3dTUnRiOFBaQ2QrWgoJREdXblpDYzZyZFlkOFRJ
        WDhNK0dCYzhGeUVEaXFhUmNONmpNNzJkRkRDL0NCQjZxcmFKZDlEQ1VzRTdDVXJ5Zk02
        VWYKCXpqbVNyTGNnSkZYSjhZK3k0N2VjaGcrY2RDTytOQThBYjQzL2E1N0xJaTBtT0JI
        V2FIUytHTkExR3c3WkpqdHdNQXcvCgllbW9heXVNYXB6d1RlRjFNTW1qKzNTa0h2WEdT
        T0JtcU5SYVBoT2hRd1p3bkpsaEhpSkNzaVl1dWJ3N3Bxa0MycytiYgoJekx3MkxNakEy
        UUppQWdDOHJmU3VYb2RUT2EzRkxhK1RmSlJ4TjhoL3p2aEU5Wmk0RDNBeC8xQ2dBS1Qx
        bTNXT3JtQ1AKCURVZDZKOXZ5c3plTWdlZ3RTWldHdU9oL1o1OGFDR1lROTFoMVdpYSt5
        VHdvU1J4c1lYdTR5ZldkT0ZlelpYQjlzMmFqCglWUEFRKzI2eE8xWlRsR29CWXVHcU1y
        TGEvaUV5S1J1UHpzZDVzcC9uU29wdE43dDQwS0h5Uy9KL1luT2RoZTltREdqUwoJMTZE
        aFJBSjRWdHBubDFmeHhubFdNcXpJeUNTMWxtTDdWeWxMdkF1YkpKZTF6MGtaTm9CNWln
        SFB5Q3V2ZW5FUVpSVkQKCUlBcFJ5YlpqSk9Pc1FoVUY3dGFYVUQwQ0F3RUFBYU9DQXJj
        d2dnS3pNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqCglCQmd3Rm9BVVU3ZUV0TEhv
        T0R5Vzc2UldMdm96M1BFUWtPQXdIUVlxxlIwT0JCWUVGRlhYTkNqTWlaMzlYVFlGU3B0
        TgoJTXFNRlNwcWNNQTRHQTFVZER3RUIvd1FFQXdJSGdEQ0NBbEVHQ2lxR1NJYjNZMlFH
        QVE4QkFmOEVnZ0krTVlJQ092K0UKCTZvV2NVSUlCd1RDQ0FiMFdCRTFCVGxBeGdnR3ov
        NFNTdVlaSUREQUtGZ1JDVGtOSW9RSUZBUCtFa3Iya1JBd3dDaFlFCglRazlTUktBQ0JR
        RC9oSnFWb0U4TE1Ba1dCRU5GVUU4Q0FRSC9oSnFoa2xBTk1Bc1dCRU5JU1ZBQ0F3Q0JF
        UCtFbXNHawoJVHd3d0NoWUVRMUJTVDZBQ0JxRCxxSnJxxWtNTU1Bb1dCRU5UUlVPZ0Fn
        VUEvNFNxalpKRUREQUtGZ1JGUTBsRW9BSUYKCUFQK0ZtcEdlVFFzd0NSWUVVMFJQVFFJ
        QkFmK0dpOVh3YVF3d0NoWUVZWFY0YWFFQ0JRRC9ob3ZWOEhBTU1Bb1dCR0YxCgllSENo
        QWdVQS80Ymp2Y1J2Q3pBSkZnUnNiMkp2QVFILy80Ymp3ZHhvRERBS0ZnUnNjRzVvb1FJ
        RkFQK0c4ODNTYUF3dwoJQ2hZRWJxxxBxS0FDQlFEL2g1TzkzR2dNTUFvV0JISnZibWln
        QWdVQS80ZVR3ZHhvRERBS0ZnUnljRzVvb1FJRkFQK0gKCW02WGdNQXd3Q2hZRWMybHdN
        S0VDQlFEL2g1dWw0REVNTUFvV0JITnBjREdoQWdVQS80ZWJwZUF5RERBS0ZnUnphWEF5
        CglvUUlGQVArSG02WGdNd3d3Q2hZRWMybHdNNkVDQlFEL2g1dTF4REFNTUFvV0JITnRZ
        akNoQWdVQS80ZWJ0Y1F4RERBSwoJRmdSemJXSXhvUUlGQVArSG03WEVNZ3d3Q2hZRWMy
        MWlNcUVDQlFEL2g3UFYwbVFNTUFvV0JIWjFhV1NnQWdVQS80VDYKCWlaUlFhVEJuRmdS
        UFFrcFFNVi8vaEtLZHBsUU1NQW9XQkVSSFUxU2dBZ1VBLzRTaXdhUlBEREFLRmdSRVVG
        SlBvUUlGCglBUCtFb3MyS1F3d3dDaFlFUkZORlE2RUNCUUQvaEtyQnBFOE1NQW9XQkVW
        UVVrK2hBZ1VBLzRTcXpZcEREREFLRmdSRgoJVTBWRG9RSUZBREFOQmdrcWhraUc5dzBC
        QVF3RkFBT0NBZ0VBalRUWGVyeE9pMnRWbkNUdXBYR3ZJZW5FQWRLNnZKZ28KCVJaTFNo
        TFo0NGFqNnYySS93V1NKblE1T1VBdGJaNEdiL1RSblZIOUV1dEtZZks0cC9GVlJOZVUv
        c0w2UjRHZEI2TGV0CgkwbWNKWkpSN2xtaUtUQmtMaFBYcnZsaU9qM2hQRlMxWHhCNDBT
        YzU2SlJ6L3REMlpjM1VPSmFNZDZza2YxR3FRd3BUaQoJUzgxVU5zS3JNVmtpc0R5YXYv
        VWxTQmpKM1hyazBCMmN1YVNpVjRaUXhZaSs0ZjRaSXUyZDQ2Y3lBMEJ3YXhBd0UwNFkK
        CU1OdDZVUXl2Y0R4VUxrMU5oUzhUbEtvMVJLczM3UWJxY2k4bUdMOU52M2N4NThjN3B4
        czBNT2VKMVY1UmNtRGxxZWVLCgliTEtTc3BnUTRLNkFHaTJwL3VsckI0YWsxU3lZZGky
        UVlMUUw5TmU3dHhlMXE3c0Zlcmw0RnluOVZGZ2F1aVIreGlvQgoJaXpMcFZWblNPa1RR
        SGgzVEtNbVpEUS9MUDdscUNrcnVCOHZPRGYxV3dITzNOQityVTRXZlBZeERyazJqOWln
        a1pDdzEKCStjVFdWMmozU2lIekk1WUQ5WGRWZmNpZklOTktiNnhhckhuODdpQkh2Rmgv
        M3hKekVqUzZTclI2WEpRTi9RU0FTTXpMCglnVkZRUXFxaHM0N1ZRNmlOS0NjZnZpR21U
        aXFoOE5vWVh1ZXUrME1Rdm5kb3NtcjUzelQzMEFTVWt0TTJnNFBKeDBuawoJUHN1dTVy
        SVVaK3pKeWd6YjVmKzlhSXRHYkNUZEdwajM4YldYR0U3aWRXYTJuQlh6bnBVbDgyd3Fh
        MlpWMHE1OFp2N20KCTBXY09ZWlRxcnVOSTcxRTVXd1duMWFCdzZQRlFOeG0xQlBOcFhS
        MD0KCTwvZGF0YT4KCTxrZXk+T0lEU1RvSW5jbHVkZTwva2V5PgoJPGFycmF5PgoJCTxz
        dHJpbmc+MS4yLjg0MC4xMTM2MzUuMTAwLjEwLjE8L3N0cmluZz4KCTwvYXJyYXk+Cgk8
        a2V5Pk9zQnVpbGRWZXJzaW9uPC9rZXk+Cgk8c3RyaW5nPjIwRTI1Mjwvc3RyaW5nPgoJ
        PGtleT5SS0NlcnRpZmljYXRpb25QdWI8L2tleT4KCTxkYXRhPgoJQkgvL3VxQ1FzNEE0
        VElCdm1ZTWNJQkhiaGo1d0ZURkJaaDU3d2JkL0hTU25aSi9ZeE5YandIZ1FhZzlkandM
        Vk84VjkKCS9DUHk2dDhmbURvbXM1TFpmYVE9Cgk8L2RhdGE+Cgk8a2V5PlNJS1B1Yjwv
        a2V5PgoJPGRhdGE+CglCUHpXTnFSZk1MYmZCNTE0ZXorMWdXNG5vRzZxWGRMa3VySTYz
        Y0NXSlRaall5cHVQVWIvUVZnNmJySUg5M2VUREd3QwoJMFJHTERuYjF3VjlPOHhSWkxM
        ODVSNGdZMVJMeGw0ZnlmYkxLbzUrVHNoQk01bkYyckRlU0hMOG43cEFVOGc9PQoJPC9k
        YXRhPgoJPGtleT5TZWN1cml0eURvbWFpbjwva2V5PgoJPGludGVnZXI+MTwvaW50ZWdl
        cj4KCTxrZXk+U2VyaWFsTnVtYmVyPC9rZXk+Cgk8c3RyaW5nPkY2WDQzOU5IRjk8L3N0
        cmluZz4KCTxrZXk+VUlLUHViPC9rZXk+Cgk8ZGF0YT4KCUJEOHVOckcvaWJvL1RzbVg5
        a3JlVHZvS1N5WW1pZ2Z4UTJzTndTODVSb20rNy90TDBUM2toMlByTVlhWithZTlidWdq
        CglNVWxFTkxFOHBGUTFaTjdmSkprPQoJPC9kYXRhPgoJPGtleT5VbmlxdWVDaGlwSUQ8
        L2tleT4KCTxpbnRlZ2VyPjY4NzE1NDQ5NTU0MTI1MTA8L2ludGVnZXI+Cgk8a2V5PlZh
        bGlkaXR5PC9rZXk+Cgk8aW50ZWdlcj40NDExODY8L2ludGVnZXI+Cgk8a2V5PnNjcnRB
        dHRlc3RhdGlvbjwva2V5PgoJPGludGVnZXI+MDwvaW50ZWdlcj4KPC9kaWN0Pgo8L3Bs
        aXN0Pgo=
        </data>
        <key>RKPropertiesSignature</key>
        <data>
        MEYCIQD6alE5at+gOBxxxxxxYAIVZ6QwFJb7Q5lWdv/s95rSZAIhALu+7s0YPJu8LtN9
        O19Svcb46Vhw2CKF9Txv7GNheg+6
        </data>
</dict>
</plist>

即使hook伪造 MGCopyAnswer获取的的设备 ID,也不能伪造成另一台真机,因为底层 attestation 必须由那台真机的 SE 自签。单纯在软件层面篡改 UniqueChipID 时,服务器端会发现 “你上报的设备 ID 和 attestation 里的(或服务器已有记录里的)设备硬件身份对不上”。

  • 返回激活证书

服务验签没问题后会返回正常的激活两本证书

-----BEGIN CERTIFICATE-----
MIIDQTCCAuagAwIBAgIGAZrdcv7/MAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh
c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j
LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTEyMDEwNTA0NTJaFw0yNjA3MzEx
MTMzNTJaMIGRMUkwRwYDVQQDDEA4YmQzNmIxNWZkNGViODgxZjZlYzNlYzE1MjJh
NjlhNzE2ZGY1YTIxNzAxZmZlNTc1NWUwMmQ0MmVjZWRhYTVjMRowGAYDVQQLDBFC
QUEgQ2VydGlmaWNhdGlvbjETMBEGx1xECgwKQXBwbGUgSW5jLjETMBEGA1UECAwK
Q2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAZRvBj8pkr4rDSb
r4x137hYn/JvpfSXJpuvcTL0XXwhvK5s/TDrhpp07/n3Vo/1GDz3DyDjGbOdIci2
6U4h54GjggFlMIIBYTAMBgNVHRMBAf8EAxxAMA4GA1UdDwEB/wQEAwIE8DCCAT8G
CSqGSIb3Y2QKAQSCATAEggEsMYIBKP+EmqGsUA0wCxYEQ0hJUAIDAIEQ/4SqjZJE
ETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRi
bWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1
MDY4NTU1/4ebydxtFDASFgRzcm5tBApGNlg0MzlOSEY5/4erkdJkIzAhFgR1ZGlk
BBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF/4e7tcJjGzAZFgR3bWFjBBFhYzox
NjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2VpZAQwMDQyRDI3QzU4QTE2OTAwMjIz
MzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VFQzdCMAoGCCqGSM49BAMCA0kAMEYC
IQCkVmdn5P6/mipbxpLOX7j9tTZ0ob4x2GzYsMeNF7mnwAIhAJgrskCv3xq9xR/Q
CaBYl+b8Ju0i2Jk5xxxxxxxxxx=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCxxIKxZIzj0EAwIwUzEnMCUGA1UEAwwe
QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy
MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg
Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3
StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD
VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj
8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG
MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv
W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ
/hgok/34jr93nhS87tOQNdxDS8xxxx=
-----END CERTIFICATE-----

这两本证书就是后面用于计算DeviceCheck Token的,格式解析如下:

3

3

验证证书有效后缓存在本地keychain,后面计算DeviceCheck Token时会有用到。

2.4、修改设备硬件信息激活验证测试

  • 修改全部设备信息
// ========= 0. Hook MGCopyAnswer =========

    var g_mgCopyAnswerHooked = false;
    var mgJsCache = {
        UniqueChipID:    null,
        ChipID:          null,
        BoardId:         null,
        SecurityDomain:  null,
        SerialNumber:    null,
        BuildVersion:    null,
        UniqueDeviceID:  null
    };

    function hookGestatcopyAnswer() {
        try {
            if (g_mgCopyAnswerHooked) {
                console.log(" MGCopyAnswer already hooked");
                return;
            }

            var mgCopyAnswer = Module.findExportByName(null, "MGCopyAnswer");
            if (!mgCopyAnswer) {
                console.error("[-] MGCopyAnswer not found");
                return;
            }

            console.log("[+] MGCopyAnswer =", mgCopyAnswer);

            Interceptor.attach(mgCopyAnswer, {
                onEnter: function (args) {
                    this.keyStr = null;
                    try {
                        var keyObj = new ObjC.Object(args[0]);
                        var ks = keyObj.toString();
                        this.keyStr = ks;
                        console.log("[MGCopyAnswer] key =", ks);
                    } catch (e) {
                        console.log("[MGCopyAnswer] key (raw) =", args[0], "err:", e);
                    }
                },
                onLeave: function (retval) {
                    var keyStr = this.keyStr;
                    var origDesc;

                    try {
                        var origObj = new ObjC.Object(retval);
                        origDesc = origObj.toString();
                    } catch (e) {
                        origDesc = "<raw> " + retval;
                    }

                    console.log("[MGCopyAnswer] orig =>", origDesc);

                    if (!CONFIG.patchMGCopyAnswer || !keyStr) {
                        return;
                    }

                    try {
                        var NSString = ObjC.classes.NSString;
                        var NSNumber = ObjC.classes.NSNumber;
                        var NSUUID   = ObjC.classes.NSUUID;
                        var fakeObj  = null;

                        var fixed    = CONFIG.fixedMG || {};
                        var useFixed = CONFIG.useFixedMGValues === true;

                        switch (keyStr) {
                            case "UniqueChipID":
                            case "Uniquechipid": {
                                var v;
                                if (useFixed && fixed.UniqueChipID !== undefined) {
                                    v = Number(fixed.UniqueChipID);
                                } else {
                                    if (mgJsCache.UniqueChipID === null) {
                                        mgJsCache.UniqueChipID = (Math.floor(Math.random() * 0xFFFFFFFF) >>> 0);
                                    }
                                    v = mgJsCache.UniqueChipID;
                                }
                                fakeObj = NSNumber.numberWithLongLong_(v);
                                fakeObj.retain();
                                console.log(" override UniqueChipID =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "ChipID":
                            case "Chipid": {
                                var cVal;
                                if (useFixed && fixed.ChipID !== undefined) {
                                    cVal = Number(fixed.ChipID);
                                } else {
                                    if (mgJsCache.ChipID === null) {
                                        mgJsCache.ChipID = (0x2000 + Math.floor(Math.random() * 0x1000)) >>> 0;
                                    }
                                    cVal = mgJsCache.ChipID;
                                }
                                fakeObj = NSNumber.numberWithUnsignedInt_(cVal >>> 0);
                                fakeObj.retain();
                                console.log(" override ChipID =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "BoardId":
                            case "BoardID": {
                                var bVal;
                                if (useFixed && fixed.BoardId !== undefined) {
                                    bVal = Number(fixed.BoardId);
                                } else {
                                    if (mgJsCache.BoardId === null) {
                                        mgJsCache.BoardId = 10 + Math.floor(Math.random() * 20);
                                    }
                                    bVal = mgJsCache.BoardId;
                                }
                                fakeObj = NSNumber.numberWithUnsignedInt_(bVal >>> 0);
                                fakeObj.retain();
                                console.log(" override BoardId =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "SecurityDomain":
                            case "Securitydomain": {
                                var sVal;
                                if (useFixed && fixed.SecurityDomain !== undefined) {
                                    sVal = Number(fixed.SecurityDomain);
                                } else {
                                    if (mgJsCache.SecurityDomain === null) {
                                        mgJsCache.SecurityDomain = 1;
                                    }
                                    sVal = mgJsCache.SecurityDomain;
                                }
                                fakeObj = NSNumber.numberWithUnsignedInt_(sVal >>> 0);
                                fakeObj.retain();
                                console.log(" override SecurityDomain =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "SerialNumber":
                            case "Serialnumber": {
                                var sn;
                                if (useFixed && fixed.SerialNumber) {
                                    sn = fixed.SerialNumber.toString();
                                } else {
                                    if (mgJsCache.SerialNumber === null) {
                                        mgJsCache.SerialNumber = "F" + randHex(11);
                                    }
                                    sn = mgJsCache.SerialNumber;
                                }
                                var snCStr = Memory.allocUtf8String(sn);
                                fakeObj = NSString.stringWithUTF8String_(snCStr);
                                fakeObj.retain();
                                console.log(" override SerialNumber =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "BuildVersion":
                            case "Buildversion": {
                                var bv;
                                if (useFixed && fixed.BuildVersion) {
                                    bv = fixed.BuildVersion.toString();
                                } else {
                                    if (mgJsCache.BuildVersion === null) {
                                        mgJsCache.BuildVersion = "20" + randHex(4);
                                    }
                                    bv = mgJsCache.BuildVersion;
                                }
                                var bvCStr = Memory.allocUtf8String(bv);
                                fakeObj = NSString.stringWithUTF8String_(bvCStr);
                                fakeObj.retain();
                                console.log(" override BuildVersion =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            case "UniqueDeviceID": {
                                var udid;
                                if (useFixed && fixed.UniqueDeviceID) {
                                    udid = fixed.UniqueDeviceID.toString();
                                } else {
                                    if (mgJsCache.UniqueDeviceID === null) {
                                        var uuidObj = NSUUID.UUID();
                                        mgJsCache.UniqueDeviceID = uuidObj.UUIDString().toString();
                                    }
                                    udid = mgJsCache.UniqueDeviceID;
                                }
                                var udidCStr = Memory.allocUtf8String(udid);
                                fakeObj = NSString.stringWithUTF8String_(udidCStr);
                                fakeObj.retain();
                                console.log(" override UniqueDeviceID =>", fakeObj.toString());
                                retval.replace(fakeObj.handle);
                                break;
                            }

                            default:
                                break;
                        }
                    } catch (e) {
                        console.log("[-] MGCopyAnswer patch error:", e);
                    }
                }
            });

            g_mgCopyAnswerHooked = true;
            console.log("[+] Hooked MGCopyAnswer (patch =", CONFIG.patchMGCopyAnswer,
                        ", useFixed =", CONFIG.useFixedMGValues, ")");
        } catch (e) {
            console.error("[-] hookGestatcopyAnswer failed:", e.stack || e);
        }
    }

全部更改设备信息服务器会返回错误

-----BEGIN ERROR-----
93:UCRT SCRT SEAL from tabasco is null.
-----END ERROR-----

站在苹果服务器的角度,它收到这些东西之后,大概会做这样几步检测:

1. 验证 SE attestation(由 Apple 根证书/中间证书链签的):
   - 检查证书链是否正确、未过期、签名有效
   - 从 attestation blob 里取出:
       * 这个 key 所在的“安全硬件身份”:比如 Secure Enclave 的某个 ID
       * 跟这一块硬件绑定的标识:UniqueChipID/ChipID/SecurityDomain/...(以某种形式存在)

2. 验证 RKPropertiesSignature:
   - 用 attestation 里证明的那把 refKey 的 “公钥” 去验签 RKPropertiesSignature
   - 确认:RKProperties 确实是 **同一个 SE 里那把 refKey** 签出来的,
           而不是你在用户态自己随便弄的 key。

3. 一致性检查:
   - 从 attestation / 后端数据库里得到的“真实硬件 ID” 记为 H = {U_real, ChipID_real, ...}
   - 从 RKProperties 里解析出你上报的 ID 记为 S = {U_reported, ChipID_reported, ...}

   然后做类似:
       if U_reported != U_real or ChipID_reported != ChipID_real ...
           => 认为这是“篡改 / 不一致”,直接拒绝,后面的 UCRT/SCRT/SEAL 都不下发
  • 修改部分真实设备信息

其它字段随机、只保留UniqueChipID、ChipID不改,正常返回证书;

  • A手机信息替换为B手机

将A手机的UniqueChipID、ChipID替换到B手机,返回如下:

-----BEGIN ERROR-----
29:ECC signature verification failed: signature incorrect.
-----END ERROR-----
  • 整体流程与修改信息验证流程

    4

    4

  • 修改设备信息验证流程

    5

    5

  • 结论

从上面验证情况来看,硬ID与SE 里的证书是绑定的。SE 里的“根密钥”和“设备证书”是在出厂生产 / 校准阶段由 Apple 写入硬件安全区的,属于“出厂级”的东西。

我改的 MobileGestalt 层(UniqueChipID/ChipID)只是“软件视角的 ID”,并不会改变 SE 里真实的密钥和它生成的签名,所以软改实现激活大概率是不可行的。

三、DeviceCheck 架构与正向流程

DeviceCheck 的工作流程涉及三方交互:客户端 App、系统守护进程 devicecheckd 以及 Apple 服务器。整体流程如下:

6

6

3.1 核心组件

  • 客户端 (App):通过 DCDevice 类发起 Token 生成请求。

  • 守护进程 (devicecheckd):iOS 系统内置的守护进程,负责与硬件安全模块(Secure Enclave)通信,执行核心加密操作。

  • Apple Server:接收 Token,验证其合法性,并根据 Token 更新或查询设备的 2-bit 状态。

3.2 bit 状态存储机制

DeviceCheck 允许开发者为每个设备-App 组合存储两个二进制位(00, 01, 10, 11)。

  • 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_bitsquery_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 timestamp
Returning cached certificates
-[MAAssetQuery getResultsFromMessage:]: Got the query meta data reply for: com.apple.MobileAsset.DeviceCheck, response: 0
Falling back to locally cached key... Asset fetch failed: Error Domain=com.apple.twobit.fetcherror Code=-3100
  • 搜索“Generating certificate...”定位到获取公钥的方法,这个密钥后面加密时会用到。
void __fastcall __37__DCCryptoProxyImpl__fetchPublicKey___block_invoke(__int64 a1, void *a2, void *a3)
{
  id v5; // x19
  id v6; // x20
  void *v7; // x23
  __int64 v8; // x0
  __int64 v9; // x0
  NSObject *v10; // x22
  _BOOL4 v11; // w0
  __int64 v12; // x22
  __int64 v13; // x0
  void *v14; // x21
  int v15; // [xsp+0h] [xbp-50h] BYREF
  id v16; // [xsp+4h] [xbp-4Ch]

  v5 = objc_retain(a2);
  v6 = objc_retain(a3);
  v7 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v5, "publicKey"));
  objc_release(v7);
  v9 = _DCLogSystem(v8);
  v10 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v9);
  v11 = os_log_type_enabled_1518(v10, OS_LOG_TYPE_DEFAULT);
  if ( v7 )
  {
    if ( v11 )
    {
      LOWORD(v15) = 0;
      _os_log_impl_1398(&dword_446A2E000, v10, OS_LOG_TYPE_DEFAULT, "Fetched remote public key...", (uint8_t *)&v15, 2u);
    }
    objc_release(v10);
    v12 = *(_QWORD *)(a1 + 32);
    v13 = objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v5, "publicKey"));
  }
  else
  {
    if ( v11 )
    {
      v15 = 138412290;
      v16 = v6;
      _os_log_impl_1398(
        &dword_446A2E000,
        v10,
        OS_LOG_TYPE_DEFAULT,
        "Falling back to locally cached key... Asset fetch failed: %@",
        (uint8_t *)&v15,
        0xCu);
    }
    objc_release(v10);
    v12 = *(_QWORD *)(a1 + 32);
    v13 = objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSData, "dataWithBytes:length:", &fallback_server_pubkey, 65));
  }
  v14 = (void *)v13;
  (*(void (__fastcall **)(__int64, __int64))(v12 + 16))(v12, v13);
  objc_release(v14);
  objc_release(v6);
  objc_release(v5);
}

尝试用 DCAssetFetcher/MobileAsset 拉最新的远程公钥,如果成功就用它;失败就用代码中默认密钥fallback_server_pubkey 常量,然后把选出来的公钥交回后续逻辑(DCCertificateGenerator 那边去做 ECDH)。

pub key
0000000A9700B010              04 50 D9 34  FA 67 BC F6 F2 DF BF 96
0000000A9700B020  62 9E 0A 72 38 E9 20 5D  75 F2 8C FC D8 4F 35 A6 
0000000A9700B030  59 2B BE 05 8A 9C 0F 8E  DB CA 2A CB 67 EF B7 74 
0000000A9700B040  97 1C A4 5F 7D 85 6A 69  4F B1 B9 C4 0B 94 FB 2E 
0000000A9700B050  7A 5A 94 98 B0
  • 准备读取本地缓存的激活证书

**这张证书属于哪一类身份 & 存在哪个抽屉**
KeychainLabel = "2bit-identity"
KeychainAccessGroup = "2bit-identity"
//生成配置信息
id +[DCCryptoUtilities identityCertificateOptions]()
{
  void *v0; // x19
  __int64 v1; // x0
  NSObject *v2; // x20
  void *v3; // x22
  void *v4; // x23
  void *v5; // x24
  void *v6; // x21
  void *v7; // x22
  __CFString *v9; // [xsp+0h] [xbp-A0h] BYREF
  _QWORD v10[6]; // [xsp+8h] [xbp-98h] BYREF
  _QWORD v11[6]; // [xsp+38h] [xbp-68h] BYREF
  __int64 vars8; // [xsp+A8h] [xbp+8h]

  v0 = objc_msgSend(&OBJC_CLASS___DCCryptoUtilities, "generateTTL");
  v1 = _DCLogSystem(v0);
  v2 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v1);
  if ( os_log_type_enabled_1518(v2, OS_LOG_TYPE_DEBUG) )
    +[DCCryptoUtilities identityCertificateOptions].cold.1(v0, v2);
  objc_release(v2);
  v10[0] = CFSTR("Validity");
  v3 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSNumber, "numberWithUnsignedInt:", v0));
  v11[0] = v3;
  v11[1] = &__kCFBooleanFalse;
  v10[1] = CFSTR("scrtAttestation");
  v10[2] = CFSTR("KeychainLabel");
  v11[2] = CFSTR("2bit-identity");
  v11[3] = CFSTR("2bit-identity");
  v10[3] = CFSTR("KeychainAccessGroup");
  v10[4] = CFSTR("IgnoreExistingKeychainItems");
  v11[4] = &__kCFBooleanFalse;
  v10[5] = CFSTR("OIDSToInclude");
  v9 = CFSTR("1.2.840.113635.100.10.1");
  v4 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSArray, "arrayWithObjects:count:", &v9, 1));
  v11[5] = v4;
  v5 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSDictionary, "dictionaryWithObjects:forKeys:count:", v11, v10, 6));
  v6 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionaryWithDictionary:", v5));
  objc_release(v5);
  objc_release(v4);
  objc_release(v3);
  if ( (unsigned int)os_variant_allows_internal_security_policies_55(0) )
  {
    v7 = objc_msgSend(
           objc_alloc((Class)&OBJC_CLASS___NSUserDefaults),
           "initWithSuiteName:",
           CFSTR("com.apple.DeviceCheck"));
    if ( (unsigned int)objc_msgSend(v7, "boolForKey:", CFSTR("DCIgnoreExistingKeychainItems")) )
      objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("IgnoreExistingKeychainItems"));
    objc_release(v7);
  }
  if ( (DeviceIdentityUCRTAttestationSupported_1() & 1) == 0 )
    objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("scrtAttestation"));
  objc_msgSend(v6, "setObject:forKeyedSubscript:", &__kCFBooleanTrue, CFSTR("ReturnReferenceDate"));
  if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
    __break(0xC471u);
  return objc_autoreleaseReturnValue(v6);
}
//开始读取
void __fastcall __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke(__int64 a1)
{
  __int64 v2; // x5
  __int64 v3; // x6
  __int64 v4; // x7
  NSObject *v5; // x20
  dispatch_queue_global_t global_queue_364; // x0
  __int64 v7; // x19
  __int64 v8; // x5
  __int64 v9; // x6
  __int64 v10; // x7
  __SecTask *v11; // x0
  __int64 v12; // x5
  __int64 v13; // x6
  __int64 v14; // x7
  __SecTask *v15; // x23
  __int64 v16; // x5
  __int64 v17; // x6
  __int64 v18; // x7
  __int64 v19; // x0
  void *v20; // x21
  unsigned __int8 v21; // w22
  void *v22; // x0
  id *v23; // x28
  void *v24; // x21
  __int64 v25; // x0
  void *v26; // x22
  void *v27; // x21
  void *v28; // x22
  __int64 v29; // x0
  void *v30; // x22
  unsigned __int8 v31; // w25
  id MobileActivationError_0; // x0
  __int64 v33; // x0
  id v34; // x0
  id v35; // x21
  CFDictionaryRef v36; // x25
  CFDataRef v37; // x28
  void *v38; // x22
  void *v39; // x27
  __int64 v40; // x8
  void *v41; // x26
  void *v42; // x9
  __int64 *v43; // x8
  const void *v44; // x0
  __int64 *v45; // x8
  const void *v46; // x0
  __int64 *v47; // x8
  const void *v48; // x0
  __int64 *v49; // x8
  const void *v50; // x0
  __int64 *v51; // x8
  const void *v52; // x0
  id v53; // x26
  id *v54; // x19
  id v55; // x0
  CFErrorRef v56; // x21
  __int64 v57; // x5
  __int64 v58; // x6
  __int64 v59; // x7
  id v60; // x0
  __int64 v61; // x0
  __int64 v62; // x8
  void *v63; // x9
  id v64; // x0
  bool v65; // w25
  __int64 v66; // x5
  __int64 v67; // x6
  __int64 v68; // x7
  char v69; // w26
  __int64 v70; // x0
  __int64 v71; // x5
  __int64 v72; // x6
  __int64 v73; // x7
  __int64 v74; // x0
  __int64 v75; // x5
  __int64 v76; // x6
  __int64 v77; // x7
  __int64 v78; // x21
  __int64 v79; // x0
  __int64 v80; // x5
  __int64 v81; // x6
  __int64 v82; // x7
  const __CFData *v83; // x21
  SecCertificateRef v84; // x0
  __int64 v85; // x5
  __int64 v86; // x6
  __int64 v87; // x7
  const __CFData *v88; // x21
  SecCertificateRef v89; // x0
  __int64 v90; // x5
  __int64 v91; // x6
  __int64 v92; // x7
  id v93; // x0
  CFErrorRef v94; // x19
  __int64 v95; // x5
  __int64 v96; // x6
  __int64 v97; // x7
  id v98; // x0
  __int64 v99; // x0
  __int64 v100; // x8
  void *v101; // x9
  __int64 v102; // x19
  __int64 v103; // x5
  __int64 v104; // x6
  __int64 v105; // x7
  __int64 v106; // x19
  void *v107; // x3
  id *v108; // x19
  void *v109; // t1
  id v110; // x0
  double v111; // d8
  __int64 v112; // x5
  __int64 v113; // x6
  __int64 v114; // x7
  __int64 v115; // x19
  void *v116; // x3
  id *v117; // x19
  void *v118; // t1
  id v119; // x0
  void *v120; // x25
  unsigned __int8 v121; // w26
  void *v122; // x21
  void *v123; // x22
  void *v124; // x25
  void *v125; // x26
  void *v126; // x27
  __int64 v127; // x5
  __int64 v128; // x6
  __int64 v129; // x7
  id v130; // x0
  int v131; // w21
  void *v132; // x3
  id v133; // x0
  id v134; // x0
  id v135; // x0
  id v136; // x0
  __int64 v137; // x5
  __int64 v138; // x6
  __int64 v139; // x7
  __int64 v140; // x5
  __int64 v141; // x6
  __int64 v142; // x7
  id v143; // x0
  void *v144; // x9
  __int64 v145; // x5
  __int64 v146; // x6
  __int64 v147; // x7
  __int64 v148; // x5
  __int64 v149; // x6
  __int64 v150; // x7
  CFDataRef v151; // x21
  __int64 v152; // x5
  __int64 v153; // x6
  __int64 v154; // x7
  __int64 v155; // x0
  __int64 v156; // x21
  char v157; // w22
  __int64 v158; // x5
  __int64 v159; // x6
  __int64 v160; // x7
  id v161; // x0
  void *v162; // x22
  __int64 v163; // x0
  void *v164; // x21
  __int64 v165; // x22
  void *v166; // x21
  __int64 v167; // x0
  void *v168; // x19
  void *v169; // x22
  __int64 v170; // x5
  __int64 v171; // x6
  __int64 v172; // x7
  id v173; // x0
  __int64 v174; // x0
  __int64 v175; // x0
  void *v176; // x9
  __int64 v177; // x5
  __int64 v178; // x6
  __int64 v179; // x7
  void *v180; // x0
  __int64 v181; // x0
  __int64 v182; // x0
  void *v183; // x9
  __int64 v184; // x5
  __int64 v185; // x6
  __int64 v186; // x7
  void *v187; // x0
  __int64 v188; // x0
  __int64 v189; // x0
  void *v190; // x9
  void *v191; // x0
  id v192; // x0
  void *v193; // x0
  void *v194; // x9
  id v195; // x0
  id v196; // x0
  id v197; // x0
  id v198; // x0
  id v199; // x0
  void *v200; // x21
  __int64 v201; // x0
  void *v202; // x22
  __int64 v203; // x5
  __int64 v204; // x6
  __int64 v205; // x7
  id v206; // x0
  void *v207; // x21
  __int64 v208; // x0
  void *v209; // x22
  __int64 v210; // x0
  __CFString *v211; // x0
  void *v212; // x21
  __int64 v213; // x0
  void *v214; // x22
  void *v215; // x21
  unsigned int v216; // w19
  void *v217; // x22
  __int64 v218; // x5
  __int64 v219; // x6
  __int64 v220; // x7
  id v221; // x0
  void *v222; // x22
  __int64 v223; // x0
  void *v224; // x25
  __int64 v225; // x5
  __int64 v226; // x6
  __int64 v227; // x7
  id v228; // x0
  void *v229; // x25
  __int64 v230; // x0
  void *v231; // x26
  __int64 v232; // x5
  __int64 v233; // x6
  __int64 v234; // x7
  id v235; // x0
  void *v236; // x22
  CFTypeID v237; // x25
  CFTypeID TypeID_4; // x26
  void *v239; // x22
  __int64 v240; // x0
  void *v241; // x25
  void *v242; // x21
  void *v243; // x22
  __int64 v244; // x0
  void *v245; // x25
  void *v246; // x21
  void *v247; // x25
  __int64 v248; // x0
  void *v249; // x26
  void *v250; // x21
  void *v251; // x21
  __int64 v252; // x0
  void *v253; // x26
  void *v254; // x21
  __int64 v255; // x0
  void *v256; // x26
  __int64 v257; // x5
  __int64 v258; // x6
  __int64 v259; // x7
  void *v260; // x25
  __int64 v261; // x0
  void *v262; // x26
  void *v263; // x21
  unsigned int v264; // w27
  void *v265; // x25
  __int64 v266; // x0
  void *v267; // x26
  void *v268; // x21
  unsigned int v269; // w22
  void *v270; // x25
  __int64 v271; // x0
  void *v272; // x26
  void *v273; // x19
  __int64 v274; // x26
  __int64 v275; // x27
  __int64 v276; // x22
  __int64 v277; // x19
  __int64 v278; // x0
  id v279; // x0
  void *v280; // x21
  __int64 v281; // x0
  __int64 v282; // x5
  __int64 v283; // x6
  __int64 v284; // x7
  __int64 v285; // x5
  __int64 v286; // x6
  __int64 v287; // x7
  id v288; // x0
  id v289; // x0
  id v290; // x0
  id v291; // x0
  __int64 v292; // x0
  __int64 v293; // x8
  void *v294; // x9
  __int64 v295; // x0
  __int64 v296; // x25
  __int64 v297; // x21
  int valid; // w28
  __int64 v299; // x0
  __int64 v300; // x21
  int v301; // w28
  __int64 v302; // x21
  char v303; // w28
  id v304; // x0
  __int64 v305; // x0
  __int64 v306; // x8
  void *v307; // x9
  id v308; // x0
  void *v309; // x8
  __int64 *v310; // x8
  const void *v311; // x0
  __int64 *v312; // x8
  const void *v313; // x0
  __int64 *v314; // x8
  const void *v315; // x0
  __int64 v316; // x8
  void *v317; // x9
  double v318; // d0
  void *v319; // x0
  __int64 v320; // x0
  char v321; // w19
  void *v322; // x8
  __int64 v323; // x0
  __int64 v324; // x21
  __int64 v325; // x21
  double v326; // d8
  double v327; // d9
  double v328; // d0
  int v329; // w25
  int v330; // w8
  id v331; // x0
  __int64 v332; // x0
  const void *v333; // x0
  __SecKey *v334; // x25
  __int64 v335; // x2
  __int64 v336; // x26
  __int64 v337; // x5
  __int64 v338; // x6
  __int64 v339; // x7
  __SecKey *v340; // x0
  __int64 v341; // x5
  __int64 v342; // x6
  __int64 v343; // x7
  __int64 v344; // x5
  __int64 v345; // x6
  __int64 v346; // x7
  CFDictionaryRef v347; // x0
  __int64 v348; // x5
  __int64 v349; // x6
  __int64 v350; // x7
  __int64 v351; // x5
  __int64 v352; // x6
  __int64 v353; // x7
  void *v354; // x26
  dispatch_queue_global_t v355; // x0
  __CFString *v356; // x0
  __int64 v357; // x8
  id v358; // x0
  id v359; // x0
  id v360; // x0
  id v361; // x0
  __int64 v362; // x9
  void *v363; // x8
  const void *v364; // x0
  CFTypeRef v365; // x0
  id v366; // x0
  void *v367; // x0
  void *v368; // x0
  void *v369; // x0
  __int64 v370; // x19
  void *v371; // x0
  id v372; // x0
  __int64 v373; // x8
  id v374; // x19
  id v375; // x0
  id v376; // x0
  id v377; // x0
  id v378; // x0
  id v379; // x0
  id v380; // x0
  __int64 v381; // x9
  __int64 *v382; // x8
  __int64 *v383; // x9
  char v384; // [xsp+0h] [xbp-680h]
  void *v385; // [xsp+18h] [xbp-668h]
  id v386; // [xsp+20h] [xbp-660h]
  void *v387; // [xsp+28h] [xbp-658h]
  id v388; // [xsp+30h] [xbp-650h]
  __int64 v389; // [xsp+38h] [xbp-648h]
  void *v390; // [xsp+38h] [xbp-648h]
  int v391; // [xsp+40h] [xbp-640h]
  unsigned int v392; // [xsp+40h] [xbp-640h]
  __int64 v393; // [xsp+40h] [xbp-640h]
  void *v394; // [xsp+40h] [xbp-640h]
  _BOOL4 v395; // [xsp+48h] [xbp-638h]
  void *v396; // [xsp+48h] [xbp-638h]
  _BOOL4 v397; // [xsp+50h] [xbp-630h]
  void *v398; // [xsp+50h] [xbp-630h]
  _BOOL4 v399; // [xsp+58h] [xbp-628h]
  id v400; // [xsp+58h] [xbp-628h]
  void *queue; // [xsp+60h] [xbp-620h]
  _BOOL4 queuea; // [xsp+60h] [xbp-620h]
  unsigned int queueb; // [xsp+60h] [xbp-620h]
  NSObject *queuec; // [xsp+60h] [xbp-620h]
  id queued; // [xsp+60h] [xbp-620h]
  id v406; // [xsp+68h] [xbp-618h]
  void *v407; // [xsp+70h] [xbp-610h]
  id v408; // [xsp+78h] [xbp-608h]
  void *v409; // [xsp+80h] [xbp-600h]
  id v410; // [xsp+88h] [xbp-5F8h]
  id v411; // [xsp+90h] [xbp-5F0h]
  void *v412; // [xsp+98h] [xbp-5E8h]
  id v413; // [xsp+A0h] [xbp-5E0h]
  CFDataRef v414; // [xsp+A8h] [xbp-5D8h]
  unsigned int v415; // [xsp+A8h] [xbp-5D8h]
  unsigned int v416; // [xsp+A8h] [xbp-5D8h]
  id v417; // [xsp+B0h] [xbp-5D0h]
  id v418; // [xsp+B8h] [xbp-5C8h]
  id v419; // [xsp+C0h] [xbp-5C0h]
  unsigned __int8 v420; // [xsp+C0h] [xbp-5C0h]
  void *v421; // [xsp+C8h] [xbp-5B8h]
  __CFString *v422; // [xsp+D0h] [xbp-5B0h]
  void *cf; // [xsp+D8h] [xbp-5A8h]
  void *cfa; // [xsp+D8h] [xbp-5A8h]
  id v425; // [xsp+E0h] [xbp-5A0h]
  _QWORD block[4]; // [xsp+E8h] [xbp-598h] BYREF
  _QWORD v427[4]; // [xsp+108h] [xbp-578h] BYREF
  _QWORD v428[4]; // [xsp+128h] [xbp-558h] BYREF
  id v429; // [xsp+148h] [xbp-538h] BYREF
  __CFString *v430; // [xsp+150h] [xbp-530h]
  id v431; // [xsp+158h] [xbp-528h]
  id v432; // [xsp+160h] [xbp-520h]
  id v433; // [xsp+168h] [xbp-518h]
  id v434; // [xsp+170h] [xbp-510h]
  id v435; // [xsp+178h] [xbp-508h]
  id v436; // [xsp+180h] [xbp-500h]
  id v437; // [xsp+188h] [xbp-4F8h]
  id v438; // [xsp+190h] [xbp-4F0h]
  id v439; // [xsp+198h] [xbp-4E8h]
  id v440; // [xsp+1A0h] [xbp-4E0h]
  id v441; // [xsp+1A8h] [xbp-4D8h]
  NSObject *v442; // [xsp+1B0h] [xbp-4D0h]
  id v443; // [xsp+1B8h] [xbp-4C8h]
  __int64 v444; // [xsp+1C0h] [xbp-4C0h]
  _QWORD *v445; // [xsp+1C8h] [xbp-4B8h]
  __int64 *v446; // [xsp+1D0h] [xbp-4B0h]
  __int64 *v447; // [xsp+1D8h] [xbp-4A8h]
  __int64 *v448; // [xsp+1E0h] [xbp-4A0h]
  __int64 *v449; // [xsp+1E8h] [xbp-498h]
  __int64 *v450; // [xsp+1F0h] [xbp-490h]
  __int64 *v451; // [xsp+1F8h] [xbp-488h]
  __int64 *v452; // [xsp+200h] [xbp-480h]
  __int64 *v453; // [xsp+208h] [xbp-478h]
  __int64 *v454; // [xsp+210h] [xbp-470h]
  __int64 *v455; // [xsp+218h] [xbp-468h]
  __int64 *v456; // [xsp+220h] [xbp-460h]
  __int64 *v457; // [xsp+228h] [xbp-458h]
  __int64 *v458; // [xsp+230h] [xbp-450h]
  __int64 *v459; // [xsp+238h] [xbp-448h]
  __int64 *v460; // [xsp+240h] [xbp-440h]
  __int64 *v461; // [xsp+248h] [xbp-438h]
  bool v462; // [xsp+250h] [xbp-430h]
  id v463; // [xsp+258h] [xbp-428h] BYREF
  id v464; // [xsp+260h] [xbp-420h]
  id v465; // [xsp+268h] [xbp-418h] BYREF
  id v466; // [xsp+270h] [xbp-410h] BYREF
  id v467; // [xsp+278h] [xbp-408h] BYREF
  id obj; // [xsp+280h] [xbp-400h] BYREF
  id v469; // [xsp+288h] [xbp-3F8h] BYREF
  id v470; // [xsp+290h] [xbp-3F0h] BYREF
  id v471; // [xsp+298h] [xbp-3E8h] BYREF
  __int64 v472; // [xsp+2A0h] [xbp-3E0h] BYREF
  double *v473; // [xsp+2A8h] [xbp-3D8h]
  __int64 v474; // [xsp+2B0h] [xbp-3D0h]
  __int64 v475; // [xsp+2B8h] [xbp-3C8h]
  __int64 v476; // [xsp+2C0h] [xbp-3C0h] BYREF
  __int64 *v477; // [xsp+2C8h] [xbp-3B8h]
  __int64 v478; // [xsp+2D0h] [xbp-3B0h]
  int v479; // [xsp+2D8h] [xbp-3A8h]
  int v480; // [xsp+2E4h] [xbp-39Ch] BYREF
  double v481; // [xsp+2E8h] [xbp-398h] BYREF
  __int64 v482; // [xsp+2F0h] [xbp-390h] BYREF
  double *v483; // [xsp+2F8h] [xbp-388h]
  __int64 v484; // [xsp+300h] [xbp-380h]
  __int64 v485; // [xsp+308h] [xbp-378h]
  __int64 v486; // [xsp+310h] [xbp-370h] BYREF
  __int64 *v487; // [xsp+318h] [xbp-368h]
  __int64 v488; // [xsp+320h] [xbp-360h]
  __int64 (__fastcall *v489)(); // [xsp+328h] [xbp-358h]
  __int64 (__fastcall *v490)(); // [xsp+330h] [xbp-350h]
  id v491; // [xsp+338h] [xbp-348h]
  __int64 v492; // [xsp+340h] [xbp-340h] BYREF
  __int64 *v493; // [xsp+348h] [xbp-338h]
  __int64 v494; // [xsp+350h] [xbp-330h]
  __int64 (__fastcall *v495)(); // [xsp+358h] [xbp-328h]
  __int64 (__fastcall *v496)(); // [xsp+360h] [xbp-320h]
  id v497; // [xsp+368h] [xbp-318h]
  __int64 v498; // [xsp+370h] [xbp-310h] BYREF
  __int64 *v499; // [xsp+378h] [xbp-308h]
  __int64 v500; // [xsp+380h] [xbp-300h]
  __int64 (__fastcall *v501)(); // [xsp+388h] [xbp-2F8h]
  __int64 (__fastcall *v502)(); // [xsp+390h] [xbp-2F0h]
  id v503; // [xsp+398h] [xbp-2E8h]
  __int64 v504; // [xsp+3A0h] [xbp-2E0h] BYREF
  __int64 *v505; // [xsp+3A8h] [xbp-2D8h]
  __int64 v506; // [xsp+3B0h] [xbp-2D0h]
  __int64 (__fastcall *v507)(); // [xsp+3B8h] [xbp-2C8h]
  __int64 (__fastcall *v508)(); // [xsp+3C0h] [xbp-2C0h]
  id v509; // [xsp+3C8h] [xbp-2B8h]
  __int64 v510; // [xsp+3D0h] [xbp-2B0h] BYREF
  __int64 *v511; // [xsp+3D8h] [xbp-2A8h]
  __int64 v512; // [xsp+3E0h] [xbp-2A0h]
  __int64 (__fastcall *v513)(); // [xsp+3E8h] [xbp-298h]
  __int64 (__fastcall *v514)(); // [xsp+3F0h] [xbp-290h]
  id v515; // [xsp+3F8h] [xbp-288h]
  __int64 v516; // [xsp+400h] [xbp-280h] BYREF
  __int64 *v517; // [xsp+408h] [xbp-278h]
  __int64 v518; // [xsp+410h] [xbp-270h]
  __int64 (__fastcall *v519)(); // [xsp+418h] [xbp-268h]
  __int64 (__fastcall *v520)(); // [xsp+420h] [xbp-260h]
  id v521; // [xsp+428h] [xbp-258h]
  int v522; // [xsp+434h] [xbp-24Ch] BYREF
  __int64 v523; // [xsp+438h] [xbp-248h] BYREF
  __int64 *v524; // [xsp+440h] [xbp-240h]
  __int64 v525; // [xsp+448h] [xbp-238h]
  __int64 v526; // [xsp+450h] [xbp-230h]
  __int64 v527; // [xsp+458h] [xbp-228h] BYREF
  __int64 *v528; // [xsp+460h] [xbp-220h]
  __int64 v529; // [xsp+468h] [xbp-218h]
  __int64 v530; // [xsp+470h] [xbp-210h]
  CFErrorRef error; // [xsp+478h] [xbp-208h] BYREF
  __int64 v532; // [xsp+480h] [xbp-200h] BYREF
  __int64 *v533; // [xsp+488h] [xbp-1F8h]
  __int64 v534; // [xsp+490h] [xbp-1F0h]
  __int64 v535; // [xsp+498h] [xbp-1E8h]
  __int64 v536; // [xsp+4A0h] [xbp-1E0h] BYREF
  __int64 *v537; // [xsp+4A8h] [xbp-1D8h]
  __int64 v538; // [xsp+4B0h] [xbp-1D0h]
  __int64 v539; // [xsp+4B8h] [xbp-1C8h]
  __int64 v540; // [xsp+4C0h] [xbp-1C0h] BYREF
  __int64 *v541; // [xsp+4C8h] [xbp-1B8h]
  __int64 v542; // [xsp+4D0h] [xbp-1B0h]
  __int64 v543; // [xsp+4D8h] [xbp-1A8h]
  __int64 v544; // [xsp+4E0h] [xbp-1A0h] BYREF
  __int64 *v545; // [xsp+4E8h] [xbp-198h]
  __int64 v546; // [xsp+4F0h] [xbp-190h]
  __int64 v547; // [xsp+4F8h] [xbp-188h]
  __int64 v548; // [xsp+500h] [xbp-180h] BYREF
  id *v549; // [xsp+508h] [xbp-178h]
  __int64 v550; // [xsp+510h] [xbp-170h]
  __int64 (__fastcall *v551)(); // [xsp+518h] [xbp-168h]
  __int64 (__fastcall *v552)(); // [xsp+520h] [xbp-160h]
  id v553; // [xsp+528h] [xbp-158h]
  _QWORD v554[5]; // [xsp+530h] [xbp-150h] BYREF
  id v555; // [xsp+558h] [xbp-128h]
  uint8_t buf[4]; // [xsp+560h] [xbp-120h] BYREF
  void *v557; // [xsp+564h] [xbp-11Ch]
  __int16 v558; // [xsp+56Ch] [xbp-114h]
  id v559; // [xsp+56Eh] [xbp-112h]
  __int16 v560; // [xsp+576h] [xbp-10Ah]
  id v561; // [xsp+578h] [xbp-108h]
  __int16 v562; // [xsp+580h] [xbp-100h]
  void *v563; // [xsp+582h] [xbp-FEh]
  __int16 v564; // [xsp+58Ah] [xbp-F6h]
  id v565; // [xsp+58Ch] [xbp-F4h]
  __int16 v566; // [xsp+594h] [xbp-ECh]
  id v567; // [xsp+596h] [xbp-EAh]
  __int16 v568; // [xsp+59Eh] [xbp-E2h]
  __int64 v569; // [xsp+5A0h] [xbp-E0h]
  __int64 v570; // [xsp+5B0h] [xbp-D0h]
  _QWORD v571[3]; // [xsp+5B8h] [xbp-C8h] BYREF
  __int64 v572; // [xsp+5D0h] [xbp-B0h] BYREF
  __CFString *v573; // [xsp+5D8h] [xbp-A8h] BYREF
  void *v574; // [xsp+5E0h] [xbp-A0h] BYREF
  __CFString *v575; // [xsp+5E8h] [xbp-98h] BYREF
  void *v576; // [xsp+5F0h] [xbp-90h] BYREF

  v554[0] = 0;
  v554[1] = v554;
  v554[2] = 0x3032000000LL;
  v554[3] = __Block_byref_object_copy__4684;
  v554[4] = __Block_byref_object_dispose__4684;
  v555 = 0;
  v548 = 0;
  v549 = (id *)&v548;
  v550 = 0x3032000000LL;
  v551 = __Block_byref_object_copy__4684;
  v552 = __Block_byref_object_dispose__4684;
  v553 = 0;
  v544 = 0;
  v545 = &v544;
  v546 = 0x2020000000LL;
  v547 = 0;
  v540 = 0;
  v541 = &v540;
  v542 = 0x2020000000LL;
  v543 = 0;
  v536 = 0;
  v537 = &v536;
  v538 = 0x2020000000LL;
  v539 = 0;
  v532 = 0;
  v533 = &v532;
  v534 = 0x2020000000LL;
  v535 = 0;
  error = 0;
  v527 = 0;
  v528 = &v527;
  v529 = 0x2020000000LL;
  v530 = 0;
  v523 = 0;
  v524 = &v523;
  v525 = 0x2020000000LL;
  v526 = 0;
  v522 = -1;
  v516 = 0;
  v517 = &v516;
  v518 = 0x3032000000LL;
  v519 = __Block_byref_object_copy__4684;
  v520 = __Block_byref_object_dispose__4684;
  v521 = 0;
  v510 = 0;
  v511 = &v510;
  v512 = 0x3032000000LL;
  v513 = __Block_byref_object_copy__4684;
  v514 = __Block_byref_object_dispose__4684;
  v515 = 0;
  v504 = 0;
  v505 = &v504;
  v506 = 0x3032000000LL;
  v507 = __Block_byref_object_copy__4684;
  v508 = __Block_byref_object_dispose__4684;
  v509 = 0;
  v498 = 0;
  v499 = &v498;
  v500 = 0x3032000000LL;
  v501 = __Block_byref_object_copy__4684;
  v502 = __Block_byref_object_dispose__4684;
  v503 = 0;
  v492 = 0;
  v493 = &v492;
  v494 = 0x3032000000LL;
  v495 = __Block_byref_object_copy__4684;
  v496 = __Block_byref_object_dispose__4684;
  v497 = 0;
  v486 = 0;
  v487 = &v486;
  v488 = 0x3032000000LL;
  v489 = __Block_byref_object_copy__4684;
  v490 = __Block_byref_object_dispose__4684;
  v491 = 0;
  v482 = 0;
  v483 = (double *)&v482;
  v484 = 0x2020000000LL;
  v485 = 0;
  v481 = 0.0;
  v480 = 0;
  v476 = 0;
  v477 = &v476;
  v478 = 0x2020000000LL;
  v479 = 0;
  v472 = 0;
  v473 = (double *)&v472;
  v474 = 0x2020000000LL;
  v475 = 0;
  v5 = (NSObject *)objc_retain(*(id *)(a1 + 32));
  if ( !v5 )
  {
    global_queue_364 = j__dispatch_get_global_queue_364(0, 0);
    v7 = objc_claimAutoreleasedReturnValue_556(global_queue_364);
    objc_release(0);
    v5 = (NSObject *)v7;
  }
  if ( !*(_QWORD *)(a1 + 48) )
  {
    MobileActivationError_0 = createMobileActivationError_0(
                                (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                                989,
                                -1,
                                0,
                                CFSTR("Invalid input."),
                                v2,
                                v3,
                                v4,
                                v384);
    v33 = objc_claimAutoreleasedReturnValue_556(MobileActivationError_0);
LABEL_20:
    v425 = 0;
LABEL_21:
    v35 = 0;
    v421 = 0;
    v422 = 0;
    v36 = 0;
    v37 = 0;
    v38 = 0;
    v39 = 0;
    v414 = 0;
    v417 = 0;
    v408 = 0;
    v409 = 0;
    v410 = 0;
    v411 = 0;
    v412 = 0;
    v413 = 0;
    v418 = 0;
    v419 = 0;
    cf = 0;
    v15 = 0;
LABEL_22:
    v406 = 0;
    v407 = 0;
LABEL_23:
    v40 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
    v41 = *(void **)(v40 + 40);
    *(_QWORD *)(v40 + 40) = v33;
    goto LABEL_24;
  }
  v425 = objc_alloc_init((Class)off_41CEDE910);
  if ( !v425 )
  {
    v34 = createMobileActivationError_0(
            (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
            995,
            -1,
            0,
            CFSTR("Failed to allocate array."),
            v8,
            v9,
            v10,
            v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v34);
    goto LABEL_20;
  }
  v11 = SecTaskCreateFromSelf_87(0);
  v15 = v11;
  if ( !v11 )
  {
    v55 = createMobileActivationError_0(
            (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
            1003,
            -1,
            0,
            CFSTR("Failed to create task."),
            v12,
            v13,
            v14,
            v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v55);
    goto LABEL_21;
  }
  v422 = (__CFString *)SecTaskCopySigningIdentifier_25(v11, &error);
  if ( !v422 )
  {
    v64 = createMobileActivationError_0(
            (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
            1009,
            -1,
            error,
            CFSTR("Failed to query code signing identifier."),
            v16,
            v17,
            v18,
            v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v64);
    v35 = 0;
    v421 = 0;
    v422 = 0;
LABEL_47:
    v36 = 0;
    v37 = 0;
    v38 = 0;
    v39 = 0;
    v414 = 0;
    v417 = 0;
    v408 = 0;
    v409 = 0;
    v410 = 0;
    v411 = 0;
    v412 = 0;
    v413 = 0;
    v418 = 0;
    v419 = 0;
LABEL_48:
    cf = 0;
    goto LABEL_22;
  }
  v421 = (void *)SecTaskCopyValueForEntitlement_98(v15, CFSTR("com.apple.mobileactivationd.spi"), &error);
  v19 = isNSNumber_0(v421);
  v20 = (void *)objc_claimAutoreleasedReturnValue_556(v19);
  if ( !v20 || (v21 = (unsigned __int8)objc_msgSend(v421, "boolValue"), objc_release(v20), (v21 & 1) == 0) )
  {
    v56 = error;
    v575 = CFSTR("com.apple.mobileactivationd.spi");
    v576 = &__kCFBooleanTrue;
    v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE908, "dictionaryWithObjects:forKeys:count:", &v576, &v575, 1));
    v60 = createMobileActivationError_0(
            (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
            1015,
            -7,
            v56,
            CFSTR("Missing required entitlement: %@"),
            v57,
            v58,
            v59,
            (char)v41);
    v61 = objc_claimAutoreleasedReturnValue_556(v60);
LABEL_45:
    v62 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
    v63 = *(void **)(v62 + 40);
    *(_QWORD *)(v62 + 40) = v61;
    objc_release(v63);
    v35 = 0;
    v36 = 0;
    v37 = 0;
    v38 = 0;
    v39 = 0;
    v414 = 0;
    v417 = 0;
    v408 = 0;
    v409 = 0;
    v410 = 0;
    v411 = 0;
    v412 = 0;
    v413 = 0;
    v418 = 0;
    v419 = 0;
    cf = 0;
    v406 = 0;
    v407 = 0;
    goto LABEL_24;
  }
  v23 = (id *)(a1 + 40);
  v22 = *(void **)(a1 + 40);
  if ( !v22 )
  {
    queuea = 0;
    v395 = 0;
    v418 = 0;
    v419 = 0;
    v65 = 0;
    v399 = 0;
    v406 = 0;
    v407 = 0;
    v412 = 0;
    v413 = 0;
    v409 = 0;
    v410 = 0;
    v417 = 0;
    v411 = 0;
    v408 = 0;
    cf = 0;
    v397 = 1;
    goto LABEL_50;
  }
  v24 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v22, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
  v25 = isNSArray();
  v26 = (void *)objc_claimAutoreleasedReturnValue_556(v25);
  objc_release(v26);
  objc_release(v24);
  if ( v26 )
  {
    v27 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v27, "containsObject:", CFSTR("1.2.840.113635.100.10.1")) & 1) == 0 )
    {
      v28 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
      if ( !(unsigned int)objc_msgSend(v28, "containsObject:", CFSTR("1.2.840.113635.100.8.1")) )
      {
        v120 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
        v121 = (unsigned __int8)objc_msgSend(v120, "containsObject:", CFSTR("1.2.840.113635.100.8.3"));
        objc_release(v120);
        objc_release(v28);
        objc_release(v27);
        if ( (v121 & 1) == 0 )
          goto LABEL_71;
        goto LABEL_15;
      }
      objc_release(v28);
    }
    objc_release(v27);
LABEL_15:
    queue = (void *)SecTaskCopyValueForEntitlement_98(
                      v15,
                      CFSTR("com.apple.mobileactivationd.device-identifiers"),
                      &error);
    objc_release(v421);
    v29 = isNSNumber_0(queue);
    v30 = (void *)objc_claimAutoreleasedReturnValue_556(v29);
    if ( !v30 || (v31 = (unsigned __int8)objc_msgSend(queue, "boolValue"), objc_release(v30), (v31 & 1) == 0) )
    {
      v94 = error;
      v573 = CFSTR("com.apple.mobileactivationd.device-identifiers");
      v574 = &__kCFBooleanTrue;
      v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE908, "dictionaryWithObjects:forKeys:count:", &v574, &v573, 1));
      v98 = createMobileActivationError_0(
              (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
              1028,
              -7,
              v94,
              CFSTR("Missing required entitlement: %@"),
              v95,
              v96,
              v97,
              (char)v41);
      v99 = objc_claimAutoreleasedReturnValue_556(v98);
      v100 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
      v101 = *(void **)(v100 + 40);
      *(_QWORD *)(v100 + 40) = v99;
      objc_release(v101);
      v35 = 0;
      v36 = 0;
      v37 = 0;
      v38 = 0;
      v39 = 0;
      v414 = 0;
      v417 = 0;
      v408 = 0;
      v409 = 0;
      v410 = 0;
      v411 = 0;
      v412 = 0;
      v413 = 0;
      v418 = 0;
      v419 = 0;
      cf = 0;
      v406 = 0;
      v407 = 0;
      v421 = queue;
      goto LABEL_24;
    }
    v421 = queue;
LABEL_71:
    v122 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v122, "containsObject:", CFSTR("1.2.840.113635.100.8.9.1")) & 1) != 0 )
    {
LABEL_80:
      objc_release(v122);
LABEL_81:
      v41 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
      v130 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1039,
               -2,
               0,
               CFSTR("This API does not support Enterprise Device Attestation OIDs: %@"),
               v127,
               v128,
               v129,
               (char)v41);
      v61 = objc_claimAutoreleasedReturnValue_556(v130);
      goto LABEL_45;
    }
    v123 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v123, "containsObject:", CFSTR("1.2.840.113635.100.8.9.2")) & 1) != 0 )
    {
LABEL_79:
      objc_release(v123);
      goto LABEL_80;
    }
    v124 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v124, "containsObject:", CFSTR("1.2.840.113635.100.8.10.1")) & 1) != 0 )
    {
LABEL_78:
      objc_release(v124);
      goto LABEL_79;
    }
    v125 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v125, "containsObject:", CFSTR("1.2.840.113635.100.8.10.2")) & 1) != 0 )
    {
LABEL_77:
      objc_release(v125);
      goto LABEL_78;
    }
    v126 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v126, "containsObject:", CFSTR("1.2.840.113635.100.8.10.3")) & 1) != 0 )
    {
      objc_release(v126);
      goto LABEL_77;
    }
    cfa = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    v420 = (unsigned __int8)objc_msgSend(cfa, "containsObject:", CFSTR("1.2.840.113635.100.8.11.1"));
    objc_release(cfa);
    objc_release(v126);
    objc_release(v125);
    objc_release(v124);
    objc_release(v123);
    objc_release(v122);
    if ( (v420 & 1) != 0 )
      goto LABEL_81;
    v168 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    if ( ((unsigned int)objc_msgSend(v168, "containsObject:", CFSTR("1.2.840.113635.100.8.6")) & 1) != 0 )
    {
      v169 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
      objc_release(v169);
      objc_release(v168);
      if ( !v169 )
      {
        v173 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1044,
                 -2,
                 0,
                 CFSTR("Missing required option: %@"),
                 v170,
                 v171,
                 v172,
                 (char)CFSTR("AccessControls"));
        v33 = objc_claimAutoreleasedReturnValue_556(v173);
LABEL_139:
        v35 = 0;
        goto LABEL_47;
      }
    }
    else
    {
      objc_release(v168);
    }
  }
  v200 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainLabel")));
  v201 = isNSString_0();
  v202 = (void *)objc_claimAutoreleasedReturnValue_556(v201);
  objc_release(v202);
  objc_release(v200);
  if ( v202 )
  {
    if ( (isRunningInRootLaunchdContext() & 1) != 0
      || (isRunningInRecovery() & 1) != 0
      || (unsigned int)isRunningInDiagnosticsMode() )
    {
      v206 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1058,
               -2,
               0,
               CFSTR("Option (%@) not allowed for processes running in the system context or diagnostics mode."),
               v203,
               v204,
               v205,
               (char)CFSTR("KeychainLabel"));
      v33 = objc_claimAutoreleasedReturnValue_556(v206);
      goto LABEL_139;
    }
    v222 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
    v223 = isNSData_0();
    v224 = (void *)objc_claimAutoreleasedReturnValue_556(v223);
    objc_release(v224);
    objc_release(v222);
    if ( v224 )
    {
      v228 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1063,
               -2,
               0,
               CFSTR("Keychain (%@) not supported with %@."),
               v225,
               v226,
               v227,
               (char)CFSTR("KeychainLabel"));
      v33 = objc_claimAutoreleasedReturnValue_556(v228);
      goto LABEL_139;
    }
    v418 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainLabel")));
    v417 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-rk"), v418));
    v412 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-leaf"), v418));
    v409 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-intermediate"), v418));
    v413 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-combined"), v418));
    v411 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-monotonic-clock"), v418));
    v408 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-server-timestamp"), v418));
    v384 = (char)v418;
    v410 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE948, "stringWithFormat:", CFSTR("%@-rtc-reset-count")));
  }
  else
  {
    v417 = 0;
    v418 = 0;
    v412 = 0;
    v413 = 0;
    v409 = 0;
    v410 = 0;
    v411 = 0;
    v408 = 0;
  }
  v207 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainAccessGroup")));
  v208 = isNSString_0();
  v209 = (void *)objc_claimAutoreleasedReturnValue_556(v208);
  objc_release(v209);
  objc_release(v207);
  if ( v209 )
    v210 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("KeychainAccessGroup")));
  else
    v210 = 0;
  if ( v418 && !v210 )
  {
    v211 = objc_retain(v422);
    v210 = (__int64)v422;
  }
  v419 = (id)v210;
  v212 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("IgnoreExistingKeychainItems")));
  v213 = isNSNumber_0(v212);
  v214 = (void *)objc_claimAutoreleasedReturnValue_556(v213);
  objc_release(v214);
  objc_release(v212);
  if ( v214 )
  {
    v215 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("IgnoreExistingKeychainItems")));
    v216 = (unsigned int)objc_msgSend(v215, "boolValue");
    objc_release(v215);
  }
  else
  {
    v216 = 0;
  }
  v217 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
  objc_release(v217);
  if ( !v217 )
    goto LABEL_163;
  if ( (isRunningInRootLaunchdContext() & 1) != 0
    || (isRunningInRecovery() & 1) != 0
    || (unsigned int)isRunningInDiagnosticsMode() )
  {
    v221 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1092,
             -2,
             0,
             CFSTR("Option (%@) not allowed for processes running in the system context or diagnostics mode."),
             v218,
             v219,
             v220,
             (char)CFSTR("AccessControls"));
    v33 = objc_claimAutoreleasedReturnValue_556(v221);
LABEL_155:
    v35 = 0;
    v36 = 0;
    v37 = 0;
    v38 = 0;
    v39 = 0;
    v414 = 0;
    goto LABEL_48;
  }
  v229 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
  v230 = isNSData_0();
  v231 = (void *)objc_claimAutoreleasedReturnValue_556(v230);
  objc_release(v231);
  objc_release(v229);
  if ( v231 )
  {
    v235 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1097,
             -2,
             0,
             CFSTR("ACLs (%@) not supported with %@."),
             v232,
             v233,
             v234,
             (char)CFSTR("AccessControls"));
    v33 = objc_claimAutoreleasedReturnValue_556(v235);
    goto LABEL_155;
  }
  v236 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
  v237 = CFGetTypeID_254(v236);
  TypeID_4 = SecAccessControlGetTypeID_4();
  objc_release(v236);
  if ( v237 == TypeID_4 )
  {
    cf = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("AccessControls")));
    objc_release(cf);
    CFRetain_262(cf);
  }
  else
  {
LABEL_163:
    cf = 0;
  }
  v239 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("reuseExistingKey")));
  v240 = isNSNumber_0(v239);
  v241 = (void *)objc_claimAutoreleasedReturnValue_556(v240);
  objc_release(v241);
  objc_release(v239);
  if ( v241 )
  {
    v242 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("reuseExistingKey")));
    v415 = (unsigned int)objc_msgSend(v242, "boolValue");
    objc_release(v242);
  }
  else
  {
    v415 = 0;
  }
  v243 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
  v244 = isNSNumber_0(v243);
  v245 = (void *)objc_claimAutoreleasedReturnValue_556(v244);
  objc_release(v245);
  objc_release(v243);
  if ( v245 )
  {
    v246 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("UseSoftwareGeneratedKey")));
    queueb = (unsigned int)objc_msgSend(v246, "boolValue");
    objc_release(v246);
  }
  else
  {
    queueb = 1;
  }
  v247 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
  v248 = isNSNumber_0(v247);
  v249 = (void *)objc_claimAutoreleasedReturnValue_556(v248);
  objc_release(v249);
  objc_release(v247);
  if ( v249 )
  {
    v250 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("scrtAttestation")));
    v392 = (unsigned int)objc_msgSend(v250, "boolValue");
    objc_release(v250);
  }
  else
  {
    v392 = 0;
  }
  v251 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
  v252 = isNSData_0();
  v253 = (void *)objc_claimAutoreleasedReturnValue_556(v252);
  objc_release(v253);
  objc_release(v251);
  if ( v253 )
  {
    v254 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
    v255 = isNSData_0();
    v256 = (void *)objc_claimAutoreleasedReturnValue_556(v255);
    objc_release(v256);
    objc_release(v254);
    if ( !v256 )
    {
      v279 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1121,
               -2,
               0,
               CFSTR("Missing required option for %@."),
               v257,
               v258,
               v259,
               (char)CFSTR("ClientAttestationPublicKey"));
      v33 = objc_claimAutoreleasedReturnValue_556(v279);
      v35 = 0;
      v36 = 0;
      v37 = 0;
      v38 = 0;
      v39 = 0;
      v414 = 0;
      goto LABEL_22;
    }
    v407 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationData")));
    v406 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ClientAttestationPublicKey")));
  }
  else
  {
    v406 = 0;
    v407 = 0;
  }
  v260 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ReturnReferenceDate")));
  v261 = isNSNumber_0(v260);
  v262 = (void *)objc_claimAutoreleasedReturnValue_556(v261);
  objc_release(v262);
  objc_release(v260);
  if ( v262 )
  {
    v263 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("ReturnReferenceDate")));
    v264 = (unsigned int)objc_msgSend(v263, "boolValue");
    objc_release(v263);
  }
  else
  {
    v264 = 0;
  }
  v265 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("SkipNetworkRequest")));
  v266 = isNSNumber_0(v265);
  v267 = (void *)objc_claimAutoreleasedReturnValue_556(v266);
  objc_release(v267);
  objc_release(v265);
  if ( v267 )
  {
    v268 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("SkipNetworkRequest")));
    v269 = (unsigned int)objc_msgSend(v268, "boolValue");
    objc_release(v268);
  }
  else
  {
    v269 = 0;
  }
  v270 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("DeleteExistingKeysAndCerts")));
  v271 = isNSNumber_0(v270);
  v272 = (void *)objc_claimAutoreleasedReturnValue_556(v271);
  objc_release(v272);
  objc_release(v270);
  v399 = v415 != 0;
  v65 = v216 != 0;
  v397 = queueb != 0;
  v395 = v264 != 0;
  queuea = v269 != 0;
  if ( v272 )
  {
    v273 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("DeleteExistingKeysAndCerts")));
    v416 = (unsigned int)objc_msgSend(v273, "boolValue");
    objc_release(v273);
    if ( !v417 )
    {
      v417 = 0;
      if ( !v416 )
        goto LABEL_199;
LABEL_194:
      v35 = 0;
      if ( v418 && v419 )
      {
        delete_keychain_data(v419, v411, 0);
        delete_keychain_data(v419, v410, 0);
        delete_keychain_data(v419, v408, 0);
        delete_keychain_data(v419, v413, 0);
        delete_keychain_item(v419, v417, 0);
        delete_certificate(v419, v412, 0);
        delete_certificate(v419, v409, 0);
        v35 = 0;
        v36 = 0;
        v37 = 0;
        v38 = 0;
        v39 = 0;
        v414 = 0;
      }
      else
      {
        v36 = 0;
        v37 = 0;
        v38 = 0;
        v39 = 0;
        v414 = 0;
      }
      goto LABEL_25;
    }
  }
  else
  {
    if ( !v417 )
    {
      v417 = 0;
      goto LABEL_199;
    }
    LOBYTE(v416) = 0;
  }
  if ( v392 )
  {
    v393 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v417, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v417);
    v389 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v412, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v412);
    v274 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v409, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v409);
    v275 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v413, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v413);
    v276 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v411, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v411);
    v277 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v408, "stringByAppendingString:", CFSTR("-scrt")));
    objc_release(v408);
    v278 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v410, "stringByAppendingString:", CFSTR("-scrt")));
  }
  else
  {
    v393 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v417, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v417);
    v389 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v412, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v412);
    v274 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v409, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v409);
    v275 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v413, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v413);
    v276 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v411, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v411);
    v277 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v408, "stringByAppendingString:", CFSTR("-ucrt")));
    objc_release(v408);
    v278 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v410, "stringByAppendingString:", CFSTR("-ucrt")));
  }
  v280 = (void *)v278;
  objc_release(v410);
  v408 = (id)v277;
  v409 = (void *)v274;
  v410 = v280;
  v411 = (id)v276;
  v417 = (id)v393;
  v412 = (void *)v389;
  v413 = (id)v275;
  if ( (v416 & 1) != 0 )
    goto LABEL_194;
LABEL_199:
  if ( v407 )
  {
    if ( cf )
      CFRelease_438(cf);
    v281 = SecAccessControlCreate_3(0, &error);
    cf = (void *)v281;
    if ( !v281 )
    {
      v289 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1195,
               -1,
               error,
               CFSTR("Failed to create access control."),
               v282,
               v283,
               v284,
               v384);
      v33 = objc_claimAutoreleasedReturnValue_556(v289);
      v35 = 0;
      v36 = 0;
      v37 = 0;
      v38 = 0;
      v39 = 0;
      v414 = 0;
      cf = 0;
      goto LABEL_23;
    }
    if ( (SecAccessControlSetProtection_3(v281, CFSTR("f"), &error) & 1) == 0 )
    {
      v288 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1200,
               -1,
               error,
               CFSTR("Failed to set ACL protection to %@."),
               v285,
               v286,
               v287,
               (char)CFSTR("f"));
      v33 = objc_claimAutoreleasedReturnValue_556(v288);
      goto LABEL_86;
    }
  }
  else
  {
    v407 = 0;
  }
LABEL_50:
  if ( (isRunningInRecovery() & 1) != 0 )
  {
    v69 = 0;
  }
  else
  {
    v102 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
    v471 = *(id *)(v102 + 40);
    v69 = isAutomaticTimeEnabledWithError(&v471);
    j__objc_storeStrong_550((id *)(v102 + 40), v471);
    v106 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
    v109 = *(void **)(v106 + 40);
    v108 = (id *)(v106 + 40);
    v107 = v109;
    if ( (v69 & 1) == 0 && v107 )
    {
      v110 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1212,
               -1,
               v107,
               CFSTR("Failed to query automatic time state."),
               v103,
               v104,
               v105,
               v384);
      v33 = objc_claimAutoreleasedReturnValue_556(v110);
      goto LABEL_86;
    }
    v470 = v107;
    v111 = copyMonotonicClock(&v470);
    j__objc_storeStrong_550(v108, v470);
    v483[3] = v111;
    v115 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
    v118 = *(void **)(v115 + 40);
    v117 = (id *)(v115 + 40);
    v116 = v118;
    if ( v111 == 0.0 )
    {
      v119 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1218,
               -1,
               v116,
               CFSTR("Failed to query monotonic clock."),
               v112,
               v113,
               v114,
               v384);
      v33 = objc_claimAutoreleasedReturnValue_556(v119);
      goto LABEL_86;
    }
    v469 = v116;
    v131 = copyRTCResetCountWithError(&v469);
    j__objc_storeStrong_550(v117, v469);
    *((_DWORD *)v477 + 6) = v131;
    if ( !v131 )
    {
      v132 = *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL);
      if ( v132 )
      {
        v133 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1224,
                 -1,
                 v132,
                 CFSTR("Failed to query RTC reset count."),
                 v66,
                 v67,
                 v68,
                 v384);
        v33 = objc_claimAutoreleasedReturnValue_556(v133);
        goto LABEL_86;
      }
    }
  }
  v35 = 0;
  v414 = 0;
  v39 = 0;
  v38 = 0;
  if ( v65 || !v418 )
    goto LABEL_248;
  v70 = copy_keychain_item(v419, v417, *v23, &v522, 0);
  v533[3] = v70;
  if ( v522 != -25300 && v522 )
  {
    v134 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1234,
             -1,
             *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
             CFSTR("Failed to query existing reference key (%@/%@): %d"),
             v71,
             v72,
             v73,
             (char)v419);
    v33 = objc_claimAutoreleasedReturnValue_556(v134);
    goto LABEL_86;
  }
  v74 = copy_keychain_data(v419, v413, &v522, 0);
  v414 = (CFDataRef)objc_claimAutoreleasedReturnValue_556(v74);
  if ( v522 != -25300 && v522 )
  {
    v135 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1240,
             -1,
             *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
             CFSTR("Failed to query existing leaf/intermediate certificates (%@/%@): %d"),
             v75,
             v76,
             v77,
             (char)v419);
    v33 = objc_claimAutoreleasedReturnValue_556(v135);
    goto LABEL_88;
  }
  if ( !v414 )
  {
    load_certificate(v528 + 3, v419, v412, &v522, 0);
    if ( v522 != -25300 && v522 )
    {
      v161 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1272,
               -1,
               *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
               CFSTR("Failed to query existing leaf certificate (%@/%@): %d"),
               v137,
               v138,
               v139,
               (char)v419);
      v33 = objc_claimAutoreleasedReturnValue_556(v161);
    }
    else
    {
      load_certificate(v524 + 3, v419, v409, &v522, 0);
      if ( v522 != -25300 && v522 )
      {
        v196 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1278,
                 -1,
                 *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
                 CFSTR("Failed to query existing intermediate certificate (%@/%@): %d"),
                 v140,
                 v141,
                 v142,
                 (char)v419);
        v33 = objc_claimAutoreleasedReturnValue_556(v196);
      }
      else
      {
        if ( !v528[3] || !v524[3] )
        {
          v414 = 0;
          goto LABEL_104;
        }
        v143 = objc_alloc_init((Class)off_41CEDE9A8);
        v144 = (void *)v517[5];
        v517[5] = (__int64)v143;
        objc_release(v144);
        if ( v517[5] )
        {
          v151 = SecCertificateCopyData_23((SecCertificateRef)v528[3]);
          if ( !v151 )
          {
            v377 = createMobileActivationError_0(
                     (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                     1291,
                     -1,
                     0,
                     CFSTR("Failed to copy certificate data."),
                     v148,
                     v149,
                     v150,
                     v384);
            v33 = objc_claimAutoreleasedReturnValue_556(v377);
            goto LABEL_86;
          }
          objc_msgSend((id)v517[5], "appendData:", v151);
          v414 = SecCertificateCopyData_23((SecCertificateRef)v524[3]);
          objc_release(v151);
          if ( !v414 )
          {
            v379 = createMobileActivationError_0(
                     (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                     1299,
                     -1,
                     0,
                     CFSTR("Failed to copy certificate data."),
                     v152,
                     v153,
                     v154,
                     v384);
            v33 = objc_claimAutoreleasedReturnValue_556(v379);
            goto LABEL_86;
          }
          objc_msgSend((id)v517[5], "appendData:", v414);
          v155 = v517[5];
          v156 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
          v467 = *(id *)(v156 + 40);
          v157 = store_keychain_data(v155, v419, v413, &v467);
          j__objc_storeStrong_550((id *)(v156 + 40), v467);
          if ( (v157 & 1) != 0 )
          {
            delete_certificate(v419, v412, 0);
            delete_certificate(v419, v409, 0);
LABEL_104:
            v39 = 0;
            goto LABEL_105;
          }
          v380 = createMobileActivationError_0(
                   (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                   1306,
                   -1,
                   *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
                   CFSTR("Failed to store leaf/intermediate certificates."),
                   v158,
                   v159,
                   v160,
                   v384);
          v33 = objc_claimAutoreleasedReturnValue_556(v380);
LABEL_88:
          v35 = 0;
          v36 = 0;
          v37 = 0;
          v38 = 0;
          v39 = 0;
          goto LABEL_23;
        }
        v199 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1285,
                 -1,
                 0,
                 CFSTR("Failed to allocate data."),
                 v145,
                 v146,
                 v147,
                 v384);
        v33 = objc_claimAutoreleasedReturnValue_556(v199);
      }
    }
LABEL_86:
    v35 = 0;
    v36 = 0;
    v37 = 0;
    v38 = 0;
    v39 = 0;
    v414 = 0;
    goto LABEL_23;
  }
  v78 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
  obj = *(id *)(v78 + 40);
  v79 = parseDERCertificatesFromChain_0(v414, &obj);
  v39 = (void *)objc_claimAutoreleasedReturnValue_556(v79);
  j__objc_storeStrong_550((id *)(v78 + 40), obj);
  if ( !v39 || objc_msgSend(v39, "count") != (void *)2 )
  {
    v136 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1251,
             -1,
             *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
             CFSTR("Failed to parse DER certificate chain."),
             v80,
             v81,
             v82,
             v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v136);
    goto LABEL_90;
  }
  v83 = (const __CFData *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v39, "objectAtIndexedSubscript:", 0));
  v84 = SecCertificateCreateWithData_33(0, v83);
  v528[3] = (__int64)v84;
  objc_release(v83);
  if ( !v528[3] )
  {
    v197 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1257,
             -1,
             0,
             CFSTR("Failed to create certificate from DER data."),
             v85,
             v86,
             v87,
             v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v197);
    goto LABEL_90;
  }
  v88 = (const __CFData *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v39, "objectAtIndexedSubscript:", 1));
  v89 = SecCertificateCreateWithData_33(0, v88);
  v524[3] = (__int64)v89;
  objc_release(v88);
  if ( !v524[3] )
  {
    v93 = createMobileActivationError_0(
            (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
            1263,
            -1,
            0,
            CFSTR("Failed to create certificate from DER data."),
            v90,
            v91,
            v92,
            v384);
    v33 = objc_claimAutoreleasedReturnValue_556(v93);
LABEL_90:
    v35 = 0;
    v36 = 0;
    v37 = 0;
    v38 = 0;
    goto LABEL_23;
  }
LABEL_105:
  if ( (isRunningInRecovery() & 1) == 0 )
  {
    v174 = copy_keychain_data(v419, v411, &v522, 0);
    v175 = objc_claimAutoreleasedReturnValue_556(v174);
    v176 = (void *)v487[5];
    v487[5] = v175;
    objc_release(v176);
    if ( v522 != -25300 && v522 )
    {
      v198 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1318,
               -1,
               *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
               CFSTR("Failed to query existing motononic time (%@/%@): %d"),
               v177,
               v178,
               v179,
               (char)v419);
      v33 = objc_claimAutoreleasedReturnValue_556(v198);
      goto LABEL_90;
    }
    v180 = (void *)v487[5];
    if ( v180 )
      objc_msgSend(v180, "getBytes:length:", &v481, 8);
    v181 = copy_keychain_data(v419, v410, &v522, 0);
    v182 = objc_claimAutoreleasedReturnValue_556(v181);
    v183 = (void *)v511[5];
    v511[5] = v182;
    objc_release(v183);
    if ( v522 != -25300 && v522 )
    {
      v290 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1328,
               -1,
               *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
               CFSTR("Failed to query existing RTC reset count (%@/%@): %d"),
               v184,
               v185,
               v186,
               (char)v419);
      v33 = objc_claimAutoreleasedReturnValue_556(v290);
      goto LABEL_90;
    }
    v187 = (void *)v511[5];
    if ( v187 )
      objc_msgSend(v187, "getBytes:length:", &v480, 4);
    v188 = copy_keychain_data(v419, v408, &v522, 0);
    v189 = objc_claimAutoreleasedReturnValue_556(v188);
    v190 = (void *)v505[5];
    v505[5] = v189;
    objc_release(v190);
    if ( v522 != -25300 && v522 )
    {
      v378 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1338,
               -1,
               *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
               CFSTR("Failed to query existing server timestamp (%@/%@): %d"),
               v66,
               v67,
               v68,
               (char)v419);
      v33 = objc_claimAutoreleasedReturnValue_556(v378);
      goto LABEL_90;
    }
    v191 = (void *)v505[5];
    if ( v191 )
    {
      objc_msgSend(v191, "getBytes:length:", v473 + 3, 8);
      v192 = objc_alloc((Class)off_41CEDE958);
      v193 = objc_msgSend(v192, "initWithTimeIntervalSinceReferenceDate:", v473[3]);
      v194 = (void *)v493[5];
      v493[5] = (__int64)v193;
      objc_release(v194);
      if ( !v493[5] )
      {
        v195 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1347,
                 -1,
                 0,
                 CFSTR("Failed to create date from server timestamp."),
                 v66,
                 v67,
                 v68,
                 v384);
        v33 = objc_claimAutoreleasedReturnValue_556(v195);
        goto LABEL_90;
      }
    }
  }
  if ( !v533[3] || !v528[3] )
  {
    v38 = 0;
LABEL_130:
    v391 = 0;
    goto LABEL_211;
  }
  v162 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
  v163 = isNSArray();
  v164 = (void *)objc_claimAutoreleasedReturnValue_556(v163);
  objc_release(v164);
  objc_release(v162);
  if ( v164 )
  {
    v165 = v528[3];
    v166 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(*v23, "objectForKeyedSubscript:", CFSTR("OIDSToInclude")));
    v167 = copyCertificateOIDsThatDiffer(v165, v166);
    v38 = (void *)objc_claimAutoreleasedReturnValue_556(v167);
    objc_release(v166);
  }
  else
  {
    v38 = 0;
  }
  if ( !objc_msgSend(v38, "count") )
    goto LABEL_130;
  v291 = createMobileActivationError_0(
           (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
           1365,
           -1,
           0,
           CFSTR("Mismatch in requested OIDs and existing certificate's OIDs (%@)."),
           v66,
           v67,
           v68,
           (char)v38);
  v292 = objc_claimAutoreleasedReturnValue_556(v291);
  v293 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
  v294 = *(void **)(v293 + 40);
  *(_QWORD *)(v293 + 40) = v292;
  objc_release(v294);
  v391 = 1;
LABEL_211:
  if ( v533[3] )
  {
    if ( (unsigned int)isFactoryMFiCertificate(v419, v528[3]) )
    {
      v295 = v533[3];
      v296 = a1 + 56;
      v297 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
      v466 = *(id *)(v297 + 40);
      valid = validSecureEnclaveReferenceKey(v295, 1, 0, &v466);
      j__objc_storeStrong_550((id *)(v297 + 40), v466);
      if ( !valid )
        goto LABEL_221;
    }
  }
  v299 = v533[3];
  if ( !v299 )
    goto LABEL_219;
  v296 = a1 + 56;
  v300 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
  v465 = *(id *)(v300 + 40);
  v301 = validSecureEnclaveReferenceKey(v299, 0, 0, &v465);
  j__objc_storeStrong_550((id *)(v300 + 40), v465);
  if ( !v301
    || v533[3]
    && v528[3]
    && (v302 = *(_QWORD *)(*(_QWORD *)v296 + 8LL),
        v464 = *(id *)(v302 + 40),
        v303 = certificatePublicKeyMatchesBIKPublicKey(),
        j__objc_storeStrong_550((id *)(v302 + 40), v464),
        (v303 & 1) == 0) )
  {
LABEL_221:
    v304 = createMobileActivationError_0(
             (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
             1385,
             -2,
             *(void **)(*(_QWORD *)(*(_QWORD *)v296 + 8LL) + 40LL),
             CFSTR("Invalid reference key."),
             v66,
             v67,
             v68,
             v384);
    v305 = objc_claimAutoreleasedReturnValue_556(v304);
    v306 = *(_QWORD *)(*(_QWORD *)v296 + 8LL);
    v307 = *(void **)(v306 + 40);
    *(_QWORD *)(v306 + 40) = v305;
    objc_release(v307);
  }
  else
  {
LABEL_219:
    if ( !v391 )
      goto LABEL_231;
  }
  v308 = objc_retain(&_os_log_default_0);
  if ( os_log_type_enabled_632((os_log_t)&_os_log_default_0, OS_LOG_TYPE_DEFAULT) )
  {
    v309 = *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL);
    *(_DWORD *)buf = 138412290;
    v557 = v309;
    _os_log_impl_600(
      &dword_40E4FC000,
      (os_log_t)&_os_log_default_0,
      OS_LOG_TYPE_DEFAULT,
      "Deleting invalid keys/certificates: %@",
      buf,
      0xCu);
  }
  objc_release(&_os_log_default_0);
  delete_keychain_data(v419, v411, 0);
  delete_keychain_data(v419, v410, 0);
  delete_keychain_data(v419, v408, 0);
  delete_keychain_data(v419, v413, 0);
  delete_keychain_item(v419, v417, 0);
  delete_certificate(v419, v412, 0);
  delete_certificate(v419, v409, 0);
  v310 = v533;
  v311 = (const void *)v533[3];
  if ( v311 )
  {
    CFRelease_438(v311);
    v310 = v533;
  }
  v310[3] = 0;
  v312 = v528;
  v313 = (const void *)v528[3];
  if ( v313 )
  {
    CFRelease_438(v313);
    v312 = v528;
  }
  v312[3] = 0;
  v314 = v524;
  v315 = (const void *)v524[3];
  if ( v315 )
  {
    CFRelease_438(v315);
    v314 = v524;
  }
  v314[3] = 0;
  v316 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
  v317 = *(void **)(v316 + 40);
  *(_QWORD *)(v316 + 40) = 0;
  objc_release(v317);
LABEL_231:
  if ( !v533[3] || !v528[3] || !v524[3] )
    goto LABEL_247;
  if ( (isRunningInRecovery() & 1) != 0 || (v69 & 1) != 0 || (v318 = v481, v481 == 0.0) || (v319 = (void *)v493[5]) == 0 )
  {
    v323 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE958, "date", v318));
    v322 = (void *)v499[5];
    v499[5] = v323;
    v321 = 1;
  }
  else
  {
    v320 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v319, "dateByAddingTimeInterval:", v483[3] - v481));
    v321 = 0;
    v322 = (void *)v499[5];
    v499[5] = v320;
  }
  objc_release(v322);
  v324 = v528[3];
  objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate");
  if ( !(unsigned int)SecCertificateIsValid_2(v324)
    || (v325 = v524[3],
        objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate"),
        !(unsigned int)SecCertificateIsValid_2(v325)) )
  {
    v330 = 0;
    v329 = 0;
    if ( (v321 & 1) == 0 )
      goto LABEL_276;
    goto LABEL_246;
  }
  v326 = SecCertificateNotValidAfter_8(v528[3]);
  v327 = SecCertificateNotValidBefore_7(v528[3]);
  objc_msgSend((id)v499[5], "timeIntervalSinceReferenceDate");
  if ( v328 - SecCertificateNotValidBefore_7(v528[3]) >= (v326 - v327) * 0.9 )
  {
    v330 = 1;
    v329 = 1;
    if ( (v321 & 1) == 0 )
      goto LABEL_276;
LABEL_246:
    if ( v330 )
      goto LABEL_277;
LABEL_247:
    v35 = 0;
    goto LABEL_248;
  }
  v329 = 0;
  v330 = 1;
  if ( (v321 & 1) != 0 )
    goto LABEL_246;
LABEL_276:
  if ( ((unsigned __int8)v330 & (*((_DWORD *)v477 + 6) == v480)) == 0 )
    goto LABEL_247;
LABEL_277:
  if ( v395 )
  {
    v381 = v524[3];
    v571[1] = v528[3];
    v571[2] = v381;
    v382 = &v572;
    v383 = v499 + 5;
  }
  else
  {
    v570 = v528[3];
    v382 = v571;
    v383 = v524 + 3;
  }
  *v382 = *v383;
  v35 = (id)objc_claimAutoreleasedReturnValue_556(objc_msgSend(off_41CEDE918, "arrayWithObjects:count:"));
  if ( v329 )
  {
LABEL_248:
    if ( queuea )
    {
      v331 = createMobileActivationError_0(
               (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
               1470,
               -1,
               0,
               CFSTR("Missing or expired certificates, and network request explictly not attempted."),
               v66,
               v67,
               v68,
               v384);
      v332 = objc_claimAutoreleasedReturnValue_556(v331);
    }
    else
    {
      if ( v399 && (v333 = (const void *)v533[3]) != 0 )
      {
        v334 = (__SecKey *)CFRetain_262(v333);
        v541[3] = (__int64)v334;
      }
      else
      {
        v335 = *(_QWORD *)(a1 + 40);
        v336 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
        v463 = *(id *)(v336 + 40);
        v334 = (__SecKey *)createReferenceKeyBlob(cf, v397, v335, &v463);
        j__objc_storeStrong_550((id *)(v336 + 40), v463);
        v541[3] = (__int64)v334;
        if ( !v334 )
        {
          v360 = createMobileActivationError_0(
                   (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                   1481,
                   -1,
                   *(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL) + 40LL),
                   CFSTR("Failed to create reference key."),
                   v337,
                   v338,
                   v339,
                   v384);
          v332 = objc_claimAutoreleasedReturnValue_556(v360);
          goto LABEL_262;
        }
      }
      v340 = SecKeyCopyPublicKey_11(v334);
      v537[3] = (__int64)v340;
      if ( v340 )
      {
        v37 = SecKeyCopyExternalRepresentation_13(v340, &error);
        if ( v37 )
        {
          v347 = SecKeyCopyAttributes_8((SecKeyRef)v541[3]);
          v36 = v347;
          if ( v347 )
          {
            v354 = (void *)objc_claimAutoreleasedReturnValue_556(-[__CFDictionary objectForKeyedSubscript:](v347, "objectForKeyedSubscript:", CFSTR("toid")));
            if ( v354 )
            {
              v355 = j__dispatch_get_global_queue_364(0, 0);
              queuec = (NSObject *)objc_claimAutoreleasedReturnValue_556(v355);
              v428[0] = &_NSConcreteStackBlock_0;
              v428[1] = 3221225472LL;
              v428[2] = __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke_2;
              v428[3] = &unk_41974FD50;
              v54 = &v429;
              v429 = objc_retain(*(id *)(a1 + 40));
              v356 = objc_retain(v422);
              v357 = *(_QWORD *)(a1 + 56);
              v430 = v356;
              v444 = v357;
              v53 = objc_retain(v354);
              v431 = v53;
              v445 = v554;
              v446 = &v498;
              v358 = objc_retain(v425);
              v462 = v395;
              v425 = v358;
              v432 = v358;
              v447 = &v516;
              v448 = &v540;
              v406 = objc_retain(v406);
              v433 = v406;
              v418 = objc_retain(v418);
              v434 = v418;
              v419 = objc_retain(v419);
              v435 = v419;
              v413 = objc_retain(v413);
              v436 = v413;
              v417 = objc_retain(v417);
              v437 = v417;
              v411 = objc_retain(v411);
              v438 = v411;
              v410 = objc_retain(v410);
              v439 = v410;
              v408 = objc_retain(v408);
              v440 = v408;
              v449 = &v486;
              v450 = &v482;
              v451 = &v510;
              v452 = &v476;
              v453 = &v472;
              v454 = &v504;
              v455 = &v544;
              v456 = &v548;
              v457 = &v532;
              v458 = &v527;
              v459 = &v523;
              v35 = objc_retain(v35);
              v441 = v35;
              v460 = &v492;
              v442 = objc_retain(v5);
              v443 = objc_retain(*(id *)(a1 + 48));
              v461 = &v536;
              j__dispatch_async_488(queuec, v428);
              objc_release(queuec);
              objc_release(v443);
              objc_release(v442);
              objc_release(v441);
              objc_release(v440);
              objc_release(v439);
              objc_release(v438);
              objc_release(v437);
              objc_release(v436);
              objc_release(v435);
              objc_release(v434);
              objc_release(v433);
              objc_release(v432);
              objc_release(v431);
              objc_release(v430);
              goto LABEL_36;
            }
            v376 = createMobileActivationError_0(
                     (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                     1532,
                     -1,
                     error,
                     CFSTR("Failed to encode RK as data."),
                     v351,
                     v352,
                     v353,
                     v384);
            v332 = objc_claimAutoreleasedReturnValue_556(v376);
            goto LABEL_264;
          }
          v375 = createMobileActivationError_0(
                   (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                   1526,
                   -1,
                   error,
                   CFSTR("Failed to copy RK attributes."),
                   v348,
                   v349,
                   v350,
                   v384);
          v332 = objc_claimAutoreleasedReturnValue_556(v375);
LABEL_263:
          v36 = 0;
LABEL_264:
          v362 = *(_QWORD *)(*(_QWORD *)(a1 + 56) + 8LL);
          v363 = *(void **)(v362 + 40);
          *(_QWORD *)(v362 + 40) = v332;
          objc_release(v363);
          goto LABEL_265;
        }
        v361 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1494,
                 -1,
                 error,
                 CFSTR("Failed to encode RK public key as data."),
                 v344,
                 v345,
                 v346,
                 v384);
        v332 = objc_claimAutoreleasedReturnValue_556(v361);
      }
      else
      {
        v359 = createMobileActivationError_0(
                 (__int64)"DeviceIdentityIssueClientCertificateWithCompletion_block_invoke",
                 1488,
                 -1,
                 0,
                 CFSTR("Failed to copy RK public key."),
                 v341,
                 v342,
                 v343,
                 v384);
        v332 = objc_claimAutoreleasedReturnValue_556(v359);
      }
    }
LABEL_262:
    v37 = 0;
    goto LABEL_263;
  }
  v37 = 0;
  v36 = 0;
LABEL_265:
  v364 = (const void *)v533[3];
  if ( !v364 || !v35 )
    goto LABEL_25;
  v365 = CFRetain_262(v364);
  v545[3] = (__int64)v365;
  j__objc_storeStrong_550(v549 + 5, v35);
  v41 = &_os_log_default_0;
  v366 = objc_retain(&_os_log_default_0);
  if ( os_log_type_enabled_632((os_log_t)&_os_log_default_0, OS_LOG_TYPE_DEFAULT) )
  {
    v394 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
    v398 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
    v367 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidBefore_7(v398));
    v388 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v367));
    v396 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 0));
    v368 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidAfter_8(v396));
    queued = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v368));
    v387 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
    v390 = (void *)objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
    v369 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidBefore_7(v390));
    v400 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v369));
    v370 = objc_claimAutoreleasedReturnValue_556(objc_msgSend(v549[5], "objectAtIndexedSubscript:", 1));
    v371 = objc_msgSend(off_41CEDE958, "dateWithTimeIntervalSinceReferenceDate:", SecCertificateNotValidAfter_8(v370));
    v372 = objc_retain((id)objc_claimAutoreleasedReturnValue_556(v371));
    v373 = v493[5];
    *(_DWORD *)buf = 138544898;
    v557 = v394;
    v558 = 2114;
    v559 = v388;
    v560 = 2114;
    v561 = queued;
    v562 = 2114;
    v385 = (void *)v370;
    v386 = v372;
    v563 = v387;
    v564 = 2114;
    v565 = v400;
    v566 = 2114;
    v567 = v372;
    v374 = v372;
    v568 = 2114;
    v569 = v373;
    v41 = &_os_log_default_0;
    _os_log_impl_600(
      &dword_40E4FC000,
      (os_log_t)&_os_log_default_0,
      OS_LOG_TYPE_DEFAULT,
      "Returning cached certificates:\n"
      "* %{public}@\n"
      "    Not Valid Before: %{public}@\n"
      "  Not Valid After: %{public}@\n"
      "* %{public}@\n"
      "    Not Valid Before: %{public}@\n"
      "  Not Valid After: %{public}@\n"
      "* Server Timestamp: %{public}@\n",
      buf,
      0x48u);
    objc_release(v374);
    objc_release(v385);
    objc_release(v400);
    objc_release(v390);
    objc_release(v387);
    objc_release(queued);
    objc_release(v396);
    objc_release(v388);
    objc_release(v398);
    objc_release(v394);
    objc_release(v386);
    objc_release(v400);
    objc_release(queued);
    objc_release(v388);
  }
LABEL_24:
  objc_release(v41);
LABEL_25:
  block[0] = &_NSConcreteStackBlock_0;
  block[1] = 3221225472LL;
  block[2] = __DeviceIdentityIssueClientCertificateWithCompletion_block_invoke_309;
  block[3] = &unk_41974FD00;
  v42 = *(void **)(a1 + 48);
  v427[1] = *(_QWORD *)(a1 + 56);
  v427[0] = objc_retain(v42);
  v427[2] = &v544;
  v427[3] = &v548;
  j__dispatch_async_488(v5, block);
  v43 = v541;
  v44 = (const void *)v541[3];
  if ( v44 )
  {
    CFRelease_438(v44);
    v43 = v541;
  }
  v43[3] = 0;
  v45 = v537;
  v46 = (const void *)v537[3];
  if ( v46 )
  {
    CFRelease_438(v46);
    v45 = v537;
  }
  v45[3] = 0;
  v47 = v533;
  v48 = (const void *)v533[3];
  if ( v48 )
  {
    CFRelease_438(v48);
    v47 = v533;
  }
  v47[3] = 0;
  v49 = v528;
  v50 = (const void *)v528[3];
  if ( v50 )
  {
    CFRelease_438(v50);
    v49 = v528;
  }
  v49[3] = 0;
  v51 = v524;
  v52 = (const void *)v524[3];
  if ( v52 )
  {
    CFRelease_438(v52);
    v51 = v524;
  }
  v53 = 0;
  v54 = (id *)v427;
  v51[3] = 0;
LABEL_36:
  objc_release(*v54);
  if ( v15 )
    CFRelease_438(v15);
  if ( error )
    CFRelease_438(error);
  error = 0;
  if ( cf )
    CFRelease_438(cf);
  _Block_object_dispose_549(&v472, 8);
  _Block_object_dispose_549(&v476, 8);
  _Block_object_dispose_549(&v482, 8);
  objc_release(v5);
  objc_release(v38);
  objc_release(v422);
  _Block_object_dispose_549(&v486, 8);
  objc_release(v491);
  _Block_object_dispose_549(&v492, 8);
  objc_release(v497);
  _Block_object_dispose_549(&v498, 8);
  objc_release(v503);
  _Block_object_dispose_549(&v504, 8);
  objc_release(v509);
  _Block_object_dispose_549(&v510, 8);
  objc_release(v515);
  _Block_object_dispose_549(&v516, 8);
  objc_release(v521);
  objc_release(v39);
  objc_release(v414);
  objc_release(v408);
  objc_release(v411);
  objc_release(v410);
  objc_release(v417);
  objc_release(v409);
  objc_release(v412);
  objc_release(v413);
  objc_release(v419);
  objc_release(v418);
  _Block_object_dispose_549(&v523, 8);
  _Block_object_dispose_549(&v527, 8);
  _Block_object_dispose_549(&v532, 8);
  _Block_object_dispose_549(&v536, 8);
  _Block_object_dispose_549(&v540, 8);
  _Block_object_dispose_549(&v544, 8);
  objc_release(v406);
  objc_release(v407);
  objc_release(v37);
  objc_release(v36);
  objc_release(v53);
  objc_release(v421);
  _Block_object_dispose_549(&v548, 8);
  objc_release(v553);
  objc_release(v35);
  objc_release(v425);
  _Block_object_dispose_549(v554, 8);
  objc_release(v555);
}

identityCertificateOptions 用来构造“我想要一张什么样的 identity 证书”;

DeviceIdentityIssueClientCertificateWithCompletion 则负责根据这些参数检查调用方权限、复用或重新签发 attestation 证书链,并在 keychain 中维护一整套“证书 + SE key + 时间防回拨信息”的档案。流程如下:

7

7

读取激活证书后准备加密生成token。

  • 加密证书

组合参数

_SecCertificateCopyData
id __fastcall __66__DCCertificateGenerator__generateCertificateChainWithCompletion___block_invoke(
        __int64 a1,
        __int64 a2)
{
  void *v2; // x27
  __int64 v3; // x0
  __int64 v4; // x0
  __int64 v5; // x21
  __int64 v6; // x0
  __int64 v7; // x0
  __int64 v8; // x23
  unsigned __int64 v9; // x0
  void *v10; // x28
  char v11; // w9
  __int64 v12; // x2
  char v13; // w8
  char v14; // w19
  char v15; // w26
  __int64 v16; // x20
  __int64 v17; // x0
  void *v18; // x21
  void *v19; // x26
  void *v20; // x24
  char *v21; // x22
  int v22; // w28
  int v23; // w27
  char *v24; // x25
  char *v25; // x0
  char *v26; // x20
  char *v27; // x28
  void *v28; // x25
  NSError *v29; // x0
  NSError *v30; // x0
  NSError *v31; // x0
  __int64 v32; // x0
  __int64 v33; // x0
  __int64 v34; // x0
  void *v35; // x0
  __int64 v36; // x21
  int v37; // w19
  __int64 v38; // x0
  __int64 v39; // x0
  __int64 v40; // x0
  __int64 v41; // x20
  __int64 v42; // x0
  void *v43; // x0
  __int64 v44; // x0
  __int64 v45; // x0
  __int64 v46; // x0
  __int64 v47; // x0
  __int64 v48; // x0
  __int64 v49; // x0
  __int64 v50; // x0
  __int64 v51; // x0
  id result; // x0
  NSError *v53; // x0
  __int64 v54; // x0
  unsigned int v55; // w20
  __int64 v56; // x20
  __int64 v57; // x0
  __int64 v58; // x0
  __int64 v59; // x22
  __int64 v60; // x0
  __int64 v61; // x0
  __int64 v62; // x20
  __int64 v63; // x0
  NSError *v64; // x0
  __int64 v65; // x20
  __int64 v66; // x0
  DCCertificateGenerator *v67; // x0
  SEL v68; // x1
  id v69; // x2
  id v70; // x3
  id *v71; // x4
  __int64 v72; // [xsp+0h] [xbp-180h]
  unsigned __int64 v73; // [xsp+10h] [xbp-170h]
  void *v75; // [xsp+20h] [xbp-160h]
  void *v77; // [xsp+30h] [xbp-150h]
  void *v78; // [xsp+40h] [xbp-140h]
  char v79; // [xsp+48h] [xbp-138h]
  char v80; // [xsp+4Ch] [xbp-134h]
  __int64 v81; // [xsp+50h] [xbp-130h] BYREF
  __CFString *v82; // [xsp+58h] [xbp-128h] BYREF
  __int64 v83; // [xsp+60h] [xbp-120h] BYREF
  __CFString *v84; // [xsp+68h] [xbp-118h] BYREF
  __int64 v85; // [xsp+70h] [xbp-110h] BYREF
  __CFString *v86; // [xsp+78h] [xbp-108h] BYREF
  char __src[16]; // [xsp+80h] [xbp-100h] BYREF
  __int128 v88; // [xsp+90h] [xbp-F0h]
  __int128 v89; // [xsp+A0h] [xbp-E0h]
  __int128 v90; // [xsp+B0h] [xbp-D0h]
  __int128 v91; // [xsp+C0h] [xbp-C0h]
  char __str[16]; // [xsp+D0h] [xbp-B0h] BYREF
  __int128 v93; // [xsp+E0h] [xbp-A0h]
  __int128 v94; // [xsp+F0h] [xbp-90h]
  __int128 v95; // [xsp+100h] [xbp-80h]
  __int128 v96; // [xsp+110h] [xbp-70h]
  unsigned __int64 v97; // [xsp+120h] [xbp-60h]

  v97 = 0x8FCA7F6773E200E4LL;
  v2 = (void *)objc_retain_x2_1310();
  v3 = ((__int64 (*)(void))MEMORY[0x243ECC210])();
  v4 = _DCLogSystem(v3);
  v5 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v4);
  v6 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v5, 0);
  if ( (_DWORD)v6 )
  {
    *(_WORD *)__str = 0;
    v6 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
           &dword_24150F000,
           v5,
           0,
           "Certificate issued, processing..",
           __str,
           2);
  }
  v7 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v6);
  v8 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC210])(v7);
  v75 = (void *)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(+[NSDate date](&OBJC_CLASS___NSDate, "date"));
  if ( v2 && (v9 = (unsigned __int64)objc_msgSend(v2, "count"), (v9 & 0xFFFFFFFFFFFFFFFELL) == 2) )
  {
    v73 = v9;
    v79 = 0;
    v10 = 0;
    v11 = 0;
    v12 = 0;
    v13 = 1;
    v77 = v2;
    while ( 1 )
    {
      v14 = v13;
      v15 = v11;
      v16 = ((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", v12));
      MEMORY[0x243ECC120]();
      v17 = ((__int64 (__fastcall *)(__int64))unk_243ECBDF0)(v16);
      v18 = (void *)((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC1B0])(v17);
      v95 = 0u;
      v96 = 0u;
      v93 = 0u;
      v94 = 0u;
      *(_OWORD *)__str = 0u;
      v90 = 0u;
      v91 = 0u;
      v88 = 0u;
      v89 = 0u;
      *(_OWORD *)__src = 0u;
      if ( v18 )
      {
        v80 = v15;
        v19 = (void *)((__int64 (*)(void))MEMORY[0x243ECC080])();
        v20 = (void *)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v18, "base64EncodedDataWithOptions:", 1));
        v21 = (char *)objc_msgSend(v20, "length");
        if ( v21 )
        {
          v78 = v10;
          v22 = snprintf(__str, 0x50u, "-----BEGIN %s-----\n", "CERTIFICATE");
          v23 = snprintf(__src, 0x50u, "\n-----END %s-----", "CERTIFICATE");
          v24 = &v21[v22 + v23];
          v25 = (char *)malloc((size_t)(v24 + 1));
          if ( v25 )
          {
            v26 = v25;
            v27 = &strncpy(v25, __str, v22)[v22];
            objc_msgSend(v20, "getBytes:range:", v27, 0, v21);
            strncpy(&v21[(_QWORD)v27], __src, v23);
            v28 = (void *)((__int64 (__fastcall *)(NSData *))MEMORY[0x243ECC0A0])(
                            +[NSData(NSData) dataWithBytesNoCopy:length:](
                              &OBJC_CLASS___NSData,
                              "dataWithBytesNoCopy:length:",
                              v26,
                              v24));
            if ( !v28 )
            {
              v85 = 0x21AEAF128LL;
              v86 = CFSTR("Failed to create pem data.");
              v31 = +[NSError errorWithDomain:code:userInfo:](
                      &OBJC_CLASS___NSError,
                      "errorWithDomain:code:userInfo:",
                      CFSTR("com.apple.devicecheck.cryptoerror"),
                      0,
                      ((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
                        +[NSDictionary dictionaryWithObjects:forKeys:count:](
                          &OBJC_CLASS___NSDictionary,
                          "dictionaryWithObjects:forKeys:count:",
                          &v86,
                          &v85,
                          1)));
              ((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v31);
              ((void (*)(void))unk_243ECC180)();
              free(v26);
            }
          }
          else
          {
            v85 = 0x21AEAF128LL;
            v86 = CFSTR("Failed to allocate buffer.");
            v30 = +[NSError errorWithDomain:code:userInfo:](
                    &OBJC_CLASS___NSError,
                    "errorWithDomain:code:userInfo:",
                    CFSTR("com.apple.devicecheck.cryptoerror"),
                    0,
                    ((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
                      +[NSDictionary dictionaryWithObjects:forKeys:count:](
                        &OBJC_CLASS___NSDictionary,
                        "dictionaryWithObjects:forKeys:count:",
                        &v86,
                        &v85,
                        1)));
            ((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v30);
            ((void (*)(void))unk_243ECC170)();
            v28 = 0;
          }
          v2 = v77;
          v10 = v78;
        }
        else
        {
          v28 = 0;
        }
        ((void (*)(void))MEMORY[0x243ECC160])();
        objc_autoreleasePoolPop(v19);
        v15 = v80;
      }
      else
      {
        v85 = 0x21AEAF128LL;
        v86 = CFSTR("Invalid inputs.");
        v29 = +[NSError errorWithDomain:code:userInfo:](
                &OBJC_CLASS___NSError,
                "errorWithDomain:code:userInfo:",
                CFSTR("com.apple.devicecheck.cryptoerror"),
                0,
                ((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
                  +[NSDictionary dictionaryWithObjects:forKeys:count:](
                    &OBJC_CLASS___NSDictionary,
                    "dictionaryWithObjects:forKeys:count:",
                    &v86,
                    &v85,
                    1)));
        ((void (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v29);
        ((void (*)(void))MEMORY[0x243ECC160])();
        v28 = 0;
      }
      v32 = ((__int64 (*)(void))MEMORY[0x243ECC140])();
      v33 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v32);
      v34 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC150])(v33);
      ((void (__fastcall *)(__int64))MEMORY[0x243ECC130])(v34);
      if ( !v28 )
        break;
      if ( v10 )
        objc_msgSend(v10, "appendBytes:length:", "\n", 1);
      else
        v10 = objc_msgSend(
                (id)((__int64 (__fastcall *)(void *))MEMORY[0x243ECC040])(&OBJC_CLASS___NSMutableData),
                "initWithCapacity:",
                objc_msgSend(v28, "length"));
      v35 = objc_msgSend(v10, "appendData:", v28);
      v13 = 0;
      v11 = 1;
      v79 = v15;
      v12 = 1;
      if ( (v14 & 1) == 0 )
      {
        v36 = v8;
        goto LABEL_36;
      }
    }
    v83 = 0x21AEAF128LL;
    v84 = CFSTR("Failed to create PEM data from cert.");
    v53 = +[NSError errorWithDomain:code:userInfo:](
            &OBJC_CLASS___NSError,
            "errorWithDomain:code:userInfo:",
            CFSTR("com.apple.devicecheck.cryptoerror"),
            0,
            ((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
              +[NSDictionary dictionaryWithObjects:forKeys:count:](
                &OBJC_CLASS___NSDictionary,
                "dictionaryWithObjects:forKeys:count:",
                &v84,
                &v83,
                1)));
    v36 = ((__int64 (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v53);
    v54 = ((__int64 (*)(void))MEMORY[0x243ECC150])();
    v35 = (void *)((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC140])(v54);
    v15 = v79;
LABEL_36:
    if ( v73 == 3 )
    {
      v55 = (unsigned int)objc_msgSend(
                            *(id *)(a1 + 32),
                            "_isNSDate:",
                            ((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", 2)));
      ((void (*)(void))MEMORY[0x243ECC140])();
      if ( v55 )
      {
        v56 = ((__int64 (__fastcall *)(void *))MEMORY[0x243ECC0A0])(objc_msgSend(v2, "objectAtIndexedSubscript:", 2));
        v57 = MEMORY[0x243ECC1A0]();
        v58 = _DCLogSystem(v57);
        v59 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v58);
        v60 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v59, 0);
        if ( (_DWORD)v60 )
        {
          *(_WORD *)__str = 0;
          v60 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
                  &dword_24150F000,
                  v59,
                  0,
                  "Using synced timestamp...",
                  __str,
                  2);
        }
        ((void (__fastcall *)(__int64))MEMORY[0x243ECC140])(v60);
        v37 = v15 & 1;
        v75 = (void *)v56;
      }
      else
      {
        v81 = 0x21AEAF128LL;
        v82 = CFSTR("Expected date field, failing...");
        v64 = +[NSError errorWithDomain:code:userInfo:](
                &OBJC_CLASS___NSError,
                "errorWithDomain:code:userInfo:",
                CFSTR("com.apple.devicecheck.cryptoerror"),
                0,
                ((__int64 (__fastcall *)(NSDictionary *))MEMORY[0x243ECC0A0])(
                  +[NSDictionary dictionaryWithObjects:forKeys:count:](
                    &OBJC_CLASS___NSDictionary,
                    "dictionaryWithObjects:forKeys:count:",
                    &v82,
                    &v81,
                    1)));
        v65 = ((__int64 (__fastcall *)(NSError *))MEMORY[0x243ECC0A0])(v64);
        v66 = MEMORY[0x243ECC130]();
        ((void (__fastcall *)(__int64))MEMORY[0x243ECC140])(v66);
        v37 = 0;
        v36 = v65;
      }
    }
    else
    {
      v61 = _DCLogSystem(v35);
      v62 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v61);
      v63 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v62, 0);
      if ( (_DWORD)v63 )
      {
        *(_WORD *)__str = 0;
        v63 = ((__int64 (__fastcall *)(int *, __int64, _QWORD, const char *, char *, __int64))MEMORY[0x243ECBE60])(
                &dword_24150F000,
                v62,
                0,
                "Using device timestamp...",
                __str,
                2);
      }
      ((void (__fastcall *)(__int64))MEMORY[0x243ECC120])(v63);
      v37 = v15 & 1;
    }
  }
  else
  {
    v10 = 0;
    v37 = 0;
    v36 = v8;
  }
  v38 = a2;
  if ( a2 )
    v38 = ((__int64 (*)(void))unk_243ECBD30)();
  v39 = _DCLogSystem(v38);
  v40 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC0A0])(v39);
  v41 = v40;
  if ( v37 )
  {
    v42 = ((__int64 (__fastcall *)(__int64, _QWORD))MEMORY[0x243ECC2A0])(v40, 0);
    if ( (_DWORD)v42 )
    {
      v43 = objc_msgSend(v10, "length");
      *(_DWORD *)__str = 134217984;
      *(_QWORD *)&__str[4] = v43;
      v42 = ((__int64 (*)(int *, __int64, _QWORD, const char *, ...))MEMORY[0x243ECBE60])(
              &dword_24150F000,
              v41,
              0,
              "Certificate processed... (%lu)",
              v72);
    }
    ((void (__fastcall *)(__int64))MEMORY[0x243ECC120])(v42);
    v44 = (*(__int64 (__fastcall **)(_QWORD, void *, void *))(*(_QWORD *)(a1 + 40) + 16LL))(
            *(_QWORD *)(a1 + 40),
            objc_msgSend(v10, "copy"),
            objc_msgSend(v75, "copy"));
    v45 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC160])(v44);
  }
  else
  {
    if ( (unsigned int)((__int64 (__fastcall *)(__int64, __int64))MEMORY[0x243ECC2A0])(v40, 16) )
      __66__DCCertificateGenerator__generateCertificateChainWithCompletion___block_invoke_cold_1(v36, v41);
    MEMORY[0x243ECC120]();
    v45 = (*(__int64 (__fastcall **)(_QWORD, _QWORD, void *))(*(_QWORD *)(a1 + 40) + 16LL))(
            *(_QWORD *)(a1 + 40),
            0,
            objc_msgSend(v75, "copy"));
  }
  v46 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC120])(v45);
  v47 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC110])(v46);
  v48 = ((__int64 (__fastcall *)(__int64))unk_243ECC190)(v47);
  v49 = ((__int64 (__fastcall *)(__int64))unk_243ECC170)(v48);
  v50 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC130])(v49);
  v51 = ((__int64 (__fastcall *)(__int64))MEMORY[0x243ECC150])(v50);
  result = (id)((__int64 (__fastcall *)(__int64))unk_243ECC180)(v51);
  if ( v97 != 0x8FCA7F6773E200E4LL )
  {
    v67 = (DCCertificateGenerator *)((__int64 (__fastcall *)(id))unk_243ECBE30)(result);
    return -[DCCertificateGenerator _encryptData:serverSyncedDate:error:](v67, v68, v69, v70, v71);
  }
  return result;
}

将组合后的两个激活证传给加密方法

  • 搜索“Encrypting data...”定位关键加密算法。
id __fastcall -[DCCertificateGenerator _encryptData:serverSyncedDate:error:](id *a1, __int64 a2, void *a3, void *a4)
{
  id v6; // x21
  __int64 v7; // x0
  NSObject *v8; // x19
  void *v9; // x19
  void *v10; // x20
  unsigned int v11; // w27
  const void *v12; // x28
  unsigned int v13; // w25
  id v14; // x21
  const void *v15; // x19
  __int64 v16; // x23
  size_t v17; // x24
  _DWORD *v18; // x0
  _DWORD *v19; // x22
  char *v20; // x23
  void *v21; // x27
  void *v22; // x0
  __int64 v23; // d0
  __int64 v24; // x0
  NSObject *v25; // x19
  __int64 v26; // x8
  __int64 v27; // x0
  __int64 v28; // x19
  __int64 v29; // x0
  NSObject *v30; // x24
  __int64 v31; // x0
  void *v32; // x25
  _OWORD *public_key_1; // x0
  __int128 v34; // q0
  __int128 v35; // q1
  __int128 v36; // q2
  __int64 i; // x20
  __int64 v38; // x0
  __int64 v39; // x19
  __int64 v40; // x0
  __int64 v41; // x0
  char *v43; // x19
  __int64 v44; // x20
  unsigned __int8 *v45; // x25
  int v46; // t1
  __int64 v47; // x0
  __int64 v48; // x19
  __int64 v49; // x0
  __int64 v50; // x0
  __int64 v51; // x25
  __int64 v52; // x0
  __int64 v53; // x0
  __int64 v54; // [xsp+28h] [xbp-D8h]
  id v55; // [xsp+30h] [xbp-D0h]
  id v56; // [xsp+38h] [xbp-C8h]
  size_t __n; // [xsp+40h] [xbp-C0h] BYREF
  __int64 v58; // [xsp+48h] [xbp-B8h] BYREF
  void *v59; // [xsp+50h] [xbp-B0h] BYREF
  __int64 v60; // [xsp+58h] [xbp-A8h] BYREF
  uint8_t v61[4]; // [xsp+60h] [xbp-A0h] BYREF
  __int64 time; // [xsp+64h] [xbp-9Ch]
  uint8_t buf[16]; // [xsp+70h] [xbp-90h] BYREF
  _DWORD v64[8]; // [xsp+80h] [xbp-80h] BYREF
  __int64 vars8; // [xsp+108h] [xbp+8h]

  v6 = objc_retain(a3);
  v56 = objc_retain(a4);
  v7 = _DCLogSystem(v56);
  v8 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v7);
  if ( os_log_type_enabled_1518(v8, OS_LOG_TYPE_DEFAULT) )
  {
    *(_WORD *)buf = 0;
    _os_log_impl_1398(&dword_446A2E000, v8, OS_LOG_TYPE_DEFAULT, "Encrypting data...", buf, 2u);
  }
  objc_release(v8);
  v9 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(a1[2], "clientAppID"));
  v10 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(v9, "dataUsingEncoding:", 4));
  objc_release(v9);
  v11 = (unsigned int)objc_msgSend(v10, "length");
  v55 = objc_retainAutorelease(v10);
  v12 = objc_msgSend(v55, "bytes");
  v13 = (unsigned int)objc_msgSend(v6, "length");
  v14 = objc_retainAutorelease(v6);
  v15 = objc_msgSend(v14, "bytes");
  v59 = 0;
  v60 = 0;
  v58 = 0;
  v16 = ccaes_gcm_encrypt_mode_18();
  *(_OWORD *)buf = 0u;
  memset(v64, 0, 28);
  v17 = v13 + v11 + 235LL;
  v18 = j__calloc_516(1u, v17);
  v19 = v18;
  if ( v18 )
  {
    v54 = v16;
    *(_DWORD *)((char *)v18 + 150) = v13 + v11 + 81;
    *v18 = 2;
    j__memcpy_1002(v18 + 5, objc_msgSend(a1[1], "bytes"), (size_t)objc_msgSend(a1[1], "length"));
    v20 = (char *)j__calloc_516(1u, *(unsigned int *)((char *)v19 + 150));
    *(_DWORD *)(v20 + 73) = v13;
    j__memcpy_1002(v20 + 81, v15, v13);
    *(_DWORD *)(v20 + 77) = v11;
    j__memcpy_1002(&v20[*(unsigned int *)(v20 + 73) + 81], v12, v11);
    v21 = v56;
    v22 = objc_msgSend(v56, "timeIntervalSince1970");
    *(_QWORD *)(v20 + 65) = v23;
    v24 = _DCLogSystem(v22);
    v25 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v24);
    if ( os_log_type_enabled_1518(v25, OS_LOG_TYPE_DEFAULT) )
    {
      v26 = *(_QWORD *)(v20 + 65);
      *(_DWORD *)v61 = 134217984;
      time = v26;
      _os_log_impl_1398(&dword_446A2E000, v25, OS_LOG_TYPE_DEFAULT, "Token timestamp: %f", v61, 0xCu);
    }
    objc_release(v25);
    v27 = aks_ref_key_create_1(objc_msgSend(a1, "keybagHandle"), 11, 4, 0, 0, &v60);
    if ( (_DWORD)v27 )
    {
      v28 = v27;
      v29 = _DCLogSystem(v27);
      v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v29);
      if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
        -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.6(v28, v30);
LABEL_20:
      v32 = 0;
      goto LABEL_21;
    }
    __n = 0;
    public_key_1 = (_OWORD *)aks_ref_key_get_public_key_1(v60, &__n);
    if ( __n != 65 )
    {
      v41 = _DCLogSystem(public_key_1);
      v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v41);
      if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
        -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.5(&__n, v30);
      goto LABEL_20;
    }
    *(_OWORD *)((char *)v19 + 85) = *public_key_1;
    v34 = public_key_1[1];
    v35 = public_key_1[2];
    v36 = public_key_1[3];
    *((_BYTE *)v19 + 149) = *((_BYTE *)public_key_1 + 64);
    *(_OWORD *)((char *)v19 + 133) = v36;
    *(_OWORD *)((char *)v19 + 117) = v35;
    *(_OWORD *)((char *)v19 + 101) = v34;
    j__memcpy_1002(v20, public_key_1, __n);
    j__printf_200("%-25.25s = ", "random_pubkey");
    for ( i = 85; i != 150; ++i )
      j__printf_200("%02x", *((unsigned __int8 *)v19 + i));
    putchar_75(10);
    v38 = aks_ref_key_compute_key_0(v60, 0, 0, objc_msgSend(a1[1], "bytes"), objc_msgSend(a1[1], "length"), &v59, &v58);
    if ( (_DWORD)v38 )
    {
      v39 = v38;
      v40 = _DCLogSystem(v38);
      v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v40);
      if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
        -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.4(v39, v30);
      goto LABEL_20;
    }
    v43 = (char *)v59;
    v44 = v58 - 2;
    j__printf_200("%-25.25s = ", "ECDH shared key");
    if ( v44 )
    {
      v45 = (unsigned __int8 *)(v43 + 2);
      do
      {
        v46 = *v45++;
        j__printf_200("%02x", v46);
        --v44;
      }
      while ( v44 );
    }
    putchar_75(10);
    v47 = cchkdf_19(&ccsha256_ltc_di, v58 - 2, (char *)v59 + 2, 0, 0, 0, 0, 44, buf);
    if ( (_DWORD)v47 )
    {
      v48 = v47;
      v49 = _DCLogSystem(v47);
      v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v49);
      if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
        -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.3(v48, v30);
      goto LABEL_20;
    }
    hex_2((std::ios_base *)"HKDF derived key");
    hex_2((std::ios_base *)"HKDF derived iv");
    v50 = ccgcm_one_shot_10(
            v54,
            32,
            buf,
            12,
            &v64[4],
            0,
            0,
            *(unsigned int *)((char *)v19 + 150),
            v20,
            (char *)v19 + 154,
            16,
            v19 + 1);
    if ( (_DWORD)v50 )
    {
      v51 = v50;
      v52 = _DCLogSystem(v50);
      v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v52);
      if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
        -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.2(v51, v30);
      goto LABEL_20;
    }
    hex_2((std::ios_base *)"tag");
    j__fprintf_285((FILE *)__stderrp_0, "encrypted_data_len: %d\n", *(_DWORD *)((char *)v19 + 150));
    v32 = (void *)objc_claimAutoreleasedReturnValue_1330(objc_msgSend(&OBJC_CLASS___NSData, "dataWithBytes:length:", v19, v17));
    v53 = _DCLogSystem(v32);
    v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v53);
    _DCLogDebugBinary_0(v30, CFSTR("Token"), v32);
  }
  else
  {
    v31 = _DCLogSystem(0);
    v30 = (NSObject *)objc_claimAutoreleasedReturnValue_1330(v31);
    if ( os_log_type_enabled_1518(v30, OS_LOG_TYPE_ERROR) )
      -[DCCertificateGenerator _encryptData:serverSyncedDate:error:].cold.1(v30);
    v20 = 0;
    v32 = 0;
    v21 = v56;
  }
LABEL_21:
  objc_release(v30);
  if ( v60 )
    aks_ref_key_free_1(&v60);
  if ( v19 )
    j__free_1273(v19);
  if ( v20 )
    j__free_1273(v20);
  if ( v59 )
    j__free_1273(v59);
  objc_release(v55);
  objc_release(v21);
  objc_release(v14);
  if ( ((vars8 ^ (2 * vars8)) & 0x4000000000000000LL) != 0 )
    __break(0xC471u);
  return objc_autoreleaseReturnValue(v32);
}

这个方法用 Secure Enclave 生成一个临时 EC 密钥 → 和服务器公钥做 ECDH → HKDF 派生 AES-256-GCM key+IV →把「[ephemeral 公钥 + 时间戳 + 激活证书 + appID]」打包加密 → 和各种公钥 / 长度 / tag 一起封装成 Token。流程如下:

8

8

4.2 加密算法流程

整个加密流程是一个变种的 ECIES (Elliptic Curve Integrated Encryption Scheme),具体步骤如下:

Payload 构建: 系统将 App ID (如 com.example.app)、设备证书链(包含 App Attest 证书和 Device CA 证书)以及 时间戳 拼接成一段二进制数据。

硬件密钥生成 (AKS): 调用私有 API aks_ref_key_create。这一步是在 Secure Enclave (SE) 安全芯片内部生成一个临时的 P-256 椭圆曲线密钥对。

  • 关键点:私钥 (Private Key) 永远停留在硬件安全区内,外部无法读取,只能通过句柄引用。

ECDH 密钥协商: 调用 aks_ref_key_compute_key。系统使用刚才生成的硬件临时私钥,与代码中硬编码的 Apple 服务器公钥 进行 ECDH (Elliptic-curve Diffie–Hellman) 运算,计算出一个 共享密钥 (Shared Secret)

HKDF 密钥派生: 调用 cchkdf (基于 HMAC 的密钥派生函数)。使用共享密钥作为输入,派生出用于后续对称加密的 AES 密钥IV (初始化向量)

AES-GCM 加密: 调用 ccgcm_one_shot。使用派生出的 AES 密钥,采用 AES-GCM 模式对第一步构建的 Payload 进行加密。GCM 模式不仅加密数据,还生成一个 Tag (认证标签),用于防止数据被篡改。

最终封装: 最终的 Token 结构大致为:

#pragma pack(push, 1)
typedef struct {
    uint8_t  ec_pubkey[65];   // 04 + X(32) + Y(32)
    double   timestamp;       // 小端 double
    uint32_t cert_len;        // 激活证书pme
    uint32_t bundle_len;      // app包名长度
    // 下面是可变部分:
    uint8_t cert_pem[cert_len];
    char    bundle[bundle_len]; // "xxC6HB646H.com.beeasy.xxopee.xx"
} TokenPlainHeader;
#pragma pack(pop)

4.3 算法还原及为什么不建议生成纯算法?

  • 还原算法
import base64
import time
import struct
from typing import Tuple

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF

class DeviceCheckTokenBuilder:
    *"""*
*    - server_pub: 固定“服务器公钥”(65 字节,0x04 开头)*
*    - ephemeral_pub: 固定“设备临时公钥”(65 字节,0x04 开头)*
*    - ikm: 固定的“ECDH shared secret”*
*    - AES key / IV 通过 HKDF(SHA256, L=44) 从 IKM 导出*
*    """*

*    *def __init__(self):
        # ==== 1. 固定服务器公钥 // fallback_server_pubkey ====
        self.server_pub = bytes.fromhex(
            "04 50 D9 34 FA 67 BC F6 F2 DF BF 96 62 9E 0A 72"
            " 38 E9 20 5D 75 F2 8C FC D8 4F 35 A6 59 2B BE 05"
            " 8A 9C 0F 8E DB CA 2A CB 67 EF B7 74 97 1C A4 5F"
            " 7D 85 6A 69 4F B1 B9 C4 0B 94 FB 2E 7A 5A 94 98"
            " B0"
        )

        # ==== 2. 固定设备临时公钥 _aks_ref_key_get_public_key_1 ====
        self.ephemeral_pub = bytes.fromhex(
            "04 79 5B C4 54 FF 9D 34 1E D8 11 CE CC"
            " 73 C4 AF 32 1E 81 27 6D A0 BE F0 BF F6 B5 D6 3C"
            " 5B AC 9F 09 2D 45 90 1B 6C A1 DA BF D9 8B 63 EF"
            " 7E 3B 9D 14 3D 14 4D FE 70 85 7C 0A 4E 07 88 40"
            " 4F 92 87 D0"
        )

        # ==== 3. 固定 IKM(ECDH shared secret)====
        self.ikm = bytes.fromhex(
            "fe3cb482384079c224225f476244d7c7"
            "4031a41bf09ea60e27f9ede0861bf42e"
        )

        # 通过 HKDF 推导 AES key & IV(仿 cchkdf_19)
        self.aes_key, self.aes_iv = self._hkdf_derive_key_iv(self.ikm)

    # ------------------ 核心加密相关 ------------------ #

    @staticmethod
    def _hkdf_derive_key_iv(ikm: bytes) -> Tuple[bytes, bytes]:
        *"""*
*        从 IKM 导出 44 字节 OKM,前 32 字节做 AES key,后 12 字节做 GCM IV*
*        相当于:*
*          cchkdf_19(sha256, ikm, outLen=44, salt=NULL, info=NULL)*
*        """*
*        *hkdf = HKDF(
            algorithm=hashes.SHA256(),
            length=44,
            salt=None,
            info=None,
        )
        okm = hkdf.derive(ikm)
        key = okm[:32]
        iv = okm[32:44]
        return key, iv

    @staticmethod
    def _gcm_encrypt(plaintext: bytes, key: bytes, iv: bytes) -> Tuple[bytes, bytes]:
        *"""*
*        AES-GCM 加密:*
*        返回 (ciphertext_without_tag, tag_16B)*
*        """*
*        *aesgcm = AESGCM(key)
        ct_with_tag = aesgcm.encrypt(iv, plaintext, None)
        tag = ct_with_tag[-16:]
        ciphertext_only = ct_with_tag[:-16]
        return ciphertext_only, tag

    def build_dc_token(
        self,
        appname: str = None,
        appcert: str = None,
        devicecert: str = None,
    ) -> str:
        *"""*

*        Token Layout:*
*          u32  version = 2*
*          u8   tag[16]*
*          u8   server_pub[65]*
*          u8   ephemeral_pub[65]*
*          u32  ciphertext_len*
*          u8   ciphertext[ciphertext_len]*
*        """*

*        *# ---- 1. 默认 appname / 证书 ---- #
        if appname is None:
            appname = "T7C6HB646H.com.beeasy.shoppe.tw"

        if appcert is None:
            appcert = """-----BEGIN CERTIFICATE-----
MIIDJjCCAsugAwIBAgIGAZrJqz2xMAoGCCqGSM49BAMCMFMxJzAlBgNVBAMMHkJh
c2ljIEF0dGVzdGF0aW9uIFVzZXIgU3ViIENBMTETMBEGA1UECgwKQXBwbGUgSW5j
LjETMBEGA1UECAwKQ2FsaWZvcm5pYTAeFw0yNTExMjcwODUzNTRaFw0yNjEwMTQx
ODIwNTRaMIGRMUkwRwYDVQQDDEBiNjdjMGY3ZWM4OWJiOTZlZmU3ZGY5OTIzNDVl
NDIxNjdiMjU3ODQyZGQyZWM5MjdkZjE5MWVjYmQwYzM0YmI5MRowGAYDVQQLDBFC
QUEgQ2VydGlmaWNhdGlvbjETMBEGA1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwK
Q2FsaWZvcm5pYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKoJsFk1GR/rs/Jj
+3iFqwYNnMZCB/0/s40hCTNSr5iooEkoAg8Apue/liWQrcVLYvknsfpRDZ74cKnp
cRI/8+ejggFKMIIBRjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DCCASQG
CSqGSIb3Y2QKAQSCARUEggERMYIBDf+EmqGSUA0wCxYEQ0hJUAIDAIEQ/4SqjZJE
ETAPFgRFQ0lEAgcYaaI8ICAe/4SSvaRECzAJFgRCT1JEAgEY/4aTtcJjGzAZFgRi
bWFjBBFhYzoxNjoxNTo2ZDphNToxZf+Gy7XKaRkwFxYEaW1laQQPMzU2MTI0NzE1
MDY4NTU1/4erkdJkIzAhFgR1ZGlkBBkwMDAwODExMC0wMDE4NjlBMjNDMjAyMDFF
/4e7tcJjGzAZFgR3bWFjBBFhYzoxNjoxNTo3OTo4ZTpmZf+Hm5XSZDowOBYEc2Vp
ZAQwMDQyRDI3QzU4QTE2OTAwMjIzMzIwMTMxNzI0MDUyMjRGRDE3MkZCRUQxM0VF
QzdCMAoGCCqGSM49BAMCA0kAMEYCIQCytP7jpU3xbaRHvXyvqCcum2F/kkDBSv1x
/RFAUXLJQwIhALeFnzR9R9BFlTjLS+nql3Cb6FqxywwJfCvf9v+JJTJl
-----END CERTIFICATE-----"""

        if devicecert is None:
            devicecert = """-----BEGIN CERTIFICATE-----
MIICIzCCAaigAwIBAgIIeNjhG9tnDGgwCgYIKoZIzj0EAwIwUzEnMCUGA1UEAwwe
QmFzaWMgQXR0ZXN0YXRpb24gVXNlciBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTE3MDQyMDAwNDIwMFoXDTMyMDMy
MjAwMDAwMFowUzEnMCUGA1UEAwweQmFzaWMgQXR0ZXN0YXRpb24gVXNlciBTdWIg
Q0ExMRMwEQYDVQQKDApBcHBsZSBJbmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoSZ/1t9eBAEVp5a8PrXacmbGb8zNC1X3
StLI9YO6Y0CL7blHmSGmjGWTwD4Q+i0J2BY3+bPHTGRyA9jGB3MSbaNmMGQwEgYD
VR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBSD5aMhnrB0w/lhkP2XTiMQdqSj
8jAdBgNVHQ4EFgQU5mWf1DYLTXUdQ9xmOH/uqeNSD80wDgYDVR0PAQH/BAQDAgEG
MAoGCCqGSM49BAMCA2kAMGYCMQC3M360LLtJS60Z9q3vVjJxMgMcFQ1roGTUcKqv
W+4hJ4CeJjySXTgq6IEHn/yWab4CMQCm5NnK6SOSK+AqWum9lL87W3E6AA1f2TvJ
/hgok/34jr93nhS87tOQNdxDS8zyiqw=
-----END CERTIFICATE-----"""

        # ---- 2. 拼接证书 + appname ---- #
        cert_bytes = bytearray()
        cert_bytes.extend(appcert.encode("utf-8"))
        cert_bytes.append(0x0A)  # 额外换行
        cert_bytes.extend(devicecert.encode("utf-8"))

        app_bytes = appname.encode("utf-8")

        cert_len = len(cert_bytes)
        app_len = len(app_bytes)

        # ---- 3. 构造明文 ---- #

        # ---- 4. AES-GCM 加密(key/iv 来自 HKDF) ---- #

        # ---- 5. 组装最终 Token ---- #
        result = bytearray()
        result.extend(struct.pack("<I", 2))      # version = 2 (小端 u32)
        result.extend(tag)                       # 16B tag
        result.extend(self.server_pub)           # 服务器公钥
        result.extend(self.ephemeral_pub)        # 设备临时公钥
        result.extend(struct.pack("<I", len(ciphertext)))
        result.extend(ciphertext)

        # Base64 输出
        return base64.b64encode(bytes(result)).decode("ascii")

if __name__ == "__main__":
    builder = DeviceCheckTokenBuilder()
    token = builder.build_dc_token()
    print("Demo DC Token (base64):")
    print(token)
  • 不建议生成纯算法原因在于:私钥不可导出。 我们在外部代码中只能看到 Apple 的公钥,但无法获取在那一瞬间硬件生成的临时私钥。没有私钥,就无法在外部环境中计算出与硬件一致的 ECDH 共享密钥,也就无法生成能被 Apple 服务器解密的 Token,写死一份是有风险的,不确定Apple服务器端是否有检测。RPC调用可能真实性会更高一些。

4.4 证书替换的可行性分析

除了伪造 ID,我们还可以通过 Hook _encryptData 的入参来伪造设备信息生成我们想要的token

  • 伪造证书

    • 逆向分析发现 _encryptDatadata 参数本质上是 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 -> PEM
            var derRef = SecCertificateCopyData(certRef);
            var derObj = cfToObj(derRef);
            if (derObj) {
                printPemFromDerNSData(derObj);
            } else {
                console.log("[!] SecCertificateCopyData failed");
            }
            if (derRef && !derRef.isNull()) CFRelease(derRef);
    
            // 3. 详细 values(如果符号存在)
            if (SecCertificateCopyValues) {
                var valuesRef = SecCertificateCopyValues(certRef, NULL, NULL);
                var valuesObj = cfToObj(valuesRef);
                if (valuesObj) {
                    console.log("Values (raw NSDictionary):");
                    console.log("  " + valuesObj.toString());
                } else {
                    console.log("[!] SecCertificateCopyValues returned NULL");
                }
                if (valuesRef && !valuesRef.isNull()) CFRelease(valuesRef);
            } else {
                console.log("Values : <SecCertificateCopyValues unavailable>");
            }
    
            console.log("========== [END] ==========\n");
        }
    
        // ====== Hook DCCertificateGenerator ======
        console.log("\n Script Loaded. Waiting...");
    
        try {
            var className  = "DCCertificateGenerator";
            var methodName = "- _encryptData:serverSyncedDate:error:";
    
            if (!ObjC.classes[className]) {
                console.error("[-] Class " + className + " not found");
                return;
            }
            if (!ObjC.classes[className][methodName]) {
                console.error("[-] Method " + methodName + " not found on " + className);
                return;
            }
    
            var hook = ObjC.classes[className][methodName];
    
            Interceptor.attach(hook.implementation, {
                onEnter: function (args) {
                    console.warn("\n[+] 🟢 Intercepted Encryption Request");
    
                    // args[2] = _encryptData:  (NSData*)
                    var dataObj = cfToObj(args[2]);
                    if (!dataObj) {
                        console.log("  [Payload Info] dataObj is NULL or invalid");
                        return;
                    }
    
                    var len = dataObj.length();
                    console.log("  [Payload Info] Raw Length: " + len + " bytes");
    
                    // 先直接当 DER 证书试
                    var certRef = SecCertificateCreateWithData(NULL, dataObj.handle);
    
                    if (!certRef.isNull()) {
                        printCertDetail(certRef, "Original (DER)");
                        CFRelease(certRef);
                    } else {
                        console.log("  [Info] SecCertificateCreateWithData failed, trying PEM path...");
    
                        var pemStrObj = ObjC.classes.NSString
                            .alloc()
                            .initWithData_encoding_(dataObj, 4); // UTF8
    
                        if (pemStrObj) {
                            var strContent = pemStrObj.toString();
    
                            if (strContent.indexOf("BEGIN CERTIFICATE") !== -1) {
                                console.log("  [Original Cert] Format: PEM (Base64 Text)");
    
                                var matches = strContent.match(/-----BEGIN CERTIFICATE-----([\s\S]+?)-----END CERTIFICATE-----/g);
                                if (matches) {
                                    for (var i = 0; i < matches.length; i++) {
                                        var block = matches[i];
                                        var cleanBase64 = block
                                            .replace(/-----BEGIN CERTIFICATE-----/g, "")
                                            .replace(/-----END CERTIFICATE-----/g, "")
                                            .replace(/[\r\n]/g, "");
    
                                        var derData = ObjC.classes.NSData
                                            .alloc()
                                            .initWithBase64EncodedString_options_(cleanBase64, 0);
    
                                        if (derData) {
                                            var certRef2 = SecCertificateCreateWithData(NULL, derData.handle);
                                            if (!certRef2.isNull()) {
                                                printCertDetail(certRef2, "Parsed PEM Cert #" + (i + 1));
                                                CFRelease(certRef2);
                                            } else {
                                                console.log("  [Parsed PEM Cert #" + (i + 1) + "] ❌ SecCertificateCreateWithData failed");
                                            }
                                        } else {
                                            console.log("  [Parsed PEM Cert #" + (i + 1) + "] ❌ initWithBase64EncodedString failed");
                                        }
                                    }
                                } else {
                                    console.log("  [Original Cert] PEM markers found but no blocks matched");
                                }
                            } else {
                                console.log("  [Original Cert] Format: Unknown Binary / Non-PEM text");
                            }
                        } else {
                            console.log("  [Original Cert] Cannot decode as UTF-8 string");
                        }
                    }
                },
    
                onLeave: function (retval) {
                    if (retval.isNull()) {
                        console.log("[+] Return value is NULL");
                        return;
                    }
    
                    try {
                        var retObj = new ObjC.Object(retval);
                        var clsName = retObj.$className || "<unknown>";
                        console.log("[+] Return ObjC class: " + clsName);
    
                        if (retObj.isKindOfClass_(ObjC.classes.NSData)) {
                            // 返回 NSData(大概率是加密后的 token)
                            dumpNSData(retObj, "Return NSData", 256);
                        } else if (retObj.isKindOfClass_(ObjC.classes.NSString)) {
                            console.log("[+] Return NSString:");
                            console.log("    " + retObj.toString());
                        } else {
                            console.log("[+] Return object description:");
                            console.log("    " + retObj.toString());
                        }
                    } catch (e) {
                        console.log("[!] onLeave: cannot wrap retval as ObjC.Object -> " + e.message);
                    }
                }
            });
    
            console.log(" Hook Success");
        } catch (e) {
            console.error("[!] Hook Error: " + e.message);
        }
    })();
    
    // frida -U -n devicecheckd -l devicecheckd1.js

五、在爬虫 / 群控场景中的实战应用

在理解了底层加密原理和 基本流程后,我们需要将视角拉回到业务对抗的一线。在黑灰产(爬虫方)与风控(防守方)的博弈中,DeviceCheck 不仅仅是一个 API,而是判定设备“生死”的判官。

5.1、爬虫方怎么用真机 + DeviceCheck 规避风控”

由于 DeviceCheck 的核心密钥(ECDH 协商用的临时私钥)被锁在 Secure Enclave 硬件中,纯算法还原(脱机算法)的路径已被彻底堵死。目前的黑灰产已全面转向“真机群控”“底层 Hook”相结合的模式。

“借尸还魂”:证书与身份的批量伪造

攻击者建立一个庞大的“白名单设备库”,这些设备是真实存在的、干净的 iPhone。

  • 采集阶段:使用越狱设备或硬改工具,批量提取白名单设备的 Device Certificate (PEM) 和 UniqueChipID 等硬件指纹。

  • 攻击阶段:在被封禁的设备(或专门用于攻击的“脏”设备)上运行 Frida 脚本(如我们之前编写的脚本)。

  • 运行时篡改

    • Hook devicecheckd 进程。

    • 在生成 Token 前,将内存中的“脏证书”替换为采集来的“白证书”。

    • 核心突破:虽然硬件签名(SE)使用的是脏设备的私钥,但只要 Hook 了 DCContext 伪造 AppID,生成的 Token 在逻辑格式上是合法的。

    “RPC 签名节点”:群控架构的演进

    为了规模化作业,攻击者不再在每台手机上跑业务逻辑,而是将其改造为签名节点

    • 架构

      • 服务器端爬虫:负责跑业务逻辑(HTTP 请求),遇到需要 DeviceToken 的接口时,向手机发送 RPC 请求。

      • 手机端(Agent):运行在后台,接收 RPC 指令,调用 DCDevice 生成 Token(配合上述的 Hook 伪造策略),然后将 Token 返回给服务器端

    • 优势:一台真机可以为十几个线程提供签名服务,极大地降低了硬件成本。

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)代表了移动安全领域的一个重要转折点:从“软件对抗”走向“硬件对抗”

通过本次逆向分析,我们得出以下核心结论:

  1. 硬件是信任的基石:DeviceCheck 的不可伪造性完全依赖于 Secure Enclave。私钥不出安全区,使得纯软件层面的算法还原(如 Python 脚本生成 Token)在理论上和工程上都成为不可能。

  2. 攻防的不对称性

    • 攻击者不得不通过昂贵的真机群控、复杂的系统级 Hook(注入 devicecheckd)以及硬改(更换基带/闪存芯片/激活证书)来绕过防护,成本呈指数级上升。

    • 防守方只需在服务端接入 Apple 的验证 API,并制定合理的 2-bit 状态标记策略,即可获得一个难以被清洗的设备指纹。

  3. 未来的趋势:随着 Apple 在 iOS 14+ 引入 DCAppAttestService,将密钥的绑定粒度从“设备”细化到了“设备 + App 实例”,并且支持对关键业务数据(Assertion)进行签名。这意味着未来的风控将更加精准,留给黑灰产“撞库”和“伪造”的空间将进一步被压缩。

对于安全从业者而言,理解 DeviceCheck 的底层逻辑,不仅有助于在红蓝对抗中制定更有效的策略,也提醒我们:在零信任架构下,基于硬件的可信证明(Hardware-backed Attestation)将是移动端身份认证的终极解决方案。

参考资料:

https://bbs.kanxue.com/thread-281819.htm

https://iosre.com/t/%E8%BD%AC%E8%BD%BD%E6%9F%90dd%E6%9F%90%E9%9F%B3-ios-devicecheck-token-%E6%AD%A3%E5%90%91%E7%A0%94%E5%8F%91%E4%B8%8E%E9%80%86%E5%90%91%E5%88%86%E6%9E%90%E4%B9%8B%E8%B7%AF%E6%80%9D%E8%80%83/24569/1

致谢: yuzhouheike  addhaloka 感谢两位大佬提供的指导与帮助

免费评分

参与人数 19吾爱币 +18 热心值 +18 收起 理由
lili1100 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
submarine1620 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
冰凌寒露 + 1 + 1 膜拜大佬
GFGWin + 1 + 1 用心讨论,共获提升!
shiyue2925 + 1 + 1 谢谢@Thanks!
Wyiyun777 + 1 + 1 我很赞同!
yt13299374849 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Euclair + 1 + 1 感谢分享!
yixi + 1 + 1 谢谢@Thanks!
111mz + 1 + 1 热心回复!
westlifehonda + 1 + 1 谢谢@Thanks!
fengbolee + 1 + 1 谢谢@Thanks!
springlu + 1 我很赞同!
grtiancheng478 + 1 + 1 用心讨论,共获提升!
xieyulei + 1 + 1 用心讨论,共获提升!
ioyr5995 + 1 + 1 热心回复!
allspark + 1 + 1 用心讨论,共获提升!
kspz + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
buluo533 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xxc99 发表于 2026-6-25 13:40
从软件到硬件,学习,
kspz 发表于 2026-6-24 21:46
感谢分享.在零信任架构下,基于硬件的可信证明(Hardware-backed Attestation)将是移动端身份认证的终极解决方案
wupeiwupei 发表于 2026-6-24 18:00
autumoon 发表于 2026-6-24 18:42
感谢分享,所以说在我们看不到的地方,也有很多努力,保证了设备本身的安全以及防止黑灰产的泛滥
JackeyLoveONE 发表于 2026-6-24 21:17
解决不了Secure Enclave,必须要走真机签名
JackeyLoveONE 发表于 2026-6-24 21:18
JackeyLoveONE 发表于 2026-6-24 21:17
解决不了Secure Enclave,必须要走真机签名

登录绑定keyid,一台机子只能签名一个
loopg 发表于 2026-6-24 22:49
牛,这文章知识点太多,我感觉我像个小学生在看大学论文!
cnggmm 发表于 2026-6-24 23:22
拜见大佬,小白看不懂
alien0774 发表于 2026-6-25 10:11
不明觉厉,拜服
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-22 03:54

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表