You can’t get bored with Nokias. That’s what I know for sure now. Because after all seemingly successful steps, the strategy suddenly has to be completely redefined once again…
The thing is,
userdata partition is encrypted anyway, even if you didn’t set up any sort of password protection. And IMEIs seem to play an important role in key generation for this partition. So, after you change them on boot (which I succeeded to achieve), you see a… password entering prompt. And after you enter 0000 (which is the default if you hadn’t set any of yours), you see this:
The password you entered is correct, but unfortunately your data is corrupt.
To resume using your phone, you need to perform a factory reset.
When you set up your phone after the reset, you’ll have an opportunity to restore any data that was backed up to your Google Account.
And a single button: “Reset phone”.
But that’s only half a problem. Another half is that you HAVE TO have stock recovery to do this. TWRP 3.2.3 just doesn’t understand the necessary commands (or, more exactly, doesn’t reset their state), so you’re thrown back into it everytime on boot even if you performed the reset.
Luckily, I had the stock recovery image and rolled back successfully. But this whole thing is a clusterfuck. So, what do we do now?
The original idea was to change IMEIs on every boot. Now, it seems like we can only change them on every factory reset. And the only thing to correctly perform it is the stock recovery. That’s why we need to modify stock recovery instead of stock boot image. Which is also fine for me, however, having no TWRP around makes things much scarier. Anyway, here we go…
By the way, I found out how to enter fastboot mode from the turned-off state. This is quite trivial: press and hold Volume Down + Power AND plug in the USB cable within the following second. After the phone vibrates, don’t release the buttons until you see
FASTBOOT mode on the screen. This is quite tricky to perform but actually works. For the recovery, the same story goes for Volume Up + Power. So, TWRP could be accessed in an autonomous fashion but that’s not our plan…
The recovery.img structure is much similar to boot.img structure. After all, they’re of the same nature, just serving different purposes. What it means for us is that we can use absolutely the same tooling (
abootimg, for instance) to manipulate them.
So, what new things do we need in the image? Obviously, a Lua 5.3 runtime binary, the
mtphreak.lua script created in the previous part, and a shell script to launch it on the file retrieved from the
nvdata partition. I decided to put all this into the
/sbin directory. And also, we need to reference the MTPhreak launcher in the
/init.rc script to be able to launch it somehow. So, to ensure that we don’t screw up, just add the permission declarations and the explicit script launch to the
on boot hook:
Rebuilding is like this:
(cd ramdisk && chmod -R 775 sbin && find . -print0 | cpio -o0a -H newc -R +0:+0 | gzip -9 > ../initrd.img)
../abootimg/abootimg --create ../new-recovery.img -f bootimg.cfg -k zImage -r initrd.img
Then we just reboot into fastboot and flash it:
adb reboot bootloader
Then we boot into the system, check our IMEIs, go to Settings - System - Reset options - Erase all data (factory reset), tap “Reset phone” and “Erase everything”, wait until the process completes, wait up to 5 minutes for the first boot, go through the entire first-time setup again, check
And the IMEI numbers are the same, just like randomization never happened. It’s clear to me now that
/nvdata/md/NVRAM/NVD_IMEI/MP0B_001 file gets rewritten from somewhere on each factory reset. We just need to find out where it’s rewritten from.
And it’s as simple as it gets: aside
nvdata, there’s another partition called just
nvram. The difference is the filesystem is totally non-standard, so we have to manipulate it on the binary level.
Nevertheless, I found the necessary partition offset for the same kind of 120-byte block as we got used to. I don’t exactly know whether this offset is different for every device. But it can be calculated as follows:
- Find the second occurrence of the
MP0B_001byte sequence in the binary dump and record its offset. In my case, it’s 0x219BE (137662).
- Subtract 120 from the offset. What I got is 0x21946, or 137542. This is the block start.
- The following 120 bytes is your IMEI block of the NVRAM.
So, the strategy is like this:
- Find the primary offset (that).
- Retrieve the 120-byte block with
dd if=/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvram of=/tmp/MP0B_001 bs=1 count=120 skip=[offset].
- Apply the
mtphreak.luascript to the block in the
- Rewrite the 120-byte block with
dd if=/tmp/MP0B_001 of=/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvram bs=1 seek=[offset] conv=notrunc.
And keep in mind that we’ve got limited choices of finding the primary offset. Of course, busybox can also be introduced but what can it offer?
Well, we have some rudimentary versions of
grep, as well as the knowledge that the
MP0B_001 sequence always starts at the even offset. Which gives us the following starting point:
hexdump -c /dev/block/platform/mtk-msdc.11230000/by-name/nvram | grep 'M P'. Not bad but still not perfect. We have to refine the result.
To do this, let’s first cut off all the offsets lower than 0x10000 and higher than 0xfffff, since actual IMEI file shouldn’t reside there. Then, we cut off all the calibration references.
hexdump -C /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvram | grep '4d 50' | grep 000 | grep -v 0000 | grep -v CAL
Now I just see 3 entries, which is already fine. But we need to cut off the other two. This is quite difficult, so the only surefire way would be to remove all the non-
MP0B strings, which gives us the following refined command to get the basic hex offset:
hexdump -C /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvram | grep '4d 50' | grep 000 | grep -Ev 'CAL|0000|MP1|MP2|MP3|MP4|MP5|MP6|MP7|MP8|MP9|MPA|MPB|MPC|MPD|MPE|MPF|MP01|MP02|MP03|MP04|MP05|MP06|MP07|MP08|MP09|MP0A|MP0C|MP0D|MP0E|MP0F'
And this is the basic offset (which can be retrieved in hexadecimal form by piping the result into
| cut -d). We don’t even know the exact position of
MP signature here. But it can be calculated with the shell builtins easily (yes, Nokia 1
busybox sh supports some bashisms). So, here’s the final version of
But something was still blocking it. And the worst part is that it’s not possible to debug this on a live recovery because adbd totally refuses to start. So, I decided to go full-Lua, ditching both
-- MTPhreak IMEI changer and randomizer for MediaTek NVRAM
Also, it turned out that the correct name to use from this recovery is
/dev/block/platform/bootdevice/by-name/nvram. Effing great, right?
Well, it also turned out that this recovery somehow runs only the
/sbin/recovery binary correctly. And I have to choose from 2 paths: either convert this entire effort to C, or modify TWRP so that the necessary recovery actions are performed in addition to the usual factory reset. I decided to go with the second one. And you’ll be able to read about the outcome in my next post.