遅延インポート関数
前回はインポート関数の列挙を解説しました。
このインポート関数は「静的」にインポートされる関数の一覧であり、
その関数を持つモジュールは起動する際同時に読み込まれます。
これに対して「動的」にインポートされる関数があり、
「遅延インポート」と呼ばれています。
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
セクションに関してはもうお馴染みの手順で、
配列の添え字だけ「IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT」として確認します。
IMAGE_DATA_DIRECTORY& tData = tNT.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
DWORD nOffset = tData.VirtualAddress;
ImgDelayDescr
インポートの時と同じ手順でセクションまで確認後、ImgDelayDescrのポインタへとキャストします。
ImpDelayDescrを使う際には「delayimp.h」をインクルードしておきます。
ImgDelayDescr* pDelay = (ImgDelayDescr*)&(pFile[nOffset - delta]);
ImgDelayDescr は以下の様に定義されています。
typedef DWORD RVA;
typedef struct ImgDelayDescr {
DWORD grAttrs; // attributes
RVA rvaDLLName; // RVA to dll name
RVA rvaHmod; // RVA of module handle
RVA rvaIAT; // RVA of the IAT
RVA rvaINT; // RVA of the INT
RVA rvaBoundIAT; // RVA of the optional bound IAT
RVA rvaUnloadIAT; // RVA of optional copy of original IAT
DWORD dwTimeStamp; // 0 if not bound,
// O.W. date/time stamp of DLL bound to (Old BIND)
} ImgDelayDescr, * PImgDelayDescr;
後は構造体の配列として定義されていますので、
rvaDLLNameが0になるまでループします。
rvaIATとrvaINTに関しては、インポートの時に解説した物と同じになりますので、
これを踏まえて列挙すると以下の様な形になります。
ただし、これまではrvaに対してdeltaとして一定の差分をとっていましたが、各ポインタに対して逐次計算をする必要があります。
#これまでは偶々同一セクションでしたが、本来は逐次全ポインタに対して確認を取った方が良さそう
inline DWORD rva2address(DWORD rva, PIMAGE_SECTION_HEADER sec)
{
DWORD delta = sec->VirtualAddress - sec->PointerToRawData;
return rva - delta;
}
for (int i = 0; pDelay[i].rvaDLLName != 0; ++i)
{
ImgDelayDescr& tDelay = pDelay[i];
LPCSTR szOrg = (char*)(rva2address(pFile[tDelay.rvaDLLName], sec));
_tprintf(TEXT("\n[%s]"), (LPCTSTR)CA2T(szOrg));
if (b64 == false)
{
IMAGE_THUNK_DATA32* pINT = (IMAGE_THUNK_DATA32*)(rva2address(pFile[tDelay.rvaINT], sec)));
IMAGE_THUNK_DATA32* pIAT = (IMAGE_THUNK_DATA32*)(rva2address(pFile[tDelay.rvaIAT], sec)));
for (int j = 0; pINT[j].u1.AddressOfData != 0 && pIAT[j].u1.Function != 0; ++j)
{
if (IMAGE_SNAP_BY_ORDINAL32(pINT[j].u1.Ordinal))
{
_tprintf(TEXT("\n\t(NONAME)[%d]"), (int)IMAGE_ORDINAL32(pINT[j].u1.Ordinal));
}
else
{
IMAGE_IMPORT_BY_NAME& tName = (*(IMAGE_IMPORT_BY_NAME*)(rva2address(pFile[pINT[j].u1.AddressOfData], sec))));
_tprintf(TEXT("\n\t%s[%d]"), (LPCTSTR)CA2T(tName.Name), tName.Hint);
}
}
}
else
{
IMAGE_THUNK_DATA64* pINT = (IMAGE_THUNK_DATA64*)(rva2address(pFile[tDelay.rvaINT], sec));
IMAGE_THUNK_DATA64* pIAT = (IMAGE_THUNK_DATA64*)(rva2address(pFile[tDelay.rvaIAT], sec);
for (int j = 0; pINT[j].u1.AddressOfData != 0 && pIAT[j].u1.Function != 0; ++j)
{
if (IMAGE_SNAP_BY_ORDINAL64(pINT[j].u1.Ordinal))
{
_tprintf(TEXT("\n\t(NONAME)[%d]"), (int)IMAGE_ORDINAL64(pINT[j].u1.Ordinal));
}
else
{
IMAGE_IMPORT_BY_NAME& tName = (*(IMAGE_IMPORT_BY_NAME*)rva2address(pFile[pINT[j].u1.AddressOfData], sec));
_tprintf(TEXT("\n\t%s[%d]"), (LPCTSTR)CA2T(tName.Name), tName.Hint);
}
}
}
}