• ベストアンサー

デコンパイル?について

noocyteの回答

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

面白そうな話題ですね.:) 自称・リバースエンジニアリング技術のホビー研究家 (笑) としては, 逆コンパイラについて書きたいことがたくさんありますが,キリがないので少しだけ…. 世界中どこでも,「逆コンパイルは可能か?」という質問をする人がいて, それに対しては「不可能」というのがお決まりの反応のようです. そしてその理由もだいたい判で押したように 「コメントやローカル変数名は復元できないから.」 (まあ,誰でもすぐ思いつく理由だからでしょうが.) 「100%元通りのソース」なんてないものねだりをしても「不可能」の一言で 片付けられるのがオチなので,ここではどこまで元の構造を復元できる (可能性がある) かについて考えてみます. といっても,復元不可能とわかっている情報 (コメントやローカル変数名など) についてはスッパリあきらめて,復元可能な情報をいかに読みやすい形で表示 するか (元通りでなくても読みやすければよい) という目標にすり替えます. 以下,その前提でC逆コンパイルについて,かなり私の推測・主観入りの難易度判定です. (今思いついたものもいくつかあるので,正確さは全く保証しません.) ・完全に復元不可能な情報の例  ・コメント  ・外部リンケージを持たない変数名・関数名   (auto 変数名,static 変数名/関数名など)  ・構造体や共用体のメンバ名  ・構造体や共用体の,全く使用されていないメンバのデータ型.  ・マクロ定義 ・復元超容易  ・外部リンケージを持つ変数名・関数名.   (extern "C" 宣言されていない C++ の識別子であれば,型名も復元可能.) ・復元わりと容易  ・基本データ型の変数.  ・式,関数呼び出し. ・復元やや難  ・構造体定義   一ヶ所で一つの構造体のすべてのメンバにアクセスしているコードがあれば   復元は楽だが,一般にはプログラムのあちこちで異なるメンバにアクセスする   ことになるので,プログラム全体でそれを調べて情報を総合する必要がある. ・復元難  ・制御構造.下手をすると goto 文だらけのソースになる.逆にうまくいけば,   元のプログラムの制御構造にもよるが,スパゲッティ化していたものが   整理される場合もありうる.制御フローグラフ解析アルゴリズムの出来次第 (たぶん). ・復元超困難  ・共用体 (またはキャストしたポインタでアクセスされる変数)   コードのどの範囲でどのデータ型としてアクセスしているのか判別が必要.   データフロー解析,制御フロー解析両面からのアプローチが必要 (たぶん). ・復元不可能? (決定不可能問題?)  ・ポインタ演算を使うポインタによるアクセス   ポインタが参照するメモリ領域の1次元的構造を復元する必要があるが,   動的に変化する可能性もあるので一般には決定不可能?  ・関数ポインタ「だけ」を使って呼び出される static 関数   関数ポインタの値を解析時に決定できなければ,static 関数のエントリ   ポイントが見つけられない (したがってその関数は逆コンパイル対象にさえ   ならない) … かも. ・復元可能であっても,ソースの表現方法が一義的に定まらないもの.  ・例:あるメモリ領域が複数の異なるデータ型としてアクセスされている場合,   それを共用体として表現するか,それともポインタのキャストで表現するか. Cに比べて Java ははるかに逆コンパイルが容易で,1996 年に (たぶん) 初の Java 逆コンパイラ Mocha が公開されて以来,多数の Java 逆コンパイラが公開 されています. Java Decompilers http://www.program-transformation.org/Transform/JavaDecompilers Javaコードを守る方法 (あるいは他人のJavaコードを参照する方法)  Javaコードの逆コンパイルおよび曖昧化の完全ガイド http://www-06.ibm.com/jp/developerworks/java/011026/j_j-obfus.html Java 逆コンパイラはかなり元のソースを復元できるので,これを脅威に感じた Java 業界はさまざまな逆コンパイラ対策ツールを有償・無償で提供しています. Java が逆コンパイルされやすい原因として,CPU 独立なバイトコードを採用して いるからだとか,オブジェクト指向だから (失笑) だとか説明しているサイトを 見かけたことがあります.しかしこれらはまったく的外れで,私は次のような Java の言語仕様に原因があると思っています. (と偉そうに書くほど Java を熟知しているわけではないので,違っていたら指摘してください.) ・共用体が存在しない. ・ポインタ演算が禁止されている. ・ポインタのキャストがかなり制限されている.(アップキャストとダウンキャストだけ?) (以上3つを上に書いたCの場合と比較してください.) それと, ・クラスファイルの中に,クラス (構造体) 定義情報が含まれている. じゃ,クラスファイルからそれを削除すればいいじゃん,と思うかもしれませんが, (多分) そうはいきません.(それができるなら上記の対策ツールがやっているはず.) その理由は, ・構造体 (インスタンス) のどの位置にどういう型のポインタ (クラス型変数) が  あるかわからないと,ガーベージコレクタが困る … つまり,オブジェクト間の  トラバースができなくなる (はず). ・クラス定義情報がないと,Java のリフレクション機能が使えなくなる (はず). 以上書いたように,Cの逆コンパイラは Java に比べて遙かに実現困難で, 実用レベルのものは存在しないはずですが,研究レベルとしては多分 dcc が有名 … かな? (Mocha の作者も dcc の論文を参考にしたらしい.) Dcc Decompiler http://www.program-transformation.org/Transform/DccDecompiler それから,マルウェア解析のために dcc を改造して Win32 PE 実行形式を 解析可能にした ndcc というのもあるようです. History Of Decompilation 3  ndcc decompiler, 2002. http://www.program-transformation.org/Transform/HistoryOfDecompilation3 Machine Code Decompilers http://www.program-transformation.org/Transform/MachineCodeDecompilers The Decompilation Wiki http://www.program-transformation.org/Transform/DeCompilation あぁ,少しだけのつもりだったのに….orz

関連する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です。