
🔬 libaudioflinger.soを動的にフックすることで、リアルタイムVoIP音声キャプチャ(アップリンク/ダウンリンク)を実現する高度なAndroid研究ツールです。Android 14上のWhatsApp、Signal、Telegramでテストおよび構築済みです。
目標: Android の audioserver(具体的には libaudioflinger.so)をフックし、システムが 通信 モードのときにアップリンク(マイク)とダウンリンク(スピーカー)の PCM バッファを記録することで、VoIP ストリームキャプチャを実演します。
コントローラーアプリ (Android)
SELinux ポリシーの設定、ペイロード注入、データ移動、再生を管理する 9 つのボタンを備えた UI。
ペイロード (libaudiohook.so)
Dobby を使用して内部の AudioFlinger メソッドをフックし、生の PCM バッファをセッションディレクトリに書き込む C++ 共有ライブラリ(アプリプロジェクトの一部としてビルド)。
後処理
追加ツール tools/audioparser.py は、生の .ac(ダウンリンク)/.bc(アップリンク)ファイルを WAV に変換します。アプリのファイルマネージャーでも変換およびアプリ内再生が可能です。
調査ユーティリティ
初期の関数トレースとオフセット発見のための Frida スクリプト。シンボル/オフセットやその他のスニペットの解析ファイル。
この Android アプリケーションは、audioserver を介して VoIP 録音を管理するためのグラフィカルインターフェースを提供します。Android オーディオスタックをフックして VoIP アプリケーションのマイク音声とスピーカー音声をキャプチャするネイティブペイロードと統合されています。
このアプリはコントロールセンターとして機能し、必要な SELinux ポリシーの注入、監視の開始/停止、録音データの管理、キャプチャした VoIP 音声ファイルの再生を行うことができます。
メインアクティビティには 9 つのコントロールボタン があります:
ポリシー注入
audioserver とこのアプリが連携して動作するために必要な SELinux ポリシーを注入します。
監視開始
audioserver に共有ライブラリのペイロードを注入し、RecordTrack と PlaybackTrack をフックして VoIP 音声キャプチャを有効にします。プロセス注入には AndKittyInjector を使用します。
監視停止
audioserver プロセスを再起動し、監視を停止して注入されたフックを削除します。
データコピー
キャプチャした 生の PCM オーディオ を一時ディレクトリ /data/local/tmp/voip から /sdcard/voip にコピーします。
ログ表示
注入、フック、録音ステータスに関するログを表示します。
SELinux 有効化
SELinux の enforcing モードを復元します。
SELinux 無効化
SELinux を permissive モードに設定します。注入したポリシーが失敗した場合に使用します。
音声再生
カスタム VoIP ファイルマネージャー (/sdcard/voip/) を開きます:
データ削除
/data/local/tmp/voip と /sdcard/voip の両方からすべての音声データを削除します。
注: データ削除後、データを保存するためのディレクトリを作成するには、audioserver への再注入が必要です。
+----------------------+
| |
| App MainActivity |
| |
| |
|(9 Control Buttons UI)|
| |
| |
+----------+-----------+
|
|
|
+----------v-----------+
| |
| JNI Layer |
| |
| Selinux, Process Inje|
| ction, |
| |
| |
+----------------------+
この共有ライブラリは audioserver に注入され、AUDIO_MODE_IN_COMMUNICATION を検出し、事前定義されたパッケージ名のセットに対して Android オーディオスタックから直接 VoIP 音声ストリームをキャプチャします。
Dobby インラインフッキングフレームワークを使用して、libaudioflinger.so 内の重要なメソッドをインターセプトします。
アップリンク(マイク) と ダウンリンク(スピーカー) の両方の音声ストリームがキャプチャされ、後で処理するためにセッションファイルに書き込まれます。
このライブラリは、AudioFlinger および関連クラス内の以下の関数にフックをインストールします:
| 関数 | 目的 |
|---|---|
AudioFlinger::setMode | IN_COMMUNICATION モード(VoIP アクティブ)への移行/からの移行を追跡します。 |
RecordTrack::getNextBuffer | マイク(アップリンク)音声フレームをキャプチャします。 |
PlaybackThread::Track::getNextBuffer | スピーカー(ダウンリンク)音声フレームをキャプチャします。 |
Track::stop | ダウンリンクファイルを閉じて確定します。 |
RecordTrack::stop | アップリンクファイルを閉じて確定します。 |
このライブラリは、UID → パッケージマッピング に基づいてストリームをフィルタリングします。
現在監視中のアプリ:
com.whatsappcom.whatsapp.w4b (WhatsApp Business)org.thoughtcrime.securesms (Signal)org.telegram.messengerorg.telegram.messenger.webaudioserver_hook.cpp 内に他のアプリケーションを追加することもできます:
static const char* kTargetPackages[] = {
"com.whatsapp",
"com.whatsapp.w4b",
"org.thoughtcrime.securesms",
"org.telegram.messenger",
"org.telegram.messenger.web"
};
セッションディレクトリ は、audioserver への注入時に以下の場所に作成されます:
/data/local/tmp/voip/audioserver_session_<timestamp>/
ファイルは最初 .tmp 拡張子 で作成され、トラック停止時に名前が変更されます:
<packageName>_<sampleRate>_<timestamp>.bc<packageName>_<sampleRate>_<timestamp>.acセッションの例:
/data/local/tmp/voip/audioserver_session_1725389200/
├── com.whatsapp_48000_1725389201_123456.ac
├── com.whatsapp_48000_1725389201_123789.bc
ターゲットライブラリはストリップされており、libaudioflinger.so 内でメソッドがエクスポートされていないため、フックを成功させるにはメソッドやその他の関連コンポーネントの正確なオフセットが必要です。
これらのオフセットは、IDA-PRO を使用した静的解析、または frida を使用した動的解析から抽出できます。
オフセットが判明したら、offsets.h ヘッダーファイル内で置き換えることができます。
android::AudioFlinger::setMode(audio_mode_t)_ZN7android12AudioFlinger7setModeE11audio_mode_tandroid::AudioFlinger::RecordThread::RecordTrack::getNextBuffer(android::AudioBufferProvider::Buffer *)_ZN7android12AudioFlinger12RecordThread11RecordTrack13getNextBufferEPNS_19AudioBufferProvider6BufferEandroid::AudioFlinger::PlaybackThread::Track::getNextBuffer(android::AudioBufferProvider::Buffer *)_ZN7android12AudioFlinger14PlaybackThread5Track13getNextBufferEPNS_19AudioBufferProvider6BufferEandroid::AudioFlinger::PlaybackThread::Track::stop(void)_ZN7android12AudioFlinger14PlaybackThread5Track4stopEvandroid::AudioFlinger::RecordThread::RecordTrack::stop(void)_ZN7android12AudioFlinger12RecordThread11RecordTrack4stopEvこれらは静的解析から取得できます。
libaudioflinger.soandroid::AudioFlinger::ThreadBase::TrackBase::TrackBaseTrackBase::TrackBase(
IAfThreadBase *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
pid_t creatorPid,
uid_t clientUid,
bool isOut,
const alloc_type alloc,
track_type type,
audio_port_handle_t portId,
std::string metricsId)