1. 概要
ダイナミックリンクライブラリまたはDLLファイルは、Windowsで使用される共有ライブラリであり、関数とデータが含まれています。 Windowsの他の実行可能ファイルと同様に、DLLファイルは Portable Executable (PE)ファイル形式です。 PEファイルのファイルヘッダーには、インポートテーブルやエクスポートテーブルなどのさまざまなデータがあります。
インポートテーブルは、PEファイルに他の共有ライブラリから含まれる関数とデータの配列です。 エクスポートテーブルは、PEファイル内に含まれる関数とデータの配列であり、外部に提供したいと考えています。 これらは、PEファイルが内部で使用する内部関数とは異なります。
DLLファイルのエクスポートデータが必要な理由はたくさんあります。 その1つは、DLLプログラムの関数を利用したプログラムを作成できるようにするためです。 Linuxでは、いくつかの異なるツールを使用して、DLLファイルのエクスポートテーブルを抽出できます。
このチュートリアルでは、これらのツールを使用してエクスポートされたシンボルを抽出する方法について説明します。これらのツールは、いくつかの異なるコマンドラインツールとPythonモジュールで構成されています。
2. ワイン
Wine は、LinuxなどのPOSIX準拠のシステムでWindowsプログラムを実行することを目的とした互換性ツールです。 また、PEファイルを操作するための一連のサポートツールも付属しています。
DLLPEファイルと対話するためのwinedumpツール。 winedump コマンドを使用して、PEファイルに関する情報を表示できます。
PEファイルは、エクスポートされたシンボルをエクスポートアドレステーブルに格納します。 次に、PEファイルはそのエクスポートアドレステーブルをPEファイルの「エクスポート」セクションに保存します。
winedumpをインストールしましょう:
sudo apt-get install wine64-tools
-j オプションを使用して、エクスポートされたシンボルをエクスポートセクションに表示します。
$ winedump -j export kernel32.dll
Contents of kernel32.dll: 725696 bytes
Exports table:
Name: KERNEL32.dll
[...]
Entry Pt Ordn Name
0009417F 1 AcquireSRWLockExclusive (-> NTDLL.RtlAcquireSRWLockExclusive)
000941B5 2 AcquireSRWLockShared (-> NTDLL.RtlAcquireSRWLockShared)
0001E860 3 ActivateActCtx
0001A570 4 ActivateActCtxWorker
00021A70 5 AddAtomA
0000FE30 6 AddAtomW
00022DE0 7 AddConsoleAliasA
00022DF0 8 AddConsoleAliasW
0009423B 9 AddDllDirectory (-> api-ms-win-core-libraryloader-l1-1-0.AddDllDirectory)
000375A0 10 AddIntegrityLabelToBoundaryDescriptor
00053150 11 AddLocalAlternateComputerNameA
000531B0 12 AddLocalAlternateComputerNameW
00020570 13 AddRefActCtx
0001E3C0 14 AddRefActCtxWorker
00035FB0 15 AddResourceAttributeAce
0001F3C0 16 AddSIDToBoundaryDescriptor
00035FC0 17 AddScopedPolicyIDAce
00034600 18 AddSecureMemoryCacheCallback
00094374 19 AddVectoredContinueHandler (-> NTDLL.RtlAddVectoredContinueHandler)
000943B4 20 AddVectoredExceptionHandler (-> NTDLL.RtlAddVectoredExceptionHandler)
0001A6B0 21 AdjustCalendarDate
00022A30 22 AllocConsole
[...]
00019E40 1614 lstrlen
00019E40 1615 lstrlenA
00017930 1616 lstrlenW
0001D240 1617 timeBeginPeriod
0001C2F0 1618 timeEndPeriod
00020470 1619 timeGetDevCaps
00061590 1620 timeGetSystemTime
0001CFE0 1621 timeGetTime
0001A510 1622 uaw_lstrcmpW
00017950 1623 uaw_lstrcmpiW
00033380 1624 uaw_lstrlenW
000333D0 1625 uaw_wcschr
000333F0 1626 uaw_wcscpy
00033420 1627 uaw_wcsicmp
00033430 1628 uaw_wcslen
00033450 1629 uaw_wcsrchr
Done dumping kernel32.dll
3. Radare2
Radare2 は、UNIXライクなリバースエンジニアリングフレームワークです。 Radare2フレームワークには、バイナリを操作するための一連のコマンドラインツールも付属しています。 LinuxとWindowsの両方でRadare2を使用でき、PEファイル形式をサポートしています。
したがって、 rabin2 ツールを使用して、選択したバイナリからプログラム情報を抽出できます。
最初にradare2とrabin2をインストールしましょう。
$ sudo apt-get install radare2
-s オプションを使用して、コマンドラインにPEファイルのエクスポートされたシンボルを表示します。
$ rabin2 -s kernel32.dll
[Symbols]
000 0x0009277f 0x18009417f GLOBAL FUNC 0 KERNEL32.dll_AcquireSRWLockExclusive
001 0x000927b5 0x1800941b5 GLOBAL FUNC 0 KERNEL32.dll_AcquireSRWLockShared
002 0x0001dc60 0x18001e860 GLOBAL FUNC 0 KERNEL32.dll_ActivateActCtx
003 0x00019970 0x18001a570 GLOBAL FUNC 0 KERNEL32.dll_ActivateActCtxWorker
004 0x00020e70 0x180021a70 GLOBAL FUNC 0 KERNEL32.dll_AddAtomA
005 0x0000f230 0x18000fe30 GLOBAL FUNC 0 KERNEL32.dll_AddAtomW
[...]
また、 rabin2 からエクスポートされたシンボルは、winedumpの出力とは少し異なって表示されることに注意する必要があります。
4. objdump
objdump は、バイナリファイルに関する情報をダンプするために使用できるツールです。 PEファイル形式は、objdumpツールでサポートされている形式の1つです。
最初にobjdumpをインストールしましょう。
$ sudo apt-get install binutils
これで、 objdump を使用して、PEファイルのエクスポートアドレステーブルをダンプできます。
$ objdump -p kernel32.dll
kernel32.dll: file format pei-x86-64
[...]
The Data Directory
Entry 0 0000000000090190 0000dd40 Export Directory [.edata (or where ever we found it)]
[Ordinal/Name Pointer] Table
[ 0] AcquireSRWLockExclusive
[ 1] AcquireSRWLockShared
[ 2] ActivateActCtx
[ 3] ActivateActCtxWorker
[ 4] AddAtomA
[ 5] AddAtomW
[...]
これにobjdumpを使用することの欠点は、エクスポートテーブルがPEに関する他の情報と一緒に表示されることです。 したがって、さらに処理したい場合は、エクスポートされたシンボルに関連する行を解析する必要があります。
また、出力として数千行のデータがある可能性があることにも注意する必要があります。そのため、 grep を実行し、それに応じて解析する必要があります。
5. pefile
最後に、 pefile は、PEファイルの操作に使用できるPythonモジュールです。
pip:を使用してpefileモジュールをインストールしましょう
$ pip3 install pefile
「exports」フラグを使用して、DLLファイルのエクスポートをダンプできます。
$ python3 -m pefile exports kernel32.dll
0x18009417f b'AcquireSRWLockExclusive' 1
0x1800941b5 b'AcquireSRWLockShared' 2
0x18001e860 b'ActivateActCtx' 3
0x18001a570 b'ActivateActCtxWorker' 4
0x180021a70 b'AddAtomA' 5
[...]
さらに、1つのPythonライナーを使用して、シンボル名の先頭から「b」を削除できます。
$ python3 -c 'import sys;import pefile;pe = pefile.PE(sys.argv[1]);wr = sys.stdout.write; [wr("%s %s %i\n"%(hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name.decode("utf-8"), exp.ordinal)) for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols]' kernel32.dll
0x18009417f AcquireSRWLockExclusive 1
0x1800941b5 AcquireSRWLockShared 2
0x18001e860 ActivateActCtx 3
0x18001a570 ActivateActCtxWorker 4
0x180021a70 AddAtomA 5
[...]
最後に、 pefile モジュールを使用するには、LinuxシステムにPythonが必要であることに注意する必要があります。
6. 結論
この記事では、wineツールの一部である winedump コマンドラインツールを使用して、DLLのエクスポートされたシンボルを表示する方法について説明しました。
次に、Radare2リバースエンジニアリングツールセットのrabin2ツールの使用を検討しました。 この後、objdumpツールを使用してPEファイルに関する情報を表示する方法について説明しました。
最後に、 pefilePythonモジュールを使用してDLLから情報を抽出する方法について説明しました。 これらのオプションのいずれかを使用して、DLLファイルがLinuxでエクスポートするシンボルを見つけることができます。