use of net.runelite.asm.attributes.code.instructions.If in project runelite by runelite.
the class PacketWriteDeobfuscator method isEnd.
private boolean isEnd(InstructionContext ctx) {
// conditions where packet write ends:
// any invoke that isn't to the packet buffer
// any variable assignment
// any field assignment
// any conditional jump
// any return
Instruction i = ctx.getInstruction();
if (i instanceof InvokeInstruction) {
InvokeInstruction ii = (InvokeInstruction) i;
Method method = ii.getMethod();
if (!method.getClazz().equals(rw.getSecretBuffer().getPoolClass()) && !method.getClazz().equals(rw.getBuffer().getPoolClass())) {
return true;
}
}
if (i instanceof LVTInstruction) {
LVTInstruction lvt = (LVTInstruction) i;
if (lvt.store()) {
return true;
}
}
if (i instanceof SetFieldInstruction) {
return true;
}
if (i instanceof If || i instanceof If0) {
return true;
}
if (i instanceof ReturnInstruction) {
return true;
}
return false;
}
use of net.runelite.asm.attributes.code.instructions.If 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.If in project runelite by runelite.
the class ConstantParameter method findDeadParameters.
private void findDeadParameters(InstructionContext ins) {
List<ConstantMethodParameter> parameters = this.findParametersForMethod(ins.getFrame().getMethod());
for (ConstantMethodParameter parameter : parameters) {
int lvtIndex = parameter.lvtIndex;
if (parameter.invalid) {
continue;
}
if (ins.getInstruction() instanceof LVTInstruction) {
LVTInstruction lvt = (LVTInstruction) ins.getInstruction();
if (lvt.getVariableIndex() != lvtIndex) {
continue;
}
if (lvt.store() || ins.getInstruction().getType() == InstructionType.IINC) {
parameter.invalid = true;
// value changes at some point, parameter is used
continue;
}
// check what pops the parameter is a comparison
assert ins.getPushes().size() == 1;
StackContext sctx = ins.getPushes().get(0);
if (sctx.getPopped().size() != 1 || !(sctx.getPopped().get(0).getInstruction() instanceof ComparisonInstruction)) {
parameter.invalid = true;
continue;
}
}
if (!(ins.getInstruction() instanceof ComparisonInstruction)) {
continue;
}
// assume that this will always be variable index #paramIndex comp with a constant.
ComparisonInstruction comp = (ComparisonInstruction) ins.getInstruction();
StackContext one, two = null;
if (comp instanceof If0) {
one = ins.getPops().get(0);
} else if (comp instanceof If) {
one = ins.getPops().get(0);
two = ins.getPops().get(1);
} else {
throw new RuntimeException("Unknown comp ins");
}
// find if one is a lvt ins
LVTInstruction lvt = null;
StackContext other = null;
if (one.getPushed().getInstruction() instanceof LVTInstruction) {
lvt = (LVTInstruction) one.getPushed().getInstruction();
other = two;
} else if (two != null && two.getPushed().getInstruction() instanceof LVTInstruction) {
lvt = (LVTInstruction) two.getPushed().getInstruction();
other = one;
}
assert lvt == null || !lvt.store();
if (lvt == null || lvt.getVariableIndex() != lvtIndex) {
continue;
}
Number otherValue = null;
if (// two is null for if0
two != null) {
if (!(other.getPushed().getInstruction() instanceof PushConstantInstruction)) {
parameter.invalid = true;
continue;
}
PushConstantInstruction pc = (PushConstantInstruction) other.getPushed().getInstruction();
otherValue = (Number) pc.getConstant();
}
for (Number value : parameter.values) {
// the result of the comparison doesn't matter, only that it always goes the same direction for every invocation
boolean result = doLogicalComparison(value, comp, otherValue);
// not that all ifs for a specific parameter always take the same path
if (parameter.result != null && parameter.result != result) {
parameter.invalid = true;
} else {
parameter.operations.add(ins.getInstruction());
parameter.result = result;
}
}
}
}
use of net.runelite.asm.attributes.code.instructions.If 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;
}
use of net.runelite.asm.attributes.code.instructions.If in project runelite by runelite.
the class HandlerFinder method findHandlers.
private List<PacketHandler> findHandlers(Method process, Field packetOpcode) {
List<PacketHandler> handlers = new ArrayList<>();
Instructions ins = process.getCode().getInstructions();
for (int j = 0; j < ins.getInstructions().size(); ++j) {
Instruction i = ins.getInstructions().get(j);
if (i.getType() != InstructionType.GETSTATIC) {
continue;
}
GetStatic gs = (GetStatic) i;
if (gs.getMyField() != packetOpcode) {
continue;
}
Instruction push = ins.getInstructions().get(j + 1);
if (!(push instanceof PushConstantInstruction)) {
continue;
}
PushConstantInstruction pci = (PushConstantInstruction) push;
if (!(pci.getConstant() instanceof Number)) {
continue;
}
int opcode = ((Number) pci.getConstant()).intValue();
if (opcode == -1) {
continue;
}
Instruction jump = ins.getInstructions().get(j + 2);
if (jump.getType() != InstructionType.IF_ICMPEQ && jump.getType() != InstructionType.IF_ICMPNE) {
continue;
}
Instruction start, end;
if (jump.getType() == InstructionType.IF_ICMPEQ) {
// this seems to not ever happen
start = ((If) jump).getJumps().get(0);
// end = ins.getInstructions().get(j + 3);
end = null;
} else {
start = ins.getInstructions().get(j + 3);
end = ((If) jump).getJumps().get(0);
}
PacketHandler handler = new PacketHandler(process, jump, start, push, opcode);
handlers.add(handler);
if (end != null) {
// Anything else which jumps to here instead needs to return.
insertReturn(ins, jump, end);
}
logger.info("Found packet handler {} opcode {}", handler, handler.getOpcode());
}
return handlers;
}
Aggregations