バイトコード解析を使用して、クラスファイルのインポート済みクラスをすべて取得しています(BCEL付き)。今、私が定数プールを読み込んだとき、インポートされたすべてのクラスがCONSTANT_Class(spec参照)として記述されているわけではなく、CONSTANT_Utf8としてのみ記述されています。私の質問:インポートされたファイルを読み込むために定数プールのCONSTANT_Classエントリだけに依存することはできませんか?私は本当にすべてのエントリを見て、クラス名の場合は、推測する必要がありますか?これはすべての状況で正しいとは思われません。または、私はバイトコード全体を読まなければならないのですか? についてクラスファイルのクラスがありません定数プール
答えて
いいえ、CONSTANT_Class_infoエントリだけを使用して他のクラス/インタフェースの依存関係を検出することは正しくありません。あなたが信頼する入力ファイルを解析している場合や、間違った情報を許容している場合は、コーナーケースを除いて定数プールの解析だけを行うことができます。任意の入力に関する正確な情報を得るには、クラスファイル全体を解析する必要があります。 (IはJVMS chapter 5に記載されているように、例外が発生することができるあなたはどのローディングなしで、またはクラスを連結これらのクラスまたはインタフェースを意味し、「依存性」で想定しています。これはClass.forName
又は他の反射手段を介して取得したクラスが含まれていない。)
考慮する次のクラス。
public class Main {
public static void main(String[] args) {
identity(null);
}
public static Object identity(Foo x) {
return x;
}
}
javap -p -v Main.class
プリント:
Classfile /C:/Users/jbosboom/Documents/stackoverflow/build/classes/Main.class
Last modified Jul 2, 2014; size 346 bytes
MD5 checksum 2237cda2a15a58382b0fb98d6afacc7e
Compiled from "Main.java"
public class Main
SourceFile: "Main.java"
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#17 // java/lang/Object."<init>":()V
#2 = Class #18 // Main
#3 = Class #19 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 LMain;
#11 = Utf8 identity
#12 = Utf8 (LFoo;)Ljava/lang/Object;
#13 = Utf8 x
#14 = Utf8 LAAA;
#15 = Utf8 SourceFile
#16 = Utf8 Main.java
#17 = NameAndType #4:#5 // "<init>":()V
#18 = Utf8 Main
#19 = Utf8 java/lang/Object
#20 = Utf8 java/lang/Thread
#21 = Class #20 // java/lang/Thread
#21 = Utf8 (LBar;)LFakename;
{
public Main();
descriptor:()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 6: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LMain;
public static java.lang.Object identity(Foo);
descriptor: (LFoo;)Ljava/lang/Object;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: areturn
LineNumberTable:
line 11: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 x LAAA;
}
Foo
クラスは、メソッドidentity
にパラメータとして参照される、CONSTANT_Class_infoエントリとして定数プールに表示されません。 identity
(エントリ#12)のメソッド記述子に表示されます。フィールド記述子は、CONSTANT_Class_infoエントリとして現れないクラスを参照することもできます。したがって、定数プールだけからすべての依存関係を見つけるには、すべてのUTF8項目を調べる必要があります。
コーナーケース:CONSTANT_String_infoエントリによって参照されるUTF8エントリが存在することがあります。重複するUTF8エントリがマージされるため、1つのUTF8エントリはメソッド記述子、文字列リテラル、またはその両方になります。あなたが定数プールを解析しているだけの場合は、このあいまいさで生きていなければなりません(おそらく、過大近似とそれを依存関係として処理する)。
あなたのコントロール下で適切に動作するJavaコンパイラによって入力が生成されたことを信頼する場合は、すべてのUTF8エントリを解析し、文字列のコーナーケースを気にして、ここでの読み上げを中止できます。手作業で作成したクラスファイル(例えば、デコンパイラを作成しており、攻撃者が逆コンパイルを防止したいなど)を攻撃者から守る必要がある場合は、クラスファイル全体を解析する必要があります。潜在的な問題のいくつかの例を次に示します。
- エントリ#20は、
Main
で使用されていないクラスの名前です。 JVMはこの参照を解決しようとすることもあれば、試みないこともあります(JVMS 5.4は遅延読み込みと熱心な読み込みの両方を許可します)。クラスが存在するため、エラーは発生しませんので、この余分な項目は無害ですが、Threadが依存関係であると考えるために定数プールを見ているツールを欺くでしょう。 - エントリ#21は、2つの架空のクラスを参照する未使用のメソッドディスクリプタです。この記述子が使用されないので、エラーは発生しませんが、定数プールを信頼するツールは解析します。
- エントリ#14は、架空のクラスを参照するフィールド記述子です。このエントリは実際にはLineNumberTable属性によって使用されますが、このデバッグ情報はJVMによってチェックされないため、参照は無害ですがツールを欺くかもしれません。
- 私はこの例を持っていませんが、InnerClasses属性はCONSTANT_Class_infoエントリを参照し、他のクラスファイルとの整合性をチェックしません(非標準的なメモではありますがJVMS 4.7.6)。これらのリファレンスは、読み込みやリンクを妨げるものではありませんが、定数プールを調べるツールを混乱させます。
これは私の頭の上から出てきたものです。きれいな攻撃者は、JVMSを細かい歯のついた櫛で捉えて、使用されていると見える定数プールにエントリを追加する場所をもっと見つけることができます。攻撃者の側でも正確な情報が必要な場合は、クラスファイル全体を解析し、JVMでどのように使用するかを理解する必要があります。
JVMS 4.2, The Internal Form of FQ Class and Interface Namesを参照してください。
Nutshell:クラス構造がUTF8エントリを指します。
(または、代わりに参照されるすべてのクラスは、クラスと名前のエントリで表されていないことを言っている?)
FWIWは、依存関係を判断するために、この情報のみに依存を警戒するクラスをロードすることができますよう動的に表示され、まったく表示されないことがあります。
はい、私は知っている、私はこれに専ら依存しない...しかし、私のusecaseのために、十分に良い。私の要点は、私が必要とするすべての参照は、utf8のエントリとして表現されていますが、クラスエントリとして表現されていないことです。だから私は推測する必要があります、utf8エントリは実際にクラス名です..(私の理解では、すべてのクラスはクラスエントリとして表されますが、このようには見えません) – wrm
- 1. ライブラリにoAuthクラスファイルがありません
- 2. クラスファイルの内部クラスですが、クラス本体にはありませんか?
- 3. 他のクラスの関数に定数がありません
- 4. Mavenがクラスをコンパイルしておらず、クラスファイルがwarファイルにありません
- 5. Maven配備のサードパーティjarにクラスファイルがありません
- 6. bintrayUploadの後にjarファイルにクラスファイルがありません
- 7. 定数プールはクラスファイル内の#3を失った
- 8. pool.queryは関数ではありません - 接続プール
- 9. `retrieve_connection ':Model(ActiveRecord :: ConnectionNotEstablished)の接続プールがありません
- 10. JOGLで自動解放プールがありません
- 11. R.javaのIDクラスがありません
- 12. beautifulsoupのクラスがありません
- 13. PDFBox2.0のクラスがありません
- 14. エラー - 引数 "inputId"がありません。既定値はありません。
- 15. "acl"の定義にクラスがありません
- 16. Googleアナリティクス - OAuth2Nativeクラスがありません
- 17. SimpleRepositoryクラスとネームスペースがありません
- 18. java.lang.IllegalArgumentException:enum constクラスがありません
- 19. javax.el.PropertyNotFoundException:クラスに 'プリファレンスプロパティ'がありません。
- 20. DatabaseException:クラスに引数のないコンストラクタがありません
- 21. ムービークリップコンポーネント(クラスファイルあり)
- 22. RCTMapクラス用に定義されたビューマネージャがありません
- 23. なぜ 'object'クラスにユーザ設定属性がありません
- 24. C#:クラスに定義がありません
- 25. Windows Phone 7.1設定クラスがありません
- 26. gson - > "クラスxyzのコンストラクタがありません"配列あり
- 27. ローカルのaarファイルプロジェクト:io.realm.RealmObjectのクラスファイルが見つかりません
- 28. UITouchクラスにinit関数がありません
- 29. swift型クラスにはメンバー関数がありません
- 30. ノードJS JavascriptクラスTypeErrorが関数ではありません
あなたがリンクしている本は1999年に出版されたので、私は参考にしません。 – Viruzzo