I’ve been wanting to make a thread about this for a while. Every single person here tuning their DME has this clever little exploit applied to their DME so I wanted to document it in case anyone was curious.
To give some context on the discussion I’ve put together a high-level memory map of the bin file. This is what the 2MB file that you make changes to actually looks like:
A brief overview of the areas:
The first area, labelled as the Boot-SW (Supplier) is what some refer to as the SBOOT. This is a small bit of code early on in the DME that handles the base functions of the chip. This contains the ISN, serial number and a backup copy of the vehicle VIN and is often referred to as the locked section of memory as it cannot be written to via the normal methods.
After that we have another area of Boot-SW, this one is customer specific often referred to as CBOOT and contains the code that BMW wrote to handle all the serial interfaces and reprogramming procedure. This can be reprogrammed along with everything after this point.
After that we have a section of ECU-SW which is the actual code that is responsible for the operation of the vehicle (boost control, fuel control, torque management). There are 2 that make up what is referred to as the software. This makes up the vast majority of the data in the 2MB file. This is what people refer to when they use terms like I8A0S, IJE0S or INA0S, this is the name of the software in the car.
We then have the calibration data. That is what most people know as the “Tune”. To put this into layman’s terms, this is the engine’s settings. This area is what is manipulated when you use TunerPro and the public XDF.
The sections in between, in white, are areas that contain the RSA signatures which are referred to as security keys and the file checksums which we won’t get into.
Now we get to the purpose of the post. The “RSA Bypass”:
All tools that read and write to the MSD80 and MSD81 (COBB, OpenFlash, MHD etc) use exactly the same process to do so. That all seemed to have copied each other down the line. I’m not sure who exactly created the original RSA bypass but I believe that COBB purchased/licensed their method and then the rest just coped it. Whoever came up with the original bypass is a real genius and undoubtedly put a lot of blood, sweat and tears into the process. I’m not sure if the trick originated on the MSD80, or if it was an existing trick that was used elsewhere that was just adapted for the MSD8x, but I’ll explain how it’s done in the context of the MSD8x.
To give context on what the RSA bypass is, we need to quickly run through what RSA protection actually is. I’m no expert on cryptography but I’ll give my understanding of it and hopefully if I mess it up, someone can correct me.
The overall function of the RSA protection is to prevent anyone from making any changes to the code inside the DME. This is to protect their warrantied engines and probably a legal requirement to protect emissions related inspection routines. To do this, RSA uses a pair of keys, the private key, that BMW keeps and is still completely secret and a public key that is written into the DME. BMW will use their private key and feed it the contents of the bin into it and it will generate a “signature”. This is then written into spare space in the bin. Once the contents of the bin are written into the DME along with the signature, the DME will use its public key to validate that signature, if the signature is valid the DME will accept the code and boot up normally. If not, the DME will reject the new code and stay in a failsafe mode until a valid file is written.
On some older DMEs they used smaller 512bit keys, probably due to hardware capabilities at the time. People (clever ones) were able to crack these by brute-force and just use the cracked private key to sign their modified files, I believe that's what they use on the MSV DMEs and old school slushbox TCUs. To prevent people cracking their new MSD80/81, BMW uses a 1024bit key and thus puts it outside of the capabilities of current brute-forcing (until quantum computing maybe).
Since brute force is off the cards, alternative exploits were investigated. The person responsible for the RSA bypass probably started off by decompiling the 2MB bin file and probing it for weaknesses. The weakness that we currently use relies on an oversight in the developer’s implementation of the RSA key verification process.
To explain the weakness, I need to add a little bit more detail to the above process of the BMW RSA signature generation. There are 2 signatures in the bin. One for the software and one for the calibration. We will just look at the software one since that is all that matters in this exploit. When the BMW software developers generate the RSA signature, they only look at certain sections of the bin. This can’t cover the entire bin contents because things like the signature itself will change after the signing is done and crucially, they also don’t check sections of memory that they expect to be blank which was the reason this exploit is possible. Once they generate the signature and write it into the bin, they convert that bin into an .0pa which is what WinKFP uses to flash the DME.
On the DME side, to match the process that the BMW engineers used at their end, the range of data that the DME looks at is defined in a table like this:
So, by looking at this table we can see the DME will take all the data currently in the chip between 80020000-8003FFFF, 80040000-80053DFF and 80080000-801FFC3F and then verify it with the public key. So as long as the data in those areas matches what BMW fed into the RSA generation using their private key we will pass the RSA check in the DME and our new software will be accepted by the DME. This is what happens when you update your DME using WinKFP and the 0pa and 0da files that in the DATEN files.
If you look at those ranges you can see that the second range looks suspect (80040000-80053DFF). This memory range is inside what should be the calibration sector. This is because the area of code that we referred to above as the CBOOT is actually the code that runs this signature check, so naturally it can’t be written to until the code has passed the RSA check. To verify the code before accepting it, the reprograming procedure requires that the area of the bin that contains the CBOOT code is parked into the calibration area temporarily until the DME can verify the signature, then it will take that code and overwrite the existing CBOOT code.
This is where things get clever. The exploit involves making a copy of the CBOOT code and modifying it to remove the part that verifies the signature, this essentially means the DME will always pass the RSA signature verification if we can manage to get the code accepted by the DME. But modifying this code will mean that it will no longer pass the signature verification while it’s parked in the temporary memory range.
To get around this problem we write both versions of our CBOOT code into DME, the first modified one in the area 80040000-80053DFF that will be written into the CBOOT upon a successful signature check, then the second copy of original unmodified code that we write into the spare calibration sector memory (0x80053E00-0x8007FFFF) which will not be used at all and be overwritten by the calibration data later on.
At this point we still have a problem with the signature as you can see in the above table, the DME will check the memory range where the modified CBOOT code is parked and will fail the signature check. To get around this issue we edit this table that lives over in the ECU-SW code. We do a similar process with this data, make a new copy of this table and place it in some spare memory that isn’t normally checked (the area after 801FFC3F). We then modify the original table so that instead of looking at the original areas where our modified code now lives, we point it to the blank memory areas where we wrote copies of the original code.
This now means once we write all this into the DME, it will check all that data and because all the data we are telling it to check is exactly the same as the data the signature was created with originally is all there, it will pass the check and write our modified code into the CBOOT area.
This now means that the code that is actively running in the CBOOT area of the DME will accept any new code. At this point the DME is “unlocked”.
To give some context on the discussion I’ve put together a high-level memory map of the bin file. This is what the 2MB file that you make changes to actually looks like:
A brief overview of the areas:
The first area, labelled as the Boot-SW (Supplier) is what some refer to as the SBOOT. This is a small bit of code early on in the DME that handles the base functions of the chip. This contains the ISN, serial number and a backup copy of the vehicle VIN and is often referred to as the locked section of memory as it cannot be written to via the normal methods.
After that we have another area of Boot-SW, this one is customer specific often referred to as CBOOT and contains the code that BMW wrote to handle all the serial interfaces and reprogramming procedure. This can be reprogrammed along with everything after this point.
After that we have a section of ECU-SW which is the actual code that is responsible for the operation of the vehicle (boost control, fuel control, torque management). There are 2 that make up what is referred to as the software. This makes up the vast majority of the data in the 2MB file. This is what people refer to when they use terms like I8A0S, IJE0S or INA0S, this is the name of the software in the car.
We then have the calibration data. That is what most people know as the “Tune”. To put this into layman’s terms, this is the engine’s settings. This area is what is manipulated when you use TunerPro and the public XDF.
The sections in between, in white, are areas that contain the RSA signatures which are referred to as security keys and the file checksums which we won’t get into.
Now we get to the purpose of the post. The “RSA Bypass”:
All tools that read and write to the MSD80 and MSD81 (COBB, OpenFlash, MHD etc) use exactly the same process to do so. That all seemed to have copied each other down the line. I’m not sure who exactly created the original RSA bypass but I believe that COBB purchased/licensed their method and then the rest just coped it. Whoever came up with the original bypass is a real genius and undoubtedly put a lot of blood, sweat and tears into the process. I’m not sure if the trick originated on the MSD80, or if it was an existing trick that was used elsewhere that was just adapted for the MSD8x, but I’ll explain how it’s done in the context of the MSD8x.
To give context on what the RSA bypass is, we need to quickly run through what RSA protection actually is. I’m no expert on cryptography but I’ll give my understanding of it and hopefully if I mess it up, someone can correct me.
The overall function of the RSA protection is to prevent anyone from making any changes to the code inside the DME. This is to protect their warrantied engines and probably a legal requirement to protect emissions related inspection routines. To do this, RSA uses a pair of keys, the private key, that BMW keeps and is still completely secret and a public key that is written into the DME. BMW will use their private key and feed it the contents of the bin into it and it will generate a “signature”. This is then written into spare space in the bin. Once the contents of the bin are written into the DME along with the signature, the DME will use its public key to validate that signature, if the signature is valid the DME will accept the code and boot up normally. If not, the DME will reject the new code and stay in a failsafe mode until a valid file is written.
On some older DMEs they used smaller 512bit keys, probably due to hardware capabilities at the time. People (clever ones) were able to crack these by brute-force and just use the cracked private key to sign their modified files, I believe that's what they use on the MSV DMEs and old school slushbox TCUs. To prevent people cracking their new MSD80/81, BMW uses a 1024bit key and thus puts it outside of the capabilities of current brute-forcing (until quantum computing maybe).
Since brute force is off the cards, alternative exploits were investigated. The person responsible for the RSA bypass probably started off by decompiling the 2MB bin file and probing it for weaknesses. The weakness that we currently use relies on an oversight in the developer’s implementation of the RSA key verification process.
To explain the weakness, I need to add a little bit more detail to the above process of the BMW RSA signature generation. There are 2 signatures in the bin. One for the software and one for the calibration. We will just look at the software one since that is all that matters in this exploit. When the BMW software developers generate the RSA signature, they only look at certain sections of the bin. This can’t cover the entire bin contents because things like the signature itself will change after the signing is done and crucially, they also don’t check sections of memory that they expect to be blank which was the reason this exploit is possible. Once they generate the signature and write it into the bin, they convert that bin into an .0pa which is what WinKFP uses to flash the DME.
On the DME side, to match the process that the BMW engineers used at their end, the range of data that the DME looks at is defined in a table like this:
So, by looking at this table we can see the DME will take all the data currently in the chip between 80020000-8003FFFF, 80040000-80053DFF and 80080000-801FFC3F and then verify it with the public key. So as long as the data in those areas matches what BMW fed into the RSA generation using their private key we will pass the RSA check in the DME and our new software will be accepted by the DME. This is what happens when you update your DME using WinKFP and the 0pa and 0da files that in the DATEN files.
If you look at those ranges you can see that the second range looks suspect (80040000-80053DFF). This memory range is inside what should be the calibration sector. This is because the area of code that we referred to above as the CBOOT is actually the code that runs this signature check, so naturally it can’t be written to until the code has passed the RSA check. To verify the code before accepting it, the reprograming procedure requires that the area of the bin that contains the CBOOT code is parked into the calibration area temporarily until the DME can verify the signature, then it will take that code and overwrite the existing CBOOT code.
This is where things get clever. The exploit involves making a copy of the CBOOT code and modifying it to remove the part that verifies the signature, this essentially means the DME will always pass the RSA signature verification if we can manage to get the code accepted by the DME. But modifying this code will mean that it will no longer pass the signature verification while it’s parked in the temporary memory range.
To get around this problem we write both versions of our CBOOT code into DME, the first modified one in the area 80040000-80053DFF that will be written into the CBOOT upon a successful signature check, then the second copy of original unmodified code that we write into the spare calibration sector memory (0x80053E00-0x8007FFFF) which will not be used at all and be overwritten by the calibration data later on.
At this point we still have a problem with the signature as you can see in the above table, the DME will check the memory range where the modified CBOOT code is parked and will fail the signature check. To get around this issue we edit this table that lives over in the ECU-SW code. We do a similar process with this data, make a new copy of this table and place it in some spare memory that isn’t normally checked (the area after 801FFC3F). We then modify the original table so that instead of looking at the original areas where our modified code now lives, we point it to the blank memory areas where we wrote copies of the original code.
This now means once we write all this into the DME, it will check all that data and because all the data we are telling it to check is exactly the same as the data the signature was created with originally is all there, it will pass the check and write our modified code into the CBOOT area.
This now means that the code that is actively running in the CBOOT area of the DME will accept any new code. At this point the DME is “unlocked”.