Androidを破壊します。 ウサギの穴はどのくらい深いのですか?

画像







私の最初のAndroid携帯電話Galaxy Note N7000は、2011年10月の発表直後に買収されました。 バウナーというニックネームのドイツ人職人のおかげで、CyanogenMod(現在のLineageOS )の最新バージョンを使用する機会がありました。 1年半前まで、携帯電話は中国の車の充電で死亡しました。







私は長い間代替品を探していましたが、 京セラ (そう、彼らは電話をリリースします)KC-S701に落ち着きました。 それはその残忍な外観とタッチボタンの欠如によって区別されます。 電話へのルートアクセスについても考えていませんでした。今では、すべての電話が何らかの形でルートを取得できると信じています。 そして、CyanogenModを移植できる職人がいます。 私は間違っていました。







1年半の間に、アップデートは1つしかリリースされませんでした-特別に形成されたpingパッケージによるカーネルクラッシュの修正 。 そして、1年前のAndroid KitKatは最初の新鮮さではありませんでした。 誰もこの電話へのルートアクセス権を取得しておらず、それに関する情報もありませんでした。 同じハードウェアがアメリカ版のKyocera Brigadier E6782電話で使用されていることに注意してください。デフォルトではfastbootモードが有効になっており、署名のないカーネルの起動に制限はありません(つまり、ファームウェアではなく、パッチが適用されていないブートローダーCVE-2014を使用する場合のみ) -4325 )および電話ボタンを固定することにより、これらのモードで起動する機能があります。 Verizon(または京セラでしょうか?)を通じて、准将のAndroidバージョンはLollipopにアップグレードされました。







そこで、私は自分でAndroidにrootになるプロセスを理解することにしました。







2か月前、Androidデバイスについて何も知りませんでした(そして今はそれ以上知りません)。 ほとんどの知識は、ソースコードと実験を研究することによって得られなければなりませんでした。 インターネットでAndroidをハッキングすることに関する情報はほとんどありません。 次の説明はAndroid 4.4 KitKatに有効ですが、新しいバージョンでも機能する可能性があります。







このレビューでは、特定の電話モデルでAndroidをハッキングする私の特定の経験のみを説明しているという事実に注意を喚起したいので、突然死んだ電話を取得したくない場合は、練習での使用に非常に注意してください。 調査を始める前に、日常生活でジェイルブレイクした電話を使用し、バックアップを作成してからハードリセットすることを忘れることをお勧めします。 これにより、エラーが発生したときにデータが保護されます。







この記事では、成功につながったアクションだけでなく、ミスについても説明しています。 真実と多くの熊手に到達する私の試みがあなたにとって興味深いものになることを願っています。







すべての研究はLinux環境で実施されました。







汚い牛(CVE-2016-5195)



簡単に言えば、dirtycow(Androidの有効なエクスプロイト )を使用すると、プロセス(ASMを熟知している場合に有用)または読み取り専用ファイル(読み取り専用ファイルシステムにある場合でも)のメモリを置き換えることができます。 置き換えられたファイルのサイズは、置き換えられたファイルのサイズ以下であることが望ましいです。 dirtycow for Androidの主な攻撃は、スプーフィング/system/bin/run-as



-アプリケーションをデバッグするsudo



に似ています。 android-19 API(APIとAndroidバージョン対応/system/bin/run-as



からCAP_SETUIDおよびCAP_SETGID機能フラグがあります(古いバージョンでは、通常のsuidビットは6755です)。







 $ getcap bin/run-as bin/run-as = cap_setgid,cap_setuid+ep
      
      





ファイルシステムが読み取り/書き込みモードでマウントされている場合、dirtycowが置き換えるものはすべてファイルシステム上にあります。 したがって、元のファイルをバックアップしてアクセスした後に復元するか、ファイルシステムを読み書きモードで再マウントしないことが必要です。 原則として、Androidの/ systemセクションはデフォルトで読み取り専用モードでマウントされます。







dirtycowがLinuxで発見された最も深刻な脆弱性の1つと考えられているのも不思議ではありません。 また、dirtycowの知識があれば、SELinuxを含むすべてのレベルのカーネル保護をバイパスできます。







SELinux



開始するには、SELinuxコンテキストの仕組みを読んでください。 良いGentoo wiki記事: https : //wiki.gentoo.org/wiki/SELinux/Tutorials/How_does_a_process_get_into_a_certain_context







要するに:









adbdとコンソール



実稼働Androidデバイスで比較的特権のあるシェルを取得する唯一の方法は、開発者モードです。 開発者モードはadbdデーモンを起動します。これは、ssh / telnetの類似物としても機能します。 Android KitKatでは、それはパス/sbin/adbd



沿ったinitramfsにあり、非rootユーザーは読み取りできません。 最初に、adbdはrootとして実行され、SELinuxコンテキスト/ initドメインで実行されます(initプロセスで使用され、通常は他のドメインよりも多くの特権を持っています)。 プロセスコンテキストが/init.rc



で明示的に指定されている/init.rc



(例:seclabel u:r:adbd:s0 )、プロセスは指定されたコンテキストで直ちに開始されます。 adbdを初期化するとき、コンパイルパラメーター( user、userdebugまたはengおよびAndroidパラメーター( properties )に応じて、特権を下げます。つまり、現在のユーザーをルートからシェルに変更し、SELinuxコンテキストをシェルに設定し、 CAP_SETUIDおよびCAP_SETGIDを除くすべてのシステム機能を切り捨てます(必須) run-as



を介したアプリケーションのデバッグ用)いわゆるケイパビリティバウンディングセットでは、子アプリケーションが機能を増やすことはできませんが、これらの権限により、電話で何もせずに行うことができます。コマンドcat /proc/self/status | grep CapBnd



。A P コマンドとそれらsshifrovat capsh



、(Android上で利用できません)例えば:







 $ capsh --decode=0000001fffffffff
      
      





現在のSELinuxコンテキストは、 id



コマンドまたはcat /proc/self/attr/current



ます。 コマンドcat /proc/self/attr/prev



と、前のプロセスコンテキストを表示できます。







コンテキストファイルの表示: ls -Z





実行中のプロセスのコンテキストを表示: ps -Z









ルートアクセスを取得する



ルート、はいそうではありません



私が最初にしたことは、意図された目的のためにdirtycowを使用することでした-UID / GIDを0に設定する/system/bin/run-as



置き換えました(suは同じです)。 しかし、tmpfsであってもファイルシステムをマウントできませんでした。 カーネルモジュールもロードできませんでした。 dmesgを表示-いいえ。 700のアクセス許可があり、他のシステムユーザーに属しているディレクトリを参照することさえできませんでした。 ブロックデバイスへの読み取りと書き込みのみが可能で、特定のユーザーのUID / GIDを設定することでファイルまたはディレクトリの表示が可能になりました( 自転車を書いた-selinuxのコンテキストとユーザー/グループを設定できるsuの類似物)。







私が最初にしたことは、ファームウェア全体のダンプ、ブート、およびリカバリでした。







 $ dd if=/dev/block/mmcblk0 of=/storage/sdcard1/mmcblk0.img $ dd if=/dev/block/platform/msm_sdcc.1/by-name/boot of=/storage/sdcard1/boot.img $ dd if=/dev/block/platform/msm_sdcc.1/by-name/recovery of=/storage/sdcard1/recovery.img
      
      





kpartx



およびunpackbootimg



kpartx



てダンプを調べることができunpackbootimg



kpartx -a mmbblk0.img



は、パス/dev/mapper/loop0



介してアクセス可能な仮想ブロックデバイスを作成します。 他のブロックデバイスと同様に作業できます。 ブートおよびリカバリのダンプセクションは、 unpackbootimg



によってアンパックされunpackbootimg









次に、recovery /dev/zero



に書き込み、チェックして、すぐにダンプから復元しようとしました。







ブロックデバイスに書き込むことができるため、カスタムリカバリを記述することができます。 BrigadierからTWRPを見つけ、それをリカバリにフラッシュし、 adb reboot recovery



adb reboot recovery



しました。 TWRPではなく、感嘆符付きのAndroidアイコンのみが表示されました。 これは標準的な回復のようです。つまり、TWRPはフラッシュしませんでした。







通常モードで再起動し、エクスプロイトを実行し、ハッシュリカバリセクションを確認します-ハッシュは元のものと一致します。 再びデータを書き込もうとしています-ハッシュが変更されました! 私はページキャッシュについて覚えています、私はきれいにします( echo 3 > /proc/sys/vm/drop_caches



)-古いハッシュ。 つまり 私がブロックデバイスに書き込むものはすべて、エラーなしで/ dev / nullに飛んで、時々Linuxキャッシュに落ち着きます。 しかし、ファームウェアの更新はどういうわけか進行中ですか? そして、ユーザーデータは何らかの形で内部メモリに書き込まれます。 さらに掘り下げなければなりません。







SELinuxを無効にしてみてください



当時、私は特権の不足に関するすべてのエラーはSELinuxが原因であると考えていました(機能がトリミングされることを完全に忘れていました)。 dmesgログは見ませんでしたが、logcatは関連するものを何も表示しませんでした。 そして、SELinuxを無効にする方法を考え始めました。







私が見つけることができた最初の手がかり:







 $ grep -A2 reload_policy boot/ramfs/init.rc on property:selinux.reload_policy=1 restart ueventd restart installd
      
      





ソースは、このオプションが変更されると、initは/sepolicy



ファイルからSELinuxポリシーをリロードすると/sepolicy



ます。







つまり dirtycowを使用して/sepolicy



sepolicyを上書きし、 setprop selinux.reload_policy 1



コマンドで更新されたポリシーをダウンロードできます。







まず、 /sepolicy



何かを知る必要があります。 sesearch



(Debianのsetoolsパッケージ)を使用して学習できます。







 $ sesearch --allow sepolicy $ sesearch --neverallow sepolicy $ sesearch --auditallow sepolicy $ sesearch --dontaudit sepolicy
      
      





私の場合、 /sepolicy



にはallowのみ含まれていました。つまり、AndroidでSELinuxモードを強制する場合、ポリシーで宣言されていることのみが許可されます。 また、initプロセスはポリシーのロードのみを許可され、切断は許可されませんでした。







 $ sesearch --allow sepolicy | grep 'load_policy' allow init kernel : security load_policy ;
      
      





私のタスクは、initコンテキストがselinux-> forceをpermissive(setenforce 0)に設定できるようにすることでした。







最初に行ったのは、標準のAndroidストックポリシーを収集し、元の/sepolicy



置き換えて(root setprop selinux.reload_policy 1



として)ロードし、ステータス行に電話が安全でないモードになっているというメッセージを受け取ることです。 その後、電話機はアプリケーションの起動を拒否し、非常に思慮深くなり、許容モードの設定にも失敗し、最終的に電話機が再起動しました。 否定的な結果も結果であり、交換/sepolicy



は機能しました。







私が最初に考えたのは、株式政策がこの携帯電話に適合せず、権利がない場合は鈍くなることです。







私は、既存のすべてのSELinuxコンテキストを単に説明し、それらを許容できると宣言するという新しいポリシーをまとめました。 それも助けにはなりませんでした。







次に、ポリシーを再構築し、可能であれば、シェルコンテキストに特権を追加することにしました。







ポリシーを「逆コンパイル」する方法を説明する記事を見つけまし 。 少し整理して、すべての依存関係を収集し、 sedump



ユーティリティを実行することができました。 出力では、(KitKat checkpolicy -M -c 26 -o sepolicy.new policy.conf



checkpolicy -M -c 26 -o sepolicy.new policy.conf



テキストファイルを受け取り、元のsepolicy



とまったく同じサイズで、16進数の内容が異なるファイルを取得することもできました。 新しいポリシーをダウンロードすると、以前とまったく同じ結果が得られました。しばらくして電話が再起動しました。







私は2つのポリシーを収集することにしました。受け取ったpolicy.conf



から、およびallow init kernel : security



allow init kernel : security



ためのすべての特権を追加したpolicy.conf



からpolicy.conf



setenforceを含むsecurity 。 16進数のファイルを比較し、同様に、元のsepolicy



バイトを置き換えます。







結局のところ、再編成された2人の政治家は、わずか数バイトの違いがありました。 元のsepolicyで同様の一致を探し始めましたが、見つかりませんでした。 次に、指定されたオフセット範囲で2バイトを「0xFF、0xFF」に置き換え、 sesearch --allow | grep " "



実行するブルートフォーススクリプトをsesearch --allow | grep " "



sesearch --allow | grep " "



。 したがって、元のポリシーに必要なバイアスを見つけ、バイトを置き換え、元のポリシーを置き換えましたが、何もありませんでした。 selinuxの無効化に再度失敗しました。







少し後に、 sepolicy-injectユーティリティが見つかりました。このユーティリティは、既にコンパイルされたsepolicy



ファイルに特権を追加します。 ルールが既に存在する場合、最大特権を追加してもポリシーの最終サイズは増加しません。 残念ながら、ユーティリティを実行すると、一度に1つのルールしか追加されません。 各ルールに最大の特権を追加するスクリプトを書きました。 結果は、各ルールに最大の特権が含まれるポリシーファイルになりました。 ファイルサイズは元のものと同じでした。 そして、それは再び助けにはなりませんでした。







次に、Androidには、何らかの方法でポリシーをリロードするload_policy



コマンドがあることがわかりました。 タンバリンと踊るのは無意味でした。







 adb shell run-as /data/local/tmp/run -u system -cu:r:init:s0 load_policy /data/local/tmp/sepolicy.new
      
      





任意の許容ドメインを追加し、新しいポリシーをロードして、このドメインのコンテキストで機能します(ちなみに、Chainfire SupersuはAndroidの新しいバージョンで機能します)。 しかし、これでもSELinuxを無効にすることはできませんでした。 私は別の方向に掘ることに決めました。







掘り戻し



画像







ブートパーティションとリカバリパーティションの違いを確認します。 initramfs以外はすべて同じです。 回復セクションのinitramfsでは、 /sbin/recovery



を実行する1つのサービスのみを記述するinit.rcを研究しています。 strings sbin/recovery | less



学習strings sbin/recovery | less



strings sbin/recovery | less



元の回復のソースコード 。 ご覧のとおり、デフォルトでは、リカバリーは単にAndroidロゴを表示します。 また、何かを行う必要がある場合、通常モードでは/cache/recovery/command



ファイルが/cache/recovery/command



セクションに書き込まれます。これには、リカバリスタートアップパラメータが含まれる場合があります。 このファイルに--show_text



を書き込むと、メニューが表示されます。







dirtycowエクスプロイトを起動し、UID / GIDを設定し、ファイルに書き込み、 adb reboot recovery



を実行します。 電話が再起動し、標準の回復メニューが表示されます。 すでに何か。 私はadb sideload



sideloadを介してsupersuでZIPファイルをフラッシュしようとしています。 操作はエラーで中止されました。 私は実際にはエラーを見ていませんが、回復コードに登り、ZIPファイルのデジタル署名を検証する責任がある場所を探します。







initramfsには、ZIPファイルのデジタル署名を検証するminicrypt形式のres/keys



公開キーが含まれていることがわかりました。 それは標準のAndroid テストキーであり、このキーでどんなアーカイブにも署名できることがわかった。 これは次のように確認できます。







 java -jar dumpkey.jar android/bootable/recovery/testdata/testkey.x509.pem > mykey diff -u mykey res/keys
      
      





sdcardから直接ZIPをインストールしようとしましたが、リカバリ中に、sdcardのマウント中にエラーが発生しました。 etc/recovery.fstab



を調べたところ、リカバリモードではsdcardがvfatとしてマウントされていることがわかりました。







 $ grep mmcblk1 recovery/ramfs/etc/recovery.fstab /dev/block/mmcblk1p1 /sdcard vfat nosuid,nodev,barrier=1,data=ordered,nodelalloc wait
      
      





64Gbフラッシュドライブはexfatでフォーマットされました。 2Gbで古いsdcardを見つけ、vfatとしてフォーマットし、ZIPを記録し、電話に挿入しました。 今回のリカバリではカードをマウントでき、その内容を電話で見ることができました。 ただし、ZIPのインストール中にエラーが発生しました: E:予想されるインストール用マウントのセットアップに失敗しました。 中止します。







strings recovery



コマンドは、この回復は通常のものとは異なり、少なくとも京セラに関連する行があり、 /data



セクションをクリアする可能性が最も高いことを示しました。 元のソースを調べてsetup_install_mounts



と、 setup_install_mounts



ファイルのsetup_install_mounts



関数で興味のあるエラーが発生していることがsetup_install_mounts



ました。







つまり ZIPを適用する前に、回復はすべてのパーティションをアンマウントしますが、私の場合は何かがおかしいです。







カーネルソースを掘る



GPLライセンスは、スマートフォンメーカーにカーネルソースのアップロードを義務付けています。 これについてLinusとStallmanに感謝します。 メーカーは時々、残っているもの、時には正しいソースをアップロードしますが、 defconfig



ファイルがなく、時には正しく、それらをアセンブルする方法に関する指示が非常にまれです(例えばLG)。







私の場合、ソースには正しいdefconfig



がありますが、指示はありdefconfig



た。 少し汗をかいて、 コアを組み立て、完全なリンデンではないことを確認することができました。







久しぶりに、私は2つのファイルに決めました。









フック



京セラは長い間考えていませんでしたが、Androidの潜在的に危険な操作のために、 mount



umount



insmod



wlan



、およびinitプロセスがそれをロードする場合にのみ、ロードできるモジュールは1つだけです)などのフックを単純に見ました。 そこに回復の問題がありました。 彼は/system



ファイル/system



アンマウントできませんでした! これらの操作は、initプロセスに対してのみ許可されていました。 特に、この機能はカーネルのコンパイル中に無効になったため、SELinuxを無効にできませんでした。 カーネルが特定のパラメーター( kcdroidboot.mode = f-ksgまたはandroidboot.mode = kcfactory 、詳細については後述)でロードされた場合にのみ、これらのフックをバイパスできました。







再起動



また、興味深いファイルです。 電話をダウンロードするための可能なオプションについて説明します。









Qualcommプロセッサを搭載した携帯電話でのダウンロード方法について少し説明します。







Qualcommの統合ROMブートローダー(pbl-プライマリブートローダー)は、sbl1(セカンダリブートローダー)パーティションをロードします。 sbl1はtz(トラストゾーン)をロードし、次にaboot(Androidブート、リトルカーネル、lk)をロードします。 次に、Abootはブート、リカバリ、またはfotaをロードします。







ダウンロードに関係するセクションの説明:









これらのセクションはすべて、証明書チェーンによって署名されています。







フォタ



場合によっては、ファームウェアの更新を無視すると便利です。







FOTA-無線によるファームウェア。 ブートとリカバリとは異なり、fotaは非公式のAndroidブートモードです。 fotaのタスクは、ファームウェアを更新することです。 京セラでは、これにRed Bendのソリューション使用されます。35Mbでは、カーネルだけでなく/system



パーティションの更新にも対応しています。 したがって、 /system



セクションへの書き込みは禁止されています。そうしないと、間違ったデータにパッチを適用すると、電話がブロックされる可能性があります。







携帯電話に更新がありました。 いつでも書き込み/cache



し、更新を中断する機会がすでにあったので、私はそれに挑戦することができました。







Javaアプリケーションアップデートのソースコードを検討した結果、どのように発生するかが明らかになりました。









, fotamng.







, /cache/delta/boot_delta.bin



. . FOTA, .







, . /cache



fota, dmseg! fota "1" fotamng:







 $ dd if=/data/local/tmp/one_bit.bin of=/dev/block/platform/msm_sdcc.1/by-name/fotamng seek=16 bs=1 count=1 $ dd if=/data/local/tmp/one_bit.bin of=/dev/block/platform/msm_sdcc.1/by-name/fotamng seek=24 bs=1 count=1 $ dd if=/data/local/tmp/one_bit.bin of=/dev/block/platform/msm_sdcc.1/by-name/fotamng seek=131088 bs=1 count=1 $ dd if=/data/local/tmp/one_bit.bin of=/dev/block/platform/msm_sdcc.1/by-name/fotamng seek=131096 bs=1 count=1
      
      





. dmesg kcdroidboot.mode=f-ksg . ここにある! つまり fota. , boot fota , Kyocera. .







little kernel (lk)



, aboot — Android, : https://source.codeaurora.org/quic/la/kernel/lk/







. , misc "boot-recovery", recovery adb reboot recovery . recovery . recovery , boot loop . , .







, emmc read-only . , recovery. Linux , , , , Kyocera. , mmc claim mode. .







: https://source.codeaurora.org/quic/la/kernel/lk/tree/platform/msm_shared/image_verify.c?h=LA.BR.1.3.3_rb2.29









dmesg



Google , : /proc/sys/kernel/dmesg_restrict



. 1 . CAP_SYS_ADMIN capability, .







uevent_helper



, , /sys/kernel/uevent_helper



. executable (shell script ), init init full capabilities.







:







 #!/system/bin/sh echo 0 > /proc/sys/kernel/dmesg_restrict
      
      





/sys/kernel/uevent_helper



. dmesg!







adbd



画像







なぜなら Android, adbd , adbd 。 70 Gb Android, . capabilities, , /sbin/adbd



root . , dmesg dmesg_restrict , , root . /system



.







, , lsh /sys/kernel/uevent_helper



. lsh , PATH



environment, .







WiFi



WiFi . WiFi — . WiFi — . , WiFi . . , , , SELinux Amazon Fire Phone: https://github.com/chaosmaster/ford_selinux_permissive







, - Module.symvers. , , Module.symvers



, .







( disagrees about version of symbol module_layout ), Module.symvers



boot



. , https://github.com/glandium/extract-symvers :







 $ unpackbootimg -i boot.img -o boot $ extract-symvers.py -e le -B 0xc0008000 boot/boot.img-zImage > %PATH_TO_KERNEL%/Module.symvers
      
      





Kyocera.







画像







? wlan . :









 ... MODULE_NAME = wlan ...
      
      





(, wlan , lsmod), SELinux .







dmesg . , : /proc/sys/kernel/printk



, INFO , . : echo '8 8 8 8' > /proc/sys/kernel/printk



. , , SELinux .







, , WiFi. / WiFi Android.











SELinux , https://github.com/chaosmaster/ford_selinux_permissive , Kyocera hooks. kc_bootmode kc_kbfm .







Linux : cat /proc/kallsyms



. 0. . : echo 0 > /proc/sys/kernel/kptr_restrict



.







, 1. , kallsyms ( d D , ), . CONFIG_KALLSYMS_ALL



.







 $ adb shell "grep kc_bootmode_setup /proc/kallsyms" c0d19d84 t kc_bootmode_setup
      
      





:







 int (*_kc_bootmode_setup)(char *buf) = (int(*)()) 0xc0d19d84;
      
      





:







 _kc_bootmode_setup("f-ksg")
      
      





:







 _kc_bootmode_setup = (int (*)(char *buf))kallsyms_lookup_name("kc_bootmode_setup");
      
      





! /system



.







emmc /system



. , cache .







- SELinux



- SELinux. defined selinux_enabled



, hooks security_ops



.







reset_security_ops



:







 void (*_reset_security_ops)(void) = NULL; ... ... ... _reset_security_ops = (void (*)(void))kallsyms_lookup_name("reset_security_ops"); if (_reset_security_ops != NULL) { _reset_security_ops(); }
      
      





SELinux , , . .







download mode



 int (*_enable_dload_mode)(char *str) = (int(*)()) 0xc0d0cc18; ... ... ... _enable_dload_mode("dload_mode");
      
      





download_mode



, . , usb mass storage device. つまり ! recovery.







, . mass storage . :







 BS=512 nextblock=0 IMG=my-recovery.img DEST=/dev/sdb12 # 64 - total amount of 512*512b blocks for 16Mb partition (16Mb*1024*1024/(512*512)) for i in {1..64}; do echo $i echo dd if=${IMG} of=${DEST} bs=${BS} seek=${nextblock} skip=${nextblock} count=${BS} oflag=direct dd if=${IMG} of=${DEST} bs=${BS} seek=${nextblock} skip=${nextblock} count=${BS} oflag=direct nextblock=$((nextblock+BS)) echo "nextblock = ${nextblock}" sleep 0.5 done sync echo 3 > /proc/sys/vm/drop_caches
      
      





, adb reboot recovery



. . misc



, recovery
.







/system



supersu . : root . WiFi , hooks. , WiFi . , .







. , :









aboot boot



boot . aboot ( binwalk -e aboot



), . , . boot , . aboot . sha256 . sha256, , .







 #!/bin/bash # print der certificate: # openssl x509 -inform der -in 0xff.crt -text -noout # mkdir boot # unpackbootimg -i 09-boot.img -o boot # cd boot # mkbootimg --kernel 09-boot.img-zImage --ramdisk 09-boot.img-ramdisk.gz --cmdline "`cat 09-boot.img-cmdline`" --base `cat 09-boot.img-base` --pagesize `cat 09-boot.img-pagesize` --dt 09-boot.img-dtb --kernel_offset `cat 09-boot.img-kerneloff` --ramdisk_offset `cat 09-boot.img-ramdiskoff` --tags_offset `cat 09-boot.img-tagsoff` --output mynew.img # dd if=../09-boot.img of=signature.bin bs=1 count=256 skip=$(ls -la mynew.img | awk '{print $5}') # cd .. # binwalk -e 05-aboot.img # extract aboot signature # dd if=05-aboot.img of=signature.bin bs=1 count=256 skip=$(od -A d -t x4 05-aboot.img | awk --non-decimal-data '/^0000016/ { i=sprintf("%d\n","0x"$3); print (i+40)}') # extract base aboot image # 40 - aboot header size, refer to: https://android.googlesource.com/kernel/lk/+/caf/master/target/msm8226/tools/mkheader.c#160 # dd if=05-aboot.img of=aboot-base.img bs=1 count=$(od -A d -t x4 05-aboot.img | awk --non-decimal-data '/^0000016/ { i=sprintf("%d\n","0x"$3); print (i)}') skip=40 # how sha256 was calculated? # openssl dgst -sha256 -sign private_key -out signature.bin aboot-base.img ? NAME=$1 IMG=${NAME}/mynew.img SIG=${NAME}/signature.bin #IMG=aboot-base.img #SIG=signature.bin CALC_SHA256=$(sha256sum ${IMG} | awk '{print $1}') for i in `find . -name *.crt`; do ORIG_SHA256=$(openssl rsautl -inkey <(openssl x509 -pubkey -noout -inform der -in ${i} 2>/dev/null) -pubin -in ${SIG} 2>/dev/null | hexdump -ve '/1 "%02x"') if [ "${ORIG_SHA256}" != "" ]; then echo "sha256 was decrypted using ${i} key - ${ORIG_SHA256}" fi if [ "${ORIG_SHA256}" = "${CALC_SHA256}" ]; then echo "sha256 ${ORIG_SHA256}" echo "$i" fi done
      
      





boot fota, , fota . , .. bootloop, bootloop recovery. fota fotamng , .







, boot , fota , bootloop , , . boot , recovery . , recovery , boot. . ramdisk tags:







boot/recovery:







  ramdisk: 0x01000000 tags: 0x00000100
      
      





fota:







  ramdisk: 0x02000000 tags: 0x01e00000
      
      





Secure boot whitepaper Qualcomm , sha256 hash sha256 hash' ELF . Subject' . OU=05 00002000 SW_SIZE , sha256 hash 256 hash' 32 (0x2000/32=256). aboot ELF sbl1 (secondary boot loader).







little kernel Qualcomm, aboot. .









Kyocera Brigadier .







aboot . Subject' , . : aboot KC-S701 Brigadier. . , emmc Brigadier. , Brigadier KC-S701. fastboot. .







, " " — . Qualcomm QHSUSB__BULK



, , download mode, USB mass storage. . , .







,





Fota



boot fota? . , , .







Kyocera properties



Kyocera android system properties properties, . , bootloader'. libkcjprop_jni.so kcjprop_daemon . , .







, :







 $ ls -la /sysprop/kcjprop/rw/8d9d788ddd5fecfdbc6c5f7c5cecfc -rw-rw---- root root 16 1970-01-22 21:01 8d9d788ddd5fecfdbc6c5f7c5cecfc
      
      





Kexec



Kexec Linux . production Kexec, . user-end , . , — .







QSEE



QSEE — Qualcomm, . — Trust Zone. .







. emmc, RPMB. SCM . RPMB (Replay Protected Memory Block) , lock/unlock .







おわりに



画像







, aboot Kyocera Propertiies github: https://github.com/kayrus/break_free .







, . . , .







, Kyocera . . . , .







PS (Nikolay Elenkov), Android security internals . bootloader' Android.







PPS , Justin Case, , , Qualcomm, .








All Articles