How a $30 Phone Caused Me a Headache & Write Protection Woes

The Setup

A few months ago while I was playing cards in my Physics class, my good friend named Quincy Jones (no relation) comes up to me and says: “Hey, I have a crappy old ZTE phone my grandma gave me, and I know that you like messing around with this kind of stuff. You want it?”

Heck yeah! Should be fun. Quick/Easy to root, then work on getting TWRP/CyanogenMod ported, etc. Right? No.

To begin, this phone runs ZTE’s (in my opinion horridly ugly) Android Jelly Bean 4.1.2. The model of this device is Z796C, which, after a quick google search, is called the ZTE Majesty, and is sold by Straight Talk Wireless (The carrier would later cause me multiple headaches, but we’ll get to that). Upon googling “ZTE Majesty Root” I was greeted by a SINGLE thread about the phone. No big surprise, it’s not a well sold device. The thread was about 8 pages of people complaining about how it hadn’t been rooted. They all said they had tried “every method”, which, at the time, I didn’t believe.

Initial Attempts

This phone runs Android 4.1.2, which means that, in theory, this device is vulnerable to hundreds of different local (and even some remote) code execution and privilege escalation exploits.

To begin, I tried SafeRoot (originally intended for 4.3), which seemed to succeed, but upon reboot, no root. Huh.

Onto attempt two, Cydia Impactor, which uses Master Key Bug, and although it seemed to work, upon reboot, no root. This should have keyed me off to the problem, but it didn’t.

Onto what should have been my go to for attempt one, TowelRoot. Downloaded the APK and installed, Bang. Root. Or so I thought.

After TowelRoot displayed its success message, I left the app and jumped over to SuperSU, which said that the SU Binary needed to be updated. Sure. I click “Yes”, and left to go for a run.

Got back about 30 minutes later, and it still displayed the “Installing…” prompt! I closed the app, and plugged it into my Surface Pro 3, and pulled up an ADB Shell.

shell@android$

Wow. That’s a painfully generic codename.

I then ran su which returned: /system/bin/sh: su: not found

Huh? I thought I had root? Maybe I was wrong. Reran TowelRoot, and it rebooted, which is TowelRoot’s way of telling you you aren’t vulnerable/it failed. At this point I knew something weird was afoot.

I then rebooted the device. Pulled up TowelRoot, and ran it. It reported success. Popped open SuperSU and decided to not update the binary, and just use the one that TowelRoot installs. Seemed like everything was fine. I opened that same ADB shell and ran su. To which I was greeted with an SuperSU prompt, to which I agreed. Boom.

root@android:/ #

Wow. That’s still a painfully generic hostname.

Success, now onto research

I started surfing around to get a lay of the land.

root@android:/ # cat /proc/partitions returns the following

root@android:/ # ls -al /dev/block/platform/msm_*/by-name

Returns: /dev/block/platform/msm_*/by-name: No such file or directory

What? No “by-name” symlink on an Android Jelly Bean era device? That sucks.

root@android:/ # cat /proc/mtd Returns: dev: size erasesize name

Ugh. No partition listing, this gets even more fun.

I tried a few more common methods that I won’t waste time outlining, all you need to know is that none of them worked.

Next plan of action for me would normally be to examine the recovery.img and get an fstab, which displays all of a devices mount points. Bad news… after a search, there are no fastboot images for this device! No problem, I’ll just dump the recovery.img from fastboot. Here we go:

PS C:\Users\Nolen> adb reboot bootloader

I then waited, the ZTE splash screen came up, and then it came up with the Android Boot Logo! What the Heck? I then found out from a quick google search that all Straight Talk phones have fastboot disabled. This particular phone also lacks a “Download Mode” to replace fastboot like what LG does with their LAF mode. Wow. This not only prevents disaster recovery, but just made a seemingly easy job much, much harder.

Where to go from here? Not sure honestly. So, I set to work researching it. Couldn’t really find anything relating to the topic.

About 30 minutes into brainstorming, the device randomly rebooted.

Regression into madness

When it rebooted, I got back on an ADB shell:

shell@android$ su

Returned: /system/bin/sh: su: not found

This means war.

What?! We had Root! Ugh. What’s going on?!

For those who haven’t figured it out yet, it was now apparent that not only the phone has write protection on the system partition. I’ll need to disable this to do anything meaningful.

But, in the meantime I can attain temporary-root via TowelRoot, so I began brainstorming how to get a partition map again.

Then it hit me, recovery knows how to mount the partitions! So, I need to get it to mount all the partition in recovery… Factory Reset!

root@android:/ # reboot recovery

Then, from recovery, I initiated a Factory Data Reset, and after it completed, I reboot to system.

root@android:/ # cat /cache/recovery/last_log returns the following

Yay! A partition map!

Sidestepping write-protection

Now to use an old trick found by Justin Case (@Jcase) to temporarily remove write protection.

We write the boot partition to the recovery partition, and then reboot to recovery, because write protection is disabled when the boot-reason is recovery or any of it’s related boot-modes, as recovery needs to be able to write to system on old file-based OTA devices.

First, we back up our boot/recovery partitions: root@android:/# dd if= /dev/block/mmcblk0p8 of=/sdcard/boot.img

root@android:/# dd if= /dev/block/mmcblk0p16 of=/sdcard/recovery.img

Now we write the contents of the boot partition to the recovery partition root@android:/# dd if= /dev/block/mmcblk0p8 of=/dev/block/mmcblk0p16

Here we go! crosses fingers PS C:\Users\Nolen> adb reboot recovery

Upon reboot, it seems completely normal. All data is intact, and system is booted successfully as expected, now to test protection. To do so, we re-run TowelRoot, then ADB Shell: root@android:/# mount –o remount,rw /system

Returns: mount –o remount,rw /system

Success! We have RW access to /system!

Now onto permanent-root. Just open up the SuperSU app from the Play Store and it will ask to Update the SU Binary, select yes, and wait. About 30 seconds later, it displayed the “Success! It is recommended you reboot now.” Message, I then went in and converted SuperSU to a /system app. Then I rebooted to the normal boot image.

Accidentally winning

I expected to have root access, but to be unable to remount /system due to write protection.

However, upon reboot: shell@android$s

root@android:/# mount –o remount,rw /system

Returns: mount –o remount,rw /system

What? How are we still able to remount system RW? To make sure I wasn’t still booted to the recovery partition, I ran: root@android:/# cat /proc/cmdline | grep bootmode

Returns: androidboot.bootreason=reboot

This implies that we’re booted from the actual boot partition, and not recovery, which is what we expected.

Well… Now I am really confused… but I can live with it! We defeated ZTE Write protection permanently! Even if by accident.

I released a one-click method to follow this procedure over on XDA forums so that others can enjoy root on their Majesty, you can find it here.

What now?

Well, I intended to work on a bootloader unlock method for this device, and then attempt to port CyanogenMod. Unfortunately fate was not on my side, and the device slipped from my pocked during a football game, down into the ether below the bleachers, never to be seen again.

Maybe we’ll cross paths again someday, but for now, goodnight, sweet prince.

Written on May 23, 2015