Apple’s Lightning is the proprietary charging and data interface found on
the iPhone and some other Apple devices.
Most people probably only know it from charging their phone, transferring files, or connecting
their wired headphones to the iPhone. However, Lightning can do much more, including some very
cool hardware hacking related things: For example you can buy these DCSD
cables online that give you - via lightning- access to the serial console of the iPhone.
There are also a couple of cables you can find information about online that give
you access to JTAG - the processor debugging interface - on the iPhone,
which makes it possible to do some really cool low-level security research.
In this series, we will investigate the technical details of Lightning: In today’s video we will
start by looking at the way Lightning communicates with the cable: What actually happens when you
plug-in a Lightning cable? In the next videos we will then look at re-implementing the Lightning
protocols on our own - eventually ending up with a home-made iPhone JTAG cable!
Now you might assume that a Lightning cable is just a simple passive cable: It has the
Lightning connector on one end, a bit of wire, and then USB on the other end. However in reality, a
simple Lightning cable is much more complex: I’ve dissolved the Lightning connector of an old broken
cable in Acetone, and if we look at the connector after removing some metal shielding we can see
that there’s much more in here than just a bit of wire: There’s a tiny PCB behind the connector,
with a couple of chips, capacitors and son! So lets start figuring out what this chip does!
1:25
To start, let's look at the Lightning connector itself:
The Lightning connector is famously reversible, and has 8 contacts on each side. However if we
remove all the lint that always gets stuck in the Lightning port, we can see that there are
only contacts on one side, and so we already know that Lightning only uses 8 of the 16 contacts.
So lets take a look at what happens on the electrical level when we plug-in a
lightning USB cable into an iPhone! I’ve cut apart a Lightning extension cable,
soldered on some jumper wires, and connected a Logic Analyzer to the plug. This allows us to see
what happens when we just plug a Lightning cable into the iPhone without anything connected to it!
Lets hit record in the logic analyzer,
plug in the lightning cable into the iPhone and we can see some signals! Well… two!
And if we zoom in on the signal, and check the different parts, it it looks
like it’s the same signal alternating over and over on both lines… As we have
nothing else connected it looks like this might be the signal that the iPhone uses
to poll whether something has been connected to the iPhone..
Before we go any further and connect an actual peripheral to the lightning port,
lets have a deeper look at that signal.
If we look at the repeating signal, we can note that it contains four larger
pauses. Maybe these are some kind of separators, for example between bytes.
Lets zoom in on one of these blocks. I’m intentionally selecting one in the center here,
as it makes it more likely we are not looking at a prologue or epilogue of the signal.
Now when staring at this we can notice that this block has 8 valleys in the signal,
with two different lengths.. And.. maybe these two lengths indicate whethera zero or one is
transmitted.. This could make sense, as with 8 of these we have enough bits to form a byte.
One problem though: We do not know what’s a 1 or what’s a 0.. And we also
don’t know the bit-order.. There are a couple of ways we can go from here,
but it’s likely that Apple did not fully reinvent the wheel when designing Lightning,
and so probably this is some kind of well-known protocol… So why not just ask ChatGPT?
So lets ask it: Which embedded single-wire busses
exist that encode bits with different lengths of low and high signals?
And it helpfully suggests: One such bus is the 1-Wire
bus developed by Dallas Semiconductor (now a part of Maxim Integrated). It uses a single
wire to communicate data by encoding a bit as a specific duration of low and high signals.
So lets check out the Wikipedia article on 1-wire, skip over all the blabla and
look for a signal diagram…and here we are.. This looks very familiar!
Ones are encoded as a short low pulse and a long high pulse, and zeroes are encoded
as a long low pulse and a short high pulse, this looks just like our signal! Awesome,
this is it! Thanks ChatGPT! The timing of our signal is a bit different, but we can
use the information from the wikipedia article as a good first assumption on encoding and bit-order.
So lets go back to our signal and try to decode it by hand:
We ignore the first part as it seems to be a start bit or something along those lines, and
look at the block after it: We can annotate the bits here with what we saw in wikipedia: Zeroes
are when the signal is mostly low, and ones are when the signal is mostly high… Lets also do the
same with the other three blocks… Now according to wikipedia, the least significant bit comes first,
so we can now go ahead and convert the signal into hex, and we end up with 4 bytes: hex 74 00 02 1F.
Now equipped with this knowledge we can write our own logic analyzer plugin. This
would make analysis much easier! But.. obviously we are not the first ones looking at Lightning,
and so there are quite some resources around it already.. In fact I wrote
a Logic Analyzer Plugin for the Lightning bus a couple of years
ago.. It’s called SDQAnalyzer and available on Github, and so let’s just use that one.
And if we load it into the Logic Analyzer and configure it correctly,
we can see that we now get the signal nicely annotated!
Time to analyze further. Let’s repeat the logic recording,
but this time with a real lightning cable connected to a computer.
To do that, I’m adding the other half of the lightning extension to our setup,
with the Logic Analyzer in the middle to sniff the signals.
So lets again hit record, connect the cable, and.. There’s a lot more going on here!
The first thing to notice is that the regular polling is gone.. Instead,
if we zoom in and remember our previous analysis of the polling signal,
we can see that the first part is the same: 74 00 02 1F - but.. now there’s a lot more
data behind it! So it looks like the cable responded to that weird polling signal And
thanks to our logic analyzer we can even see the bytes: Hex 75, 10 09 and so on and so forth!
But there’s a lot more going on here. A lot of different messages via that 1-wire bus,
and we can also see that two other lines become active: Channel 1 and channel
2 have this weird differential signal going on.. And you might recognize it:
This is a high-speed USB signal! We can see the voltage is somewhere around 400mV, which is the
signalling level for USB! So is all that Lightning communication necessary just to get USB activated?
Now zooming back in onto the initial signal we can also see a short pause between the
data from the phone, and the response of the cable - this lets us figure out which
part of the signal is coming from the phone, and which part is coming from the cable! The
Logic Analyzer Plugin already knows about this, and so it put a small square there.
Now by just staring at this answer we will probably not be able to figure out what exactly
is going on here, but one thing we can notice: The first byte sent by the iPhone is hex 74,
while the answer begins with hex 75… Lets look at the next transmission..
Here we get hex 70, 40, 00 A6 sent from the iPhone, and hex 71 93 answered by the cable…
Again the first byte of the data sent by the iPhone is just increased by one in the response.
And in the next block it’s the same: 0x76 sent by the iphone, and the response begins
with 0x77! And here the same: hex 90 from the phone, 91 replied by the cable.
This makes it likely that the first byte sent by the phone indicates the type of
command or request, while the first byte returned from the cable is the
indication that it’s the answer to the request.
Also, if we list some of the requests, most of data seems pretty pretty low entropy:
The command or request at the beginning, lots of zeroes, but.. The last byte is always seemingly
random. If you’ve looked at embedded protocols before you can probably already guess what
this might be: a checksum! A checksum is used to check whether the data is was correctly received,
and the most common type of checksum is CRC - the cyclic redundancy check. However,
there are lots of different CRC polynoms, and so while we know the size - 1 byte or 8 bits,
there are still a lot of different CRCs that this could potentially be. Luckily, CRCs are relatively
easy to reverse-engineer, and using a tool call reveng, we can do it in a couple of seconds!
We just tell reveng the size of the CRC we are looking for - in
our case 8 bits - and provide it with a couple of samples. I’ve just copied
in a couple of the requests we saw in the logic analyzer.
And if we hit return… We indeed get two CRC polynoms that match the signal - perfect,
with this we are able to create CRCs for when we want to send our own messages! We
will need this when we start building our own Lightning implementation.
Now with the Logic Analyzer we can also decode all
data at once as string… and there are a couple of interesting things in there:
Over here there’s a string saying Apple, Inc - so this might indicate the manufacturer of the
Lightning accessory, over here it says USB-C to Lightnint Cable - which this indeed is,
and over here is a weird string.. And if you look very closely at your Lightning cable,
it actually has a serial number printed on it - and this is exactly that serial number!
Using this information we can infer the meaning of some commands: For example this request: Hex
80 00 causes the cable to respond with 81 Apple, Inc - so it might be a “Get manufacturer” command.
We can also notice that the cable responds with a 31 byte string - and the 0x1F in the request
happens to be 31 in decimal - so this might be the length of the response the iPhone expects.
And this request here, 80 01, causes the cable to
reply with A2249 - which happens to be the model number of the cable.
And.. 80 02 causes the cable to respond with USB-C to Lightning Cable (1m).
So just by staring at the logic analyzer output we
were able to already determine the meaning of some commands - awesome!
To summarize: We’ve figured out the communication protocol between the chip in the cable and
the iPhone - which by the way is commonly referred to as SDQ or IDBUS and I’ve linked
a couple of resources about it in the description, We’ve reverse engineered the CRC8 checksum used in
Lightning, and we were even already able to figure out the meaning of some of the Lightning commands!
In the next video, we will start building our OWN lightning cable - and program a
microcontroller to act as if it was the chip integrated in the Lightning cable.
I hope you liked this video, and to see you on the next one!