python-registry を使用して Windows レジストリを破棄する

最近、Windows レジストリに常駐するフォレンジック アーティファクトを深く掘り下げたいと思いました。この作業をより面白くするために、お気に入りのオペレーティング システムである Linux にネイティブなツールのみを使用することに挑戦しました。しかし、Perl の Win32::Registry 以外に Windows レジストリ フォレンジック用のオープンなクロスプラットフォーム ツールがほとんどないため、すぐにがっかりしました。そこで、私は、お気に入りのプログラミング言語である Python を使用して、この空白を埋めるツールを作成しました。 Python-registry はこの取り組みの成果であり、Windows レジストリ ファイルへの便利なアクセスを提供します。純粋な Python であるため、すべての主要なオペレーティング システムで使用できます。

バックグラウンド

Windows レジストリ ファイル形式は、HBIN ブロックと呼ばれる一連の割り当て単位で構成されています。各ブロックは、フォーマット内のコンテンツの基本単位を形成するセルに分割されます。セルには純粋なバイナリ データが含まれる場合がありますが、多くのセルはメタデータの格納のみに使用されます。これらには、nk-records (Windows レジストリのツリー状構造のノード)、lf-records (ノードの子を指す)、および vk-records (単一のレジストリ値を記述する) が含まれます。 Python-registry は、これらの低レベル構造を解析して読み取る RegistryParse モジュールの一連のクラスを公開します。 1 つの RegistryParse クラスが各構造にマップされ、それぞれがメタデータやその他の参照構造にアクセスするための一連の便利なメソッドを公開します。

たとえば、Windows レジストリ ファイルが python-registry によって読み込まれると、HBIN ブロックを選択し、各セルを反復処理できます。次のコード リストは、フリー セルを特定する方法を示しています。フリー セルは抽出される可能性があるため、削除されたレジストリ キーを検索できます。

f = open(“NTUSER.DAT”) buf = f.read() regf = RegistryParse.REGFBlock(buf, 0, false) regf.hbins() 内の HBIN: HBIN.cells() 内のセル: if cell. is_free(): print “オフセット 0x%x の割り当てられていないセル” % (cell.offset())

実際には、Windows レジストリ ファイルを解析するライブラリはほとんどなく、基盤となる構造との対話を促進するライブラリはさらに少数です。進取の気性に富んだ法医学者は、python-registry を使用して、レジストリ キーの回復に関する将来の研究を可能にする機会を認識する必要があります。

低レベルの解析クラスに加えて、python-registry は、Microsoft Windows API によって公開されるものと同様の高レベルのインターフェイスを提供します。レジストリ モジュールの抽象化レイヤーは、アロケーション ユニットとレコードに関するユーザーの詳細を削除し、見覚えのある RegistryKey および RegistryValue クラスを提供します。 Windows レジストリ ファイルが読み込まれると、RegistryKey クラスのインスタンスがツリー構造に編成され、RegistryValues のリストに関連付けられる場合があります。このツリーは、対応する Windows レジストリを RegEdit で調べた場合に表示される構造を反映しています。

python-registry によるフォレンジック

Harlan Carvey のRegRipperと同様に、python-registry はフォレンジック分析に特に適しています。 Python-registry は、ライブ ハイブではなく、レジストリ ハイブ ファイルと直接連携するため、取得後にフォレンジック ワークステーションで簡単に使用できます。

最近、私は python-registry を使用して、Mandiant のニューヨーク市オフィスからのインシデント対応中に侵害されたサーバーを特定しました。別のシステムで見つかったリモート ログイン イベントに基づいて、システムがマルウェアに感染している疑いがあり、さらに詳しく調査したいと考えました。 Mandiant Intelligent Response® (MIR) を使用して、C:WINDOWSsystem32configsoftware を含むレジストリ ハイブ ファイルをリモート システムから取得し、Linux ラップトップにダウンロードしました。

次に、python-registry を使用して次の 10 行の Python スクリプトを作成し、各キーとその最終更新日を出力し、疑わしい時間枠でフィルタリングしました。

from Registry import Registry def rec(key): if MIN_DATE < key.timestamp() < MAX_DATE: print “%s %s” % (key.timestamp(), key.path()) for subkey in key.subkeys() : rec(サブキー) f = open(“ソフトウェア”, “rb”) r = Registry.Registry(f) rec(r.root())

すぐに、「$$$PROTO.HIVMicrosoftWindowsCurrentVersionRun」というパスのエントリが目に留まりました。期間中に何が変更されましたか?

python-registry パッケージには、python-registry を使用して構築され、その使用法を示す一連のツールが含まれており、samples ディレクトリに含まれています。次の図に示すように、regview.py GUI ツール (RegEdit.exe に似ています) を使用して、「実行」キーを調べることができます。

python-registry

悪意のあるエントリは、攻撃者が起動時に実行するマルウェアを追加することで持続性を獲得したことを示していました。システムは確実に侵害されました。 shellbag パーサーなど、開発していた実験的なスクリプトをさらにいくつか使用してレジストリの分析を続けたところ、クライアントは満足していました。

Python-registry は柔軟で直感的なので効果的です。このパッケージは、1 回限りのスクリプトと大規模なプロジェクトの両方に簡単に統合できるライブラリです。たとえば、インタラクティブな Python コンソール (IPython など) で python-registry を使用すると、迅速なトリアージと分析に効果的な環境であることがわかりました。 Python-registry は、レジストリ値をネイティブのデータ型に変換します。これにより、データの操作が Python プログラマーにとってなじみ深いものになります。つまり、python-registry メソッド呼び出しの出力を、別の場所で開発されたデコード関数に簡単に渡すことができます。

ライブラリの使用

このライブラリを簡単に利用する方法を探ってみましょう。次のコード スニペットに示すように、すべての RegistryKey を再帰してアクションを実行できます。このユーティリティは、各 RegistryKey に関数を適用することで、このロジックをカプセル化します。

def rec(key, f): “”” すべての RegistryKey にわたって再帰し、関数 f を適用します。 key : Registry.RegistryKey f : 引数を 1 つ取る関数。 key.subkeys() のサブキー: rec(サブキー, f)

特定の RegistryKey に関するメタデータには、メソッド .name()、.path()、および .timestamp() を介してアクセスできます。 RegistryKey.subkeys() は、遅延解析された子 RegistryKey オブジェクトのリストを返します。ファイルを遅延解析することにより、python-registry はメモリ消費を削減し、初期読み込み時間を最小限に抑えます。次のコード リストは、すべてのレジストリ キー パスを出力する方法を示しています。

from Registry import Registry def print_key(key): “”” RegistryKey のパスを表示します。key : Registry.RegistryKey の戻り値: None “”” print key.path() f = open(“NTUSER.DAT”, “rb “) reg = Registry.Registry(f) rec(reg.root(), print_key)

python-registry では、Registry オブジェクトを構築することによって、Registry ファイルが最初に読み込まれます。 .root() メソッドはルート RegistryKey を返し、ほとんどの関数の開始点として機能します。または、スクリプトで .open() メソッドを使用して、パスで RegistryKey を開こうとする場合もあります。

前の例の print_key() 関数の修正版を使用して、悪意のある「Run」キーを特定することもできました。ただし、もう少し興味深いアプリケーションは、指定された文字列を含む文字列型のすべてのレジストリ値を出力することです。次のコード リストでは、文字列以外の値を除外しながら、各 RegistryKey に関連付けられた RegistryValues を反復処理します。再帰ユーティリティ rec() を使用して find_microsoft() 関数を各 RegistryKey に適用し、RegistryValue ヒットを出力します。

def find_microsoft(key): “”” 値に文字列 “microsoft” が含まれるレジストリ キーを出力します。 if v.value_type() == Registry.RegSZ または v.value_type() == Registry.RegExpandSZ]: 値が「microsoft」の場合: print key.path() rec(reg.root(), find_microsoft)

RegistryKey の .values() メソッドは、キーに関連付けられた RegistryValues のリストを返します。 RegistryValues は、概念的には (名前、タイプ、データ) のタプルであり、メソッド .name()、.value_type()、および .data() にマップされます。 RegistryValue のタイプは、0x0 から 0xB までの範囲の整数で表され、「文字列」、「バイナリ」、または「dword」などを意味する場合があります。さいわい、python-registry には、Registry.RegSZ、Registry.RegBin、Registry.RegDWord などの一連の定数が用意されており、読みやすさが向上しています。 .data() メソッドを使用して RegistryValue からデータが要求されると、最初にネイティブの Python データ型に変換されます。たとえば、文字列は ASCII または Unicode からネイティブ文字列に変換され、数値型は整数に変換されます。

ドキュメンテーション

ほとんどのクラスとメソッドは文書化されています。ただし、持っていない人のために、ソースコードは自己文書化するように書かれています。 Python-registry は Apache 2 ライセンスの下でリリースされているため、すべてのユーザーはソースの基本構造を参照することをお勧めします。 Windows レジストリ ファイル形式を実装する明確でアクセスしやすいソース コードが、形式に関する知識の中心的なリポジトリとして機能することを願っています。

結論

Python-registry は、Python および Windows レジストリ フォレンジックを楽しみ、Microsoft Windows 以外のプラットフォームを使用する可能性がある人向けに作成されたパッケージです。下位レベルの構造のそれぞれを実装しますが、1 回限りのスクリプトと実質的な処理の両方を促進する高レベルのインターフェイスも提供します。 python-registry は Apache 2 ライセンスの下でリリースされているため、すべての人がソース コードを調べてパッチを当てることをお勧めします。 python-registry のホームページはこちら、最新のソースは GitHub のこちらからダウンロードできます。

謝辞

  • http://pogostick.net/~phn/ntpasswd/WinReg.txt にある BD の「WinReg.txt」
  • http://www.sentinelchicken.com/research/registry_format にある Timothy Morgan による「The Windows NT Registry File Format」
  • http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/ にある Peter Morris による「Windows レジストリの内部構造」

参照: https://www.mandiant.com/resources/blog/parsing-registry-hives-python

コメント

タイトルとURLをコピーしました