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を取ります。
- XDAフォーラムhttps://forum.xda-developers.com/android/software-hacking/root-tool-dirtycow-apk-adb-t3525120
- 必要なファイルhttp://www.mediafire.com/file/r3i900n7jb2zfoo/EXPLOIT_ADB.rar/file
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は、ファイル内に埋もれてるファイルを表示してくれます。
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氏制作のツールを使用させていただきます。
これをいつもどおり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を使用します。
これを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の事やら書きたいのが本音です。