V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
FaiChou
V2EX  ›  macOS

macOS 有试用期的应用验证策略问题请教

  •  
  •   FaiChou · 2020-02-24 18:19:09 +08:00 · 2484 次点击
    这是一个创建于 1736 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一般收费并且有免费试用期的 APP 有两种验证策略:

    1. 应用安装时将安装日期或到期日期写到本地
    2. 使用唯一 id 来联网验证

    本地验证

    这种方法比较简陋,可以用脚本等方法篡改使用期限。

    联网验证

    这种方法应该可以躲避一些脚本,但获取唯一 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:

    • UUID 是电脑给应用配置的唯一 id,当 app 卸载重装,这个 id 会变
    • UDID 是电脑唯一 id,一般情况禁止使用,使用它不能上架市场

    我在研究另一款试用软件时候(仅学习研究用),发现它使用的 id 并不是这个 UDID,而且卸载重装时候发现,这个 id 还是之前的 id。既然不是 UDID,那么它有可能将 UUID 保存到 keychain 里来持久化,但是去 keychain 里并没有找到。

    所以好奇它是如何做到的,在联网验证时候,一般使用哪一种 id ?

    以上的测试软件是 Sip, 使用 charles 抓包验证此 id 非 UDID:

    id

    我的电脑 Hardware UUID13C2951E-2B99-510A-BEF4-xxxxxxxxxx

    第 1 条附言  ·  2020-02-24 22:13:13 +08:00

    最直白的解决方法:直接询问开发者。开发者 Rui Aureliano 是这样回复我的:

    Hey,

    I can give you a light how this works

    1. We use the kIOPlatformSerialNumberKey, basically this identifies a machine, the only way the user change this is by changing the board
    2. We made some changes to this serial number, basically using some function in CryptoKit and some private keys
    3. Then we save that transformed and some data locally and remote
    4. Everytime a user open Sip, sip try validate that data, a check if the hash saved locally is different in the server, if that’s different, that means something changed in local, so we delete everything and the user need to start again, will need to enter the license, like you deleted the app
    5. We have some algorithms to handle some edge cases, like what if the user dent have internet, what if sip servers are down etc

    Hope this helps you

    14 条回复    2020-02-26 13:28:29 +08:00
    Mitt
        1
    Mitt  
       2020-02-24 18:39:01 +08:00
    用系统序列号不好吗,那玩意也是唯一的
    NeezerGu
        2
    NeezerGu  
       2020-02-24 18:51:06 +08:00
    看到你懂这么多,我就好奇请教一下。。。

    第二步里,是不是我只需要想办法不断的修改我软件里的 udid,就能无限试用?
    FaiChou
        3
    FaiChou  
    OP
       2020-02-24 19:03:40 +08:00
    @Mitt #1 在 iOS 下获取不到序列号,macOS 上我不确定可不可以,但我的疑问是 Sip 这个软件的唯一 id 是怎么保持不变的?

    @NeezerGu 理论上是的,但你首先你得确定软件用的是哪种 id,比如 Sip 这个软件它就不是你的系统 UDID。当然你也可以针对抓包的这个接口进行重放,修改返回信息来达到所谓的「无限试用」。
    elderwand
        4
    elderwand  
       2020-02-24 19:14:02 +08:00   ❤️ 1
    @FaiChou
    这里的 UDID 也是 UUID 的一种,只是叫法不一样,不算歧义

    Sip 可能是用了 IDFA,你可以试试重置 IDFA 看看
    macOS 可以用系统序列号吗?
    https://gist.github.com/leogdion/77f6143ecf793e1ba381917d4b3b286c
    Mitt
        5
    Mitt  
       2020-02-24 19:45:59 +08:00 via iPhone   ❤️ 1
    @FaiChou macos 可以用序列号,ios 苹果是不允许跟踪用户的,也就不允许你获取设备唯一码,以前看过别人绕过的方法,是在 keychain 里自己随机生成一串放进去,卸载也不会删除,变相跟踪,不知道是不是类似的方法,如果开了 iCloud 存储的话应该是有效的
    FaiChou
        6
    FaiChou  
    OP
       2020-02-24 19:50:59 +08:00
    @elderwand 谢谢纠正,我重置了电脑的 IDFA,重装 Sip,发现 id 没变。

    @Mitt 在问题中我也提到过「将 UUID 保存到 keychain 里来持久化」,这种方法我做 iOS 时候用过,但是我在电脑 keychain 里找不到 Sip 相关的 item,大概也能排除这种方法。
    Mitt
        7
    Mitt  
       2020-02-24 19:54:06 +08:00 via iPhone
    @FaiChou macOS 特别一点 其实卸载软件配置文件似乎不会删除,你可以找找是不是残留的文件里存了类似的 id 虽然可能是加密的
    FaiChou
        8
    FaiChou  
    OP
       2020-02-24 19:56:19 +08:00
    @Mitt #7 我用的是 AppCleaner,它会扫描软件相关所有内容,进行删除,暂且相信它。
    Mitt
        9
    Mitt  
       2020-02-24 20:06:38 +08:00
    @FaiChou 如果不是 App Store 下载的软件就不要相信第三方 Cleaner 的准确度了,沙盒外的软件是可以在任何地方拉屎的,那保不齐它把配置文件塞哪里了,第三方清理软件并不能准确跟踪
    FaiChou
        10
    FaiChou  
    OP
       2020-02-24 21:25:19 +08:00


    在使用 "Hopper Disassembler v4" (第一次使用)查看 Sip 的反编译,能搜到关于 UUID 和 keychain 的相关代码,不过有一大部分是 AppCenter 的代码,但也能发现 Sip 也是用了 UUID 和 keychain。

    我记得上午在 keychain 里找到过 Sip 相关但一个 item,被我删掉了,但是重装几次 Sip,keychain 里就再也找不到有关但证据了。

    现在一头雾水。
    FaiChou
        11
    FaiChou  
    OP
       2020-02-24 22:21:16 +08:00
    @Mitt 这个软件的开发者回复我了,他用的就是序列号(kIOPlatformSerialNumberKey)。
    aptx4689
        12
    aptx4689  
       2020-02-25 00:34:52 +08:00
    软件开发者居然还会回复这种问题,太热心了
    FaiChou
        13
    FaiChou  
    OP
       2020-02-25 10:08:05 +08:00
    @aptx4689 #12 如果有人问我 app 的相关细节,我也会回复的,但那个作者在 10 分钟就回复我的邮件也太效率了。
    ihwbunny
        14
    ihwbunny  
       2020-02-26 13:28:29 +08:00   ❤️ 1
    我想一种逻辑可以这样:

    每次运行
    . 判断证书, 如果有效, 就继续运行
    . 如果没有有效的证书, 就获得本机 ID (不管什么硬件 ID)
    . 上传到服务器, 服务器根据这个 ID, 判断:
    1. 没有记录, 生成一个有时效的证书, 比如试用 30 天, 发给客户端, 并保留硬件 ID 和证书等数据
    2. 有记录, 而且证书没失效, 发给客户端, 客户端可以继续试用
    3. 有记录, 而且失效, 告诉客户端购买
    . 客户端把证书保留在 keychain 中
    . 如果本地证书已经失效, 告诉客户端购买

    这个的好处是, 无论有没有网络都可以, 而且时间和证书发放都掌握在服务器端.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1760 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:41 · PVG 00:41 · LAX 08:41 · JFK 11:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.