トップ «前の日記(2013-10-09) 最新 次の日記(2013-10-12)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2013-10-10

_ EncodePointer/DecodePointer

素に近いWindows XPで動いているシステムがあって、どうしても、その中で動いているDLLの新版を入れたいとする。

そのDLLを呼び出すプログラムは、VC++6で遥か昔に作られたものだ。

しかし、手元にはVisual C++ 2010と2012しか無い。ここでランタイムをDLLとしてリンクするとすごく嫌なことが起きそうな気がする。かたやMSVCRT.dllをロードし、こちらはMSVCR10.DLLをロードする。競合はしないとは思うが(関数名の前のモジュール名が異なる)、ランタイムのバージョンが合わないというのはいかにも危なそうな匂いがする。

で、Visual C++ 2010でランタイムを静的にリンクすれば、mallocしたポインタをモジュールをまたがったところでfreeしたり、FILE*の交換などしなければ、気持ち的には安全なように思う。

そこで、Visual C++2010で静的ランタイムライブラリとリンクしてDLLを作ってインストールしたとする。

すると、オリジナルのプログラムが、入れ替えたDLLをLoadLibraryでロードしようとするとErrorCode 127(ERROR_PROC_NOT_FOUND)でエラーとなる。

何が原因でしょうか?

答えは、Visual C++2010のランタイムライブラリが内部でEncodePointer/DecodePointerという、Windwos XP SP2以降のKernel32.dllに実装されたWindows APIを呼んでいるからだ。素に近いWindows XPのKernel32.dllには、そういう関数は無い。そのため解決できずにロードエラーとなる。

で、このAPIは何ものか? と調べると、EncodePointerというように、exploit対策のためのポインタ曖昧化APIなのだった。

crtのソースを読むと、なるほど、onexitポインタのように、いかにも固定化しているとやばそうなポインタを曖昧化している。

やることをやっているんだなぁと、ちょっと感動した。と同時にマイクロソフトがやることをやっているのだから、素に近いWindows XPとか使ってはいかんよなぁという後ろめたい気持ちも生じるのであった。

# 面倒なのでやらないが、やってみるとどうなるか知りたいこと。EncodePointerで曖昧化したポインタをDecodePointerせずに踏むと、どういうエラーが表示(あるいはログ出力)されるのだろうか。

_ 実際に試した結果

何か気がきいた仕組みなのかと思ったら、単に0xc0000005(Access violation)した。
#include <windows.h>
#include <stdio.h>
int hello()
{
    return printf("hello world\n");
}
int main(int argc, char* argv[])
{
    int(*eptr)();
    int(*ptr)() = hello;
    printf("%p\n", ptr);
    ptr();
    eptr = EncodePointer(ptr);
    printf("%p\n", eptr);
    ptr = DecodePointer(eptr);
    printf("%p\n", ptr);
    ptr();
    fflush(stdout);
    eptr();
    return 0;
}
実行すると
c:\test>ptr.exe(上をコンパイルしたもの)
00811000
hello world
6E81F379
00811000
hello world
(ptr.exeは動作を停止しましたダイアログを表示)
追記:エンコードしたポインタへジャンプすることを想定しているのではなく、ダンプから取得した値へジャンプするライブパッチを作らせないことが目的なんだから、これで良いのだった。

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|

ジェズイットを見習え