use of net.runelite.asm.attributes.code.Label in project runelite by runelite.
the class RuneliteBufferTransformer method injectLengthHeader.
/**
* inject the length header after the packet opcode
*
* @param group
*/
private void injectLengthHeader(ClassGroup group) {
RWOpcodeFinder rw = new RWOpcodeFinder(group);
rw.find();
Method writeOpcode = rw.getWriteOpcode();
Code code = writeOpcode.getCode();
Instructions instructions = code.getInstructions();
List<Instruction> ins = instructions.getInstructions();
Instruction start = ins.get(0);
Instruction end = ins.stream().filter(i -> i.getType() == RETURN).findFirst().get();
Label labelForStart = instructions.createLabelFor(start);
Label labelForEnd = instructions.createLabelFor(end);
final net.runelite.asm.pool.Field runelitePacketField = new net.runelite.asm.pool.Field(new net.runelite.asm.pool.Class(findClient(group).getName()), RUNELITE_PACKET, Type.BOOLEAN);
int idx = ins.indexOf(labelForStart);
instructions.addInstruction(idx++, new GetStatic(instructions, runelitePacketField));
instructions.addInstruction(idx++, new IfEq(instructions, labelForStart));
net.runelite.asm.pool.Method method = new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(writeOpcode.getClassFile().getName()), RUNELITE_FINISH_PACKET, new Signature("()V"));
instructions.addInstruction(idx++, new ALoad(instructions, 0));
instructions.addInstruction(idx++, new InvokeVirtual(instructions, method));
idx = ins.indexOf(labelForEnd);
instructions.addInstruction(idx++, new GetStatic(instructions, runelitePacketField));
instructions.addInstruction(idx++, new IfEq(instructions, labelForEnd));
method = new net.runelite.asm.pool.Method(new net.runelite.asm.pool.Class(writeOpcode.getClassFile().getName()), RUNELITE_INIT_PACKET, new Signature("()V"));
instructions.addInstruction(idx++, new ALoad(instructions, 0));
instructions.addInstruction(idx++, new InvokeVirtual(instructions, method));
logger.info("Injected finish/init packet calls into {}", writeOpcode);
}
use of net.runelite.asm.attributes.code.Label in project runelite by runelite.
the class BufferMethodInjector method inject.
private void inject(ClassFile bufferClass, Method method) {
assert method.getExceptions().getExceptions().isEmpty();
Method newMethod = new Method(bufferClass, method.getName(), method.getDescriptor());
Code code = new Code(newMethod);
newMethod.setCode(code);
method.getCode().getInstructions().getInstructions().stream().forEach(i -> {
if (!(i instanceof Label)) {
i = i.clone();
}
if (i instanceof FieldInstruction) {
FieldInstruction fi = (FieldInstruction) i;
if (fi.getField().getName().equals("offset")) {
fi.setField(bp.getOffset().getPoolField());
} else if (fi.getField().getName().equals("payload")) {
fi.setField(bp.getBuffer().getPoolField());
} else if (fi.getField().getName().equals("runeliteLengthOffset")) {
fi.setField(bufferClass.findField("runeliteLengthOffset").getPoolField());
}
}
i.setInstructions(code.getInstructions());
code.getInstructions().addInstruction(i);
});
code.getExceptions().getExceptions().addAll(method.getCode().getExceptions().getExceptions());
bufferClass.addMethod(newMethod);
}
use of net.runelite.asm.attributes.code.Label in project runelite by runelite.
the class MenuActionDeobfuscator method insert.
private void insert(Method method, List<Comparison> comparisons) {
Instructions instructions = method.getCode().getInstructions();
List<Instruction> ins = instructions.getInstructions();
// replace all if(var == constant) with a jump to the false branch
// then, insert before the first jump the ifs to jump to the old
// true branch
//
// this is probably actually lookupswitch but it isn't mappable
// currently...
int min = -1;
for (Comparison comp : comparisons) {
if (min == -1) {
min = ins.indexOf(comp.lvt);
} else {
min = Math.min(min, ins.indexOf(comp.lvt));
}
if (comp.cmp.getType() == InstructionType.IF_ICMPEQ) {
If cmp = (If) comp.cmp;
// remove
instructions.remove(comp.ldc);
instructions.remove((Instruction) comp.lvt);
instructions.remove(comp.cmp);
comp.next = cmp.getJumps().get(0);
} else if (comp.cmp.getType() == InstructionType.IF_ICMPNE) {
// replace with goto dest
If cmp = (If) comp.cmp;
int idx = ins.indexOf(cmp);
assert idx != -1;
comp.next = instructions.createLabelFor(ins.get(idx + 1));
instructions.remove(comp.ldc);
instructions.remove((Instruction) comp.lvt);
instructions.replace(comp.cmp, new Goto(instructions, cmp.getJumps().get(0)));
} else {
throw new IllegalStateException();
}
}
assert min != -1;
// sort comparisons - but if they jump to the same address, they are equal..
List<Comparison> sortedComparisons = new ArrayList<>(comparisons);
Collections.sort(sortedComparisons, (c1, c2) -> compare(comparisons, c1, c2));
// reinsert jumps
for (int i = 0; i < sortedComparisons.size(); ++i) {
Comparison comp = sortedComparisons.get(i);
Instruction lvt = (Instruction) comp.lvt;
lvt.setInstructions(instructions);
comp.ldc.setInstructions(instructions);
instructions.addInstruction(min++, lvt);
instructions.addInstruction(min++, comp.ldc);
// use if_icmpeq if what follows also jumps to the same location
boolean multiple = i + 1 < sortedComparisons.size() && sortedComparisons.get(i + 1).next == comp.next;
if (multiple) {
instructions.addInstruction(min++, new IfICmpEq(instructions, comp.next));
} else {
// fernflower decompiles a series of if_icmpeq as chains of not equal expressions
Label label = instructions.createLabelFor(ins.get(min));
instructions.addInstruction(min++, new IfICmpNe(instructions, label));
instructions.addInstruction(min++, new Goto(instructions, comp.next));
// go past label
++min;
}
}
}
use of net.runelite.asm.attributes.code.Label in project runelite by runelite.
the class UnreachedCodeTest method testRun.
@Test
public void testRun() throws IOException {
UnreachedCode uc = new UnreachedCode();
uc.run(group);
ClassFile cf = group.getClasses().get(0);
Method method = cf.findMethod("entry");
Assert.assertFalse(method.getCode().getExceptions().getExceptions().isEmpty());
method = cf.findMethod("method1Unused");
Assert.assertNotNull(method);
Assert.assertFalse(method.getCode().getInstructions().getInstructions().stream().filter(i -> !(i instanceof Label)).findAny().isPresent());
Assert.assertTrue(method.getCode().getExceptions().getExceptions().isEmpty());
// Method is now invalid, remove so jar can be saved
cf.removeMethod(method);
// constructor now has no instructions
method = cf.findMethod("<init>");
Assert.assertNotNull(method);
Assert.assertFalse(method.getCode().getInstructions().getInstructions().stream().filter(i -> !(i instanceof Label)).findAny().isPresent());
// remove it too
cf.removeMethod(method);
}
use of net.runelite.asm.attributes.code.Label in project runelite by runelite.
the class MultiplicationDeobfuscatorTest method test4.
@Test
public void test4() {
ClassGroup group = ClassGroupFactory.generateGroup();
Code code = group.findClass("test").findMethod("func").getCode();
Instructions ins = code.getInstructions();
code.setMaxStack(2);
Instruction[] prepareVariables = { new LDC(ins, 3), new IStore(ins, 0) };
for (Instruction i : prepareVariables) {
ins.addInstruction(i);
}
LDC constant1 = new LDC(ins, 1807370871);
LDC constant2 = new LDC(ins, 981643079);
Label label1 = new Label(ins);
Instruction[] body = { new ILoad(ins, 0), new LDC(ins, 2), new IMul(ins), new LDC(ins, 0), new IfEq(ins, label1), new Pop(ins), new LDC(ins, 3), label1, constant1, new IMul(ins), constant2, new IMul(ins), new VReturn(ins) };
for (Instruction i : body) {
ins.addInstruction(i);
}
Execution e = new Execution(group);
e.populateInitialMethods();
e.run();
assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
Deobfuscator d = new MultiplicationDeobfuscator();
d.run(group);
Assert.assertEquals(1, constant1.getConstantAsInt());
Assert.assertEquals(1, constant2.getConstantAsInt());
}
Aggregations