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を見に行く等ですね

参考文献