Mac App Store 收据验证码?

发布于 2024-10-04 05:46:24 字数 585 浏览 2 评论 0原文

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

仅适用于注册开发人员的 Apple 文档:

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

Roddi 的 ValidateStoreReceipt (看起来很有前途,但记录很少):

https:/ /github.com/roddi/ValidateStoreReceipt

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

还有其他好的参考吗?

Wondering if anyone has a tutorial or working code for the new Mac App Store's receipt validation? About the only references I've been able to find so far are Apple's stellar documentation on the topic and one open source project which compiles but doesn't have a lot of inline comments so it's hard to understand unless you are a crypto whiz.

Apple docs for registered devs only:

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

Roddi's ValidateStoreReceipt (looks promising, but sparsely documented):

https://github.com/roddi/ValidateStoreReceipt

Also wondering why Apple does not just provide working code for validation?

Any other good references out there?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

随风而去 2024-10-11 05:46:24

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

这些 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 (免责声明:我是该应用程序的开发人员)。

It is hard to provide a generic solution for Mac App Store receipt validation, mainly because this is a very sensitive piece of code that must be hard to bypass (cf. Apple documentation).

These GitHub projects are very good starting points to learn about what steps must be performed in receipt validation:

Once you have understood what must be done, here is some advice:

  • Don't use Objective-C classes or methods. Objective-C carries a lot of metadata, and its dynamic nature exposes it to runtime injection.
  • Only use C function calls. Even if you need more lines of code with the CoreFoundation framework, you can perfectly do what the Foundation framework can do (NSString, NSArray, NSDictionary, ...).
  • Don't link dynamically with the OpenSSL library as it has been deprecated in Mac OS X Lion. If you want to go with OpenSSL, link it statically to be sure to have the latest release.
  • Use system functions for cryptography. Mac OS X ships with equivalent functions since 10.5. For example, to compute a SHA-1 hash, you can use the CC_SHA1 function.
  • Don't put strings in plaintext in your code. Encode them or encrypt them. If you fail to do so, you give a hint about the location of your code.
  • Don't use numeric constants in your code. Compute them at runtime, with some simple operations (+, -, / or *). Again, if you fail to do so, you give a hint about the location of your code.
  • Avoid simple tests for validation by embedding your tests and the call to NSApplicationMain into a complex loop.
  • Avoid calling NSApplicationMain directly. Use a function pointer to hide the invocation. If you fail to do so, you give a hint about the location of your code.
  • For each release of your application, slightly modify the validation code so it is never the same.

Remember that receipt validation is necessary and is not simple as it seems. It can consume a lot of time that you may better spend on your application.

So I suggest you to take a look at this application: Receigen (Disclaimer: I am the developer of this application).

瑶笙 2024-10-11 05:46:24

为了在测试后验证真实收据,请将 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

In order to validate against the real receipt after testing, change this line of code in your main.m file:

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

to

#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

and in your compiler settings, "Other C Flags" for your Debug Configuration should include -DUSE_SAMPLE_RECEIPT

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

霓裳挽歌倾城醉 2024-10-11 05:46:24

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

请参阅 http://pastebin.com/1eWf9LCg ,看起来《愤怒的小鸟》错过了这一点,并将其留给人们在收据中替换一个免费的应用程序。

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

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

Be sure to check that you are validating a receipt for your app. Easy to do all the crypto and verification of signatures for the wrong receipt.

See http://pastebin.com/1eWf9LCg where it looks like Angry Birds missed this bit and left them open to people substituting in a receipt from a free app.

Alan Quatermain also has code to do this up on github. https://github.com/AlanQuatermain/mac-app-store-validation-sample

It should not be used as-is to avoid automated removal.

深海夜未眠 2024-10-11 05:46:24

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

You could try NPReceiptVerification. It's the easiest way to add receipt verification to your app. You just add the class files to your project, set the version and bundle identifier, and everything else is handled automatically.

孤芳又自赏 2024-10-11 05:46:24

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

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

当开发者将应用程序提交到应用商店进行审批时,签名证书如下:

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

应用程序从应用商店交付给最终用户后,签名证书如下:

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

另外,我建议仅在以下情况下退出(173) :收据不见了,但其他一切都井然有序。

I reviewed Alan Quartermain's code and it looks good. Something to think about:

the last parameter here could/should be a compiled requirement stating that the code must be signed by YOUR certificate and no-one else's.

When the developer submits an app to the store for approval, the signing certificates are as follows:

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

After the app is delivered from the App Store to the end user, the signing certificates are as follows:

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

Also, I suggest only exit(173) when the receipt is missing, but everything else is in order.

惜醉颜 2024-10-11 05:46:24

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

You can Refer the RVNReceiptValidation it is easy to implement. Just you have to set the Bundle id in RVNReceiptValidation.m file and version of your App. Remember to get the receipt from the apple you have to launch the app from the Finder. This Class also helps in the implementation of InApp Purchase.

街角卖回忆 2024-10-11 05:46:24

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

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

I'd propose to implement the code verification routines as C functions, not ObjC methods.

This technique makes it (a bit) harder to locate receipt checking code, since fewer method-names get compiled into the binary.

妄断弥空 2024-10-11 05:46:24

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");
}

RVNReceiptValidation is great and it uses CommonCrypto rather than the now deprecated by Apple, openssl. you will have to attach a valid receipt to your project to debug it. Do this by getting a valid receipt from another app bundle and create a build phase in your test environment to add it to your bundle. I suggest the following techniques for obfuscation:

Encrypt the kRVNBundleID and kRVNBundleVersion and decrypt them when you compare them to the CFBundleIdentifier and CFBundleShortVersionString.

I create an array of function pointers with random values and change them to valid pointers to the functions in RVNReceiptValuation at run time before executing them using code like this:

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");
}
自控 2024-10-11 05:46:24

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

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

I'll elaborate on priller's answer. If Apple provided a code sample for the validation process then it would be very easy for a Bad Guy to take your compiled app and scan through it for the code corresponding to the validation process. The Bad Guy would know exactly what the compiled code looks like if you use a standard code sample from Apple. Once the Bad Guy has found that section of the code it is pretty trivial to modify the app's compiled code to just skip the receipt verification stage, rendering the entire thing useless.

All that said, a determined cracker is probably going to get around any copy protection you put in place regardless of what you do. The games industry (for example) spends a lot of time trying to protect their software, and cracked versions seem to always be available.

柳絮泡泡 2024-10-11 05:46:24

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

When creating the sample receipt from Apple Docs, be sure not to include any extra characters after 'end' else the uudecode will fail.

我做我的改变 2024-10-11 05:46:24

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

Yes, in their docs it says, "It is important that you employ a solution that is unique to your application."

乖不如嘢 2024-10-11 05:46:24

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 调试标志的原因。

完毕。您现在可以调试您的应用程序。

roddi's ValidateStoreReceipt worked for me before, but it does not work any more.
I wrote a blog post about the solution: http://vinceyuan.blogspot.com/2012/07/validate-mac-app-store-receipt-2012.html

Copied here:
roddi's code is still working. You need not change it. (Just need to get the latest version)
Follow these steps (internet required):

  1. Log out from Mac App Store app.
  2. Remove USE_SAMPLE_RECEIPT flag from your project settings -> Preprocessor Macros.
  3. Compile your project
  4. Find this app in Finder
  5. Double click it in Finder to run. Do not run it in Xcode.
  6. The OS will ask you to log in with your Apple ID. Do not log in with your real iTunes account. You need to log in with the test account. Find it or create it in the iTunesconnect website.
  7. The OS will say something like "Your app is broken. Download it in App Store". Ignore this message. If you "Show Package Contents" of this app in Finder, you will see there is a file _MASReceipt/receipt. The OS installed a development receipt. We will not need the old sample receipt any more. That's why we remove USE_SAMPLE_RECEIPT debugging flag.

Done. You can debug your app now.

祁梦 2024-10-11 05:46:24

即使使用 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

Even with NPReceiptValidation you still should validate the security of your application bundle including the signing certificates. This is documented in the WWDR recommendations for developers.

A solution:
http://itunes.apple.com/us/app/apptight-pro-app-store-code/id427083596?mt=12

One potential problem with NPReceiptValidation is that method selectors on Cocoa objects are very easy to hijack. It's the most popular way of extending apps.

Here's another tool for assisting with In-App purchase parsing:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文