@Override public void computeDataOffsets(DexBody body) { Debug.printDbg("compute data offset"); if (!(instruction instanceof Instruction31t)) throw new IllegalArgumentException( "Expected Instruction31t but got: " + instruction.getClass()); Instruction31t fillArrayInstr = (Instruction31t) instruction; int offset = fillArrayInstr.getCodeOffset(); int targetAddress = codeAddress + offset; Instruction referenceTable = body.instructionAtAddress(targetAddress).instruction; if (!(referenceTable instanceof ArrayPayload)) { throw new RuntimeException( "Address 0x" + Integer.toHexString(targetAddress) + " refers to an invalid PseudoInstruction (" + referenceTable.getClass() + ")."); } ArrayPayload arrayTable = (ArrayPayload) referenceTable; int numElements = arrayTable.getArrayElements().size(); int widthElement = arrayTable.getElementWidth(); int size = (widthElement * numElements) / 2; // addresses are on 16bits // From org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction we learn // that there are 6 bytes after the magic number that we have to jump. // 6 bytes to jump = address + 3 // // out.writeByte(0x00); // magic // out.writeByte(0x03); // number // out.writeShort(elementWidth); // 2 bytes // out.writeInt(elementCount); // 4 bytes // out.write(encodedValues); // setDataFirstByte(targetAddress + 3); // address for 16 bits elements not 8 bits setDataLastByte(targetAddress + 3 + size); // - 1); setDataSize(size); // TODO: how to handle this with dexlib2 ? // ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); // arrayTable.write(out, targetAddress); // // byte[] outa = out.getArray(); // byte[] data = new byte[outa.length-6]; // for (int i=6; i<outa.length; i++) { // data[i-6] = outa[i]; // } // setData (data); }
public void jimplify(DexBody body) { if (!(instruction instanceof Instruction31t)) throw new IllegalArgumentException( "Expected Instruction31t but got: " + instruction.getClass()); Instruction31t fillArrayInstr = (Instruction31t) instruction; int destRegister = fillArrayInstr.getRegisterA(); int offset = fillArrayInstr.getCodeOffset(); int targetAddress = codeAddress + offset; Instruction referenceTable = body.instructionAtAddress(targetAddress).instruction; if (!(referenceTable instanceof ArrayPayload)) { throw new RuntimeException( "Address " + targetAddress + "refers to an invalid PseudoInstruction."); } ArrayPayload arrayTable = (ArrayPayload) referenceTable; // NopStmt nopStmtBeginning = Jimple.v().newNopStmt(); // body.add(nopStmtBeginning); Local arrayReference = body.getRegisterLocal(destRegister); List<Number> elements = arrayTable.getArrayElements(); int numElements = elements.size(); Stmt firstAssign = null; for (int i = 0; i < numElements; i++) { ArrayRef arrayRef = Jimple.v().newArrayRef(arrayReference, IntConstant.v(i)); NumericConstant element = getArrayElement(elements.get(i), body, destRegister); if (element == null) // array was not defined -> element type can not be found (obfuscated bytecode?) break; AssignStmt assign = Jimple.v().newAssignStmt(arrayRef, element); addTags(assign); body.add(assign); if (i == 0) { firstAssign = assign; } } if (firstAssign == null) { // if numElements == 0. Is it possible? firstAssign = Jimple.v().newNopStmt(); body.add(firstAssign); } // NopStmt nopStmtEnd = Jimple.v().newNopStmt(); // body.add(nopStmtEnd); // defineBlock(nopStmtBeginning, nopStmtEnd); setUnit(firstAssign); }