ページの先頭です


ページ内移動用のリンクです

  1. ホーム
  2. IIJの技術
  3. セキュリティ・技術レポート
  4. Internet Infrastructure Review(IIR)
  5. Vol.54
  6. 2. フォーカス・リサーチ(1)mac_aptプラグインの作成(前編)

Internet Infrastructure Review(IIR)Vol.54
2022年3月29日発行
RSS

目次

2. フォーカス・リサーチ(1)

mac_aptプラグインの作成(前編)

2.1 mac_aptとは

Windowsにおけるデジタルフォレンジックはフリーまたはオープンソースのツールだけで、ほとんどのアーティファクトを解析できるほど充実しています。一方、Windowsと同様にデスクトップOSとして多く使用されているmacOSでは、フリーやオープンソースのツールは言わずもがな、商用製品ですらWindowsと比べると、その数は少ないのが現状です。

このような状況はOSのシェアやデジタルフォレンジック市場における必要性が結果として現れたものであると思われます。しかし、ここ数年でオープンソースのmacOS用フォレンジック解析ツールにも実用に足るだけの機能を実装したものがリリースされています。筆者が個人的に特に注目しているツールがmac_apt(注1)です。

このツールはmacOSフォレンジック解析フレームワークとして開発されており、様々なアーティファクトを40以上のプラグインで解析することができます。また、独自のAPFSとHFS+のファイルシステムパーサーを実装しており、ディスクイメージをマウントせずに直接解析することができます。このため、ディスクイメージをOSにマウントして解析することを前提としたツールに比べ、ファイルシステムドライバーのインストールが不要となり、解析者が使用するコンピュータのOSに依存せずに解析することができます。その上、RAWやE01のようなデファクトスタンダードのディスクイメージフォーマットだけではなく、AFF4やSPARSEIMAGEなど比較的マイナーなフォーマットのディスクイメージもサポートしています。これらは商用のフォレンジックツールがディスクイメージの保存フォーマットとして採用しています。

ディスクイメージは変換ツールによって様々なフォーマットに変換可能であるため、必ずしも解析ツールが多くのフォーマットをサポートしている必要はありません。しかし、近年のコンピュータのディスクイメージの容量は数百GB以上であることが多く、ディスクイメージの変換には長い時間と多くのディスクスペースが必要となります。したがって、ディスクイメージを変換することなく解析できることは、解析者にとって大きなメリットとなります。

mac_aptは多数のプラグインを実装しており、主要なアーティファクトの多くを解析することができます。しかし、作者のYogesh Khatri氏がほぼ一人で開発していることもあり、すべてのアーティファクトをサポートすることはできません。

このような場合、mac_aptの開発リポジトリにIssueを登録して有志がプラグインを実装してくれるのを待つ、というのが一般的かもしれません。しかし、アーティファクトのデータ構造をある程度、把握できているのであれば、自分でプラグインを実装することを検討しても良いのではないでしょうか。前述したように、mac_aptはフォレンジック解析フレームワークとして開発されているからです。

少々前置きが長くなってしまいましたが、今回はmacOS用フォレンジック解析フレームワークであるmac_aptプラグインの作成の基本について解説します。なお、プラグイン作成に関する公式のドキュメントなどは用意されていないため、実装されているプラグインのコード及び筆者がプラグインを作成したときに得られた知見を基に解説します。また、mac_aptはPythonで記述されていますが、Pythonの用語などの解説は行いません。

2.2 macOSフォレンジックで重要なファイルフォーマット

プラグインの作成に入る前に、macOSフォレンジックで解析対象となることが多いファイルフォーマットについて触れておきます。macOSとそのアプリケーションは、設定や履歴を保存するため、随所でProperty List (plist)とSQLiteを使用しています。そのため、必然的にアーティファクトファイルも、どちらかのフォーマットであることが多くなります(フォレンジック解析では、設定や履歴を解析する場合が多いためです)。

plistは主にOSやアプリケーションの設定値や履歴などの簡単なデータを保存する目的で使われています。役割的には、Windowsのレジストリに相当しますが、アプリケーションごとに作成されるため、ファイルシステム内の様々な場所に存在しています。初期のplistファイルはXMLフォーマットが使われていましたが、現在はバイナリフォーマットがデフォルトで使用されています。コマンドラインで内容を確認する場合、plutilコマンドで内容を確認することができます。図-1はドックに登録されているアプリケーションの設定が保存されるcom.apple.dock.plistをplutilコマンドで表示した例です。

図-1 plistの例(com.apple.dock.plist)

SQLiteはplistと同様に設定値や履歴などの記録にも使われますが、送受信データのblobなど、少し大きなデータの保存にも使われます。Chromeなど様々なアプリケーションでも使用されており、最近はWindowsでも一部のアーティファクトはSQLiteで保存されます。データを見る場合、DB Browser for SQLite(注2)を使うのが便利です。図-2はWebブラウザなどでファイルをダウンロードした際に記録されるQuarantineに関する情報が保存されるcom.apple.LaunchServices.QuarantineEventsV2をDB Browserで読み込んだ例です。

図-2 SQLiteの例(com.apple.LaunchServices.QuarantineEventsV2)

2.3 mac_aptプラグインの構造

2.3.1 デモ用プラグイン

デモ用プラグインとして、_demo_plugin.pyというファイルがmac_aptのpluginsフォルダに用意されています。このプラグインは「/System/Library/CoreServices/SystemVersion.plist」というファイルを読み込んで、ProductVersionに設定されている値を取得し、画面に表示すると共に解析結果をファイルに保存します。

簡単な解析しか行いませんが、プラグインの構造を理解するのにちょうど良いと思われるため、これを例として一般的なプラグインの処理の流れを見てみましょう。

2.3.2 プロパティ

プラグインの先頭付近(モジュールインポートの直後)には、プラグインのプロパティを設定する箇所があります(図-3)。それぞれの意味については、表-1を参照してください。

図-3 プラグインのプロパティの設定

表-1 プラグインのプロパティの意味

これらは基本的にプラグイン作者が任意に設定することができますが、__Plugin_Nameはプラグインの識別に使われるため、ユニークな名前にしなければなりません。また、__Plugin_Modesは、そのプラグインがサポートするOSの種類(MACOSまたはIOS)を指定します。なお、このプロパティでは「ARTIFACTONLY」というキーワードも指定することができますが、これはエクスポートされたアーティファクトファイル単体の解析をサポートすることを表す場合に指定します。

2.3.3 エントリーポイント

すべてのプラグインは「Plugin_Start()」または「Plugin_Start_Standalone()」、「Plugin_Start_Ios()」という関数が最初に呼び出されます。mac_aptのコマンドと呼び出されるプラグインのエントリーポイントの対応は表-2を参照してください。

表-2 mac_aptの各コマンドと呼び出されるエントリーポイント

デモ用プラグインでは、Plugin_Start()とPlugin_Start_Standalone()の2つのエントリーポイントが実装されています。これはプロパティの__Plugin_Modesの設定とも合致しています(Plugin_Start_Ios()はpassのみが書かれており、__Plugin_ModesにもIOSは設定されていません)。次にそれぞれのエントリーポイントの処理内容の詳細を確認してみましょう。

Plugin_Start()

Plugin_Start()(図-4)は引数として、mac_infoを持っています。このオブジェクトは解析対象ディスクイメージから取得したmacOSの基本的な情報(OSバージョンやユーザリストなど)やディスクイメージ内のファイルにアクセスするための基本的なメソッドを持っています。

図-4 Plugin_Start()関数

デモ用プラグインでは、mac_aptが動作しているOSの種類と解析対象のmacOSのバージョンを画面出力しています(40~41行目)。その後、アーティファクトファイルのパスを設定し、Process_File()関数でアーティファクトファイルからバージョン番号を取得し画面出力しています(44~46行目)。次にアーティファクトファイルをディスクイメージからエクスポートし、プラグインと同じ名前のフォルダに保存します(49行目)。そして、最後にWriteMe()関数で解析結果を保存します(52行目)。

このように、エントリーポイントではアーティファクトファイルのパスを設定した後、解析を行う関数及び解析結果を保存する関数の呼び出しが主な処理内容となります(Process_File()、WriteMe()の詳細については後述します)。実際に解析に使用される他のプラグインも同じ流れになります。

デモ用プラグインで解析を行うアーティファクトのファイルパスは固定ですが、アーティファクトによってはファイルパスが未確定の場合があります。例えば、アーティファクトファイルがユーザのホームディレクトリ以下にある場合、ファイルパスにユーザ名が含まれるため、ファイルパスは一定ではありません。このような場合、mac_aptに用意されたメソッドを使って、ディスクイメージ内のディレクトリやファイルのリストを取得して、動的にアーティファクトファイルのパスを構築しなければなりません。

Plugin_Start_Standalone()

Plugin_Start_Standalone()(図-5)は第1引数として、mac_apt_artifact_only.pyのコマンドラインで指定されたアーティファクトファイルがlistオブジェクトとして渡されるため、これを利用して、アーティファクトを順次、処理することが可能です(96行目)。

図-5 Plugin_Start_Standalone()関数

ただし、アーティファクトが複数のファイルで構成されているような場合や、設定によってアーティファクトファイルのパスが未確定になる場合は、やはり動的にアーティファクトファイルのパスを構築する必要があります。アーティファクトファイルはmac_aptを実行しているOSのファイルシステム上に存在するため、Python標準のosモジュールを使用して、ファイルリストなどを取得できます。

デモ用プラグインではファイルパスが「SystemVersion.plist」で終わっている場合、mac_aptが提供しているCommonFunctionsモジュールのReadPlist()メソッドでファイルをパースしています(100行目)。パースに成功した場合、OSバージョンを取得した後、WriteMe()関数で解析結果を保存します(101~106行目)。Process_File()関数は呼び出されていませんが、Plugin_start()と処理の流れはほぼ同じであることが分かります。

なお、ReadPlist()メソッドによる、plistファイルのパース結果(2番目の返り値)はdictionaryオブジェクトになります。

2.3.4 デモ用プラグインのその他の関数
Process_File()

SystemVersion.plistをパースする関数です(図-6)。第2引数で渡されたアーティファクトファイルをmac_infoオブジェクトのReadPlist()メソッドでパースします(60行目)。成功した場合、後述するGetMacOsVersion()関数を呼び出し、バージョン番号を取得して、返り値とします(61~65行目)。

図-6 Process_File()関数

mac_infoオブジェクトのReadPlistメソッドはCommonFunctionsモジュールのそれと同じく、plistのパース結果をdictionaryオブジェクトとして返します。

GetMacOsVersion()

パースされたplistのデータからOSバージョンを取得し、返り値とします(図-7)。

図-7 GetMacOsVersion()関数

WriteMe()

解析結果をファイルに保存する関数です(図-8)。col_infoは解析結果を保存する際のカラムの定義です(77行目)。定義にはtupleオブジェクトのlistを使います。tupleの1つ目の要素がカラム名で、2つ目の要素がカラムの型になります。型は多くの場合、「DataType.TEXT」または「DataType.INTEGER」を指定します。デモ用プラグインの場合、最初のカラムは「Version info」というカラム名でテキスト型になり、2つ目のカラムは「Major」というカラム名で整数型になります。

図-8 WriteMe()関数

dataは保存するデータ(listオブジェクト)になります(79行目)。このとき、リストの長さはカラムの定義と同じである必要があります。

DataWriterオブジェクトはmac_aptのコマンドラインで指定された保存先に、指定されたファイル形式で解析結果を保存するためのオブジェクトです(82行目)。第1引数は保存先のフォルダなどの設定情報、第2引数はテーブル名(SQLite形式で保存する場合)、第3引数はカラム定義、第4引数はアーティファクトファイルパスになります。しかし、第4引数は使用されないため、空文字列を渡しても問題ありません。DataWriterオブジェクトのWriteRow()メソッドで実際にデータを書き込みます。

ただし、90行目のコメントにあるように、上記の処理はWriteList()関数を使って1行で行うこともできます。他のプラグインを参照すると、ほとんどのケースでWriteList()関数を使っているようです。なお、第1引数はデータの詳細を表す文字列ですが、ログに出力されるのみでファイルには保存されません。また、第6引数はWriteList()関数内部でDataWriterオブジェクトの第4引数として渡されるため、空文字列で問題ありません。

2.3.5 関数等の命名規則

エントリーポイントの関数名は固定されていますが、それ以外の解析を行う関数と解析結果を保存する関数の名前をプラグインの作者が決める必要があります。前述したようにプラグインの書き方については、特にドキュメントなどは用意されていませんが、既存のプラグインを見るとほとんどの関数名はパスカルケースで記述されているようです。また、変数名についてはスネークケースで記述されています。他のプラグインと統一感を持たせるのであれば、これらを多少意識すると良いと思われます。

なお、解析を行う関数名は「ProcessXxxx()」や「ParseXxxx()」となっていることが多いようです。また、解析結果を保存する関数名は「PrintAll()」で統一されています(デモプラグインはWriteMe()になっていますが)。この関数は3つの引数を持ちます。第1引数は保存する解析結果のlistオブジェクト、第2引数は保存先や保存ファイルフォーマットなどの設定が記録されたオブジェクト(mac_info.output_params)、第3引数は最終的にWriteList()関数の第6引数として渡されるため、空文字列が設定される場合がほとんどのようです。

2.4 mac_aptが未対応のアーティファクトの探し方

前述したように、mac_aptはほぼ作者一人でメンテナンスされているため、未対応のアーティファクトも存在します。そのため、他の解析ツールの調査やmacOSセキュリティ関連の記事を読んでいるときに、mac_aptが対応していないアーティファクトを見かけることがあります。

例えば、パーシステンスとしてドックに登録されているアプリケーションのパスを攻撃者が用意したプログラムのパスに差し替える手法に関する記事(注3)を読んだ際に「~/Library/ Caches/<Application Bundle ID>/Cache.db」はmac_aptでは解析されないことに気が付きました。mac_aptが該当するアーティファクトに対応しているか否かはプラグインリストを確認するか、または、mac_aptのソースコードをアーティファクトファイルの名前で検索するのが良いでしょう。

実機のCache.dbを確認してみるとHTTPだけではなく、HTTPSによる通信も記録されていることが分かりました(図-9)。それだけではなく、HTTPリクエストメソッドやHTTPステータス、HTTPヘッダ、レスポンスボディも記録されていることが確認できました(図-10、図-11)。このような情報はフォレンジックを行う際に非常に有用であると考えられるため、プラグインの実装を検討するのは十分に価値がありそうです。

図-9 cfrul_cache_responseテーブル

図-10 cfurl_cache_receiver_dataテーブル

図-11 cfurl_cache_blob_dataテーブル

Cache.dbに保存されているデータの詳細や、このアーティファクトファイルを解析するプラグインの実装については、次号のIIRで解説します。

  1. (注1)macOS(& ios)Artifact Parsing Tool(https://github.com/ydkhatri/mac_apt)。
  2. (注2)DB Browser for SQLite(https://sqlitebrowser.org/)。
  3. (注3)Are You Docking Kidding Me?(https://posts.specterops.io/are-you-docking-kidding-me-9aa79c24bdc1)。

小林 稔

執筆者プロフィール

小林 稔(こばやし みのる)

IIJセキュリティ本部セキュリティ情報統括室フォレンジックインベスティゲーター。
IIJ-SECTメンバーで主にデジタルフォレンジックを担当し、インシデントレスポンスや社内の技術力向上に努める。
Black HatやFIRST TC、JSAC、セキュリティキャンプなどの国内外のセキュリティ関連イベントで講演やトレーニングを行う。

2. フォーカス・リサーチ(1) mac_aptプラグインの作成(前編)

ページの終わりです

ページの先頭へ戻る