espes / Slave-in-the-Magic-Mirror

Open source implementation of AirPlay Mirroring. WIP.
610 stars 122 forks source link

iOS9 #12

Open ghost opened 8 years ago

ghost commented 8 years ago

So i've managed to get iOS9 to negotiate and start sending data. The config record looks correct (non encrypted). But the video data makes no sense once decrypted.

It appears that the key must have changed.

I tried to find a decrypted version of the newest formware for apple TV but I can't seem to find one. Emulating thumb is not a problem if i can find the firmware.

Any ideas

espes commented 8 years ago

what happened?

ghost commented 8 years ago

I just updated the first post.

It works, the problem was I wasn't keeping the event port open. But the decryption key seems incorrect.

As a sanity check I checked the challenge/response from a log of ios9 and an appleTV and fed the same into the existing airtunesd and the results are different. ios9 still seems to accept them and sends the video data though.

I can only guess the decryption key must have changed.

ghost commented 8 years ago

There also seems to be data of type 5 every 30 video packets. I'm guessing it may be audio info since everything is now being sent over this one connection.

Type is: 1 config record Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 5 wtf 194 5 0 0.0 Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 0 Encrypted Video Data Type is: 5 wtf 25194 5 0 0.0

ghost commented 8 years ago

Strangely ios7 works with the same protocol, AND the video data still doesn't decrypt.

ghost commented 8 years ago

Hmm looks like i've hit a dead :( It seems ios9 is using a different key/encryption which probably needs the library from the new apple tv firmware. I don't think decryption keys are available for the new apple tv firmware tho?

Any ideas on your end? It's also possible the video format has changed but i doubt it.

ghost commented 8 years ago

Maybe the sochi firmware can handle this type of encryption. I'll have to setup qemu and find the entry points tho. Any chance you have the entry points already?

espes commented 8 years ago

No. I'm going to have a look at all this soon now that unicorn is released.

ghost commented 8 years ago

Oh i didn't know about unicorn! I'm attempting to decrypt an even newer firmware at the moment, will let you know how it goes. In the meantime here's a quick test vector for challenge 1 so you can check if it's generating with the new or old key.

46504c590301010000000004020003bb < 46504c5903010200000000820203d7ce93237c7d52efb40385eee64ed14616cad9dc49bdba930c1d8b359475f8d3da5a8356dbdd929eddb74e3a5e2b1e3c7e2587b9ba5a48f387484a4530f825d789440f15f9965d547d2bb51d45f1de0c58962bcbc0b8ca451793305a89aafbd60bf436272dd75fff777b2976112f8b373bac39e8175ac4a5b08e2f95cab6e47e

The current airtunesd returns this instead: 46504c5903010200000000820203879f7a3d3ce5a4c5db51176fa886babd9ca307a9626d8bbeee2ec31a2efdec3d9f5714833e2b3ffe6044b09a8c9946dfda0bceb86af01d27757f2f37ab366d138c0bd89b792d35695884089618460d4888ee0d09ed829b61a94f41e0f4cba1d49a2009130a64336ce44a030bca9960b9ba91511db91f4a3df46f246de2171f98

Noiled commented 8 years ago

@kam187 which firmware do you use to pass negotiate?

ghost commented 8 years ago

It's a special set of attributes in the bonjour message to skip it. Let me get to my computer and I'll post it in about half an hour.

ghost commented 8 years ago

Here you go: The real device sends 0x507FFFF7,0x1E but the following is sufficient to make the device connect AND skip the initial verify stages:

            'features': u'0x507FFFF7',
            'model' : u'AppleTV3,2',
            'srcvers': u'220.68',
Noiled commented 8 years ago

@kam187 when I change the attributes as you said above , no video data comes and logs below AirTunes: 172.16.8.93 - - [22/Oct/2015 16:11:39] "POST /fp-setup HTTP/1.1" 200 - AirTunes: 172.16.8.93 - - [22/Oct/2015 16:11:39] code 501, message Unsupported method ('TEARDOWN')

on iOS 9.0.2

ghost commented 8 years ago

It's not as simple as that. The protocol is totally different. If you're just expecting it to work it won't, a lot more work needs to be done yet.

Noiled commented 8 years ago

@kam187 ok , if you decode the video successfully, please let me know.

ghost commented 8 years ago

The encryption has changed so we need to find the decryption key for the new firmware and then reverse that firmware to find the decrypt function :/

espes commented 8 years ago

What would be useful is a packet capture of the newer protocol. Can you help with that?

ghost commented 8 years ago

Yeah sure Ill upload it when I get to my computer

In the mean time there's one on here too:

https://github.com/juhovh/shairplay/issues/43

Although it doesn't show the actual image data

ghost commented 8 years ago

Hmm a bit of an update. I've managed to debug through a commercial solution (took forever) to get me a decrypt key for a logged session but the resulting data has no valid NALU format :/

Any ideas?

ghost commented 8 years ago

I wonder if it's switched to AES-GCM mode, but i wonder what the authenticated tag is...

ghost commented 8 years ago

Nope not AES-GCM :/

Noiled commented 8 years ago

@kam187 leave me an email

ghost commented 8 years ago

My id at gmail dot com

ghost commented 8 years ago

Anyway I'll try to debug and double check the key when I have time. The only other thing I can thing to do is try to debug the decryption part but the whole thing is heavily obfuscated :/. Probably the original AirPlay library embedded in there.

ghost commented 8 years ago

I've got hold of a airtunesd from version 190.9, it looks to have updated init/challenge/decrypt functions which i've identified.

It contains thumb code though so we need a better emulator - espes drop me an email I can pass it over if you want to have a go.

ghost commented 8 years ago

One more experiment, i sent a fake bonjour with features 0x527FFFF7 but pointing to a commercial airplay receiver. I traced the traffic and there was no pair verify as expected but the whole thing worked fine.

So that means (for now at least) we can ignore the pair verify and use this feature ID and concentrate on the init/challenge/decrypt.

ghost commented 8 years ago

More progress. I'm now able to load the library and run it. But the fp_init function seems to have changed. There's a call to GetFairPlayHWInfo which stores something at a pointer which now has to be passed into fp_init. Unfortunately GetFairPlayHWInfo is an external symbol and I don't have access to the full firmware :(

I've tried the usual stuff of mallocing an buffer and passing it in but it doesn't work :(

ghost commented 8 years ago

omg decryption key is verified, sending the NALU directly to VLC displays some garbled parts of the screen until it crashes.

That means the old format of LEN , LEN, has now changed to something else.

ghost commented 8 years ago

Edit false alarm, was deciding the wrong stream :/

Noiled commented 8 years ago

Can you show a screenshot ?

发自我的 iPhone

在 2015年10月30日,下午11:30,kam187 notifications@github.com 写道:

omg decryption key is verified, sending the NALU directly to VLC displays some garbled parts of the screen until it crashes.

That means the old format of LEN , LEN, has now changed to something else.

— Reply to this email directly or view it on GitHub.

SharpCode commented 8 years ago

@kam187 int _GetFairPlayHWInfo(int arg0) { rbx = arg0; _GetPrimaryMACAddress(rbx + 0x4, var_C); rax = var_C; if (rax == 0x0) { (int32_t )rbx = 0x6; } return rax; }

ghost commented 8 years ago

Thanks. I've just discovered the airtunesd that was sent to me is from 7.0.1 firmware '11A470e' which has a decryption key available (https://ipsw.me/keys/AppleTV2,1)

int fp_init(int a1, int a2) @ 0x429B4 int fp_challenge(int a1, int a2, int a3, int a4, int a5, int a6, int a7, _BYTE a8 @ 0x7B67C int fp_decrypt(int a1, int a2, int a3, int a4, int a4) @ 0x34418

(fp_init is definitely correct, the other two are from a quick glance but looks correct, first step is to get init to work!)

ghost commented 8 years ago

SharpCode, which file is that from? I'll decrypt the firmware and take a closer look.

SharpCode commented 8 years ago

OSX 10.11.1 /System/Library/PrivateFrameworks/CoreUtils.framework

SharpCode commented 8 years ago

/System/Library/PrivateFrameworks/AirPlaySender.framework

ghost commented 8 years ago

Cool, thanks! I just found this:

https://github.com/foxsen/fairplay-server/blob/master/fairplay-server.c

anyone know the offset for 'airplay_load_hwinfo' in the old airtunesd? I'll just use that to grab the structure. Getting the AirPlaySender.framework to work may not be easy.

ghost commented 8 years ago

(of course that's his name for it, but the equivalent anyway)

ghost commented 8 years ago

nvm 0x1D754 :) <-- EDIT, nope that's not it.

In the old airtunesd it passes in a unsigned chat buf[24] memset to 0

SharpCode commented 8 years ago

Cool @kam187 Your information is very useful!

ghost commented 8 years ago

Ok so the old initsap gets passed in the unsigned char buf[24] memset to zero and when it returns it's full of 30 30 30 30 30 etc i.e. ascii 0's

This is running on an iphone though. Switching to the new airtunesd i now have unresolved symbols. I'm trying to add in coreutils now.

ghost commented 8 years ago

Finally extracted all 495 frameworks.. slowly slowly getting there!

ghost commented 8 years ago

So here's an update - There's 3 main methods i've tried and each one has failed for a different reason - but I thought an update here might be useful. (Here 'old library' means the current one in slave in the mirror that is the OLD protocol).

1) The first method which is probably the easiest to prove the library before going to too much effort is to use an iphone and dlopen the airtuned. An iphone because it's a bsd based system running on ARM and for the most part libraries are compatible because things like lockdownd etc exist on an iphone too. This isn't so great for the long term obviously because you can't use an iphone as a slave to decrypt :P Anyway....

With the old library this works fine. You can create a pointer to the function and call it directly - in the same way as slave in the mirror does now actually. This works because a) the init/start function of the airtunesd is self contained. i.e it doesn't call any external functions, so the library loads in without complaint. AND b) because the init function is self contained and doesn't need to call symbolic functions, it just branches around and calls fixed subroutines as part of its obfuscation.

With the new library, the start/init section calls some functions which are in an external library (CoreUtils), so the dlopen fails and airtunesd doesn't load in. To get around this I extracted the CoreUtils lib from the apple firmare and tried to link it. Codesign fails complaining it's the wrong format. So i used a jailbroken iphone and turned off codesign. Now the library links AND loads 'yay'!

However when i try to load airtunesd it's still looking for the library in the Private framework directory. This means that library's imports need to be changed - headache! (that's because the iphone uses a shared cache which has all the libraries in it and it's not as easy at pointing it to a local copy of that library :(

If i try to statically link airtunesd (where i have more control on where it gets it's symbols) it fails because after xcode 5 the arm executable overide no longer works

Dead end for now.

2) The second thing i tried was essentially 'copying' the assembly of the function and running it. I malloc some memory and mark it as executable. I load in the whole airtunes library, point to the correct memory address and run the function.

With the OLD library this works, with the new one i get a sigsys or signal 4. This means at some point it's calling a symbolised function or worse an imported function which obviously doesn't exist yet :( This clearly won't work for this new library.

[BTW this was with qemu in user mode and not with an iphone]

3) I extracted the AirPlayFramework from the latest firmware (sochi) we have a key for and disassembled it. I tried the same two methods above, but the same issues exist. The library imports functions from CoreUtils and directly running the function crashes.

i'm hearing stories that people have this running on qemu etc but i'm inclined to think that's either the previous library or they're importing a bunch of the private libraries from an apple tv and have got around the dependancy nightmare somehow.

Anyway now i've jailbroken the iPhone my next step is probably to install gdb on it and go back to the directly running the asm method to see where and why it's actually crashing.

Oh and one last thing, it seems the gethwaddress stuff was a mistake. The mac address IS passed into the initSAP function but that's not what is/was making it crash. I assume that's just to index the buffer against the incoming client or something like that - in any case it may be relevant to the key at a later stage but for now passing buf[24] full of 0's is enough.

Anyone with any other ideas or any help would be welcome!

ghost commented 8 years ago

slight update on 3)

I can statically link the AirPlayReceiver.framework AND confirm it's loaded in. BUT the fp_init function is no longer an exported function. Pointing to it's address gives me a EXEC_BAD_ACCESS or in the linux world i believe this is a SIGSEGV or bad memory access.

This could be happening because that memory is protected, OR because again an import is missing. I'll need to get gdb running to check it out i think

BTW if anyone has any ideas please let me know. I can share source code but you'll need to extract the firmware yourself for legal reasons.

ghost commented 8 years ago

Challenge phase 1: 46 50 4C 59 03 01 01 00 00 00 00 04 02 00 00 BB Response: 46 50 4C 59 03 01 02 00 00 00 00 82 02 00 3B 25 AC 1F 18 9A F1 19 18 56 65 64 D5 1D 76 53 57 A4 9F 7D 77 55 75 B2 A7 C4 CC 62 50 37 63 3E 35 4F F0 36 0B F9 BA 14 63 5A 90 BC BE 88 F7 0B 74 75 81 26 08 D8 A9 BC 8F E2 2A A1 6D F2 93 88 AB 54 29 E3 39 F8 36 00 3E 06 E2 B7 A7 2B 58 E4 82 A8 A6 6B 69 D1 F5 60 2D 16 0A 6B 7D D9 A0 5F 73 65 FE 8C 31 DA 11 97 0D B0 55 92 0E A1 1C 3B 5B 9B 11 27 81 95 48 06 F4 76 4D B3 8C ED 93 D4 Challenge phase 2: 46 50 4C 59 03 01 03 00 00 00 00 98 00 8F 1A 9C C0 42 CD F4 D1 16 A4 7F DC 6A E4 76 63 BB 48 D4 59 98 D8 FC 24 D9 98 BB C9 95 9E 28 04 92 D9 D5 C1 8A 63 DC 93 30 2B 9D 01 38 DA CF 02 ED 43 E9 26 29 0B E7 53 0D C6 1B A7 53 DC B4 96 0F FB D5 0A 86 B0 E9 18 E0 12 DA 63 90 23 C5 96 B8 A4 09 B5 19 39 A0 53 BC 4C FE 6F 52 35 C4 73 CC 89 DF 31 D9 66 7D C7 A2 F7 79 6B 67 A6 18 1B 7F 29 DF 08 E6 41 1F F7 2D 31 0C AD EF BC 60 20 55 D4 A6 48 97 F4 E9 52 C5 B1 59 11 E0 23 A9 67 6B 96 8D 96 A3 F2 F0 Response: 46 50 4C 59 03 01 04 00 00 00 00 14 48 97 F4 E9 52 C5 B1 59 11 E0 23 A9 67 6B 96 8D 96 A3 F2 F0 Decrypt:46 50 4C 59 01 02 01 00 00 00 00 3C 00 00 00 00 0F 30 DF E0 7D AB 9C 2F 04 A1 CF 05 2B F7 FF D0 00 00 00 10 B6 D4 3C E1 FB 16 DE B6 F3 9D 03 D2 D3 94 AF C5 8D 11 7E B2 DB A0 50 36 8C 10 14 14 0C D5 E2 F5 70 87 9C 28 Response: 47 BE 46 1F D2 46 91 AD 03 BD 4A 39 73 DE 91 81

Next problem, this key results in incorrect data :/

jkiddo commented 8 years ago

Nice!

jkiddo commented 8 years ago

You wouldn't happen to know if it is the same key pair used for the fairplay part used between iTunes-to-iTunes instance?

ghost commented 8 years ago

Unfortunately not because all i'm actually doing is forcing the library to load and calling its functions. It's heavily obfuscated.

Challenge 1 and 2 (and the responses) above come from a log between my phone and my appleTV. I've passed the same challenges to the airtunesd i have running and the responses match (YAY).

The encrypted key (Decrypt challenge) come from the same long, and the result comes from this airtunesd. I can't verify if it's correct or not because i have nothing to match it against.

Anyway i've tried decrypting the video traffic with this key and it doesn't give me any sensible NALU data. I even tried playing with endiness etc in case that was it, but nope nothing.

Not sure where to go from here :(

jkiddo commented 8 years ago

For whats its worth - I've been in contact with foxsen and he has pulled his server down. However you should check your mail right now ;)

ghost commented 8 years ago

Awesome! Thanks. Is that the new or old airtunesd tho? I'll find out in a second...

BenxiangGe commented 8 years ago

@kam187 , could you share the source? my email: gebenxiang at hotmail.com. Many thx.

omittchi commented 8 years ago

I don't know if this helps you any, but apparently a Chinese developer was able to accomplish mirroring functionality in ios9. There a thread here discussing it http://forum.kodi.tv/showthread.php?tid=223465