use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class ModArith method guess.
private void guess() {
for (ClassFile cf : group.getClasses()) {
for (Field f : cf.getFields()) {
FieldInfo fieldInfo = getFieldInfo(f);
// all constants in instructions associated with the field
Collection<AssociatedConstant> col = fieldInfo.constants;
if (col.isEmpty()) {
continue;
}
Type type = f.getType();
assert type.equals(Type.INT) || type.equals(Type.LONG);
Class typeOfField = type.equals(Type.INT) ? Integer.class : Long.class;
// filter collect constants of the correct type
Collection<AssociatedConstant> col2 = col.stream().filter(i -> i.value.getClass() == typeOfField).collect(Collectors.toList());
// filer out ones that have another field in the expression
List<Number> noOther = col2.stream().filter(i -> !i.other && !i.constant).map(i -> i.value).distinct().collect(Collectors.toList());
List<Number> other = col2.stream().filter(i -> i.other || i.constant).map(i -> i.value).collect(Collectors.toList());
other.addAll(noOther);
other = ImmutableSet.copyOf(other).asList();
// guess with constants not associated with other fields
Pair p = this.guess(f, noOther);
if (p == null) {
// fall back to all constants
p = this.guess(f, other);
}
// check that this guess doesn't increase constants
if (p != null && !fieldInfo.guessDecreasesConstants(p)) {
continue;
}
if (p != null) {
pairs.add(p);
}
}
}
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class MultiplyOneDeobfuscator method visit.
private void visit(MethodContext mctx) {
for (InstructionContext ictx : mctx.getInstructionContexts()) {
Instruction instruction = ictx.getInstruction();
if (!(instruction instanceof IMul) && !(instruction instanceof LMul)) {
continue;
}
Instructions ins = ictx.getInstruction().getInstructions();
if (ins == null) {
continue;
}
List<Instruction> ilist = ins.getInstructions();
if (!ilist.contains(ictx.getInstruction())) {
// already done
continue;
}
StackContext one = ictx.getPops().get(0);
StackContext two = ictx.getPops().get(1);
StackContext other = null;
int removeIdx = -1;
if (one.getPushed().getInstruction() instanceof PushConstantInstruction && DMath.equals((Number) ((PushConstantInstruction) one.getPushed().getInstruction()).getConstant(), 1)) {
removeIdx = 0;
other = two;
} else if (two.getPushed().getInstruction() instanceof PushConstantInstruction && DMath.equals((Number) ((PushConstantInstruction) two.getPushed().getInstruction()).getConstant(), 1)) {
removeIdx = 1;
other = one;
}
if (removeIdx == -1) {
continue;
}
if (onlyConstants && !(other.getPushed().getInstruction() instanceof PushConstantInstruction)) {
continue;
}
if (!MultiplicationDeobfuscator.isOnlyPath(ictx, removeIdx == 0 ? one : two)) {
continue;
}
// remove 1
ictx.removeStack(removeIdx);
// remove mul
ins.remove(instruction);
++count;
}
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class ControlFlowDeobfuscator method run.
private void run(Code code) {
Instructions ins = code.getInstructions();
Exceptions exceptions = code.getExceptions();
ControlFlowGraph graph = new ControlFlowGraph.Builder().build(code);
for (Block block : graph.getBlocks()) {
assert block.getFlowsFrom() == null;
assert block.getFlowsInto() == null;
}
if (// graph.toString() is expensive
logger.isDebugEnabled()) {
logger.debug(graph.toString());
}
List<Exception> originalExceptions = new ArrayList<>(exceptions.getExceptions());
// Clear existing exceptions and instructions as we are going to
// rebuild them
exceptions.clear();
ins.clear();
List<Block> done = new ArrayList<>();
Queue<Block> queue = new PriorityQueue<>(this::compareBlock);
// add initial code block
queue.add(graph.getHead());
while (!queue.isEmpty()) {
Block block = queue.remove();
if (done.contains(block)) {
continue;
}
done.add(block);
++placedBlocks;
logger.debug("Placed block {}", block.getId());
List<Block> next = block.getNext();
if (next.isEmpty() == false) {
// jumps are added in order their instructions are reached by ControlFlowGraph,
// so the last jump is the goto.
//
// removing this line causes the priority queue (due to implementation detail on how
// it handles objects with equal priority) to try to optimize for block closeness
// (how close blocks which are neighbors are to each other in bytecode).
// I get a jump delta of ~+14k with this on 143, vs ~-47k when priotiziing optimizing
// out jumps. I can't tell which is better.
next.get(next.size() - 1).setJumptarget(true);
}
// add next reachable blocks
for (Block bl : next) {
queue.add(bl);
}
for (Instruction i : block.getInstructions()) {
assert i.getInstructions() == null;
// I shouldn't have to do this here
i.setInstructions(ins);
ins.addInstruction(i);
}
}
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class MultiplyZeroDeobfuscator method visit.
private void visit(MethodContext mctx) {
for (InstructionContext ictx : mctx.getInstructionContexts()) {
Instruction instruction = ictx.getInstruction();
Instructions ins = instruction.getInstructions();
if (ins == null) {
continue;
}
if (!(instruction instanceof IMul) && !(instruction instanceof LMul)) {
continue;
}
List<Instruction> ilist = ins.getInstructions();
StackContext one = ictx.getPops().get(0);
StackContext two = ictx.getPops().get(1);
Instruction ione = one.getPushed().getInstruction(), itwo = two.getPushed().getInstruction();
boolean remove = false;
if (ione instanceof PushConstantInstruction) {
PushConstantInstruction pci = (PushConstantInstruction) ione;
Number value = (Number) pci.getConstant();
if (DMath.equals(value, 0)) {
remove = true;
}
}
if (itwo instanceof PushConstantInstruction) {
PushConstantInstruction pci = (PushConstantInstruction) itwo;
Number value = (Number) pci.getConstant();
if (DMath.equals(value, 0)) {
remove = true;
}
}
if (remove == false) {
continue;
}
if (!ilist.contains(instruction)) {
// already done
continue;
}
if (!MultiplicationDeobfuscator.isOnlyPath(ictx, null)) {
continue;
}
// remove both, remove imul, push 0
ictx.removeStack(1);
ictx.removeStack(0);
if (instruction instanceof IMul) {
ins.replace(instruction, new LDC(ins, 0));
} else if (instruction instanceof LMul) {
ins.replace(instruction, new LDC(ins, 0L));
} else {
throw new IllegalStateException();
}
++count;
}
}
use of net.runelite.asm.attributes.code.Instructions in project runelite by runelite.
the class ConstantParameter method removeDeadOperations.
// remove logically dead comparisons
private int removeDeadOperations(MethodContext mctx) {
int count = 0;
for (ConstantMethodParameter cmp : parameters.values()) {
if (cmp.invalid) {
continue;
}
if (!cmp.methods.contains(mctx.getMethod())) {
continue;
}
// only annotate garbage value of last param
if (cmp.paramIndex + 1 == mctx.getMethod().getDescriptor().size()) {
annotateObfuscatedSignature(cmp);
}
for (// comparisons
Instruction ins : // comparisons
cmp.operations) {
if (ins.getInstructions() == null || ins.getInstructions().getCode().getMethod() != mctx.getMethod()) {
continue;
}
InstructionContext ctx = mctx.getInstructonContexts(ins).toArray(new InstructionContext[0])[0];
// branch that is always taken
boolean branch = cmp.result;
if (ins.getInstructions() == null) {
// ins already removed?
continue;
}
Instructions instructions = ins.getInstructions();
// remove the if
if (ctx.getInstruction() instanceof If) {
ctx.removeStack(1);
}
ctx.removeStack(0);
int idx = instructions.getInstructions().indexOf(ins);
if (idx == -1) {
// already removed?
continue;
}
++count;
Instruction to;
if (branch) {
JumpingInstruction jumpIns = (JumpingInstruction) ins;
assert jumpIns.getJumps().size() == 1;
to = jumpIns.getJumps().get(0);
} else {
// just go to next instruction
to = instructions.getInstructions().get(idx + 1);
}
assert to.getInstructions() == instructions;
assert ins != to;
assert instructions.getInstructions().contains(to);
instructions.remove(ins);
assert instructions.getInstructions().contains(to);
if (branch) {
Goto gotoins = new Goto(instructions, instructions.createLabelFor(to));
// insert goto
instructions.getInstructions().add(idx, gotoins);
}
}
}
return count;
}
Aggregations