一般收费并且有免费试用期的 APP 有两种验证策略:
这种方法比较简陋,可以用脚本等方法篡改使用期限。
这种方法应该可以躲避一些脚本,但获取唯一 id 是个难题,这也是我提出本问题的原因。
用以下代码可以获取一个系统的 id:
- (NSString *)getSystemID {
io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,IOServiceMatching("IOPlatformExpertDevice"));
if (!platformExpert)
return nil;
CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,CFSTR(kIOPlatformUUIDKey),kCFAllocatorDefault, 0);
if (!serialNumberAsCFString)
return nil;
IOObjectRelease(platformExpert);
return (__bridge NSString *)(serialNumberAsCFString);;
}
获取的 id 和电脑打开系统报告看到的 Hardware UUID
是一样的,我认为这里的 Hardware UUID
字段有歧义,按我的理解应该是 UDID
.
关于 UUID 和 UDID:
我在研究另一款试用软件时候(仅学习研究用),发现它使用的 id 并不是这个 UDID,而且卸载重装时候发现,这个 id 还是之前的 id。既然不是 UDID,那么它有可能将 UUID 保存到 keychain 里来持久化,但是去 keychain 里并没有找到。
所以好奇它是如何做到的,在联网验证时候,一般使用哪一种 id ?
以上的测试软件是 Sip, 使用 charles 抓包验证此 id 非 UDID:
我的电脑 Hardware UUID
是 13C2951E-2B99-510A-BEF4-xxxxxxxxxx
最直白的解决方法:直接询问开发者。开发者 Rui Aureliano 是这样回复我的:
Hey,
I can give you a light how this works
Hope this helps you
1
Mitt 2020-02-24 18:39:01 +08:00
用系统序列号不好吗,那玩意也是唯一的
|
2
NeezerGu 2020-02-24 18:51:06 +08:00
看到你懂这么多,我就好奇请教一下。。。
第二步里,是不是我只需要想办法不断的修改我软件里的 udid,就能无限试用? |
3
FaiChou OP |
4
elderwand 2020-02-24 19:14:02 +08:00 1
@FaiChou
这里的 UDID 也是 UUID 的一种,只是叫法不一样,不算歧义 Sip 可能是用了 IDFA,你可以试试重置 IDFA 看看 macOS 可以用系统序列号吗? https://gist.github.com/leogdion/77f6143ecf793e1ba381917d4b3b286c |
5
Mitt 2020-02-24 19:45:59 +08:00 via iPhone 1
@FaiChou macos 可以用序列号,ios 苹果是不允许跟踪用户的,也就不允许你获取设备唯一码,以前看过别人绕过的方法,是在 keychain 里自己随机生成一串放进去,卸载也不会删除,变相跟踪,不知道是不是类似的方法,如果开了 iCloud 存储的话应该是有效的
|
6
FaiChou OP |
7
Mitt 2020-02-24 19:54:06 +08:00 via iPhone
@FaiChou macOS 特别一点 其实卸载软件配置文件似乎不会删除,你可以找找是不是残留的文件里存了类似的 id 虽然可能是加密的
|
9
Mitt 2020-02-24 20:06:38 +08:00
@FaiChou 如果不是 App Store 下载的软件就不要相信第三方 Cleaner 的准确度了,沙盒外的软件是可以在任何地方拉屎的,那保不齐它把配置文件塞哪里了,第三方清理软件并不能准确跟踪
|
10
FaiChou OP |
12
aptx4689 2020-02-25 00:34:52 +08:00
软件开发者居然还会回复这种问题,太热心了
|
13
FaiChou OP @aptx4689 #12 如果有人问我 app 的相关细节,我也会回复的,但那个作者在 10 分钟就回复我的邮件也太效率了。
|
14
ihwbunny 2020-02-26 13:28:29 +08:00 1
我想一种逻辑可以这样:
每次运行 . 判断证书, 如果有效, 就继续运行 . 如果没有有效的证书, 就获得本机 ID (不管什么硬件 ID) . 上传到服务器, 服务器根据这个 ID, 判断: 1. 没有记录, 生成一个有时效的证书, 比如试用 30 天, 发给客户端, 并保留硬件 ID 和证书等数据 2. 有记录, 而且证书没失效, 发给客户端, 客户端可以继续试用 3. 有记录, 而且失效, 告诉客户端购买 . 客户端把证书保留在 keychain 中 . 如果本地证书已经失效, 告诉客户端购买 这个的好处是, 无论有没有网络都可以, 而且时间和证书发放都掌握在服务器端. |