Androidの証明書関連のお話(弊研究室の某課題について考える6日目)
はじめに
この記事は弊研究室の某課題について考える6日目の記事です
本来はパーミッションの話をする予定でしたが,学内CTFの問題にならないので変えました
Androidの証明書
Androidのアプリケーションの実体はAPKファイルなのですがこのAPKファイルに署名をしないと端末にインストールすることはできません。
証明書がどのような役割を持っているかですが、APK内にあるファイルが改ざんされていないかを確認することができます。
4日目に書きましたがMETA-INFディレクトリ以下に署名関連のファイルは存在します。その中でも重要となるのはMETA-INF/MANIFEST.MF
というファイルです。
以下に私が作成したテストアプリのマニフェストファイルとそのディレクトリ構成を示します。
Manifest-Version: 1.0 Created-By: 1.8.0_161 (Oracle Corporation) Name: res/drawable-xhdpi-v4/ic_launcher.png SHA-256-Digest: N32Dm15hayJA533LvqCbKTjB2VKktf8s07k5/GsrcSY= Name: AndroidManifest.xml SHA-256-Digest: TZXq3N83t1tAAfKW2Msiqf61rlc52yCRG0xnViSz6qQ= Name: res/drawable-hdpi-v4/ic_launcher.png SHA-256-Digest: wFAEDtDl2JOrQllos6kANCnFUUeuQYLRxBxZ4rPQT44= Name: res/layout/activity_main.xml SHA-256-Digest: ZfSju9DUI4erELJwRPGT/4quaScbbcc/sNZxzBoDn8U= Name: resources.arsc SHA-256-Digest: 5xEbB46maGyhMKqlKNX/E2CcJWus2fp9XE5Pci1b/Ek= Name: res/drawable-mdpi-v4/ic_launcher.png SHA-256-Digest: oDeveiogn/RmjjLSWBqGIkEm00m9vvxVI2A4iyG9hq8= Name: classes.dex SHA-256-Digest: mwFrI/cqNGVZeSHxWO2kzM7F/Xa/YBpfxRcG8M9OnM4= Name: res/drawable-xxhdpi-v4/ic_launcher.png SHA-256-Digest: 9tez3E9oIUiz8dzaZvZBX44SD3jDbVjG7AcunU5NOQ8= Name: res/menu/main.xml SHA-256-Digest: JmNDf4y9RNEWeRvzDM9HrKBucRjxYfJ0TQ7zkoB3uzw=
$ tree ./ ./ ├── AndroidManifest.xml ├── classes.dex ├── res │ ├── drawable-hdpi-v4 │ │ └── ic_launcher.png │ ├── drawable-mdpi-v4 │ │ └── ic_launcher.png │ ├── drawable-xhdpi-v4 │ │ └── ic_launcher.png │ ├── drawable-xxhdpi-v4 │ │ └── ic_launcher.png │ ├── layout │ │ └── activity_main.xml │ └── menu │ └── main.xml └── resources.arsc
APKファイル内の全てのハッシュ値がMANIFEST.MFに記述されています。この値とファイルのハッシュ値を比較すれば改ざんされているかを確認できます。
ファイルのハッシュ値計算方法
ファイルのハッシュ値ですが,ファイルのハッシュダイジェストの20バイトのバイナリ長で返されたものをbase64エンコードしたものとなります。
ハッシュアルゴリズムに関してはMANIFEST.MFに書いてあるのでそれで計算します。今回は上のclasses.dexのハッシュ値を確認します。
phpでのハッシュ確認
$ php -r "echo base64_encode(hash_file('sha256','classes.dex',true));" mwFrI/cqNGVZeSHxWO2kzM7F/Xa/YBpfxRcG8M9OnM4=%
という感じで計算できているのが確認できます。hash_file
関数の最後にtrue
を指定しないと16進で値が返ってきてしまいますので結果が変わってしまうので気をつけてください。
pythonでのハッシュ確認
>>> import hashlib >>> import base64 >>> f = open("./classes.dex","rb") >>> content = f.read() >>> print(base64.b64encode(hashlib.sha256(content).digest())) mwFrI/cqNGVZeSHxWO2kzM7F/Xa/YBpfxRcG8M9OnM4=
こんな感じですね、Pythonのほうが特に気をつけることもなくて楽ですね
おわりに
弊研究室のB4課題の知識としては上のことを知ってれば解けるはず、もっと詳しく知りたい方は参考文献を見る。もしくはAndroid Developerを見に行く等ですね