Java バイトコードからソース コードを完全にリバース エンジニアリングできますか? この機能が Java で許可されている理由と、難読化ツールに対する Java デコンパイラの成功率は?
4 に答える
この質問が古いことは知っていますが、何も見つからなくなるまで信頼できる答えを探し続けました。そこで、この投稿では、J2EE JAR を難読化するための取り組みの一部を要約します。2014年(執筆時)までに、そこには多くのオプションがないようです. 後でこのレビューを読んだ場合、状況が変更または修正されている可能性があります. その理由を考えると、難読化の取り組み全体が誤った安心感を与えていることに気づき始めます。誤解しないでください。一定レベルのセキュリティが追加されますが、期待するほどではありません. 私は自分自身を説明するために見つけたもののプレビューをしようとします. 私の推奨は個人的なものであり、他の人はそれに反対するかもしれません.
まず、Java での難読化とは、バイトコードを取得し、元の機能を維持しながら (もちろん逆コンパイラを使用して) 読みにくくするプロセスです。私たちにできることは、インターパーターとして動作する Java は、バイトコードを公開したままにしておく必要があることです。クラス ファイルが悪用された場合に備えて、セキュリティ対策として難読化ツールを実行します。難読化の結果、リバース マッピング ファイルと、難読化されたクラスを含む JAR が生成されます。もちろん、リバース マッピング ファイルは、スタック トレースの読み取り (再トレース) を実行したり、バイトコードを元の形状に戻したりするために使用されます。難読化されたクラスのランタイム パフォーマンス ヒットは 10% を超えるべきではありません (ただし、これはコードで何を行うかによって異なります)。
しかし、大きな「しかし」があります。難読化はコードを混乱させますが、ハッカーから守ることはできません。時間を稼ぐだけで、断固たるハッカーがバイトコードを純粋なアルゴリズムにリバース エンジニアリングする方法を見つけることを心に留めておいてください。
IMHO: 機密性の高いコードを隠す最善の方法は、無意味なコードの山に紛れ込ませることです。
一部のハッカーは、目的を達成するために (コード インジェクションによって) バイトコードを変更しようとします。一部の難読化ツールは、追加レベルの JAR 強化を提供し、変更を困難にします。
難読化解除ツールと逆コンパイラ: 私のお気に入りの Java 逆コンパイラは JD-GUI です。しかし、難読化解除ツールに関して言えば、市場はかなり空いていることがわかりました。ほとんどのツールはヒント (ソース JAR の暗号化に使用された難読化ツール) を求めますが、実際に結果を提供するツールはありません (JAR を解読しようとするとクラッシュするツールもあります)。これらは、メンテナンスの少ないオープン ソース プロジェクトです。適切な難読化解除を行うための有料アプリケーションさえ見つけることができませんでした。あなたが何かを知っているなら、私に教えてください。
無料のソリューション
オープンソースの無料の難読化ツールがあり、通常はクラス/メソッド名を単純に名前変更して、1 文字のメソッドにします (つまり、printUsage(String params) から a(String p) に)。ここで示唆されているように、デバッグ情報を削除して、少し難しくすることさえあります。(デバッグ情報はすべての Java メソッド バイトコードの最後に保持され、行番号、変数名などを含みます)。これは素晴らしい努力ですが、デバッガーを使用する経験豊富な Java 開発者は、ライブ実行をほとんど行わなくても、各パラメーターの目的を非常に簡単に推測できます。優れたオープン ソースの難読化ツールの 1 つは ProGuard ですが、他にもいくつかのツールがあります。それにもかかわらず、あなたが本当にセキュリティ狂信者なら、おそらくもっと強力なものが欲しいでしょう. Stronger はより多くの機能 (およびより多くのお金) を要求し、次の箇条書きにつながります。
有料ソリューション
無料の製品はクラスのメソッド名を変更するだけですが、有料の製品は通常より多くの機能を提供します:
コード/フローの難読化: これにより、メソッド コードが変更され、空のループ/デッド コード/紛らわしいスイッチ テーブルなどが挿入されます。それらのいくつかは、例外テーブルの内容をスクランブルすることさえあります。通常、難読化の強度によって出力サイズが決まります。注: コードの難読化について: レビューでは意図的に詳細を避けました。私が確認して分析したバイトコードの一部は、難読化の方法を公開しており、それらの IP を保護したいと考えています。誰がより優れたアルゴリズムを使用しているかについて、私は意見を持っています。知りたい場合は私に連絡してください。
クラス/メソッドの名前変更 : これは明らかです。無料の難読化で説明しました。一部の製品はクラス名を変更し、そのクラスのリフレクションの使用を再帰的に検索して修正します。有料製品は、同じ目的で Spring /Wink 構成ファイルの名前を変更することさえあります (リフレクションでの名前変更)。文字列の暗号化: コード内の「このような」すべての文字列について、あるレベルまで暗号化し、キーをどこかに保持します (クラス定数テーブル/静的ブロック/新しいメソッドまたはその他の手段)。
デバッグ情報: パーツの削除またはスクランブリング。それらの多くは、行番号情報を削除します。クラス
強化: クラス/メソッドの先頭に何らかの署名スキームを挿入するなど、あらゆる種類のメソッド。部外者が JAR を簡単に変更して実行できないようにします。いずれにせよ、それらのほとんどはデジタル署名されているため、Android やアプレットではそれほど重要ではありません。強化と透かしを組み合わせて、海賊版を追跡するものもあります。しかし、ソフトウェアによる著作権侵害対策がハッキングされる運命にあることは誰もが知っています。ゲーム業界は、ネットワーク ベースのサブスクリプションが登場するまで、何十年もの間、この問題に悩まされていました。
ここにあるほとんどの製品は Java を扱っているため、一部の製品は Android 統合を提供しています。これは、Java (dalvik) コードを難読化するだけでなく、Android のマニフェスト ファイルとリソースも操作することを意味します。アンチデバッグを提供するものもあります: Android アプリのデバッグ フラグを削除します。
さまざまなオプションを構成し、特定のログ ファイルで再トレースを行うための優れた GUI アプリ。UI は通常、構成ファイルを生成するために使用されます。このようなファイルを使用すると、コマンドラインからでも、難読化を後で何度も再生できます。
インクリメンタル ビルドのサポート - これは、製品の更新や修正を頻繁にリリースする大規模なグループに役立ちます。古い「難読化」の結果を保持し、「新しい」コード フローのみをランダムに難読化するよう難読化ツールに指示できます。このようにして、メソッドの署名への影響を最小限に抑えることができます。このフラグがないと、ほとんどの優れたツールはアルゴリズムである程度のランダム性を使用するため、JAR の難読化サイクルごとに異なる出力が生成されます。
CLI および分散ビルド。単独で作業する場合、難読化ツールを実行することは大きな問題ではありません。難読化ツールを関連するオプションに設定して実行する必要があります。ただし、企業では、難読化ツールをビルド スクリプトに統合する場合は少し異なります。複雑さには別のレベルがあります。ビルド エンジン タスク (ant/maven など) とライセンス管理です。私がテストしたすべての難読化ツールにはコマンド ライン API があるという朗報があります。分散ビルド環境には、ビルドの同時要求をサポートするビルド マシンのクラスター/プールがあります。クラスタは動的かつ仮想的であり、マシンはさまざまな条件に応じて稼働または停止します。一部の難読化製品は、cpuID ライセンス ファイルまたはホスト名に基づいています。これは、ビルド チームが統合するのにかなりの課題をもたらす可能性があります。ローカルのフローティング ライセンス サーバーを好む人もいます。パブリック ライセンス サーバーが必要な場合もあります (ただし、すべてのビルド ファームがパブリック インターネットにアクセスできるわけではありません)。マルチサイト ライセンスを提供しているものもあります (私の意見ではこれが最適です)。
コードの最適化を提供するものもあります-代数的等価性とデッドコードの削除。それは素晴らしいことですが、今日の JDK はバイトコードの最適化においてうまく機能していると思います。デッド コードによってダウンロード可能なサイズが大きくなるのは事実ですが、今日の帯域幅では問題にはなりません。また、今日のソフトウェアでは、20:80 の経験則が依然として適用されると信じたいと思います。いずれにせよ、どのアプリケーションでも 20% はおそらくデッド コードです。
それで、私が試したプレーヤーは誰ですか?
KlassMaster by Zelix.com - 業界で最も古いものの 1 つです。それでも、年間 3 ~ 4 回のリリースで堅実な製品を提供しています。これは何十年も続いています (1997 年以来)。Zelix は優れたメール サポートを提供し、すべてのメールにタイムリーに返信してくれました。JARを難読化するか、将来の難読化のために構成ファイルを作成するための優れたGUIクライアントがあります。シンプルでスマートです。ここでは特別なことは何もありません。彼らは、すべてのフラグについて読みやすいオンライン ドキュメントを提供しました。エンジンが何を難読化するかについて、「除外」と「含める」の両方の正規表現をサポートしています。彼らのプロセスで私が最も気に入った点は、例外テーブルに「ノイズ」が追加されることです。メソッドの例外処理に関しては、もう少し混乱します。それらのフロー難読化ツールの強度は非常に優れており、3 つの可能なレベル (ライト、ミディアム、アグレッシブ) の間で構成できます。私が気に入ったもう 1 つの機能は、デバッグ情報のストリッピング (オンライン行番号、オンライン ローカル変数、またはその両方) のために提供される微調整です。クラス マスターは、専用の Android フラグや改ざん防止メソッドを提供しません。ライセンス モデルは非常に単純です。KlassMaster のメイン JAR の近くに配置されるテキスト ファイルです。また、段階的な難読化もサポートしています。
secureTeam.net の JFuscator : secureTeam にも .Net ツールがありますが、私はその Java ツール機能に注目します。彼らの (Swing ベースの) GUI ツールは良さそうに見えますが、最も単純な難読化タスクを実行しようとするとクラッシュします。エラーは常に同じでした: Error reading '/opt/sun-jdk1.7.0_55/jre\lib\rt.jar'. 理由: ''/opt/sun-jdk1.7.0_55/jre\lib\rt.jar': no such file or directory' . もちろん、Java を /opt/sun-jdk1.7.0_55/jre にインストールしました。Linux のバックスラッシュ構造を想定していなかったことが想像できます。小さな「パス」の問題について、メールで secureTeam.net サポートに連絡しました。彼らは私が Linux ユーザーかどうか尋ねました。また、彼らの Web サイトのオンライン チャットも試しましたが、応答がありません。そこで私はテストをやめました。さらに結果がなければ、難読化されたバイトコードの品質を調べることができませんでした。
GuartIt4J (by Arxan.com) : Arxan はモバイル環境でかなり堅実なプレイヤーであり、当然ながら Java でうまく機能する Android 難読化ツールを提供しています。最も柔軟なエンジンの 1 つを備えています。コードの難読化、文字列の暗号化などを提供します。コードの難読化の複雑さを定義できます。それは単なる整数です。高いほど、方法が長くなります。もちろん、クラスごとに JVM の 64KB の制限を超えないように注意する必要があります… 前に述べたように、機密コードを隠すための最善の戦略の 1 つは、コードを暗号化するのではなく、巨大なゴミの山に挿入することです。これはまさに GuardIt が行うことです。メソッドの例外テーブルと同じ方法で展開することもできます。例外テーブルに 100 個の例外を持つメソッドを作成することができました (難読化前は 5 でした)。彼らが見逃しているもの: それらの再トレース プログラムは、提供されたメイン JAR の一部ではありません。それにもかかわらず、リバース マッピング ファイルとログを指定して再トレースを実行するサンプル Java プログラムを送ってくれました。それらは増分難読化をサポートしておらず、デバッグ情報に関する柔軟性もありません。デバッグ情報のストリッピングは、すべてかまったくないかのいずれかです。出力 JAR を見ると、注入された大量の条件とジャンプが表示されます。クラスサイズを爆発させると、パフォーマンスが低下することに注意してください。いくつかのメソッドでは、長時間の難読化を適用すると、ほぼ 50% のパフォーマンス ヒットが測定されました (これらのメソッドでは I/O はありません)。そのため、コードの推定には代償が伴います (400 のオペコードから - 難読化後に 2200 のオペコードになりました)。JD-GUI 、私の逆コンパイラはそのようなクラスを開くことができず、クラッシュしました (IndexOutOfBoundException)。また、完全なクラス暗号化も提供します。つまり、クラスは、メモリ内で開くために特別な (またはカスタムで作成された) クラス ローダーを要求する対称キーで暗号化されます。これは改ざん防止メカニズムであり、コードを隠すためのものでもあります。JVM は、クラス ローダーの助けなしではそのクラスを実行できないことを覚えておいてください。これは素晴らしい機能ですが、秘密鍵とブートストラップ ローダー JAR はおそらくそこにあります。彼が暗号化された JAR を入手した場合、ハッカーは最終的に手を取り、クラスを復号化します。しかし、この別のレベルの障害は、一般的なハッカーが通過する必要があります。ここで気に入らなかったのは、ライセンス ファイル ポリシーです。CPUid にバインドされているか、フローティング ライセンス サーバーをインストールする必要があります。JVM は、クラス ローダーの助けなしではそのクラスを実行できないことを覚えておいてください。これは素晴らしい機能ですが、秘密鍵とブートストラップ ローダー JAR はおそらくそこにあります。彼が暗号化された JAR を入手した場合、ハッカーは最終的に手を取り、クラスを復号化します。しかし、この別のレベルの障害は、一般的なハッカーが通過する必要があります。ここで気に入らなかったのは、ライセンス ファイル ポリシーです。CPUid にバインドされているか、フローティング ライセンス サーバーをインストールする必要があります。JVM は、クラス ローダーの助けなしではそのクラスを実行できないことを覚えておいてください。これは素晴らしい機能ですが、秘密鍵とブートストラップ ローダー JAR はおそらくそこにあります。彼が暗号化された JAR を入手した場合、ハッカーは最終的に手を取り、クラスを復号化します。しかし、この別のレベルの障害は、一般的なハッカーが通過する必要があります。ここで気に入らなかったのは、ライセンス ファイル ポリシーです。CPUid にバインドされているか、フローティング ライセンス サーバーをインストールする必要があります。
SecureIt (by Allatori.com) : SecureIt は、一般的なコードの難読化、文字列の暗号化、名前の変更などをすべて提供します。標準的な難読化方法に加えて、改ざん防止/海賊行為防止方法であるある種のウォーターマーキングも提供します。Android と JavaME をサポートしています (最近、誰が ME を使用しているのですか?!)。これらは増分難読化をサポートしています。SecureIt の設定について注意すべきことは、すべてコマンド ラインです。今回はGUIツールはありません。個人的には、適切なドキュメントが付属している限り、コマンド ライン ツールは気にしません。幸いなことに、彼らには非常に優れたドキュメントと、必要に応じて調整できる多くのフラグを備えた豊富な API があります。それらのツール (コマンド ラインでもあります) を使用して再トレースできます。例外テーブルを難読化することはできません。私は彼らのライセンスメカニズムをチェックしませんでした.
DashO (by Preemptive.com) : DashO 難読化ツールは、おそらく (構成を作成するために) 入手できる最高の UI ツールとして記憶されるでしょう。SecureIt と同様に、例外テーブルの難読化を回避しますが、必要な残りの機能をすべて備えています (CLI、Spring フレームワーク、gradle/ant 統合、さらには eclipse プラグインも) 。まあ、彼らは try-catch 難読化ツール (例外テーブル難読化ツールと同じ) を文書化していますが、それはエンジンへの推奨事項にすぎません。試してみたところ、例外テーブルには何も影響しませんでした。前述したように、GUI ツールは優れており、再トレース機能が組み込まれています。また、改ざん/海賊行為防止メカニズムとして、ある種のアプリケーション署名と透かしを提供します。DashO は優れた Android 統合を提供し、分析アップロード用のドアも製品に組み込んでいます。実際にアプリケーションを追跡できます。クラッシュ ログ アップローダとレポート コードを JAR に挿入します。それにもかかわらず、それは難読化の範囲ではありません。それはまったく別のコード インジェクション製品です。彼らは非常に良いサポートをしています。オンラインでも電話でも。彼らのライセンス方式は、毎月のサブスクリプションまたは 1 回限りの購入支払いに基づいています。他とはちょっと違う。大規模な環境をサポートするためにフローティング ライセンス サーバーを使用しています。
これが少し役立つことを願っています..
Java バイトコードからソース コードを完全にリバース エンジニアリングできますか?
空白、ローカル変数名、コメントなど、ソース コードの一部の側面がバイトコードに保持されないため、完全ではありません。それ以外の場合は、はい -- まったく同じソース コードを取得することはできませんが、ほとんどの場合、少なくとも同じバイトコードにコンパイルできるものを取得できます。
この機能が Java で許可されている理由
「許可」されているというよりは、「防止されていない」のです。そして、そうすることが不可能であるため、防止されるわけではありません。コードが有用であるためには、実行可能でなければなりません。コードが実行可能であれば、分析可能です。分析可能な場合は、十分な分析を行ってソースに戻すことができます。
java逆コンパイラは難読化ツールに対してどの程度成功していますか?
あまりない。私が見たほとんどの難読化ツール (特に ProGuard) は、主に意味のある関数名とクラス名を削除するのに効果的です。通常、ロジック自体の難読化は試みられません。
最近では、バイナリからソース コードを取得できます。Javaのバイトコードで取得したソースコードの方が読みやすいのですが、難読化すると少し読みにくくなります。コードをリバースエンジニアリングできるのは Java だけというわけではありません。最近の C/C++ (IDA Pro 用の Hexrays プラグインを使用) でさえ、ソースに逆コンパイルできます。難読化すると読みにくくなりますが、不可能ではありません。知的で有能なリバース エンジニアからあなたのプログラムを救えるものは何もありません。:)。
幸運を。
Java バイトコードからソース コードを完全にリバース エンジニアリングできますか?
Java クラス ファイルは仕様に基づいているため、誰でも読み込むことができます。JD-GUIのようなツールを使えば、ソース コードを簡単に破ることができます。それ自体は「機能」ではありません。100% のリバース エンジニアリングは不可能ですが、ほとんどのコードはリバース エンジニアリングできます。
java逆コンパイラは難読化ツールに対してどの程度成功していますか?
依存します。難読化ツールのポイントは、意味のある名前をすべて削除し、パフォーマンスに影響を与えずにコードを混乱させることです。ほとんどの開発者は、コード自体を難読化するのが得意です:) Pro-guard は難読化がかなり得意です。