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://github.com/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" "$@"