- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在对一个 Java 客户端应用程序进行逆向工程,我想跟踪该应用程序的某些字段的修改,以了解在采取解决混淆名称的操作后发生了什么变化。
我可能可以使用某种调试器,但我决定自制它以获取学习体验。
我使用 ASM 创建了一个类适配器,它会检查每个方法的每个指令,当它遇到 PUTFIELD 指令时,它应该调用对象的 fireCallback 方法
只要我可以预期 PUTFIELD 目标是工作类,就非常简单,但是如果在其他对象上调用它,我无法弄清楚如何检测它在哪个对象上调用
我正在阅读 JVM 规范,发现有一个 DUP 和 POP 指令可用于堆栈操作,并且当调用 PUTFIELD 时,堆栈上有对象引用和设置值,所以我想为什么我不能复制putfield 之前的堆栈,然后简单地弹出设置值并在剩余的 objectref 上调用 fireCallback
但事情不可能那么简单,不幸的是,如果设置值是 double 或 long 类型,PUTFIELD 需要两个字,我无法简单地弄清楚如何处理这个异常?
或者有更简单的方法吗?我如何知道在 putfield 之前将哪个对象加载到堆栈?
我当前的代码:
for (MethodNode method : (List<MethodNode>) methods) {
if (ADD_FIELD_CALLBACKS) {
Iterator<AbstractInsnNode> insIt = method.instructions
.iterator();
while (insIt.hasNext()) {
AbstractInsnNode ins = insIt.next();
int opcode = ins.getOpcode();
if (ins.getOpcode() == Opcodes.PUTFIELD) {
FieldInsnNode fieldInsNode = (FieldInsnNode) ins;
System.out.println(name + "'s updating "
+ fieldInsNode.owner + "'s "
+ fieldInsNode.name + " in method "
+ method.name);
InsnList onFieldEditInsList = new InsnList();
method.instructions.insertBefore(ins, new InsnNode(
Opcodes.DUP2));
onFieldEditInsList.add(new InsnNode(Opcodes.POP));
onFieldEditInsList.add(new LdcInsnNode(
fieldInsNode.name));
onFieldEditInsList
.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
fieldInsNode.owner, "fireCallback",
"(Ljava/lang/String;)V", false));
method.maxStack += 2;
method.instructions.insert(ins, onFieldEditInsList);
}
}
}
}
这会导致一个VerifyError,并显示消息“期望在堆栈上找到对象/数组”,以防当时堆栈中存在不同的项目集。
最佳答案
您的问题看起来有点奇怪,因为 putfield
指令已经包含您需要的所有信息。它有一个 reference to the owner class和一个field signature telling the type of the field .
因此,对于遇到 putfield
指令时的有效字节码,最顶层堆栈值必须与字段的类型兼容,下一个值必须是对与所有者类兼容的实例的引用。换句话说,如果字段的签名是 "J"
或 "D"
,则您的值在堆栈顶部占据两个单词,否则它是一个单词.
请注意,对于此类任务,请使用 GeneratorAdapter
比较方便。当用作访问者时,它默认会复制遇到的代码,并且可以计算 maxStack 和 maxLocal 值等。因此,您只需重写要注入(inject)代码的指令的访问方法,而无需实现迭代逻辑。
例如对于代码看起来的每个 putField
指令,在类 mypackage.MyDebugger
中调用类似 public static void fieldWrite(Object Owner, String fieldName)
的方法像:
// i.e. class MyCodeTransformer extends GeneratorAdapter
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if(opcode==Opcodes.PUTFIELD) {
final Type fieldType = Type.getType(desc);
super.swap(Type.getObjectType(owner), fieldType);
if(fieldType.getSize()==1) super.dupX1(); else super.dupX2();
super.visitLdcInsn(name);
super.visitMethodInsn(Opcodes.INVOKESTATIC, "mypackage/MyDebugger",
"fieldWrite", "(Ljava/lang/Object;Ljava/lang/String;)V", false);
}
super.visitFieldInsn(opcode, owner, name, desc);
}
关于java - 使用字节码操作库 ASM 在每次 putfield 操作后调用对象的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24026909/
在 java 字节码中,“putfield”指令期望栈顶是一个值,栈顶 1 是一个引用。为什么不是相反? 在我的讲义中被问到,我找不到答案。 最佳答案 顺序实际上并不重要,因为 VM 和编译器可以很容
目前,我们将用户的 session 对象序列化到数据库中,但该对象最近变化太大,因此我们决定重新设计此过程。我们都同意我们不能序列化整个对象,我们需要逐个字段保存它。有 2 条建议, 将所有字段存储在
我正在对一个 Java 客户端应用程序进行逆向工程,我想跟踪该应用程序的某些字段的修改,以了解在采取解决混淆名称的操作后发生了什么变化。 我可能可以使用某种调试器,但我决定自制它以获取学习体验。 我使
有人知道如何使用ObjectInputStream.GetField和ObjectOutputStream.PutField吗?我的程序需要在特定时间查找特定对象,上面的类确实可以帮助我找到正确的方法
我在 eclipse 中打开了我的 java 类文件,我对这一行有疑问。 iconst_10 putfield Test.a : int [12] [12] 是什么意思?它是否表示已分配字节数? 我的
我正在使用 ASM字节码操作框架,用于对 Java 代码执行静态分析。我希望检测何时重新分配对象的字段,即何时发生这种代码: class MyObject { private int valu
我是一名优秀的程序员,十分优秀!