• ベストアンサー

デコンパイル?について

noocyteの回答

  • ベストアンサー
  • noocyte
  • ベストアンサー率58% (171/291)
回答No.8

> 構造体情報は実行時、基本的に唯のアドレスのオフセットにしか展開されないわけで、 > (中略) > # と、またここでもコンパイラを特定することが前提に。 色々な実行ファイル形式やコンパイラの出力を調べたわけではないので かなり推測混じりですが… 構造体がポインタを使わずにアクセスされている場合には,複数の基本型変数が 構造体メンバなのか,それともバラ売りのスカラ型なのかの判別は困難だと思います. ただ,処理内容が変わるわけではないので,これは #5 に書いたソースの表現方法の 曖昧さの問題ですね.だから実用上はデフォルトでバラ売りを選んでおいて,ユーザ の指示があれば構造体にまとめる,という方法がいいのではないかと思います. 他方,構造体がポインタでアクセスされている場合には復元しやすいと思います. それは必ずしも (ベースアドレス+オフセット) のようなアドレシングモード のメモリアクセス命令でなくてもかまいません. メモリアクセス命令があれば,その参照アドレスのデータフローを逆にたどり, (ベースアドレス+オフセット) という演算がなされていれば構造体メンバ アクセスだと見なしてメモリマップに書き込みます.これをプログラム全体 について行えば構造体が復元できると思います. (その過程で共用体やポインタのキャストが発見される場合もありますが. あ,それと,構造体配列の可能性を考えるともっと厄介になりそう….orz) > 関数ポインタ経由であろうが、static関数であろうが、 > (最適化で削除されずに)コード領域に残っているなら、 > コード領域を舐めれば対象にできますし。(読み取るのは解析者の仕事では) はい,既存の逆アセンブラではそうやっているものもありますよね. それだと,その関数単独 (およびその関数が呼び出している関数群) の 解析はできるので,#5 で書いたような見逃しはなくなります. それでも次のような問題が残ります.(今,気がつきました.) 実行ファイルのエントリポイント (≒main() … 本当はスタートアップルーチン だけど) を出発点とする制御フロー/データフロー解析を行うに当たり, そのような関数 (とりあえず,ここでは孤児と呼ぶことにします) については 関数間の呼び出し関係をたどるグローバルなフロー解析ができません. したがって構造体や共用体の復元に支障が出る場合があります.一例を挙げると, 孤児とその呼び出し元の間で同じ構造体や共用体にアクセスしていながら, 一方のみが使用しているメンバがある場合です.例えば, 元のソース ----------------------------------------------------------------- struct A {   double a1; // size=alignment=8,offset=0 とする.   char a2; // size=alignment=1,offset=8 とする. }; // sizeof(struct A)=16 static void bar(struct A *pA); // フロー解析の対象になっている関数 // (逆アセンブラは,これが main() から直接間接に呼び出されること, // そしてその呼び出し方 (引数の型など) を知っている.) void foo(…) {   struct A a;   void (*f)(struct A*);   // ここで色々演算して,最終的な f の値は bar になるが,   // 逆コンパイラにはそれがわからないものとする.   // また,この関数内では a.a2 には一切アクセスしないものとする.   (*f)(&a); // 逆コンパイラには,これが bar を呼んでいることがわからない.   :   : } // フロー解析の対象外の関数 (孤児) // (逆コンパイラは,これがどこからどのように呼ばれているのかわからない.) static void bar(struct A *pA) {   // この関数 (およびそれが呼び出す関数) では,   // pA->a1 には一切アクセスしないものとする.   :   :   pA->a2 = 'A';   :   : } 逆コンパイルされたソース (最大限の可能性を想定した場合) -------------------- // main() を始点とするグローバルフロー解析により復元された struct A. struct Struct1 {   double Struct1_Member1; // (struct A)::a1   char Struct1_Unused1[8]; // 8バイトの未使用領域と誤認された. }; // bar() を始点とするグローバルフロー解析により復元された struct A. // 逆コンパイラには Struct1 と同一であることがわからない. struct Struct2 {   char Struct2_Unused1[8]; // 8バイトの未使用領域と誤認された.   char Struct2_Member1; // (struct A)::a2   char Struct2_Unused2[7]; // struct A 末尾のパディング (7バイト) }; void foo(…) {   struct Struct1 var1; // a   void (*var2)(struct Struct1 *); // f   :   :   (*var2)(&var1);   :   : } // bar static void StaticOrphanFunc1(struct Struct2 *arg1) {   :   :   arg1->Struct2_Member1 = 'A';   :   : } ---------------------------------------------------------------------------- このように,(*var2)(&var1) の呼び出し先がわからなければ,元の struct A に 対して Struct1 と Struct2 の2つの構造体定義ができてしまいます. もし逆コンパイラのユーザが (*var2)(&var1) が StaticOrphanFunc1 を呼び出して いることを教えてやれば,(*var2)(&var1) と StaticOrphanFunc1 の引数を照合 することによって Struct1 と Struct2 が同一であることがわかるため,両者を マージして struct Struct3 {   double Struct3_Member1; // (struct A)::a1   char Struct3_Member2; // (struct A)::a2   char Struct3_Unused1[7]; // struct A 末尾のパディング (7バイト) }; のように復元できるはずです.ただしマージ中に衝突 (同じアドレスが異なる データ型としてアクセスされている) が発見された場合,共用体またはポインタ のキャストということになるので,#5 で書いたように厄介なことになります.

関連するQ&A

  • C言語の用語について。

    現在Cygwinを使ってC言語?をやりはじめたものです。 make app=ファイル名でコンパイル?すると思うのですが、 make、app=、ビルドとはなんですか? 以前Javaを少しやっていたのですが、 make = javac app= = .java ビルド = コンパイル みたいなものですか?

  • Eclipseでクラスファイルが生成されない

    Eclipse(Helios)、java(JDK1.6)の環境で作業をしています。 指定した出力フォルダにクラスファイルが生成されません。 先日までは生成されていました。 コンパイルエラーはありません。 Javaのビルドパス ⇒ ソース ⇒ デフォルト出力フォルダの指定です ソースフォルダごとの出力フォルダの指定を可能にするはオフにしてあります。 設定は少しくらい変えたかも知れませんが、重要なところは変えていないと思います。 # あやふやですみません。 考えられる理由を教えてください。

    • ベストアンサー
    • Java
  • コマンドプロンプト

    初心者ですが、よろしくお願いします。 Cドライブの中にjavaというフォルダを作り、この中に「HelloWorldApp.java」というソースファイルを作りました。 そして、コマンドプロンプトを使ってこのソースファイルを コンパイルしようとしているのですができません。 「C:\java>dir」を行うと、「ドライブCのボリュームラベルがありません。」と出ます。コンパイルできないのと関係あるのでしょうか?

    • ベストアンサー
    • Java
  • eclipseのフォルダ

    eclipseのフォルダには 1.フォルダ 2.ソースフォルダ 3.パッケージ の3つの概念がありますが 1のフォルダにおいたJavaファイルを コンパイル対象にするにはどうしたらいいのでしょうか? 2のソースフォルダにJavaファイルを置いた場合は そのJavaファイルをクリックするとファイルが開きコンパイルが自動的に行われます。 しかし1のフォルダにJavaファイルを置いた場合は そのJavaファイルをクリックするとファイルが開くもののコンパイルは行われません。 1の単純なフォルダにJavaファイルをおいてもクラスファイルはできないのでフォルダを作って使うことに価値は無いのでしょうか?

    • ベストアンサー
    • Java
  • C言語CGIの一括コンパイルの方法

    10年くらい前に作ったゲームの復活を考えています。 当時ledhat7.1上で展開していたゲームをSentOS上で再開します。 ゲームはC言語で出来ていますが、作った本人が手を付けることができません。 そこで、当方が10年前の姿にまでは持っていこうと考えています。 いろいろ調べていくと、 「C言語によるCGIプログラムは、それを動かそうとする サーバー上でソースファイルをコンパイルする必要があります。 他のマシンでコンパイルしたCGIプログラムをそのまま持って来ても、動かない 可能性の方が大きいです。ご注意下さい。」 という記述を見つけました。 全部、コンパイルし直す必要がありそうです。 当方の現在の環境は下記の通りです。 サーバー  自宅にあり。直接接続可能 もちろんSSHも可 CGI の数 178個 ディレクトリは40個くらいに分かれている コンパイル前のC言語ファイルは「.c ファイル」として 保存されている ひとつひとつコンパイルしていったのでは、1ケ月くらい 掛かりそうです。 一括コンパイルのような方法はありませんでしょうか? 一括でなくとも、ディレクトリごとでも構いません。 宜しくお願い致します。

  • jspとサーブレット

    jspはサーブレットに比べるとソースファイルを生成しなければならない分、処理速度が遅くなると書かれてたのですが、ソースファイルを生成とはどういうことなのかわかりません。htmlに埋め込まれたJAVAを取り出すということでしょうか? またサーブレットもJSPもクライアントから要求がきてからプログラムをコンパイルしてるのでしょうか?すなわちコンパイルされてないままWEBサーバに保管されてるのですか? 2点よろしくお願いします。

    • ベストアンサー
    • Java
  • JNAでc言語ファイルの読み込み方が分かりません

    JNAでc言語ファイルの読み込み方が分かりません JNAを使用して、javaからcを読み込み動作するプログラムを作っています。 なんとなく定義は分かってきたのですが、 javaのソースコードに CLibrary.INSTANCE.printf(); のように、c言語を書き込んでいる状況なのですが、 JNAを利用した.javaファイルから.cファイルを読み込む方法はありますか? c言語の場合、.cファイルごとに分割された関数をmainが呼び出すとき、 extern void Sample(); とプロトタイプ宣言の後に Sample(); で呼び出せるみたいなので、 これを使って、 CLibrary.INSTANCE.extern void Sample(); とやってみましたが、コンパイルできませんでした;; 他にやり方がありますか? 知ってる方がいらっしゃいましたら、教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • シンボルを見つけられませんというエラーでコンパイルできない

    こんにちは。 Test.javaとTest2.javaというファイルを作りコンパイルしようとしたんですがタイトルのエラーが出てコンパイルできません。全く意味が分からなくて困ってます。 test.javaの中で Test2 test2 = new Test2(); という形でTest2クラスのインスタンスを生成しています。 同じフォルダの中にあるのに見当たらないというのはどうにも分かりません。 環境変数は CLASSPATH . PATH C:\Program File\Java\jdk1.5.0_06\bin となってます。

    • ベストアンサー
    • Java
  • あるCのソースをコンパイルしたのですが、なぜか実行時にエラーになってし

    あるCのソースをコンパイルしたのですが、なぜか実行時にエラーになってしまいます。 (Command not found. と表示されてしまいます。) 初心者です。 さくらインターネット上で makeコマンドで生成したファイルが ls -l で -rwxr-xr-x 1 xxxxxxxxx users 8730 May 6 14:08 screw と表示されるのですが カレントをそのまま(Cソースがあるフォルダ)で screw と実行すると screw: Command not found. と表示されてしまいます。 何が悪いのでしょうか?

  • flrからswfへコンパイルするにはどうしたらいいですか

    flashのデコンパイラ"flare"を用いてswfをデコンパイルしてflrファイルを生成しました。 このflrファイルを再びswfに戻すにはどうしたらよいですか。 有料のソフトを使わずに、無料でコンパイルする方法を教えてください。 OSはwindows vistaです。