PEファイル形式の学習(4):テーブルのインポート



Pe File Format Learning



更新:

  • インポートテーブルの構造を理解するのに役立つように、インターネット上にある記事の最後にある写真を更新しました

1。概要

テーブルのインポートは、リバース分析およびウイルス分析においてより重要なテーブルです。ウイルスを分析するときは、プログラムのインポートテーブルの内容をほぼ最初に調べて、プログラムが使用する機能を特定する必要があります。



インポートテーブルは、データカタログテーブルの2番目の要素であり、エクスポートテーブルの後に配置されます。

2.インポートテーブル分析

PEファイルのインポートテーブルの構造を見てみましょう。



struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics DWORD OriginalFirstThunk } DUMMYUNIONNAME DWORD TimeDateStamp DWORD ForwarderChain DWORD Name DWORD FirstThunk } IMAGE_IMPORT_DESCRIPTOR

説明フィールドの前に、インポートテーブルが配列であり、各要素が上記の構造であり、長さが14hであり、14hバイトの「0」が配列の終わりとして使用されていることに注意してください。プログラムが複数のモジュールをインポートする場合。の場合、この配列の長さは14h *(n + 1)である必要があります。

以下は、フィールドの説明です。



DWORD TimeDateStamp:通常は空で、上の図の0x00000000に対応します

DWORD ForwarderChain:上の図0x00000000に対応

DWORD名:上の図の0x0000230cに対応するモジュール名のRVAをインポートします。

DWORDの特性:上記の図0x0000227cに対応するOrginalFirstThunkとの結合です。

DWORD OrginalFirstThunk:特性を備えたコンソーシアムです。通常、OrginalFirstThunkが有効になります。これは、IMAGE_THUNK_DATA配列のRVAであり、上の図の0x0000227cに対応します。

IMAGE_THUNK_DATA構造を見てみましょう。

struct _IMAGE_THUNK_DATA32{ union { DWORD ForwarderString DWORD Function the memory address of the function being input DWORD Ordinal The ordinal value of the API being entered DWORD AddressOfData The high bit is 0 to point to IMAGE_IMPORT_BY_NAME structure 2 }u1 }IMAGE_THUNK_DATA32

IMAGE_THUNK_DATAを指すRVAは0x0000227cであり、オフセットは107chであることがわかっています。以下に示すように、107chから0x00000000で終わるまでは、インポートされた関数の完全な配列です。

IMAGE_THUNK_DATAのフィールドを1つずつ説明します。

ForwarderString:IMAGE_IMPORT_DESCRIPTORのForwarderChainに値がある場合にのみ有効です

関数:インポートされた関数の実際のメモリアドレス。メモリにロードされた場合にのみ有効です。

序数:関数のシリアル番号をエクスポートします。エクスポートテーブルを使用すると、シリアル番号を使用して関数をエクスポートできます。インポートテーブルにも対応するメカニズムがあります。 IMAGE_THUNK_DATAの最上位ビットが1の場合にのみ有効です。

AddressOfData:IMAGE_THUNK_DATAの最上位ビットが0の場合、IMAGE_IMPORT_BY_NAME構造体配列を指すことが有効です。最上位ビットが1で、関数が関数名としてインポートされる可能性はありますか?最大ビットが1の最小数も0x80000000であることがわかっています。この位置はシステムスペースであり、プログラムにアクセスできないため、不可能です。

IMAGE_IMPORT_BY_NAME構造は次のとおりです。

struct _IMAGE_IMPORT_BY_NAME { WORD Hint BYTE Name[1] } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME

ヒント:関数が配置されているdllの出力テーブルにある関数のシーケンス番号を示します。

名前:入力する関数の関数名を示します

次は、IMAGE_IMPORT_DESCRIPTORの最後のフィールドです。

DWORD FirstThunk:IMAGE_IMPORT_DESCRIPTOR画像の0x00002000に対応します。これは、OriginalFirstThunkと同じディスク上の場所を指し、IMAGE_THUNK_DATA配列も指します。 PEファイルがメモリにロードされると、FirstThunkが指すIMAGE_THUNK_DATA配列の関数は、関数アドレスを実メモリに格納します。 OriginalFirstThunkもIMAGE_THUNK_DATA配列を指しますが、実メモリー内の関数アドレスは保存されませんが、IMAGE_IMPORT_BY_NAME配列は保存されます。 RVAは、インポート関数のファイル名を保存します。

3.まとめ

1.重要な点は、ディスクとメモリのOriginalFirstThunkとFirstThunkの違いを区別することです。どちらもディスク内で同じです。メモリ内では、前者のIMAGE_THUNK_DATA構造がAddressOfDataフィールドで有効になるため、IMAGE_IMPORT_BY_NAME配列のRVAを指すため、INTとも呼ばれ、後者はインポートされた関数の実際のアドレスをメモリに保持します。 IATと呼ばれます。

2. PEのインポートテーブル、つまりIMAGE_IMPORT_DESCRIPTOR構造が配列内にあること、つまりPEファイルに複数のインポートテーブルが存在する可能性があり、各インポートテーブルにOriginalFirstThunkとFirstThunkが1つしかないことを明確にする必要があります。 、ただし、IMAGE_THUNK_DATAが配列であることを示しています。配列内の要素の数は、関数の数を表します。 IMAGE_THUNK_DATAのAddressOfDataフィールドが有効な場合、それはIMAGE_IMPORT_BY_NAMEの配列を指します。この配列の要素数は、関数に名前がないため、IMAGE_THUNK_DATAの要素数とは異なる場合があります。

3.配列の最後は0で埋める必要があり、長さは配列要素のサイズであり、文字列は00で終わります。