質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Delphi

DelphiはPascalを拡張してオブジェクト指向を導入したWindows, OS X,iOS,Androidのネイティブアプリケーションを開発するための言語です。旧称はObject Pascal。開発用IDE「Delphi」にあわせ現在の名前に改称されました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

906閲覧

メモリ上にあるプロセスを、選択して実行ファイルとして保存したい

essex

総合スコア21

Delphi

DelphiはPascalを拡張してオブジェクト指向を導入したWindows, OS X,iOS,Androidのネイティブアプリケーションを開発するための言語です。旧称はObject Pascal。開発用IDE「Delphi」にあわせ現在の名前に改称されました。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

2グッド

4クリップ

投稿2018/04/24 01:03

メモリ上にあるプロセスを、選択して実行ファイルとして保存したいと考えています。

選択したプロセスの情報をGetModuleInformationで収集し、ベースアドレスからプロセスの長さ分の
データをディスクに書き出すという仕組みで、一応ディスク上にファイルとして保存されます。
しかし残念ながら、保存したファイルを実行しようとしても、
有効なアプリケーションではない旨のエラーが表示され、動作してくれません。

バイナリエディタでダンプしてみると、一見それっぽいのですが、ディスク上のファイルと比較すると、
PEヘッダの後方やファイルの末尾に0の列が追加されており、全体にフォーマットが崩れてしまっている様に見えます。

トレースすると、GetModuleInformationで返るサイズが、ディスク上のファイルサイズより大きく、
その差分の領域に0が並んでいる様にも見えますが、そうであるなら、ファイルの末尾に0が並びそうに思います。
しかし実際には、ファイル内にパーティションの様に0が挿入されています。

当初は、プログラム上の間違いかと思い、言語系の掲示板でアドバイスを仰いだところ、
「メモリ上にあるプロセスは、実行用に展開された状態で、ディスクにある時とは異なるので、
書き出したファイルは、正しいのではないか?」というアドバイスをいただきました。

そこで、書き出したファイルを再配置して、実行可能な形にできないかと模索しているのですが、
ディスク上のPEファイルとメモリ上の状態の対比について、なかなかこれという情報にたどり着けません。

非常に漠然とした質問で恐縮ですが、参考になる資料や、良い情報がありましたら、ご教示下さい。
よろしくお願いします。

nullbot, yohhoy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

「IATの再構築」で検索するといい気がします。
セクションテーブルも再構築必要だっけ…?

投稿2018/04/24 01:56

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/04/24 03:05 編集

うわわ、そんなことができるんですね! 知らずにできない(困難)て書いちゃいました orz
asm

2018/04/24 03:35

非常に面倒な前提条件が必要ですし、成功するかも微妙で 簡単な作業じゃないのは確かですね
essex

2018/04/24 09:55

ご回答、ありがとうございます。 早速ググってみましたが、正にこういう情報を探していました。 特にスペシャルねこまんま57号は凄いですね。 PEファイルの再構築を、半ば自動でやってくれるんですね。 再構築してもすぐクラッシュしてしまうので、使い方が間違っているのかも知れません。 今は、使い方の解説を探し中です。
asm

2018/04/24 10:37

猫飯での再構築は個人的には成功した試しがないんですよねぇ・・・ 他の回答者様も言ってるように、「どの時点のメモリをダンプするか」にも注意する必要があります。
essex

2018/04/25 09:44

そうなんですね。 確かに、そのままでは動いてくれません。 今は、教えていただいた言葉でググりながら、手動で色々やっています。 何か、コツがあったら、教えて下さい(>ω<)
guest

0

実行ファイルを実行するという場合、その実行ファイルのアドレス情報を元にメモリ上に展開されます
ですんで、メモリパターンをそのまま持ってきても実行ファイルにはなりません

「EXEファイルフォーマット」でぐぐるとそこら辺の情報が引っかかると思います

ましかし、メモリ上のデータ持ってきて実行ファイルに再構築するというのはちと無謀ではないかと思われますが。

投稿2018/04/24 01:39

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

essex

2018/04/24 09:55

ご回答、ありがとうございます。 メモリをそのまま保存しても、実行ファイルにならないのですね。 実行ファイルに再構築するのは、色々ハードル高いですね。
guest

0

こんにちは。

やったことはありませんが、基本的には無理と思います。
多くのOSのロードモジュールは、ロード先のメモリ・アドレスがロード時に決定するため、jmp命令の飛び先などはロード時に埋められます。その埋める操作に必要な情報は、ロードされてしまったプロセスにはもう不要な情報ですから破棄されていると思います。
従って、それらの情報を回復するのは並大抵のことでは無理だろうと思います。

そんなことするより、そのモジュールのパスを入手してファイルをコピーすれば手っ取り早いと思います。恐らくフックすれば、後は簡単に取れるのではないかと思います。(フックはちょっと面倒ですが。)
GetModuleHandle
GetModuleFileName

投稿2018/04/24 08:46

編集2018/04/24 08:48
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

essex

2018/04/24 09:54

ご回答、ありがとうございます。 フックというのは面白いですね。 ハンドルを取得すれば、パスも取得できそうですから、 タイミングを見てコピーというのも、ありかもしれないですね。
guest

0

実際上は無理(または非常に困難)と思います。

エントリーポイントから実行するケース

仮にexecutableにできたとして、それをエントリーポイントから実行開始するなら、プログラムが正常に動くために少なくともグローバルな領域が初期状態になっていないといけないです。グローバルな領域に置かれた情報がプログラムの制御にどうからむかはプログラム次第です。一般的に実行開始済みの任意のタイミングのグローバル領域の状態を退避・回復して強引にエントリーポイントからプログラムを走行させた場合、正常に動くとは期待できません。

そういうことを考えるよりはプロセスの起動元のexecutableファイルを普通に起動することを考える方が単純・明快ですね。

退避した時点の実行状態から再開させるケース

GetModuleInformationで得られる程度の情報では不足です。再開には少なくとも実行コンテキストを完全に復活できなければならないと思います。実行コンテキストの例を挙げると

  • (A) スタックの状態
  • (B) 当該プロセス上の全スレッドのその時点での全レジスターの値
  • (C) OSがそのプロセスに割り当てている資源

オープン中のファイル、ウィンドウハンドル、スレッド等々の動的資源

  • (D) 各仮想空間上のセグメント(ページ)の正確な状態

などがあります。また退避の際には当該プロセスの全スレッドをsuspend状態にしないといけません。そうでないと保存すべきコンテキストが決まりませんので。


GetModuleInformationで返るサイズが、ディスク上のファイルサイズより大きく、

例えば未初期化のグローバル領域はデータ内容が全て0と決まっているのでexecutableファイル内に一々そんなデータは格納せず「グローバル領域の大きさはBSSバイト」というようなサイズ情報しか入ってないのです。また前述した実行コンテキストの(A)や実行開始後に動的に確保する仮想空間はexecutableの中には入ってませんので内容はかなり違ったものになります。

投稿2018/04/24 03:01

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

essex

2018/04/24 09:56 編集

詳しい解説を、ありがとうございます。 確かに、実行時には、スタックもレジスタも含めて使用している訳ですから、 それらも再現しないと、実行状態の再現はできませんね。 プロセスだけダンプしても、PEファイルとは、かなり違ったものになりますね。
guest

0

メモリイメージをファイルに保存して実行ファイルを復元することは、極めて困難だと思います。

メモリイメージをファイルに保存するということは、実行中のある瞬間の状態を保存するということなので、再度実行するには完璧に同じ状態を再現する必要があります。単にエントリーポイントから実行させるだけでは正しく動きません。

どういうことかというと、EXEファイルを実行すると、まずOSやランタイムの初期化処理が走り、アプリを実行するための準備を整えてからmainあるいはWinMain関数に制御を移すわけですが、実行中のメモリの状態をそのままファイルに保存すると「すでに初期化済み」の状態となっているわけであり、正しく初期化されません。あるいは、例えば、アプリの処理で「あるポインタ変数がNULLなら領域を確保してそのポインタを設定する」のような処理が行われていたら、実行開始時にNULLになっておらずに領域が確保されることなく不正なポインタになってしまいます。

それらを解消するには、それこそリバースエンジニアリングして初期状態を再現させなければいけませんが、そこまでやりますか?

投稿2018/04/24 02:51

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

essex

2018/04/24 09:55

ご回答、ありがとうございます。 確かに、入力待ちのプログラムを作成してダンプしてみると、 入力された値等も一緒にストアされますから、 再構築は難しいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問