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

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

ただいまの
回答率

90.53%

  • C++

    3430questions

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

  • Delphi

    17questions

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

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

解決済

回答 5

投稿

  • 評価
  • クリップ 4
  • VIEW 452

essex

score 14

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

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

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

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

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+4

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/24 12:05 編集

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

    キャンセル

  • 2018/04/24 12:35

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

    キャンセル

  • 2018/04/24 18:55

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

    キャンセル

  • 2018/04/24 19:37

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

    キャンセル

  • 2018/04/25 18:44

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

    キャンセル

+2

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/24 18:55

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

    キャンセル

0

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/24 18:55

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

    キャンセル

0

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

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

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

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

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

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

  • (A) スタックの状態
  • (B) 当該プロセス上の全スレッドのその時点での全レジスターの値
  • (C) OSがそのプロセスに割り当てている資源
    オープン中のファイル、ウィンドウハンドル、スレッド等々の動的資源
  • (D) 各仮想空間上のセグメント(ページ)の正確な状態

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


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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/24 18:55 編集

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

    キャンセル

0

こんにちは。

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/24 18:54

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

    キャンセル

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

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    3430questions

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

  • Delphi

    17questions

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