Boost」など、さまざまなカンファレンスを企画・運営しています。BOOKS(コードジン・ブックス)は、CodeZineの連載からカットアップした、開発現場の課題解決に役立つ書籍シリーズです。呼び出し元APIフックまとめ参考資料SEXYHOOK_DARKCAST:何でもvoidにキャストするSEXYHOOK_DARKCASTは、渡されたどんな型でもvoid*にキャストします。*reinterpret_cast<void**>(&p);}普通の型は、(void*)pointerとすればvoid*型になりますが、メソッドのポインタだけはC++の保護によりvoid*にキャストすることができません。このメソッドはその壁を打ち砕くメソッドです。通常、メソッドのポインタは同じ呼出規約のメソッドのポインタにしか変換できません。キャストだけはうまくいきません。変換することはできません。変換することはできません。変換することはできません。変換することはできません。変換することはできません。変換することはできません。SEXYHOOK_DARKCASTを利用すれば、問答無用で変換可能です。SEXYHOOK_DARKCAST(p1);そもそも、classの呼び出しはthiscallなので、最初の0番目引数にthisを積んだ関数と同じになるはずです。関数だったら、定義された実体へのアドレスにキャストして何が悪い、と。当初はprintf()の...にどんな型でも渡せるという特性を利用して作っていた(当初)のですが、codeprojectに掲載されていた下記トピックスのbrute_castがあまりにも素晴らしかったので、アイディアをいただきました。Functions関数フックSEXYHOOKでは、関数のフックにアセンブラを利用しています。関数の先頭5バイトをjmp命令に書き換えることにより、自分が好きな関数へ飛ばしています。C++のデバッグの混合モードを利用すると、C言語とそれに対応するアセンブラを簡単に見ることができて便利です。retadd関数は分断されてしまいます。最初のjmpフックルーチン以降は実行されません。以後はフックルーチンが実行されます。それはフックルーチンのretを利用します。本来呼び出された関数と、フックルーチンとで呼出規約をまったく同じにそろえているのはそのためです(後で解説します)。実際に書き換えを行っているのは、SEXYHOOKFuncBase::FunctionHookFunction関数の下の方です。;//フックされる関数の先頭を書き換えて、フックルーチンへ制御を移すようにする。&this->OrignalAsm);コメント中にも書いたのですが、このルーチンを作成するに当たり、次の2つのサイトが非常に参考になりました。この場をお借りしてお礼を述べさせてください。日々の破片アセンブラと機械語の対応が分からないよ、でも知りたいよ!のときに読むページやっている内容ですが、jmpフックルーチンというマシン語を作成し、メモリを書き換える関数を呼んでいます。無条件ジャンプ命令のマシン語は0xe9[相対アドレス4バイト]の合計5バイトで表現されます。無条件命令のオペコードで、続く4バイトの相対アドレスにジャンプします。相対アドレスというのは、この命令を実行したアドレス(eipレジスタの値)から相対でNバイト飛べという命令です。(uintptr_t)overraideFunctionAddrと、この関数を埋め込む位置(将来のeip)からフックルーチンが格納されているアドレスを引いています。相対アドレス4バイトは、Intelアーキテクチャなので、リトルエンディアンで書き込む必要があります。現在のアドレスが004010AAで00401470アドレスにあるadd関数の実体に飛びたいとします。E9の部分が無条件ジャンプ命令をあらわしていて、次が現在のアドレス(eip)に加える4バイトのアドレスです。現在のアドレスから飛びたいアドレスの差を格納するわけですから、こうなります。