私の最初の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
要するに:
- 同様の操作がsepolicyルールに記述されている場合、SELinuxプロセスのコンテキストを変更できます。 Androidのバージョン4.4(KitKat)では、コンテキストを変更することで特権を増やす機会があります。 ただし、5.x以降では、これを実行できなくなりました。
- ファイルコンテキストが存在します。
- ファイルとプロセスのコンテキストに加えて、Androidはproperty_contextsパラメーターのコンテキストを実装します。
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つのファイルに決めました。
- https://github.com/kayrus/kc-s701-torque-kernel/blob/master/security/selinux/hooks.c
- https://github.com/kayrus/kc-s701-torque-kernel/blob/master/arch/arm/mach-msm/restart.c
フック
京セラは長い間考えていませんでしたが、Androidの潜在的に危険な操作のために、 mount
、 umount
、 insmod
( wlan
、およびinitプロセスがそれをロードする場合にのみ、ロードできるモジュールは1つだけです)などのフックを単純に見ました。 そこに回復の問題がありました。 彼は/system
ファイル/system
アンマウントできませんでした! これらの操作は、initプロセスに対してのみ許可されていました。 特に、この機能はカーネルのコンパイル中に無効になったため、SELinuxを無効にできませんでした。 カーネルが特定のパラメーター( kcdroidboot.mode = f-ksgまたはandroidboot.mode = kcfactory 、詳細については後述)でロードされた場合にのみ、これらのフックをバイパスできました。
再起動
また、興味深いファイルです。 電話をダウンロードするための可能なオプションについて説明します。
- adb reboot bootloader -fastbootモード、携帯電話では使用不可(
0x77665500
-sbl1セクションの16進ラベル00556677) - adb reboot recovery-リカバリモード(
0x77665502
-sbl1セクションの16進ラベル02556677) - adb reboot rtc-いわゆるALARM_BOOT。 sbl1にラベルがないのはなぜかわかりませんでした。 おそらくhttps://developer.android.com/reference/android/app/AlarmManager.htmlを意味します
- adb reboot oem-X (私の場合、oem-
0x6f656d01
はsbl1セクションの16進ラベル016d656fです)。 このモード中に何が起こるかは、メーカーが設定します。 ソースコードから判断すると、モデムセクションからのファームウェアの認証でエラーが発生した場合、電話機はこのモードで再起動します。 - adb reboot edl-緊急ダウンロード。電話を通常のクアルコムのダウンロードモードに移行します。 電話機はQHSUSB__BULK COMポートとして定義されます。これを介して、署名されたブートローダーを転送し(間違っていない場合、各ブートローダーはSoCの1つのタイプと電話機メーカー向けに設計されます)、フラッシュを含む電話機で低レベルの操作を実行できます。 一般にQPSTと組み合わせて使用されます。 京セラKYL22など、一部の電話では、ブートローダーがネットワークにリークします。 彼らがどこから来たのかは私には分からない。
- ダウンロードモードの一種。adb再起動では起動できません。 ここでは興味深いです...しかし、それについては後で詳しく説明します。
Qualcommプロセッサを搭載した携帯電話でのダウンロード方法について少し説明します。
Qualcommの統合ROMブートローダー(pbl-プライマリブートローダー)は、sbl1(セカンダリブートローダー)パーティションをロードします。 sbl1はtz(トラストゾーン)をロードし、次にaboot(Androidブート、リトルカーネル、lk)をロードします。 次に、Abootはブート、リカバリ、またはfotaをロードします。
ダウンロードに関係するセクションの説明:
- tz-Qualcomm Trust Zone。 QFuses(rpmbセクション)での作業を含む、低レベルの操作を実行します。
- rpm-リソースおよび電源マネージャーのファームウェア。 リソースと栄養を担当する専門のSoCのファームウェア。
- sdi-トラストゾーンストレージパーティション。 Trust Zoneが使用するデータ。
これらのセクションはすべて、証明書チェーンによって署名されています。
フォタ
場合によっては、ファームウェアの更新を無視すると便利です。
FOTA-無線によるファームウェア。 ブートとリカバリとは異なり、fotaは非公式のAndroidブートモードです。 fotaのタスクは、ファームウェアを更新することです。 京セラでは、これにRed Bendのソリューションが使用されます。35Mbでは、カーネルだけでなく/system
パーティションの更新にも対応しています。 したがって、 /system
セクションへの書き込みは禁止されています。そうしないと、間違ったデータにパッチを適用すると、電話がブロックされる可能性があります。
携帯電話に更新がありました。 いつでも書き込み/cache
し、更新を中断する機会がすでにあったので、私はそれに挑戦することができました。
Javaアプリケーションアップデートのソースコードを検討した結果、どのように発生するかが明らかになりました。
- Java
/cache/delta/boot_delta.bin
,/cache/delta/Alt-OTA_dlcomplete
, , header'. - .
- ,
libjnialtota.so
fotamng
. - .
, 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. .
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.
- symlink
wlan.c
- Makefile
... 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");
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, .