U+E000 私用領域

しがない緑茶好きのメモ的なの。

boot.imgから任意のシンボルのアドレスを発掘する

去年暮れから書き始めた国産スマホ周りの延長的なやつです。
URBANO V01(KYV31)をrootできなかった言い訳も含んでます。
今回はboot.imgからカーネル本体を引っ張り出して、ほしいシンボルのアドレスを発掘する話です。
少しだけarmアセンブリ要素もあります。

なぜそんなことするの?

前回前々回の記事を読んでもらえばわかりますが、国産スマホでroot権限を奪取したりカーネルを書き換えるには、いくつかのシンボルのアドレスが必要になります。
しかし今回実際にアドレスを発掘するURBANO V01(KYV31)だと、get_essential_address(詳しくは過去記事を参照)が使えません。

$ ./get_essential_address                          


Device detected: KYV31 (103.0.2e00)

Try without fb_mem_exploit fist...

Try to find address in memory...
Attempt msm_cameraconfig exploit...
Detected kernel physical address at 0x00008000 from iomem

You need to manage to get remap_pfn_range address.

Try copying kernel memory... It will take a long time.
Attempt pingpong exploit...
Attempt futex exploit...
failed to exploit...
Attempt get_user exploit...
error in setsockopt().
Failed to get prepare_kernel_cred address.
Failed to get commit_creds address.
Failed to get remap_pfn_range address.
Failed to get vmalloc_exec address.
Failed to get ptmx_fops address.
connect(): failed
Attempt get_user exploit...
error in setsockopt().
Failed to get prepare_kernel_cred address.
Failed to get commit_creds address.
Failed to get remap_pfn_range address.
Failed to get vmalloc_exec address.
Failed to get ptmx_fops address.
KYV31 (103.0.2e00) is not supported.


Try again with fb_mem_exploit...

KYV31 (103.0.2e00) is not supported.


Try again with fb_mem_exploit...

Try to find address in memory...
Attempt msm_cameraconfig exploit...
Detected kernel physical address at 0x00008000 from iomem

Attempt fb_mem exploit...
Detected kernel physical address at 0x00008000 from iomem
Failed to open /dev/graphics/fb0 due to Permission denied
You need to manage to get remap_pfn_range address.

Try copying kernel memory... It will take a long time.
Attempt pingpong exploit...
Attempt futex exploit...
connect(): failed
Attempt get_user exploit...
error in setsockopt().
Failed to get prepare_kernel_cred address.
Failed to get commit_creds address.
Failed to get remap_pfn_range address.
Failed to get vmalloc_exec address.
Failed to get ptmx_fops address.
KYV31 (103.0.2e00) is not supported.
Failed to setup variables.
Try to find address in memory...
Attempt msm_cameraconfig exploit...
Detected kernel physical address at 0x00008000 from iomem

Attempt fb_mem exploit...
Detected kernel physical address at 0x00008000 from iomem
Failed to open /dev/graphics/fb0 due to Permission denied
You need to manage to get remap_pfn_range address.

Try copying kernel memory... It will take a long time.
Attempt pingpong exploit...
Attempt futex exploit...
connect(): failed
Attempt get_user exploit...
error in setsockopt().
Failed to get prepare_kernel_cred address.
Failed to get commit_creds address.
Failed to get remap_pfn_range address.
Failed to get vmalloc_exec address.
Failed to get ptmx_fops address.
KYV31 (103.0.2e00) is not supported.
Failed to setup variables.

アドレスを取る時に使用していた脆弱性郡が塞がれてしまっているからです。
なので、今回はboot.imgを取り出した後、母艦PCからアドレスを出して、脆弱性を使えるようにしようという考えです。
今回は試しにptmx_fopsのアドレスを発掘してみます。

ptmx_fopsとは

staticな変数の構造体です。
すごく簡単にいってしまうと、ここを抑えてしまえば任意の関数をカーネル権限で実行できてしまいます。
"なんかカーネル権限であれこれできちゃうやべーやつ"みたいな認識です。
この記事を読む分にはその程度で構いませんが、このやべーやつの正体をもっと深く知りたい方は、ももいろテクノロジー様が詳しく解説していますのでリンクを貼っておきます。

inaz2.hatenablog.com
非常に面白く、わかりやすい記事なのでぜひご一読を。

boot.imgを取ってくる

兎にも角にも、boot領域のイメージがないと始まりません。
方法としては、

  • メーカーのサイトからアップデート用データ落として取り出す
  • root権限奪取して、ddで取り出す

辺りがあると思いますが、KYV31はオンラインでのアップデートのみでアップデート用のデータとかが公開されてないので、今回はroot奪取する方法で行きたいと思います。
ちなみに今回使ってるKYV31ですが、ビルド番号は103.0.2e00です。
これ以前のやつは前回とかの方法でroot奪取、LSM解除まで簡単にいけます。
(とあるベトナムの方のKYV31、ビル番102で確認済み)
しかし103以降のものだと、run_root_shellとかでのroot奪取はできません。
なので、あの有名なDirtyCowくんを使ってrootを取ります。

rarのパスワードは"nox"だそうです。(XDAフォーラム参照)
解答して出てきたファイルをいつもの/data/local/tmpにpushして実行します。

$ ls
busybox  exploit.sh  libsupol.so  patch-init  readelf  run-as-dirtycow  run-as-dirtycow64  su.img  supolicy
$ adb push * /data/local/tmp
busybox: 1 file pushed. 2.6 MB/s (1815252 bytes in 0.654s)
exploit.sh: 1 file pushed. 0.6 MB/s (10397 bytes in 0.016s)
libsupol.so: 1 file pushed. 2.2 MB/s (203236 bytes in 0.090s)
patch-init: 1 file pushed. 1.2 MB/s (11584 bytes in 0.009s)
readelf: 1 file pushed. 2.5 MB/s (683324 bytes in 0.258s)
run-as-dirtycow: 1 file pushed. 2.7 MB/s (11448 bytes in 0.004s)
run-as-dirtycow64: 1 file pushed. 0.8 MB/s (10000 bytes in 0.011s)
su.img: 1 file pushed. 4.3 MB/s (5242880 bytes in 1.167s)
supolicy: 1 file pushed. 1.9 MB/s (38308 bytes in 0.019s)
9 files pushed. 3.4 MB/s (8026429 bytes in 2.234s)
shell@KYV31:/data/local/tmp $ chmod 755 *
shell@KYV31:/data/local/tmp $ ./exploit.sh                                     

              (      )
              ~(^^^^)~
               ) @@ \~_          |\
              /     | \        \~ /  CVE-2016-5195
             ( 0  0  ) \        | |   Lollipop (32bits)
              ---___/~  \       | |   SeLinux bye
               /'__/ |   ~-_____/ |
o          _   ~----~      ___---~
  O       //     |         |
         ((~\  _|         -|
   o  O //-_ \/ |        ~  |
        ^   \_ /         ~  |
               |          ~ |
               |     /     ~ |
               |     (       |
                \     \      /\
               / -_____-\   \ ~~-*
               |  /       \  \
               / /         / /
             /~  |       /~  |
             ~~~~        ~~~~

# Device:KYV31_jp_kdi

-Getting uid 0->Ok.
-Checking permissive run-as.->No
-Dump policy->Ok
-Dump init

Error searching shellcode addr, already patched?

なぜかうまくいきません。
カーネルのバージョン的にも有効なはずなんですが...
一応、解決策はありますが...非常に屈辱的です。
その方法というのがKingRootを使うというものです。ええ、あのKingRootです。
あの怪しくて何をしてるのかわからん上に余計なアプリぶち込んできたり、勝手にロック画面を乗っ取るあのKingRootです。
あのアプリを実行してもKYV31はroot化されません(KingRootはLSM解除非対応)
しかし、実行してしばらくすると何故かSELinuxが少しの間Permissiveになるんです。
そのすきにDirtyCow動かすとroot権限が奪い取れます。
他のDirtyCow使ってるexploitを使ってみても/data/local/tmpすら覗けないなんちゃってroot権限になりますし、こうするしかなかったんです...
DirtyCowはSELinuxがEnforcingでも動くのがウリなのに、何やってんだって感じですよ...
えー、本題はboot.imgからシンボルのアドレスを取ることなので、自虐的なナニカはこの辺にしてboot.imgを取っていきます。

shell@KYV31:/ $ cd /data/local/tmp
shell@KYV31:/data/local/tmp $ getenforce                                       
Permissive
shell@KYV31:/data/local/tmp $ ./exploit.sh                                     
              (      )
              ~(^^^^)~
               ) @@ \~_          |\
              /     | \        \~ /  CVE-2016-5195
             ( 0  0  ) \        | |   Lollipop (32bits)
              ---___/~  \       | |   SeLinux bye
               /'__/ |   ~-_____/ |
o          _   ~----~      ___---~
  O       //     |         |
         ((~\  _|         -|
   o  O //-_ \/ |        ~  |
        ^   \_ /         ~  |
               |          ~ |
               |     /     ~ |
               |     (       |
                \     \      /\
               / -_____-\   \ ~~-*
               |  /       \  \
               / /         / /
             /~  |       /~  |
             ~~~~        ~~~~

# Device:KYV31_jp_kdi

-Getting uid 0->Ok.
-Checking permissive run-as.->Ok
# turn off/on the bluetooth...
root@KYV31:/data/local/tmp # 
root@KYV31:/data/local/tmp # id
uid=0(root) gid=0(root) context=u:r:init:s0

KingRoot動かしたらgetenforceしまくって、謎Permissiveになったらexploit。
技術者の端くれとして非常に屈辱的です。
とりあえずrootは取れたので、bootのイメージをとります。

# ls -l /dev/block/platform/msm_sdcc.1/by-name | grep boot
lrwxrwxrwx root     root              1970-01-22 12:27 aboot -> /dev/block/mmcblk0p5
lrwxrwxrwx root     root              1970-01-22 12:27 abootbk -> /dev/block/mmcblk0p11
lrwxrwxrwx root     root              1970-01-22 12:27 boot -> /dev/block/mmcblk0p14
lrwxrwxrwx root     root              1970-01-22 12:27 bootwork -> /dev/block/mmcblk0p27
# dd if=/dev/block/mmcblk0p14 of=boot.img         
34816+0 records in
34816+0 records out
17825792 bytes transferred in 0.730 secs (24418893 bytes/sec)

無事にとれました。母艦に移します。

$ adb pull /data/local/tmp/boot.img
/data/local/tmp/boot.img: 1 file pu...3.9 MB/s (17825792 bytes in 4.409s)

なんか思ったより長くなりましたが、これで下準備完了です。

カーネル本体を取り出す

boot.imgは取れたわけですが、今回必要なのはboot領域すべてではなくkernelのみです。
ramdiskとかに用はないので、bootイメージからカーネル部のみを取り出します。
boot.imgの分解はsplit_bootとかmkbootimgとかでできるそうですが、入れるのが面倒そうなので、binwalkで取り出します。
binwalkっていうのは...まあ見たほうが早いです。

$ binwalk boot.img

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Android bootimg, kernel size: 6426600 bytes, kernel addr: 0x8000, ramdisk size: 650124 bytes, ramdisk addr: 0x1000000, product name: ""
2048          0x800           Linux kernel ARM boot executable zImage (little-endian)
18255         0x474F          gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
6428672       0x621800        gzip compressed data, from Unix, last modified: 1970-01-01 00:00:00 (null date)
7079936       0x6C0800        Qualcomm device tree container, version: 2, DTB entries: 105
7084032       0x6C1800        device tree image (dtb)
7280640       0x6F1800        device tree image (dtb)
7479296       0x722000        device tree image (dtb)
7677952       0x752800        device tree image (dtb)
7872512       0x782000        device tree image (dtb)
8069120       0x7B2000        device tree image (dtb)
8265728       0x7E2000        device tree image (dtb)
8460288       0x811800        device tree image (dtb)
8656896       0x841800        device tree image (dtb)
8853504       0x871800        device tree image (dtb)
9050112       0x8A1800        device tree image (dtb)
9246720       0x8D1800        device tree image (dtb)
9443328       0x901800        device tree image (dtb)
9629696       0x92F000        device tree image (dtb)
9816064       0x95C800        device tree image (dtb)
10012672      0x98C800        device tree image (dtb)
10209280      0x9BC800        device tree image (dtb)
10405888      0x9EC800        device tree image (dtb)
10602496      0xA1C800        device tree image (dtb)
10797056      0xA4C000        device tree image (dtb)
10991616      0xA7B800        device tree image (dtb)
11204608      0xAAF800        device tree image (dtb)
11417600      0xAE3800        device tree image (dtb)
11646976      0xB1B800        device tree image (dtb)
11859968      0xB4F800        device tree image (dtb)
11886592      0xB56000        device tree image (dtb)
12101632      0xB8A800        device tree image (dtb)
12312576      0xBBE000        device tree image (dtb)
12525568      0xBF2000        device tree image (dtb)
12738560      0xC26000        device tree image (dtb)

なんかdtbが多いですが出ました。
binwalkは、ファイル内に埋もれてるファイルを表示してくれます。

github.com

Ubuntuだったらapt install binwalkでいけます。
gzipが2つありますが、上がカーネル本体、下がramdiskです。
ちなみに、binwalkは-eオプションで検出したファイルを取り出してくれます。

$ binwalk -e boot.img 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
(省略)
$ ls
_boot.img.extracted  boot.img  default.prop
$ cd _boot.img.extracted/ && ls
474F  621800
$ file *
474F:   data
621800: ASCII cpio archive (SVR4 with no CRC)

474Fがカーネル、621800がramdiskです。
カーネルをリネームしてわかりやすい場所においておきます。

アドレスを引っ張り出す

ようやっと本題です。
アドレスを引っ張りだす方法ですが、またしてもfi01氏制作のツールを使用させていただきます。

github.com

これをいつもどおりgit cloneします。

$ git clone https://github.com/fi01/kallsymsprint
Cloning into 'kallsymsprint'...
remote: Enumerating objects: 68, done.
remote: Total 68 (delta 0), reused 0 (delta 0), pack-reused 68
Unpacking objects: 100% (68/68), done.
$ cd kallsymsprint/
$ ls
Android.mk  Application.mk  README.md  kallsymsprint  kallsymsprint.arm64  kallsymsprint.x64  kallsymsprint.x86  libkallsyms  main.c

すでにコンパイル済みのものが置かれているので、ありがたく使用させていただきます。
使い方は、引数にカーネル本体へのパスを渡せばOKです。

$ ./kallsymsprint.x86 ../kernel.dump > kallsyms_kyv31.txt
[+]mmap
  mem=f6cf0000 length=0106fd04 offset=c9318000
[+]kallsyms_addresses=c0aac2b0
  count=00011316
[+]kallsyms_num_syms=00011316
[+]kallsyms_names=c0af0f20
[+]kallsyms_markers=c0bb9ac0
[+]kallsyms_token_table=c0bb9f10
[+]kallsyms_token_index=c0bba2b0
[+]kallsyms_lookup_name
$ head kallsyms_kyv31.txt
c0100000 asm_do_IRQ
c0100000 _stext
c0100000 __exception_text_start
c0100004 do_undefinstr
c010022c do_IPI
c0100230 do_DataAbort
c01003dc do_PrefetchAbort
c0100474 gic_handle_irq
c0100580 __do_fixup_smp_on_up
c0100580 __exception_text_end

とれましたね。
最初の方で述べた通り、今回必要なのはptmx_fopsのアドレスです。grepで探してみましょう。

$ cat kallsyms_kyv31.txt | grep ptmx_fops
$

ないです。
しかし隠してあるだけで実際には存在しています。
というわけで前回同様ディスアセンブルをして、ptmx_fopsを探していきます。

ptmx_fopsを探し出す

さて、どうやって見つけるんだって話ですが、ptmx_fopsを使用している関数から見つけます。
例えばカーネルの関数unix98_pty_initのソースは以下のようになっています。

unix98_pty_init()
  {
    (省略)
    /* Now create the /dev/ptmx special device */
    tty_default_fops(&ptmx_fops);
    ptmx_fops.open = ptmx_open;

    cdev_init(&ptmx_cdev, &ptmx_fops);
    (省略)
  }

なので、この関数をディスアセンブルすればptmx_fopsのアドレスがわかるはず...です。
ディスアセンブルには、前回からお世話になっているarm7-dasmを使用します。

github.com

これをgit clone、コンパイルして使用します。

$ git clone https://github.com/fi01/arm7-dasm
Cloning into 'arm7-dasm'...
remote: Enumerating objects: 71, done.
remote: Total 71 (delta 0), reused 0 (delta 0), pack-reused 71
Unpacking objects: 100% (71/71), done.
$ cd arm7-dasm/
$ ls
README.md  arm7-dasm.c  arm7core.h  arm7dasm.c  emu.h
$ gcc -o arm7-dasm arm7-dasm.c

ディスアセンブルの方法はREADMEに載ってます。

Disassemble with symbol table:  
$ ./arm7-dasm [kernel image filename] [image base address] [start address or symbol name] [symbol table file]  

早速ディスアセンブルしてみます。

$ ./arm7-dasm kernel.dump c0008000 pty_init kallsyms_kyv31.txt > pty_init.dasm
70271 symbols are loaded.
$ head pty_init.dasm 
Disassemble 0xc0e1e86c - 0xc0e1ebb0
c0e1e86c:             <pty_init>
c0e1e86c: e9 2d 4f f0     STMPW   [SP], { R4-R11, LR }
c0e1e870: e2 4d d0 14     SUB     SP, SP, #$14
c0e1e874: e5 9f 53 38     LDR     R5, =$c0fc0544 [$c0e1ebb4]
c0e1e878: e5 95 00 00     LDR     R0, [R5]
c0e1e87c: e3 50 00 00     CMPS    R0, #$0
c0e1e880: da 00 00 52     BLE     $c0e1e9d0
c0e1e884: e3 a0 10 00     MOV     R1, #$0
c0e1e888: eb d6 d9 94     BL      $c03d4ee0 <__alloc_tty_driver>

無事にディスアセンブルできたみたいです。
以下、ディスアセンブル結果

Disassemble 0xc0e1e86c - 0xc0e1ebb0
c0e1e86c:             <pty_init>
c0e1e86c: e9 2d 4f f0     STMPW   [SP], { R4-R11, LR }
c0e1e870: e2 4d d0 14     SUB     SP, SP, #$14
c0e1e874: e5 9f 53 38     LDR     R5, =$c0fc0544 [$c0e1ebb4]
c0e1e878: e5 95 00 00     LDR     R0, [R5]
c0e1e87c: e3 50 00 00     CMPS    R0, #$0
c0e1e880: da 00 00 52     BLE     $c0e1e9d0
c0e1e884: e3 a0 10 00     MOV     R1, #$0
c0e1e888: eb d6 d9 94     BL      $c03d4ee0 <__alloc_tty_driver>
c0e1e88c: e2 50 40 00     SUBS    R4, R0, #$0
c0e1e890: 05 9f 03 20     LDREQ   R0, =$c0c22160 [$c0e1ebb8]
c0e1e894: 0a 00 00 05     BEQ     $c0e1e8b0
c0e1e898: e5 95 00 00     LDR     R0, [R5]
c0e1e89c: e3 a0 10 00     MOV     R1, #$0
c0e1e8a0: eb d6 d9 8e     BL      $c03d4ee0 <__alloc_tty_driver>
c0e1e8a4: e2 50 60 00     SUBS    R6, R0, #$0
c0e1e8a8: 1a 00 00 01     BNE     $c0e1e8b4
c0e1e8ac: e5 9f 03 08     LDR     R0, =$c0c2217d [$c0e1ebbc]
c0e1e8b0:                                             ; from c0e1e894
c0e1e8b0:                                             ;      c0e1e9b8
c0e1e8b0:                                             ;      c0e1e9cc
c0e1e8b0:                                             ;      c0e1e9ec
c0e1e8b0:                                             ;      c0e1ea0c
c0e1e8b0:                                             ;      c0e1eb1c
c0e1e8b0:                                             ;      c0e1eb30
c0e1e8b0:                                             ;      c0e1eb6c
c0e1e8b0: eb ec 9d 77     BL      $c0945e94 <panic>
c0e1e8b4:                                             ; from c0e1e8a8
c0e1e8b4: e5 9f 33 04     LDR     R3, =$c0c221a0 [$c0e1ebc0]
c0e1e8b8: e3 a0 70 00     MOV     R7, #$0
c0e1e8bc: e3 a0 c0 04     MOV     R12, #$4
c0e1e8c0: e5 9f 52 fc     LDR     R5, =$c0fc0484 [$c0e1ebc4]
c0e1e8c4: e3 a0 b0 02     MOV     R11, #$2
c0e1e8c8: e2 84 e0 64     ADD     LR, R4, #$64
c0e1e8cc: e1 c4 c6 b0     STRH    R12, [R4,#$60]
c0e1e8d0: e3 a0 8c 96     MOV     R8, #$9600
c0e1e8d4: e3 a0 90 bf     MOV     R9, #$bf
c0e1e8d8: e5 84 b0 54     STR     R11, [R4, #$54]
c0e1e8dc: e3 a0 a0 06     MOV     R10, #$6
c0e1e8e0: e5 84 30 48     STR     R3, [R4, #$48]
c0e1e8e4: e5 9f 32 dc     LDR     R3, =$c0cb3542 [$c0e1ebc8]
c0e1e8e8: e5 84 70 58     STR     R7, [R4, #$58]
c0e1e8ec: e5 84 30 4c     STR     R3, [R4, #$4c]
c0e1e8f0: e3 a0 30 01     MOV     R3, #$1
c0e1e8f4: e1 c4 36 b2     STRH    R3, [R4,#$62]
c0e1e8f8: e8 b5 00 0f     LDMUW   [R5], { R0-R3 }
c0e1e8fc: e8 ae 00 0f     STMUW   [LR], { R0-R3 }
c0e1e900: e8 b5 00 0f     LDMUW   [R5], { R0-R3 }
c0e1e904: e8 ae 00 0f     STMUW   [LR], { R0-R3 }
c0e1e908: e8 95 00 07     LDMU    [R5], { R0-R2 }
c0e1e90c: e8 8e 00 07     STMU    [LR], { R0-R2 }
c0e1e910: e1 a0 00 04     MOV     R0, R4 
c0e1e914: e5 9f 12 b0     LDR     R1, =$c0a39a34 <master_pty_ops_bsd> [$c0e1ebcc]
c0e1e918: e5 84 70 64     STR     R7, [R4, #$64]
c0e1e91c: e5 84 70 68     STR     R7, [R4, #$68]
c0e1e920: e5 84 90 6c     STR     R9, [R4, #$6c]
c0e1e924: e5 84 70 70     STR     R7, [R4, #$70]
c0e1e928: e5 84 80 88     STR     R8, [R4, #$88]
c0e1e92c: e5 84 80 8c     STR     R8, [R4, #$8c]
c0e1e930: e5 84 a0 90     STR     R10, [R4, #$90]
c0e1e934: e5 84 60 98     STR     R6, [R4, #$98]
c0e1e938: e5 8d c0 0c     STR     R12, [SP, #$c]
c0e1e93c: eb d6 d8 77     BL      $c03d4b20 <tty_set_operations>
c0e1e940: e5 9f 32 88     LDR     R3, =$c0c221ab [$c0e1ebd0]
c0e1e944: e5 86 70 58     STR     R7, [R6, #$58]
c0e1e948: e2 45 e0 20     SUB     LR, R5, #$20
c0e1e94c: e5 86 30 48     STR     R3, [R6, #$48]
c0e1e950: e5 9f 32 7c     LDR     R3, =$c0c221b5 [$c0e1ebd4]
c0e1e954: e5 86 30 4c     STR     R3, [R6, #$4c]
c0e1e958: e3 a0 30 03     MOV     R3, #$3
c0e1e95c: e5 86 30 54     STR     R3, [R6, #$54]
c0e1e960: e5 9d c0 0c     LDR     R12, [SP, #$c]
c0e1e964: e1 c6 b6 b2     STRH    R11, [R6,#$62]
c0e1e968: e8 be 00 0f     LDMUW   [LR], { R0-R3 }
c0e1e96c: e1 c6 c6 b0     STRH    R12, [R6,#$60]
c0e1e970: e2 86 c0 64     ADD     R12, R6, #$64
c0e1e974: e8 ac 00 0f     STMUW   [R12], { R0-R3 }
c0e1e978: e8 be 00 0f     LDMUW   [LR], { R0-R3 }
c0e1e97c: e8 ac 00 0f     STMUW   [R12], { R0-R3 }
c0e1e980: e8 95 00 07     LDMU    [R5], { R0-R2 }
c0e1e984: e8 8c 00 07     STMU    [R12], { R0-R2 }
c0e1e988: e1 a0 00 06     MOV     R0, R6 
c0e1e98c: e5 9f 12 44     LDR     R1, =$c0a39ab0 <slave_pty_ops_bsd> [$c0e1ebd8]
c0e1e990: e5 86 90 6c     STR     R9, [R6, #$6c]
c0e1e994: e5 86 80 88     STR     R8, [R6, #$88]
c0e1e998: e5 86 80 8c     STR     R8, [R6, #$8c]
c0e1e99c: e5 86 a0 90     STR     R10, [R6, #$90]
c0e1e9a0: e5 86 40 98     STR     R4, [R6, #$98]
c0e1e9a4: eb d6 d8 5d     BL      $c03d4b20 <tty_set_operations>
c0e1e9a8: e1 a0 00 04     MOV     R0, R4 
c0e1e9ac: eb d6 d9 81     BL      $c03d4fb8 <tty_register_driver>
c0e1e9b0: e1 50 00 07     CMPS    R0, R7 
c0e1e9b4: 15 9f 02 20     LDRNE   R0, =$c0c221ba [$c0e1ebdc]
c0e1e9b8: 1a ff ff bc     BNE     $c0e1e8b0
c0e1e9bc: e1 a0 00 06     MOV     R0, R6 
c0e1e9c0: eb d6 d9 7c     BL      $c03d4fb8 <tty_register_driver>
c0e1e9c4: e3 50 00 00     CMPS    R0, #$0
c0e1e9c8: 15 9f 02 10     LDRNE   R0, =$c0c221d7 [$c0e1ebe0]
c0e1e9cc: 1a ff ff b7     BNE     $c0e1e8b0
c0e1e9d0:                                             ; from c0e1e880
c0e1e9d0: e3 a0 06 01     MOV     R0, #$100000
c0e1e9d4: e3 a0 10 00     MOV     R1, #$0
c0e1e9d8: e5 9f 52 04     LDR     R5, =$c1175a70 [$c0e1ebe4]
c0e1e9dc: eb d6 d9 3f     BL      $c03d4ee0 <__alloc_tty_driver>
c0e1e9e0: e3 50 00 00     CMPS    R0, #$0
c0e1e9e4: e5 85 00 00     STR     R0, [R5]
c0e1e9e8: 05 9f 01 f8     LDREQ   R0, =$c0c221fa [$c0e1ebe8]
c0e1e9ec: 0a ff ff af     BEQ     $c0e1e8b0
c0e1e9f0: e3 a0 06 01     MOV     R0, #$100000
c0e1e9f4: e3 a0 10 00     MOV     R1, #$0
c0e1e9f8: eb d6 d9 38     BL      $c03d4ee0 <__alloc_tty_driver>
c0e1e9fc: e3 50 00 00     CMPS    R0, #$0
c0e1ea00: e1 a0 e0 00     MOV     LR, R0 
c0e1ea04: e5 85 00 04     STR     R0, [R5, #$4]
c0e1ea08: 05 9f 01 dc     LDREQ   R0, =$c0c2221e [$c0e1ebec]
c0e1ea0c: 0a ff ff a7     BEQ     $c0e1e8b0
c0e1ea10: e5 95 c0 00     LDR     R12, [R5]
c0e1ea14: e3 a0 60 00     MOV     R6, #$0
c0e1ea18: e3 a0 b0 04     MOV     R11, #$4
c0e1ea1c: e5 9f 31 9c     LDR     R3, =$c0c221a0 [$c0e1ebc0]
c0e1ea20: e3 a0 80 01     MOV     R8, #$1
c0e1ea24: e3 a0 90 bf     MOV     R9, #$bf
c0e1ea28: e5 9f 41 94     LDR     R4, =$c0fc0484 [$c0e1ebc4]
c0e1ea2c: e3 a0 a0 1e     MOV     R10, #$1e
c0e1ea30: e2 8c 70 64     ADD     R7, R12, #$64
c0e1ea34: e5 8c 60 58     STR     R6, [R12, #$58]
c0e1ea38: e5 8c 30 48     STR     R3, [R12, #$48]
c0e1ea3c: e5 9f 31 ac     LDR     R3, =$c0c22242 [$c0e1ebf0]
c0e1ea40: e1 cc b6 b0     STRH    R11, [R12,#$60]
c0e1ea44: e1 cc 86 b2     STRH    R8, [R12,#$62]
c0e1ea48: e5 8c 30 4c     STR     R3, [R12, #$4c]
c0e1ea4c: e3 a0 30 80     MOV     R3, #$80
c0e1ea50: e5 8c 30 54     STR     R3, [R12, #$54]
c0e1ea54: e8 b4 00 0f     LDMUW   [R4], { R0-R3 }
c0e1ea58: e8 a7 00 0f     STMUW   [R7], { R0-R3 }
c0e1ea5c: e8 b4 00 0f     LDMUW   [R4], { R0-R3 }
c0e1ea60: e8 a7 00 0f     STMUW   [R7], { R0-R3 }
c0e1ea64: e8 94 00 07     LDMU    [R4], { R0-R2 }
c0e1ea68: e8 87 00 07     STMU    [R7], { R0-R2 }
c0e1ea6c: e3 a0 7c 96     MOV     R7, #$9600
c0e1ea70: e1 a0 00 0c     MOV     R0, R12 
c0e1ea74: e5 9f 11 78     LDR     R1, =$c0a39b2c <ptm_unix98_ops> [$c0e1ebf4]
c0e1ea78: e5 8c 60 64     STR     R6, [R12, #$64]
c0e1ea7c: e5 8c 60 68     STR     R6, [R12, #$68]
c0e1ea80: e5 8c 60 70     STR     R6, [R12, #$70]
c0e1ea84: e5 8c 90 6c     STR     R9, [R12, #$6c]
c0e1ea88: e5 8c 70 88     STR     R7, [R12, #$88]
c0e1ea8c: e5 8c e0 98     STR     LR, [R12, #$98]
c0e1ea90: e5 8c 70 8c     STR     R7, [R12, #$8c]
c0e1ea94: e5 8c a0 90     STR     R10, [R12, #$90]
c0e1ea98: eb d6 d8 20     BL      $c03d4b20 <tty_set_operations>
c0e1ea9c: e5 95 e0 04     LDR     LR, [R5, #$4]
c0e1eaa0: e5 9f 31 28     LDR     R3, =$c0c221ab [$c0e1ebd0]
c0e1eaa4: e5 8e 60 58     STR     R6, [LR, #$58]
c0e1eaa8: e2 44 60 20     SUB     R6, R4, #$20
c0e1eaac: e2 8e c0 64     ADD     R12, LR, #$64
c0e1eab0: e5 8e 30 48     STR     R3, [LR, #$48]
c0e1eab4: e5 9f 31 3c     LDR     R3, =$c0bea6c2 [$c0e1ebf8]
c0e1eab8: e1 ce b6 b0     STRH    R11, [LR,#$60]
c0e1eabc: e5 8e 30 4c     STR     R3, [LR, #$4c]
c0e1eac0: e3 a0 30 88     MOV     R3, #$88
c0e1eac4: e5 8e 30 54     STR     R3, [LR, #$54]
c0e1eac8: e3 a0 30 02     MOV     R3, #$2
c0e1eacc: e1 ce 36 b2     STRH    R3, [LR,#$62]
c0e1ead0: e8 b6 00 0f     LDMUW   [R6], { R0-R3 }
c0e1ead4: e8 ac 00 0f     STMUW   [R12], { R0-R3 }
c0e1ead8: e8 b6 00 0f     LDMUW   [R6], { R0-R3 }
c0e1eadc: e8 ac 00 0f     STMUW   [R12], { R0-R3 }
c0e1eae0: e8 94 00 07     LDMU    [R4], { R0-R2 }
c0e1eae4: e5 95 30 00     LDR     R3, [R5]
c0e1eae8: e8 8c 00 07     STMU    [R12], { R0-R2 }
c0e1eaec: e1 a0 00 0e     MOV     R0, LR 
c0e1eaf0: e5 9f 11 04     LDR     R1, =$c0a39ba8 <pty_unix98_ops> [$c0e1ebfc]
c0e1eaf4: e5 8e 90 6c     STR     R9, [LR, #$6c]
c0e1eaf8: e5 8e 70 88     STR     R7, [LR, #$88]
c0e1eafc: e5 8e 70 8c     STR     R7, [LR, #$8c]
c0e1eb00: e5 8e a0 90     STR     R10, [LR, #$90]
c0e1eb04: e5 8e 30 98     STR     R3, [LR, #$98]
c0e1eb08: eb d6 d8 04     BL      $c03d4b20 <tty_set_operations>
c0e1eb0c: e5 95 00 00     LDR     R0, [R5]
c0e1eb10: eb d6 d9 28     BL      $c03d4fb8 <tty_register_driver>
c0e1eb14: e3 50 00 00     CMPS    R0, #$0
c0e1eb18: 15 9f 00 e0     LDRNE   R0, =$c0c22246 [$c0e1ec00]
c0e1eb1c: 1a ff ff 63     BNE     $c0e1e8b0
c0e1eb20: e5 95 00 04     LDR     R0, [R5, #$4]
c0e1eb24: eb d6 d9 23     BL      $c03d4fb8 <tty_register_driver>
c0e1eb28: e3 50 00 00     CMPS    R0, #$0
c0e1eb2c: 15 9f 00 d0     LDRNE   R0, =$c0c2226a [$c0e1ec04]
c0e1eb30: 1a ff ff 5e     BNE     $c0e1e8b0
c0e1eb34: e2 85 00 08     ADD     R0, R5, #$8
c0e1eb38: eb d6 e5 85     BL      $c03d8154 <tty_default_fops>
c0e1eb3c: e5 9f 30 c4     LDR     R3, =$c03de998 <ptmx_open> [$c0e1ec08]
c0e1eb40: e2 85 00 70     ADD     R0, R5, #$70
c0e1eb44: e2 85 10 08     ADD     R1, R5, #$8
c0e1eb48: e5 85 30 34     STR     R3, [R5, #$34]
c0e1eb4c: eb d0 f4 3c     BL      $c025bc44 <cdev_init>
c0e1eb50: e2 85 00 70     ADD     R0, R5, #$70
c0e1eb54: e5 9f 10 b0     LDR     R1, =$500002 [$c0e1ec0c]
c0e1eb58: e1 a0 20 08     MOV     R2, R8 
c0e1eb5c: eb d0 f4 6d     BL      $c025bd18 <cdev_add>
c0e1eb60: e2 50 40 00     SUBS    R4, R0, #$0
c0e1eb64: 0a 00 00 01     BEQ     $c0e1eb70
c0e1eb68:                                             ; from c0e1eb84
c0e1eb68: e5 9f 00 a0     LDR     R0, =$c0c2228e [$c0e1ec10]
c0e1eb6c: ea ff ff 4f     B       $c0e1e8b0
c0e1eb70:                                             ; from c0e1eb64
c0e1eb70: e5 9f 00 94     LDR     R0, =$500002 [$c0e1ec0c]
c0e1eb74: e1 a0 10 08     MOV     R1, R8 
c0e1eb78: e5 9f 20 94     LDR     R2, =$c0bf8e0d [$c0e1ec14]
c0e1eb7c: eb d0 f5 46     BL      $c025c09c <register_chrdev_region>
c0e1eb80: e3 50 00 00     CMPS    R0, #$0
c0e1eb84: ba ff ff f7     BLT     $c0e1eb68
c0e1eb88: e5 9f 30 88     LDR     R3, =$c0bf8e12 [$c0e1ec18]
c0e1eb8c: e1 a0 10 04     MOV     R1, R4 
c0e1eb90: e5 9f 20 74     LDR     R2, =$500002 [$c0e1ec0c]
c0e1eb94: e5 8d 30 00     STR     R3, [SP]
c0e1eb98: e5 9f 30 7c     LDR     R3, =$c1175968 [$c0e1ec1c]
c0e1eb9c: e5 93 00 00     LDR     R0, [R3]
c0e1eba0: e1 a0 30 04     MOV     R3, R4 
c0e1eba4: eb d8 a6 a9     BL      $c0448650 <device_create>
c0e1eba8: e1 a0 00 04     MOV     R0, R4 
c0e1ebac: e2 8d d0 14     ADD     SP, SP, #$14
c0e1ebb0: e8 bd 8f f0     LDMUW   [SP], { R4-R11, PC }

長いですね。すみませんでした。
注目するべきところは

c0e1eb34: e2 85 00 08     ADD     R0, R5, #$8
c0e1eb38: eb d6 e5 85     BL      $c03d8154 <tty_default_fops>

のところです。
前半のpty_initのソースに、

tty_default_fops(&ptmx_fops);

とありましたが、まさにその部分がこれです。

c0e1eb34: e2 85 00 08     ADD     R0, R5, #$8

はR5に8を足してR0に入れる(R0=R5+8)っていう動きをするのですが、このR0こそptmx_fopsのアドレスになります。
なので、R5の値を特定して8を足してやればR0と同じ、つまりptmx_fopsの値になります。
そこで直前のR5レジスタの動きを見てみましょう。
このディスアセンブラは基本的に
<命令> <命令を受けるレジスタとか>, <命令実行に使うレジスタとか>
といった感じなので、命令を受けてるR5、簡単に言えば命令のとなりにいるR5を探します。
すると、

c0e1e9d8: e5 9f 52 04     LDR     R5, =$c1175a70 [$c0e1ebe4]

というのが見つかります。
LDR命令は32bitの定数値か何かしらのアドレスをレジスタにロードする命令です。
今回の場合は、アドレスc0e1ebe4の中身がロードされています。
そこで、c0e1ebe4の部分をディスアセンブルしてみます。

$ ./arm7-dasm kernel.dump c0008000 c0e1ebe4 kallsyms_kyv31.txt | grep c0e1ebe4
70271 symbols are loaded.
Disassemble whole image.
Disassemble 0xc0e1ebe4 - 0xc1077d00
c0e1ebe4: c1 17 5a 70     TSTGTS  R7, R0 ,ROR R10

マシン語の部分がc1175a70なので、R5にロードにされた値はc1175a70、つまりR5=c1175a70となるので
R5+8=R0=ptmx_fopsのアドレス より、ptmx_fopsのアドレスはc1175a78となります。
これで無事おわりなわけですが、この方法だと少しばかり面倒ですよね...

ptmx_open

そんなわけでptmx_open式の紹介です。
正直、こっちのほうが早いです。
とりあえず、ptmx_openをディスアセンブルします。

$ ./arm7-dasm kernel.dump c0008000 ptmx_open kallsyms_kyv31.txt > ptmx_open.dasm
70271 symbols are loaded.

以下、ディスアセンブル結果

Disassemble 0xc03de998 - 0xc03dea90
c03de998:             <ptmx_open>
c03de998: e9 2d 41 f0     STMPW   [SP], { R4-R8, LR }
c03de99c: e1 a0 60 01     MOV     R6, R1 
c03de9a0: e1 a0 70 00     MOV     R7, R0 
c03de9a4: eb f9 de ec     BL      $c025655c <nonseekable_open>
c03de9a8: e1 a0 00 06     MOV     R0, R6 
c03de9ac: eb ff db 6e     BL      $c03d576c <tty_alloc_file>
c03de9b0: e2 50 40 00     SUBS    R4, R0, #$0
c03de9b4: 1a 00 00 34     BNE     $c03dea8c
c03de9b8: eb 15 dc e3     BL      $c0955d4c <tty_lock>
c03de9bc: e1 a0 00 07     MOV     R0, R7 
c03de9c0: eb fb 33 fc     BL      $c02ab9b8 <devpts_new_index>
c03de9c4: e1 a0 40 00     MOV     R4, R0 
c03de9c8: eb 15 dc dc     BL      $c0955d40 <tty_unlock>
c03de9cc: e3 54 00 00     CMPS    R4, #$0
c03de9d0: ba 00 00 2b     BLT     $c03dea84
c03de9d4: e5 9f 80 b8     LDR     R8, =$c1175a70 [$c03dea94]
c03de9d8: e5 9f 00 b8     LDR     R0, =$c0fc0440 [$c03dea98]
c03de9dc: eb 15 d3 c1     BL      $c09538e8 <mutex_lock>
c03de9e0: eb 15 dc d9     BL      $c0955d4c <tty_lock>
c03de9e4: e1 a0 10 04     MOV     R1, R4 
c03de9e8: e5 98 00 00     LDR     R0, [R8]
c03de9ec: eb ff df e9     BL      $c03d6998 <tty_init_dev>
c03de9f0: e1 a0 50 00     MOV     R5, R0 
c03de9f4: e5 9f 00 9c     LDR     R0, =$c0fc0440 [$c03dea98]
c03de9f8: eb 15 d3 41     BL      $c0953704 <mutex_unlock>
c03de9fc: e3 75 0a 01     CMNS    R5, #$1000
c03dea00: 9a 00 00 05     BLS     $c03dea1c
c03dea04: e1 a0 10 04     MOV     R1, R4 
c03dea08: e1 a0 00 07     MOV     R0, R7 
c03dea0c: eb fb 34 21     BL      $c02aba98 <devpts_kill_index>
c03dea10: e1 a0 40 05     MOV     R4, R5 
c03dea14: eb 15 dc c9     BL      $c0955d40 <tty_unlock>
c03dea18: ea 00 00 19     B       $c03dea84
c03dea1c:                                             ; from c03dea00
c03dea1c: e3 a0 00 10     MOV     R0, #$10
c03dea20: e2 85 10 9c     ADD     R1, R5, #$9c
c03dea24: eb fe 01 71     BL      $c035eff0 <_set_bit>
c03dea28: e1 a0 00 05     MOV     R0, R5 
c03dea2c: e1 a0 10 06     MOV     R1, R6 
c03dea30: eb ff db 60     BL      $c03d57b8 <tty_add_file>
c03dea34: e1 a0 00 07     MOV     R0, R7 
c03dea38: e5 95 10 b4     LDR     R1, [R5, #$b4]
c03dea3c: eb fb 34 29     BL      $c02abae8 <devpts_pty_new>
c03dea40: e2 50 40 00     SUBS    R4, R0, #$0
c03dea44: 1a 00 00 09     BNE     $c03dea70
c03dea48: e5 98 30 00     LDR     R3, [R8]
c03dea4c: e1 a0 00 05     MOV     R0, R5 
c03dea50: e1 a0 10 06     MOV     R1, R6 
c03dea54: e5 93 30 a8     LDR     R3, [R3, #$a8]
c03dea58: e5 93 30 0c     LDR     R3, [R3, #$c]
c03dea5c: e1 2f ff 33     BLX     R3
c03dea60: e2 50 40 00     SUBS    R4, R0, #$0
c03dea64: 1a 00 00 01     BNE     $c03dea70
c03dea68: eb 15 dc b4     BL      $c0955d40 <tty_unlock>
c03dea6c: ea 00 00 06     B       $c03dea8c
c03dea70:                                             ; from c03dea44
c03dea70:                                             ;      c03dea64
c03dea70: eb 15 dc b2     BL      $c0955d40 <tty_unlock>
c03dea74: e1 a0 00 07     MOV     R0, R7 
c03dea78: e1 a0 10 06     MOV     R1, R6 
c03dea7c: eb ff e0 1d     BL      $c03d6af8 <tty_release>
c03dea80: ea 00 00 01     B       $c03dea8c
c03dea84:                                             ; from c03de9d0
c03dea84:                                             ;      c03dea18
c03dea84: e1 a0 00 06     MOV     R0, R6 
c03dea88: eb ff db 5d     BL      $c03d5804 <tty_free_file>
c03dea8c:                                             ; from c03de9b4
c03dea8c:                                             ;      c03dea6c
c03dea8c:                                             ;      c03dea80
c03dea8c: e1 a0 00 04     MOV     R0, R4 
c03dea90: e8 bd 81 f0     LDMUW   [SP], { R4-R8, PC }

c03de9d4になんだか見覚えのあるアドレスがのってますね。

c03de9d4: e5 9f 80 b8     LDR     R8, =$c1175a70 [$c03dea94]

さっきのR5の値ですね。
お察しの通り、ptmx_openを使う場合は2連続でLDRしてるとこを見つけて、上のLDRする値に8を足せばおしまいです。
さっきよりも何倍も早いですね。

オチ

さて、無事にptmx_fopsを手に入れたわけですし、早速device.dbに書き込んで実行したいところですが、
他のアドレスが0xc0n00000番台なのに、0xc1175a78って少し大きすぎませんか?
実は、このptmx_fopsはtextセクションに書かれています。
低レイヤーなことやってる人ならご存知だと思いますが、ここで説明すると長いのですごく簡単に言うと、おいそれとは書き込めない領域です。
つまるところ、KYV31のビル番103以降のやつはptmx_fopsを使ったあれこれができません。
そんなオチでした、まる

次はN-05Dあたりになるのかな...
404KCも手に入りそうなのでそっちをするかもしれません。
しかし国産スマホネタは需要が微妙というか変にマニアックなので、せっせと書いてCTFの事やら書きたいのが本音です。