iMessage,解释
iMessage, explained

原始链接: https://jjtech.dev/reverse-engineering/imessage-explained/

随着技术继续以闪电般的速度发展,理解并能够驾驭复杂的系统变得越来越重要。 Apple 的消息传递平台 iMessage 就是此类系统之一,它包含多个层,可在用户之间传递端到端加密消息。 本文通过 pypush 的视角概述了 iMessage 的内部工作原理,pypush 是一个旨在提供通信协议透明度的开源项目。 首先,让我们更深入地研究 Apple 推送通知服务 (APNS) 所扮演的角色,它是 iMessage 使用的双向组件。 设备成功连接到 APNS 并获得“推送令牌”后,即可实现通知和消息的双向交换,类似于传统的电子邮件通信。 为了确保此功能,用户需要推送令牌和感兴趣的主题(在本例中为 com.apple.madrid),从而允许服务器相应地过滤通知。 APNS 使用伪 HTTP,允许通过 APNS 传输请求和回复。 ID 系统 (IDS) 在 iMessage 基础设施中发挥着关键作用,特别是作为密钥服务器。 向 IDS 注册需要获取身份验证令牌,这涉及共享用户的登录凭据。 经过身份验证后,每个用户都会向密钥服务器提供有效的加密和签名密钥。 随后执行公钥查找需要提交包含所需用户帐户详细信息的请求。 通过这样做,人们可以获得与所提供的帐户相关的身份列表,包括公钥、唯一设备 ID、会话令牌和推送令牌等基本信息。 会话令牌非常重要,因为它们提供对目标帐户的临时访问。 因此,发送消息需要知道收件人的会话令牌,这与地址作为目的地标准的常规电子邮件不同。 最后,由 HMAC 标记的每个 iMessage 有效负载附带的 AES 密钥并不完全随机。 今后,接收消息需要利用涉及预密钥的前向科学技术,确保充分防止潜在的未经授权的入侵。 用于进一步探索 iMessage 架构的资源和参考资料包括一些突出显示值得注意的技术方面的信息出版物。 这些资源包括 IM Freedom 的知识库、ElcomSoft 关于 iMessage 安全的研究、QuarksLab 关于 iMessage 隐私的文章、Nicolas

作者承认,创建 pypush 的黑客方法可能会导致面临与版权法相关的法律后果。 此外,作者还提到,由于担心潜在的反竞争行为,未来实施 pypush 等解决方案可能会遇到障碍,特别是考虑到围绕苹果 iMessage 等流行消息平台的市场竞争格局。 最后,作者强调了在处理复杂系统时保持在界限内的重要性,以免造成进一步的复杂化。 尽管可能面临法律影响,作者仍继续开发技术解决方案来满足实际需求,例如 pypush,而不是仅仅关注意识形态的纯洁性。 然而,作者指出,一些针对 pypush 项目的评论可能会导致混乱,而不是建设性的批评。 总体而言,作者认为,尽管开发替代解决方案存在法律和实际挑战,但尝试创新方法仍然是研究人员的一项重要任务。
相关文章

原文

This blog post is going to be a cursory overview of the internals iMessage, as I’ve discovered during my work on pypush, an open source project that reimplements iMessage.

I gloss over specific technical details in the pursuit of brevity and clarity. If you would like to see how things are specifically implemented, check out the pypush repository as I mentioned above. It’s a pretty cool project, if I do say so myself. Make sure to check it out!

If you still end up with any questions, feel free to ask me in the pypush Discord

the foundational layer

One of the most foundational components of iMessage is Apple Push Notification Service (APNs). You might have encountered this before, as it is the same service that is used by applications on the App Store to receive realtime notifications and updates, even while the app is closed.

However, what you probably didn’t know about APNs is that it is bidirectional. That’s right, APNs can be used to send push notifications as well as receive them. You can probably already tell where this is going, right?

Internally, after a device connects to APNs it will receive a “push token”. This token can be used to route notifications to that specific device.

Note: This token is technically different then the token you receive when using the application:didRegisterForRemoteNotificationsWithDeviceToken: API. That token is scoped for per-app use, and is requested using the bundle ID of the application. However, it is basically used for the same purpose.

When sending push notifications to a device, you also need to specify the topic a message is for. This usually looks like a Bundle ID, and for iMessage it’s com.apple.madrid. When a device connects to APNs, it sends a filter message instructing the server on which messages it wants delivered to it.

Note: The APNs server is also known as the APNs Courier. The filter message includes several lists of topics, for each of the different possible states. It may want a topic to be enabled, opertunistic, paused, or disabled

APNs is not only used for the actual message delivery part of iMessage. Using a pseudo-HTTP layer on top of APNs, IDS (which will be explained in a moment) can send queries and receive responses over APNs as well.

One tricky note that I will mention is that in order to connect to APNs, you need a client certificate issued by the Albert activation server.

the keyserver

The next piece of this puzzle is IDS. As far as I can figure out, this stands for IDentity Services, though I don’t think there is any official confirmation on that.

Note: You may also see it referred to as ESS. This is confusing because the APNs topic FaceTime uses is specifically called com.apple.ess. Moving on…

IDS is used as a keyserver for iMessage, as well as a few other services like FaceTime. Remember, iMessage is E2E encrypted, so the public keys of each participant must be exchanged securely.

The first step in registering for IDS is getting an authentication token. This requires giving the API your Apple ID Username and Password.

Note: As 2FA is now standard, it had to be retrofitted into the IDS API. There are 2 options for this: the legacy option, in which a 2FA code is directly appended to the password, and the “GrandSlam” option. In the GrandSlam option, “Anisette data” is used to prove you are the same device and thus do not need to enter the 2FA code again. You then receive a Password Equivalent Token (PET) which can be used as if it was the password + 2FA code.

After one has gotten an authentication token, it must be immediately exchanged for a longer lived authentication certificate. This certificate allows registering with IDS, but it is not yet enough to perform key lookups.

Perhaps the most important step of the IDS setup process is registration. This is where public encryption and signing keys are uploaded to the keyserver, as well as various other “client data” about what features the device supports.

When making an IDS registration request, a binary blob called “validation data” is required. This is essentially Apple’s verification mechanism to make sure that non-Apple devices cannot use iMessage.

Warning: In order to generate the “validation data”, pieces of information about the device such as its serial number, model, and disk UUID are used. This means that not all validation data can be treated equivalently: just like with Hackintoshes, the account age and “score” determine if an invalid serial can be used, or if you get the “customer code” error.

Note: The binary that generates this “validation data” is highly obfuscated. pypush sidesteps this issue by using a custom mach-o loader and the Unicorn Engine to emulate an obfuscated binary. pypush also bundles device properties such as the serial number in a file called data.plist, which it feeds to the emulated binary.

After registering with IDS, you will receive an “identity keypair”. This keypair can then be used to perform public key lookups.

When performing a lookup, you provide the account(s) that you would like to look up, and receive a list of “identities”. Each of these identities corresponds to a device registered on the account, and includes important details such as its public key, push token, and session token.

Warning: Session tokens are necessary to send messages to a device. They essentially prove that you made a recent lookup, because the session token expires. Session tokens cannot be shared, as they can only be used by the account that performed the lookup request.

message encryption

Now, we’ve setup the basics of iMessage. We have enough that we can look up the public keys of another user, as well as publish our own. Now we just need to put it together with APNs to send and receive messages!

In order to receive messages, one simply filters the APNs connection to com.apple.madrid and sends the active state packet.

Depending on which capabilities you advertised in your IDS registration, as well as the iOS version of the sending device, you may receive messages in the legacy (pre-iOS 13) pair encryption format, or in the new pair-ec format. While the pair format is much more documented and easier to implement, it does not provide forward secrecy using “pre-keys” (similar to Signal) as the new pair-ec format does.

You can then decrypt the message as described in several papers, and as implemented in pypush. Verifying the message signature is optional, but is obviously important if you intend your client to be secure.

Sending messages is pretty much the inverse to receiving them. Keep in mind that you can chose to individually send out messages to each recipient, or you can bundle all the different recipients and their respective encrypted payloads into a giant bundle, which APNs will split up for you.

Note: Another thing to keep in mind is that message are delivered to all participants in a conversation, including the other devices on your own account.

One more thing to keep in mind that is often overlooked when sending messages is that the AES key is not entirely random: it is tagged with an HMAC. Your message will fail to decrypt on newer devices if you use an entirely random AES key.

And that’s pretty much it! As I mentioned, this blog post is designed to give you a good idea of how the iMessage protocol fits together, so that you can explore the pypush code, not directly explain every technical detail.

resources and attribution

Many people and prior works have helped me understand iMessage. Here is a brief list, in no way exhaustive:

This blog post has been reworked from its original version.

联系我们 contact @ memedata.com