

DllShimmer は元の DLL を解析し、エクスポートされた関数に関する情報(名前、序数、フォワーダー情報)を抽出します。この情報に基づいて、DllShimmer はボイラープレート C++ ファイル (.cpp) を作成します。生成されたファイルを使用すると、プログラムの通常の動作を妨げることなく、元の DLL からエクスポートされた各関数に独自のコードを追加できます。 DllShimmer は関数シグネチャに依存しないため、リバースエンジニアリングやインストルメンテーションは必要ありません(詳細は「制限事項」を参照)。
生成される 2 つ目のファイルは .def ファイルで、コンパイル後にプロキシからエクスポートされるすべての DLL が、元の DLL と同じ名前と序数を持つことを保証します。
コンパイル後、プロキシ DLL の EAT は元の DLL の EAT の正確なコピーになります。エクスポートされた関数のすべての名前と序数が一致し、フォワーダー関数もフォワーダーとしてエクスポートされます。 DllShimmer は(ほとんどのツールのように)すべての関数を明示的にフォワーダー化するわけではないため、まったく新しい不審な EAT 構造を作成することはありません。
Go ソースコードをコンパイルするか、コンパイル済みバイナリをダウンロードしてください。
依存関係:
x86_64-w64-mingw32-g++x86_64-w64-mingw32-dlltool例:
# Backdoor version.dll (proxy to absolute path)
./DllShimmer -i version.dll -o project/ -x "C:/Windows/System32/version.dll" -m
# Backdoor random chat.dll (proxy to relative path)
./DllShimmer -i chat.dll -o project/ -x "lib/chat2.dll" -m
# Backdoor random app.dll (static linking to the original DLL)
./DllShimmer -i app.dll -o project/ -x "app2.dll" -m --static
パラメータ:
-i / --input <path> [必須]
バックドアを仕込みたい元の DLL。
-o / --output <path> [必須]
DllShimmer が生成したすべてのファイルを保存するディレクトリのパス。
-x / --original <path> [必須]
動的リンク(デフォルト)の場合、ターゲットシステム上でプロキシ DLL が元の DLL を見つけるパスを指定します。
静的リンク (--static) の場合は、元の DLL の名前だけを指定します。Windows のデフォルトの読み込み順序に従って検索されます。
-m / --mutex [オプション]
このオプションを有効にすると、ソースファイルにミューテックスが追加され、1 回のプログラム実行中にバックドアが複数回実行されるのを防ぎます。元の関数はすべて正常に動作し続けます。
--static [オプション]
プロキシ DLL (IAT) と元の DLL (EAT) の間で静的リンクを有効にします。これにより、出力ディレクトリに追加の .lib ファイルが生成され、静的コンパイル時に元の DLL として機能します。
この手法には、動的リンクと比較していくつか重大な制限があります:
ただし、静的リンクはシナリオによってはよりステルス性が高く、自然な場合があります。
デフォルト:DllShimmer は常に LoadLibraryA() と GetProcAddress() 関数を使用した動的リンクを使用します。
--debug-file <path> [オプション]
デバッグログをファイルに保存します。ログはプログラムの実行中に継続的にファイルに書き込まれます。選択した場合、ログは STDOUT に出力されません。
デフォルト:DllShimmer は常にデバッグログを STDOUT に書き込みます。
デバッグ出力の例:

トラブルシューティングを始める前に:
--static) を使用していないことを確認してください。動的リンク(デフォルト)の方がデバッグしやすいです。--debug-file)。.cpp ファイルに、元の DLL のすべてのエクスポート関数が表示されません。元の DLL で「フォワーダー」として定義されている関数は .cpp ファイルに含まれません。ただし、.def ファイルでは確認できます。コンパイル後も、元の DLL とまったく同じようにエクスポートされます。
場合によっては、-x パラメータで理論的には正しい相対パスを指定したにもかかわらず、プロキシ DLL が元の DLL の読み込み時にエラーコード 126 を表示することがあります。なぜ機能しないのでしょうか?!?
DLL は Current Directory 内で検索されます。98% のケースでは、これは単にメイン EXE ファイルの場所ですが、SetCurrentDirectoryW() などを使用して Current Directory を任意に変更するプログラム(ほとんどが古いレガシープログラム)があります。メインプログラムはこの変更を認識しているため、プロキシ DLL を正しく読み込みますが、あなたはこの変更に気づかず、元の DLL を相対的に読み込もうとします。一方、プログラムは変更された Current Directory 内でそれを検索します。
このルールは、元の DLL の静的読み込みと動的読み込みの両方に適用されます。残念ながら、静的リンクではデバッグ情報がないため、この問題を検出するのははるかに困難です。システムローダーが失敗して終わりです。これが、常にデフォルトの動的リンクを最初に使用することをお勧めする理由です。
動的リンクの場合、2 つのオプションがあります:
-x パラメータのパスを新しい Current Directory の状況に合わせて調整します。Current Directory を動的に変更して、目的の場所で DLL を検索します。静的リンクの場合、実際には 1 つのオプションしかありません:
Current Directory に移動します。