【问题标题】:Mac App Store Receipt Validation Code?Mac App Store 收据验证码?
【发布时间】:2011-05-14 18:21:23
【问题描述】:

想知道是否有人有新 Mac App Store 收据验证的教程或工作代码?到目前为止,我能找到的唯一参考资料是 Apple 关于该主题的出色文档和一个可以编译但没有很多内联 cmets 的开源项目,因此除非您是加密专家,否则很难理解。

仅限注册开发者的 Apple 文档:

https://developer.apple.com/devcenter/mac/documents/validating.html

Roddi 的 ValidateStoreReceipt(看起来很有希望,但文档很少):

https://github.com/roddi/ValidateStoreReceipt

还想知道为什么 Apple 不只提供用于验证的工作代码?

还有其他好的参考吗?

【问题讨论】:

  • Apple 不提供完整代码的原因是,如果每个人都使用相同的代码,那么所有应用程序都同样容易被破解。如果每个人的做法都略有不同,那应该会让饼干更加困难。
  • 赏金给任何解释得足够好以至于我可以真正让它工作的人。特别是我尝试使用 Alan Quartermain 的代码并遇到编译错误。 . .在 Koregan 的回答下方查看我的评论。
  • @Nick 我认为 99% 的开发人员并不关心黑客,如果他们想破解您的应用程序,他们会的。我只是想确保如果普通用户从他/她的朋友计算机上复制我的应用程序,它不起作用。
  • @Tibidabo 我同意你的看法。我只是在回答“为什么 Apple 不只是提供用于验证的工作代码?”这个问题,而不是为此提出论据。我用的是罗迪的:)

标签: cocoa macos validation app-store


【解决方案1】:

很难为 Mac App Store 收据验证提供通用解决方案,主要是因为这是一段非常敏感的代码,必须难以绕过(参见Apple documentation)。

这些 GitHub 项目是了解收据验证必须执行哪些步骤的非常好的起点:

一旦你了解了必须做什么,这里有一些建议:

  • 不要使用 Objective-C 类或方法。 Objective-C 携带大量元数据,其动态特性将其暴露于运行时注入。
  • 仅使用 C 函数调用。即使您需要 CoreFoundation 框架的更多代码行,您也可以完美地完成 Foundation 框架可以做的事情(NSString、NSArray、NSDictionary 等)。
  • 不要与 OpenSSL 库动态链接,因为它在 Mac OS X Lion 中已被弃用。如果您想使用OpenSSL,请将其静态链接以确保拥有最新版本。
  • 使用系统函数进行加密。 Mac OS X 自 10.5 起就提供了等效的功能。例如,要计算 SHA-1 哈希,您可以使用 CC_SHA1 函数。
  • 不要在代码中以明文形式放置字符串。对它们进行编码或加密。如果你没有这样做,你会提示你代码的位置。
  • 不要在代码中使用数字常量。使用一些简单的操作(+、-、/ 或 *)在运行时计算它们。同样,如果您没有这样做,您会提示您的代码的位置。
  • 通过将测试和对NSApplicationMain 的调用嵌入到复杂的循环中来避免简单的验证测试。
  • 避免直接调用 NSApplicationMain。使用函数指针隐藏调用。如果你没有这样做,你会提示你代码的位置。
  • 对于应用程序的每个版本,稍微修改验证代码,使其永远不会相同。

请记住,收据验证是必要的,并不像看起来那么简单。它可能会消耗大量时间,您最好花在您的应用程序上。

所以我建议你看看这个应用程序:Receigen(免责声明:我是这个应用程序的开发者)。

【讨论】:

  • 所以所有那些使用 Obj-C 代码的项目都没有用,因为它们暴露于运行时注入,而不是你的 Receigen 它是纯 C 代码。我现在有一个问题,在购买之前如何检查您的应用程序?您可以理解,由于其性质(代码生成器),它可以在购买之前用作演示(我也没有看到任何评论来检查应用程序用户的评论)。我会为此付费,前提是我之前可以查看该应用程序。
  • 你说得很好。我仍然不知道如何提供免费版本的 Receigen,以便人们可以测试代码生成(它应该只生成一部分代码,或者混淆结果,......)。您能说出什么足以让您评估申请吗?
  • @LaurentEtiemble 这篇文章对从 App Store 进行销售很有帮助,但您能否帮助我了解如何保护从我自己的网站销售的应用程序(即 zip 文件下载)? security.stackexchange.com/questions/21226/…
  • 我与 Laurent 没有任何关系,但请使用 Receigen。我可以确认它有效,但它有多“不可破解”?对我来说已经足够好了。鉴于任何软件最终都可能被黑客入侵。顺便说一句:我也在使用 Receigen 和 Swift:swiftrien.blogspot.com/2015/05/…
  • 实际上,如果您担心难以绕过您的检查,则应该使用系统库进行加密。这些是非常明显的攻击目标。并且您无法隐藏对 NSApplicationMain 的调用。它通常是 main() 函数中调用的唯一函数。相反,应在代码中的多个位置执行验证,而不仅仅是在 main() 中。
【解决方案2】:

为了在测试后验证真实收据,请在您的 ma​​in.m 文件中更改这行代码:

if (!validateReceiptAtPath(@"~/Desktop/receipt"))

#ifdef USE_SAMPLE_RECEIPT   // defined for debug version
    NSString *pathToReceipt = @"~/Desktop/receipt";
#else
    NSString *pathToReceipt = [[[NSBundle mainBundle] bundlePath]
        stringByAppendingPathComponent:@"Contents/_MASReceipt/receipt"];
#endif  
    if (!validateReceiptAtPath(pathToReceipt))
        exit(173); //receipt did not validate

在您的编译器设置中,调试配置的“其他 C 标志”应包括 -DUSE_SAMPLE_RECEIPT

礼貌http://jesusagora.org/groups/futurebasic/0::53562:get:1read.html

【讨论】:

  • 从哪里获得调试/测试收据?
  • 在 Lion 及更高版本上,使用 [[[NSBundle mainBundle] appStoreReceiptURL] path] 而不是硬编码收据路径。
【解决方案3】:

请务必检查您是否正在验证您的应用的收据。轻松完成所有加密和验证错误收据的签名。

请参阅 http://pastebin.com/1eWf9LCg,其中 Angry Birds 似乎错过了这一点,并让人们使用免费应用程序的收据代替它们。

Alan Quatermain 在 github 上也有执行此操作的代码。 https://github.com/AlanQuatermain/mac-app-store-validation-sample

不应按原样使用它以避免自动删除。

【讨论】:

  • 下载后。 . .我如何让它运行?我在那里看不到 .xcodeproj,而且 gcc main.m 给了我错误。
  • 只是为了详细说明。 . .我尝试将他的源代码导入我的项目。但是每当我尝试编译 asn1 目录中的任何文件时,我都会在 AppKit.h 中得到至少 22000 个编译错误。我会在某处遗漏设置吗?
  • 样本是直接从常规的 OS X 10.6 Cocoa 应用程序中挑选出来的。你可以用这个替换你自己的 main.m 文件,然后直接在它们的子文件夹中添加其他文件,它应该可以正常工作。您需要在 Security.framework 中链接才能编译 Keychain 的东西,否则它只需要 Cocoa 库 IIRC。
  • 您列出的符号由 libcrypto 导出,它是 OpenSSL 的一部分。您是否也尝试过链接 libcrypto?您可以通过编辑项目设置、构建选项卡、其他链接器标志并指定 -lcryptostackoverflow.com/questions/4893333/… 来做到这一点
  • 当你说不要使用“原样”时,它的哪一部分可以改变?
【解决方案4】:

你可以试试NPReceiptVerification。这是向您的应用添加收据验证的最简单方法。您只需将类文件添加到项目中,设置版本和包标识符,其他一切都会自动处理。

【讨论】:

    【解决方案5】:

    我查看了 Alan Quartermain 的代码,它看起来不错。需要考虑的事情:

    这里的最后一个参数可以/应该是一个编译要求,说明代码必须由您的证书签名,而不是其他人的。

    开发者提交应用到商店审批时,签名证书如下:

    3rd Party Mac Developer Application: me
    Apple Worldwide Developer Relations Certification Authority
    Apple Root CA
    

    应用从App Store交付给最终用户后,签名证书如下:

    Apple Mac OS Application Signing
    Apple Worldwide Developer Relations Certification Authority
    Apple Root CA
    

    另外,我建议只在收据丢失时退出(173),但其他一切正常。

    【讨论】:

    • 我真的建议您进行某种形式的证书检查,因为这将有助于防止您对二进制文件进行十六进制编辑。如果签名无效,OS X 不会杀死应用程序,它只会限制对钥匙串等内容的访问,直到用户同意此类访问。您可以随时检查证书是否与您的证书或 Apple 用于发布应用程序的官方证书相匹配。
    【解决方案6】:

    我建议将代码验证例程实现为 C 函数,而不是 ObjC 方法。

    这种技术使查找收据检查代码变得(有点)困难,因为更少的方法名称被编译到二进制文件中。

    【讨论】:

      【解决方案7】:

      您可以参考RVNReceiptValidation,它很容易实现。只需在RVNReceiptValidation.m 文件和应用程序版本中设置Bundle id。记住要从 Apple 获取收据,您必须从 Finder 启动应用程序。该类还有助于实现 InApp 购买。

      【讨论】:

        【解决方案8】:

        我会详细说明普里勒的回答。如果 Apple 为验证过程提供了代码示例,那么坏人很容易获取您编译的应用程序并扫描它以查找与验证过程相对应的代码。如果您使用 Apple 的标准代码示例,Bad Guy 将确切知道编译后的代码是什么样子。一旦坏人找到了该部分的代码,修改应用程序的编译代码以跳过收据验证阶段就变得非常简单,从而使整个事情变得毫无用处。

        话虽如此,一个坚定的破解者可能会绕过你设置的任何复制保护,无论你做什么。游戏行业(例如)花费大量时间试图保护他们的软件,而且破解版似乎总是可用。

        【讨论】:

          【解决方案9】:

          从 Apple Docs 创建示例收据时,请确保不要在 'end' 之后包含任何额外字符,否则 uudecode 将失败。

          【讨论】:

          • “Apple Docs”在哪里?如何创建样本收据?
          【解决方案10】:

          RVNReceiptValidation 很棒,它使用 CommonCrypto,而不是现在被 Apple 弃用的 openssl。您必须将有效收据附加到您的项目才能对其进行调试。通过从另一个应用程序包中获取有效收据并在您的测试环境中创建一个构建阶段以将其添加到您的包中来执行此操作。我建议以下混淆技术:

          加密 kRVNBundleID 和 kRVNBundleVersion 并在将它们与 CFBundleIdentifier 和 CFBundleShortVersionString 进行比较时解密它们。

          我创建了一个具有随机值的函数指针数组,并在运行时将它们更改为指向 RVNReceiptValuation 中函数的有效指针,然后使用如下代码执行它们:

          static void testFunction(void);
          
          typedef void (*functionPtr)(void);
          
          functionPtr obfuscationArray[8] = {
              (functionPtr)0xA243F6A8,
              (functionPtr)0x885308D3,
              (functionPtr)0x13198A2E,
              (functionPtr)0x03707344,
              (functionPtr)0xA4093822,
              (functionPtr)0x299F31D0,
              (functionPtr)0x082EFA98,
              (functionPtr)0xEC4E6C89};
          
          int main(int argc, const char * argv[]) {
              functionPtr myFuncPtr;
          
              obfuscationArray[3] = &testFunction;
              myFuncPtr = obfuscationArray[3];
              (myFuncPtr)();
          
              return 0;
          }
          
          static void testFunction(void){
              printf("function executed\n");
          }
          

          【讨论】:

            【解决方案11】:

            是的,在他们的文档中它说:“重要的是,您必须采用对您的应用程序独特的解决方案。”

            【讨论】:

              【解决方案12】:

              roddi 的 ValidateStoreReceipt 以前为我工作过,但它不再工作了。 我写了一篇关于解决方案的博文:http://vinceyuan.blogspot.com/2012/07/validate-mac-app-store-receipt-2012.html

              复制到这里: roddi 的代码仍然有效。你不需要改变它。 (只需要获取最新版本) 请按照以下步骤操作(需要互联网):

              1. 从 Mac App Store 应用注销。
              2. 从您的项目设置中删除 USE_SAMPLE_RECEIPT 标志 -> 预处理器宏。
              3. 编译您的项目
              4. 在 Finder 中查找此应用
              5. 在 Finder 中双击运行。不要在 Xcode 中运行它。
              6. 操作系统会要求您使用 Apple ID 登录。不要使用您的真实 iTunes 帐户登录。您需要使用测试帐户登录。在 iTunesconnect 网站上找到或创建它。
              7. 操作系统会说“您的应用程序已损坏。在 App Store 中下载它”。忽略此消息。如果您在 Finder 中“显示此应用程序的包内容”,您将看到有一个文件 _MASReceipt/receipt。操作系统安装了开发收据。我们不再需要旧的样品收据。这就是我们移除 USE_SAMPLE_RECEIPT 调试标志的原因。

              完成。您现在可以调试您的应用了。

              【讨论】:

                【解决方案13】:

                即使使用 NPReceiptValidation,您仍然应该验证应用程序包的安全性,包括签名证书。这在面向开发人员的 WWDR 建议中有所记录。

                解决方案: http://itunes.apple.com/us/app/apptight-pro-app-store-code/id427083596?mt=12

                NPReceiptValidation 的一个潜在问题是 Cocoa 对象上的方法选择器很容易被劫持。这是扩展应用程序最流行的方式。

                这是另一个帮助解析应用内购买的工具:

                http://itunes.apple.com/us/app/pkcs-7viewer/id547539804?mt=12

                【讨论】:

                • 您提到了验证 WWDR 开发人员建议中提到的签名证书。能否请您指出这些 WWDR 建议以及如何完成。
                • 从 Lion SDK 开始,有用于获取签名证书和(在 Mountain Lion 下)信任证书链的 API。评估签名/信任证书的 SHA1 哈希,并将它们与 Apple 真实证书的已知(已发布)值进行比较。您的应用不会受到俄罗斯人的绕过。
                猜你喜欢
                • 2014-05-22
                • 1970-01-01
                • 1970-01-01
                • 2011-09-05
                • 2012-06-27
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多