Firstly, we should know about our stupid device:
Fig.1 Get information from device
Secondly, we could compile an exploit program. I used timwr's code cause it's simple enough. We simply need only toolchains provided by Google, e.g. I used android-ndk-r13b. We don't need SDK cause we already know the cpu abi and sdk version. After slightly changing the Makefile and the PATH env by export PATH=/home/march/android-ndk-r13b/build:$PATH we just run make build.
Fig.2 Makefile modification
Fig.3 Build our exploit program
We use adb push to transfer our files to the device.
Fig.4 Adb push
Actually, we don't have to use cross-compile toolchains provide by Google. Standalone arm-linux-gnueabihf-gcc are also capable of producing target program, like su, with which, for example, /system/bin/run-as is substituted. However, there's no gnu c lib in Android system, so you have to statically compile, which results in huge file size and you cannot use such huge file to overwrite the poor dummy program in /system/bin.
Now we come to the climax. After chmod 755 dirtycow making dirtycow executable, we run ./dirtycow ./run-as /system/bin/run-as to exploit and substitute run-as.
Fig.5 Crazy exploit
Just in milliseconds, we rooted! Aha. Run run-as to get root privilege, and run id to verify.
So, we want to remount /system to read-write mode to do whatever evil we want.
Fig.6 Unable to remount
WHAT ??? I'm so-called root! A root who can't remount /system can't be root!!! So what happened? After digging the internet and asking my android-expert friend, I found out that such device manufacturers have functions like remount, mount and write to mmcblk0p0 forbidden in the kernel scope! No way!
Fig.7 Unable to write to mmcblk0p27
What interesting is, I found that mmcblk0 self is writable. By the way, I have to mention, chmod 777 /data/local/tmp would be really helpful.
Fig.8 Writable mmcblk0
An idea came to my mind. What if I copy the whole /system partition and mount it on my own computer and add su and all evil stuff to it and finally write it back to the device? Sounds reasonable.
First of all, we have to find way know the partition map of the device. In beginning, I was trying to find it out in somewhere in /etc and in boot.img. Nothing! I found nothing! It indicates that all the partition mapping stuff are done in the hard-coded linux kernel. No way again!
Thanks to the internet, pre-compiled parted can be easily found.
Fig.9 Partition map
Let's grep /system(Number 27 in Fig.9) ! Be careful with the following two commands. Once you messed up, especially the second one, your device becomes so-called nothing but a brick.
# change skip, seek and count according to your own device !!!
dd if=/dev/block/mmcblk0 of=/data/local/tmp/zzzz bs=1024 count=921600 skip=329264
dd of=/dev/block/mmcblk0 if=/data/local/tmp/zzzz bs=1024 count=921600 seek=329264
In which, bs=1024 stands for each unit is 1KiB sized. Skip is for input file stream, seek is for output file stream. What skip, seek and count stand for is self-evident. The first command will read the partition and write it to a temporary file and vice versa.
I'm not going deeper about how to put some file in this partition image. There're tons of articles telling you how to put su in /system correctly and set such 4755 attribute.
Fig.10 Mount and umount partition
You may transmit and receive the image file through adb:
Fig.11 Adb pull and push
Don't forget to reboot device after writing back /system!
Finally, we get a rooted device.
Fig.12 Rooted device
... and, one more thing:
Fig.13 Stupid device refuses to update cause it's rooted.