スポンサーリンク

メモリの中身を読んでみよう (プロセスをダンプ+解析する方法)

実行中のプログラムは,メモリ上に存在する。


そのメモリ上のデータを読み取れば,アプリケーションが扱っている生のデータを,そっくりそのまま取得できてしまう。


ユーザがどのような値を入力したか,アプリケーションがどこと通信してどういうデータを取得したか,全て丸見えである。


逆アセンブルの場合,プログラムの「実行前」のスタティックな姿しかわからない。

しかしメモリ上のイメージをダンプすれば,まさに「実行中」のプログラムの姿がわかる。これが逆アセンブルとダンプの大きな違いだ。



下記では,Windows上で実行中のプロセスをダンプし,プログラムにユーザが入力した値をメモリ上から実際に読み取る。


利用するフリーソフトは

  • User Mode Process Dumper
  • バイナリエディタ
  • WinDbg

の3つ。(これに加え,適当なC言語コンパイラがあるとよい。)


ちなみに,ソフトウェアの利用承諾書に「無断での解析を禁じます」と書いてある場合があるので,既存のソフトウェアのダンプにあたってはくれぐれも注意すること。


(1) ダンプファイルを作成する

マイクロソフトが無償で提供している,通称「Toolkit」というツールがある。


Microsoft Support Professionals Toolkit for Windows ダウンロード
http://www.microsoft.com/japan/windowsserver2003/downloads/supporttools.mspx

Windows用ダンプツール、マイクロソフトが無償で公開
http://www.atmarkit.co.jp/news/200601/12/windows.html

 Toolkit Version 8.0に含まれるのは2つのツール。「User Mode Process Dumper」はユーザーモードで動作するアプリケーションの任意のプロセスに対して、スナップショットダンプを生成することができる。


数点ある中から,「User Mode Process Dumper Version 8.1」 をダウンロード。

installerを実行。


そして,インストール終了後に

C:\kktools\userdump8.1\x86

にある「setup.exe」を実行する。

これで,User Mode Process Dumperを利用できるようになった。



同じディレクトリに userdump.exe というのがあるから,これをコマンドプロンプトから起動してみる。

 userdump.exe

とだけ入力するとコマンド一覧のヘルプが表示される。

 userdump.exe -p

とすると,実行中のプロセス名とプロセスID (PID)の対応一覧が表示される。

あなたがコマンドプロンプト使いなら,ぜひとも

 userdump.exe -p | sort /+6

と入力して見やすく整形しよう。

sort /+n は n 文字目の並びでソートをかける事を指す。
すると,実行結果をプロセス名順に並び替える事ができる。



プロセスIDが3884のアプリケーションをダンプしたい場合,

 userdump.exe 3884 a.dmp

のように入力し,少々待つ。(a.dmpは任意の出力ファイル名)


同ディレクトリ上にダンプファイルが作成される。その中身は,実行中のプログラムのスナップショットである。


(2) ダンプファイルを読む

ダンプファイルの中味を読むためには,バイナリエディタが必要になる。有名どころではStirling(スターリング)などがある。

Stirling - 使いやすさと高機能を両立した最強の新・定番バイナリエディタ

http://www.vector.co.jp/soft/win95/util/se079072.html


しかし,意味もわからず読むだけでは全然面白くない。


ここは一つ,自分がプログラム実行時に対話入力した内容が,しっかりメモリ上に格納されている事を確かめてみる。


下記のような初歩的なCのプログラムをコンパイルする。

#include "stdio.h"

void main()
{
	char *str = "Hello, World!\r\n";
	char in[200] = "入力された内容は:";

	printf("%s", str);

	printf("何か入力してください。\r\n");
	fgets( &in[18], sizeof(in), stdin );

	printf("キーを押すと終了します。\r\n");
	getchar();
	
	return;
}

このプログラムは,コマンドラインに「Hello, World!」と表示した後,「何か入力してください」と言って,標準入力からの文字列を待つ(fgets)。


エンターキーで入力が終わると,入力した内容は in という配列の18文字目以降に格納される。
(※最初の18文字は,「入力された内容は:」という文字列になっている。実はこれが,あとでダンプした時に目印になる。)


入力が終わったらすぐに終了せず,キーが押されるまで終了待ちになる(getchar)。


Visual Studioがあるなら,コマンドラインから

 cl ファイル名.c

とするだけで.exeにコンパイルできるだろう。

かりに名称をp.exeとして,このプログラムを実行してみる。



上図は,「何か入力してください。」に対して「hogehigehage」と入力してエンター押下したところ。

そして,そのまま終了させずにおく。



さて,この p.exe は,今まさにメモリ上にある。(実行中なので)


早速ダンプしてみよう。

userdump.exe -p で p.exe のプロセスIDを調べ,そのPIDに対して userdump.exe 〜 p.dmp とする。

C:\kktools\userdump8.1\x86>userdump.exe 3608 p.dmp
User Mode Process Dumper (Version 8.1.2929.5)
Copyright (c) Microsoft Corp. All rights reserved.
Dumping process 3608 (p.exe) to
C:\kktools\userdump8.1\x86\p.dmp...
The process was dumped successfully.

のように出力されるはず。


このダンプファイルをバイナリエディタで開く。

Ctrl+Fで検索ウィンドウを開き,「入力された内容は」という文字列で検索する。

そして,検索結果の直後に現れる文字列に注目する。



なんと,「hogehigehage」という,コマンドラインから入力した文字列が丸見えになった。


メモリ領域の中で,「in」という名前の配列変数は,ここに場所が割り当てられていたのだという事がわかる。


そして「hogehigehage」という文字列から,恐らく,このプログラムを実行したユーザは真面目に入力しなかったのだろうという事をも推測できてしまう。


このように,メモリの中味を読むと,アプリケーション実行時のユーザの挙動が衆目にさらされることになる。
(もっとも,ダンプファイルの内容を理解できるかどうかという問題はある。
単に変数の中味を知りたいというだけの場合は,デバッガが利用可能ならデバッガを使った方が楽だが…)


(3) ダンプファイルを解析する方法

ダンプデータから,バイナリエディタで読む以上の情報を引き出したい場合は,それなりの解析ツールを使う必要がある。

有名なフリーの解析ツールはWinDbgだが,このソフトはまた,日本語の情報が少ない事でも有名だったりする。


WinDbgのダウンロード
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx


Current Release versionをダウンロードし,インストール。

その後,利用するために初期設定が必要になる。

WinDbgのインストールと3つのコマンド
http://enterprisezine.jp/article/detail/743?p=2

にあるように,

  • boot.iniの編集
  • シンボルサーバの設定

が必要だ。


(注:シンボルサーバについて


Windbgで File -> Open Crash Dump File からダンプファイルを読み込んだ後は,下記サイトにあるような使い方でダンプ時の情報を引き出せる。

例えばクラッシュエラーの原因を

!analyze -v

で表示できる。プログラム中で定義されている構造体や,利用しているDLLの情報も読み出せる。


先ほど挙げたCプログラムは簡易なものなので,それほど面白い情報は引き出せない。

ただし,PCがブルースクリーンになってメモリ全体の完全ダンプファイルが作成されたような場合は,Windbgによるカーネルデバッグが相当役に立つ。

カーネルデバッグコマンド例
http://d.hatena.ne.jp/egggarden/20080107/1199634711



関連する記事:

ウィンドウをきっかけに Windows の内部の仕組みを探る (前半の補足)アセンブラでウィンドウを生成する方法 - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20081109/1226258057


ウィンドウをきっかけに Windows の内部の仕組みを探る (後半)システムコールからカーネルデバイスドライバまで - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20081111/1226413103


コマンドラインからマウスを操作する方法 (rundll32.exeで動くDLLの作成法) - 主に言語とシステム開発に関して
http://d.hatena.ne.jp/language_and_engineering/20081117/1226943698