はじめに
イメージ・マジックの安藤です。先日から季節が急速に真冬の様相を呈していますね。風邪やインフルエンザが流行りだす時期なので皆様におかれましても十分ご用心ください。ちなみに、私は去年の大晦日から今年の三が日にかけてインフルエンザを発症するという何とも言えない新年スタートを切っているので気を付けます。
今回は題名の通りDLLの解析をしたという話です。
DLLとは
多分この説明要らないんじゃないかなぁと思いつつ書いておきます。DLLとは、プログラムのある機能を再利用できるようにプログラム本体と切り分けたライブラリのことを指します。Windowsならば.dll、Linux系では.soという拡張子が使われます。
なお、今回の話はWindowsの.dllで、一般的な、Cで記述されたDLLという話です。
コンパイルを通すのに必要なもの
DLLの利用方法には暗黙的リンクと明示的リンクが存在します。今回は完全に個人的にDLLを使いたいだけなので暗黙的リンクでコンパイルするものとします。以下が必要になります。
- インポートライブラリ(.lib)
- ヘッダファイル(.h)
- エクスポートされている関数名
- 関数の引数と型
初期状態
DLLがどんな状態で使われていたのかを少しだけ書いておきます。DLLとDLLの機能をラップしたEXEがあり、EXEに引数を渡して実行してあげるとDLLの機能が使えるという構成になっていました。最終的にはこのEXEを介さずにDLLの機能を呼び出すのがゴールです。
インポートライブラリを用意する
第一の関門として、インポートライブラリが存在していません。ただ、これに関してはVisual Studioを使えばDLLから同等のものを用意することができます。まず、以下のコマンドを実行します。
dumpbin /exports hoge.dll
C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools>dumpbin /exports VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64\c1.dll Microsoft (R) COFF/PE Dumper Version 14.16.27024.1 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64\c1.dll File Type: DLL Section contains the following exports for c1.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 3 number of functions 3 number of names ordinal hint RVA name 1 0 000DDDB0 AbortCompilerPass 2 1 000DDE50 CloseTypeServerPDB 3 2 000055FC InvokeCompilerPassW Summary 32000 .data 17000 .pdata F3000 .rdata 7000 .reloc 1000 .rsrc 138000 .textこのコマンドでDLLからエクスポートされている関数の一覧がテーブル上に表示されます。MSVCに存在する適当なDLLを表示してみます。 ここでordinal~nameの列に注目すると関数名が分かります。この関数名を以下のように羅列し、拡張子を.defで保存します。これはモジュール定義ファイルと呼ばれるものです。
EXPORTS AbortCompilerPass CloseTypeServerPDB InvokeCompilerPassW作成したモジュール定義ファイルは以下のコマンドでインポートライブラリに変換できます。なお、64bitアーキテクチャを想定しています。
lib /DEF:hoge.def /MACHINE:X64 /out:hoge.lib
ヘッダファイルを用意する
ヘッダファイルでは以下のように書くことでDLLの関数を宣言できます。#define DLLImport __declspec(dllimport) #ifdef __cplusplus extern "C"{ #endif DLLImport void funcName1(); DLLImport int funcName2(int arg); #ifdef __cplusplus } #endif以上を見るとわかりますが、関数の戻り値と引数がわからないとDLLの機能は使えないことが分かります。
以降、今回のケースで関数定義をどう解析したかは次回の私の番で書いていきたいと思います。