Another approach

As you already know, the previous part was a complete failure. And there are not that many attack vectors left, actually. And we still have an unlocked bootloader. However, it seems like the project goals have to be redefined. By the way…

By the way, I have recently watched the movie “Algorithm” (2014). Don’t get me wrong, the movie itself is great, however there’s a single ultrablooper that makes the whole thing utterly unrealistic. Look at this: the protagonist is so cool that he had broken into a phone company and installed his own backdoor, he had obtained and flashed a whole bunch of blank SIM cards, and he duly interchanges them every day at 18:00 in his… iPhone 5S. Lolwut? Really? There are so many wrong things about it I cannot even decide where to start from.

The first and most obvious issue is: what good is interchanging SIMs without altering IMEI number? Doesn’t such a z3ro c00l (pun intended) hacker know that you can be tracked by IMEI alone, and that only altering both IMSI (ICCID) and IMEI can give you a truly new network identity? And for obvious reasons, no iPhone allows you to even get close to its NVRAM/EFS/whatever it uses.

The second issue is that all iPhones have non-removable battery. Trust me, no real phreaker uses devices where you can’t physically cut off the power. And this is my main complaint about most touchscreen smartphones of nowadays. And this is why I keep my Nokia 1 around and am eagerly waiting for the ability to buy a Nokia 1 Plus.

Third, this is Apple. They track you by themselves. Even if you somehow manage to change IMEI, the serial number remains the same and it gets to Apple servers each time you do pretty much anything. Heck, Apple can even remotely render your device unusable, so how can such an ostensibly smart guy trust them anyway?

Anyway, back to the project. So, as I said, the goals have to be changed. And now, my primary goal is to create a boot image which randomizes IMEIs in the NVRAM at start, another boot image to backup the original and install this one, and another one to restore the original in case we need to run stock updates. That’s all I can think of in this situation.

This consists of several challenges:

  1. Dumping the original boot image (remember, we don’t have a working TWRP image on TA-1047) and NVRAM partitions to base the modified boot image on.
  2. Figuring out the format of /vendor/nvdata/md/NVRAM/NVD_IMEI/MP0B_001 file which contains both IMEIs, and an algorithm of encoding it.
  3. Creating a bootable modified image.

So, let’s take a look at what /vendor/nvdata and boot partitions are from the limited ADB shell.
Yep, unlike Qualcomm, MediaTek kernels don’t have that convenient /dev/block/bootdevice/by-name/ naming shortcuts. Everything must be accessed like this: /dev/block/mmcblk0p[some_number]. Which is confusing and error-prone unless you have the exact mapping…

Well, guess what? It’s not entirely that bad but the paths are definitely more confusing:

FRT:/ $ ls -la /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot

lrwxrwxrwx 1 root root 20 2019-02-27 10:15 /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/boot -> /dev/block/mmcblk0p7

FRT:/ $ ls -la /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvdata

lrwxrwxrwx 1 root root 21 2019-02-27 10:15 /dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/nvdata -> /dev/block/mmcblk0p18

So, we now know that boot partition is /dev/block/mmcblk0p7 and nvdata partition is /dev/block/mmcblk0p18. Well, at least the latter is EXT4. So after we extract the image, we can analyze it without significant obstacles. And yes, we NEED to analyze it because it seems like the file can have a different name than MP0B_001. For instance, on Xiaomi Redmi 6A, it’s actually called LD0B_001. And here, we only know the directory for sure but not the name itself.

So, here are your partition targets. And before actually starting doing anything, I’d like to find out about the IMEI file format which seems to be the same for all MediaTeks.

So, of course there is a tool to create the file of this format, and even though it’s not Faildows-only, no algorithm or source code was preserved. And of course, it’s undocumented. So, no option is left other than to reverse-engineer this stupid imei.i386… Or find another tool. Which reveals that the format is quite simple:

  1. The file is a sequence of one, two or three 12-byte blocks, one per each SIM.
  2. The first 8 bytes of a block (byte 0 to 7) are 15 IMEI digits with 0 added to the end and each pair swapped (i.e. 357369035621901 becomes [0x53, 0x37, 0x96, 0x30, 0x65, 0x12, 0x09, 0x01]), and then XORred with the byte sequence [0xAB, 0xA0, 0x6F, 0x2F, 0x1F, 0x1E, 0x9A, 0x45].
  3. Next 2 bytes (byte 8 and 9) are 0x57 and 0xDB respectively.
  4. And the next 2 bytes (byte 10 and 11) are modulo 256 sums of even and odd positions of all previous 10 bytes.

Yep, it’s that simple. Here’s a JavaScript function that performs the calculation for one 12-byte block from one 15-digit IMEI string, along with a randomizer function which respects Luhn’s checksum:

function IMEIblk(imeistr) {
let out = new Uint8Array([0xAB, 0xA0, 0x6F, 0x2F, 0x1F, 0x1E, 0x9A, 0x45, 0x57, 0xDB, 0, 0]),
nibbles = imeistr.split('').map(Number).concat([0]), i
out[i] ^= nibbles[(i<<1)+1] << 4 | nibbles[i<<1]
out[i&1 ? 11 : 10] += out[i]
return out

function getRandomImei() {
let imei = new Uint8Array(14).map(x=>(Math.random()*1000|0)%10),
revmap = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9],
oddsum = imei[0] + imei[2] + imei[4] + imei[6] + imei[8] + imei[10] + imei[12],
evensum = revmap[imei[1]] + revmap[imei[3]] + revmap[imei[5]] + revmap[imei[7]] + revmap[imei[9]] + revmap[imei[11]] + revmap[imei[13]],
luhn = 10 - (oddsum + evensum) % 10
return imei.join('') + (luhn > 9 ? 0 : luhn)

function getRandomImeiBlock() {
return IMEIblk(getRandomImei())

Of course, I’ll have to translate all this to another language when building the boot image but I just wanted to demonstrate that there’s nothing cryptic about this format. And there’ll probably be a nice Web-based tool for it as well.

That’s all for today. Now that we have the understanding which partitions to look at and what’s the IMEI file format in the NVRAM, let’s prepare for the actual dumping…