
ペンテスター向けのWin32およびカーネル悪用テクニック
ペンテスターとレッドチーマーのための Win32 およびカーネルを悪用するテクニック集。作者: @UVision と @RistBS
開発モード有効、どんな助けでも歓迎です :)
DOS_HEADER : PE の最初のヘッダー。MS DOS メッセージ ("This programm cannot be run in DOS mode....")、MZ ヘッダー (PE を識別するマジックバイト)、およびスタブコンテンツを含む。IMAGE_NT_HEADER : PE ファイルシグネチャ、File Header、Optionnal Header を含む。SECTION_TABLE : セクションヘッダーを含む。SECTIONS : ヘッダーではありませんが、知っておくと便利です。これらは PE のセクションです。詳細 : https://www.researchgate.net/figure/PE-structure-of-normal-executable_fig1_259647266
IAT と ILT の絶対アドレスを取得するための簡単な PE 解析:
GetModuleHandleA(NULL);BaseAddress+PIMAGE_DOS_HEADER.e_lfnanew (NT_HEADER の RVA)OptionnalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]IMAGE_DATA_DIRECTORY.VirtualAddress (IMAGE_IMPORT_DIRECTORY の RVA)BaseAddress + IMAGE_IMPORT_DIRECTORY.VirtualAddress (IMAGE_IMPORT_DESCRIPTOR の RVA)EAT は、PE によってエクスポートされるすべての関数を解決し、DLL も解決します。これは IMAGE_EXPORT_DIRECTORY 構造体で定義されています:```c
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name; // name of DLL
DWORD Base; // first ordinal number
DWORD NumberOfFunctions; // number of entries in EAT
DWORD NumberOfNames; // number of entries in (1) (2)
DWORD AddressOfFunctions; // RVA EAT and contains also RVA of exported functions
DWORD AddressOfNames; // Pointer array contains address of function names
DWORD AddressOfNameOrdinals; // Pointer array contains address of ordinal number of functions (index in AddressOfFunctions)
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
EAT は「実際の」PE ではなく、DLL 内で定義されていることに注意してください(PE は、ロードされた DLL の EAT を使用して、使用したい関数へのポインタを解決します)。
### 関数アドレスを解決する
**関数アドレスを使用する**
何を待っているのですか?この関数を見つけてください!
**序数を使用する**
序数とは、`AddressOfFunctions` 配列内の対応する関数アドレスへの**インデックス位置**です。これを使用して、**関数の正しいアドレスを取得**できます。例は次のとおりです:
与えられた序数 3 を使って、対応するアドレス(Addr4)を見つけてみましょう。
- **AddressOfFunctions** : *Addr1 Addr2 Addr3 Addr4 .... AddrN*
- **AdressOfNameOrdinals** : *2 5 7 3 ... N*
探しているアドレスは(0 から数えて)3 番目の位置にあり、序数はこのアドレスの**インデックス**に対応しています。
**関数名を使用する**
AddressOfNames 配列の N 番目の要素は AddressOfNameOrdinals 配列の N 番目の要素に対応しています。つまり、名前を指定すれば対応する序数を取得でき、その番号を使って関数アドレスを特定できます。
## インポート アドレス テーブル (IAT)
- PE ローダーは、どの関数にどのアドレスが対応するのかを把握していません。そこで、IAT に助けてもらいましょう。
- IMAGE_IMPORT_DIRECTORY 構造体で定義されています:```c
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
DWORD Characteristics;
DWORD OriginalFirstThunk; // RVA to ILT
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name; // RVA of imported DLL name
DWORD FirstThunk; // RVA to IAT
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
まとめとして、IATは、読み込まれたDLL(ntdll、kernel32...)からPEによってインポートされるいくつかの関数へのポインタを含むテーブルである。
詳細なコード例はこちら: https://github.com/matthieu-hackwitharts/Win32_Offensive_Cheatsheet/blob/main/miscellaneous/iat_parser.cpp
PEによってインポートされるすべてのDLLは、それぞれ独自のILTを持つ。``` Absolute address of ILT = BaseAddress + OriginalFirstThunk (IAT)
インポートされたDLL内のすべての関数名が含まれています。
<br>
## SeDebug特権を有効にする
**SeDebug** 特権は、Windowsの特権リストすべての中で「最も欲しい」特権です。これにより、認可された任意のプロセスを「デバッグ」でき、```PROCESS_ALL_ACCESS``` 権限を持つハンドルを開くなど、いくつかの攻撃的な操作に変換できます。
ユーザーモードで有効にするには、次のような関数を使用する必要があります。```cpp
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;