Skip to content

📞 ImmutableInstruction35c

ImmutableInstruction35c 实现格式 35c(3 code units,最多 5 个寄存器 + 16-bit 引用),是 Dalvik 中方法调用最常用的格式,对应 invoke-virtualinvoke-directinvoke-staticinvoke-interfacefilled-new-array 等指令。

属性
源码immutable/instruction/ImmutableInstruction35c.java
包名org.jf.dexlib2.immutable.instruction
格式Format.Format35c(6 字节)
实现接口Instruction35c

🎯 职责

持有最多 5 个参数寄存器(registerC~registerG)+ 方法/类型引用 + 实际参数数量(registerCount),支持 0~5 个参数的方法调用。

🧠 关键实现

java
public class ImmutableInstruction35c extends ImmutableInstruction implements Instruction35c {
    protected final int registerCount;
    protected final int registerC, registerD, registerE, registerF, registerG;
    @Nonnull protected final ImmutableReference reference;

    public ImmutableInstruction35c(@Nonnull Opcode opcode,
                                    int registerCount,
                                    int registerC, int registerD, int registerE,
                                    int registerF, int registerG,
                                    @Nonnull Reference reference) {
        super(opcode);
        this.registerCount = Preconditions.check35cRegisterCount(registerCount); // 0~5
        // 未使用的寄存器槽位强制为 0
        this.registerC = (registerCount > 0) ? Preconditions.checkNibbleRegister(registerC) : 0;
        this.registerD = (registerCount > 1) ? Preconditions.checkNibbleRegister(registerD) : 0;
        this.registerE = (registerCount > 2) ? Preconditions.checkNibbleRegister(registerE) : 0;
        this.registerF = (registerCount > 3) ? Preconditions.checkNibbleRegister(registerF) : 0;
        this.registerG = (registerCount > 4) ? Preconditions.checkNibbleRegister(registerG) : 0;
        this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference);
    }
}

遍历 invoke 指令示例

java
for (Instruction instruction : methodImpl.getInstructions()) {
    if (instruction instanceof Instruction35c) {
        Instruction35c inv = (Instruction35c) instruction;
        if (inv.getReference() instanceof MethodReference) {
            MethodReference mRef = (MethodReference) inv.getReference();
            // ZjDroid:识别被混淆的方法调用,重建真实引用
            System.out.println(mRef.getDefiningClass() + "->" + mRef.getName());
        }
    }
}

📐 格式布局(6 字节)

+--------+--------+--------+--------+--------+--------+
| opcode |B|regG  |   方法引用索引(16位)  |D |  E |F|G|
+--------+--------+--------+--------+--------+--------+
                             寄存器 C~G 编码在高低 nibble 中

其中 B = registerCount(4 bits),G = registerG(4 bits),在同一字节中。

超过 5 个参数时

当方法参数 > 5 时,使用 Format3rc(即 invoke-virtual/range),以寄存器范围方式表达。ImmutableInstruction3rc 持有 startRegisterregisterCount

🔗 关系

📌 小结

ImmutableInstruction35c 是 ZjDroid 在分析方法调用链时最常遇到的指令类型。通过 getReference() 获取 MethodReference 后,可以还原完整的方法签名(定义类->方法名(参数类型列表)返回类型),这是 ZjDroid smali 重建输出的关键数据来源。

基于 MIT 协议发布 · 本文档仅用于安全研究与教学目的