
非逆コンパイル型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](https://github.com/alterakey/ts2-disasm-ghidra) が必要)
* iOS アプリの基本的な脆弱性スキャン (NB: [ts2-disasm-ghidra](https://github.com/alterakey/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](https://github.com/alterakey/trueseeing/issues/254) も参照):
$ docker run --rm -v $(pwd):/out ghcr.io/alterakey/trueseeing
### [uv](https://github.com/astral-sh/uv) でインストール
または、[uv](https://github.com/astral-sh/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](https://github.com/zubanls/zuban) で型チェックを行うだけでなく、IDE からの十分な支援も受けられます。詳細については、詳細セクションを参照してください。
## ビルド
以下のようにビルドできます:
$ docker build -t trueseeing https://github.com/alterakey/trueseeing.git#main
wheel をビルドするには、[flit](https://flit.pypa.io/en/stable/) を使用します:
$ flit build
ハックするには、適切なビルド環境を作成する必要があります。[uv](https://github.com/astral-sh/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](https://flit.pypa.io/en/stable/) と検証ツールチェーン ([zuban](https://github.com/zubanls/zuban) と [ruff](https://github.com/astral-sh/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` を提供します:
```python
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` を提供します:
```python
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 ファイルサポートを提供します:
```python
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)
```
次に、シグネチャ内でコンテキストのタイプをチェックし、サポートされていないコンテキストでは無視されるようにします:
```python
context = self._helper.get_context().require_type('apk2')
```
チェックが成功すると、`require_type(...)` は便利なように適切なタイプにダウンキャストしようとします。
ただし、設計上、既知のタイプ (現在は `apk`) でのみ機能します。そのため、`apk` タイプと同様に新しいコンテキストクラスに詳細なインターフェースを定義している場合、ここでダウンキャストを行う必要があります:
```python
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](https://www.dandwiki.com/wiki/SRD:True_Seeing) です。