上篇說了OpenUDID。
在mpaas裏直接把循環後由+[UTDIDOpenUDID _generateFreshOpenUDID]生成方法改成了[[[UTDIDMain alloc] init] value]
var_C0 = [var_60 keysSortedByValueUsingSelector:@selector(compare:)];
if ((var_C0 != 0x0) && ([var_C0 count] > 0x0)) {
var_168 = [var_C0 lastObject];
}
else {
var_168 = 0x0;
}
var_C8 = var_168;
if (var_30 == 0x0) {
if (var_C8 == 0x0) {
var_30 = [[[UTDIDMain alloc] init] value];
}
else {
var_30 = var_C8;
}
if (var_50 == 0x0) {
var_50 = [NSMutableDictionary dictionaryWithCapacity:0x4];
[var_50 setObject:var_30 forKey:@"UTDID"];
[var_50 setObject:var_68 forKey:@"UTDID_appUID"];
[var_50 setObject:[NSDate date] forKey:@"UTDID_createdTS"];
if ((var_41 & 0x1) != 0x0) {
[var_50 setObject:var_40 forKey:@"UTDID_createdTS"];
}
var_42 = 0x1;
}
}
UTDIDMain初始化時由UTDIDMain提供 aes祕鑰 , [UTDIDPersistentConf initWithIdentifier:@"Alvin"]持久配置
參考:阿里移動數據安全UTDID分析 這篇的先後判斷邏輯。
從NSUserDefaults取值
var_-168 = [NSUserDefaults standardUserDefaults];
rax = [var_-168 retain];
var_-56 = rax;
var_-184 = [rax objectForKey:@"PK_455469921"];
不是空的話dePack 退包,是驗證都是意思嗎?
void * -[UTDIDHelper dePack:](void * self, void * _cmd, void * arg2) {
objc_storeStrong(&var_80, arg2);
//解密
var_88 = [[UTDIDAES AES256DecryptWithKey:0x0 forKey:self->mAESKey] retain];
if ([var_88 length] == 0x16) {
var_A0 = [[UTDIDBaseUtils platform] retain];
if (0x0 != var_A0) {
var_A8 = [[UTDIDIntUtils bytes:[UTDIDStringUtils hashCode:var_A0]] retain];
var_C0 = [[var_88 subdataWithRange:0x0] retain];
var_C8 = [[UTDIDIntUtils bytes:0x0] retain];
if ((([var_C8 isEqualToData:var_C0] & 0x1) == 0x0) && (([var_A8 isEqualToData:var_C0] & 0x1) == 0x0)) {
var_68 = 0x0;
var_CC = 0x1;
}
else {
var_CC = 0x0;
}
objc_storeStrong(&var_C8, 0x0);
objc_storeStrong(&var_C0, 0x0);
objc_storeStrong(&var_A8, 0x0);
if (var_CC == 0x0) {
var_E8 = [[var_88 subdataWithRange:0x4] retain];
var_68 = [var_E8 retain];
objc_storeStrong(&var_E8, 0x0);
}
}
else {
var_E8 = [[var_88 subdataWithRange:0x4] retain];
var_68 = [var_E8 retain];
objc_storeStrong(&var_E8, 0x0);
}
objc_storeStrong(&var_A0, 0x0);
}
else {
var_68 = 0x0;
}
var_80 = 0x0;
objc_storeStrong(&var_88, 0x0);
objc_storeStrong(&var_80, 0x0);
rax = [var_68 autorelease];
return rax;
}
解密,取設備平臺hw.machine,然後每個字節比對。
是空的話也解密?然後[var_10->mDevicePersistentConfig setObject:var_40 forKey:@"c"];
然後生成與存儲
void * -[UTDIDMain generateUtdidAndSave](void * self, void * _cmd) {
var_10 = self;
var_20 = [[UTDIDMain generateUtdid] retain];
var_28 = [[var_10->mUtdidHelper pack:var_20] retain];
if (([var_10 isUtdidValid:var_28] & 0x1) == 0x0) {
var_8 = 0x0;
}
else {
[var_10 saveUtdid:var_28];
var_8 = [var_20 retain];
}
objc_storeStrong(&var_28, 0x0);
objc_storeStrong(&var_20, 0x0);
rax = [var_8 autorelease];
return rax;
}
+[UTDIDMain generateUtdid]
void * +[UTDIDMain generateUtdid](void * self, void * _cmd) {
var_18 = [[NSMutableData alloc] init];
rax = [NSDate date];
rax = [rax retain];
var_74 = intrinsic_cvttsd2si([rax timeIntervalSince1970], xmm0);
[rax release];
rax = arc4random();
var_20 = rax - -(rax * 0x80000001 >> 0x3f);
var_21 = 0x3;
var_22 = 0x0;
var_30 = [[UTDIDMain uniqueGlobalDeviceIdentifier] retain];
rax = [UTDIDIntUtils bytes:var_74];
rax = [rax retain];
var_38 = rax;
[var_18 appendData:rax];
rax = [UTDIDIntUtils bytes:var_20];
rax = [rax retain];
rdi = var_38;
var_38 = rax;
[rdi release];
[var_18 appendData:var_38];
[var_18 appendBytes:&var_21 length:0x1];
[var_18 appendBytes:&var_22 length:0x1];
rax = [UTDIDStringUtils hashCode:var_30];
rax = [UTDIDIntUtils bytes:rax];
rax = [rax retain];
rdi = var_38;
var_38 = rax;
[rdi release];
[var_18 appendData:var_38];
rax = [UTDIDBaseUtils hmacBase64Value:var_18 key:"d6fc3a4a06adbde89223bvefedc24fecde188aaa9161"];
rax = [rax retain];
var_48 = rax;
rax = [UTDIDStringUtils hashCode:rax];
rax = [UTDIDIntUtils bytes:rax];
rax = [rax retain];
var_58 = rax;
[var_18 appendData:rax];
var_88 = [var_18 retain];
objc_storeStrong(&var_58, 0x0);
objc_storeStrong(&var_48, 0x0);
objc_storeStrong(&var_38, 0x0);
objc_storeStrong(&var_30, 0x0);
objc_storeStrong(&var_18, 0x0);
rax = [var_88 autorelease];
return rax;
}
上面是核心算法:取時間戳 隨機數
然後用系統方法創建uuid
void * +[UTDIDMain uniqueGlobalDeviceIdentifier](void * self, void * _cmd) {
var_-32 = CFUUIDCreate(0x0);
var_-40 = CFUUIDCreateString(0x0, var_-32);
CFRelease(var_-32);
if (0x0 == var_-40) {
var_-8 = [[UTDIDBaseUtils uniqueID] retain];
}
else {
var_-8 = [var_-40 retain];
}
objc_storeStrong(&var_-40, 0x0);
rax = [var_-8 autorelease];
return rax;
}
var_-8 = [[UTDIDBaseUtils uniqueID] retain];這個基本用不上。
然後生成hmac,rax = [UTDIDBaseUtils hmacBase64Value:var_-24 key:"d6fc3a4a06adbde89223bvefedc24fecde188aaa9161"];
拼接二進制,再轉字節,
猜的沒錯,斷點截圖
核心代碼試着放到工程裏更直觀的看看
//
// UTDIDMain+YYY.h
//
// Created by YYY on 2020/3/4.
//
NS_ASSUME_NONNULL_BEGIN
@interface UTDIDMain : NSObject
+ (id)uniqueGlobalDeviceIdentifier;
@end
@interface UTDIDMain (YYY)
@end
NS_ASSUME_NONNULL_END
//
// UTDIDMain+YYY.m
//
// Created by YYY on 2020/3/4.
//
#import "UTDIDMain+YYY.h"
#import <objc/runtime.h>
@interface UTDIDIntUtils : NSObject
{
}
+ (id)bytes:(unsigned int)arg1;
+ (int)positive:(int)arg1;
@end
@interface UTDIDStringUtils : NSObject
{
}
+ (int)hashCode:(id)arg1;
+ (_Bool)isEmpty:(id)arg1;
@end
@interface UTDIDBaseUtils : NSObject
{
}
+ (id)hmacBase64Value:(id)arg1 key:(char *)arg2;
+ (id)platform;
+ (id)uniqueID;
@end
@implementation UTDIDMain (YYY)
+(NSData*)generateUtdidS {
NSMutableData *var_24 = [[NSMutableData alloc] init];
NSDate *rax0 = [NSDate date];//2020-03-03 16:33:21 +0000
NSTimeInterval var_116 = [rax0 timeIntervalSince1970];//1583253201.224169
uint32_t rax1 = arc4random();//3935423772
uint32_t var_32 = (rax1 * 0x80000001 >> 0x3f);//0
int var_33 = 0x3;
int var_34 = 0x0;
NSString *var_48 = [UTDIDMain uniqueGlobalDeviceIdentifier] ;//F37FA956-45E4-4CB6-811A-AA2C9CB03D75
NSData *rax2 = [UTDIDIntUtils bytes:var_116];//<5e5e86d1>
NSData *var_56 = rax2;
[var_24 appendData:rax2];//第一步 先拼時間戳生成的dbyte
NSData * rax3 = [UTDIDIntUtils bytes:var_32];//
NSData *rdi = var_56;
var_56 = rax3;
[var_24 appendData:var_56];//第二步 拼接隨機數右移的值
[var_24 appendBytes:&var_33 length:0x1];//第3步 拼接1
[var_24 appendBytes:&var_34 length:0x1];//第4步 拼接1
Byte rax4 = [UTDIDStringUtils hashCode:var_48];
NSData* rax5 = [UTDIDIntUtils bytes:rax4];//<00000057>
rdi = var_56;
var_56 = rax5;
[var_24 appendData:var_56];////第5步 拼接uniqueGlobalDeviceIdentifier hashCode的值
NSData* rax6 = [UTDIDBaseUtils hmacBase64Value:var_24 key:"d6fc3a4a06adbde89223bvefedc24fecde188aaa9161"];//zBc/8BGEZzWAAEgG0shNPItLQs8=
int rax7 = [UTDIDStringUtils hashCode:rax6];//-797734293
NSData *rax8 = [UTDIDIntUtils bytes:rax7];//<d0738a6b>
[var_24 appendData:rax8];//第6步 拼接hmacBase64Value hashCode的值
NSData* var_136 = var_24 ;
return var_136;//<5e5e86d1 00000000 03000000 0057d073 8a6b>
}
@end
總結核心代碼生成步驟:
//第一步 先拼時間戳生成的byte
//第二步 拼接隨機數右移的值
//第3步 拼接3
//第4步 拼接0
//第5步 拼接uniqueGlobalDeviceIdentifier hashCode的值
//第6步 拼接hmacBase64Value hashCode的值