Android Modules

There you are. You have your rooted Android device. But now, you need an additional kernel module. This is what happened to me. Thus here we go for the phones I do own, namely an Sony Xperia Z C6603 and a Samsung Galaxy S4 Active GT-I9295. First you need the proper toolchain from here. Then you need the proper kernel source for your device. In my case that is:

  • Sony Xperia Z C6603 Build 10.3.1.A.2.67: direct download
  • Samsung Galaxy S4 Active GT-I9295 Build JDQ39.I9295XXUBMK3: Go to the Samsung open source site and download the file: GT-I9295_SEA_JB_Opensource.zip

Note: The following is for Linux x86_64. Windows is not supported. I do not use it. Period.

From the downloaded file unpack the kernel source tree. Ignore the Samsung kernel build instructions, they are broken rubbish. I do assume, that the toolchain is located in arm-eabi-4.6 which is located in /home/geek.

Sony Xperia Z:
env ARCH=arm CROSS_COMPILE=/home/geek/arm-eabi-4.6/bin/arm-eabi- make fusion3_yuga_defconfig
env ARCH=arm CROSS_COMPILE=/home/geek/arm-eabi-4.6/bin/arm-eabi- make

Samsung Galaxy S4 Active:

Get a .config from the /proc/config.gz of your device.
env ARCH=arm CROSS_COMPILE=/home/geek/arm-eabi-4.6/bin/arm-eabi- TIMA_ENABLED=1 make

If you experience errors you may have to edit scripts/gcc-wrapper.py to enforce usage of Python 2.7.

Now you do have a kernel with modules that is compatible to the kernel of your device.

To modify the kernel configuration use:

env ARCH=arm CROSS_COMPILE=/home/geek/arm-eabi-4.6/bin/arm-eabi- make menuconfig

You can now build any module you wish as long as the actual kernel itself doesn't need to be recompiled for the module. You can check this very easily. Do the desired modifications to the kernel configuration and build the tree. If anything else than the build number or config.gz is modified that doesn't belong to the module itself you can't use the module. To see, what is a valid module that can be built, enable the TPROXY module.

On the Sony you are done. Copy the module(s) to the device and insmod there as root. Good.

On the Samsung we are in the opening stage of an opera orchestrated to discourage the ordinary developer. Insmod of your precious module will result in ENOEXEC as Samsung decided to only allow authenticated i.e. Samsung built modules to be inserted. This wouldn't be a problem if Samsung would offer all potentially required modules which they do not. Now, there's help on your way (inspired by this). Documented as a self serve service.

/home/geek/arm-eabi-4.6/bin/arm-eabi-objdump -d kernel/module.o | more

Search for copy_and_check.isra.22 - you will see something like:

00001f54 <copy_and_check.isra.22>:
    1f54:       e59f33d4        ldr     r3, [pc, #980]  ; 2330 <copy_and_check.isra.22+0x3dc>
    1f58:       e3520033        cmp     r2, #51 ; 0x33
    1f5c:       e92d4ff0        push    {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    1f60:       e24dd05c        sub     sp, sp, #92     ; 0x5c
    1f64:       e5933000        ldr     r3, [r3]
    1f68:       e1a04001        mov     r4, r1

A few lines further down you will fine the following lines:

    21d0:       e5da3147        ldrb    r3, [sl, #327]  ; 0x147
    21d4:       e1911c03        orrs    r1, r1, r3, lsl #24
    21d8:       1a000002        bne     21e8 <copy_and_check.isra.22+0x294>
    21dc:       e59f0184        ldr     r0, [pc, #388]  ; 2368 <copy_and_check.isra.22+0x414>
    21e0:       ebfffffe        bl      0 <printk>

The important thing which needs to be patched is the 'bne' statement which needs to be replaced by a 'nop'. This is as modifing the source as follows:

Original:

static int lkmauth(Elf_Ehdr *hdr, int len)
{
...
        /* parse result */
        if (krsp->ret == 0) {
                pr_warn("TIMA: lkmauth--verification succeeded.n");
                ret = 0; /* ret should already be 0 before the assignment. */
        } else {
...
}

Patched:
static int lkmauth(Elf_Ehdr *hdr, int len)
{
...
        /* parse result */
                pr_warn("TIMA: lkmauth--verification succeeded.n");
                ret = 0; /* ret should already be 0 before the assignment. */
        if(0) {
...
}

Thus, one needs to patch the address copy_and_check.isra.22+0x284 which contains 0x1a000002 to contain 0x0 which is a 'nop' instruction. So one needs to find the actual address of copy_and_check.isra.22 in the running kernel. First, we need some kind of helpful hints where to look. Search for copy_and_check.isra.22 in System.map and you will find:

c00b9504 t copy_and_check.isra.22

Look on the device in /proc/iomem where system RAM starts,  you will find:

80200000-87dfffff : System RAM

Let's calculate the address where copy_and_check.isra.22 should be located in system memory is we did the complete sources from Samsung:

0xc00b9504 - 0xc0000000 + 0x80200000 = 0x802b9504

Ok, let's check if the code is there as expected. Hold it, how? Fortunately /dev/mem comes to our rescure and there is a simple tool around to read from and to write to this device. Thus on the Galaxy S4 Active, we do need to read the memory from 0x802b9504 and compare the byte sequence to the above objdump byte sequence. And? No match! Reason: Samsung seemingly applies patches to the kernel source and doesn't include them in the downloadable version of the kernel source code. Not really GPL compliant as far as I can see. Still, patches tend to enlarge the kernel, thus we do have to read some more bytes of memory until we get a match:

root@android:/ # /data/opt/devmem2 0x802b95b8 w
/dev/mem opened.
Memory mapped at address 0x4033c000.
Value at address 0x802B95B8 (0x4033c5b8): 0xE59F33D4
root@android:/ # /data/opt/devmem2 0x802b95bc w
/dev/mem opened.
Memory mapped at address 0x402ea000.
Value at address 0x802B95BC (0x402ea5bc): 0xE3520033
root@android:/ # /data/opt/devmem2 0x802b95c0 w
/dev/mem opened.
Memory mapped at address 0x4026f000.
Value at address 0x802B95C0 (0x4026f5c0): 0xE92D4FF0
root@android:/ # /data/opt/devmem2 0x802b95c4 w
/dev/mem opened.
Memory mapped at address 0x401b2000.
Value at address 0x802B95C4 (0x401b25c4): 0xE24DD05C

Thus we have a difference of 0xb4 between the expected and the actual address. So copy_and_check.isra.22+0x284 is actually:

0x802b95b8 + 0x284 = 0x802b983c

Let's verify if we find the expected value 0x1A000002 at this location:

root@android:/ # /data/opt/devmem2 0x802b983c w
/dev/mem opened.
Memory mapped at address 0x40239000.
Value at address 0x802B983C (0x4023983c): 0x1A000002

Gotcha. Patching the running kernel is now easy:

/data/opt/devmem2 0x802b983c w 0x0

And, well, now you can insmod all your home built modules. You should however, after doing the insmod, restore the old value of 0x1A000002 to pretend security (well, everybody can read the instructions here and sufficently able people can figure out themselves).

If you just need the prebuilt TPROXY modules for the above phones, a kernel config or a precompiled devmem2 tool to try to brick your phone by poking around memory and hardware you can find all this in the downloads section.

If you don't understand any of the above, ask your friendly next door hacker, not me. I will not give any support. And: don't use what you don't understand. If you brick your device that's your fault, not mine.