
trueseeing v2.2.11
非逆コンパイル型iOS/Androidアプリ脆弱性スキャナー (DC25 demo lab, CB17)
README
trueseeing は、iOS/Android アプリ向けの高速で正確かつ堅牢な脆弱性スキャナーです。Android では Dalvik VM レベルで動作するため、ターゲットアプリが難読化されているかどうかは問いません。
機能
現在以下のことが可能です:
- アプリを自動的にスキャンし、脆弱性を HTML/JSON/テキスト形式で報告 (下記参照)
- 解析を容易にするためのアプリの操作: 例: デバッグビットの有効化、フルバックアップの有効化、TLS ピン留めの無効化、ターゲット API レベルの変更、frida-gadget の注入など
- アプリの一般的な情報を調査
- デバッグインターフェースを介したアプリデータのコピーイン/アウト
- 特定の呼び出し/定数/sput/iput の検索
- オペランドの引数の定数/型セットの推定
- ネイティブコードの API/プライベート呼び出しのスキャン (NB: ts2-disasm-ghidra が必要)
- iOS アプリの基本的な脆弱性スキャン (NB: ts2-disasm-ghidra が必要)
- frida スクリプトのアタッチ
- frida の対話セッションの提供
- 呼び出しのトレース
- など
インストール
コンテナ
注:
- 2.1.9 以降、ghcr.io を使用しています (Docker Hub はやや非推奨です)
- ホスト側にデバイスを制御するための adbd が必要です。
すぐに使用できるコンテナを提供しています。以下は推奨される方法であり、Windows 上で実行する唯一の方法です:
$ docker run --rm -v $(pwd):/out -v ts2:/cache ghcr.io/alterakey/trueseeing
ステートレスに実行したい場合は、/cache へのボリュームマウントを省略します (日常的な使用には推奨しません。また #254 も参照):
$ docker run --rm -v $(pwd):/out ghcr.io/alterakey/trueseeing
uv でインストール
または、uv を使用してパッケージをインストールすることもできます。特に uv tool install 形式のインストールは拡張機能 (後述) に役立ち、最大の自由度を与えます。ただし、JRE と (オプションでデバイスを操作するための) Android SDK が必要です。
$ uvx trueseeing
$ uv tool install trueseeing
$ trueseeing
pip でインストール (非推奨)
もちろん、従来の pip を使用することもできます:
$ pip install trueseeing
使い方
対話モード
アプリを対話的にスキャン/解析/パッチ適用などができるため、手動解析に最適です:
$ trueseeing target.apk
[+] trueseeing x.y.z
ts[target.apk]> ?
...
ts[target.apk]> i # 一般的な情報を表示
...
ts[target.apk]> pf AndroidManifest.xml # マニフェストファイルを表示
...
ts[target.apk]> a # リソースも解析
...
ts[target.apk]> /s something # テキスト検索
...
ts[target.apk]> as # スキャン
...
[+] done, found 6403 issues (174.94 sec.)
ts[target.apk]> gh report.html
バッチモード
プロンプトが表示される前に実行するインラインコマンド (-c) またはスクリプトファイル (-i) を受け付け、またプロンプトを表示せずにすぐに終了することもできます (-q; このモードでは tty は不要です!)。
これらの機能を使用してバッチスキャンを実行できます。例えば、結果を stderr に直接出力するには:
$ trueseeing -eqc 'as' target.apk
HTML 形式のレポートファイルを生成するには:
$ trueseeing -eqc 'as;gh report.html' target.apk
JSON 形式のレポートファイルを生成するには:
$ trueseeing -eqc 'as;gj report.json' target.apk
レポートを stdout に出力するには、最後の g* コマンドでファイル名を省略します:
$ trueseeing -eqc 'as;gh' target.apk > report.html
$ trueseeing -eqc 'as;gj' target.apk > report.json
非対話スキャンモード (非推奨)
従来は、以下のコマンドラインでアプリをスキャンし、結果を stderr に一覧表示できました:
$ trueseeing --scan target.apk
HTML 形式のレポートを生成するには:
$ trueseeing --scan --scan-output report.html target.apk
$ trueseeing --scan --scan-report=html --scan-output report.html target.apk
JSON 形式のレポートを生成するには:
$ trueseeing --scan --scan-report=json --scan-output report.json target.apk
レポートを stdout に出力するには、ファイル名として '-' を指定します:
$ trueseeing --scan --scan-output - target.apk > report.html
$ trueseeing --scan --scan-report=html --scan-output - target.apk > report.html
$ trueseeing --scan --scan-report=json --scan-output - target.apk > report.json
高度な使い方
拡張機能
独自のコマンドやシグネチャを拡張機能として記述できます。拡張機能は /ext (コンテナ) または ~/.trueseeing2/extensions/ (uv/pip) に配置します。また、拡張機能を wheel として配布することもできます。型情報を提供しているため、zuban で型チェックを行うだけでなく、IDE からの十分な支援も受けられます。詳細については、詳細セクションを参照してください。
ビルド
以下のようにビルドできます:
$ docker build -t trueseeing https://github.com/alterakey/trueseeing.git#main
wheel をビルドするには、flit を使用します:
$ flit build
ハックするには、適切なビルド環境を作成する必要があります。uv を使用する場合:
$ git clone https://github.com/alterakey/trueseeing.git wc
$ uv sync --locked --dev
$ (... ハック ...)
$ uv run trueseeing ... # 実行
$ uv run zuban check trueseeing && uv run ruff trueseeing # 検証
Success: no issues found in XX source files
$ uv run flit build # ビルド (wheel)
$ docker build -t trueseeing . # ビルド (コンテナ)
pip を使用する場合、まず venv をセットアップし、flit と検証ツールチェーン (zuban と ruff) をインストールし、flit で依存関係をプルします。簡単に言うと:
$ git clone https://github.com/alterakey/trueseeing.git wc
$ python3 -m venv wc/.venv
$ source wc/.venv/bin/activate
(.venv) $ pip install flit zuban ruff
(.venv) $ flit install --deps=develop -s
(.venv) $ (... ハック ...)
(.venv) $ trueseeing ... # 実行
(.venv) $ zuban check trueseeing && ruff check trueseeing # 検証
Success: no issues found in XX source files
(.venv) $ flit build # ビルド (wheel)
(.venv) $ docker build -t trueseeing . # ビルド (コンテナ)
詳細
脆弱性クラス
現在、以下の脆弱性クラスを検出できます。主に OWASP Mobile Top 10 - 2016 でカバーされているものです:
-
プラットフォームの不適切な使用 (M1)
- デバッグ可能
- アクティビティ、サービス、コンテンツプロバイダ、BroadcastReceiver の意図しない公開
-
安全でないデータ (M2)
- バックアップ可能 (すなわち、バックアップ攻撃の対象)
- 安全でないファイルパーミッション
- ログ出力
-
安全でない通信 (M3)
- ピン留めの欠如 (すなわち、TLS 傍受攻撃の対象)
- 平文 HTTP の使用
- 改ざん可能な WebView
-
不十分な暗号化 (M5)
- ハードコードされたパスフレーズ/秘密鍵
- 静的鍵を使用した Vernum 暗号
- ECB モードの使用
-
クライアントコードの品質問題 (M7)
- リフレクション可能な WebView (すなわち、JS リフレクションを介して XSS がリモートコード実行に昇格される可能性がある)
- 混合コンテンツに対する安全でないポリシーの使用
-
コード改ざん (M8)
- ハードコードされた証明書
-
リバースエンジニアリング (M9)
- 難読化の欠如
拡張 API
拡張 API は trueseeing.api パッケージの下にあります。型情報が提供されているため、拡張機能の作成時に IDE が支援します。IDE (またはその言語サーバー) の PYTHONPATH が、当パッケージが存在する venv をカバーしていることを確認してください。uv tool install でインストールした場合は uv tool list --show-paths を参照してください。uvx でインストールした場合は、uvx install で再インストールを検討してください。pip でインストールした場合は、その場所は既におわかりでしょう。
コマンド
新しいコマンドを定義するには、trueseeing.api.Command を実装し、広告します。
以下のクラスは、サンプルコマンドとして t を提供します:
from typing import TYPE_CHECKING
from trueseeing.api import Command
from trueseeing.core.ui import ui
if TYPE_CHECKING:
from trueseeing.api import CommandMap, CommandPatternMap, ModifierMap, OptionMap, ConfigMap
class MyCommand(Command):
@staticmethod
def create() -> Command:
return MyCommand()
def get_commands(self) -> CommandMap:
return {'t':dict(e=self._test, n='t', d='sample command')}
def get_command_patterns(self) -> CommandPatternMap:
return dict()
def get_modifiers(self) -> ModifierMap:
return dict()
def get_options(self) -> OptionMap:
return dict()
def get_configs(self) -> ConfigMap:
return dict()
async def _test(self) -> None:
ui.info('hello world')
シグネチャ
新しいシグネチャを定義するには、trueseeing.api.Signature を実装し、広告します。
以下のクラスは、サンプル検出器として my-sig を提供します:
from typing import TYPE_CHECKING
from trueseeing.api import Signature
if TYPE_CHECKING:
from trueseeing.api import SignatureMap, ConfigMap
class MySignature(Signature):
@staticmethod
def create() -> Signature:
return MySignature()
def get_sigs(self) -> SignatureMap:
return {'my-sig':dict(e=self._detect, d='sample signature')}
def get_configs(self) -> ConfigMap:
return dict()
async def _detect(self) -> None:
self._helper.raise_issue(
self._helper.build_issue(
sigid='my-sig',
title='hello world',
cvss='CVSS:3.0/AV:P/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N/',
)
)
ファイル形式
新しいファイル形式を定義するには、まず形式の Context (ABC) を実装し、次に trueseeing.api.FileFormatHandler を実装してそのインスタンスを作成して返し、広告します。
以下のクラスは、apk2 という名前のタイプで APK ファイルサポートを提供します:
from typing import TYPE_CHECKING
from trueseeing.api import FileFormatHandler
from trueseeing.core.android.context import APKContext
if TYPE_CHECKING:
from typing import Optional, Set
from trueseeing.api import FormatMap, ConfigMap
from trueseeing.core.context import Context, ContextType
class MyAPKContext(APKContext):
# 異なるコンテキストタイプを使用
def _get_type(self) -> Set[ContextType]:
return {'apk2'}
class APKFileFormatHandler(FileFormatHandler):
@staticmethod
def create() -> FileFormatHandler:
return APKFileFormatHandler()
def get_formats(self) -> FormatMap:
return {'apk2':dict(e=self._handle, r=r'\.apk$', d='sample file format', t=None)} # このハンドラがデバイスコンテキストタイプを提案できる場合は t に広告
def get_configs(self) -> ConfigMap:
return dict()
def _handle(self, path: str) -> Optional[Context]:
return MyAPKContext(path)
次に、シグネチャ内でコンテキストのタイプをチェックし、サポートされていないコンテキストでは無視されるようにします:
context = self._helper.get_context().require_type('apk2')
チェックが成功すると、require_type(...) は便利なように適切なタイプにダウンキャストしようとします。
ただし、設計上、既知のタイプ (現在は apk) でのみ機能します。そのため、apk タイプと同様に新しいコンテキストクラスに詳細なインターフェースを定義している場合、ここでダウンキャストを行う必要があります:
context: MyAPKContext = self._helper.get_context().require_type('apk2') # type:ignore[assignment]
同じパターンに一致する複数の形式を定義することは可能です。パターンは最も厳密 (すなわち長い) なものから最も緩いものの順に評価します。-F スイッチを使用して、ターゲットファイルに特定の形式を強制できます:
$ trueseeing -F apk2 target.apk
パッケージ要件
拡張機能は、a) /ext (コンテナ) または ~/.trueseeing2/extensions (pip) に配置された任意のパッケージ、または b) 接頭辞 trueseeing_ext0_ で命名されたインストール済みモジュールのいずれかです。
プロジェクト名の由来?
D&D の呪文、True Seeing です。