- Joined
- Mar 17, 2016
- Messages
- 90
- Likes
- 67
Something I've been working on lately, figured I'd post my progress.
Introduction:
The DSi and 3DS share many things, one of those is their protecting half of the bootrom on each main processor (of which there are two in each console). Initially upon boot, the bootroms are readable and executable, but near the end of the boot process, they are locked permanently. The DSi has an ARM7 and an ARM9, while the 3DS has an ARM9 and an ARM11. I'm going to be initially grabbing the ARM9 bootrom from the DSi, then possibly looking into attacking ARM7 using the early code execution to take over ARM7.
Basic concepts:
ARM processors, like most processors, have something called exceptions. Exceptions generally happen when something goes wrong with the software running on the processor. Initially upon boot, the exception vectors point to some uninitialized memory for it's handler, however RAM contents are kept upon reboot so we can put our own exception handler in, then all we have to do is cause an exception before bootrom gets locked. Easy, right? Well, not so much. Given that the bootrom is read only, it's pretty hard to get exceptions to happen and is likely impossible without some sort of external influence. This is where we use a technique called fault injection. Fault injection usually involves hardware, we can do lots of things like playing with clock speed, voltage levels or other things.
Basic tests:
About a week ago I started playing with the main voltage for the DSi processor, initially I wasn't getting very good results, but with some more testing I discovered where I was going wrong.
My initial setup was very simple, just a potentiometer on the voltage line and a switch to switch between normal voltage and the new, lower voltage. Initially I was trying to drag the voltage level down really far, but noticed that this wasn't very effective. I did get a few exceptions, but it was very inconsistent and crashed more often than I liked. After more testing, I found the sweet spot; it seems that just barely dropping the voltage fairly consistently causes an exception! So, after finding a good value on the pot, I replaced it with fixed resistors. This was my first real milestone.
Automation:
Doing this manually was way too slow, unfortunately, so I need to build something that can switch for me. Someone had graciously given me a dead 3d printer board, and on it I found some solid state relays. After a bit of testing, I determined that these were perfect for my purposes, and have since made a basic circuit with them:
(Please excuse the text oddities, those were out of my control)
From here, it's a simple matter of writing some code to control this circuit externally. I'll be using a raspberry pi 2 B to do this, since I have one on hand. I currently haven't written any code, but it's on the todo directly after writing this post
Hopefully, the ARM9 bootrom will be mine sometime this week
Introduction:
The DSi and 3DS share many things, one of those is their protecting half of the bootrom on each main processor (of which there are two in each console). Initially upon boot, the bootroms are readable and executable, but near the end of the boot process, they are locked permanently. The DSi has an ARM7 and an ARM9, while the 3DS has an ARM9 and an ARM11. I'm going to be initially grabbing the ARM9 bootrom from the DSi, then possibly looking into attacking ARM7 using the early code execution to take over ARM7.
Basic concepts:
ARM processors, like most processors, have something called exceptions. Exceptions generally happen when something goes wrong with the software running on the processor. Initially upon boot, the exception vectors point to some uninitialized memory for it's handler, however RAM contents are kept upon reboot so we can put our own exception handler in, then all we have to do is cause an exception before bootrom gets locked. Easy, right? Well, not so much. Given that the bootrom is read only, it's pretty hard to get exceptions to happen and is likely impossible without some sort of external influence. This is where we use a technique called fault injection. Fault injection usually involves hardware, we can do lots of things like playing with clock speed, voltage levels or other things.
Basic tests:
About a week ago I started playing with the main voltage for the DSi processor, initially I wasn't getting very good results, but with some more testing I discovered where I was going wrong.
My initial setup was very simple, just a potentiometer on the voltage line and a switch to switch between normal voltage and the new, lower voltage. Initially I was trying to drag the voltage level down really far, but noticed that this wasn't very effective. I did get a few exceptions, but it was very inconsistent and crashed more often than I liked. After more testing, I found the sweet spot; it seems that just barely dropping the voltage fairly consistently causes an exception! So, after finding a good value on the pot, I replaced it with fixed resistors. This was my first real milestone.
Automation:
Doing this manually was way too slow, unfortunately, so I need to build something that can switch for me. Someone had graciously given me a dead 3d printer board, and on it I found some solid state relays. After a bit of testing, I determined that these were perfect for my purposes, and have since made a basic circuit with them:
(Please excuse the text oddities, those were out of my control)
From here, it's a simple matter of writing some code to control this circuit externally. I'll be using a raspberry pi 2 B to do this, since I have one on hand. I currently haven't written any code, but it's on the todo directly after writing this post

Hopefully, the ARM9 bootrom will be mine sometime this week


. That rules out dumping to RAM, then just using an exploit to dump it out on a normal reboot. So, I had to think of something else. Looking at gbatek, most of the I/O is all on the arm7, and we're just getting code execution on the arm9 here, which has not a lot of contact with the outside of the SoC package. The few areas where it could, you need to poke some arm7-only registers to active them, and a few other things that may have been useful (the CE2 line, for example) are just write-once registers (until reboot, ofc) so it's not like we could send the data out in a serial fashion. I got stuck for awhile, but I think I've got the answer here, I just need to implement it. Some more data about the RAM: it has an active low "Write enable" signal, which, as it sounds, will disable writes if pulled high. Perfect, we can just pull that high and RAM won't be cleared, but the DSi won't end up booting into it's FW. However, it's easy to take over the arm7 at the stage of execution it's in, due to it mapping code into the shared WRAM that both arm9 and arm7 can access. So the final plan to get everything working is as follows: execute the glitch and get code execution before bootrom is locked. Once we have that, copy the data from the bootrom and into the main ram, then disable writes to main ram. Reboot again, wait for execution to reach the stage where we can easily take over the arm7, take it over and dump the bootrom to an SD card using the arm7