1.三つのDLLのロードタイミング:
- 入力テーブルDLL(静的入力)にロードされたプロセスの作成
- LoadLibraryのオートローディング(動的ローディング)を呼び出すことによって
- プリロードされたシステム
介入プロセス入力テーブルを介して、DLLのローディング対象
表1の静的改変PEの入力方法(試験方法メモ帳)
- 準備:どこでも機能メッセージ(MsgDLL、)あなた自身を準備します。
#include " STDAFX.H " BOOL APIENTRYのDllMain(HMODULE HMODULE、 DWORD ul_reason_for_call、 LPVOID lpReserved ) { 場合(ul_reason_for_call == DLL_PROCESS_ATTACH) { のCreateThread(NULL、0、ThreadShow、NULL、0 、NULL); } 戻りTRUE。 } DWORD WINAPI ThreadShow(LPVOID lpParameter) { チャー szPath [MAX_PATH] = { 0 }。 チャー szBuf [ 1024 ] = { 0}; // ホストプロセスのパス取得 GetModuleFileNameは(NULL、(LPWSTR)szPath、MAX_PATH)を、 はsprintf(szBuf、" DLLがプロセス内に注入された:%S \ T [%D = PID] \ N- " 、szPath、GetCurrentProcessId( )); //は3通りの方法でその存在を示し // 1. メッセージボックス(NULL、(LPWSTR)szBuf、" DLLの有無" 、MB_OK); // 2. のprintf(" %S \のN- " 、szBuf)。 // 3 のOutputDebugString((LPWSTR)szBuf); 戻り 0 ; }
意味パラメータ:
①hModuleパラメータ:DLLのインスタンスは、それ自体にポイントを扱います。
②ul_reason_for_callパラメータ:DLLが呼び出された理由を示して、あなたは以下の4つの値を持つことができます。
1. DLL_PROCESS_ATTACH:
DLLは>> <<呼ばれるDllMain関数で、その結果、プロセスを呼び出した最初のとき、
一方ul_reason_for_call値DLL_PROCESS_ATTACH、
同じプロセスが再び後でこのDLLを呼び出すと、オペレーティングシステムは、DLLの使用頻度が増加します
DLL_PROCESS_ATTACH DllMain関数の呼び出しは、DLLを使用しません。
2.DLL_PROCESS_DETACH:
DLLがプロセスのアドレス空間からマップされていない場合は、システムが渡され、そのDllMainの、ul_reason_for_call値がDLL_PROCESS_DETACHで呼び出します。
★コールのTerminateProcessため、プロセスの終了した場合、システムは、DLLのDllMain DLL_PROCESS_DETACH関数を呼び出すために使用されることはありません。これは、DLLがプロセスの終了前に、クリーンアップ作業を実行する機会がないことを意味します。
3.DLL_THREAD_ATTACH:
プロセスがスレッドを作成するとき、すべてのDLLファイルイメージをプロセスのアドレス空間にマッピングされ、現在のシステムを表示し、
そして、値のDLL_THREAD_ATTACHと機能のDLLをDllMainの呼び出し。
DLLのDllMain関数の実装に責任を新しく作成されたスレッド、
すべてのDLLは、通知の処理を終了したときにのみ、システムは唯一のスレッドがそのスレッド関数の実行を開始できます。
4.DLL_THREAD_DETACH:
スレッドは、スレッドを終了するExitThreadを呼び出す場合、(スレッド関数が戻ると、システムが自動的にExitThreadを呼び出します)
現在のすべてのシステムDLLファイルイメージがプロセス空間にマッピングされたビュー、
そしてDllMain関数を呼び出すDLL_THREAD_DETACHと、
スレッドレベルのクリーンアップを実行するために、すべてのDLLを通知します。
★注意:システムがのTerminateThreadを呼び出すためのスレッドの終了をスレッドがある場合は、
DLL_THREAD_DETACH値システムは、すべてのDLLのDllMain関数を呼び出すために使用されることはありません。
③lpReservedパラメータ:予約
- ステップ2:私たちのエクスポート機能を格納するための十分なスペースがあるかどうかを確認-----「(PEフォーマットの知識)
- スペースが不足している場合)、その後、我々はストレージの場所を追加するセクションまたはセクションを拡張するために必要。
- メモ帳には、セクションを展開し、最後の方法を取るために、私はここにいる、私たちのエクスポート機能を保存することはできません
PEフォーマットした後は、インポートテーブルRVA 00007604のディレクトリエントリ内のデータを見ることができます
だから我々は、オフセットFOAファイルに変身RVAについて話をするためにここにいる:0x7604 -0x1000(仮想アドレス)+ 0x400(生アドレス)= 0x6a04 ---「PEの知識は、重い学校PEを理解していません
その後、私はここで使用されるオープンメモ帳の16進ソフトウェアは、010エディタです。
まず、我々は、20バイトのインポートテーブルの構造を見ることができるで16時間、入力テーブル、ダイナミックリンクライブラリDLLの通話データに対応する各20バイト(Image_Import_Directory):
インポートテーブルと、それは0x14のすべてのゼロサイズのセットに終了タグで終了するまで連続しています
示されるように、0x6a04を標的とする、それが後端マークサイズ0x14にあります
次に、我々は最後のセクションゾーンの展開になります。
新しいアドレスにオリジナルのインポートテーブルを移動(コピーして、新しいアドレスに貼り付けます):
あなたは(私たちは私たち自身の構造をして、部屋を作るために、元のインポートテーブル領域を貼り付けた後にクリアすることに注意してください)、貼り付け、元のインポートテーブル領域の新しいOriginalFirstThunk、名前とFirstThunk構造上に構築された後は
まずクリア
その後、私たちOriginalFirstThunk、名前や構造を構築FirstThunk
PEファイルがロードされる前に、OriginalFirstThunkとFirstThunkはIMPORT_BY_NAMEを指しています
私たちが知っているような構成によれば:
DLLNAME RawOffset = 0x6A14 RVA = 0x6A14 -0x400(生アドレス)+ 0x1000を(仮想アドレス)= 0x7614
IMPORT_BY_NAME RawOffset = 0x6A20 RVA = 0x6A20 -0x400(生アドレス)+ 0x1000を(仮想アドレス)= 0x7620
手動で問題に注意を払う必要があり、データのバイト順に入力します。
剛構造は、次に、充填し、二オフセット名前は、新しいインポートテーブル構造を埋めます
OriginalFirstThunk:RawOffset = 0x6a04 RVA = 0x6a04 -0x400(生アドレス)+ 0x1000を(仮想アドレス)= 0x7604
FirstThunk:RawOffset = 0x6a0c RVA = 0x6a0c -0x400(生アドレス)+ 0x1000を(仮想アドレス)= 0x7620
DLLNAME RawOffset = 0x6A14 RVA = 0x6A14 -0x400(生アドレス)+ 0x1000を(仮想アドレス)= 0x7614
編集後、我々は、PEファイルのヘッダ情報を修正します。
- 場所にディレクトリテーブルのポイントを入力します。
- FirstThunk - 「書き込み可能なプロパティ
第一は、位置への入力テーブルディレクトリ点を補正します。
RVAテーブルは010に導入された検索するには:
それは最後の1の場所で私たちの新しい代替場所の値を指すように変更されました:
メモリオフセット= 0XB000 + 0X8000 = 0X13000
ファイルオフセット= 0x8400 + 0x8000で= 0x10400
起因FirstThunkインポートテーブルアレイ装置の元の位置の使用、RVAながら元の位置は、開始位置とセクションのオフセットに応じて、0X7604である、セクション、テキストセクションに属し、元のプロパティのセクションが0X60000020であることを決定することができます次のように書き込み属性が定義されています
DEFINE IMAGE_SCN_MEM_WRITE# 0x800000000 // セクションでは、書き込み可能です
0X 60000020 +は0x80000000 = 0xE0000020
その後、新しいセクションは、元の性質であるプラスプロパティの値は0xE0000020です
ここまでは、変更を保存し、改訂を完了しています
メモ帳改定の結果に何のメッセージボックスポップを実行していません!
これはIMAGE_IMPORT_DESCRIPTORは、エントリがオリジナルの事前バインドされている変更を意味し、-1であるから0xFFFFFFFFにTimeDateStampを定義しているため、システムが事前にバンドルされ有効であることが見出さ検出した場合、それは入力テーブルがロードされた処理に行くことはありませんので、我々単に0x1B0は0x1B8コンテンツに保存するために再びクリアされます
私たちは本当に私たちのMsgDll.dllを読み込ま見ることができます