如果要使用 pcode API 执行此操作,则必须检查PTRSUB操作的参数,这->
与 C 级别上的等效。
PTRSUB 执行简单的指针计算 input0 + input1,但也明确指示 input0 是对结构化数据类型的引用,并且正在访问其子组件之一。Input0 是指向结构开头的指针,input1 是到子组件的字节偏移量。作为操作,PTRSUB 生成一个指向子组件的指针并将其存储在输出中。
请注意,该PTRSUB
操作不是问题中发布的原始 pcode 的一部分,而是在分析过程中由反编译器插入的。再次引用文档:
以下操作码不是作为机器指令原始转换为 p 代码操作的一部分生成的,因此它们都不能用于处理器规范。但是,它们可能会在稍后阶段通过各种分析算法引入。
以下代码将查找给定函数中对结构偏移量的所有调用:
DecompileResults results = decompiler.decompileFunction(function,
decompiler.getOptions().getDefaultTimeout(), monitor);
HighFunction hfunc = results.getHighFunction();
for(PCodeOpAST op : hfunc.getPcodeOps()) {
if (op.getOpcode() == PcodeOp.CALLIND) {
Varnode funcAddress = op.getInput(0);
while (funcAddress.getDef().getOpcode() == PcodeOp.LOAD)
funcAddress = funcAddress.getDef().getInput(1);
if (funcAddress.getDef().getOpcode() == PcodeOp.PTRSUB) {
Varnode struct = funcAddress.getDef().getInput(0);
Varnode field = funcAddress.getDef().getInput(1);
DataType structDataType = struct.getHigh().getDataType();
while(structDataType instanceof Pointer || structDataType instanceof TypeDef) {
if (structDataType instanceof Pointer)
structDataType = ((Pointer)structDataType).getDataType();
else if (structDataType instanceof TypeDef)
structDataType = ((TypeDef)structDataType).getDataType();
}
if (structDataType instanceof Structure && field.isConstant()) {
Structure structure = (Structure) structDataType;
int offset = (int)field.getOffset();
DataTypeComponent component = structure.getComponentAt(offset);
System.out.println("Call to " + component.getFieldName() +
" in " + structure.getName());
for (int i = 1; i < op.getNumInputs(); ++i) { // 0 is the function address, 1+ are arguments
System.out.println(" with argument " + i + " = " + op.getInput(i).getAddress());
}
}
}
}
}
或者,您可以在程序中搜索对 FindClass 字段的所有引用,但请注意,这将列出所有类型的引用,而不仅仅是调用:
DataType jniEnvDataType = program.getDataTypeManager().getDataType("/jni_all.h/JNIEnv");
Accumulator<LocationReference> accumulator = new ListAccumulator<>();
ReferenceUtils.findDataTypeReferences(accumulator, jniEnvDataType, "FindClass",
program, TaskMonitor.DUMMY);
for(LocationReference location : accumulator) {
System.out.println(location.getLocationOfUse());
}
(这基本上相当于 UI 中的“Find Uses of JNIEnv.FindClass ...”)