如何隐藏变量不被Java的JDI检测到?

huangapple go评论82阅读模式
英文:

How to hide variables from Java's JDI?

问题

我正在为一些类进行仪器化,并引入了一些新的局部变量。现在,当用户在代码中设置断点并停止执行时,新引入的局部变量可以在Intellij IDEA的调试器窗口中看到。如何隐藏它们?

更新:我将不得不以某种方式从仪器化的代码中删除调试信息,但不确定如何做。

更新2:我正在使用ASM库进行仪器化。

  1. public void visitCode() {
  2. this.mv.visitLdcInsn(stringToPass);
  3. this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "MyAgentClass", "loadData", "(Ljava/lang/String;)LDataClass;", false);
  4. this.mv.visitVarInsn(Opcodes.ASTORE, this.getDataIndex());
  5. }
  6. public void visitMaxs(int maxStack, int maxLocals) {
  7. if (this.myStartLabel != null && this.myEndLabel != null) {
  8. this.mv.visitLocalVariable("__my__data__", "Ljava/lang/Object;", (String) null, this.myStartLabel, this.myEndLabel, this.getDataIndex());
  9. }
  10. super.visitMaxs(maxStack, maxLocals);
  11. }

__my__data__ 在Intellij IDEA中可见。

英文:

I am instrumenting some classes and introducing some new local variables. Now, when the user places a breakpoint in the code, and execution is stopped, the newly introduced local variables can be seen inside Intellij IDEA's debugger window. How can I hide them?

UPDATE: I will have to somehow remove debug info from the instrumented code, but not sure how to do it.

UPDATE 2: I am using the ASM library for instrumentation.

  1. public void visitCode() {
  2. this.mv.visitLdcInsn(stringToPass);
  3. this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, "MyAgentClass", "loadData", "(Ljava/lang/String;)LDataClass;", false);
  4. this.mv.visitVarInsn(Opcodes.ASTORE, this.getDataIndex());
  5. }
  6. public void visitMaxs(int maxStack, int maxLocals) {
  7. if (this.myStartLabel != null && this.myEndLabel != null) {
  8. this.mv.visitLocalVariable("__my__data__", "Ljava/lang/Object;", (String) null, this.myStartLabel, this.myEndLabel, this.getDataIndex());
  9. }
  10. super.visitMaxs(maxStack, maxLocals);
  11. }

__my__data__ is shown inside Intellij IDEA.

答案1

得分: 1

根据JVM规范,您可以从LocalVariableTable中删除您的局部变量。 Javassist会在生成的代码中自动执行此操作,我在运行期间无法看到变量secretCode

反编译结果类可以显示它没有LocalVariableTable条目:

  1. public void run();
  2. descriptor: ()V
  3. flags: ACC_PUBLIC
  4. Code:
  5. stack=2, locals=3, args_size=1
  6. 0: ldc #39 // int -889275714
  7. 2: istore_1
  8. 3: iload_1
  9. 4: invokestatic #43 // Method org/example/App.test:(I)Ljava/lang/Integer;
  10. 7: astore_2
  11. 8: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
  12. 11: aload_2
  13. 12: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  14. 15: new #2 // class SecreFoo
  15. 18: dup
  16. 19: invokespecial #3 // Method "<init>":()V
  17. 22: astore_1
  18. 23: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
  19. 26: aload_1
  20. 27: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  21. 30: return
  22. LineNumberTable:
  23. line 14: 15
  24. line 15: 23
  25. line 16: 30
  26. LocalVariableTable:
  27. Start Length Slot Name Signature
  28. 0 31 0 this LSecreFoo;
  29. 23 8 1 fCopy LSecreFoo;

因此,当您对类进行插桩时,请从表中删除所有局部变量(或不要添加它们)。

英文:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.13

Based on the JVM specs, you can remove your local variables from LocalVariableTable. Javassist does that automatically in generated code and I cannot see the variable secretCode during the run:

如何隐藏变量不被Java的JDI检测到?

Decompiling the result class can show that there are no LocalVariableTable entries for it:

  1. public void run();
  2. descriptor: ()V
  3. flags: ACC_PUBLIC
  4. Code:
  5. stack=2, locals=3, args_size=1
  6. 0: ldc #39 // int -889275714
  7. 2: istore_1
  8. 3: iload_1
  9. 4: invokestatic #43 // Method org/example/App.test:(I)Ljava/lang/Integer;
  10. 7: astore_2
  11. 8: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
  12. 11: aload_2
  13. 12: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  14. 15: new #2 // class SecreFoo
  15. 18: dup
  16. 19: invokespecial #3 // Method "<init>":()V
  17. 22: astore_1
  18. 23: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
  19. 26: aload_1
  20. 27: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  21. 30: return
  22. LineNumberTable:
  23. line 14: 15
  24. line 15: 23
  25. line 16: 30
  26. LocalVariableTable:
  27. Start Length Slot Name Signature
  28. 0 31 0 this LSecreFoo;
  29. 23 8 1 fCopy LSecreFoo;

So when you are instrumenting your class, drop all your local variables from the table (or do not add them).

huangapple
  • 本文由 发表于 2020年8月9日 19:51:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63325980.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定