> HELP WANTED: If you happen to know why -0x400 trick works, or can get in touch with Geohotz/MuscleNerd, please let me know. I have tried to ask around but have not found any explanation. I would be happy to update this article if someone knows.
This is commonly done with fw updaters. first 0x400 bytes is a header that the earlier stage loader needs to see before it'll allow this stage to boot. So you RX the data, write it freely, just not the header. This is safe and will not allow any code exec since the header is missing. then at the end you sig check the whole thing you wrote, and if it is good, you write the header, making the whole image valid.
the trick here is you write 0x400 bytes of garbage first, 0x400 bytes earlier than your desired write. this is buffered but not written (treated as the headers). The rest of what you sent IS written (writing what you wanted where you wanted). then sig is checked. you fail. the first 0x400 is not written (and you did not want it written).
Also the part where you talk about “recovery mode” I think we referred to this as DFU mode back in the day. “Device firmware update” I’m not entirely sure it was called “recovery” at the time though I could be wrong as it’s been more than 15 years
DFU is implemented in the ROM; it is morally if not technically a subset of the open standard by the same name.
Recovery mode is implemented in iBoot; it provides mediated access to the command interpreter and some file-ish transfer capabilities.
Both are still in use; whilst the implementations have obviously evolved the fundamental interactions have not changed since the original Apple (not Samsung) ROMs.
I think DFU mode and recovery mode are different. In recovery mode the screen is initialized and displays the “connect to iTunes” image. In DFU mode the screen is blank; I think this is implemented by the bootrom and can be used to restore even iBoot.
ooo good point it’s been so long I might be misremembering. the reason I commented was because I thought you had to put the device in DFU to upload the image to the Media dir that was mounted rw. But again it’s been 15 years lol
We seek to 0x400 before where we need to write the data
SendWrite(fd, foo, 0x400, false);
We set the first 0x400 bytes of what we want to write to 0
SendWrite(fd, fw, fwsize, true);
We then set the rest of the bytes to our data.
SendEndSecpack(fd);
The iphone copies the data from 0x400 bytes onwards (which is all the data we wanted to write), then tries to verify the signature and fails. If the signature could be verified the first 0x400 bytes (which we left as all zeros) would then be copied.
So very many products are, but most people never see any of it, and most are boring enough that nobody cares to break them apart and see what's inside.
I think Fabien is looking for an explanation as to why shifting by 0x400 bypasses the signature check. For example, is that shift somehow corrupting the signature check logic, or bypassing it by convincing the checker that no check needs to be performed?
My guess is that the chip doesn't have enough RAM to store firmware image, verify it, and only then write it to flash. So instead it needs to write it on the fly as it receives data in chunks of 0x400 byte pages. It starts by erasing first page, but instead of immediately writing it instead keeps buffer for that page for later. Then it transfers remaining pages normally, and at the end only when signature is correctly verified it goes back to write the first page.
So it would appear the firmware has a header of 0x400 which is buffered during upload but discarded if the firmware fails the checksum at the end of the upload.
I'm reading this as the iPhone holds the first 0x400 bytes in a buffer and doesn't write them until the signature has been verified. Everything else does get written. The assumption is that stripping off those initial bytes would render the firmware unusable, except in this case where they just padded the write by 0x400 bytes!
I think it was lack of imagination on the part of whoever programmed it. I wager they were more afraid of someone taking total control of the baseband so they figured everyone would start writing programs at 0, so they protected the beginning, which is their most important code. They didn't foresee someone just skipping that part and writing part of the firmware for such a small change.
Just for history’s sake: I wrote iPHUC (and yes I was 19 and came up with that name lmao) and a guy with the nic “nightwatch” who I loved working with was responsible for the initial jailbreak and coining the term itself. I believe he was also responsible for pdf or tiff exploits that unlocked the PSP, too. He worked and lived in South America possibly at a university … but that’s all I know.
It was a really fun time and I learned a lot.
Also, George Hotz endangered the welfare of a few people who had kindly gotten us access to some documentation in Japanese despite repeated pleas not to do so. Very frustrating and why the dev team all eventually stopped working on the project.
Oh, I just remembered one of the people who helped us understand the ARM architecture (it was somewhat new at the time) had the nic “pineapple” which is why many of the early UIs had pineapples on them. Again, great people and it’s a shame we never kept in touch
ARM32 was nearly 15 years old by that point (the ARM700, the first 32 bit core dates to 1993).
Maybe not exciting but the ARM32 had the bulk of its life before the iPhone, ARM64 came shortly after. Old and boring for the original iPhone ISA was also intentional.
sorry i shouldn't have said "arm architecture" there obviously arm32 wasnt anything new: i figured that was implied. we wanted specifics on the S5L8900 and they were (and still are) quite hard to come by. this contributed to the discovery and instrumentation of DFU mode, iboot, etc that contributed to jailbreak
Less “intentional” and more “unavoidable”. There was limited runway to fix the S5L8900 design, the Cortex A8 wasn’t ready at tapeout, and so the ARM1176 was it. If Broadcom hadn’t looked like they were fumbling the BCM2730 it would have been an ARM1132 instead, and history would have been a little different.
And yet those are all 32 bit ARM cores. Which in some way was "unavoidable" as I don't know what viable alternatives existed for a phone SoC in 2007, though someone can correct that.
ARM1132? That is not a core I have ever heard of nor can find any reference to. I assume it would be some ARMv6 ARM11 though, a uarch that was already quite mature by the time the iphone rolled around.
> Also, George Hotz endangered the welfare of a few people who had kindly gotten us access to some documentation in Japanese despite repeated pleas not to do so. Very frustrating and why the dev team all eventually stopped working on the project.
Would love any elaboration on this that you can provide which wouldn't expose you to a libel suit.
Honestly I just remember careful coordination about what information / code / artifacts to release from the private IRC channel and when. He ignored the consensus a bunch of times which lead to demoralization and people leaving.
I’ll never know how real the threat to peoples jobs were but I don’t think they were being overly cautious.
Given his later actions with the Playstation 3 where he watched Fail0verflow's CCC presentation, then immediately pushed the first "Hello World!" firmware patch just so he could say he did. Immediately landing the entire team in hot water as Sony (understandably) assumed they were related parties
Geohot seems to have a history of throwing other people under the bus to score "victories" for attention
this was my experience so i was not surprised to read about the ps3 stuff. about 8 or 9 years ago i made a comment somewhere in the depths of HN with more information. honestly i dont really care about GH so much as I wish other people who were kind and brilliant got the attention and credit they deserve
It's tough because those events are exactly why GH "got the attention". People who kind and brilliant don't tend to beg for the spotlight, especially when working in greyhat matters like this.
>These three fields would be concatenated into a token.
The token would be sent to Apple server (albert.apple.com) where it would be signed with Apple's private key.
The signed token would then be sent back to the device.
A daemon lockdownd, listening over USB verified the token using Apple's public key.
With the proof that the token came from Apple, and matching DeviceID, IMEI, and ICCID, lockdownd updated the device state to "Activated".
The user then had access to the iPhone homescreen and the apps.
One anecdote I remember was when the release of iPhone OS 1.1 broke jailbreak and I was on the IRC channel: one of the tricks found was to downgrade to 1.0.2, jailbreak the phone, symlink the `/root/Media` directory (reachable through iTunes) to `/` which was preserved during an upgrade, then do a firmware update and have access to rootfs then.
There is no consensus on what the "S" stood for, and Apple never officially made any statement on the matter. "Successor" or "Second" or "Speed" all more or less fit, but there's no real answer.
Generally, "S" just indicated a marginal upgrade over the base model.
fuck this was a beautiful trip down memory lane thanks for the work putting and narrating this story so well.
I remember following the progress half way across the globe and doing the hardware soldering hack on my 1st-gen, then good ol'd Cydia days.
Can't process how young these people were and how they knew how to do such low-level investigative coding. I remember back then I was doing .NET c# and thought i'm the boss, humbling.
This is commonly done with fw updaters. first 0x400 bytes is a header that the earlier stage loader needs to see before it'll allow this stage to boot. So you RX the data, write it freely, just not the header. This is safe and will not allow any code exec since the header is missing. then at the end you sig check the whole thing you wrote, and if it is good, you write the header, making the whole image valid.
the trick here is you write 0x400 bytes of garbage first, 0x400 bytes earlier than your desired write. this is buffered but not written (treated as the headers). The rest of what you sent IS written (writing what you wanted where you wanted). then sig is checked. you fail. the first 0x400 is not written (and you did not want it written).
win