IOS防作弊产品技术原理分析

本文介绍了iOS防作弊产品的技术原理,包括SDK整体框架和详细的技术细节分析。在iOS上,由于系统的封闭性,防作弊主要依赖于获取IDFA、IDFV及风险APP信息。SDK在APP启动时生成唯一ID,并通过加密通信与服务器交互,防止设备模拟。同时,文章还涵盖了设备ID的生成、风险信息的上报等关键步骤。
摘要由CSDN通过智能技术生成

由于时间和水平有限,本文会存在诸多不足,希望得到您的及时反馈与指正,多谢!

工具环境:
iPhone 6、
系统版本 10.1.1
IDA Pro 7.0

0x00:防作弊产品介绍

1.由于IOS系统的不开放性,能获取的信息太少,所在IOS上的防作弊产品可做的功能就相比较于安卓要少很多了。硬件方面主要获取IDFA、IDFV这两个值,软件方面主要获取一些风险APP的名称。

0x01:SDK整体框架

1.该防作弊产品提供SDK形式给开发者调用,当开发者成功集成到APP后,APP启动时就会生成一个唯一的ID值。

2.SDK客户端整体流程如图1所示:

                图1

3.服务器返回的ID会存放在系统中,这个ID值用通俗的话说,就是为每台设备注册一个身份证号,它代表了设备。这样一来,如果刷量者通过hook机制来修改IDFA、mac等设备模拟新用户就不起作用了。

0x02:技术细节分析

1.APP启动时会解密会判断本地是否缓存了deviceID值与风险app名单,如果没有就生成一个随机的deviceid然后解密写死在app中的风险文件名单。

2.从服务器获取deviceid值

如果没有缓存ID就生成一个ID,生成随机的deviceID代码如下:

  1 // 第一次生成deviceid (uuid+当前时间)
  2 id __cdecl -[SmidManager genFpId](SmidManager *self, SEL a2)
  3 {
  4   __int64 v2; // x0
  5   __int64 v3; // x0
  6   __int64 v4; // x0
  7   __int64 v5; // x0
  8   void *v6; // x0
  9   void *v7; // x0
 10   void *v8; // x0
 11   void *v9; // x0
 12   void *second; // x0
 13   void *v11; // x0
 14   __int64 v12; // x0
 15   __int64 currtime; // ST68_8
 16   id v14; // x0
 17   __int64 uuid_md5; // x0
 18   __int64 v16; // ST58_8
 19   void *v17; // x0
 20   void *v18; // x0
 21   void *v19; // x0
 22   void *v20; // x0
 23   void *v21; // x9
 24   void *v22; // x0
 25   void *v23; // x0
 26   void *v24; // x9
 27   void *v25; // x0
 28   void *v26; // x0
 29   void *v27; // x9
 30   void *v28; // x0
 31   void *v29; // x0
 32   void *v30; // x9
 33   void *v31; // x0
 34   void *v32; // x0
 35   void *v33; // x9
 36   void *v34; // x0
 37   void *v35; // x0
 38   void *v36; // x9
 39   void *v37; // x0
 40   void *v38; // x0
 41   void *v39; // x9
 42   void *v40; // x0
 43   void *v41; // x0
 44   void *v42; // x9
 45   void *v43; // x0
 46   struct objc_object *v44; // x0
 47   struct objc_object *v45; // ST38_8
 48   id v46; // x0
 49   void *v47; // x0
 50   __int64 v48; // x0
 51   void *v49; // x0
 52   __int64 v50; // ST30_8
 53   __int64 v52; // [xsp+98h] [xbp-B8h]
 54   void *v53; // [xsp+A0h] [xbp-B0h]
 55   void *v54; // [xsp+A8h] [xbp-A8h]
 56   void *v55; // [xsp+B0h] [xbp-A0h]
 57   __int64 v56; // [xsp+B8h] [xbp-98h]
 58   void *v57; // [xsp+C0h] [xbp-90h]
 59   void *minute; // [xsp+C8h] [xbp-88h]
 60   void *hour; // [xsp+D0h] [xbp-80h]
 61   void *day; // [xsp+D8h] [xbp-78h]
 62   void *month; // [xsp+E0h] [xbp-70h]
 63   void *year; // [xsp+E8h] [xbp-68h]
 64   void *v63; // [xsp+F0h] [xbp-60h]
 65   __int64 v64; // [xsp+F8h] [xbp-58h]
 66   void *v65; // [xsp+100h] [xbp-50h]
 67   __int64 v66; // [xsp+108h] [xbp-48h]
 68   struct objc_object *uuid; // [xsp+110h] [xbp-40h]
 69   __int64 v68; // [xsp+118h] [xbp-38h]
 70   __int64 v69; // [xsp+120h] [xbp-30h]
 71   SEL v70; // [xsp+128h] [xbp-28h]
 72   SmidManager *v71; // [xsp+130h] [xbp-20h]
 73   __int64 v72; // [xsp+138h] [xbp-18h]
 74 
 75   v71 = self;
 76   v70 = a2;
 77   v2 = CFUUIDCreate();
 78   v69 = v2;
 79   v3 = CFUUIDCreateString(0LL, v2);
 80   v68 = v3;
 81   v4 = CFStringCreateCopy(0LL, v3);
 82   v72 = v4;
 83   v5 = objc_autoreleaseReturnValue(v4);
 84   uuid = (struct objc_object *)objc_retainAutoreleasedReturnValue(v5);
 85   CFRelease(v69);
 86   CFRelease(v68);
 87   v6 = objc_msgSend(&OBJC_CLASS___NSDate, (const char *)&unk_195EEC6AF);
 88   v66 = objc_retainAutoreleasedReturnValue(v6);
 89   v7 = objc_msgSend(&OBJC_CLASS___NSCalendar, (const char *)&unk_195F34590);
 90   v8 = (void *)objc_retainAutoreleasedReturnValue(v7);
 91   v65 = v8;
 92   v64 = 252LL;
 93   v9 = objc_msgSend(v8, (const char *)&unk_195F345E4, 252LL, v66);
 94   v63 = (void *)objc_retainAutoreleasedReturnValue(v9);
 95   year = objc_msgSend(v63, (const char *)&unk_195F9F96E);
 96   month = objc_msgSend(v63, (const char *)&unk_195F9F973);
 97   day = objc_msgSend(v63, (const char *)&unk_195F9F979);
 98   hour = objc_msgSend(v63, (const char *)&unk_195F34810);
 99   minute = objc_msgSend(v63, (const char *)&unk_195F5F105);
100   second = objc_msgSend(v63, (const char *)&unk_195F5F10C);
101   v57 = second;
102   v11 = objc_msgSend(
103           &OBJC_CLASS___NSString,
104           (const char *)&unk_195EDDC2A,
105           CFSTR("%04d%02d%02d%02d%02d%02d"),
106           year,
107           month,
108           day,
109           hour,
110           minute,
111           second);
112   v12 = objc_retainAutoreleasedReturnValue(v11);
113   v56 = v12;
114   currtime = v12;
115   v14 = ((id (__cdecl *)(SmUtils_meta *, SEL, id))objc_msgSend)(
116           (SmUtils_meta *)&OBJC_CLASS___SmUtils,
117           "md5EncodeStr:",
118           uuid);
119   uuid_md5 = objc_retainAutoreleasedReturnValue(v14);
120   v16 = uuid_md5;
121   v17 = objc_msgSend(
122           &OBJC_CLASS___NSString,
123           (const char *)&unk_195EDDC2A,
124           CFSTR("%@%@%@"),
125           currtime,
126           uuid_md5,
127           CFSTR("00"));
128   v55 = (void *)objc_retainAutoreleasedReturnValue(v17);
129   objc_release(v16);
130   v18 = (void *)objc_retain(&stru_1027FA700);
131   v54 = v18;
132   v19 = objc_msgSend(v18, (const char *)&unk_195EF0B91, CFSTR("shumei"));
133   v20 = (void *)objc_retainAutoreleasedReturnValue(v19);
134   v21 = v54;
135   v54 = v20;
136   objc_release(v21);
137   v22 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("_"));
138   v23 = (void *)objc_retainAutoreleasedReturnValue(v22);
139   v24 = v54;
140   v54 = v23;
141   objc_release(v24);
142   v25 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("ios"));
143   v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
144   v27 = v54;
145   v54 = v26;
146   objc_release(v27);
147   v28 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("_"));
148   v29 = (void *)objc_retainAutoreleasedReturnValue(v28);
149   v30 = v54;
150   v54 = v29;
151   objc_release(v30);
152   v31 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("sec"));
153   v32 = (void *)objc_retainAutoreleasedReturnValue(v31);
154   v33 = v54;
155   v54 = v32;
156   objc_release(v33);
157   v34 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("_"));
158   v35 = (void *)objc_retainAutoreleasedReturnValue(v34);
159   v36 = v54;
160   v54 = v35;
161   objc_release(v36);
162   v37 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("key"));
163   v38 = (void *)objc_retainAutoreleasedReturnValue(v37);
164   v39 = v54;
165   v54 = v38;
166   objc_release(v39);
167   v40 = objc_msgSend(v54, (const char *)&unk_195EF0B91, CFSTR("_"));
168   v41 = (void *)objc_retainAutoreleasedReturnValue(v40);
169   v42 = v54;
170   v54 = v41;
171   objc_release(v42);
172   v43 = objc_msgSend(&OBJC_CLASS___NSString, (const char *)&unk_195EDDC2A, CFSTR("%@%@"), v54, v55);
173   v44 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v43);
174   v45 = v44;
175   v46 = ((id (__cdecl *)(SmUtils_meta *, SEL, id))objc_msgSend)(
176           (SmUtils_meta *)&OBJC_CLASS___SmUtils,
177           "md5EncodeStr:",
178           v44);
179   v53 = (void *)objc_retainAutoreleasedReturnValue(v46);
180   objc_release(v45);
181   v47 = objc_msgSend(v53, (const char *)&unk_195F19145, 14LL);
182   v48 = objc_retainAutoreleasedReturnValue(v47);
183   v52 = v48;
184   v49 = objc_msgSend(v55, (const char *)&unk_195EF0B91, v48);
185   v50 = objc_retainAutoreleasedReturnValue(v49);
186   objc_storeStrong(&v52, 0LL);
187   objc_storeStrong(&v53, 0LL);
188   objc_storeStrong(&v54, 0LL);
189   objc_storeStrong(&v55, 0LL);
190   objc_storeStrong(&v56, 0LL);
191   objc_storeStrong(&v63, 0LL);
192   objc_storeStrong(&v65, 0LL);
193   objc_storeStrong(&v66, 0LL);
194   objc_storeStrong(&uuid, 0LL);
195   return (id)objc_autoreleaseReturnValue(v50);
196 }

判断deviceID类型 本地随机生成为0 服务下发的为1

  1 signed __int64 __cdecl +[SmidManager typeId:](SmidManager_meta *self, SEL a2, id a3)
  2 {
  3   void *v3; // x0
  4   void *v4; // x0
  5   void *v5; // x0
  6   void *v6; // x8
  7   void *v7; // x0
  8   void *v8; // x0
  9   void *v9; // x8
 10   void *v10; // x0
 11   void *v11; // x0
 12   void *v12; // x8
 13   void *v13; // x0
 14   void *v14; // x0
 15   void *v15; // x8
 16   void *v16; // x0
 17   void *v17; // x0
 18   void *v18; // x8
 19   void *v19; // x0
 20   void *v20; // x0
 21   void *v21; // x8
 22   void *v22; // x0
 23   void *v23; // x0
 24   void *v24; // x8
 25   void *v25; // x0
 26   void *v26; // x0
 27   void *v27; // x8
 28   void *v28; // x0
 29   __int64 v29; // x0
 30   __int64 v30; // ST18_8
 31   void *v31; // x0
 32   id v32; // x0
 33   void *v33; // x0
 34   void *v34; // x0
 35   __int64 v35; // x0
 36   __int64 v36; // x8
 37   void *v37; // x0
 38   __int64 v39; // [xsp+68h] [xbp-48h]
 39   void *v40; // [xsp+70h] [xbp-40h]
 40   struct objc_object *v41; // [xsp+78h] [xbp-38h]
 41   void *v42; // [xsp+80h] [xbp-30h]
 42   int v43; // [xsp+8Ch] [xbp-24h]
 43   void *v44; // [xsp+90h] [xbp-20h]
 44   SEL v45; // [xsp+98h] [xbp-18h]
 45   SmidManager_meta *v46; // [xsp+A0h] [xbp-10h]
 46   __int64 v47; // [xsp+A8h] [xbp-8h]
 47 
 48   v46 = self;
 49   v45 = a2;
 50   v44 = 0LL;
 51   objc_storeStrong(&v44, a3);
 52   if ( (unsigned __int64)+[SmStrUtils empty:](&OBJC_CLASS___SmStrUtils, "empty:", v44) & 1
 53     || objc_msgSend(v44, (const char *)&unk_195EE38EE) != &unk_3E )
 54   {
 55     v47 = -1LL;
 56     v43 = 1;
 57   }
 58   else
 59   {
 60     v3 = (void *)objc_retain(&stru_1027FA700);
 61     v42 = v3;
 62     v4 = objc_msgSend(v3, (const char *)&unk_195EF0B91, CFSTR("shumei"));
 63     v5 = (void *)objc_retainAutoreleasedReturnValue(v4);
 64     v6 = v42;
 65     v42 = v5;
 66     objc_release(v6);
 67     v7 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("_"));
 68     v8 = (void *)objc_retainAutoreleasedReturnValue(v7);
 69     v9 = v42;
 70     v42 = v8;
 71     objc_release(v9);
 72     v10 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("ios"));
 73     v11 = (void *)objc_retainAutoreleasedReturnValue(v10);
 74     v12 = v42;
 75     v42 = v11;
 76     objc_release(v12);
 77     v13 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("_"));
 78     v14 = (void *)objc_retainAutoreleasedReturnValue(v13);
 79     v15 = v42;
 80     v42 = v14;
 81     objc_release(v15);
 82     v16 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("sec"));
 83     v17 = (void *)objc_retainAutoreleasedReturnValue(v16);
 84     v18 = v42;
 85     v42 = v17;
 86     objc_release(v18);
 87     v19 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("_"));
 88     v20 = (void *)objc_retainAutoreleasedReturnValue(v19);
 89     v21 = v42;
 90     v42 = v20;
 91     objc_release(v21);
 92     v22 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("key"));
 93     v23 = (void *)objc_retainAutoreleasedReturnValue(v22);
 94     v24 = v42;
 95     v42 = v23;
 96     objc_release(v24);
 97     v25 = objc_msgSend(v42, (const char *)&unk_195EF0B91, CFSTR("_"));
 98     v26 = (void *)objc_retainAutoreleasedReturnValue(v25);
 99     v27 = v42;
100     v42 = v26;
101     objc_release(v27);
102     v28 = objc_msgSend(v44, (const char *)&unk_195F19145, 48LL);
103     v29 = objc_retainAutoreleasedReturnValue(v28);
104     v30 = v29;
105     v31 = objc_msgSend(&OBJC_CLASS___NSString, (const char *)&unk_195EDDC2A, CFSTR("%@%@"), v42, v29);
106     v41 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v31);
107     objc_release(v30);
108     v32 = ((id (__cdecl *)(SmUtils_meta *, SEL, id))objc_msgSend)(
109             (SmUtils_meta *)&OBJC_CLASS___SmUtils,
110             "md5EncodeStr:",
111             v41);
112     v33 = (void *)objc_retainAutoreleasedReturnValue(v32);
113     v40 = v33;
114     v34 = objc_msgSend(v33, (const char *)&unk_195F19145, 14LL);
115     v35 = objc_retainAutoreleasedReturnValue(v34);
116     v36 = (__int64)v40;
117     v40 = (void *)v35;
118     objc_release(v36);
119     v37 = objc_msgSend(v44, (const char *)&unk_195EDFD20, 48LL);
120     v39 = objc_retainAutoreleasedReturnValue(v37);
121     if ( (unsigned __int64)+[SmStrUtils equal:right:](&OBJC_CLASS___SmStrUtils, "equal:right:", v40, v39) & 1 )
122     {
123       if ( (unsigned __int16)objc_msgSend(v44, (const char *)&unk_195F17186, 47LL) == 48 )
124       {
125         v47 = 0LL;
126         v43 = 1;
127       }
128       else
129       {
130         if ( (unsigned __int16)objc_msgSend(v44, (const char *)&unk_195F17186, 47LL) == 49 )
131           v47 = 1LL;
132         else
133           v47 = -1LL;
134         v43 = 1;
135       }
136     }
137     else
138     {
139       v47 = 2LL;
140       v43 = 1;
141     }
142     objc_storeStrong(&v39, 0LL);
143     objc_storeStrong(&v40, 0LL);
144     objc_storeStrong(&v41, 0LL);
145     objc_storeStrong(&v42, 0LL);
146   }
147   objc_storeStrong(&v44, 0LL);
148   return v47;
149 }

将获取到的硬件信息与刚生成的deviceid组合加密传给服务器,如果成功服务器就返回一个deviceID值。

 1 //组合请求体
 2 {
 3     "lstat":[
 4         1,
 5         0
 6     ],
 7     "idfa":"56076342-6AA8-4EF3-A3B3-FF0E2C6Exxxx",
 8     "os":"ios",
 9     "rtype":"core",
10     "t":1559112353610,
11     "sdkver":"2.5.0",
12     "idfv":"DFF15047-2F42-4612-8BE2-8D0B2482xxxx",
13     "boot":1559009952219,
14     "appId":"",
15     "lfrom":"gen",
16     "smid":"2019052914070272ea50eee30ea85b0bcc2141c04e5bcd00ebfc34bfe82ae9" //本地随机生成
17 }

加密传给服务器 获取deviceid key为smsdkWd4Z1WnKWa9R3ud4Jxxx(md5值)

  1 id __cdecl -[SmAntiFraud wrap:](SmAntiFraud *self, SEL a2, id a3)
  2 {
  3   void *v3; // x0
  4   __int64 v4; // x0
  5   __int64 v5; // STD0_8
  6   void *v6; // x0
  7   void *v7; // STC8_8
  8   void *v8; // x0
  9   __int64 v9; // x0
 10   __int64 v10; // STC0_8
 11   void *v11; // x0
 12   id v12; // x0
 13   void *v13; // x0
 14   void *v14; // STB8_8
 15   void *v15; // x0
 16   id v16; // x0
 17   __int64 v17; // x0
 18   __int64 v18; // x8
 19   NSMutableDictionary *v19; // x0
 20   void *v20; // x0
 21   void *v21; // STA8_8
 22   char v22; // STA4_1
 23   void *v23; // x0
 24   __int64 v24; // ST90_8
 25   void *v25; // x0
 26   __int64 v26; // ST78_8
 27   id v27; // x0
 28   __int64 v28; // x0
 29   __int64 v29; // ST58_8
 30   void *v30; // x0
 31   void *v31; // x0
 32   __int64 v32; // x0
 33   const __CFString *v33; // x9
 34   __int64 v34; // ST48_8
 35   void *v35; // x0
 36   id v36; // x0
 37   struct objc_object *v37; // x0
 38   id v38; // x0
 39   __int64 v39; // x0
 40   __int64 v40; // x8
 41   __int64 v41; // ST30_8
 42   __int64 v43; // [xsp+D8h] [xbp-68h]
 43   struct objc_object *v44; // [xsp+E0h] [xbp-60h]
 44   __int64 v45; // [xsp+E8h] [xbp-58h]
 45   void *v46; // [xsp+F0h] [xbp-50h]
 46   struct objc_object *v47; // [xsp+F8h] [xbp-48h]
 47   struct objc_object *v48; // [xsp+100h] [xbp-40h]
 48   __int64 v49; // [xsp+108h] [xbp-38h]
 49   char v50; // [xsp+117h] [xbp-29h]
 50   struct objc_object *v51; // [xsp+118h] [xbp-28h]
 51   SEL v52; // [xsp+120h] [xbp-20h]
 52   SmAntiFraud *v53; // [xsp+128h] [xbp-18h]
 53 
 54   v53 = self;
 55   v52 = a2;
 56   v51 = 0LL;
 57   objc_storeStrong(&v51, a3);
 58   if ( (unsigned __int64)+[SmStrUtils empty:](&OBJC_CLASS___SmStrUtils, "empty:", v51) & 1 )
 59     objc_storeStrong(&v51, &stru_1027FA700);
 60   v50 = 0;
 61   v49 = 0LL;
 62   if ( (unsigned __int64)objc_msgSend(v53->_option, (const char *)&unk_1A7804C37) & 1 )
 63   {
 64     v3 = objc_msgSend(v53->_option, (const char *)&unk_192B2C190);
 65     v4 = objc_retainAutoreleasedReturnValue(v3);
 66     v5 = v4;
 67     v6 = objc_msgSend(CFSTR("smsdk"), (const char *)&unk_195EF0B91, v4);
 68     v7 = (void *)objc_retainAutoreleasedReturnValue(v6);
 69     v8 = -[SmOption privKey](v53->_option, "privKey");
 70     v9 = objc_retainAutoreleasedReturnValue(v8);
 71     v10 = v9;
 72     v11 = objc_msgSend(v7, (const char *)&unk_195EF0B91, v9);
 73     v48 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v11);
 74     objc_release(v10);
 75     objc_release(v7);
 76     objc_release(v5);
 77     v12 = ((id (__cdecl *)(SmUtils_meta *, SEL, id))objc_msgSend)(
 78             (SmUtils_meta *)&OBJC_CLASS___SmUtils,
 79             "md5EncodeStr:",
 80             v48);
 81     v13 = (void *)objc_retainAutoreleasedReturnValue(v12);
 82     v14 = v13;
 83     v15 = objc_msgSend(v13, (const char *)&unk_195F390C0);
 84     v47 = (struct objc_object *)objc_retainAutoreleasedReturnValue(v15);
 85     objc_release(v14);
 86     v16 = ((id (__cdecl *)(SmUtils_meta *, SEL, id, id))objc_msgSend)(
 87             (SmUtils_meta *)&OBJC_CLASS___SmUtils,
 88             "aes256EncryptStr:key:",
 89             v51,
 90             v47);
 91     v17 = objc_retainAutoreleasedReturnValue(v16);
 92     v18 = v49;
 93     v49 = v17;
 94     objc_release(v18);
 95     v50 = 1;
 96     objc_storeStrong(&v47, 0LL);
 97     objc_storeStrong(&v48, 0LL);
 98   }
 99   else
100   {
101     objc_storeStrong(&v49, v51);
102   }
103   if ( (unsigned __int64)+[SmStrUtils empty:](&OBJC_CLASS___SmStrUtils, "empty:", v49) & 1 )
104     objc_storeStrong(&v49, &stru_1027FA700)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值