読者です 読者をやめる 読者になる 読者になる

experimental codes

最近書いた雑多な実験コードのまとめ。


GetThisOfCaller()
現在の関数の呼び出し元がメンバ関数であればその this を返すというもの。
スタックフレームをさかのぼり、デバッグ情報を使って該当スコープの変数を巡回して this が見つかればそれを返す、ということをやっています。(たまたま今回 this が欲しかっただけで、それ以外の変数も可能です)
非 Debug ビルドの時はよくデタラメな値が返ってくるため、使いものにならないですが、Debug で限定的な状況で役立つ可能性が無きにしもあらずです。


メンバ関数の中と外で違う処理を行うマクロ
VisualC++ の拡張 __if_exits, __is_not_exits を使って this の有無で違う処理をさせるというもの。
__if_exits は指定シンボルの有無で分岐するという代物で、主にメタプログラングに使われる機能ですが、こういうこともできるようです。
また、clang にも __if_exits はありますが、this を認識できないようでコンパイルできませんでした。こちらはメタプログラングしか想定してない実装になってるんじゃないかと思います。


8bit atomic operation
VisualC++ には _InterlockedIncrement() 一族の atomic 操作系 intrinsics がありますが、なぜか 8bit 整数版が用意されていません。
必要な場合アセンブラで自力で書く必要があるようで、書いてみました。


dll の export,import 関数を巡回するコード
ロードされている dll のアドレス (HMODULE) からその export,import 関数を巡回するコード。
既存のシンボルが一切見えない特殊な状況に置かれることが稀にあり、そのとき kernel32.dll の export 関数を巡回する必要に迫られます。
また、MemoryLeakBuster は import 関数テーブルを書き換えて HeapAlloc() に hook を仕込むことで実装しました。


shellcode
shellcode を書いてみる実験。shellcode とは大雑把に言うと既存のプログラムにねじ込んで実行させるバイナリコード片です。
既存のプロセスの中で実行されるため、外部シンボルが一切見えないという特殊な条件を強いられることになります。
FS レジスタから辿れる Process Environment Block にロードされている dll のリストがあるため、それを辿って kernel32.dll を探し、(上記の dll export を巡回する手順で) LoadLibrary() と GetProcAddress() を得ることで既存の関数を呼べるようにします。
今回の例はメッセージボックスを出しています。


buffer_overflow
buffer overflow のバグがある場合、入力データで return address を書き換えて任意の場所に制御を飛ばせる可能性があります。任意のコードを実行可能な脆弱性がうんぬんとよくニュースになるあれの原因の一つです。
実際に buffer overflow を突いて任意のコード (ここでは上の shellcode) を実行させてみたものです。


DLL Injection
Windows には、既存の任意のプロセスのアドレス空間にメモリを確保する VirtualAllocEx()、既存の任意のプロセスにスレッドを作る CreateRemoteThread() という強力な API があります。
これを利用すると、既存の任意のプロセスに任意のコードを仕込んで実行させることができます。
この仕込みを使って既存のプロセスに DLL を inject し、malloc() を乗っ取ってみた、という実験です。
ムービーキャプチャソフトや Nsight のような解析ツールの類もこの仕組みを使ってるんじゃないかと思います。