源码加上翻译是
// Private method to create and return a new OpenUDID
// Theoretically, this function is called once ever per application when calling [OpenUDID value] for the first time.
// After that, the caching/pasteboard/redundancy mechanism inside [OpenUDID value] returns a persistent and cross application OpenUDID
//
//创建并返回新OpenUDID的私有方法
//理论上,当第一次调用[OpenUDID value]时,每个应用程序都会调用此函数一次。
//之后,[OpenUDID value]中的缓存/粘贴板/冗余机制返回一个持久的、跨应用程序的OpenUDID
+ (NSString*) _generateFreshOpenUDID {
NSString* _openUDID = nil;
//2011年8月:有一天,iOS可能不再允许这样做。如果是这样的话,就把这一行注释掉。
//2012年3月25日:这一天到了,让我们删除这个“非法”的电话。。。
//2012年8月:好吧,也许什么都不做;无论如何,WWDC2012给了我们一些东西来工作;请看下面
// August 2011: One day, this may no longer be allowed in iOS. When that is, just comment this line out.
// March 25th 2012: this day has come, let's remove this "outlawed" call...
// August 2012: well, perhaps much ado about nothing; in any case WWDC2012 gave us something to work with; read below
#if TARGET_OS_IPHONE
// if([UIDevice instancesRespondToSelector:@selector(uniqueIdentifier)]){
// _openUDID = [[UIDevice currentDevice] uniqueIdentifier];
// }
#endif
//
// !!!!! IMPORTANT README !!!!!
//
// August 2012: iOS 6 introduces new APIs that help us deal with the now deprecated [UIDevice uniqueIdentifier]
// Since iOS 6 is still pre-release and under NDA, the following piece of code is meant to produce an error at
// compile time. Accredited developers integrating OpenUDID are expected to review the iOS 6 release notes and
// documentation, and replace the underscore ______ in the last part of the selector below with the right
// selector syntax as described here (make sure to use the right one! last word starts with the letter "A"):
// https://developer.apple.com/library/prerelease/ios/#documentation/UIKit/Reference/UIDevice_Class/Reference/UIDevice.html
//
// !!!!! 重要自述!!!!!
//
//2012年8月:iOS 6引入了新的api,帮助我们处理现在被弃用的[UIDevice uniqueIdentifier]
//由于iOS 6仍然是预发行版,并且在NDA下,下面的代码将在
//编译时。集成OpenUDID的合格开发人员将审查iOS 6发行说明和
//文档,并将下面选择器最后部分的下划线替换为右侧
//这里描述的选择器语法(确保使用正确的语法!最后一个字以字母“A”)开头:
// The semantic compiler warnings are still normal if you are compiling for iOS 5 only since Xcode will not
// know about the two instance methods used on that line; the code running on iOS will work well at run-time.
// Either way, it's time that you junped on the iOS 6 bandwagon and start testing your code on iOS 6 ;-)
//
// WHAT IS THE SIGNIFICANCE OF THIS CHANGE?
//
// Essentially, this means that OpenUDID will keep on behaving the same way as before for existing users or
// new users in iOS 5 and before. For new users on iOS 6 and after, the new official public APIs will take over.
// OpenUDID will therefore be obsoleted when iOS reaches significant adoption, anticipated around mid-2013.
//如果只为iOS 5编译,语义编译器警告仍然是正常的,因为Xcode不会
//了解这一行中使用的两个实例方法;在iOS上运行的代码在运行时可以很好地工作。
//不管怎样,现在是时候让你沉迷于iOS 6的潮流,开始在ios6上测试你的代码了;-)
//
//这一变化的意义何在?
//
//本质上,这意味着OpenUDID将继续以与以前相同的方式对现有用户或
//iOS5及之前的新用户。对于iOS 6及以后的新用户,新的官方公共api将接管。
//因此,当iOS在2013年年中被广泛采用时,OpenUDID将被淘汰。
/*
September 14; ok, new development. The alleged API has moved!
This part of the code will therefore be updated when iOS 6 is actually released.
Nevertheless, if you want to go ahead, the code should be pretty easy to
guess... it involves including a .h file from a nine-letter framework that ends
with the word "Support", and then assigning _openUDID with the only identifier method called on the sharedManager of that new class... don't forget to add
the framework to your project!
9月14日;好的,新的发展。所谓的API已经移动了!
因此,这部分代码将在iOS 6实际发布时更新。
不过,如果您想继续,代码应该很容易
猜猜看。。。它包括一个9个字母的框架中的.h文件
使用“支持”一词,然后使用在该新类的sharedManager上调用的唯一标识符方法分配openUDID。。。别忘了加上
你的项目框架!
#if TARGET_OS_IPHONE
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) {
_openUDID = [[[UIDevice currentDevice] identifierForA_______] UUIDString];
# error ^ read comments above, fix accordingly, and remove this #error line
}
#endif
*/
// Next we generate a UUID.
// UUIDs (Universally Unique Identifiers), also known as GUIDs (Globally Unique Identifiers) or IIDs
// (Interface Identifiers), are 128-bit values guaranteed to be unique. A UUID is made unique over
// both space and time by combining a value unique to the computer on which it was generated—usually the
// Ethernet hardware address—and a value representing the number of 100-nanosecond intervals since
// October 15, 1582 at 00:00:00.
// We then hash this UUID with md5 to get 32 bytes, and then add 4 extra random bytes
// Collision is possible of course, but unlikely and suitable for most industry needs (e.g. aggregate tracking)
//
//接下来我们生成一个UUID。
//uuid(通用唯一标识符),也称为guid(全局唯一标识符)或iid
//(接口标识符)是保证唯一的128位值。UUID在
//空间和时间都是通过组合计算机所特有的值来生成的,通常
//以太网硬件地址和一个值,表示自
//1582年10月15日00:00:00。
//然后我们用md5散列这个UUID,得到32个字节,然后再添加4个随机字节
//当然,碰撞是可能的,但不太可能,而且适合大多数行业的需要(例如,聚合跟踪)
//
if (_openUDID==nil) {
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef cfstring = CFUUIDCreateString(kCFAllocatorDefault, uuid);
const char *cStr = CFStringGetCStringPtr(cfstring,CFStringGetFastestEncoding(cfstring));
unsigned char result[16];
CC_MD5( cStr, strlen(cStr), result );
CFRelease(uuid);
CFRelease(cfstring);
_openUDID = [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15],
(NSUInteger)(arc4random() % NSUIntegerMax)];
}
//给开源社区中的其他开发人员打电话:
//
//请随意建议更好或替代的“UDID”生成代码以上。
//注意,目标不是寻找更好的散列方法,而是寻找分散的方法(即,不是基于web的方法)
//160位/20字节的随机字符串生成器,可能的冲突最少。
//
// Call to other developers in the Open Source community:
//
// feel free to suggest better or alternative "UDID" generation code above.
// NOTE that the goal is NOT to find a better hash method, but rather, find a decentralized (i.e. not web-based)
// 160 bits / 20 bytes random string generator with the fewest possible collisions.
//
return _openUDID;
}
// Main public method that returns the OpenUDID
// This method will generate and store the OpenUDID if it doesn't exist, typically the first time it is called
// It will return the null udid (forty zeros) if the user has somehow opted this app out (this is subject to 3rd party implementation)
// Otherwise, it will register the current app and return the OpenUDID
//
//返回OpenUDID的主公共方法
//如果OpenUDID不存在,这个方法将生成并存储它,通常是在第一次调用它时
//如果用户以某种方式选择了此应用程序,它将返回空udid(40个零)(这取决于第三方实现)
//否则,它将注册当前应用程序并返回OpenUDID
//
+ (NSString*) value {
return [OpenUDID valueWithError:nil];
}
+ (NSString*) valueWithError:(NSError **)error {
if (kOpenUDIDSessionCache!=nil) {
if (error!=nil)
*error = [NSError errorWithDomain:kOpenUDIDDomain
code:kOpenUDIDErrorNone
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID in cache from first call",@"description", nil]];
return kOpenUDIDSessionCache;
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// The AppUID will uniquely identify this app within the pastebins
//AppUID将在pastebins中唯一标识此应用程序
NSString * appUID = [defaults objectForKey:kOpenUDIDAppUIDKey];
if(appUID == nil)
{
// generate a new uuid and store it in user defaults
CFUUIDRef uuid = CFUUIDCreate(NULL);
appUID = (NSString *) CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
[appUID autorelease];
}
NSString* openUDID = nil;
NSString* myRedundancySlotPBid = nil;
NSDate* optedOutDate = nil;
BOOL optedOut = NO;
BOOL saveLocalDictToDefaults = NO;
BOOL isCompromised = NO;
// Do we have a local copy of the OpenUDID dictionary?
// This local copy contains a copy of the openUDID, myRedundancySlotPBid (and unused in this block, the local bundleid, and the timestamp)
//
//我们有OpenUDID字典的本地副本吗?
//此本地副本包含openUDID、myRedundancySlotPBid的副本(在此块中未使用、本地bundleid和时间戳)
id localDict = [defaults objectForKey:kOpenUDIDKey];
if ([localDict isKindOfClass:[NSDictionary class]]) {
localDict = [NSMutableDictionary dictionaryWithDictionary:localDict]; // we might need to set/overwrite the redundancy slot
openUDID = [localDict objectForKey:kOpenUDIDKey];
myRedundancySlotPBid = [localDict objectForKey:kOpenUDIDSlotKey];
optedOutDate = [localDict objectForKey:kOpenUDIDOOTSKey];
optedOut = optedOutDate!=nil;
OpenUDIDLog(@"localDict = %@",localDict);
}
// Here we go through a sequence of slots, each of which being a UIPasteboard created by each participating app
// The idea behind this is to both multiple and redundant representations of OpenUDIDs, as well as serve as placeholder for potential opt-out
//
//在这里,我们将浏览一系列的插槽,每个插槽都是每个参与应用程序创建的UIPasteboard
//其背后的思想是同时使用openudid的多个和冗余表示,以及作为潜在退出的占位符
NSString* availableSlotPBid = nil;
NSMutableDictionary* frequencyDict = [NSMutableDictionary dictionaryWithCapacity:kOpenUDIDRedundancySlots];
for (int n=0; n<kOpenUDIDRedundancySlots; n++) {
NSString* slotPBid = [NSString stringWithFormat:@"%@%d",kOpenUDIDSlotPBPrefix,n];
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:slotPBid create:NO];
#else
NSPasteboard* slotPB = [NSPasteboard pasteboardWithName:slotPBid];
#endif
OpenUDIDLog(@"SlotPB name = %@",slotPBid);
if (slotPB==nil) {
// assign availableSlotPBid to be the first one available
//将availableSlotPBid指定为第一个可用的
if (availableSlotPBid==nil) availableSlotPBid = slotPBid;
} else {
NSDictionary* dict = [OpenUDID _getDictFromPasteboard:slotPB];
NSString* oudid = [dict objectForKey:kOpenUDIDKey];
OpenUDIDLog(@"SlotPB dict = %@",dict);
if (oudid==nil) {
//availableSlotPBid可以位于未找到oudid的非空插槽中
// availableSlotPBid could inside a non null slot where no oudid can be found
if (availableSlotPBid==nil) availableSlotPBid = slotPBid;
} else {
// increment the frequency of this oudid key
// 增加此oudo键的频率
int count = [[frequencyDict valueForKey:oudid] intValue];
[frequencyDict setObject:[NSNumber numberWithInt:++count] forKey:oudid];
}
// if we have a match with the app unique id,
// then let's look if the external UIPasteboard representation marks this app as OptedOut
//如果我们与应用程序唯一id匹配,
//然后让我们看看外部UIPasteboard表示是否将此应用程序标记为opendout
NSString* gid = [dict objectForKey:kOpenUDIDAppUIDKey];
if (gid!=nil && [gid isEqualToString:appUID]) {
myRedundancySlotPBid = slotPBid;
//本地词典在选择退出主题上是首选项,因此如果已经在本地选择退出,请忽略
// the local dictionary is prime on the opt-out subject, so ignore if already opted-out locally
if (optedOut) {
optedOutDate = [dict objectForKey:kOpenUDIDOOTSKey];
optedOut = optedOutDate!=nil;
}
}
}
}
//对同一OpenUDID(冗余、故障保护)中出现次数最高的频率dict进行排序
//最高的是最后一个
// sort the Frequency dict with highest occurence count of the same OpenUDID (redundancy, failsafe)
// highest is last in the list
//
NSArray* arrayOfUDIDs = [frequencyDict keysSortedByValueUsingSelector:@selector(compare:)];
NSString* mostReliableOpenUDID = (arrayOfUDIDs!=nil && [arrayOfUDIDs count]>0)? [arrayOfUDIDs lastObject] : nil;
OpenUDIDLog(@"Freq Dict = %@\nMost reliable %@",frequencyDict,mostReliableOpenUDID);
// if openUDID was not retrieved from the local preferences, then let's try to get it from the frequency dictionary above
//
//如果没有从本地首选项中检索到openUDID,那么让我们尝试从上面的频率字典中获取它
if (openUDID==nil) {
if (mostReliableOpenUDID==nil) {
// this is the case where this app instance is likely to be the first one to use OpenUDID on this device
// we create the OpenUDID, legacy or semi-random (i.e. most certainly unique)
//
//在这种情况下,此应用程序实例可能是第一个在此设备上使用OpenUDID的应用程序实例
//我们创建OpenUDID、legacy或半随机(也就是说,非常独特)
//
openUDID = [OpenUDID _generateFreshOpenUDID];
} else {
// or we leverage the OpenUDID shared by other apps that have already gone through the process
//
//或者我们利用其他已经完成这个过程的应用程序共享的OpenUDID
openUDID = mostReliableOpenUDID;
}
// then we create a local representation
//
//然后我们创建一个局部表示
if (localDict==nil) {
localDict = [NSMutableDictionary dictionaryWithCapacity:4];
[localDict setObject:openUDID forKey:kOpenUDIDKey];
[localDict setObject:appUID forKey:kOpenUDIDAppUIDKey];
[localDict setObject:[NSDate date] forKey:kOpenUDIDTSKey];
if (optedOut) [localDict setObject:optedOutDate forKey:kOpenUDIDTSKey];
saveLocalDictToDefaults = YES;
}
}
else {
// Sanity/tampering check
////健全/篡改检查
if (mostReliableOpenUDID!=nil && ![mostReliableOpenUDID isEqualToString:openUDID])
isCompromised = YES;
}
// Here we store in the available PB slot, if applicable
////如果适用,我们将存储在可用的PB插槽中
OpenUDIDLog(@"Available Slot %@ Existing Slot %@",availableSlotPBid,myRedundancySlotPBid);
if (availableSlotPBid!=nil && (myRedundancySlotPBid==nil || [availableSlotPBid isEqualToString:myRedundancySlotPBid])) {
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:availableSlotPBid create:YES];
[slotPB setPersistent:YES];
#else
NSPasteboard* slotPB = [NSPasteboard pasteboardWithName:availableSlotPBid];
#endif
// save slotPBid to the defaults, and remember to save later
////将slotPBid保存为默认值,并记住以后保存
if (localDict) {
[localDict setObject:availableSlotPBid forKey:kOpenUDIDSlotKey];
saveLocalDictToDefaults = YES;
}
// Save the local dictionary to the corresponding UIPasteboard slot
////将本地字典保存到相应的UIPasteboard插槽
if (openUDID && localDict)
[OpenUDID _setDict:localDict forPasteboard:slotPB];
}
// Save the dictionary locally if applicable
////在本地保存字典(如果适用)
if (localDict && saveLocalDictToDefaults)
[defaults setObject:localDict forKey:kOpenUDIDKey];
// If the UIPasteboard external representation marks this app as opted-out, then to respect privacy, we return the ZERO OpenUDID, a sequence of 40 zeros...
// This is a *new* case that developers have to deal with. Unlikely, statistically low, but still.
// To circumvent this and maintain good tracking (conversion ratios, etc.), developers are invited to calculate how many of their users have opted-out from the full set of users.
// This ratio will let them extrapolate convertion ratios more accurately.
//
//如果UIPasteboard外部表示将此应用程序标记为已选择退出,那么为了尊重隐私,我们将返回零OpenUDID,一个40个零的序列。。。
//这是一个开发人员必须处理的“新”案例。不太可能,统计数据很低,但仍然如此。
//为了避免这种情况,并保持良好的跟踪(转换率等),请开发人员计算出有多少用户从完整的用户集中选择出来。
//这个比率将使他们能够更准确地推断转换比率。
//
if (optedOut) {
if (error!=nil) *error = [NSError errorWithDomain:kOpenUDIDDomain
code:kOpenUDIDErrorOptedOut
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Application with unique id %@ is opted-out from OpenUDID as of %@",appUID,optedOutDate],@"description", nil]];
kOpenUDIDSessionCache = [[NSString stringWithFormat:@"%040x",0] retain];
return kOpenUDIDSessionCache;
}
// return the well earned openUDID!
//把赚得盆满钵满的openUDID还给我!
if (error!=nil) {
if (isCompromised)
*error = [NSError errorWithDomain:kOpenUDIDDomain
code:kOpenUDIDErrorCompromised
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Found a discrepancy between stored OpenUDID (reliable) and redundant copies; one of the apps on the device is most likely corrupting the OpenUDID protocol",@"description", nil]];
else
*error = [NSError errorWithDomain:kOpenUDIDDomain
code:kOpenUDIDErrorNone
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID succesfully retrieved",@"description", nil]];
}
kOpenUDIDSessionCache = [openUDID retain];
return kOpenUDIDSessionCache;
}
将其添加到工程使用hopper反编译的伪源码是
void * +[OpenUDID _generateFreshOpenUDID](void * self, void * _cmd) {
var_58 = 0x0;
if (var_58 == 0x0) {
var_60 = CFUUIDCreate(*_kCFAllocatorDefault);
var_68 = CFUUIDCreateString(*_kCFAllocatorDefault, var_60);
rax = CFStringGetFastestEncoding(var_68);
rax = CFStringGetCStringPtr(var_68, rax);
CC_MD5(rax, strlen(rax), &var_40);
CFRelease(var_60);
CFRelease(var_68);
var_58 = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x", var_40 & 0xff, var_3F & 0xff, var_3E & 0xff, var_3D & 0xff, var_3C & 0xff, var_3B & 0xff, var_3A & 0xff, var_39 & 0xff, var_38 & 0xff, var_37 & 0xff, var_36 & 0xff, var_35 & 0xff, var_34 & 0xff, var_33 & 0xff, var_32 & 0xff, var_31 & 0xff, arc4random() % 0xffffffffffffffff];
}
var_100 = var_58;
if (*___stack_chk_guard == *___stack_chk_guard) {
rax = var_100;
}
else {
rax = __stack_chk_fail();
}
return rax;
}
void * +[OpenUDID valueWithError:](void * self, void * _cmd, void * * arg2) {
var_20 = arg2;
if (*_kOpenUDIDSessionCache != 0x0) {
if (var_20 != 0x0) {
*var_20 = [NSError errorWithDomain:@"org.OpenUDID" code:0x0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID in cache from first call", @"description", 0x0]];
}
var_8 = *_kOpenUDIDSessionCache;
}
else {
var_28 = [NSUserDefaults standardUserDefaults];
var_30 = [var_28 objectForKey:@"OpenUDID_appUID"];
if (var_30 == 0x0) {
var_38 = CFUUIDCreate(0x0);
var_30 = CFUUIDCreateString(0x0, var_38);
CFRelease(var_38);
[var_30 autorelease];
}
var_40 = 0x0;
var_48 = 0x0;
var_50 = 0x0;
var_51 = 0x0;
var_52 = 0x0;
var_53 = 0x0;
var_60 = [var_28 objectForKey:@"OpenUDID"];
if (([var_60 isKindOfClass:[NSDictionary class]] & 0x1) != 0x0) {
var_60 = [NSMutableDictionary dictionaryWithDictionary:var_60];
var_40 = [var_60 objectForKey:@"OpenUDID"];
var_48 = [var_60 objectForKey:@"OpenUDID_slot"];
var_50 = [var_60 objectForKey:@"OpenUDID_optOutTS"];
var_51 = (var_50 != 0x0 ? 0x1 : 0x0) & 0x1;
}
var_68 = 0x0;
var_70 = [NSMutableDictionary dictionaryWithCapacity:0x64];
for (var_74 = 0x0; var_74 < 0x64; var_74 = var_74 + 0x1) {
var_80 = [NSString stringWithFormat:@"%@%d", @"org.OpenUDID.slot.", var_74];
var_88 = [UIPasteboard pasteboardWithName:var_80 create:0x0];
if (var_88 == 0x0) {
if (var_68 == 0x0) {
var_68 = var_80;
}
}
else {
var_90 = [OpenUDID _getDictFromPasteboard:var_88];
var_98 = [var_90 objectForKey:@"OpenUDID"];
if (var_98 == 0x0) {
if (var_68 == 0x0) {
var_68 = var_80;
}
}
else {
[var_70 setObject:[NSNumber numberWithInt:[[var_70 valueForKey:var_98] intValue] + 0x1] forKey:var_98];
}
var_A8 = [var_90 objectForKey:@"OpenUDID_appUID"];
if ((var_A8 != 0x0) && (([var_A8 isEqualToString:var_30] & 0x1) != 0x0)) {
var_48 = var_80;
if ((var_51 & 0x1) != 0x0) {
var_50 = [var_90 objectForKey:@"OpenUDID_optOutTS"];
var_51 = (var_50 != 0x0 ? 0x1 : 0x0) & 0x1;
}
}
}
}
var_B0 = [var_70 keysSortedByValueUsingSelector:@selector(compare:)];
if ((var_B0 != 0x0) && ([var_B0 count] > 0x0)) {
var_118 = [var_B0 lastObject];
}
else {
var_118 = 0x0;
}
var_B8 = var_118;
if (var_40 == 0x0) {
if (var_B8 == 0x0) {
var_40 = [OpenUDID _generateFreshOpenUDID];
}
else {
var_40 = var_B8;
}
if (var_60 == 0x0) {
var_60 = [NSMutableDictionary dictionaryWithCapacity:0x4];
[var_60 setObject:var_40 forKey:@"OpenUDID"];
[var_60 setObject:var_30 forKey:@"OpenUDID_appUID"];
[var_60 setObject:[NSDate date] forKey:@"OpenUDID_createdTS"];
if ((var_51 & 0x1) != 0x0) {
[var_60 setObject:var_50 forKey:@"OpenUDID_createdTS"];
}
var_52 = 0x1;
}
}
else {
if ((var_B8 != 0x0) && (([var_B8 isEqualToString:var_40] & 0x1) == 0x0)) {
var_53 = 0x1;
}
}
if ((var_68 != 0x0) && (((var_48 == 0x0) || (([var_68 isEqualToString:var_48] & 0x1) != 0x0)))) {
var_C0 = [UIPasteboard pasteboardWithName:var_68 create:0x1];
[var_C0 setPersistent:0x1];
if (var_60 != 0x0) {
[var_60 setObject:var_68 forKey:@"OpenUDID_slot"];
var_52 = 0x1;
}
if ((var_40 != 0x0) && (var_60 != 0x0)) {
[OpenUDID _setDict:var_60 forPasteboard:var_C0];
}
}
if ((var_60 != 0x0) && ((var_52 & 0x1) != 0x0)) {
[var_28 setObject:var_60 forKey:@"OpenUDID"];
}
if ((var_51 & 0x1) != 0x0) {
if (var_20 != 0x0) {
*var_20 = [NSError errorWithDomain:@"org.OpenUDID" code:0x1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Application with unique id %@ is opted-out from OpenUDID as of %@", var_30, var_50], @"description", 0x0]];
}
*_kOpenUDIDSessionCache = [[NSString stringWithFormat:@"%040x", 0x0] retain];
var_8 = *_kOpenUDIDSessionCache;
}
else {
if (var_20 != 0x0) {
if ((var_53 & 0x1) != 0x0) {
*var_20 = [NSError errorWithDomain:@"org.OpenUDID" code:0x2 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Found a discrepancy between stored OpenUDID (reliable) and redundant copies; one of the apps on the device is most likely corrupting the OpenUDID protocol", @"description", 0x0]];
}
else {
*var_20 = [NSError errorWithDomain:@"org.OpenUDID" code:0x0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID succesfully retrieved", @"description", 0x0]];
}
}
*_kOpenUDIDSessionCache = [var_40 retain];
var_8 = *_kOpenUDIDSessionCache;
}
}
rax = var_8;
return rax;
}
这个在2013年作者就deprecated了。
我的运行环境:xcode10 ,ios12.1
疑问1:kOpenUDIDAppUIDKey = @"OpenUDID_appUID" ,注释是:在pastebins中唯一标识此应用程序,但是它直接取值NSUserDefaults的一级,但没地方存!!每次运行都是空值,它是怎么判断的?320多行创建的 390多行才使用
疑问2:本地副本意思是NSUserDefaults存 kOpenUDIDKey = @"OpenUDID"的key对应的字典里面也有一个
疑问3:然后进入循环,kOpenUDIDRedundancySlots = 100 ,100遍,只有第一遍有值,其他99遍都啥都没赋值,也不知道有啥用,
kOpenUDIDSlotPBPrefix = @"org.OpenUDID.slot."这个标记了循环的顺序。
疑问4:从剪贴板获取[UIPasteboard pasteboardWithName:slotPBid(org.OpenUDID.slot.0) create:NO],的值是
{
OpenUDID = 02f268b1add131a529845a3a1886b8c6df279e89;//uuidcreate后做md5
"OpenUDID_appUID" = "C3FD02F2-FA71-4732-A674-DEB1DF338FE6";、//系统uuidcreate创建
"OpenUDID_createdTS" = "2020-03-02 13:18:01 +0000";时间
"OpenUDID_slot" = "org.OpenUDID.slot.0";创建顺序
}这个是卸载重装也会有的
剪贴板的key是org.OpenUDID.slot.0类似
上面这个字典NSUserDefaults也存一遍,key是kOpenUDIDKey = @"OpenUDID"
系统还原后看循环:循环里面一个都不走,然后通过[OpenUDID _generateFreshOpenUDID]创建第一个值,重新走一遍这个方法CFUUIDCreateString md5,作为openudid, 然后320行那里的创建的作为kOpenUDIDAppUIDKey,
存剪贴板 本地
{
OpenUDID = 958a60666597945dabf734d1e8767bbcb7d68708;
"OpenUDID_appUID" = "053E23DB-D3A0-42B0-B640-FF5EA911B9DA";
"OpenUDID_createdTS" = "2020-03-03 03:19:16 +0000";
"OpenUDID_slot" = "org.OpenUDID.slot.0";
}
完成
以下是+[UTDevice utdid]如何实现的一些探索
void * +[UTDevice utdid](void * self, void * _cmd) {
var_-96 = 0x0;
var_-88 = &var_-96;
var_-176 = &var_-56;
var_-184 = [UTDIDOpenUDID value];
*var_-176 = [var_-184 retain];
var_-192 = &var_-96 + 0x28;
objc_storeStrong(&var_-16, &var_-152);
if (*_utdid.onceToken != 0xffffffffffffffff) {
dispatch_once(_utdid.onceToken, 0x0);
}
var_-16 = 0x0;
objc_storeStrong(&var_-16, 0x0);
if (*(var_-88 + 0x28) == 0x0) {
var_-200 = @"ffffffffffffffffffffffff";
}
else {
var_-200 = *(var_-88 + 0x28);
}
var_-24 = [var_-200 retain];
_Block_object_dispose(&var_-96, 0x8);
rdi = var_-192;
objc_storeStrong(rdi, 0x0);
var_-212 = 0x1;
if ((0x0 & 0x1) == 0x0) {
rcx = var_-212 - 0x2;
var_-216 = var_-212;
if (rcx != 0x0) {
rax = var_-216 - 0x3;
if (rax != 0x0) {
rax = [var_-24 autorelease];
}
else {
*(rdi + 0x28) = 0x0;
objc_storeStrong(rdi + 0x28, *0x28);
rax = objc_storeStrong(0x28, 0x0);
}
}
else {
var_-24 = [@"eeeeeeeeeeeeeeeeeeeeeeee" retain];
rax = [var_-24 autorelease];
}
}
else {
rax = objc_exception_rethrow();
}
return rax;
}
这么一堆就一句有用 [UTDIDOpenUDID value];
void * +[UTDIDOpenUDID value](void * self, void * _cmd) {
rax = [UTDIDOpenUDID valueWithError:0x0];
return rax;
}
下一个方法
void * +[UTDIDOpenUDID valueWithError:](void * self, void * _cmd, void * * arg2) {
var_-16 = self;
var_-32 = arg2;
if (*_kUTDIDOpenUDIDSessionCache != 0x0) {
if (var_-32 != 0x0) {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID in cache from first call", @"description", 0x0]];
}
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
else {
var_-40 = [NSUserDefaults standardUserDefaults];
var_-48 = 0x0;
var_-56 = 0x0;
var_-64 = 0x0;
var_-65 = 0x0;
var_-66 = 0x0;
var_-67 = 0x0;
var_-80 = [var_-40 objectForKey:@"UTDID"];
if (([var_-80 isKindOfClass:[NSDictionary class]] & 0x1) == 0x0) {
var_-88 = 0x0;
var_-96 = [NSMutableDictionary dictionaryWithCapacity:0x64];
var_-104 = [var_-16 appUid];
for (var_-108 = 0x0; var_-108 < 0x64; var_-108 = var_-108 + 0x1) {
var_-248 = [NSString stringWithFormat:@"%@%d", @"com.UTDID.", var_-108];
var_-120 = var_-248;
var_-272 = [UIPasteboard pasteboardWithName:var_-248 create:0x0];
var_-144 = var_-272;
if (var_-144 == 0x0) {
if (var_-88 == 0x0) {
var_-88 = var_-120;
}
}
else {
var_-280 = [UTDIDOpenUDID _getDictFromPasteboard:var_-144];
var_-152 = var_-280;
var_-288 = [var_-280 objectForKey:@"UTDID"];
var_-160 = var_-288;
if (var_-160 == 0x0) {
if (var_-88 == 0x0) {
var_-88 = var_-120;
}
}
else {
var_-296 = [var_-96 valueForKey:var_-160];
var_-300 = [var_-296 intValue];
var_-312 = var_-96;
var_-328 = [NSNumber numberWithInt:var_-300 + 0x1];
[var_-312 setObject:var_-328 forKey:var_-160];
}
var_-336 = [var_-152 objectForKey:@"UTDID_appUID"];
var_-176 = var_-336;
if (var_-176 != 0x0) {
var_-337 = [var_-176 isEqualToString:var_-104];
if ((var_-337 & 0x1) != 0x0) {
var_-56 = var_-120;
if ((var_-65 & 0x1) != 0x0) {
var_-352 = [var_-152 objectForKey:@"UTDID_optOutTS"];
var_-64 = var_-352;
var_-65 = (var_-64 != 0x0 ? 0x1 : 0x0) & 0x1;
}
}
}
}
}
var_-192 = [var_-96 keysSortedByValueUsingSelector:@selector(compare:)];
if ((var_-192 != 0x0) && ([var_-192 count] > 0x0)) {
var_-360 = [var_-192 lastObject];
}
else {
var_-360 = 0x0;
}
var_-200 = var_-360;
if (var_-48 == 0x0) {
if (var_-200 == 0x0) {
var_-48 = [[[UTDIDMain alloc] init] value];
}
else {
var_-48 = var_-200;
}
if (var_-80 == 0x0) {
var_-80 = [NSMutableDictionary dictionaryWithCapacity:0x4];
[var_-80 setObject:var_-48 forKey:@"UTDID"];
[var_-80 setObject:var_-104 forKey:@"UTDID_appUID"];
[var_-80 setObject:[NSDate date] forKey:@"UTDID_createdTS"];
if ((var_-65 & 0x1) != 0x0) {
[var_-80 setObject:var_-64 forKey:@"UTDID_createdTS"];
}
var_-66 = 0x1;
}
}
else {
if ((var_-200 != 0x0) && (([var_-200 isEqualToString:var_-48] & 0x1) == 0x0)) {
var_-67 = 0x1;
}
}
if ((var_-88 != 0x0) && (((var_-56 == 0x0) || (([var_-88 isEqualToString:var_-56] & 0x1) != 0x0)))) {
var_-208 = [UIPasteboard pasteboardWithName:var_-88 create:0x1];
[var_-208 setPersistent:0x1];
if (var_-80 != 0x0) {
[var_-80 setObject:var_-88 forKey:@"UTDID_slot"];
var_-66 = 0x1;
}
if ((var_-48 != 0x0) && (var_-80 != 0x0)) {
[UTDIDOpenUDID _setDict:var_-80 forPasteboard:var_-208];
}
}
if ((var_-80 != 0x0) && ((var_-66 & 0x1) != 0x0)) {
[var_-40 setObject:var_-80 forKey:@"UTDID"];
}
if ((var_-65 & 0x1) != 0x0) {
if (var_-32 != 0x0) {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Application with unique id %@ is opted-out from OpenUDID as of %@", var_-104, var_-64], @"description", 0x0]];
}
*_kUTDIDOpenUDIDSessionCache = [[NSString stringWithFormat:@"%040x", 0x0] retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
else {
if (var_-32 != 0x0) {
if ((var_-67 & 0x1) != 0x0) {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x2 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Found a discrepancy between stored OpenUDID (reliable) and redundant copies; one of the apps on the device is most likely corrupting the OpenUDID protocol", @"description", 0x0]];
}
else {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID succesfully retrieved", @"description", 0x0]];
}
}
*_kUTDIDOpenUDIDSessionCache = [var_-48 retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
}
else {
var_-80 = [NSMutableDictionary dictionaryWithDictionary:var_-80];
var_-48 = [var_-80 objectForKey:@"UTDID"];
var_-56 = [var_-80 objectForKey:@"UTDID_slot"];
var_-64 = [var_-80 objectForKey:@"UTDID_optOutTS"];
var_-65 = (var_-64 != 0x0 ? 0x1 : 0x0) & 0x1;
if (0x0 != var_-48) {
*_kUTDIDOpenUDIDSessionCache = [var_-48 retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
else {
var_-88 = 0x0;
var_-96 = [NSMutableDictionary dictionaryWithCapacity:0x64];
var_-104 = [var_-16 appUid];
for (var_-108 = 0x0; var_-108 < 0x64; var_-108 = var_-108 + 0x1) {
var_-248 = [NSString stringWithFormat:@"%@%d", @"com.UTDID.", var_-108];
var_-120 = var_-248;
var_-272 = [UIPasteboard pasteboardWithName:var_-248 create:0x0];
var_-144 = var_-272;
if (var_-144 == 0x0) {
if (var_-88 == 0x0) {
var_-88 = var_-120;
}
}
else {
var_-280 = [UTDIDOpenUDID _getDictFromPasteboard:var_-144];
var_-152 = var_-280;
var_-288 = [var_-280 objectForKey:@"UTDID"];
var_-160 = var_-288;
if (var_-160 == 0x0) {
if (var_-88 == 0x0) {
var_-88 = var_-120;
}
}
else {
var_-296 = [var_-96 valueForKey:var_-160];
var_-300 = [var_-296 intValue];
var_-312 = var_-96;
var_-328 = [NSNumber numberWithInt:var_-300 + 0x1];
[var_-312 setObject:var_-328 forKey:var_-160];
}
var_-336 = [var_-152 objectForKey:@"UTDID_appUID"];
var_-176 = var_-336;
if (var_-176 != 0x0) {
var_-337 = [var_-176 isEqualToString:var_-104];
if ((var_-337 & 0x1) != 0x0) {
var_-56 = var_-120;
if ((var_-65 & 0x1) != 0x0) {
var_-352 = [var_-152 objectForKey:@"UTDID_optOutTS"];
var_-64 = var_-352;
var_-65 = (var_-64 != 0x0 ? 0x1 : 0x0) & 0x1;
}
}
}
}
}
var_-192 = [var_-96 keysSortedByValueUsingSelector:@selector(compare:)];
if ((var_-192 != 0x0) && ([var_-192 count] > 0x0)) {
var_-360 = [var_-192 lastObject];
}
else {
var_-360 = 0x0;
}
var_-200 = var_-360;
if (var_-48 == 0x0) {
if (var_-200 == 0x0) {
var_-48 = [[[UTDIDMain alloc] init] value];
}
else {
var_-48 = var_-200;
}
if (var_-80 == 0x0) {
var_-80 = [NSMutableDictionary dictionaryWithCapacity:0x4];
[var_-80 setObject:var_-48 forKey:@"UTDID"];
[var_-80 setObject:var_-104 forKey:@"UTDID_appUID"];
[var_-80 setObject:[NSDate date] forKey:@"UTDID_createdTS"];
if ((var_-65 & 0x1) != 0x0) {
[var_-80 setObject:var_-64 forKey:@"UTDID_createdTS"];
}
var_-66 = 0x1;
}
}
else {
if ((var_-200 != 0x0) && (([var_-200 isEqualToString:var_-48] & 0x1) == 0x0)) {
var_-67 = 0x1;
}
}
if ((var_-88 != 0x0) && (((var_-56 == 0x0) || (([var_-88 isEqualToString:var_-56] & 0x1) != 0x0)))) {
var_-208 = [UIPasteboard pasteboardWithName:var_-88 create:0x1];
[var_-208 setPersistent:0x1];
if (var_-80 != 0x0) {
[var_-80 setObject:var_-88 forKey:@"UTDID_slot"];
var_-66 = 0x1;
}
if ((var_-48 != 0x0) && (var_-80 != 0x0)) {
[UTDIDOpenUDID _setDict:var_-80 forPasteboard:var_-208];
}
}
if ((var_-80 != 0x0) && ((var_-66 & 0x1) != 0x0)) {
[var_-40 setObject:var_-80 forKey:@"UTDID"];
}
if ((var_-65 & 0x1) != 0x0) {
if (var_-32 != 0x0) {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x1 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Application with unique id %@ is opted-out from OpenUDID as of %@", var_-104, var_-64], @"description", 0x0]];
}
*_kUTDIDOpenUDIDSessionCache = [[NSString stringWithFormat:@"%040x", 0x0] retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
else {
if (var_-32 != 0x0) {
if ((var_-67 & 0x1) != 0x0) {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x2 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Found a discrepancy between stored OpenUDID (reliable) and redundant copies; one of the apps on the device is most likely corrupting the OpenUDID protocol", @"description", 0x0]];
}
else {
*var_-32 = [NSError errorWithDomain:@"com.UTDID" code:0x0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"OpenUDID succesfully retrieved", @"description", 0x0]];
}
}
*_kUTDIDOpenUDIDSessionCache = [var_-48 retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
}
}
}
rax = var_-8;
return rax;
}
1 & 0x1 = 1;
不是字典时
void * +[UTDIDOpenUDID appUid](void * self, void * _cmd) {
var_20 = [[NSUserDefaults standardUserDefaults] objectForKey:@"UTDID_appUID"];
if (var_20 == 0x0) {
var_28 = CFUUIDCreate(0x0);
var_20 = CFUUIDCreateString(0x0, var_28);
CFRelease(var_28);
[var_20 autorelease];
}
rax = var_20;
return rax;
}
function CFUUIDCreate {
rax = _CFUUIDCreate(rdi);
return rax;
}
function CFUUIDCreateString {
rax = _CFUUIDCreateString(rdi, rsi);
return rax;
}
上面这是系统提供的生成uuid的c语言方法
[UIPasteboard pasteboardWithName:var_F8 create:0x0]; 这也是系统方法
void * +[UTDIDOpenUDID _getDictFromPasteboard:](void * self, void * _cmd, void * arg2) {
var_20 = [arg2 dataForPasteboardType:@"com.UTDID"];
if (var_20 != 0x0) {
var_40 = [NSKeyedUnarchiver unarchiveObjectWithData:var_20];
var_20 = var_40;
}
if ((var_20 != 0x0) && (([var_20 isKindOfClass:[NSDictionary class]] & 0x1) == 0x0)) {
var_58 = 0x0;
}
else {
var_58 = var_20;
}
rax = [NSMutableDictionary dictionaryWithDictionary:var_58];
return rax;
}
把上面代码循环64遍后,然后又出来下面的一个方法
void * -[UTDIDMain value](void * self, void * _cmd) {
var_10 = self;
rax = [@"S_UTDID_OPT_LOCK" retain];
var_98 = rax;
objc_sync_enter(rax);
if (0x0 == *_s_utdid) goto loc_100e18800;
loc_100e187e1:
var_8 = [*_s_utdid retain];
goto loc_100e18d83;
loc_100e18d83:
objc_sync_exit(var_98);
[var_98 release];
rax = [var_8 autorelease];
return rax;
loc_100e18800:
[var_10 preInit];
var_2D = 0x1;
var_2E = 0x0;
var_A8 = [NSUserDefaults standardUserDefaults];
rax = [var_A8 retain];
var_38 = rax;
var_B8 = [rax objectForKey:@"PK_455469921"];
var_40 = [var_B8 retain];
var_49 = 0x0;
var_B9 = 0x1;
if (0x0 != var_40) {
var_C8 = [var_10->mUtdidHelper dePack:var_40];
rax = [var_C8 retain];
var_48 = rax;
var_49 = 0x1;
var_B9 = 0x0 == rax ? 0x1 : 0x0;
}
var_C9 = var_B9;
if ((var_49 & 0x1) != 0x0) {
[var_48 release];
}
if ((var_C9 & 0x1) != 0x0) goto loc_100e1892a;
loc_100e18be6:
var_88 = 0x0;
var_130 = [var_10->mUtdidHelper dePack:var_40];
var_90 = [var_130 retain];
if (0x0 == var_90) {
var_8 = [@"dddddddddddddddddddddddd" retain];
}
else {
if ((var_2E & 0x1) != 0x0) {
[var_10->mDevicePersistentConfig setObject:var_40 forKey:@"c"];
[var_10->mDevicePersistentConfig commit];
}
var_138 = [UTDIDTypeConvert NSData2Base64:var_90];
var_88 = [var_138 retain];
[0x0 release];
objc_storeStrong(_s_utdid, var_88);
var_8 = [var_88 retain];
}
objc_storeStrong(&var_90, 0x0);
objc_storeStrong(&var_88, 0x0);
goto loc_100e18d63;
loc_100e18d63:
objc_storeStrong(&var_40, 0x0);
objc_storeStrong(&var_38, 0x0);
goto loc_100e18d83;
loc_100e1892a:
var_D8 = [var_10->mDevicePersistentConfig objectForKey:@"c"];
rax = [var_D8 retain];
rdi = var_40;
var_40 = rax;
[rdi release];
var_59 = 0x0;
var_D9 = 0x1;
if (0x0 != var_40) {
var_E8 = [var_10->mUtdidHelper dePack:var_40];
rax = [var_E8 retain];
var_58 = rax;
var_59 = 0x1;
var_D9 = 0x0 == rax ? 0x1 : 0x0;
}
var_E9 = var_D9;
if ((var_59 & 0x1) != 0x0) {
[var_58 release];
}
if ((var_E9 & 0x1) != 0x0) goto loc_100e18a0d;
loc_100e18bcc:
var_2D = 0x0;
goto loc_100e18be6;
loc_100e18a0d:
var_2E = 0x1;
var_F8 = [var_10->mUIPasteBoard dataForPasteboardType:@"K_1427156438"];
rax = [var_F8 retain];
rdi = var_40;
var_40 = rax;
[rdi release];
var_69 = 0x0;
var_F9 = 0x1;
if (0x0 != var_40) {
var_108 = [var_10->mUtdidHelper dePack:var_40];
rax = [var_108 retain];
var_68 = rax;
var_69 = 0x1;
var_F9 = 0x0 == rax ? 0x1 : 0x0;
}
var_109 = var_F9;
if ((var_69 & 0x1) != 0x0) {
[var_68 release];
}
if ((var_109 & 0x1) != 0x0) goto loc_100e18af7;
loc_100e18bc6:
var_2D = 0x0;
goto loc_100e18be6;
loc_100e18af7:
var_118 = [var_10 generateUtdidAndSave];
rax = [var_118 retain];
var_78 = rax;
var_120 = [UTDIDTypeConvert NSData2Base64:rax];
var_80 = [var_120 retain];
objc_storeStrong(_s_utdid, var_80);
var_8 = [var_80 retain];
objc_storeStrong(&var_80, 0x0);
objc_storeStrong(&var_78, 0x0);
goto loc_100e18d63;
}
void -[UTDIDMain preInit](void * self, void * _cmd) {
var_-8 = self;
if (0x0 == var_-8->mUIPasteBoard) {
var_-8->mDevicePersistentConfig = [[UTDIDPersistentConf initWithIdentifier:@"Alvin"] retain];
[var_-8->mDevicePersistentConfig release];
var_-8->mUIPasteBoard = [[UIPasteboard pasteboardWithName:@"D_518825059" create:0x1] retain];
[var_-8->mUIPasteBoard release];
[var_-8->mUIPasteBoard setPersistent:0x1];
var_-8->mUtdidHelper = [[UTDIDHelper alloc] init];
[var_-8->mUtdidHelper release];
}
return;
}
void * +[UTDIDPersistentConf initWithIdentifier:](void * self, void * _cmd, void * arg2) {
objc_storeStrong(&var_-32, arg2);
if (0x0 != 0x0) {
var_-40 = [[UTDIDPersistentConf alloc] init];
[var_-40 create:0x0];
var_-8 = [var_-40 retain];
objc_storeStrong(&var_-40, 0x0);
}
else {
var_-8 = 0x0;
}
var_-32 = 0x0;
objc_storeStrong(&var_-32, 0x0);
rax = [var_-8 autorelease];
return rax;
}
void -[UTDIDPersistentConf create:](void * self, void * _cmd, void * arg2) {
rax = &var_-24;
var_-24 = 0x0;
objc_storeStrong(rax, arg2);
*(int8_t *)&self->mIsModified = 0x0;
objc_storeStrong(&self->mIdentifier, var_-24);
self->mKeyChainWrapper = [[UTDIDKeychainItemWrapper alloc] initWithIdentifier:self->mIdentifier accessGroup:0x0];
[self->mKeyChainWrapper release];
self->mPersistentFile = [[UTDIDPersistentFile createWithFile:@".UTSystemConfig" and:var_-24] retain];
[self->mPersistentFile release];
[self initData];
objc_storeStrong(&var_-24, 0x0);
return;
}
void * +[UTDIDPersistentFile createWithFile:and:](void * self, void * _cmd, void * arg2, void * arg3) {
objc_storeStrong(&var_-32, arg2);
objc_storeStrong(&var_-40, arg3);
if ((([UTDIDStringUtils isEmpty:0x0] & 0x1) == 0x0) && (([UTDIDStringUtils isEmpty:0x0] & 0x1) == 0x0)) {
var_-48 = [[UTDIDPersistentFile alloc] init];
[var_-48 create:0x0 and:0x0];
var_-8 = [var_-48 retain];
objc_storeStrong(&var_-48, 0x0);
}
else {
var_-8 = 0x0;
}
var_-32 = 0x0;
var_-40 = 0x0;
objc_storeStrong(&var_-40, 0x0);
objc_storeStrong(&var_-32, 0x0);
rax = [var_-8 autorelease];
return rax;
}
存钥匙串
void * -[UTDIDHelper init](void * self, void * _cmd) {
var_-8 = 0x0;
rax = [[&var_-32 super] init];
rsi = &var_-8;
var_-8 = rax;
objc_storeStrong(rsi, rax);
if (var_-8 != 0x0) {
rax = [@"iIAjd0narA7LwEsUqYLvMIF8n5pXBlbuYLN61VA4APYahCvFrIXj7ZsDBeRfDgqViDdsWh3YUNbqoxm7pAEm6COKYnb9KimZqJdagZHulvlr6HI6OEIqkOObZfcmWjQ1KEa1jUt9AlVVtbSXuargyTdodgA6mfJQ9RATlM5ousF8Bhh3K6WgfzB47KBqjSJ6sS1lfba90OZ9HzaW0n8YKWck3mz1WX4t8cb2oC0V5LpdTi5wNLhBqFHzRnwChbYf" dataUsingEncoding:0x4];
rax = [rax retain];
var_-8->mAESKey = [[UTDIDTypeConvert NSData2Base64:rax] retain];
[var_-8->mAESKey release];
[rax release];
}
var_-72 = [var_-8 retain];
objc_storeStrong(&var_-8, 0x0);
rax = var_-72;
return rax;
}
上面是aes的秘钥
void * -[UTDIDHelper dePack:](void * self, void * _cmd, void * arg2) {
objc_storeStrong(&var_-128, arg2);
var_-136 = [[UTDIDAES AES256DecryptWithKey:0x0 forKey:self->mAESKey] retain];
if ([var_-136 length] == 0x16) {
var_-160 = [[UTDIDBaseUtils platform] retain];
if (0x0 != var_-160) {
var_-168 = [[UTDIDIntUtils bytes:[UTDIDStringUtils hashCode:var_-160]] retain];
var_-192 = [[var_-136 subdataWithRange:0x0] retain];
var_-200 = [[UTDIDIntUtils bytes:0x0] retain];
if ((([var_-200 isEqualToData:var_-192] & 0x1) == 0x0) && (([var_-168 isEqualToData:var_-192] & 0x1) == 0x0)) {
var_-104 = 0x0;
var_-204 = 0x1;
}
else {
var_-204 = 0x0;
}
objc_storeStrong(&var_-200, 0x0);
objc_storeStrong(&var_-192, 0x0);
objc_storeStrong(&var_-168, 0x0);
if (var_-204 == 0x0) {
var_-232 = [[var_-136 subdataWithRange:0x4] retain];
var_-104 = [var_-232 retain];
objc_storeStrong(&var_-232, 0x0);
}
}
else {
var_-232 = [[var_-136 subdataWithRange:0x4] retain];
var_-104 = [var_-232 retain];
objc_storeStrong(&var_-232, 0x0);
}
objc_storeStrong(&var_-160, 0x0);
}
else {
var_-104 = 0x0;
}
var_-128 = 0x0;
objc_storeStrong(&var_-136, 0x0);
objc_storeStrong(&var_-128, 0x0);
rax = [var_-104 autorelease];
return rax;
}
void * +[UTDIDBaseUtils platform](void * self, void * _cmd) {
sysctlbyname("hw.machine", 0x0, &var_-32, 0x0, 0x0);
var_-40 = malloc(var_-32);
if (var_-40 != 0x0) {
sysctlbyname("hw.machine", var_-40, &var_-32, 0x0, 0x0);
var_-48 = [[NSString stringWithCString:var_-40 encoding:0x4] retain];
free(var_-40);
var_-8 = [var_-48 retain];
objc_storeStrong(&var_-48, 0x0);
}
else {
var_-8 = 0x0;
}
rax = [var_-8 autorelease];
return rax;
}
void * +[UTDIDIntUtils bytes:](void * self, void * _cmd, unsigned int arg2) {
var_-24 = var_-17;
rax = [NSData dataWithBytes:&var_-24 length:0x4];
rax = [rax retain];
var_-32 = rax;
var_-56 = [rax retain];
objc_storeStrong(&var_-32, 0x0);
rax = [var_-56 autorelease];
return rax;
}
int +[UTDIDStringUtils hashCode:](void * self, void * _cmd, void * arg2) {
objc_storeStrong(&var_-32, arg2);
if (0x0 == 0x0) {
var_-4 = 0x0;
}
else {
var_-40 = 0x0;
if ((var_-40 == 0x0) && ([0x0 length] > 0x0)) {
var_-48 = [objc_retainAutorelease(0x0) UTF8String];
var_-52 = 0x0;
while (sign_extend_64(var_-52) < [0x0 length]) {
var_-40 = var_-40 * 0x1f + sign_extend_64(*(int8_t *)(var_-48 + sign_extend_64(var_-52)));
var_-52 = var_-52 + 0x1;
}
}
var_-4 = var_-40;
}
var_-32 = 0x0;
objc_storeStrong(&var_-32, 0x0);
rax = var_-4;
return rax;
}
void * +[UTDIDTypeConvert NSData2Base64:](void * self, void * _cmd, void * arg2) {
objc_storeStrong(&var_-24, arg2);
var_-28 = 0x0;
var_-40 = [UTDIDTypeConvert newBase64Encode:[objc_retainAutorelease(0x0) bytes] :[0x0 length] :0x1 :&var_-28];
var_-48 = 0x0;
if (var_-40 != 0x0) {
if (var_-28 > 0x0) {
var_-48 = [[NSString alloc] initWithBytes:var_-40 length:var_-28 encoding:0x1];
[0x0 release];
}
free(var_-40);
}
var_-24 = 0x0;
var_-88 = [var_-48 retain];
objc_storeStrong(&var_-48, 0x0);
objc_storeStrong(&var_-24, 0x0);
rax = [var_-88 autorelease];
return rax;
}
char * +[UTDIDTypeConvert newBase64Encode::::](void * self, void * _cmd, void * arg2, unsigned int arg3, bool arg4, unsigned int * arg5) {
r8 = 0x0;
var_-36 = arg3;
var_-37 = arg4 & 0x1;
var_-48 = arg5;
var_-56 = arg2;
var_-92 = var_-36 / 0x3;
if (var_-36 % 0x3 != 0x0) {
r8 = 0x1;
}
var_-60 = var_-92 + r8 << 0x2;
if ((var_-37 & 0x1) != 0x0) {
var_-60 = (var_-60 >> 0x6 << 0x1) + var_-60;
}
var_-72 = malloc(var_-60 + 0x1);
if (var_-72 == 0x0) {
var_-8 = 0x0;
}
else {
var_-76 = 0x0;
var_-80 = 0x0;
if ((var_-37 & 0x1) != 0x0) {
var_-96 = 0x30;
}
else {
var_-96 = var_-36;
}
var_-84 = var_-96;
var_-88 = var_-84;
do {
if (var_-88 > var_-36) {
var_-88 = var_-36;
}
while (var_-76 + 0x3 - 0x1 < var_-88) {
*(int8_t *)(var_-72 + var_-80) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64(SAR((*(int8_t *)(var_-56 + var_-76) & 0xff & 0xfc), 0x2)));
*(int8_t *)(var_-72 + var_-80 + 0x1) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64((*(int8_t *)(var_-56 + var_-76) & 0xff & 0x3) << 0x4 | SAR((*(int8_t *)(var_-56 + var_-76 + 0x1) & 0xff & 0xf0), 0x4)));
*(int8_t *)(var_-72 + var_-80 + 0x2) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64((*(int8_t *)(var_-56 + var_-76 + 0x1) & 0xff & 0xf) << 0x2 | SAR((*(int8_t *)(var_-56 + var_-76 + 0x2) & 0xff & 0xc0), 0x6)));
rcx = var_-80 + 0x3;
var_-80 = rcx + 0x1;
*(int8_t *)(var_-72 + rcx) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64(*(int8_t *)(var_-56 + var_-76 + 0x2) & 0xff & 0x3f));
var_-76 = var_-76 + 0x3;
}
if (var_-88 == var_-36) {
break;
}
*(int8_t *)(var_-72 + var_-80) = 0xd;
rax = var_-80 + 0x1;
var_-80 = rax + 0x1;
*(int8_t *)(var_-72 + rax) = 0xa;
var_-88 = var_-84 + var_-88;
} while (true);
if (var_-76 + 0x1 < var_-36) {
*(int8_t *)(var_-72 + var_-80) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64(SAR((*(int8_t *)(var_-56 + var_-76) & 0xff & 0xfc), 0x2)));
*(int8_t *)(var_-72 + var_-80 + 0x1) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64((*(int8_t *)(var_-56 + var_-76) & 0xff & 0x3) << 0x4 | SAR((*(int8_t *)(var_-56 + var_-76 + 0x1) & 0xff & 0xf0), 0x4)));
*(int8_t *)(var_-72 + var_-80 + 0x2) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64((*(int8_t *)(var_-56 + var_-76 + 0x1) & 0xff & 0xf) << 0x2));
rcx = var_-80 + 0x3;
var_-80 = rcx + 0x1;
*(int8_t *)(var_-72 + rcx) = 0x3d;
}
else {
if (var_-76 < var_-36) {
*(int8_t *)(var_-72 + var_-80) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64(SAR((*(int8_t *)(var_-56 + var_-76) & 0xff & 0xfc), 0x2)));
*(int8_t *)(var_-72 + var_-80 + 0x1) = *(int8_t *)("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + sign_extend_64((*(int8_t *)(var_-56 + var_-76) & 0xff & 0x3) << 0x4));
*(int8_t *)(var_-72 + var_-80 + 0x2) = 0x3d;
rcx = var_-80 + 0x3;
var_-80 = rcx + 0x1;
*(int8_t *)(var_-72 + rcx) = 0x3d;
}
}
*(int8_t *)(var_-72 + var_-80) = 0x0;
if (var_-48 != 0x0) {
*(int32_t *)var_-48 = var_-80;
}
var_-8 = var_-72;
}
rax = var_-8;
return rax;
}
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;
}
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;
}
void * +[UTDIDMain uniqueGlobalDeviceIdentifier](void * self, void * _cmd) {
var_20 = CFUUIDCreate(0x0);
var_28 = CFUUIDCreateString(0x0, var_20);
CFRelease(var_20);
if (0x0 == var_28) {
var_8 = [[UTDIDBaseUtils uniqueID] retain];
}
else {
var_8 = [var_28 retain];
}
objc_storeStrong(&var_28, 0x0);
rax = [var_8 autorelease];
return rax;
}
void * +[UTDIDBaseUtils uniqueID](void * self, void * _cmd) {
var_18 = [[NSMutableData alloc] init];
rax = arc4random();
var_1C = rax - -(rax * 0x80000001 >> 0x3f);
rax = arc4random();
var_20 = rax - -(rax * 0x80000001 >> 0x3f);
rax = arc4random();
var_24 = rax - -(rax * 0x80000001 >> 0x3f);
rax = arc4random();
var_28 = rax - -(rax * 0x80000001 >> 0x3f);
[var_18 appendBytes:&var_1C length:0x4];
[var_18 appendBytes:&var_20 length:0x4];
[var_18 appendBytes:&var_24 length:0x4];
[var_18 appendBytes:&var_28 length:0x4];
rax = [UTDIDTypeConvert NSData2Base64:var_18];
rax = [rax retain];
var_30 = rax;
var_58 = [rax retain];
objc_storeStrong(&var_30, 0x0);
objc_storeStrong(&var_18, 0x0);
rax = [var_58 autorelease];
return rax;
}
(lldb) po [[NSUserDefaults standardUserDefaults]objectForKey:@"UTDID"]
{
UTDID = "Xh+vQjn4X1ADAM3C7AE95sqH";
"UTDID_appUID" = "907097C2-DBDC-466E-94EF-9A75EF4D6433";
"UTDID_createdTS" = "2020-02-27 03:14:51 +0000";
"UTDID_slot" = "com.UTDID.13";
}
如果已经有值执行顺序 +[UTDIDOpenUDID valueWithError:]
[NSUserDefaults standardUserDefaults]; var_-80 = [var_-40 objectForKey:@"UTDID"];
if (([var_-80 isKindOfClass:[NSDictionary class]] & 0x1) == 0x0){
}else{
走这里
var_-48 = [var_-80 objectForKey:@"UTDID"];
if (0x0 != var_-48) {
*_kUTDIDOpenUDIDSessionCache = [var_-48 retain];
var_-8 = *_kUTDIDOpenUDIDSessionCache;
}
rax = var_-8;
return rax;
}
补充:还原设备,第一次运行走了这个方法utdidmain.说明mpaas没有使用openudid 的 _generateFreshOpenUDID方法(既生成openudid的方法)