Advertisement
Guest User

Untitled

a guest
Jul 21st, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.45 KB | None | 0 0
  1. package io.deki.updater.asm.deob;
  2.  
  3. import io.deki.updater.asm.FieldMult;
  4. import io.deki.updater.hook.FieldHook;
  5. import org.objectweb.asm.Opcodes;
  6. import org.objectweb.asm.tree.*;
  7.  
  8. import java.util.*;
  9.  
  10. /**
  11. * Created by Deki on 09.07.2019
  12. */
  13. public class MultFinder {
  14.  
  15. private static List<FieldMult> potentialMults, mults;
  16.  
  17. /**
  18. * main function
  19. * @param nodes List of classnodes from gamepack
  20. */
  21. public static void mapMults(Collection<ClassNode> nodes) {
  22. potentialMults = new ArrayList<>();
  23. mults = new ArrayList<>();
  24. for (ClassNode node : nodes) {
  25. process(node);
  26. }
  27. }
  28.  
  29. /**
  30. * Finds a specified hooks' mult in the mappings and sets it.
  31. * FUN FACT: streams are better for big datasets than iterators,
  32. * not sure if this counts as a big dataset though :)
  33. * @param hook Field hook object used to store owner/name/mult
  34. */
  35. public static void setMult(FieldHook hook) {
  36. FieldMult mult = mults.stream().filter(m -> m.getOwner().equals(hook.getClazz())
  37. && m.getName().equals(hook.getField())).findFirst().orElse(null);
  38. if (mult != null) hook.setMultiplier(mult.getMult());
  39. }
  40.  
  41. /**
  42. * Internal method to process each class node.
  43. * We're looking for this pattern:
  44. * GETFIELD/GETSTATIC/PUTFIELD
  45. * LDC
  46. * IMUL/LMUL
  47. * (ldc and getter/setter can be swapped)
  48. * @param node Class node to be processed
  49. */
  50. private static void process(ClassNode node) {
  51. //we want to loop through all methods
  52. node.methods.forEach(methodNode -> methodNode.instructions.iterator().forEachRemaining(insn -> {
  53. //we're looking for IMUL/LMULs, no need for the other ones
  54. if (insn.opcode() != Opcodes.IMUL && insn.opcode() != Opcodes.LMUL) return;
  55. //get the instruction from before the multiplication instruction
  56. AbstractInsnNode first = insn.previous();
  57. long constant = decodeLdc(first);
  58. FieldInsnNode field = decodeField(first);
  59. //here we split the path into two for optimal results (thanks spencer!):
  60. //first option is if the pattern is GET/LDC/MUL
  61. //second is LDC/GET/MUL
  62. if (constant == -1) {
  63. AbstractInsnNode second = first.previous();
  64. constant = decodeLdc(second);
  65. } else {
  66. AbstractInsnNode second = first.previous();
  67. field = decodeField(second);
  68. }
  69. //check if anything is null or if the mult is an even number (thanks spencer!)
  70. if (field == null || constant == -1 || (constant & 1) == 0) return;
  71. boolean decoder = field.opcode() == Opcodes.GETFIELD || field.opcode() == Opcodes.GETSTATIC;
  72. //create a FieldMult object, just used for storing values
  73. FieldMult mult = new FieldMult(field.owner, field.name, constant, decoder);
  74. //check if we already mapped the mult in question
  75. if (mults.contains(mult)) return;
  76. //check if we already encountered this specific mult.
  77. //jagex's obfuscator sprinkles in dummy constants, but these never occur more than once.
  78. //if it's present more than once we're confident that it's the real deal.
  79. if (potentialMults.contains(mult)) {
  80. mults.add(mult);
  81. return;
  82. }
  83. //add the field to encountered mults.
  84. potentialMults.add(mult);
  85. }));
  86. }
  87.  
  88. private static long decodeLdc(AbstractInsnNode node) {
  89. //if this isn't an ldc instruction it doesn't match our pattern and we don't need it
  90. if (node == null || node.opcode() != Opcodes.LDC) return -1;
  91. //at this point we know it's an ldc and we can store its value for later use.
  92. //we're parsing the value as a string as the jvm gets angry if we just cast
  93. return Long.parseLong("" + ((LdcInsnNode) node).cst);
  94. }
  95.  
  96. private static FieldInsnNode decodeField(AbstractInsnNode node) {
  97. //check if its a getfield/getstatic/putfield, if not we don't want it
  98. if (node == null || (node.opcode() != Opcodes.GETFIELD && node.opcode() != Opcodes.GETSTATIC
  99. && node.opcode() != Opcodes.PUTFIELD && node.opcode() != Opcodes.PUTSTATIC)) return null;
  100. //store this as a FieldInsnNode as I cba to cast it all the time
  101. return (FieldInsnNode) node;
  102. }
  103.  
  104. public static List<FieldMult> getMults() {
  105. return mults;
  106. }
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement