Q&A以下の解説は、デバッガを用いたPCゲーム解析などプログラム解析の、初心者の方を対象として執筆しました。以下の解説は、特に記載のない限り32ビットアプリケーションを対象としています。以下の回答はVer1.10使用時をベースにしています。以下ではメニュー等の項目名について、対応する日本語化パッチ適用後の項目名を黄色で併記しています。日本語化パッチは当サイトメインページで配布しています。以下に挙げたキー操作は、標準メニューや右クリックによるポップアップメニューから同様の操作を行えるものもあります。以下の「メインウィンドウ」とは、『OllyDbg』でアプリケーションを起動させると最初に表示される「CPUウィンドウ」のことです。指定のない場合、以下の「左上ウィンドウ」等はこの「CPUウィンドウ」内の分割されたウィンドウ(ペイン)を指します。デバッグ対象実行ファイルまたはプロセスのことを、一般に「デバッギー」・「デバッギ」(Debuggee)と呼びます。当ページと併せて、プログラム解析全般の解説である「プログラム解析一般Q&A」も参照されることをお勧めします。以下の回答は匿名希望のリバースエンジニア有志と、うさぴょん、Lucaで行っています。Vista以降での動作について教えてください。逆アセンブルコードリストについて教えて下さい。ブレークポイントの種類とその違いについて教えて下さい。デバッグ特権の必要性が分かりませんデバッグ中にシステムDLL内でアクセス違反が生じるのはOSの問題ですか?デバッギーからデタッチすることはできませんか?デバッギーのエントリーポイントがコードセクション内ならウイルスには感染していませんか?ウイルス対策としてのデバッグ検出について教えて下さいデバッギーのウイルス感染やバグによるレジストリ破壊等に備えて、完全に独立した環境で解析を行いたい。解析時にデバッギーが行ったファイル・レジストリ操作の結果だけを簡単に確認したい。デバッガ検出手法を教えてください。INT命令を用いたデバッガ検出が上手くいきません(環境:WindowsXP)。『OllyDbg』のプロセスを検出して解析を妨害するタイプのウイルスを解析したいOS上でデバッガが動作したことを検出する方法を教えてくださいアタッチしてブレークポイントを設定すると、ブレークポイントが機能しない上に強制終了するソフトウェアがあるのですが。デバッガで起動/アタッチすると、デバッギーが終了していないのにデバッガがデバッギー終了と認識します。2で実装されるデータ実行防止機能で注意すべき点があるそうですが...『OllyDbg』のセキュリティホールについて教えてください『OllyDbg』の改造版とはどのようなものですか?MFCのランタイムDLLがエクスポートする関数の詳細を知りたい海外のソフトウェアを日本語化してみたいAPIフックに用いられるプロセス注入用DLLを検出したい逆アセンブルが正常に行えず、しかもエントリーポイントがNOP命令というソフトウェアがあるのですが。『OllyDbg』の操作方法等を解説した参考書はありますか?『OllyDbg』から解析対象を簡単に起動する方法を知りたい。操作上で特に覚えておくと役立つポイントはありますか?『OllyDbg』プラグインの入手先は?API関数呼び出しへのブレークポイント設定の仕方を知りたい。条件付きブレークポイントを設定してみたい。ウィンドウメッセージにブレークポイントを設定してみたい。API関数呼び出し箇所ではない任意の複数コードに一括してブレークポイントを設定したい。リアルタイムアセンブラで注意すべきことは?メモリ内容の内容変動箇所を調べるには?プログラムが参照している文字列の一覧表示機能を使いたい。特定文字列の参照コード一覧表示機能を使いたい。特定のコードにワンタッチで戻る方法が知りたい。コール命令からサブルーチン及び、ジャンプ命令からジャンプ先にワンタッチで移動する方法はありませんか?F7キーでサブルーチンにステップインした後に、簡単にサブルーチンを抜ける方法はありませんか?システムDLL等、デバッギー実行ファイル以外のコードを表示した場合の対処法は?逆アセンブルコードウィンドウ(左上ウィンドウ)でコード変更後の実行ファイルの保存が上手くいきません。Vista以降での動作について教えてください。当サイトQuestions/Suggestionsの「プログラム解析一般Q&A」を参照してください。「64ビット版Windows上での使用」や「セキュリティソフトによる干渉」などといった複合的な要因により、『OllyDbg』のような解析ツールでの解析時に不具合が生じることもあります。そのため、このような不具合発生を回避する、解析専用の環境を構築されることをお勧めします(参照)。逆アセンブルコードリストについて教えて下さい。デバッガ「OllyDbg」で表示されたり、逆アセンブラ「PeRdr」で出力する、プログラムのコードを逆アセンブルと呼ばれる操作により人間がプログラムの処理の流れを視認できるようにしたものを、「逆アセンブルコードリスト」と呼びます。OllyDbgが表示しているのは、対象アプリケーションの起動に伴いプロセスメモリ上に読み込まれた、対象アプリケーションのEXEファイルに含まれるプログラムのコードを、プロセスメモリから読み込んで逆アセンブルしたものです。「PeRdr」は実行ファイルを実行されないままファイルからプログラムのコードを読み込んで逆アセンブルしています。デバッガを用いたPCゲームの解析においては、逆アセンブルコードリストの読解は必須となります。そのため、逆アセンブルコードリストの構成要素である「レジスタ」、「ニーモニック」、「(アセンブリ言語の)命令」、「API関数」等を理解する必要があります。デバッガを用いたPCゲーム解析を始める前に、ヘキサエディタやプロセスメモリエディタといった基本ツールの操作を理解しておくと、デバッガを用いたPCゲーム解析がよりスムーズに理解できるようになります。そのため、これからPCゲーム解析を始めようという方には、いきなりデバッガから入るのではなく、あらかじめプロセスメモリエディタの操作に慣れておくことを強くお勧めします。以下では、32ビットアプリケーションの逆アセンブルコードリストの読解を始めるための端緒とすべく、必要最低限の基本事項を簡潔に解説します。プログラム解析という視点での解説であり、CPUアーキテクチャ全般の解説やプログラミングを目的とする解説ではありません。64ビットアプリケーションの解析についてはこの質問と回答を参照して下さい。以下はPCゲームの開発で一般的に使用されているC/C++言語で開発されたゲームの逆アセンブル例です。今後増えると予想されるC#言語で開発された.NET対応アプリケーションでは以下のような逆アセンブルは行えず、専用の逆コンパイラ等を使用して解析することになります。C言語で開発されたゲームでも、プログラムのコードに圧縮や暗号化を施すことで逆アセンブルを困難にしているケースもあります。これら基本事項の詳細については、当サイトから以下のリンクにて資料や参考となる書籍を紹介していますので、入手・参照されることを強くお勧めします。SDK」は、逆アセンブルコードリストの読解を含むプログラム解析に大いに役立ちます。ネット上での検索も積極的に活用することをお勧めします。デバッグ時の逆アセンブルコードリストとの関わりを理解されることをお勧めします。これは各種チュートリアルや実際の解析を通しての試行錯誤が、理解する上での近道になると考えられます。●アドレス上記の例では「40158F」といった16進数の値。これは、実行されるコードのプロセスメモリ上での番地を指し、32ビットアプリケーションでは4バイトの値となる。EXEファイル等の実行ファイルがプログラムとして実行される際には、まず実行ファイルがシステムにより用意された当該プロセスのためのプロセスメモリ上にロードされ、その実行ファイルに含まれるコードがプロセスメモリ上で実行される。Vista以降では、EXEモジュールをランダムなアドレスにロードする機能ASLRが実装されています。ASLRの解説と、プログラム解析におけるASLRへの対処については、この質問と回答を参照してください)。実行ファイルに付属する、Kernel32.DLL等のシステムファイルではないDLLファイルは基本的にアドレス0x10000000にロードされるが、複数のDLLが使用される場合は別のアドレスにもロードされる。この配置換えをリロケーションと呼ぶ。実行ファイルのおおまかな構造としては、PEヘッダと呼ばれる実行ファイルの基本設定を格納するデータブロックが先頭にあり、その後にセクションと呼ばれる、コードやデータ等の格納内容に応じて区切られたデータブロックが並んでいる。基本的に、実行されるコードが含まれるコードセクションが最初のセクションとなる。10」といった16進数で表示されるデータ。これは、プロセスメモリ上にある実行されるコードの実体で、CPUは0か1で指定された2進数のデータ(バイナリデータ)として読み込む。CPUはこのバイナリデータをコードとして直接解釈して対応する処理を実行するため、このコード対応バイナリデータはマシン語(機械語)と呼ばれる。プログラムの処理とは、このマシン語で指定された処理をCPUが1つ1つ順番に実行していくことを意味する。バイナリデータを16進数で表示しているのは人間にとっての視認性や可読性向上のため。10」といった、ニーモニックと呼ばれる英数字文字列。これはマシン語の内容を人間が理解できるよう分かりやすく翻訳したものでアセンブリ言語と呼ばれる。本来アセンブリ言語はマシン語と1対1で対応する処理をニーモニックの形式で記述して実行ファイルを作成(アセンブル)する開発言語であるため、マシン語からアセンブリ言語に翻訳する処理を「逆アセンブル」という。アセンブリ言語で記述されたコードをアセンブルするソフトウェアをアセンブラと呼ぶ。●オペコードニーモニックの最初にある「PUSH」、「MOV」、「CMP」および「J**」といった英字文字列はCPUが行う処理の種類を指すもので「(アセンブリ言語の)命令」と呼ぶ。ニーモニックの構成要素としてはオペコードと呼ばれる。●オペランドニーモニックの中で、演算等、命令の処理対象となる数値やレジスタ(後述)をオペランドと呼ぶ。EAX,1」においてはEAXレジスタが第1オペランド、数値1が第2オペランドと呼ばれる。]の中のアドレスに格納された値を意味する。[402010]」や単に「[402010]」ならば、アドレス0x402010に格納されたDWORDの値となる。●レジスタオペランドとして使用される、CPUの内部にある一時記憶用メモリ。一般的な命令に使用される汎用レジスタや、浮動小数点数を用いた演算に使われるものおよび、マシン語レベルでのアプリケーションのデバッグ専用のもの等がある。32ビットCPUにおける汎用レジスタは、EAX、EBX、ECX、EDX、ESI、EDIがあり、他には特殊な用途に用いられるESP、EBP、EIP、EFLAGSがある。32ビットCPUにおける汎用レジスタのサイズは4バイト(32ビット)となるが、汎用レジスタE*Xは、4バイトのうちの2バイトや1バイトを処理対象として使用することもできる(EAXレジスタの下位2バイト=AX、AXの上位1バイト=AH、下位1バイト=AL)。レジスタ名先頭の「E」は16ビットCPUのレジスタとの対比で32ビットへ拡張(Extend)されたことを意味する。E*Xレジスタは特に演算やポインタ(アドレスを指定するためにレジスタや特定アドレスに格納された値を使うやり方)およびカウンタ等を主用途とする。E*Xレジスタにはそれぞれ本来の用途(EAX:各種演算、EBX:ポインタ、ECX:カウンタ、EDX:データ一時記憶およびEAXとの連携による乗除算)が定められているがその用途に制限される訳ではない。ESIとEDIレジスタは汎用的な使用も可能だが、本来はデータ転送命令等でデータの転送元アドレス(SI:SourceIndex)や転送先アドレス(DI:DestinationIndex)が格納されるもの。ESP(SP:StackPointer)は現在のスタック(後述)のアドレスが格納される。EBP(BP:BasePointer)は基本的にスタック上のデータに対するポインタとして使用される。EIP(IP:InstructionPointer)は、次に実行される命令のアドレスが格納され、命令が実行されるたびに内容が更新される。●フラグ演算命令や比較命令の実行後、演算結果がゼロか否かや、比較結果での大きいか否かなどを意味するフラグがビット単位の1か0でEFLAGSレジスタに格納される。EFLAGSレジスタにはゼロか否かなど特定条件に対応するビットがあらかじめ指定してあり、条件に合致したらフラグをセット(該当ビットに1を設定)、条件に合致しないならばフラグをクリア(該当ビットに0を設定)する。このフラグの状況を元にジャンプ命令を使ってプログラムの処理を条件分岐させることが可能になる。EFLAGSレジスタ内のこのようなフラグをステータス・フラグと呼ぶ。逆アセンブルコードリスト上では、アドレスやオペランドとして使用される数値は16進数で表示される。一般的に16進数であることを明示する場合は数値の後に「h」を付加するか、数値の前に「0x」を付加することで行う。●スタックプログラムが一時的にデータを格納するメモリ領域。スタック内で新たにデータを格納するアドレスは常にESPレジスタに格納されており、プログラム側でアドレスを直接指定する必要がない。スタックにデータを格納する際はPUSH命令を用い、スタック内では、アドレス0x10FFF8にデータを格納したら次はアドレス0x10FFF4というように、アドレスの高い方から低い方へ向かって、まるで積み木を積むようにデータが格納されるため、これをスタックに積むという。スタックからデータを取り出す際にはPOP命令が用いられ、ESPレジスタのスタックポインタを用いるスタックのデータ格納方式により、後に積まれたデータが先に取り出されることになる。PUSH/POP命令実行時には自動的にESPレジスタの格納値が修正される。汎用レジスタの内容をスタックに格納/取り出しするPUSHAD/POPAD命令や、EFLAGSレジスタの内容をスタックに格納/取り出しするPUSHFD/POPFD命令もある。上記の例では「USER32.GetAsyncKeyState」。Interface)の1要素。この例では、WindowsOSのシステムDLLであるUser32.dllが提供する、特定のキーが押されているか否かを判断する機能を持つGetAsyncKeyState関数を呼び出している。API関数の呼び出しにあたり、関数の処理を実行するために必要なパラメータ(引数:ひきすう)を指定する場合は、PUSH命令で数値そのものあるいはデータが格納されたアドレス等をスタックに積むことで指定する。上記の例では10hがShiftキーを意味する。API関数の多くは、関数の処理が実行されると、関数の処理結果や、関数が成功したか否か等を意味する値(戻り値)がEAXレジスタに格納される。NT系OSが内部的に用いる基本的に非公開のAPI関数を「ネイティブAPI」と呼ぶ。ネイティブAPIはユーザー側(ユーザーモード)とシステム側(カーネルモード)の間で処理の橋渡しを行う役目を持つ。API関数はそれぞれが特定の機能を持つため、例えばCD/DVDチェックの解析においては逆アセンブルコードリスト上で同チェックに頻用されるAPI関数の呼び出しを探す等、PCゲーム解析において解析の手がかりとなることが少なくない。どのようなケースにどのようなAPI関数が使われるかは、当サイトのチュートリアルやQ&Aなどで解説しているので、参照されることをお勧めする。プログラム解析において頻出する基本的な命令MOV命令:「MOVe」すなわち転送命令でメモリ−レジスタ間やレジスタ同士間でのデータの転送を行う。転送元データには数値1といった即値も使用可能。転送の方向は第2オペランドから第1オペランド。転送元のデータはそのまま保持されるので、実際の動作としてはコピーといえる。第2オペランド)により比較し、比較結果はステータス・フラグとしてEFLAGSレジスタに格納される。オペランドの中身は変化しない。TEST命令:論理演算による論理比較命令で、第1オペランドと第2オペランドでAND(論理積)演算を実行し、演算結果はステータス・フラグとしてEFLAGSレジスタに格納される。オペランドの中身は変化しない。JMP命令:「Jump」で無条件ジャンプを意味する。オペランドで指定したアドレスへジャンプし、その後はジャンプ先以降の命令が実行される。通常オペランドでのジャンプ先アドレスの指定には、ジャンプ命令を含むニーモニックの次のニーモニックの先頭アドレスを基準とした相対値を用いる。この相対値はジャンプ距離によって4バイトまたは1バイトで指定し、符号つきの値を用いるため処理の前方向と後方向のどちらにもジャンプ可能。J**命令:「JNZ」「JG」などの条件ジャンプ命令。論理演算命令に伴いEFLAGSレジスタに格納されたフラグの状況(0か1)を条件とし、条件に合致した場合はJMP命令同様にジャンプを行う。条件ジャンプ命令の、J(Jump)と組み合わされる条件指定要素としては、N(Not)、E(Equal)、Z(Zero)、G(Greater:符号有り)、L(Less:符号有り)、A(Above:符号無し)、B(Below:符号無し)などがある。1」実行時にEAXレジスタの中身が値2ならば、この命令の結果にしたがってEFLAGSレジスタのCF、OF、SF、ZF、AF、PFフラグ(後述)が更新され、この後にEFLAGSレジスタでZF=0およびSF=OFすなわち「より大きい」を適合条件とする条件ジャンプ命令JGがある場合はジャンプする。同様に、EAXレジスタの中身が値1ならば、JZ(=JE)、JGE(=JNL)、JAE(=JNB)、JNG(=JLE)、JNA(=JBE)などでジャンプする。CALL命令:サブルーチンと呼ばれる、複数の命令で構成される処理の固まりを呼び出して実行する命令。サブルーチン内でRET命令を実行するとサブルーチンの処理を抜けて呼び出し元に処理が戻る。API関数の呼び出しもほぼ同様の処理といえる。CALL命令実行時には、EIPレジスタに格納されたCALL命令の次の命令のアドレスが自動的にスタックに格納され、RET命令実行時にはスタックに格納されていた同アドレスの値でEIPレジスタの中身を復元する。CALL命令はJMP命令とPUSH命令を同時に行うものともいえる。ADD命令:加算の算術演算命令。他の算術演算命令にはSUB(減算)、MUL(乗算)、DIV(除算)などがある。AND命令:論理積の論理演算命令。他の論理演算命令にはOR(論理和)やXOR(排他的論理和)などがある。Operation」の略。何もしないのではなく、EAXレジスタとEAXレジスタの中身を入れ替えるという、「処理は行うが結果に意味がない命令」。逆アセンブルコードリスト上で既存のコードをNOP命令(オペコードは0x90でオペランドはない)で上書きすることにより、既存のコードの無効化が可能になる。コードの無効化には、実行させたくないコードをJMP命令でスキップさせたり、条件ジャンプ命令を無条件ジャンプに書き替えあるいはジャンプ幅をゼロにするといった様々なアプローチがある。このようなコードの書き替えには、実行ファイルそのものを書き替える方法と、実行に伴いプロセスメモリ上にロードされている実行ファイルに含まれるコードを動的に書き替える方法がある。後者では任意のタイミングでコードを色々と書き替えて動的にプログラムの処理の流れを制御することが可能になるが、あくまでプロセスメモリ上でのコードの変更であるため、その効果は対象プロセスが終了するまでとなる。Address」の略。[EBX+ECX*4]」といったニーモニックで第2オペランドの内容を演算した上で、その結果を第1オペランドに転送する。主なステータス・フラグゼロフラグ(ZF):演算結果がゼロならばセットされ、そうでなければクリアされる。サインフラグ(SF):演算結果の符号が負ならばセットされ、そうでなければクリアされる。キャリーフラグ(CF):演算結果で桁上がりが生じた場合にはセットされ、そうでなければクリアされる。オーバーフローフラグ(OF):符号付き演算で桁あふれが生じたらセットされ、そうでなければクリアされる。ブレークポイントの種類とその違いについて教えて下さい。呼ばれる通常のプログラムの処理では起こらない(筈の)特殊な状況を起こさせる必要があります。デバッギーに例外が生じた時点でデバッギーの制御はデバッガに移るため、デバッガはこの時点でデバッギーのスレッドにおける汎用レジスタやステータス制御レジスタの値等を取得・変更可能です。この違いに応じてデバッギーへの異なる解析アプローチを行うことが可能になります。ブレークポイントこれは、メモリ上に展開・実行されるコード中の任意の箇所のニーモニック先頭アドレス(1バイト)を、「INT3」(オペコードはCC)命令に書き換えるものです。この割り込み命令は実行するとデバッグ例外ハンドラを呼び出す特殊なもので、この呼び出しをデバッガ側で例外として検出します。デバッガはブレーク時に「INT3」で書き換えた箇所を一時的にオリジナルの命令に書き直して、オリジナルの命令を実行させます。ブレークポイントこれは、デバッギーの任意のメモリブロックのアクセス属性を読み(書き)不可に変更することで、デバッギーがそのメモリブロック内のアドレスに読み(書き)操作を行った際にアクセス違反を生じさせ、このアクセス違反をデバッガ側で例外として検出します。このブレークポイントはメモリブロックのアクセス属性を本来ありえない属性に変更するため、デバッギーをクラッシュさせることがあります。このブレークポイント設定によるアクセス違反と、デバッギーのバグ等によるアクセス違反は似て非なるものです。後者の場合は、基本的にデバッガはEIP該当ニーモニックを無効化あるいはEIPの値を次のニーモニック先頭のアドレスに書き換えて例外を処理しないと、例外から抜け出すことができません。アクセス違反によっては、その例外を無視して処理を続行可能なケースもあります。80386」以降のCPUに実装されているデバッグレジスタを使用して、コード実行及びメモリアクセス(読み書き)でブレークさせるものです。上記1及び2と異なり、デバッギーのコードやメモリブロックのアクセス属性は変更しません。ハードウェアブレークポイントはデバッギーのプロセスが持つスレッド毎に設定を行いますが、Windows95では自動的に全スレッドに一括設定されます(『OllyDbg』はデフォルトで全スレッドに一括設定)。デバッグレジスタ8つ(DR0〜DR7)のうち、ハードウェアブレークポイントの設定には最高5つ(DR0/1/2/3+DR7)を使用し、4箇所までブレークポイントを設定可能です。ブレークポイントの設定単位は1,2,4バイトですが、解析者が意図しないブレークの可能性を考えると、通常は1バイトでの設定が適切といえます。上記3種のブレークポイントについては、いずれもデバッギー側で設定されたことを検出可能です。ブレークポイントを設定されていなくとも、デバッギーは自分がデバッグされていることを容易に検出できます。ソフトウェア製作者はリバースエンジニアリング対策として、デバッガから起動・アタッチあるいはブレークポイントを設定された時点で実行される、何らかのリバースエンジニア向けの処理をソフトウェアに仕込むことも可能です。デバッグ特権の必要性が分かりませんデバッグ特権がない状態でも、HBP/INT3ブレークポイントを設定してブレークさせるといった、デバッガとしての処理は一応可能です。そのため、実際の解析ツールの使用上で目立つ点としては、プロセスの列挙に関する点といえます。デバッグ特権がなければ、一部のシステムプロセスなどは認識できません。List)を操作してアクセス権を読み書き不可に設定したプロセスであっても、問題なくそのプロセスメモリの読み書きを行うことができることです。Entry)を書き換えて、PROCESS_VM_READのアクセス権を取り除くことが可能です。変更後のDACLの設定には、SetSecurityDescriptorDacl関数やSetKernelObjectSecurity関数を使用します。同様に、起動直後に自身を再起動させたり、ローダーを経由することで、そのプロセス生成時(CreateProcess関数呼び出し時)に制限を施したDACLを適用するという解析対策も可能です。この場合の新しいDACLを設定する処理には、BuildExplicitAccessWithName関数やSetSecurityDescriptorDacl関数などが使用されます。加えて、デバッグ特権があれば、上記の手法でPROCESS_TERMINATEのアクセス権を取り除いたプロセスでも、強制終了させることが可能です。解析対象のプロセスは、DACLからPROCESS_VM_READなどのアクセス権を除去した状態で起動し、さらに検出したデバッガやプロセスメモリエディタのデバッグ特権を動的に奪えば、自分のプロセスのプロセスメモリをこれらの解析ツールから一切アクセス不可にしたり、プロセス強制終了不可にすることが可能になります。ほとんどの解析ツールは、自分のデバッグ特権が動的に奪われるという事態は想定していません。『うさみみハリケーン』では、特定プロセスのデバッグ特権といった各種特権を動的に有効化・無効化することができます。この機能は、メニューの[ファイル]→[プロセスの各種情報を表示]→[特権]で対象特権を右クリックから実行します。『うさみみハリケーン』起動時に表示されるプロセスリスト上で、右クリックによるポップアップメニューで[プロセスの各種情報を表示]からこの機能を呼び出すこともできます。関連して、解析ツールのデバッグ特権は、解析ツールを管理者権限で起動しないと、特権が無効にされることに注意してください。解析ツールでのプロセスの列挙やオープンに不具合が生じたら、まずは解析ツールを管理者権限で起動し直すことをお勧めします。デバッグ中にシステムDLL内でアクセス違反が生じるのはOSの問題ですか?OSの不具合である可能性もありますが、大抵の場合はデバッギー側でのAPI関数呼び出し時の引数に原因があります。引数の指定内容(特に構造体のメンバ変数)に注意して下さい。プログラマがソフトウェア動作上で問題が無いと判断した上で、引数が不適切になるケースに対処していないこともあるため、デバッグ時のみ表面化するようなアクセス違反をソフトウェアのバグとは断定できません。デバッギーからデタッチすることはできませんか?WindowsOSでは、基本的にデバッガがいったんデバッギーにアタッチすると、デタッチしてデバッギーのデバッグをOSに引き継ぐことはできません。そのため、デバッグ中にデバッガを終了させると、デバッギーは例外等への対処が不可能になるため必ず終了します。これを利用すれば、Windows2000/XPでのサービスプログラム等、特殊な権限を持ち通常は強制終了不可のプロセスでも、強制終了が可能なケースもあります(アタッチしてデバッガごと終了)。同様に、強制終了させたいプロセスを指定してDebugActiveProcess関数でアタッチ後に、DebugBreakProcess関数を呼び出すという方法もあります(デバッガ側では例外を処理しない)。一般的なプロセスはブレークを処理する例外ハンドラを持たないため、この関数呼び出しでも動作を停止させることが可能です。サービスプログラム等の強制終了はシステムに悪影響を与える可能性があるため、十分な注意が必要です。XPで実装されたDebugSetProcessKillOnExit関数を用いれば、デバッガ終了時にデバッギーを終了させないことが可能です。このAPI関数はデバッガのスレッドとデバッギーのプロセスを切り離すものであり、デバッガのスレッドのうち、CreateProcess関数あるいはDebugActiveProcess関数でデバッギーと接続したスレッドのみがデタッチ処理対象です。デバッガがマルチスレッドで動作し、デバッガの機能とは関係ないスレッドがデバッギーのプロセスを操作していたならば、DebugSetProcessKillOnExit関数呼び出しでも完全なデタッチはできません。NtRemoveProcessDebug関数などのネイティブAPIを使用すれば、ほぼ確実なデタッチが可能になります。Helper』があります。XPで実装されたDebugActiveProcessStopというAPI関数もあります。デバッギー側でネイティブAPIのZwSetInformationThread関数を用いてデバッガからデタッチを行う方法は、デタッチ後の例外処理の面で安全性に問題があります。デバッギーのエントリーポイントがコードセクション内ならウイルスには感染していませんか?ウイルスによってはコードセクションの空き領域にコードを埋め込むこともあり、この場合エントリーポイントはコードセクション内になります。ソフトウェアの入手先の信頼度等に関わらず、解析前にウイルスチェックは必ず行ってください。ウイルス対策としてのデバッグ検出について教えて下さい実行ファイルを感染対象とするウイルスとしては、実行ファイルを書き換えてコードを埋め込むタイプがよく知られていますが、一部のウイルスには実行されているプロセスの制御を奪い、そのプロセスメモリに書き込んだウイルスのコードを実行させて動的に感染・破壊活動を行うものもあります。このプロセスの制御を奪う手法は複数ありますが、その内の一つに、デバッガとしてターゲットプロセスにアタッチする手法があります。そのため、ソフトウェア開発者によっては、自作ソフトの動的ウイルス感染に対処するために、デバッグされていることを検出する機能を自作ソフトに実装するケースがあります。一般的に、フリーウェアでデバッグ検出機能が実装されている場合は、対ウイルスの自己防御目的と考えて差し支えないと思われます。デバッギーのウイルス感染やバグによるレジストリ破壊等に備えて、完全に独立した環境で解析を行いたい。Pro』の使用をお勧めします。このソフトは、数ある仮想マシン構築ソフトのなかでも実機の再現性に優れています。Pro』ではセッションで行った全ての操作を元に戻すスナップショット機能があるため、常にOSクリーンインストール直後の状態で解析することが可能です。私が仮想マシン(ゲストOS:WindowsMe/2000/XP)で試した限りでは、『OllyDbg』は問題なく動作します。VirtualBox』を用いることにより、仮想マシンを用いた解析環境を無償で構築可能です。Player』は仮想マシン作成に対応しています。Edge関連の互換性確認用に配布されている、仮想マシン構築ソフト用のゲストOSイメージを使用することも可能です。Player)』を用いた、ゲストOS上で実行されているアプリケーションをホストOS上のVMwareプロセスごと解析するアプローチについては、『「VMware」を用いたフルスクリーン型ゲームへの対処』を参照して下さい。プログラム解析環境としては、Windowsをインストールした仮想マシンを用意し、そこに必要な各種解析ツールを導入していくのが基本といえます。VM」でインストールされるツール群のリストが参考になります。このリストには日本製の各種解析ツールは含まれていません。OSを用いた解析環境について述べていますが、リバースエンジニアリングおよびマルウェア解析用のLinuxディストリビューションである『REMnux』などを使うというアプローチもあります。デバッギー側から仮想マシン構築ソフト上で実行されていることを検出することは、『VMware』と『VirtualBox』のいずれも可能です。この場合、『VMware』ならばIN命令を使った『VMware』特有のポートの有無による検出か、「VMwareUser.exe」・「VMwareService.exe」等『VMware』特有のプロセスの有無や、ドライバ「vmhgfs.sys」等の有無による検出が想定されます。使用されるCPUなど色々な条件を満たせば、CPUID命令を実行してHyper-Vが有効か確認することで、仮想PC上で起動されたことを検出可能になるケースもあります。『VMware』の新しいバージョンでは、仮想PCであることを検出されないための、特殊な設定を行うことが可能です。この場合はVMXファイルに以下の設定を書き込みます。その後、検出されないか確認しながら、必要に応じて以下のうち不要な設定を削除していきます。"true"マルウェア等が実装している仮想PCチェック処理では、たいてい特有の文字列やバイト列を使用します。そこで、『うさみみハリケーン』に同梱している汎用ファイルアナライザ『青い空を見上げればいつもそこに白い猫』の「YARAルールでスキャン機能」では、この特有の文字列等を条件としたYARAルールで、仮想PCチェック処理の検出に対応しています。関連して、対象アプリケーション実行時のファイル・レジストリ書き換えなどを監視し、行われるシステムへの変更内容を仮想化することで、システムを同アプリケーション実行前の状態に復元可能なタイプのソフトも使用可能です。このような「サンドボックス」などと呼ばれるソフトは、実行対象がマルウェアの場合に対抗策を講じられ、システムを元の状態に復元できなくなるケースも考えられます。解析対象アプリケーションの安全性が確認できないならば、仮想マシン構築ソフトを使用されることをお勧めします。解析時にデバッギーが行ったファイル・レジストリ操作の結果だけを簡単に確認したい。このようなアプローチでは、任意のタイミングでファイルやレジストリのスナップショットを作成し、異なるタイミングで作成した2つのスナップショットを比較することで、ファイルおよびレジストリの変更箇所を表示するソフトを使用します。『SystemExplorer』が同種の機能を実装しています。レジストリへの操作を監視することに特化した『レジストリ番犬バロン』や『RegistryChangesView』、『RegFromApp』など、他にも同種のソフトがあります。Monitor』を使用してください。Monitor』は、一般的なファイルの読み書きだけではなく、LoadLibrary関数などによる、DLLファイルのロード処理のモニタリングにも使用可能です。デバッガ検出手法を教えてください。代表的なデバッガ検出手法としては、カーネルモードデバッガ検出専用のものを含めて約20種類程が知られています。そのうち、プログラマが簡単に思いつくような検出例は以下。パッケージソフト、PCゲームおよびシェアウェアのプログラマは、ユーザー視点での動作の安全性確保という点で、Microsoftが文書化していないトリッキーなデバッグ検出手法の実装には消極的です(注:好んで実装するプログラマも実在します)。実際には、プログラムコードとしての実装ではなく、デバッガ検出・対処機能を付加するパッカーの使用によるデバッガ検出というケースもあります。ちなみに、マルウェアにはデバッガ対策を施しているケースが少なくないため、そのソースコードで実践的なデバッガ検出手法を学んでいるリバースエンジニアの方も実在します。現在では、詳細なデバッガ検出手法についての有用な資料がネット上で公開されています。そのため、当サイトの解説とあわせて、下記の資料を参考にされることをお勧めします。これらの資料がネット上で公開されている以上、すでにこれらの手法が陳腐化していることや、さらに発展させた手法が編み出されている可能性を考慮してください。Neutralizationデバッガ対策無効化ライブラリ「ScyllaHide」のドキュメントとソースコード1.IsDebuggerPresent関数このWindows98で実装されたAPI関数を使えば、ソフトウェアは自分がデバッグされているか簡単に知ることが出来ます。この関数の戻り値がゼロでなければデバッグされています。この検出手法は関数呼び出しが偽装されない限り、解析時に容易に発見可能です。WindowsXPサービスパック1で実装された、CheckRemoteDebuggerPresent関数で特定プロセスがデバッグされているか調べることも可能です。IsDebuggerPresent関数を使用せずに、自分でプロセス関連情報(PEBのメンバ変数BeingDebugged)を取得して、デバッグされていることを検出可能ではありますが、外部アプリケーションから被デバッグ検出を簡単に無効化される等の問題があり、実装工数対効果の面で現実性に欠けます。NT系OSでは、このプロセス関連情報を簡易に取得可能にする、ネイティブAPIのNtQueryInformationProcess関数やRtlGetCurrentPeb関数があります。基本的に、アプリケーションが自分自身のPEBを参照するのは、「何か特殊なことをしようとしている」と判断してよいでしょう。2.仮想デバイスドライバ検出これは比較的古い検出手法であり、SoftICEやTRW2000の検出などに使用されます。仮想デバイスドライバを、CreateFile関数でパス解析オフにして検出するものです。一部のセキュリティソフトは、SoftICE他の検出処理を「マルウェアとして疑わしい」要素と判断しているとみられます。"\\\\.\\仮想デバイスドライバ名"という形で行います。}実行ファイル中で参照される仮想デバイスドライバ名の例は以下。Monitor(参考)の分も併記しました。\\.\TRW\\.\SICE\\.\NTICE\\.\FILEVXD\\.\FILEMON\\.\REGVXD\\.\REGMON\\.\Global\ProcmonDebugLogger3.ウィンドウクラス名取得OllyDbgは、そのウィンドウクラス名が「OLLYDBG」となっているため、FindWindow関数(Window名はNULL)か、EnumWindows関数とGetClassName関数併用で検出が可能です。4.INT3サーチソフトウェアがプロセスメモリのモジュールエリアにあるコードセクションを、タイマ制御等で定期的に自分でメモリサーチして、バイナリデータがINT3(0xCC)となっている箇所の数をカウントし、実行ファイル中に保存しておいたオリジナルのカウント値と比較することで、INT3によるブレークポイント設定を検出します。INT3はコードセクションのチェックサム(単純加算・XOR・CRC-32・MD5等)生成による自己改ざん検出にもヒットします。メモリサーチやチェックサム生成を行う以上、コードセクションへの読み込みメモリアクセスが発生する点に注目してください(注:ドライバを使って物理メモリ上からチェックする方法もある)。5.特定メモリエリアのアクセス属性取得VirtualQuery関数を用いて自己プロセス内の特定メモリエリアのアクセス属性を取得し、本来ありえない属性になっている場合はメモリアクセスのブレークポイントが設定されている(あるいは何らかのプロセスメモリ改ざん)と判断します。自己プロセスに対してWriteProcessMemory関数を使用してアクセス属性の異変を探ることも可能です。INT3ブレークポイントやコード動的改変の検出例として、コードセクションに該当するメモリエリアのアクセス属性がPAGE_EXECUTE_WRITECOPYになっている場合は、被デバッグ等検出の可能性が高いといえます。この場合、デバッガ等による同メモリエリアへのプロセスメモリ書き込みが行われた時点で、OSのプロセスメモリ関連処理に伴いアクセス属性は自動的にPAGE_EXECUTE_READWRITEに変化し、元のアクセス属性に戻すことはできません。基本的に、このようなアクセス属性取得による被デバッグ等検出は、アクセス属性を変更しないハードウェアブレークポイント設定の検出とセットで行われる可能性が高いといえます。FS:[0]」といった「FS:[0]」を含むコードが現れます。attached!!","Info",MB_OK);}構造化例外ハンドラを用いた、デバッグレジスタ参照によるハードウェアブレークポイント設定の検出ならば、以下の手法が使用可能です。)」に相当し、たいていJMP命令のすぐ後で実行される、CALL命令での例外フィルタ呼び出し処理を端緒とするのが有効と考えられます。CONTEXT構造体の内容についても各種資料で参照されることをお勧めします。GetExceptionInformation関数はAPI関数ではなく組み込み関数であり、プログラムコードとして展開されます。7.GetThreadContext関数を用いたハードウェアブレークポイント検出デバッグレジスタではなく汎用レジスタならばインラインアセンブラを用いることで簡単に取得可能です。inactive.","Info",MB_OK);}}8.ネイティブAPIのNtQueryInformationProcess関数を使用したデバッグ検出この関数やZwQuerySystemInformation関数他のネイティブAPIでデバッグを検出可能ですが、これらの関数は将来的に互換性が失われる可能性があるため、一般的なアプリケーションへ実装される可能性は低いと考えられます。解析されるであろう特定の処理の実行に要した時間をGetTickCount関数などで計測し、あらかじめ指定した閾値(しきいち・いきち)を超えるとデバッグされている(ブレークやステップ実行が行われた)と判断します。対象プログラムの処理として、本来必要とは考えられない時間関連のAPI関数(参考)の呼び出しと戻り値の大小比較に注目してください。このデバッグ検出手法は、解説や実装例を見る限り、たいていGetTickCount関数が使用されます。用いて、GetTickCount関数ベースでの時間経過を極端に遅くすれば、プログラムコードの改変なしで対処できるケースもあると考えられます。API関数を用いたミリ秒単位の経過時間取得は、PCゲームでの処理タイミング制御時などにも行いますが、PCゲームの場合は、より精度の高いtimeGetTime関数を使用するのが基本とされています。Vista以降では、アドレス0x7FFE0000にあるKUSER_SHARED_DATA構造体の、メンバであるTickCountなどを直接参照する可能性があります(参考)。ファイル名など)を参照します。これはデバッガや、各種APIフックを行うソフトなどから起動された場合に有効な検出手法です。起動後にデバッガからアタッチされても、親プロセスがデバッガのプロセスに変更される訳ではありません。この場合は、まずGetCurrentProcessId関数で自分自身のプロセスIDを取得します。参考までに、以下のインラインアセンブラや、同様にNtCurrentTeb関数の戻り値+20hも、プロセスID取得に使用可能です。eax}次に、CreateToolhelp32Snapshot関数やProcess32First/Process32Next関数を使って、自分のプロセスにおけるPROCESSENTRY32構造体のメンバth32ParentProcessIDを取得します。親プロセスのプロセスIDに対して、CreateToolhelp32Snapshot関数とModule32First関数で、親プロセスのメインモジュールのファイル名やパスを取得します。親プロセスのプロセスIDは、NtQueryInformationProcess関数でも取得可能です(PROCESS_BASIC_INFORMATION構造体のメンバInheritedFromUniqueProcessId)。取得したパスを使って、GetFileVersionInfoSize関数、GetFileVersionInfo関数やVerQueryValue関数で、バージョン情報の詳細を取得します。『OllyDbg』のバージョン情報の「内部名」は「OllyDbg」となっており、この文字列を基に自分がデバッグされていることを検出可能です。デバッガ側でのこの検出手法の回避策としては、リソースのバージョン情報文字列を改変したり、リソースセクションを操作するパッカーを適用することが想定されます。自分がデバッグされている場合への対処策としては、親プロセスがエクスプローラ以外のプロセスならば、親プロセスに対して、パラサイトルーチンを使って、デバッグを行うスレッドが必ず使用するWaitForDebugEvent関数のエントリをフックし、自分のプロセスIDを引数にしてDebugActiveProcessStop関数を呼び出させます。パラサイトルーチンは以下のようになります。関数エントリこれにより、もし自分のプロセスがデバッグされているならば、デバッガをデバッグ不能にさせるか、デバッガの状況によっては自分のプロセスを強制終了させることになり、いずれにしてもデバッガ対策となります。211.INT命令によるデバッガ検出INT3h(BCHK検出)、INT2Fh、INT41h、INT68h等を用います。デバッガ検出手法として必ずしも信頼性の高いものではありません。INT命令を用いたデバッガ検出が上手くいきません(環境:WindowsXP)。INT3h、INT2Fh、INT41h、INT68hを用いたデバッガ検出手法はOSのバージョンやその他の条件に依存するため、一般的なソフトウェアへの実装はお奨めしません。『OllyDbg』のプロセスを検出して解析を妨害するタイプのウイルスを解析したい基本的なOllyDbgのプロセス検出手法としては、Windows上で実行されているプロセスの一覧を取得して、各プロセス名のチェックによりOllyDbgが起動されているかを判断します。API関数を用いてプロセス一覧を取得する方法は5種類ありますが、通常は以下の3つの方法のいずれかを使用します。簡単なプロセス検出回避アプローチとしては、Windowsが把握するプロセス名はプロセスの実行ファイル名となるため、単純にOllyDbgの実行ファイル名を別のものに変更すれば、起動時にエラーメッセージは出るもののプロセス名も変更されOllyDbgのプロセスは検出されなくなります。全プロセスのプロセスメモリ上のモジュールエリアで特定文字列を検索するケースなど、詳細なOllyDbgプロセス検出を行っており、かつマルウェアがプロセス検出ルーチンの無効化を阻止する強固な改ざん対策を実装している場合には、API関数呼び出しへの操作や実行ファイルのリネームとは別のアプローチを行う必要があります。このようなケースでは、まず、そのような解析対策を無効化するための、特殊なツールまたはOllyDbgプラグインを使用します。このようなツールは以下のサイトなどで入手可能です。Breakpoint』などがあります。Toolsこれらの対解析対策ツールやOllyDbgプラグインで対処できないときは、rootkitと呼ばれるツールを用いて、Windowsが保持するプロセスのリストを改変したりプロセス一覧取得用のAPI関数を操作することで、OllyDbgのプロセスをWindows上で隠蔽してからマルウェアの解析を行うというアプローチが有効と考えられます。任意のプロセスの隠蔽機能を持つrootkitは以下のものなどが挙げられます。プロセスの隠蔽はセキュリティ上深刻な問題を招きかねないため、セキュリティソフトによってはこのようなrootkit自体をウイルスやトロイの一種と判断することがあります。下記rootkitは、これらがどのようなツールであるかを十分理解した上で、必ず自己の責任において入手と使用を行って下さい。(Ring3ベースAPIフック)同様に、商用プロテクトが施されたオンラインゲーム用の、ほとんどrootkitと同じ処理を行う、北東アジア製ゲーム解析補助ツールを使用するという選択肢もあります。ゲーム用ツールでありリバースエンジニアリングという面では知名度が低く、かつ英語版が存在しないということもあり、比較的対策されにくいという利点があります。rootkitのようなDKOMで隠蔽されたプロセスのウィンドウ情報を元にプロセスIDを取得して、隠蔽されていないプロセス同様に解析することが可能です。Rootkitが用いるようなAPIフックで隠蔽されたプロセスでも、プロセスIDを取得・解析することができます。これらの特殊なプロセス列挙機能は、『うさみみハリケーン』起動時に表示されるプロセスリスト上で、右クリックにより表示されるポップアップメニューから呼び出します。書き換えによるAPIフックの解除機能を実装しており、rootkit等が実装しているAPIフックを用いた各種解析対策に対処可能なケースもあります。ちなみに、ウイルスの一般的な解析アプローチについては、以下のページが参考になります。未知のバイナリの解析OS上でデバッガが動作したことを検出する方法を教えてくださいこの場合は、OS上で実行されている全てのプロセスで、APIフックを用いてデバッガに関連するAPI関数(DebugActiveProcess関数他)の呼び出しを監視します。APIフックにより、デバッガの動作に限らず、プロセスのオープンや強制終了、プロセスメモリの読み書き、プロセスやスレッドの作成他、API関数を使用する色々な処理を監視可能です。監視だけに止まらず、引数の操作等によるAPI関数呼び出しの無効化もできます。攻撃編』が参考になります。他にもネット上でAPIフックに関する資料を見つけることもできます。APIフックに関して、Windows2000/XP以降を動作環境とする一部のセキュリティソフトやトロイ等では、監視するプロセスの実行ファイルにパッカーが使用されているケース等に対処するために、監視するプロセスのメインモジュールのIATではなく、スタブDLL(各プロセスに読み込まれたシステムDLLのコピー)内にあるAPI関数の開始アドレス以降のバイナリデータを書き換えて、各プロセスにロードさせた監視用DLL内の処理にジャンプさせています。Windows2000/XP/Vistaおよびそれ以降においては全てのスタブDLLがアプリケーション有効アドレス範囲内に収まるため、このような書き換えが可能になります。Windows9xではKernel32.DLLなど一部のシステムDLLのモジュールアドレスはアプリケーション有効アドレス範囲外となるため、一般的なアプリケーションからそのシステムDLLに属するアドレスのバイナリデータは読み込みは可能ですが書き換えはできません。このAPIフック手法において、API関数呼び出しを監視するためのコードは、監視用DLL内ではなくフック対象プロセスの仮想アドレス空間に書き込んだものを使用するという方法もあります。このAPIフックを行うアプリケーション側が逆アセンブラを実装している場合は、監視対象プロセスにおけるAPI関数の開始アドレスではなく、API関数の開始アドレスから4つめのニーモニックの先頭アドレスを書き換えて、監視用DLL内の処理にジャンプさせるといったことも可能です。この場合は監視用DLL内の処理でPUSHAD/POPAD+PUSHFD/POPFD命令を使って処理の安全性を高めると考えられます。API関数の開始アドレス直後を書き換える必要はないことに注意して下さい。ユーザーモードでのAPIフックを用いたOS上でのデバッガ動作検出は、どのような状況でも完璧に検出できる訳ではありません。基本的に、Windows9x環境でかつデバッガがパッカーで圧縮/暗号化されプロセスメモリ上でのIATの解析が必要なケースでは、このデバッガ動作検出は難しくなると考えられます。API関数の開始アドレス以降のバイナリデータを書き換える検出手法では、デバッガ側がデバッガ関連各API関数の開始アドレス以降のバイナリデータ16バイト程度を、『あらかじめAPIフックされていないクリーンな状況で取得しておいた』オリジナルのバイナリデータを用いて高頻度で書き戻すことにより、APIフックによるデバッガ動作検出を無効化させることも可能です。Table)を同ドライバ内の関数に繋がるよう書き換えています。Restore』を用いてSDTを書き戻すことで無効化が可能です。x64用の64ビット版Windowsでは、その仕様上このようなSDT(およびIDT、GDT)の書き換えは行えません。●<参考>セキュリティソフトのAPIフック対象リスト例(一部を抜粋)[kernel32.dll]CreateProcessInternalWDebugActiveProcessGetProcAddressLoadLibraryExWMapViewOfFileMapViewOfFileExMoveFileWOpenProcessReadProcessMemoryVirtualProtectVirtualProtectExWriteProcessMemory[user32.dll]GetWindowThreadProcessIdPostMessageAPostMessageWSendInputSendMessageASendMessageWSetCursorPosSetWindowsHookExASetWindowsHookExWkeybd_eventmouse_event[ntdll.dll]NtOpenProcessNtQuerySystemInformationNtSuspendThreadNtTerminateThreadRtlGetNativeSystemInformationZwOpenProcessZwQuerySystemInformationZwReadVirtualMemoryZwSuspendThreadZwTerminateThreadZwWriteVirtualMemoryアタッチしてブレークポイントを設定すると、ブレークポイントが機能しない上に強制終了するソフトウェアがあるのですが。用いたデバッガ対策である可能性があります。逆アセンブルコードリスト上で、構造化例外ハンドラに特有のセグメントレジスタへのアクセスを追いかけてみてください。解析者が逆アセンブルコードリスト上で「FS:[0]」を検索することを想定して、意図的に「FS:[初期化した汎用レジスタ]」としているケースもありますので注意が必要です。デバッガで起動/アタッチすると、デバッギーが終了していないのにデバッガがデバッギー終了と認識します。まれなケースですが、デバッガのデバッグアプローチの方法とデバッギーのデバッガ対策の組み合わせにより、この様な状況が生じることがあります。デバッガでのアプローチ手法を変えてみてください。(TIB)」と呼ばれる、スレッドのローカル格納領域です。このデータブロックの先頭アドレスはセグメントレジスタを用いて、「FS:[18]」で取得することができます。EAX,FS:[18]」の処理を行う、ネイティブAPIのNtCurrentTeb関数を使用する方法もあります。『OllyDbg』が表示する「最後のエラー」のエラーコードは「FS:[34]」(Win2k/XP/Vista/7)または「FS:[60]」(Win9x/Me)の値です。7でのGetLastError関数の内部処理は以下のようになっています。EAX,[EAX+34]RETNただし、このエラーコードの値がGetLastError関数の戻り値と一致しないケースもあります。Windowsの一部のバージョンでのみGetLastError関数でエラーコードを取得可能なAPI関数に注意して下さい。『スペシャルねこまんま57号』にはエラーコードを日本語の説明文に変換する機能を実装しています(メニューの[システム]→[稼動アプリケーション制御]のダイアログ下部)。ちなみに、デバッギーのメインスレッドで「FS:[04]」と「FS:[08]」の値からスタックエリアを特定することもできます。SP2で仕様が変更されたため、NT系OSにおいて必ずしも従来のように各プロセスの特定アドレス(0x7FFDF000)以降にあるとは限りません。SDK等の資料ではこの関数の仕様が将来的に変更される可能性を示唆しており、プログラム解析ツールへの実装は注意が必要です。解析対象プログラム側では、Microsoftが文書化していないネイティブAPIである、RtlGetCurrentPeb関数を使用することで自分のPEBのアドレスを取得できます。他のアプローチとしては、VirtualAllocEx関数、WriteProcessMemory関数およびCreateRemoteThread関数を用いて解析対象プロセスのスレッドとして以下の様なアセンブルコードを実行させることで、PEBのアドレスが格納されるFS:[30]の値を出力させ、ReadProcessMemory関数でその値を取得することも可能です。・以下の「00403000-648B0530000000」といった文字列は、『うさみみハリケーン』や『スペシャルねこまんま57号』で使用可能なプロセスメモリ書き換え用の改造コード(書き換え処理自動化用のスクリプト)です。[403050],EAX0040300D-890550304000;RETN00403013-C3●参考<IsDebuggerPresent関数無効化>PEBのアドレス取得に伴い、IsDebuggerPresent関数がTEB経由で参照する、PEB構造体に含まれるプロセスの被デバッグ情報を指すメンバ変数BeingDebuggedの書き替え(1→0)により、同関数によるデバッグ検出の無効化が可能になります。[EAX+2],000403007-C6800200000000;RETN0040300E-C3●参考<OSバージョン偽装>PEBのアドレス取得に伴い、解析対象アプリケーションがGetVersionEx関数で取得するWindowsのバージョンを偽装することも可能です。8のバージョン情報を返す仕様になっています(参照)。8.1/10対応項目の記述により回避可能ですが、同マニフェストによる対処時は、GetVersion(Ex)関数以外の処理にも影響が及びます。8.1以降の正確なバージョン情報の取得のみが目的のケースでは、NtQueryInformationProcess関数でアドレスを取得した、自プロセスのPEBからバージョン情報を取得するというアプローチが選択肢の一つとなります。PEBでは先頭アドレスから+A4h(32Bit)、あるいは+118h(64Bit)以降に、メジャーバージョン、マイナーバージョンおよびビルドナンバーといったバージョン情報が格納されています(下記参照)。ntdll.dllがエクスポートするRtlGetVersion関数でもPEBを参照しており、正確なバージョン取得が可能です。●参考<PEB構造体>注意:以下は公式の情報ではない上、今後のWindowsのアップデートでメンバが変更される可能性もあります。参考程度として下さい。*PPEB;関連して、解析ツールがGetThreadContext関数を用いて解析対象プロセスに属するスレッドのセグメントレジスタを取得済みである場合は、GetThreadSelectorEntry関数でTEBのアドレスを取得して、そこからプロセスとスレッドの各種情報を参照することもできます。WindowsXPのSP1以前やWindows2000であれば、メインスレッドのTEBのアドレスに+1000hすることでPEBのアドレスになります。Prevention)機能により、コードが実行されるメモリエリアは、必ずアクセス属性として実行属性が必要になります。パラサイトルーチンを埋め込むメモリエリアとして、コードセクション以外のセクションの空き領域を使用する場合、そのセクションを含むメモリエリアにはアクセス属性として実行属性が必須となります。パッカーによりパックされたアプリケーションが、起動時に実行する解凍/復号化ルーチンを格納したセクションも同様です。このようなケースでは、PEヘッダで指定された当該セクションのCharacteristicsとして実行属性IMAGE_SCN_MEM_EXECUTE(0x20000000)を論理和で追加設定することで対処可能と考えられます。『うさみみハリケーン』付属のPEエディタ『UMPE』を使用することで、セクションの詳細情報の表示や属性変更が可能です。)を使えば、実行及び読み書き属性を持つ任意の名前とサイズのセクションを、実行ファイルに追加することができます。モジュールエリア上の実行属性を持つセクション以外のメモリエリアでは、コードを実行するためにはVirtualAlloc関数によるメモリ割り当て時にPAGE_EXECUTE等の実行属性を付加する必要があります。VirtualAllocEx関数による他プロセス上でのメモリ割り当てや、すでに割り当てられたメモリエリアのアクセス属性変更についても同様です。既定プロセスヒープやスタックエリア上でのコード実行は、原則不可となります。HeapCreate関数で第1引数に定数HEAP_CREATE_ENABLE_EXECUTE(0x00040000)を論理和で設定することにより、コードを実行可能なヒープの作成が可能です。(0xC0000005)が発生します。従来のメモリアクセス違反と異なり、例外ハンドラのサーチ無しにプロセスが終了されることに注意が必要です。デバッガを用いてもこのデータ実行防止機能により発生した例外を動的に無効化することはできません。このデータ実行防止機能にはアプリケーションを指定して無効化するオプションが実装されています。設定方法については、「プログラム解析一般Q&A」を参照してください。『OllyDbg』のセキュリティホールについて教えてくださいOllyDbgの1.10及び過去のいくつかのバージョンでは、デバッギーがOutputDebugString関数の第一引数に「%s」や「%08X」等の書式指定文字列を含んだ文字列を指定した場合に、その出力文字列をそのまま表示せず、wsprintf関数を実行するように、スタックの内容を元にその書式指定文字列を変換して表示するというバグがあります。このため、悪意のあるデバッギーが、書式指定文字列を大量に含む文字列をOutputDebugString関数で出力した場合、OllyDbgはクラッシュすることがあります。応急的な対処策としては、デバッギーのOutputDebugString関数呼び出しを無効化することが挙げられます。同関数の呼び出しにブレークポイントを設定しておいて、第一引数の内容を確認するようにしておくことも有効な対処策と考えられます。OllyDbg実行ファイル書き換えによる対処の方法は、下記質問を参照して下さい。完璧な対処ではありません。『うさみみハリケーン』のデバッガには、上記のセキュリティホールはありませんので、『うさみみハリケーン』であらかじめデバッグ文字列の取得を試してみることも予防策として有効です。『OllyDbg』の改造版とはどのようなものですか?OllyDbg1.10は複数の『改造版』がネット上で配布されています。Forums』などで有志が公開したパッチ情報を組み込んだり、ネット上で公開されているOllyDbgプラグインなどを同梱したものです。リソースを改変しているケースもありますが、OllyDbgの機能や利便性にはさほど影響のないものが殆どです。アンチデバッグ対策等、改造版がウリにしている追加機能も、実際はそのような機能を持つOllyDbgプラグインを同梱したり、実行ファイル名を変えただけということが多いようです。既知のプラグインに偽装した、悪意のあるプラグインが同梱される可能性を考慮すれば、ネット上の出所不明な再配布『OllyDbg』の入手はお勧めできません。パッチについては概ね以下のものが組み込まれています。)で簡単に行うことが可能です。「シンボルサーバー使用可能化」については、下記質問を参照して下さい。64なお、シンボルサーバー使用可能化など、環境によっては上記パッチによりOllyDbgの一部の機能が使用不能になることもあります。パッチコード実行の際にはバックアップの作成をお勧めします。Class)の共有DLLがエクスポートする関数は、そのDLL内では名前が設定されていないため、逆アセンブルコードリスト上ではたいてい関数名が序数(関数に設定された番号)で表示されることになります。この関数にも、一般的なAPI関数のような、実際の機能を表す関数名が設定されています。Studio(有償版)に付属するDEFファイルをテキストエディタで開けば、関数の序数を基にして本来の関数名を確認することができます。Studioインストール先フォルダの以下の場所にあります。Studioの有償版は、Microsoftがネット上で配布している評価版で試用可能です。Community」もあります。MFCのエクスポート関数名の解析については、以下のソフトの同梱資料が参考になります。海外のソフトウェアを日本語化してみたい以下の解説は、デバッガを用いたプログラム解析の応用としての日本語化について述べています。プログラム解析とはリンクしない一般的な日本語化では、基本的にバイナリエディタとリソースエディタでの書き換えのみで日本語化を行います。ソフトウェアの日本語化にあたっては、バイナリエディタ、リソースエディタ、さらにプロセスメモリエディタやデバッガも使用することになるため、これら各種解析ツールの使い方を学ぶという点で良い経験になります。加えて、日本語化という形で結実したものが他の方に役立つ点も、有益なことといえるでしょう。日本語化する対象のソフトウェアは、日本語のものでは同種または同機能を持つソフトウェアが存在しないものにしましょう。私の日本語化経験を含めた、過去の日本語化例を見る限り、日本語のものでおおむね事足りるにもかかわらず、需要を無視して同種の海外のソフトウェアを日本語化しても、さして見向きもされず虚しい結果に終わります。対象ソフトウェアがシェアウェアならば、トラブル回避のため、すでに日本の企業が翻訳権を取得し、日本語化したものを販売していないか、事前に十分に調査してください。実際の日本語化は、基本的に以下の手順で行います。過去の実例を見る限り、日本語化における各種の問題を、一人で全てを解決しようとするより、色々な協力者からアイディアを頂いて解決していくことで、日本語化の完成度が高まることが少なくありません。自分で努力し、かつ「善意による人の意見には耳を傾ける」という姿勢が、日本語化の質を高めるといえます。一方で、(悪意によるものを含む)人の意見に左右され過ぎないよう自分を律することも必要です。SDKなどを参照してください。使用するツールについては、当Webサイトのツール欄を参照してください。対象ソフトウェアがパッカーを使用している場合は、作者の意図を尊重して、あえてアンパックをしてまで日本語化せず、まずは作者に多言語対応用DLLの導入など、アンパックなしで日本語化できるよう要望を出すことが望ましいといえます。使用されているパッカーが可逆性のあるUPXの場合は、アンパックや翻訳パッチも「作者の想定範囲内」と考える向きもあります。次善策としては、後述のプロセスメモリ書き換え型日本語化パッチの作成が挙げられます。1.バイナリエディタで実行ファイル内データセクションの文字列を書き換え実行ファイル中のオリジナル言語文字列を、元の文字列サイズ内に収まるよう注意しながら、日本語文字列に書き換えます。事前にANSI・Unicodeといった文字コードの違いや、その文字列終端を意味する00h・0000hを理解する必要があります。ユーザー視点での分かりやすさを基準に、正確な日本語訳と若干の意訳を織り交ぜて使うと、ユーザーに違和感を感じさせない「センスの良い」日本語化になります。使用されるコンパイラによっては、1つの文字列が共用されるケースが生じることに注意してください。File」という文字列があり、プログラムの1箇所からはこの文字列そのものを、もう1箇所からはこの文字列中の「File」という文字列を参照するといったケースです。そのため、日本語化の進捗状況に応じて、デバッガあるいはプロセスメモリエディタの逆アセンブラを使い、逆アセンブルコードリスト上での参照文字列一覧を確認されることをお勧めします。この段階での作業工数削減のため、可能ならば、バイナリエディタでの文字列書き換えを補助するツールの自作をお勧めします。2.リソースエディタでリソースのフォント名や文字列を書き換え日本語化に併せて、ダイアログのサイズ、ボタンのサイズや配置、コンボボックスのリスト縦サイズなどで、ユーザーインターフェイスを改良し「使いやすくする」ことにも配慮しましょう。日本語版』付属の『ResUpdate』が使用可能です。私の場合は、リソース書き換え内容を『eXeScope』用のスクリプト形式で保存しておき、以降のバージョンアップ時のリソース書き換え処理を自動化させています。Gothic」の9ポイントになっています。ボタンなどのリソースをリソースセクションに格納せず、プログラムの処理としてボタンなどのコントロールを動的に作成するケースもあります。プログラミングでは、主にダイアログ上で表示されるボタンやエディットボックス、リストボックスなどを「コントロール」といいます。この場合は、CreateWindow関数の第1引数や、CreateWindowEx関数の第2引数で、コントロールの作成を設定する以下の文字列(例)が参照されます。これらのAPI関数呼び出し時の引数で、コントロールの文字列やサイズも設定されます。BUTTONCOMBOBOXEDITLISTBOX他3.プログラム上のフォント作成処理を書き換え対象アプリケーションが動的にフォントを作成しているならば、デバッガあるいはプロセスメモリエディタの逆アセンブラを使ってその処理を書き換え、アドレス→オフセット変換結果を使って、その変更内容を実行ファイルに適用して日本語文字列対応にします。CreateFont関数やCreateFontIndirect関数呼び出し時の引数が書き換え対象となります。Gothic」など使用状況に応じた適当な日本語フォント名に変更します。CreateFontIndirect関数ならば、第1引数で参照されるLOGFONT構造体の内容に対し、同様の書き換えを行います。書き換えアプリケーションによっては、プログラムの処理で必要となる固定文字列を、プロセスメモリ上に動的に作成・変更して使用することがあります。解析やプログラムコード書き換えに要する作業工数を勘案すれば、このような文字列は「できれば」日本語化するという考えで良いと思われます。散見されるケースとしては、プログラム解析ツールなどのUnicode文字列(バイナリデータ)検索機能で、入力文字列をANSI文字列として認識し、それを内部的にUnicode文字列へ変換している場合に、変換後の文字列のサイズ(バイト数)を、単純に元の文字列のサイズの2倍に固定するケースがあります。例として日本語で「諸行無常」はANSIでもUnicodeでも文字列のサイズは8バイトですが、上記のケースでは文字列サイズを2倍にした16バイトのバイナリデータとして検索することになります(当然検索に失敗する)。これは、特に欧米の1バイト文字を使用している人たちにとって、ANSI文字列をUnicode文字列に変換すれば必ず文字列のサイズは2倍になるという、彼らの「常識」が原因で生じる問題(≠バグ)です。この場合はMultiByteToWideChar関数呼び出し時の処理を観察し、同関数の戻り値(変換後の正しい文字数)を使って、検索対象バイト数を単純に元の文字列サイズの2倍にしている処理を書き換えることになります。プログラムコードの注入といった、やや煩雑な書き換え処理が必要となるため、可能ならば作者に対応を促すという選択もありえます。この場合は作者側では動作確認ができないため、対応を求めた自分が責任を持って動作確認を行うことになります。以上の日本語化結果を適用した実行ファイルと、オリジナルの実行ファイルを元に、パッチ作成ツールを使って日本語化パッチを作成します。同梱する説明文書も作成し、日本語化済実行ファイルの動作確認や、パッチのウイルスチェックを行ったうえで配布します。(参考)プロセスメモリ書き換えによる日本語化もし、日本語化対象のソフトウェアが解析・改造対策を施している場合や、実行ファイルのデジタル署名を保持させたい場合は、そのプロセスメモリを書き換えるタイプの日本語化パッチを製作するという手段もあります。表示済みのコントロールの文字列などは、単純なプロセスメモリ書き換えでは日本語化できないといった制約があります。メッセージ送信で、プログラムの処理としての動的な文字列書き換えが必要となるケースもあります。対象実行ファイル起動時にエントリーポイントで停止させ(参照)、その状態でプロセスメモリ上のリソースデータを書き換えます。この種の日本語化には、ローダー兼プロセスメモリパッチャーを製作する、プログラミングの知識と開発環境が必要となります。)を使用すれば、『スペシャルねこまんま57号』を起動するだけで、用意しておいた日本語化用の改造コード群を簡単に自動実行できます。APIフックに用いられるプロセス注入用DLLを検出したい自分のプロセスに注入された、ユーザーモードでのAPIフック用DLLモジュールの検出は、基本的に特定モジュール名を元に行います。一般的に、APIフックに用いられるDLLはファイル名が固定になっているケースが多いため、たいていはモジュールのファイル名を元に、使用されるであろう特定ツールからのAPIフックを検出可能です。Date」系、他にはユーザーモードで動作する各種モニタリングツールの検出が挙げられます。この場合は、GetModuleHandle関数を使用して、その戻り値で特定DLLモジュールの有無を判断します。API(PSAPI)のEnumProcessModules関数・GetModuleFileNameEx関数も使用可能です。ネイティブAPIのNtQueryVirtualMemory関数を使用し、「MemorySectionName」として自分のプロセスにロードされたDLLモジュール(のパス)を列挙することもできます。API関数を使用せずに、PEBからプロセスメモリ上にあるモジュールのリストを辿ることも可能です(参考)。CreateRemoteThread関数などを用いた、外部ツールからのDLL注入(ロード)を検出するために、ntdll.dllのエクスポート関数であるLdrLoadDll関数を自分自身でフックする方法もあります。セキュリティソフトが原因でLdrLoadDll関数へのフックが失敗することもあるため、必要に応じてLoadLibraryEx関数を自前でフックします。この手法では、APIフック対象プロセスを、起動時にエントリーポイントでいったん停止させてから、DLL注入とAPIフックを行うツールには対処できません。『うさみみハリケーン』では実行ファイルを指定して起動する際に、エントリーポイントで実行を一時停止させることができます(メニューの[ファイル]→[ファイルを指定して実行])。近年では、APIフックを行うツールが、モジュール一覧からAPIフックを検出されること等に対処するため、APIフック対象プロセスのプロセスメモリ上にある、ロードされたモジュールのリストを書き換えて、APIフックに用いるDLLモジュールを隠蔽する手法が広まりつつあります。この隠蔽手法では、対象プロセスのPEBからPEB_LDR_DATA構造体をたどり、同構造体の3つのLIST_ENTRYでFlink・Blinkを修正して、APIフック用DLLモジュールをリンクから除外します。これはあくまでモジュールのリストの改変であり、プロセスメモリ上のモジュール自体が隠蔽される訳ではありません。この隠蔽手法が使用されても、VirtualQuery関数を使用して64KB境界上にあるタイプがMEM_IMAGEのページでPEヘッダ取得後、リソースセクションのアドレスとサイズを取得してから特定文字列検索などといった、プロセスメモリの精査により、APIフック用DLLモジュールを検出できる余地はあります。APIフックにあたって、DLLモジュールの注入が必須となる訳ではありません。実行属性を持つプロセスメモリ上の任意のメモリエリアにプログラムコードを書き込み、IATやAPI関数のエントリからそのプログラムコードにジャンプさせることで、注入DLLを用いるAPIフックと同様の処理を行わせることが可能です。APIフック時の取得データをアウトプットする場合は、API関数呼び出し時の引数あるいは呼び出し後の戻り値を、wsprintf関数などで文字列データに変換し、OutputDebugString関数で出力します。API関数の呼び出しは関数エントリのアドレスを直接CALLします。)を参照してください。)を使えば、対象プロセスへのアタッチなしに取得可能です。逆アセンブルが正常に行えず、しかもエントリーポイントがNOP命令というソフトウェアがあるのですが。単純な偽装済UPXでした(実物で確認)。エントリーポイントを1バイト前にずらしてNOP命令から開始するのは、『UMPE』や『PEiD』等パッカーの種類を特定する特殊なソフトウェアにより、エントリーポイントを基点とするバイナリパターンを元に、UPX圧縮と判定されるのを避けるためです。UPXで自作のソフトウェアの実行ファイルを圧縮し、デバッガで起動してエントリーポイントから展開ルーチンを抜けて、本来のエントリーポイントに至るまでの処理を考察されることをお奨めします。オリジナルとUPX圧縮後の実行ファイルでPEヘッダの内容を比較してみて下さい。デバッガなどのプログラム解析関連ツールを自作してみたいデバッガを含むプログラム解析関連ツールを自作して無償で公開するのは、プログラム解析の振興だけにとどまらず、自己のプログラミングや解析のスキルアップという面からみても素晴らしいことです。『OllyDbg』のような優秀なデバッガがある以上、重複する機能を持つデバッガの自作よりは、『OllyDbg』に無い機能を実装した『OllyDbg』プラグインやプログラム解析関連ツールなどを自作する方が、そのプラグインやツールのユーザーにとって、より解析における利便性を向上させたりアプローチの可能性を広げるという点で有益と考えられます。『うさみみハリケーン』のデバッガが、スレッド毎のブレークポイント設定機能など『OllyDbg』に無い機能を重視して実装しているのは上記の考えによるものです。その手法を解説されていますので、参照されることをお勧めします。SDKやネット上の検索に加え、参考図書、プログラミング系サイトの資料も役立ちます。プログラム解析関連ツールの自作で参考になるサイトは、当サイトのメインページでリンクしていますが、それ以外では以下などが挙げられます。ロシア語や中国語のサイトに有用な解説がみつかることもありますので、Googleなどで検索対象を日本語・英語のサイトに限定しないことをお勧めします。ソースコード検索http://code.google.com/なお、プラグインやツールの製作にあたっては、まずそれらが必要となる局面や需要を十分に検討した上でプログラミングを進めて下さい。最初にコンセプトを明確にしておかないと、実装する機能などで迷いが生じ、プログラミングが迷走することになりかねません。ソフトウェア製作一般にいえることですが、『ユーザーに目を向けて』開発とサポートを行って下さい。ユーザーが喜ぶものを、ユーザーの役に立つものを作るという「もの作りの基本」を忘れると、ユーザーから目を向けられなくなります。プロセスメモリ上のモジュールエリアを実行ファイルとしてダンプ(ファイルに保存)しても、正常に動作しないのは何故ですか?プロセスメモリ上にロードされた実行ファイルと、元のディスクイメージ上の実行ファイルは構造が異なるためです。当サイトのチュートリアル「オフセット−アドレス変換の原理とCDチェック解除への応用」で述べているように、PEヘッダ内のセクション情報にはメモリイメージ上での設定とディスクイメージ上での設定両方が含まれており、単純にプロセスメモリ上からダンプしたものでは、セクション情報に齟齬が生じるため修正が必要です。UPX等による実行ファイルの圧縮やその他の各種パッカーによる実行ファイルの暗号化等で実行ファイルに操作が加えられている場合は、他にも修正しなければならない箇所があります。プログラムとしては自分がオリジナルかダンプされたものか判別するのは容易であり、ダンプした実行ファイルを起動すると警告を表示するソフトウェアも実在します。例:UPXで圧縮された実行ファイルをプロセスメモリ上からダンプした場合は、以下の操作で正常に動作する実行ファイルが得られます。このような解凍あるいは復号化操作は、リバースエンジニアの間ではどちらも「アンパック」と呼ばれています。Code」の修正(動作上必須ではない)『うさみみハリケーン』および同梱PEダンパー兼PEエディタ「UMPE」では、モジュールのダンプ時に「pe_unmapper」を使って自動的にセクション情報の修正等を行います。これによりダンプしたモジュールをPEファイルとしてそのまま実行可能にしたり、解析を容易にすることができます。この修正にIATの再構築は含まれません。他人が製作したソフトウェアの実行ファイルのアンパックは、公益を目的とする脆弱性の解析や、マルウェアの解析および、日本語化目的等の特殊なケース以外は、著作権法や不正競争防止法に抵触するといわれていますので注意して下さい。解析超初心者がデバッガで解析対象を起動する前に行うべきことは?以下は複数のリバースエンジニアの方々から頂いた意見をまとめたものです。質問で「起動前」となっているので、解析対象の実際の動作を見ないとアプローチを想定できないケースは考慮していません。以下のような解析の方向性を探るための、本格的な解析の前段階にあたるアプローチは、「表層解析」と呼ばれることがあります。される各種アルゴリズム、各種解析対策、その他挙動に関する情報といった付随情報を取得4.PCゲームの場合はリソースエディタでリソースも確認してデバッグモード等の有無を判断(PCゲームに限らずリソースにEXE・DLLファイルを格納するケースもある)5.以上と既存のチュートリアル等を元にどのようなアプローチを行うか想定6.想定したアプローチにおいて、API関数等の必要な知識が不足している場合はあらかじめ資料で確認しておくデバッガで解析対象を起動後に場当たり的なアプローチを行うのではなく、あらかじめ解析対象について考察することが解析スキルを向上させる上で重要です。既存のチュートリアルで解説されている手法を漫然となぞるのではなく、解析中も常にアプローチのポイントとなる点を自分なりに考えることにより、必要最小限の手数で効果的な解析を行うための解析センスを磨くことが可能です。『OllyDbg』の操作方法等を解説した参考書はありますか?プログラム解析の解説書で、OllyDbgについての解説があるものとしては以下が挙げられます。いずれもOllyDbgを使いこなす上で必要となるアセンブリ言語やAPI関数および基本的なアプローチ方法等、プログラム解析の基本事項も解説しており、有用な解説書と言えます。・クラッキングバイブル『OllyDbg』から解析対象を簡単に起動する方法を知りたい。バイナリエディタやリソースエディタ他の、各種解析ツールなどについても、エクスプローラ上での実行ファイル右クリックで表示されるポップアップメニューに同ツールを登録する、上記同様のレジストリ操作を行うことをお奨めします。このレジストリ操作は、当Webサイトのツール欄で配布している、『PeRdr』用の「エクスプローラへの登録用レジストリファイル(日本語説明つき)」が参考になります。操作上で特に覚えておくと役立つポイントはありますか?『OllyDbg』では、マウスで各ウィンドウ上の数値や範囲等を選択すると、そこから右クリックでポップアップメニューを呼び出し、選択内容に応じた色々な機能を使うことができます。操作に慣れないうちは色々な箇所で右クリックして、どのような機能があるか確認しておくことをお奨めします。分かり辛いのですが、レジスタウィンドウ(右上ウィンドウ)では汎用レジスタだけでなくEFLAGSレジスタやゼロフラグ等の各ステータスフラグも変更可能です。ウィンドウによってはドラッグまたは「Shift」キーを押しながら範囲を選択することで複数列等範囲選択が可能で、レジスタウィンドウ(右上ウィンドウ)ではドラッグで表示内容の移動を行うこともできます。『OllyDbg』プラグインの入手先は?以下のページを参照して下さい。最初は「OllyDump」、「OllyScript」などの基本的なプラグインを導入して使用法を理解し、その後必要に応じて少しずつ追加していくと良いでしょう。PluginsAPI関数呼び出しへのブレークポイント設定の仕方を知りたい。特定のコードにブレークポイントを設定する場合は、メインウィンドウの左上ウィンドウ上で逆アセンブルコードリストから目的のコードを選択してF2キーですが、API関数へのブレークポイントの場合は以下の手法を用います。module」(ラベル名(現在のモジュール内))で、デバッギーが使用する関数一覧を表示させます(「Ctrl」キー+「N」キーでも可)。by」(整列)メニューを使うと目的の関数を探し易くなります。options」(解析詳細設定)→「Addresses」(アドレス)タブで設定できます。reference」(全ての参照にブレークポイントをセット)で、目的の関数を呼び出すコードに一括してブレークポイント設定を行います。DS:[<USER32.DialogBoxParamA>]」)も参照箇所に含まれますので、必要に応じてこのジャンプ命令へのブレークポイントを解除して下さい。import」(インポート関数の一覧表示)で関数呼び出し箇所のコード一覧を表示させ、各コードをマウスや上下カーソルキーで選択してF2キーでブレークポイント設定(解除)を行います。条件付きブレークポイントを設定してみたい。レジスタや参照アドレスの値等が条件の場合は、メインウィンドウの左上ウィンドウ上で、目的のコードを選択してから「Shift」キー+F2キーでブレークする条件を設定します。条件式のフォーマットはヘルプを参照して下さい。[432100]<=(EAX+270F)また、「Shift」キー+F4キーでログ付き条件ブレークポイントを設定できます。ここでの式の例としては上記条件式の左辺(レジスタや特定アドレスの格納値)等です。これにより、条件判定時の式の値がログウィンドウに記録されます。ログウィンドウは「Alt」キー+「L」キーで呼び出せます。ウィンドウメッセージにブレークポイントを設定してみたい。WinProc」(メッセージブレークポイントをセット->WinProc)で詳細設定ダイアログを呼び出してブレークポイントを設定します。WinProc」(WinProcのアドレス取得の為コードの注入を許可する)で正確なウィンドウプロシージャを認識することが可能です。この手法は安全性と確実性に問題がありますので注意して下さい。このオプションを使用した場合は、デバッギーをF12キー等で停止させた状態でのみウィンドウプロシージャにメッセージブレークポイントを設定して下さい。上記の手法で上手くメッセージブレークポイントを設定できない場合は手動で行います。この場合は、ウィンドウメッセージを認識するウィンドウプロシージャの、先頭コードか呼び出し元コードに対し条件付きブレークポイントを設定します。同プロシージャのアドレスはRegisterClass関数やダイアログ生成関数の引数で確認可能です。このアドレスは、ウィンドウプロシージャで処理しないウィンドウメッセージをシステム側で処理させるための、DefWindowProc関数の呼び出し箇所から探し出すことも可能です。DefWindowProc関数は通常ウィンドウプロシージャの最後に近い部分で呼び出されます。ダイアログベースのアプリケーションでは通常プログラムの実行処理としてDefWindowProc関数を呼び出すことはありません。WM_LBUTTONDBLCLKの場合の条件式は下記。MSG==0203目的のプロシージャ内でウィンドウメッセージの値が格納されるアドレスとメッセージ名を指定することもできます。[EBP+C]==WM_LBUTTONDBLCLKなお、目的のウィンドウに送られるウィンドウメッセージの監視を行いたい場合は、メッセージループのTranslateMessage関数呼び出し箇所にログ付き条件ブレークポイント(式:MSG)を設定してブレーク結果をログウィンドウに表示させることで、メッセージモニターの様に処理させることが可能です。ダイアログベースのソフトウェアは、動作上コード中にメッセージループが必須ではありません。<参考>C言語でのメッセージループ例。SDKに目を通すことをお奨めします。当サイトで公開している『改造初心者向け練習用プログラム』のソースコードも参考になると思われます。0)){TranslateMessage(&msg);DispatchMessage(&msg);}API関数呼び出し箇所ではない任意の複数コードに一括してブレークポイントを設定したい。その様なブレークポイントを設定したいコードにユーザー定義ラベルを設定しておいて下さい。command」(全てのコマンドにブレークポイントをセット)です。これにより一括ブレークポイント設定が可能になります。リアルタイムアセンブラで注意すべきことは?PCゲームでのパラサイトルーチン埋め込み等、リアルタイムアセンブラによりコードを動的に変更/追加する場合は、汎用レジスタの値が変更/追加箇所の前後で保持されないと不具合を招くケースがあります(特にESI及びEDIレジスタ)。この場合はPUSHAD命令とPOPAD命令を変更/追加箇所の先頭と終端に用いれば最小限のコードで対処可能です。EFLAGSレジスタの内容を保持したい場合はPUSHFD命令とPOPFD命令を用います。2で実装されるデータ実行防止機能により、コードが実行されるメモリエリアは、必ずアクセス属性として実行属性が必要になります(参照)。kernel32.ExitProcess」というように関数名を入力します。関数名は大文字/小文字も正確に入力して下さい。コードの動的変更中に『OllyDbg』が誤った逆アセンブルコードを表示した場合は、「Ctrl」キー+「A」キーでコードを再解析させると対処できます。メモリ内容の内容変動箇所を調べるには?まず標準メニューから「View」(表示)→「Memory」(メモリ)でメモリーマップを表示します。これによりそのエリアのメモリ内容に変動があれば、その変動箇所がハイライト表示になります。data」(修正済データ)で検索可能です。上の機能では値増減等の変動内容詳細を区別できず、また、絞り込み検索機能も実装されていません。そのため、PCゲーム解析時等のプロセスメモリ上の変動検索には、『うさみみハリケーン』や『スペシャルねこまんま57号』を使用されることをお奨めします。プログラムが参照している文字列の一覧表示機能を使いたい。strings」(全ての参照文字列)を選択して下さい。して下さい(当サイト配布の日本語化パッチ添付文書を参照願います)。特定文字列の参照コード一覧表示機能を使いたい。デフォルトでデータセクションの内容が表示されるメインウィンドウの左下ウィンドウで、目的の文字列を探し出し(ポップアップメニューから検索可能)、その文字列の先頭アドレスに当たるバイナリデータを選択・右クリックします。references」(参照を検索)(「Ctrl」キー+「R」キーでも可)を選択して下さい。特定のコードにワンタッチで戻る方法が知りたい。to」(移動)→「Origin」(移動元)で元のコードへワンタッチで戻ってくることができます。ここでいう移動はコードを実行させている訳ではなく、あくまで逆アセンブルコードリスト上での表示箇所を変更しているだけです。目的のコードを「Enter」キーで表示リストに登録しておいて「+」や「-」キー等で移動する方法や、Bookmarkプラグインを利用するという選択肢もあります。コール命令からサブルーチン及び、ジャンプ命令からジャンプ先にワンタッチで移動する方法はありませんか?コールまたはジャンプ命令のコードを選択して、「Enter」キーです。F7キーでサブルーチンにステップインした後に、簡単にサブルーチンを抜ける方法はありませんか?「Ctrl」キー+F9キーでリターンまで実行させるか、予めCALL命令によるプロシージャ呼び出し部の次のコードにブレークポイントを設定しておきます。システムDLL等、デバッギー実行ファイル以外のコードを表示した場合の対処法は?上記の手法で表示位置を変更あるいは、「Alt」キー+F9キーでユーザーコード(デバッギーのコード)まで実行させます。ユーザーコードまで実行させる場合は、いったんデバッギーに制御を戻して何らかの処理を行わせることが必要なケースもあります。左上ウィンドウ上で右クリックから「View」(表示)で任意のモジュールにワンタッチで表示を変更することも可能です。CPU」(CPUコード表示)でも対処できます。逆アセンブルコードウィンドウ(左上ウィンドウ)でコード変更後の実行ファイルの保存が上手くいきません。file」(ファイル保存)で保存します。この保存先ファイルは必ずオリジナルとは別名のものにして、オリジナルの実行ファイルには一切変更を加えないで下さい。デバッグ)とは何ですか?簡単に言えば、アプリケーションが何らかの問題によりクラッシュした場合に、デバッガでそのアプリケーションにアタッチして問題箇所の発見・解決を促す機能です。debugging」用デバッガとしてレジストリに登録されることもあります。debugging」用デバッガとして登録しておくことをお奨めします。アプリケーションの不具合を作者に知らせる際に役立つことがあります。2008OllyDbgでソースレベルデバッグを行う場合は、事前にコンパイラでリンク時の設定を変更して、「デバッグ情報の生成」でpdb形式のデバッグ情報ファイルを出力させるようにしてからコンパイルしておきます。files」(ソースファイル)で表示されるソースファイルリスト上で目的のソースファイルを選択・ダブルクリックすると、そのソースファイル内のソースコードが別ウィンドウで表示されます。表示されたソースコードの行番号の左に「>」がある行では、行選択→右クリックで表示されるポップアップメニューから各種ブレークポイントを設定可能です。Disassembler」(逆アセンブラ画面表示)で、ソースコード上の選択行に対応する逆アセンブルコードをCPUウィンドウ内の左上ウィンドウの逆アセンブルコードリスト上で選択・ハイライト表示にします。逆に、逆アセンブルコードリスト上でブレークポイントを設定すると、表示されたソースコードの該当位置の行番号がハイライト表示になります。ソースレベルデバッグ中は、ブレークポイントでのブレーク時のログにソースコードの情報(関数名と関数開始アドレスからのオフセット)が併せて表示されます。このソースレベルデバッグは、コンパイラにVCを用いる場合では、OllyDbgがPDBファイルのデバッグ情報を元にデバッグシンボルを利用するために、コンパイルをデバッグビルドとして行う必要があります。OllyDbgはソースレベルデバッグをデバッグヘルプ系API関数によって実現していますが、このAPI関数はバージョン差異を含む全てのコンパイラが生成するデバッグシンボルに対応している訳ではないため、ソースレベルデバッグができないケースもあります。その場合はOllyDbg同梱のDBGHELP.DLLを、使用しているコンパイラが出力するデバッグシンボルに対応するバージョンのものを入手して置き換えることで対処可能と考えられます(DBGHELP.DLLは再配布可能コンポーネント)。Windows』から同DLLを抽出する必要があります。DBGHELP.DLLはMicrosoft製以外のコンパイラで出力されたデバッグシンボルにも対応しているとは限りませんので注意して下さい。ユーザーモードで動作するアプリケーションのデバッグにおいては、大抵システムデバッグシンボルは不要ですが、OllyDbgでシステムデバッグシンボルを利用したい場合は、以下の操作を行ってシンボルサーバーを使えるようにしておいて下さい。以下の操作結果に伴うOllyDbgの動作は保証致しかねます。Windows』をインストールし、『dbghelp.dll』、『symsrv.dll』および『srcsrv.dll』をOllyDbgのフォルダにコピーします。実行ファイル「OLLYDBG.EXE」に以下の書き換えを行います。このパッチコードによる書き換えは、『スペシャルねこまんま57号』でメニューの「ファイル」から「簡易バイナリファイル書き換え」で簡単に行うことが可能です。環境変数「_NT_SYMBOL_PATH」でシステムデバッグシンボルのフォルダが設定されているか確認します。『OllyDbg』などを使ったPCゲーム解析のチュートリアルはありませんか?もし入手可能ならば、ゲーム誌『ExGAME』Vol6にBlueAshさんが詳細なチュートリアルを寄稿されていますのでご覧下さい。操作方法だけでなく、アプローチに対する考え方が詳しく解説されており、必見だと思います。ちなみに、このチュートリアルが日本人向けに公開された最初の『OllyDbg』を用いた解析チュートリアルです。【x64対応版】』および、当サイトリンク先の「DANAの部屋」にもチュートリアルがありますので、ご覧になることをお奨めします。近年では、文章としての解析チュートリアルではなく、動画による解析チュートリアルを製作してYouTubeなどにアップロードするケースも増えています。メジャーなゲームならば、必要に応じて解析関連動画がないか検索してみることをお勧めします。チュートリアルに動画を使えば、アプローチにおける操作手順解説などをより分かりやすくすることが可能であり、特に超初心者向けの解説に有用です。チュートリアルを製作して他の方に解説し、情報の共有を行いたいと考えている方は、動画という選択肢も視野に入れておくと良いでしょう。『OllyDbg』でのメモリ書き換え操作を記録・再現するには?『うさみみハリケーン』や『スペシャルねこまんま57号』のデバッガに付属するAPIトレース機能を使用して下さい。この機能で『OllyDbg』のWriteProcessMemory関数呼び出しをトレースすることにより、『OllyDbg』が行った全てのプロセスメモリ書き換え操作を、『うさみみハリケーン』や『スペシャルねこまんま57号』用の改造コードとして出力することができます。このAPIトレース機能は、『OllyDbg』以外のWriteProcessMemory関数を用いるソフトウェアにも使用可能です。海外のゲーム専門リバースエンジニアの『OllyDbg』に対する評価はどうでしょうか?プログラム解析ツールとしてある程度の評価は得ています。海外で人気があるFPSゲーム等は、『OllyDbg』が対応できないDirectX排他モードで動作するものも多いため、アダルトゲームや同人ゲームなどの、『OllyDbg』で解析可能なゲームが潤沢である日本ほどは評価されていないように見受けられます。現在ではDirectX初期化処理のフック等により強制ウィンドウモード化を実現するソフトウェアも公開されているため、『OllyDbg』はメインの解析用デバッガとして十分使用可能です。DirectX排他モードのゲームでも、エントリーポイントからウィンドウ作成の間でコードの実行を停止させた状態ならば、『OllyDbg』単体でも各種解析が可能です。自作ツールがマルウェアに流用されたら罪に問われますか?現在の日本の法制度上では、正当な目的で作成したデバッガ等の自作ツールが、マルウェアあるいは、マルウェアの補助ツールとして配布されても、罪に問われることはありません。参考:いわゆるコンピュータ・ウイルスに関する罪について(法務省の見解)実際にマルウェアに流用されたケースとしては、Sysinternalsの『PsTools』が挙げられます。この例を見る限り、マルウェアに流用されることがあっても、日本人に向けた同ツールの公開中止には至っておらず、また、そのことが何らかの問題を生じているようには見えません。そもそも、ツールの仕様にもよりますが、悪意を持って流用されることを完璧に防ぐというのは無理があります。抵触といった事例に流用されても、不法行為への使用禁止条項や免責条項を含む使用許諾契約書を備えたツールの作者が、責任を問われることはほとんど無いといえます。社会的影響の程度によっては、責任を問われる可能性が生じます。特定の有償ソフトウェア・ゲーム「専用」のプログラム改造ツールを配布することは、訴訟コスト等からみて危険性は低いものの、常に法的リスクに晒されているといえます。近年改正が進んでいる不正競争防止法に抵触するようなツールの配布は、控えたほうがよいと思われます。万一の際には、無料あるいは安価な国選弁護人ではなく、私選弁護人を雇うことを強くお勧めします。国選弁護人の中には、弁護士としての役目や責任を果たさない者もいます。私の経験から言えば、ここで弁護士に払う金を惜しむと、一生後悔するような裁判内容や判決になりかねません。