zoukankan      html  css  js  c++  java
  • 某虚拟定位APP从破解到原理分析

    工具环境
    ida7.0
    iphone 6
    ios 10.2

    0x00:基本情况

    1. 该app可以修改模拟手机地理位置(gps、基站、WIFI),拥有全局定位、指定应用定位、模拟扫街等功能,只能在已越狱的IOS系统上使用,安装须要用到Cydia,安装后主要分为插件与主程序两个部分,主程序负责与用户交互,插件主要实现了修改地理位置的功能。在Cydia插件安装目录可以找到它释放的xxtweak.dylib文件,拷贝出来后面做详细分析。

    2. 程序运行后如果不是vip用户是不能使用修改定位的功能,如下:

    0x01:保护机制分析

    1. 将手机设置好代理,启动app登录,用抓包工具获取数据包做分析,发送到服务器的数据与服务器返回的数据都是加密的,如下图:

    2. 通过动态调试主app来寻找突破口,主app通过sysctl来做反调试,先编写一个tweak来过掉反调试。这个代码网上很多,如下:

    static int (*orig_sysctl)(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize);
    static int my_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize){
        int ret = orig_sysctl(name,namelen,info,infosize,newinfo,newinfosize);
        if(namelen == 4 && name[0] == 1 && name[1] == 14 && name[2] == 1){
            struct kinfo_proc *info_ptr = (struct kinfo_proc *)info;
            if(info_ptr && (info_ptr->kp_proc.p_flag & P_TRACED) != 0){
                NSLog(@"[AntiAntiDebug] - sysctl query trace status.");
                info_ptr->kp_proc.p_flag ^= P_TRACED;
                if((info_ptr->kp_proc.p_flag & P_TRACED) == 0){
                    NSLog(@"[AntiAntiDebug] trace status reomve success!");
                }
            }
        }
        return ret;
    }

    3. 将app放入ida中反编,用登录抓包获取到的信息中关键字来查找字符串定位到组合参数的地方,组合后格式如下:

    {
        "data":"{
    "clientid":"4092f7a187943eff48d1c4b827b5f53c",
    "username":"xxxxx",//用户名
    "password":"xxxxxx"//密码
    }",
        "header":{
            "uptime":"1540607913",
            "sysapi":"10.2",
            "model":"iPhone 6",
            "systype":"1",
            "vercode":"15.13",
            "uuid":"DA148217C2491937"
        }
    }

    然后将组合后的代码用AES加密发送到服务器代码如下:

    void __cdecl -[TXYUserInfoRequset loginUserwith:andPassword:andClientid:](TXYUserInfoRequset *self, SEL a2, id a3, id a4, id a5)
    {
      id v5; // x21
      id v6; // x20
      TXYUserInfoRequset *v7; // x22
      __int64 username; // x19
      __int64 v9; // x1
      __int64 passwrod; // x20
      __int64 v11; // x1
      __int64 v12; // x21
      void *url; // x0
      void *v14; // x0
      void *v15; // x0
      void *v16; // x24
      void *v17; // x0
      __int64 clientId; // x23
      void *v19; // x0
      const __CFString *v20; // x2
      struct objc_object *v21; // x0
      struct objc_object *v22; // ST28_8
      id v23; // x0
      __int64 v24; // ST20_8
      id v25; // x0
      void *v26; // x0
      void *v27; // x28
      void *v28; // x0
      __int64 v29; // x25
      void *v30; // x0
      struct objc_object *v31; // ST18_8
      id v32; // x0
      struct objc_object *info_json; // x0
      struct objc_object *v34; // x28
      id ret; // x0
      __int64 v36; // x21
      void *v37; // x0
      void *v38; // x26
      double v39; // d0
      void *v40; // x0
      __int64 v41; // x25
      void *v42; // x0
      struct objc_object *bodydata; // x24
      __int64 v44; // x1
      NSURLSessionTask *v45; // x0
      __int64 v46; // x0
      struct objc_object *httpurl; // [xsp+38h] [xbp-138h]
      void *v48; // [xsp+40h] [xbp-130h]
      int v49; // [xsp+48h] [xbp-128h]
      int v50; // [xsp+4Ch] [xbp-124h]
      __int64 (__fastcall *v51)(__int64, __int64); // [xsp+50h] [xbp-120h]
      void *v52; // [xsp+58h] [xbp-118h]
      __int64 v53; // [xsp+60h] [xbp-110h]
      const __CFString *body; // [xsp+68h] [xbp-108h]
      const __CFString *v55; // [xsp+70h] [xbp-100h]
      const __CFString *v56; // [xsp+78h] [xbp-F8h]
      const __CFString *v57; // [xsp+80h] [xbp-F0h]
      __int64 encdata; // [xsp+88h] [xbp-E8h]
      const __CFString *v59; // [xsp+90h] [xbp-E0h]
      const __CFString *v60; // [xsp+98h] [xbp-D8h]
      __int64 v61; // [xsp+A0h] [xbp-D0h]
      const __CFString *v62; // [xsp+A8h] [xbp-C8h]
      const __CFString *v63; // [xsp+B0h] [xbp-C0h]
      __int64 v64; // [xsp+B8h] [xbp-B8h]
      __int64 v65; // [xsp+C0h] [xbp-B0h]
      const __CFString *v66; // [xsp+C8h] [xbp-A8h]
      const __CFString *v67; // [xsp+D0h] [xbp-A0h]
      const __CFString *v68; // [xsp+D8h] [xbp-98h]
      __int64 username_1; // [xsp+E0h] [xbp-90h]
      __int64 passwrod_1; // [xsp+E8h] [xbp-88h]
      __int64 clientId_1; // [xsp+F0h] [xbp-80h]
      const __CFString *v72; // [xsp+F8h] [xbp-78h]
      const __CFString *v73; // [xsp+100h] [xbp-70h]
      __int64 v74; // [xsp+108h] [xbp-68h]
      __int64 v75; // [xsp+110h] [xbp-60h]
      __int64 v76; // [xsp+118h] [xbp-58h]
    
      v5 = a5;
      v6 = a4;
      v7 = self;
      v76 = -7228227847426539268LL;
      username = objc_retain(a3, a2);
      passwrod = objc_retain(v6, v9);
      v12 = objc_retain(v5, v11);
      if ( !username )
      {
        v20 = CFSTR("缺少用户名");
    LABEL_7:
        objc_msgSend(v7, (const char *)&MEMORY[0x19AEA7047], v20);
        clientId = v12;
        goto LABEL_10;
      }
      if ( !passwrod )
      {
        v20 = CFSTR("缺少密码");
        goto LABEL_7;
      }
      url = objc_msgSend(
              &MEMORY[0x1B559E398],
              (const char *)&MEMORY[0x1966A229A],
              CFSTR("%@%@"),
              CFSTR("http://ipay.txyapp.com:7658/api/entrance"),
              CFSTR("/111"));
      httpurl = (struct objc_object *)objc_retainAutoreleasedReturnValue(url);
      v14 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
      v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
      v16 = v15;
      v17 = objc_msgSend(v15, (const char *)&MEMORY[0x1966A8093], CFSTR("clientId"));
      clientId = objc_retainAutoreleasedReturnValue(v17);
      objc_release(v12);
      objc_release(v16);
      if ( clientId )
      {
        username_1 = username;
        v66 = CFSTR("username");
        v67 = CFSTR("password");
        passwrod_1 = passwrod;
        v68 = CFSTR("clientid");
        clientId_1 = clientId;
        v19 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &username_1, &v66, 3LL);
      }
      else
      {
        v72 = CFSTR("username");
        v73 = CFSTR("password");
        v74 = username;
        v75 = passwrod;
        v19 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &v74, &v72, 2LL);
      }
      v21 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v19);
      v22 = v21;
      v23 = ((id (__cdecl *)(TXYUserInfoRequset *, SEL, id))objc_msgSend)(v7, "convertToJSONData:", v21);
      v24 = objc_retainAutoreleasedReturnValue(v23);
      v62 = CFSTR("data");
      v63 = CFSTR("header");
      v64 = v24;
      v25 = ((id (__cdecl *)(DeviceAbout_meta *, SEL))objc_msgSend)(
              (DeviceAbout_meta *)&OBJC_CLASS___DeviceAbout,
              "sharedDevice");
      v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
      v27 = v26;
      v28 = objc_msgSend(v26, "getPublicPhone");
      v29 = objc_retainAutoreleasedReturnValue(v28);
      v65 = v29;
      v30 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &v64, &v62, 2LL);
      v31 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v30);
      objc_release(v29);
      objc_release(v27);
      v32 = ((id (__cdecl *)(TXYUserInfoRequset *, SEL, id))objc_msgSend)(v7, "convertToJSONData:", v31);
      info_json = (struct objc_object *)objc_retainAutoreleasedReturnValue(v32);
      v34 = info_json;
      ret = ((id (__cdecl *)(AES128_meta *, SEL, id, id))objc_msgSend)(// 加密参数
              (AES128_meta *)&OBJC_CLASS___AES128,
              "AES128Encrypt:withKey:",
              info_json,
              (id)CFSTR("Hz2Ywe8UBe@YfZ0*"));
      v36 = objc_retainAutoreleasedReturnValue(ret);
      encdata = v36;
      body = CFSTR("body");
      v55 = CFSTR("type");
      v59 = CFSTR("111");
      v56 = CFSTR("flag");
      v60 = CFSTR("4");
      v57 = CFSTR("t1");
      v37 = objc_msgSend(&MEMORY[0x1B5592FC0], (const char *)&MEMORY[0x1966B0E63]);
      v38 = (void *)objc_retainAutoreleasedReturnValue(v37);
      objc_msgSend(v38, (const char *)&MEMORY[0x19678A07E]);
      v40 = objc_msgSend(&MEMORY[0x1B559E398], (const char *)&MEMORY[0x1966A229A], CFSTR("%lld"), (signed __int64)v39);
      v41 = objc_retainAutoreleasedReturnValue(v40);
      v61 = v41;
      v42 = objc_msgSend(&MEMORY[0x1B5593128], (const char *)&MEMORY[0x1966A2036], &encdata, &body, 4LL);
      bodydata = (struct objc_object *)objc_retainAutoreleasedReturnValue(v42);
      objc_release(v41);
      objc_release(v38);
      v48 = &MEMORY[0x1B558B298];
      v49 = -1040187392;
      v50 = 0;
      v51 = __60__TXYUserInfoRequset_loginUserwith_andPassword_andClientid___block_invoke_2;// 解密返回数并存放配置文件中
      v52 = &__block_descriptor_tmp259;
      v53 = objc_retain(v7, v44);
      v45 = ((NSURLSessionTask *(__cdecl *)(TXYNetManager_meta *, SEL, unsigned __int64, id, id, id, id, id))objc_msgSend)(// 发送网络
              (TXYNetManager_meta *)&OBJC_CLASS___TXYNetManager,
              "txy_requestWithType:urlString:parameters:progress:successBlock:failureBlock:",
              1uLL,
              httpurl,
              bodydata,
              (id)&__block_literal_global240,
              (id)&v48,
              (id)&__block_literal_global262);
      v46 = objc_retainAutoreleasedReturnValue(v45);
      objc_release(v46);
      objc_release(v53);
      objc_release(bodydata);
      objc_release(v36);
      objc_release(v34);
      objc_release(v31);
      objc_release(v24);
      objc_release(v22);
      objc_release(httpurl);
    LABEL_10:
      objc_release(clientId);
      objc_release(passwrod);
      objc_release(username);
    }

    4. 解密与解析服务器返回的数据,解密后数据格式如下:

    {
        "status":0,
        "token":"de9dc56d7d7cc085f4bb1897075e4801",
        "username":"xxxx",//用户名
        "vip":0, //是否为vip用户
        "expiretime":0 //会员过期时间
    }

    解密代码如下:

    / 登录后存放authValue到文件
    __int64 __fastcall __60__TXYUserInfoRequset_loginUserwith_andPassword_andClientid___block_invoke_2(__int64 a1, __int64 a2)
    {
      __int64 v2; // x28
      __int64 v3; // x19
      void *v4; // x0
      void *v5; // x21
      __int64 v6; // x1
      void *v7; // x19
      void *v8; // x0
      __int64 v9; // x22
      void *v10; // x0
      __int64 v11; // x23
      void *v12; // x0
      __int64 v13; // ST10_8
      void *v14; // x0
      void *v15; // x23
      void *v16; // x24
      void *v17; // x0
      struct objc_object *data; // x0
      struct objc_object *v19; // x24
      id v20; // x0
      void *v21; // x0
      void *v22; // x28
      void *v23; // x0
      __int64 v24; // x0
      void *v25; // x0
      void *v26; // x0
      void *v27; // x26
      void *v28; // x0
      __int64 v29; // ST08_8
      void *v30; // x0
      void *v31; // x23
      void *v32; // x22
      void *v33; // x0
      __int64 v34; // x22
      __int64 v35; // x23
      void *v36; // x20
      void *v37; // x0
      __int64 v38; // x21
      __int64 v39; // x0
      void *v40; // x0
      __int64 v41; // x22
      void *v42; // x0
      __int64 v43; // ST00_8
      void *v44; // x0
      void *v45; // x23
      void *v46; // x0
      __int64 v47; // x28
      void *v48; // x0
      __int64 v49; // x22
      void *v50; // x0
      __int64 v51; // ST00_8
      void *v52; // x0
      void *v53; // x23
      void *v54; // x0
      __int64 v55; // x22
      void *v56; // x0
      __int64 v57; // x22
      __int64 v58; // x24
      void *v59; // x0
      void *v60; // x23
      void *v61; // x22
      void *v62; // x0
      void *v63; // x0
      void *v64; // x23
      void *v65; // x0
      __int64 v66; // x24
      void *v67; // x0
      __int64 v68; // x0
      __int64 v69; // x22
      __int64 v70; // x0
      void *v71; // x0
      void *v72; // x22
      int vip; // w24
      id v74; // x0
      void *v75; // x0
      void *v76; // x23
      void *v77; // x0
      void *v78; // x28
      void *v79; // x0
      __int64 v80; // x24
      void *v81; // x0
      __int64 v82; // x23
      void *v83; // x0
      void *v84; // x23
      id v85; // x0
      void *v86; // x0
      __int64 v87; // x24
      void *v88; // x0
      __int64 v89; // x23
      void *v90; // x0
      void *v91; // x22
      void *v92; // x0
      __int64 v93; // x21
      void *v94; // x0
      __int64 v95; // x20
      __int64 v97; // [xsp+0h] [xbp-90h]
      void *v98; // [xsp+20h] [xbp-70h]
      struct objc_object *v99; // [xsp+28h] [xbp-68h]
      __int64 v100; // [xsp+30h] [xbp-60h]
      __int64 v101; // [xsp+38h] [xbp-58h]
      __int64 v102; // [xsp+38h] [xbp-58h]
    
      v2 = a1;
      v3 = objc_retain(a2, a2);
      v4 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
      v5 = (void *)objc_retainAutoreleasedReturnValue(v4);
      objc_msgSend(v5, (const char *)&MEMORY[0x1966A8EE2], CFSTR("no"), CFSTR("geostates"));
      objc_release(v5);
      v7 = (void *)objc_retain(v3, v6);
      NSLog(CFSTR("response====%@"));
      v8 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("error"), v7);
      v9 = objc_retainAutoreleasedReturnValue(v8);
      v10 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("info"));
      v11 = objc_retainAutoreleasedReturnValue(v10);
      v12 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("status"));
      v13 = objc_retainAutoreleasedReturnValue(v12);
      NSLog(CFSTR("error = %@ info = %@ status = %@"));
      objc_release(v13);
      objc_release(v11);
      objc_release(v9);
      v14 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("status"), v9, v11, v13);
      v15 = (void *)objc_retainAutoreleasedReturnValue(v14);
      v16 = objc_msgSend(v15, (const char *)&MEMORY[0x1966A5F6B]);
      objc_release(v15);
      if ( !v16 )                                   // 判断网络是否返回成功
      {
        v101 = v2;
        v17 = objc_msgSend(v7, (const char *)&MEMORY[0x1966A4322], CFSTR("data"));// 获取返回值中的data数据
        data = (struct objc_object *)objc_retainAutoreleasedReturnValue(v17);
        v19 = data;
        v20 = ((id (__cdecl *)(AES128_meta *, SEL, id, id))objc_msgSend)(// 解密data数据
                (AES128_meta *)&OBJC_CLASS___AES128,
                "AES128Decrypt:withKey:",
                data,
                (id)CFSTR("Hz2Ywe8UBe@YfZ0*"));
        v21 = (void *)objc_retainAutoreleasedReturnValue(v20);
        v22 = v21;
        v23 = objc_msgSend(v21, (const char *)&MEMORY[0x196754444], 4LL);
        v24 = objc_retainAutoreleasedReturnValue(v23);
        v100 = v24;
        v25 = objc_msgSend(&MEMORY[0x1B55A0FF8], (const char *)&MEMORY[0x197C763B3], v24, 1LL, 0LL);
        v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
        v27 = v26;
        v28 = objc_msgSend(v26, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
        v29 = objc_retainAutoreleasedReturnValue(v28);
        NSLog(CFSTR("----%@ -------%@"));
        objc_release(v29);
        v30 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("status"), v27, v29);
        v31 = (void *)objc_retainAutoreleasedReturnValue(v30);
        v32 = objc_msgSend(v31, (const char *)&MEMORY[0x1966A5F6B]);
        objc_release(v31);
        if ( v32 )
        {
          v33 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
          v34 = objc_retainAutoreleasedReturnValue(v33);
          objc_release(v34);
          v35 = v100;
          if ( !v34 )
          {
    LABEL_21:
            objc_release(v27);
            objc_release(v35);
            objc_release(v22);
            objc_release(v19);
            goto LABEL_22;
          }
          v36 = *(void **)(v101 + 32);
          v37 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
          v38 = objc_retainAutoreleasedReturnValue(v37);
          objc_msgSend(v36, (const char *)&MEMORY[0x19AEA7047], v38);
          v39 = v38;
        }
        else
        {
          v98 = v22;
          v40 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
          v41 = objc_retainAutoreleasedReturnValue(v40);
          objc_release(v41);
          if ( v41 )
          {
            v42 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
            v43 = objc_retainAutoreleasedReturnValue(v42);
            NSLog(CFSTR("%@"));
            objc_release(v43);
            v44 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA], v43);
            v45 = (void *)objc_retainAutoreleasedReturnValue(v44);
            v46 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("token"));
            v47 = objc_retainAutoreleasedReturnValue(v46);
            objc_msgSend(v45, (const char *)&MEMORY[0x1966A8EE2], v47, CFSTR("token"));
            objc_release(v47);
            objc_release(v45);
          }
          v99 = v19;
          v48 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
          v49 = objc_retainAutoreleasedReturnValue(v48);
          objc_release(v49);
          if ( v49 )
          {
            v50 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
            v51 = objc_retainAutoreleasedReturnValue(v50);
            NSLog(CFSTR("%@"));
            objc_release(v51);
            v52 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA], v51);
            v53 = (void *)objc_retainAutoreleasedReturnValue(v52);
            v54 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("username"));
            v55 = objc_retainAutoreleasedReturnValue(v54);
            objc_msgSend(v53, (const char *)&MEMORY[0x1966A8EE2], v55, CFSTR("userName"));
            objc_release(v55);
            objc_release(v53);
          }
          v56 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("expiretime"));
          v57 = objc_retainAutoreleasedReturnValue(v56);
          objc_release(v57);
          v58 = v101;
          if ( v57 )
          {
            v59 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("expiretime"));
            v60 = (void *)objc_retainAutoreleasedReturnValue(v59);
            v61 = objc_msgSend(v60, (const char *)&MEMORY[0x1966ABDF3]);
            objc_release(v60);
            v62 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
            v63 = (void *)objc_retainAutoreleasedReturnValue(v62);
            v64 = v63;
            if ( (_DWORD)v61 )
            {
              v65 = objc_msgSend(*(void **)(v101 + 32), "timeFormatted:", v61);
              v66 = objc_retainAutoreleasedReturnValue(v65);
              objc_msgSend(v64, (const char *)&MEMORY[0x1966A8EE2], v66, CFSTR("expiretime"));
              objc_release(v66);
              objc_release(v64);
              v58 = v101;
              v67 = objc_msgSend(*(void **)(v101 + 32), "timeFormatted:", v61);
              v68 = objc_retainAutoreleasedReturnValue(v67);
              v69 = v68;
              v97 = v68;
              NSLog(CFSTR("expiretime = %@ "));
              v70 = v69;
            }
            else
            {
              objc_msgSend(v63, (const char *)&MEMORY[0x1966A8EE2], CFSTR("0"), CFSTR("expiretime"));
              v70 = (__int64)v64;
            }
            objc_release(v70);
          }
          v102 = v58;
          v71 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("vip"), v97);
          v72 = (void *)objc_retainAutoreleasedReturnValue(v71);
          vip = (unsigned __int64)objc_msgSend(v72, (const char *)&MEMORY[0x1966ABDF3]);
          objc_release(v72);
          v74 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
          v75 = (void *)objc_retainAutoreleasedReturnValue(v74);
          v76 = v75;
          v77 = objc_msgSend(v75, "loadSetDictForPath:", CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));
          v78 = (void *)objc_retainAutoreleasedReturnValue(v77);
          objc_release(v76);
          if ( vip )                                // 如果vip不为0
          {
            v79 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 1LL);
            v80 = objc_retainAutoreleasedReturnValue(v79);
            objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v80, CFSTR("authValue"));
            objc_release(v80);
            v81 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 1LL);
            v82 = objc_retainAutoreleasedReturnValue(v81);
            objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v82, CFSTR("Toggle"));
            objc_release(v82);
            v83 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
            v84 = (void *)objc_retainAutoreleasedReturnValue(v83);
            objc_msgSend(v84, (const char *)&MEMORY[0x1966A8EE2], CFSTR("1"), CFSTR("isVIP"));
          }
          else                                      // 如果vip为0
          {
            v86 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 0LL);
            v87 = objc_retainAutoreleasedReturnValue(v86);
            objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v87, CFSTR("authValue"));
            objc_release(v87);
            v88 = objc_msgSend(&MEMORY[0x1B559E4B0], (const char *)&MEMORY[0x1966A7D6A], 0LL);
            v89 = objc_retainAutoreleasedReturnValue(v88);
            objc_msgSend(v78, (const char *)&MEMORY[0x1966A8EE2], v89, CFSTR("Toggle"));
            objc_release(v89);
            v90 = objc_msgSend(&MEMORY[0x1B5593F88], (const char *)&MEMORY[0x1966A95FA]);
            v84 = (void *)objc_retainAutoreleasedReturnValue(v90);
            objc_msgSend(v84, (const char *)&MEMORY[0x1966A8EE2], CFSTR("0"), CFSTR("isVIP"));
          }
          objc_release(v84);
          v85 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
          v91 = (void *)objc_retainAutoreleasedReturnValue(v85);
          objc_msgSend(v91, "writeDict:toPath:", v78, CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));// 写入配置文件
          objc_release(v91);
          objc_release(v78);
          v35 = v100;
          v22 = v98;
          v19 = v99;
          v92 = objc_msgSend(v27, (const char *)&MEMORY[0x1966A4322], CFSTR("msg"));
          v93 = objc_retainAutoreleasedReturnValue(v92);
          objc_release(v93);
          if ( v93 )
            objc_msgSend(*(void **)(v102 + 32), (const char *)&MEMORY[0x19AEA7047], CFSTR("登录成功"));
          v94 = objc_msgSend(*(void **)(v102 + 32), "requestResult");
          v95 = objc_retainAutoreleasedReturnValue(v94);
          (*(void (**)(void))(v95 + 16))();
          v39 = v95;
        }
        objc_release(v39);
        goto LABEL_21;
      }
    LABEL_22:
      objc_release(v7);
      return objc_release(v7);
    }

    1. 整个登录过程就分析完成了,主要用到了AES加密算法。

    0x02:破解思路

    1. 通过上面登录过程的分析,根据上面数据格式可以直接改vip与expiretime的值就能成功破解成会员用户,如下图 :

    2. 将服务器返回的值存入.plist文件后,程序会调用-[TXYTools isCanOpen]方法读取文件判断是否为vip,代码如下:

      bool __cdecl -[TXYTools isCanOpen](TXYTools *self, SEL a2)
    {
      void *v2; // x0
      void *v3; // x0
      void *v4; // x20
      void *v5; // x0
      void *v6; // x23
      void *isVIP; // x19
      id v8; // x0
      void *v9; // x0
      void *v10; // x23
      void *v11; // x0
      void *v12; // x20
      void *v13; // x0
      void *v14; // x23
      void *authValue; // x21
    
      v2 = objc_msgSend(&OBJC_CLASS___NSUserDefaults, (const char *)&unk_188A615FA);
      v3 = (void *)objc_retainAutoreleasedReturnValue(v2);
      v4 = v3;
      v5 = objc_msgSend(v3, (const char *)&unk_188A60093, CFSTR("isVIP"));
      v6 = (void *)objc_retainAutoreleasedReturnValue(v5);
      isVIP = objc_msgSend(v6, (const char *)&unk_188A5DF6B);
      objc_release(v6);
      objc_release(v4);
      v8 = ((id (__cdecl *)(TXYTools_meta *, SEL))objc_msgSend)((TXYTools_meta *)&OBJC_CLASS___TXYTools, "sharedTools");
      v9 = (void *)objc_retainAutoreleasedReturnValue(v8);
      v10 = v9;
      v11 = objc_msgSend(v9, "loadSetDictForPath:", CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"));
      v12 = (void *)objc_retainAutoreleasedReturnValue(v11);
      objc_release(v10);
      v13 = objc_msgSend(v12, (const char *)&unk_188A60093, CFSTR("authValue"));
      v14 = (void *)objc_retainAutoreleasedReturnValue(v13);
      authValue = objc_msgSend(v14, (const char *)&unk_188A5DF6B);
      objc_release(v14);
      NSLog(CFSTR("user = %ld"));
      NSLog(CFSTR("isVIP = %ld"));
      objc_release(v12);
      return (signed __int64)isVIP > 0 && (signed __int64)authValue > 0;
    }

    3. 第一是可以通过修改服务器返回值做破解,第二是通过hook方法isCanOpen来做破解。代码如下 :

    %hook TXYTools
    - (BOOL)isCanOpen
    {
    return YES;
    }
    %end

    破解成功后可以正常使用功能,如下图所示 :

    0x03:实现原理

    1. 主app获取到要修改的经纬度与地名后DES加密存放在.plist配置文件中,将选择的地图上的经纬度与地址名加密后写入.plist配置文件,代码如下:

    //将选择的app的Build地图上的经纬度与地址名加密后写入.plist配置文件
    __int64 __fastcall -[TXYConfig setLocationWithBundleId:andType:andGPS:withAddress:withIsOn:](void *a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, double a7, double a8)
    {
      __int64 v8; // x26
      __int64 v9; // x19
      double v10; // d8
      double v11; // d9
      __int64 v12; // x25
      void *v13; // x20
      __int64 v14; // x1
      const __CFString *v15; // x19
      void *v16; // x0
      void *v17; // x0
      void *v18; // x21
      void *v19; // x0
      __int64 v20; // x1
      void *v21; // x22
      void *v22; // x0
      void *v23; // x0
      __int64 v24; // x0
      __int64 v25; // x28
      void *v26; // x0
      __int64 v27; // x0
      __int64 v28; // x24
      void *v29; // x0
      __int64 v30; // x0
      __int64 v31; // x20
      void *v32; // x0
      void *v33; // x26
      void *v34; // x0
      __int64 v35; // x20
      void *v36; // x0
      __int64 v37; // x20
      __int64 v39; // [xsp+10h] [xbp-C0h]
      __int64 v40; // [xsp+18h] [xbp-B8h]
      void *v41; // [xsp+20h] [xbp-B0h]
      const __CFString *v42; // [xsp+28h] [xbp-A8h]
      const __CFString *v43; // [xsp+30h] [xbp-A0h]
      const __CFString *v44; // [xsp+38h] [xbp-98h]
      const __CFString *v45; // [xsp+40h] [xbp-90h]
      __int64 v46; // [xsp+48h] [xbp-88h]
      __int64 v47; // [xsp+50h] [xbp-80h]
      const __CFString *v48; // [xsp+58h] [xbp-78h]
      __int64 v49; // [xsp+60h] [xbp-70h]
      __int64 v50; // [xsp+68h] [xbp-68h]
    
      v8 = a6;
      v9 = a5;
      v10 = a8;
      v11 = a7;
      v12 = a4;
      v13 = a1;
      v40 = a3;
      v41 = a1;
      v50 = -7228227847426539268LL;
      v39 = objc_retain(a3, a2);
      v15 = (const __CFString *)objc_retain(v9, v14);
      v16 = objc_msgSend(v13, "loadSetDict");
      v17 = (void *)objc_retainAutoreleasedReturnValue(v16);
      v18 = v17;
      v19 = objc_msgSend(v17, (const char *)&unk_1966A8093, CFSTR("AppLocation"));
      v21 = (void *)objc_retainAutoreleasedReturnValue(v19);
      if ( !v21 )
      {
        v22 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, (const char *)&unk_1966A833B);
        v21 = (void *)objc_retainAutoreleasedReturnValue(v22);
      }
      if ( !(_DWORD)v12 )
      {
        objc_retain(CFSTR("跟随系统真实位置"), v20);
        objc_release(v15);
        v15 = CFSTR("跟随系统真实位置");
      }
      v42 = CFSTR("Latitude");
      v23 = objc_msgSend(&OBJC_CLASS___NSNumber, (const char *)&unk_1966A25C1, v11);
      v24 = objc_retainAutoreleasedReturnValue(v23);
      v25 = v24;
      v46 = v24;
      v43 = CFSTR("Longitude");
      v26 = objc_msgSend(&OBJC_CLASS___NSNumber, (const char *)&unk_1966A25C1, v10);
      v27 = objc_retainAutoreleasedReturnValue(v26);
      v28 = v27;
      v47 = v27;
      v44 = CFSTR("address");
      v48 = v15;
      v45 = CFSTR("isOn");
      v29 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithbool, v8);
      v30 = objc_retainAutoreleasedReturnValue(v29);
      v31 = v30;
      v49 = v30;
      v32 = objc_msgSend(&OBJC_CLASS___NSDictionary, &aDictionarywith, &v46, &v42, 4LL);
      v33 = objc_msgSend(v32, "mutableCopy");
      objc_release(v31);
      objc_release(v28);
      objc_release(v25);
      v34 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithunsi, v12);
      v35 = objc_retainAutoreleasedReturnValue(v34);
      objc_msgSend(v33, &aSetobjectForke, v35, CFSTR("FakeType"));
      objc_release(v35);
      objc_msgSend(v21, &aSetobjectForke, v33, v40);
      objc_release(v39);
      v36 = objc_msgSend(&OBJC_CLASS___NSNumber, &aNumberwithbool, 1LL);
      v37 = objc_retainAutoreleasedReturnValue(v36);
      objc_msgSend(v18, &aSetobjectForke, v37, CFSTR("Toggle"));
      objc_release(v37);
      objc_msgSend(v18, &aSetobjectForke, v21, CFSTR("AppLocation"));
      NSLog(CFSTR("%@"));
      objc_msgSend(v41, "writeSetConfigWithDict:", v18, v18);// 加密并写入配置文件
      objc_release(v33);
      objc_release(v21);
      objc_release(v18);
      return objc_release(v15);
    }
    
    //加密并写入配置文件
    bool __cdecl -[TXYConfig writeSetConfigWithDict:](TXYConfig *self, SEL a2, id a3)
    {
      void *v3; // x0
      __int64 v4; // x19
      void *v5; // x0
      void *v6; // x0
      void *v7; // x20
      struct objc_object *v8; // x0
      void *v9; // x21
      char v10; // w22
      __int64 v12; // [xsp+8h] [xbp-28h]
    
      v3 = objc_msgSend(&OBJC_CLASS___NSJSONSerialization, &aDatawithjsonob, a3, 1LL, 0LL);
      v4 = objc_retainAutoreleasedReturnValue(v3);
      v5 = objc_msgSend(&OBJC_CLASS___NSString, &aAlloc_0);
      v6 = objc_msgSend(v5, &aInitwithdataEn, v4, 4LL);
      v7 = v6;
      v8 = +[DES encryptString:](&OBJC_CLASS___DES, "encryptString:", v6);// des加密
      v9 = (void *)objc_retainAutoreleasedReturnValue(v8);
      v12 = 0LL;
      v10 = (unsigned __int64)objc_msgSend(
                                v9,
                                &aWritetofileAto,
                                CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"),
                                0LL,
                                4LL,
                                &v12);
      objc_release(v9);
      objc_release(v7);
      objc_release(v4);
      return v10;
    }
    id __cdecl +[DES encryptString:](DES_meta *self, SEL a2, id a3)
    {
      return (id)objc_msgSend(self, "TripleDES:encryptOrDecrypt:key:", a3, 0LL, CFSTR("3b38e11ffd65698aedeb5ffc"));
    }

    2. Tweak插件主要是hook了几个函数,当目标程序调用获取地理位置信息函数时就解密主app加密存放好的值做为获取值,代码如下:

    Hook获取位置函数

    char *__fastcall _logosLocalCtor_3415ee8c(int a1, char **a2, char **a3)
    {
      void *v3; // ST30_8
      __int64 v4; // x0
      __int64 v5; // x8
      const char *v7; // [xsp+0h] [xbp-4C0h]
      const char *v8; // [xsp+8h] [xbp-4B8h]
      signed __int64 v9; // [xsp+10h] [xbp-4B0h]
      const char *v10; // [xsp+18h] [xbp-4A8h]
      void *v11; // [xsp+20h] [xbp-4A0h]
      char v12; // [xsp+58h] [xbp-468h]
      __int64 v13; // [xsp+70h] [xbp-450h]
      int v14; // [xsp+7Ch] [xbp-444h]
      __int64 CLLocationManager; // [xsp+80h] [xbp-440h]
      __int64 v16; // [xsp+88h] [xbp-438h]
      char **v17; // [xsp+90h] [xbp-430h]
      char **v18; // [xsp+98h] [xbp-428h]
      int v19; // [xsp+A4h] [xbp-41Ch]
      char v20; // [xsp+A8h] [xbp-418h]
      char v21; // [xsp+A9h] [xbp-417h]
      char v22; // [xsp+AAh] [xbp-416h]
      char v23; // [xsp+ABh] [xbp-415h]
      char v24; // [xsp+ACh] [xbp-414h]
      char v25; // [xsp+ADh] [xbp-413h]
      char v26; // [xsp+AEh] [xbp-412h]
      char v27; // [xsp+AFh] [xbp-411h]
    
      v19 = a1;
      v18 = a2;
      v17 = a3;
      v16 = objc_getClass("AMapLocationManager");
      if ( v16 )
      {
        MSHookMessageEx(
          v16,
          "detectRiskOfFakeLocation",
          _logos_method$_ungrouped$AMapLocationManager$detectRiskOfFakeLocation,// 检测虚拟定位
          &_logos_orig$_ungrouped$AMapLocationManager$detectRiskOfFakeLocation);
      }
      else
      {
        v11 = objc_msgSend(&OBJC_CLASS___NSString, "stringWithFormat:", CFSTR("logos: nil class %s"), "AMapLocationManager");
        v10 = "ERROR";
        v9 = 276LL;
        v8 = "Tweak.xm";
        v7 = "txytweak";
        CFLog(3LL, CFSTR("x1B[1;31m[%s] x1B[mx1B[0;31m%s:%dx1B[m x1B[0;30;41m%s:x1B[m %@"));
      }
      CLLocationManager = objc_getClass("CLLocationManager");
      if ( CLLocationManager )
      {
        MSHookMessageEx(
          CLLocationManager,
          "location",
          _logos_method$_ungrouped$CLLocationManager$location,
          &_logos_orig$_ungrouped$CLLocationManager$location);
      }
      else
      {
        v11 = objc_msgSend(
                &OBJC_CLASS___NSString,
                "stringWithFormat:",
                CFSTR("logos: nil class %s"),
                "CLLocationManager",
                v8,
                v9,
                v10,
                v11);
        v10 = "ERROR";
        v9 = 276LL;
        v8 = "Tweak.xm";
        v7 = "txytweak";
        CFLog(3LL, CFSTR("x1B[1;31m[%s] x1B[mx1B[0;31m%s:%dx1B[m x1B[0;30;41m%s:x1B[m %@"));
      }
      if ( CLLocationManager )
      {
        MSHookMessageEx(
          CLLocationManager,
          "startUpdatingLocation",
          _logos_method$_ungrouped$CLLocationManager$startUpdatingLocation,
          &_logos_orig$_ungrouped$CLLocationManager$startUpdatingLocation);
      }
      else
      {
        v11 = objc_msgSend(
                &OBJC_CLASS___NSString,
                "stringWithFormat:",
                CFSTR("logos: nil class %s"),
                "CLLocationManager",
                v8,
                v9,
                v10,
                v11);
        v10 = "ERROR";
        v9 = 276LL;
        v8 = "Tweak.xm";
        v7 = "txytweak";
        CFLog(3LL, CFSTR("x1B[1;31m[%s] x1B[mx1B[0;31m%s:%dx1B[m x1B[0;30;41m%s:x1B[m %@"));
      }
      v20 = 118;
      v21 = 64;
      v22 = 58;
      v23 = 35;
      v24 = 58;
      v25 = 35;
      v26 = 58;
      v14 = 7;
      v27 = 0;
      class_addMethod();
      v13 = CFNotificationCenterGetDarwinNotifyCenter();
      CFNotificationCenterAddObserver();
      objc_msgSend(&OBJC_CLASS___NSBundle, "mainBundle", v7, v8, v9, v10, v11);
      v3 = (void *)objc_retainAutoreleasedReturnValue();
      objc_msgSend(v3, "bundleIdentifier");
      v4 = objc_retainAutoreleasedReturnValue();
      v5 = curBundle;
      curBundle = v4;
      objc_release(v5);
      objc_release(v3);
      NSLog(CFSTR("txy hook success1111111"));
      return &v12;
    }

    读取 .plist配置文中的数据并解密。

    void __cdecl -[TXYLocation replacedLocationManager:didUpdateToLocation:fromLocation:](TXYLocation *self, SEL a2, id a3, id a4, id a5)
    {
      void *v5; // ST2F8_8
      __int64 v6; // x0
      void *v7; // ST1F0_8
      void *v8; // x0
      void *v9; // ST1E0_8
      void *v10; // ST1D0_8
      char v11; // ST1CC_1
      void *v12; // ST2A8_8
      void *v13; // ST1B8_8
      double v14; // d0
      double v15; // ST2C0_8
      void *v16; // ST1A8_8
      double v17; // d0
      double v18; // ST2C8_8
      __int64 v19; // ST2A0_8
      void *v20; // ST1A0_8
      double v21; // d0
      double v22; // ST198_8
      double v23; // d0
      double v24; // ST190_8
      double v25; // d0
      double v26; // ST188_8
      double v27; // ST180_8
      double v28; // d0
      double v29; // d0
      double v30; // d1
      void *v31; // ST150_8
      void *v32; // ST148_8
      int v33; // ST144_4
      void *v34; // ST258_8
      void *v35; // ST138_8
      double v36; // d0
      void *v37; // ST130_8
      double v38; // d0
      void *v39; // ST128_8
      int v40; // ST124_4
      void *v41; // ST238_8
      void *v42; // ST118_8
      double v43; // d0
      void *v44; // ST110_8
      double v45; // d0
      void *v46; // STF8_8
      double v47; // d0
      double v48; // STE8_8
      double v49; // d0
      double v50; // STD8_8
      double v51; // d0
      double v52; // STC8_8
      double v53; // d0
      double v54; // STB8_8
      double v55; // d0
      double v56; // STA8_8
      __int64 v57; // x0
      __int64 v58; // ST98_8
      void *v59; // x0
      __int64 v60; // x9
      void *v61; // ST88_8
      double v62; // d0
      double v63; // ST80_8
      double v64; // d0
      double v65; // ST78_8
      double v66; // d0
      double v67; // ST70_8
      double v68; // d0
      double v69; // ST68_8
      double v70; // d0
      double v71; // ST60_8
      __int64 v72; // ST58_8
      void *v73; // ST50_8
      double v74; // d0
      double v75; // ST48_8
      double v76; // d0
      double v77; // ST40_8
      double v78; // d0
      double v79; // ST38_8
      double v80; // d0
      double v81; // ST30_8
      double v82; // d0
      double v83; // ST28_8
      __int64 v84; // ST20_8
      double v85; // d0
      double v86; // d1
      double v87; // d2
      double v88; // d3
      char v89; // [xsp+15Ch] [xbp-1E4h]
      char v90; // [xsp+1DCh] [xbp-164h]
      char v91; // [xsp+1ECh] [xbp-154h]
      void *v92; // [xsp+228h] [xbp-118h]
      char v93; // [xsp+267h] [xbp-D9h]
      void *v94; // [xsp+268h] [xbp-D8h]
      unsigned int v95; // [xsp+274h] [xbp-CCh]
      double v96; // [xsp+290h] [xbp-B0h]
      void *v97; // [xsp+298h] [xbp-A8h]
      void *v98; // [xsp+2B0h] [xbp-90h]
      void *v99; // [xsp+2B8h] [xbp-88h]
      double v100; // [xsp+2C0h] [xbp-80h]
      double v101; // [xsp+2C8h] [xbp-78h]
      void *v102; // [xsp+2D0h] [xbp-70h]
      void *jsondata; // [xsp+2E8h] [xbp-58h]
      struct objc_object *v104; // [xsp+300h] [xbp-40h]
      TXYLocation *v105; // [xsp+328h] [xbp-18h]
    
      v105 = self;
      objc_storeStrong();
      objc_storeStrong();
      objc_storeStrong();
      NSLog(CFSTR("第一个方法相应"));
      objc_msgSend(
        &OBJC_CLASS___NSString,
        "stringWithContentsOfFile:encoding:error:",
        CFSTR("/var/mobile/Library/Preferences/com.txy.TxyNew.plist"),
        4LL,
        0LL);
      v104 = (struct objc_object *)objc_retainAutoreleasedReturnValue();
      if ( v104 )
      {
        ((void (__cdecl *)(DES_meta *, SEL, id))objc_msgSend)((DES_meta *)&OBJC_CLASS___DES, "decryptString:", v104);// 解密
        v5 = (void *)objc_retainAutoreleasedReturnValue();
        objc_msgSend(v5, "dataUsingEncoding:", 4LL);
        v6 = objc_retainAutoreleasedReturnValue();
        objc_msgSend(&OBJC_CLASS___NSJSONSerialization, "JSONObjectWithData:options:error:", v6, 1LL, 0LL);
        jsondata = (void *)objc_retainAutoreleasedReturnValue();
        if ( !jsondata )
        {
          objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
          jsondata = (void *)objc_retainAutoreleasedReturnValue();
          objc_release(0LL);
        }
        objc_msgSend(jsondata, "valueForKey:", CFSTR("Toggle"));
        v7 = (void *)objc_retainAutoreleasedReturnValue();
        v91 = (unsigned __int64)objc_msgSend(v7, "boolValue");
        objc_release(v7);
        if ( objc_retain(CFSTR("/var/mobile/Library/Preferences/com.txy.FakeStatus.plist")) )
        {
          v8 = objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "alloc");
          v102 = objc_msgSend(
                   v8,
                   "initWithContentsOfFile:",
                   CFSTR("/var/mobile/Library/Preferences/com.txy.FakeStatus.plist"));
          objc_release(0LL);
          if ( !v102 )
          {
            objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
            v102 = (void *)objc_retainAutoreleasedReturnValue();
            objc_release(0LL);
          }
        }
        else
        {
          objc_msgSend(&OBJC_CLASS___NSMutableDictionary, "dictionary");
          v102 = (void *)objc_retainAutoreleasedReturnValue();
          objc_release(0LL);
        }
        objc_msgSend(v102, "objectForKey:", CFSTR("fakeStatus"));
        v9 = (void *)objc_retainAutoreleasedReturnValue();
        v90 = (unsigned __int64)objc_msgSend(v9, "isEqualToString:", CFSTR("no"));
        objc_release(v9);
        if ( !(v91 & 1) )
        {
          _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
    LABEL_36:
          v95 = 0;
    LABEL_37:
          objc_storeStrong();
          objc_storeStrong();
          objc_storeStrong();
          objc_storeStrong();
          objc_storeStrong();
          if ( v95 )
            goto LABEL_41;
          goto LABEL_40;
        }
        objc_msgSend(jsondata, "objectForKey:", CFSTR("AppLocation"));
        v99 = (void *)objc_retainAutoreleasedReturnValue();
        objc_msgSend(jsondata, "objectForKey:", CFSTR("AppScan"));
        v98 = (void *)objc_retainAutoreleasedReturnValue();
        objc_msgSend(v98, "allKeys");
        v10 = (void *)objc_retainAutoreleasedReturnValue();
        v11 = (unsigned __int64)objc_msgSend(v10, "containsObject:", curBundle);
        objc_release(v10);
        if ( v11 & 1 )
        {
          objc_msgSend(v98, "objectForKey:", curBundle);
          v12 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v12, "objectForKey:", CFSTR("Latitude"));
          v13 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v13, "doubleValue");
          v15 = v14;
          objc_release(v13);
          objc_msgSend(v12, "objectForKey:", CFSTR("Longitude"));
          v16 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v16, "doubleValue");
          v18 = v17;
          objc_release(v16);
          objc_msgSend(&OBJC_CLASS___NSDate, "date");
          v19 = objc_retainAutoreleasedReturnValue();
          v20 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
          objc_msgSend(0LL, "altitude");
          v22 = v21;
          objc_msgSend(0LL, "horizontalAccuracy");
          v24 = v23;
          objc_msgSend(0LL, "verticalAccuracy");
          v26 = v25;
          v27 = *(double *)&lastCourse;
          objc_msgSend(0LL, "speed");
          v97 = objc_msgSend(
                  v20,
                  "initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
                  v19,
                  v15,
                  v18,
                  v22,
                  v24,
                  v26,
                  v27,
                  v28);
          objc_msgSend((void *)lastFakeFromLocation, "coordinate");
          v96 = headingToLocation(v15, v18, v29, v30);
          objc_storeStrong();
          if ( v96 != 0.0 )
            lastCourse = *(_QWORD *)&v96;
          _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, v97, v97);
          v95 = 1;
          objc_storeStrong();
          objc_storeStrong();
          objc_storeStrong();
          goto LABEL_33;
        }
        v93 = 0;
        v89 = 0;
        if ( v99 )
        {
          objc_msgSend(v99, "allKeys");
          v94 = (void *)objc_retainAutoreleasedReturnValue();
          v93 = 1;
          v89 = (unsigned __int64)objc_msgSend(v94, "containsObject:", curBundle);
        }
        if ( v93 & 1 )
          objc_release(v94);
        if ( v89 & 1 )
        {
          objc_msgSend(v99, "objectForKeyedSubscript:", curBundle);
          v31 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v31, "objectForKeyedSubscript:", CFSTR("isOn"));
          v32 = (void *)objc_retainAutoreleasedReturnValue();
          v33 = (unsigned __int64)objc_msgSend(v32, "intValue");
          objc_release(v32);
          objc_release(v31);
          if ( v33 != 1 )
          {
            _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
            v95 = 1;
            goto LABEL_33;
          }
          objc_msgSend(v99, "objectForKey:", curBundle);
          v34 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v34, "objectForKey:", CFSTR("Latitude"));
          v35 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v35, "doubleValue");
          v100 = v36;
          objc_release(v35);
          objc_msgSend(v34, "objectForKey:", CFSTR("Longitude"));
          v37 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v37, "doubleValue");
          v101 = v38;
          objc_release(v37);
          objc_msgSend(v34, "objectForKey:", CFSTR("FakeType"));
          v39 = (void *)objc_retainAutoreleasedReturnValue();
          v40 = (unsigned __int64)objc_msgSend(v39, "intValue");
          objc_release(v39);
          if ( v40 )
          {
            v95 = 0;
          }
          else
          {
            _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
            v95 = 1;
          }
          objc_storeStrong();
          if ( v95 )
          {
    LABEL_33:
            objc_storeStrong();
            objc_storeStrong();
            if ( v95 )
              goto LABEL_37;
            goto LABEL_36;
          }
        }
        else
        {
          if ( (v90 & 1) != 0 )
          {
            _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
            v95 = 1;
            goto LABEL_33;
          }
          objc_msgSend(jsondata, "objectForKey:", CFSTR("FakeLocation"));
          v41 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v41, "objectForKey:", CFSTR("FakeLatitude"));
          v42 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v42, "doubleValue");
          v100 = v43;
          objc_release(v42);
          objc_msgSend(v41, "objectForKey:", CFSTR("FakeLongitude"));
          v44 = (void *)objc_retainAutoreleasedReturnValue();
          objc_msgSend(v44, "doubleValue");
          v101 = v45;
          objc_release(v44);
          objc_storeStrong();
        }
        if ( lastFakeFromLocation )
        {
          v73 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
          objc_msgSend(0LL, "altitude");
          v75 = v74;
          objc_msgSend(0LL, "horizontalAccuracy");
          v77 = v76;
          objc_msgSend(0LL, "verticalAccuracy");
          v79 = v78;
          objc_msgSend(0LL, "course");
          v81 = v80;
          objc_msgSend(0LL, "speed");
          v83 = v82;
          objc_msgSend(0LL, "timestamp");
          v84 = objc_retainAutoreleasedReturnValue();
          v92 = objc_msgSend(
                  v73,
                  "initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
                  v84,
                  v100,
                  v101,
                  v75,
                  v77,
                  v79,
                  v81,
                  v83);
          objc_release(0LL);
          objc_release(v84);
        }
        else
        {
          v46 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
          objc_msgSend(0LL, "altitude");
          v48 = v47;
          objc_msgSend(0LL, "horizontalAccuracy");
          v50 = v49;
          objc_msgSend(0LL, "verticalAccuracy");
          v52 = v51;
          objc_msgSend(0LL, "course");
          v54 = v53;
          objc_msgSend(0LL, "speed");
          v56 = v55;
          objc_msgSend(0LL, "timestamp");
          v57 = objc_retainAutoreleasedReturnValue();
          v58 = v57;
          v59 = objc_msgSend(
                  v46,
                  "initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
                  v57,
                  v100,
                  v101,
                  v48,
                  v50,
                  v52,
                  v54,
                  v56);
          v60 = lastFakeFromLocation;
          lastFakeFromLocation = (__int64)v59;
          objc_release(v60);
          objc_release(v58);
          v61 = objc_msgSend(&OBJC_CLASS___CLLocation, "alloc");
          objc_msgSend(0LL, "altitude");
          v63 = v62;
          objc_msgSend(0LL, "horizontalAccuracy");
          v65 = v64;
          objc_msgSend(0LL, "verticalAccuracy");
          v67 = v66;
          objc_msgSend(0LL, "course");
          v69 = v68;
          objc_msgSend(0LL, "speed");
          v71 = v70;
          objc_msgSend(0LL, "timestamp");
          v72 = objc_retainAutoreleasedReturnValue();
          v92 = objc_msgSend(
                  v61,
                  "initWithCoordinate:altitude:horizontalAccuracy:verticalAccuracy:course:speed:timestamp:",
                  v72,
                  v100,
                  v101,
                  v63,
                  v65,
                  v67,
                  v69,
                  v71);
          objc_release(0LL);
          objc_release(v72);
        }
        _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, v92, v92);
        objc_storeStrong();
        objc_storeStrong();
        v95 = 0;
        goto LABEL_33;
      }
      _objc_msgSend(v105, "replacedLocationManager:didUpdateToLocation:fromLocation:", 0LL, 0LL, 0LL);
    LABEL_40:
      v95 = 0;
    LABEL_41:
      objc_storeStrong();
      objc_storeStrong();
      objc_storeStrong();
      objc_storeStrong();
      if ( v95 > 1 )
        headingToLocation(v85, v86, v87, v88);
    }

    0x04:总结

    1. 虽然与服务器交互的数据是加密的,但软件保护逻辑比较简单,实现修改地理位置的功能主要是通过hook获取位置的函数。

    欢迎关注公众号

  • 相关阅读:
    静态导入
    OC中的Debug表达式
    友盟消息推送(一)
    Xcode7.0 更新完后,网络请求报错
    HTTP返回的状态码
    ios 通知监听App进入后台,然后再进入App(获取验证码的时间间隔)
    iOS保存model数据(自定义Model 可以存放到本地)
    tatableView 刷新
    iOS bounds和Frame的区别
    UIButton下面添加滑动的线
  • 原文地址:https://www.cnblogs.com/2014asm/p/9866901.html
Copyright © 2011-2022 走看看