MinGW+GCCでImmunity Debugger Plugin開発
今度はImmunity Debuggerです。
OllyDbgを元にしているのでPlugin用のインターフェイスなどは
シンボル名を除いて大体同じです。
が、1.7系までと1.8系以降でエクスポートされている関数名などが変わっている
ため、対象バージョンによりプラグインを分ける必要があります。
更にPDKは1.7系の物までしか配布されていないので、1.8系は適当に書き換えて
使用します。一応問題無く動いているようですが何か変な可能性もあります。
(自分で使用してるAPIだけしか動作確認してないので)
なお、今回の動作や仕様確認はバージョン1.73と1.83で行っています。
PDKは以下の場所から取得できます。
もうメンテナンスされてないようなのでいつまで置かれているかは分かりませんが。
- Immunity Debugger PDK (1.7Xまで)
まずは差分を確認しましょう。
以下は、各バージョンのImmunity DebuggerとOllyDbgのプラグインでエクスポートする
必要のあるコールバック関数です(一部抜粋)。呼び出し規約はすべてcdeclです。
OllyDbg 1.10 | Immunity Debugger 1.7X | Immunity Debugger 1.8X |
---|---|---|
_ODBG_Pluginaction | _IMMDBG_Pluginaction | IMMDBG_Pluginaction |
_ODBG_Pluginclose | _IMMDBG_Pluginclose | IMMDBG_Pluginclose |
_ODBG_Plugindata | _IMMDBG_Plugindata | IMMDBG_Plugindata |
_ODBG_Plugindestroy | _IMMDBG_Plugindestroy | IMMDBG_Plugindestroy |
_ODBG_Plugininit | _IMMDBG_Plugininit | IMMDBG_Plugininit |
_ODBG_Pluginmainloop | _IMMDBG_Pluginmainloop | IMMDBG_Pluginmainloop |
_ODBG_Pluginmenu | _IMMDBG_Pluginmenu | IMMDBG_Pluginmenu |
_ODBG_Pluginreset | _IMMDBG_Pluginreset | IMMDBG_Pluginreset |
この通り1.7Xと1.8Xで関数先頭の_が除去されています。
更に以下がデバッガのexeがエクスポートしている関数です(一部抜粋)。
プラグインからはインポートする対象になります。
呼び出し規約は同様にすべてcdeclです。
Immunity DebuggerではPython拡張で用いたと思われるPy*のシンボル等が追加されていますが、
OllyDbg互換で書く分には特に気にする必要はありません。
OllyDbg 1.10 | Immunity Debugger 1.7X | Immunity Debugger 1.8X |
---|---|---|
_Addsorteddata | _Addsorteddata | Addsorteddata |
_Addtolist | _Addtolist | Addtolist |
_Analysecode | _Analysecode | Analysecode |
_Assemble | _Assemble | Assemble |
_Broadcast | _Broadcast | Broadcast |
_Browsefilename | _Browsefilename | Browsefilename |
こちらも同様で関数先頭の_が除去されています。
この辺の差違を吸収するため、1.7Xまで使えていたPDKのplugin.hを以下の通り修正します。
OllyDbgのPDKを元に書き換えても動くと思いますが、折角あるのでこちらを元にします。
コンパイル時に渡すバージョンでどちらの名前でエクスポートするか振り分けます。
Immunity Debugger専用にプラグインを書いている人はあまりいないと思うので
基本的にOllyDbgのシンボルに合わせてあります。
// If you like Microsoft compiler, this will force byte alignment and verify // that character is set to unsigned. #ifdef _MSC_VER ... #endif + #ifdef __GNUC__ + #pragma pack(1) + #ifndef cdecl + #define cdecl __cdecl + #endif + #undef _export + #if IMMDBGVER >= 180 + #define ODBG_Plugindata IMMDBG_Plugindata + #define ODBG_Plugininit IMMDBG_Plugininit + #define ODBG_Pluginmainloop IMMDBG_Pluginmainloop + #define ODBG_Pluginsaveudd IMMDBG_Pluginsaveudd + #define ODBG_Pluginuddrecord IMMDBG_Pluginuddrecord + #define ODBG_Pluginmenu IMMDBG_Pluginmenu + #define ODBG_Pluginaction IMMDBG_Pluginaction + #define ODBG_Pluginshortcut IMMDBG_Pluginshortcut + #define ODBG_Pluginreset IMMDBG_Pluginreset + #define ODBG_Pluginclose IMMDBG_Pluginclose + #define ODBG_Plugindestroy IMMDBG_Plugindestroy + #define ODBG_Paused IMMDBG_Paused + #define ODBG_Pausedex IMMDBG_Pausedex + #define ODBG_Plugincmd IMMDBG_Plugincmd + #else + #define IMMDBG_Plugindata _IMMDBG_Plugindata + #define IMMDBG_Plugininit _IMMDBG_Plugininit + #define IMMDBG_Pluginmainloop _IMMDBG_Pluginmainloop + #define IMMDBG_Pluginsaveudd _IMMDBG_Pluginsaveudd + #define IMMDBG_Pluginuddrecord _IMMDBG_Pluginuddrecord + #define IMMDBG_Pluginmenu _IMMDBG_Pluginmenu + #define IMMDBG_Pluginaction _IMMDBG_Pluginaction + #define IMMDBG_Pluginshortcut _IMMDBG_Pluginshortcut + #define IMMDBG_Pluginreset _IMMDBG_Pluginreset + #define IMMDBG_Pluginclose _IMMDBG_Pluginclose + #define IMMDBG_Plugindestroy _IMMDBG_Plugindestroy + #define IMMDBG_Paused _IMMDBG_Paused + #define IMMDBG_Pausedex _IMMDBG_Pausedex + #define IMMDBG_Plugincmd _IMMDBG_Plugincmd + + #define ODBG_Plugindata _IMMDBG_Plugindata + #define ODBG_Plugininit _IMMDBG_Plugininit + #define ODBG_Pluginmainloop _IMMDBG_Pluginmainloop + #define ODBG_Pluginsaveudd _IMMDBG_Pluginsaveudd + #define ODBG_Pluginuddrecord _IMMDBG_Pluginuddrecord + #define ODBG_Pluginmenu _IMMDBG_Pluginmenu + #define ODBG_Pluginaction _IMMDBG_Pluginaction + #define ODBG_Pluginshortcut _IMMDBG_Pluginshortcut + #define ODBG_Pluginreset _IMMDBG_Pluginreset + #define ODBG_Pluginclose _IMMDBG_Pluginclose + #define ODBG_Plugindestroy _IMMDBG_Plugindestroy + #define ODBG_Paused _IMMDBG_Paused + #define ODBG_Pausedex _IMMDBG_Pausedex + #define ODBG_Plugincmd _IMMDBG_Plugincmd + #endif + #endif
ImmunityDebugger.defをOllyDbgの時と同様に変換します。
1.7Xと1.8X用のインポートテーブル分を別々に生成します。(差分は-Uオプション)
# dlltoolが処理できない不要な宣言削除、 関数名の_を外す $ sed -e 's/^CODE.*//' -e 's/^EXETYPE.*//' -e 's/^DATA.*//' -e '/^$/d' -e 's/_//' ImmunityDebugger.def \ > ImmunityDebugger.def.mingw # gccで扱える形式に変換 (1.7X用) $ i686-pc-mingw32-dlltool -U --dllname ImmunityDebugger.exe --input-def ImmunityDebugger.def.mingw --output-lib immdbg17.a # gccで扱える形式に変換 (1.8X用) $ i686-pc-mingw32-dlltool --dllname ImmunityDebugger.exe --input-def ImmunityDebugger.def.mingw --output-lib immdbg18.a
プラグインのソースをコンパイルする際にバーションを引数で渡して振り分けます。
# 1.7X用オブジェクトファイル生成 $ i686-pc-mingw32-gcc -funsigned-char -mwindows -c Bookmark.c -DIMMDBGVER=173 -o Bookmark_17.o # 1.8X用オブジェクトファイル生成 $ i686-pc-mingw32-gcc -funsigned-char -mwindows -c Bookmark.c -DIMMDBGVER=183 -o Bookmark_18.o
リンク時にそれぞれのバージョンのライブラリにリンクします。
# 1.7X用DLL生成 $ i686-pc-mingw32-gcc -funsigned-char -mwindows Bookmark_17.o immdbg17.a \ -o Bookmark_17.dll -W -shared -Wl,--dll # 1.8X用DLL生成 $ i686-pc-mingw32-gcc -funsigned-char -mwindows Bookmark_18.o immdbg18.a \ -o Bookmark_18.dll -W -shared -Wl,--dll
インクルードファイルとリンクするライブラリを振り分けてあげれば
一つのソースコードでOllyDbg 1.10も含む各バージョンで動くプラグイン
が生成できます。
既にバイナリになっている物はImmunity Debugger Plugin Fixer Tool等で
書き換えるしか無いですが、折角プラグインを作るなら最初からそれぞれで
動くバージョンを用意した方が良いんじゃ無いでしょうか。
ほとんど差が無いのでそれほど手間も掛かりませんし。