はじめに
Intel Pinというのが楽しいから遊んで欲しいというだけの話。
Instrumentation
Instrumentation(計装)という概念がある。耳馴染みのない言葉だが、Wikipedia(en)にはしっかり記事がある。
一般に計装とは制御装置による測定を指す曖昧な概念だが、プログラミングの文脈におけるInstrumentationは「プログラムにコードを挿入することで実行時の情報を取得・操作する」技術を指す用語だ。
その及ぶ範囲はパフォーマンスの測定やエラー検出、CPUキャッシュの分析や未定義命令のエミュレーションなど多岐に渡る。
Instrumentationはその手法によって二種類に大別される。
- Source Code Instrumentation(SCI)
- ソースコードにinstrumentする。
- Binary Instrumentation(BI)
- 実行ファイルに直接instrumentする。
また、BIは更に二種類に分類される。
- Static Binary Instrumentation
- 実行前にinstrumentする。実行ファイルは変更される。
- Dynamic Binary Instrumentation
- 実行時にinstrumentする。実行ファイルは変更されない。
例えば、QEMUは異なるアーキテクチャのコードを実行するためにTCG(Tiny Code Generator)という機構を備えている。これはDynamic Binary Translation(DBT)と呼ばれる手法によるものだが、DBTはBIの一種であると言える。QEMUのDBTについては以前紹介した。
さて、Intel Pinはその名の通りIntelが開発したInstrumentation Toolだ。用いられる手法はDynamic Binary Instrumentationにあたるが、これを用いる利点としては以下が挙げられる。
- 言語から独立している
- 古いソフトウェアに対しても適用できる
- 再コンパイルの必要がない
- 動的に生成されるコードを扱うことができる
- 実行中のプロセスにアタッチできる
C++のconstepxrなんかはとても楽しいが、しかし人類は実行時から逃れられない。
Intel Pinの概要
Intel PinはマルチプラットフォームなInstrumentation Toolで、動的リンクライブラリと解析対象を引数に与えて実行する。Intel PinのSDKを用いたツールを自作する場合、ユーザーは動的リンクライブラリを作成することになる。
pin -t pintool.dll - application
実行中のプロセスにアタッチする場合はPIDを指定する。
pin -t pintool.dll -pid 1234
Intel Pinのサンプル
ユーザーガイドの最初に登場するサンプル、inscountを紹介する。
#include <iostream> #include <fstream> #include "pin.H" ofstream OutFile; // The running count of instructions is kept here // make it static to help the compiler optimize docount static UINT64 icount = 0; // This function is called before every instruction is executed VOID docount() { icount++; } // Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { // Insert a call to docount before every instruction, no arguments are passed INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_END); } KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "inscount.out", "specify output file name"); // This function is called when the application exits VOID Fini(INT32 code, VOID *v) { // Write to a file since cout and cerr maybe closed by the application OutFile.setf(ios::showbase); OutFile << "Count " << icount << endl; OutFile.close(); } /* ===================================================================== */ /* Print Help Message */ /* ===================================================================== */ INT32 Usage() { cerr << "This tool counts the number of dynamic instructions executed" << endl; cerr << endl << KNOB_BASE::StringKnobSummary() << endl; return -1; } /* ===================================================================== */ /* Main */ /* ===================================================================== */ /* argc, argv are the entire command line: pin -t <toolname> -- ... */ /* ===================================================================== */ int main(int argc, char * argv[]) { // Initialize pin if (PIN_Init(argc, argv)) return Usage(); OutFile.open(KnobOutputFile.Value().c_str()); // Register Instruction to be called to instrument instructions INS_AddInstrumentFunction(Instruction, 0); // Register Fini to be called when the application exits PIN_AddFiniFunction(Fini, 0); // Start the program, never returns PIN_StartProgram(); return 0; }
あれこれAPIが呼ばれているが、注目すべき点は少ない。VOID Instruction(INS ins, VOID *v)で解析ルーチンであるVOID docount()をinstrumentしているだけだ。解析対象であるアプリケーションとIntel Pinとそれぞれ別々のスタックを持つため、実行状態が壊れるということはない。基本このような感じで、適当にmoduleを叩いていくだけでそれなりのことができるので楽しい。特にSymbol Objectがいい感じだった。
Intel Pinのアーキテクチャ
DLLを与えていることから分かるように、Intel Pinの本質はコードインジェクションだ。先述のinscountを読み込む場合、アプリケーションの内部はこのようになる。
元々のコードとinstrumentされたコードが組み合わさって実行される。アプリケーション内部にVMを埋め込む発想が面白い。
アーキテクチャの細部については公式のドキュメントを参照されたい。
とりわけ、CGO 2012/ISPASS 2012の資料は非常に充実している。
Intel Pinを取り巻く環境
Intel Pinは国内ではほぼ無名の存在だが、ダウンロード数は30,000を越え、被引用数は700を越えているキラープロダクトだ。
例えば、下記のグループでは日夜Intel Pinの質問が飛び交っている。
IDA Pro(商用版)と連携するためのSDKが公開されていることからも、その需要の高さを読み取ることができるだろう。
先日開催されたRecon 2014でもIntel Pinが用いられた発表があった。
CTFに関して言うと、例えばSMT SolverであるZ3やSageは徐々に広まりつつあるが、Intel Pinなどinstrumentation toolについても検討する必要があるかもしれない。どちらもConcolic Testing(Symbolic Execution)の同一線上に置かれる技術だ。
そしてもちろん、Taint AnalysisにおいてもIntel Pinは絶大な威力を持つだろう。
FuzzWin[SSTIC14] https://t.co/qesDXjshTX Intel PinとZ3を用いたfuzzerで、concolic testing(symbolic + concrete execution)を行う
— 能登だでぃ子 (@ntddk) 2014, 6月 25また、CTFtimeランク2位、PPPの母体であるCMUが開発しているBAPにもIntel Pinは利用されている。