So, after all the preparations in the previous part, we can actually look at the partitions. Well, not quite outright…
Dumping and extraction of the initial boot image was honestly the hardest part for me, largely because I had to do all this via Wine. I had to use a special version of SP Flash Tool with a special version of readback configuration XML which didn’t even work as expected but at least it had read something from the boot partition. If the image is not corrupted, I’m fine with this: as long as I can boot the image via
fastboot boot (remember that the bootloader was already unlocked in the very first part), everything else can be read with
busybox dd from it. I’ll call this hard-obtained
boot.img file the genesis image.
So, I decided to extract the genesis image structure the same way I did it for GerdaOS tree (luckily, this partition format is platform-agnostic), which involves abootimg tool. It definitely turned out that this image is incomplete. But my first idea was to actually fix the TWRP image with the genesis-extracted kernel and try booting it. So I actually needed nothing but
zImage, which was unaffected and fully read. So I extracted the
zImage with this Perl script and then tried putting it into TWRP tree. Still didn’t boot, although it’s clear that it tried.
At this point, I almost gave up. I mean, I admitted that I’m fine with sacrificing one of the partitions. And I ran
fastboot flash recovery twrp323.img from the snapshot from one of the forums (which also contained the non-working stock recovery image if anything). And it worked. So, the point is
fastboot boot doesn’t have enough working memory in this device to be actually functional. This really sucks. As well as the fact that you can’t just boot into recovery with Volume Up + Power or Volume Down + Power, you have to run
adb reboot recovery for that. Keeping both Volume buttons pressed certainly does something different, but it’s not booting into the recovery for sure. Bottom line: in order to boot into the recovery, you have to have a working system or Faildows-only tools. Nice, isn’t it?
Anyway, at least I managed to make
nvdata partition backups. That’s all I needed. TWRP 3.2.3 is fine for most purposes, and it also gives you full root ADB access. That’s what I really appreciate there. Of course, you can’t explore any modem-related stuff on a non-fully-booted system. But this is expected and also fine. Heck, it even has an internal terminal emulator - you can practically live there!
Now, this is where the pain ends and the fun comes.
First, I was able to look at the init structure of boot.img and… to find out that we don’t have many places to hook into anyway. But we’ll get to that in the next chapter.
Second, I mounted the nvdata partition right from the TWRP and found out that the file we need is called
/nvdata/md/NVRAM/NVD_IMEI/MP0B_001 indeed. So, I pulled it for the analysis, and I really don’t know why it’s 120 bytes long and why are the other 12-byte blocks (except the first 2 ones) non-zero and have this repeating pattern:
e9 1a 0b 2e 17 95 bd 0f 8b 86 53 72. Well, guess what? They changed the algo or at least the key mask since then! All my research is irrelevant now. Or is it?..
Well, 12-block pattern is still the case but whatever was true for the older MediaTeks is not true now. Now I have to figure it out myself. After all, I have some computer security education. Time to apply it for once, lol.
So, here’s what we know for now:
- The IMEI file is called
- It contains 10 12-byte blocks, so the algo is probably not much different from the previously known one.
- Whenever IMEI is zero - or empty - of just absent - whatever, the resulting 12-byte block is set to
e9 1a 0b 2e 17 95 bd 0f 8b 86 53 72.
- Whenever IMEI is non-zero, bytes 8 and 9 are always
0x79respectively. So the algo is definitely not so different from the previous one, just uses a different mask value.
At least that’s true for my device. I also know the values which my own device IMEIs translate into. So, we know the plaintext, we know the ciphertext, we know (with very high probability) how the data is arranged and that a simple XOR is used for the first 8 values, now we just need to find the key. And it turned out that the key can be derived by just inverting (XORring with 0xff) first 10 bytes of an “empty” 12-byte block. Really. The 0x74 and 0x79 values also come from this. So, in my case, inversion result was:
16 e5 f4 d1 e8 6a 42 f0 74 79
Which perfectly corresponded to what I had calculated with known plaintext. And the 0x74 and 0x79 values are not so magic anymore.
So now, we have a perfect IMEI file modification algorithm for really all MediaTeks (where such a kind of NVRAM access is enabled):
- Take the last 12-byte block of the existing 120-byte
MP0B_001file. Invert all its bytes by XORring with 255 (0xff) and then set the last two bytes (10 and 11) to zero. This becomes the master key block.
- Shape the first 8 bytes of an operating block (byte 0 to 7) from 15 IMEI1 digits with 0 added to the end and each pair swapped (i.e. 357369035621901 becomes
[0x53, 0x37, 0x96, 0x30, 0x65, 0x12, 0x09, 0x01]).
- XOR the operating block with the master key block. Result should be 12 bytes long.
- Set byte 10 of the resulting block to modulo 256 sum of odd positions of first 10 bytes.
- Set byte 11 of the resulting block to modulo 256 sum of even positions of first 10 bytes.
- For IMEI1, write the resulting block to the position 0 of
MP0B_001file, overwriting existing bytes.
- For IMEI2, repeat the steps 2 to 5 and write the resulting block to the position 12 of
MP0B_001file, overwriting existing bytes.
Here’s a function I came up with which implements this algo:
//MTK IMEI file manipulation routine
And now I have to translate all this, including IMEI randomizer, into Lua 5.3. Why? Because I already have a static Lua binary for ARM! I can’t stand languages where indexing starts from 1 instead of 0 but it’s a one-time task anyway.
So, here’s the entire module recreated in Lua 5.3, very suboptimal but working:
-- MTPhreak IMEI changer and randomizer for MediaTek NVRAM
Now, this is what I call open-source. Just copy, paste and run.
In the next chapter, we’ll get to the actual boot image modification. Stay tuned!