|
| 1 | +# Bytecode Utilities Guide |
| 2 | + |
| 3 | +This project now includes comprehensive bytecode manipulation utilities that can be used independently or as part of the obfuscation framework. |
| 4 | + |
| 5 | +## Core Utilities |
| 6 | + |
| 7 | +### BytecodeUtils |
| 8 | +Provides static utility methods for common bytecode operations: |
| 9 | + |
| 10 | +```java |
| 11 | +// Push integer constants efficiently |
| 12 | +BytecodeUtils.pushInteger(mv, 42); |
| 13 | + |
| 14 | +// Check instruction types |
| 15 | +if (BytecodeUtils.isConstantInstruction(opcode)) { ... } |
| 16 | +if (BytecodeUtils.isIntegerConstant(opcode)) { ... } |
| 17 | + |
| 18 | +// Get constant values |
| 19 | +int value = BytecodeUtils.getConstantValue(Opcodes.ICONST_1); // returns 1 |
| 20 | + |
| 21 | +// Check if methods/fields should be skipped |
| 22 | +if (BytecodeUtils.isMethodSkippable("main", access)) { ... } |
| 23 | +``` |
| 24 | + |
| 25 | +### InstructionObfuscator |
| 26 | +Handles instruction-level obfuscation with multiple strategies: |
| 27 | + |
| 28 | +```java |
| 29 | +Random random = new Random(); |
| 30 | +InstructionObfuscator obfuscator = new InstructionObfuscator(random, |
| 31 | + InstructionObfuscator.ObfuscationStrategy.ARITHMETIC); |
| 32 | + |
| 33 | +// Obfuscate a constant instruction |
| 34 | +obfuscator.obfuscateConstant(mv, Opcodes.ICONST_1); |
| 35 | + |
| 36 | +// Obfuscate specific integer values |
| 37 | +obfuscator.obfuscateIntegerValue(mv, 42); |
| 38 | +``` |
| 39 | + |
| 40 | +Available strategies: |
| 41 | +- `ARITHMETIC`: Uses arithmetic operations (add, subtract, multiply, divide, xor) |
| 42 | +- `BITWISE`: Uses bitwise operations (and, or, shift) |
| 43 | +- `STACK_MANIPULATION`: Uses stack manipulation techniques |
| 44 | +- `MIXED`: Randomly combines all strategies |
| 45 | + |
| 46 | +## Abstract Base Classes |
| 47 | + |
| 48 | +### AbstractMethodVisitor |
| 49 | +Extends ASM's MethodVisitor with common functionality: |
| 50 | + |
| 51 | +```java |
| 52 | +public class MyMethodVisitor extends AbstractMethodVisitor { |
| 53 | + public MyMethodVisitor(MethodVisitor mv, ObfuscationContext context, |
| 54 | + String className, String methodName, String methodDescriptor) { |
| 55 | + super(mv, context, className, methodName, methodDescriptor); |
| 56 | + } |
| 57 | + |
| 58 | + @Override |
| 59 | + public void visitInsn(int opcode) { |
| 60 | + if (shouldProcessWithProbability(0.1f)) { |
| 61 | + emitGarbage(); // Add random garbage instructions |
| 62 | + logTransformation("Added garbage instruction"); |
| 63 | + } |
| 64 | + super.visitInsn(opcode); |
| 65 | + } |
| 66 | + |
| 67 | + @Override |
| 68 | + protected String getTransformerName() { |
| 69 | + return "MyTransformer"; |
| 70 | + } |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +### AbstractClassVisitor |
| 75 | +Extends ASM's ClassVisitor with common patterns: |
| 76 | + |
| 77 | +```java |
| 78 | +public class MyClassVisitor extends AbstractClassVisitor { |
| 79 | + public MyClassVisitor(ClassVisitor cv, ObfuscationContext context) { |
| 80 | + super(cv, context); |
| 81 | + } |
| 82 | + |
| 83 | + @Override |
| 84 | + protected MethodVisitor createMethodVisitor(MethodVisitor mv, int access, String name, |
| 85 | + String descriptor, String signature, String[] exceptions) { |
| 86 | + return new MyMethodVisitor(mv, context, currentClassName, name, descriptor); |
| 87 | + } |
| 88 | + |
| 89 | + @Override |
| 90 | + protected String getTransformerName() { |
| 91 | + return "MyTransformer"; |
| 92 | + } |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +## Transformation Factory |
| 97 | + |
| 98 | +The `BytecodeTransformationFactory` provides pre-built transformers: |
| 99 | + |
| 100 | +### Quick Transformers |
| 101 | +```java |
| 102 | +// Create a constant obfuscator with 15% probability |
| 103 | +ClassVisitor constantObfuscator = BytecodeTransformationFactory.createConstantObfuscator( |
| 104 | + writer, context, 0.15f); |
| 105 | + |
| 106 | +// Create a garbage injector with 5% probability |
| 107 | +ClassVisitor garbageInjector = BytecodeTransformationFactory.createGarbageInjector( |
| 108 | + writer, context, 0.05f); |
| 109 | + |
| 110 | +// Create an instruction obfuscator with mixed strategy |
| 111 | +ClassVisitor instructionObfuscator = BytecodeTransformationFactory.createInstructionObfuscator( |
| 112 | + writer, context, InstructionObfuscator.ObfuscationStrategy.MIXED, 0.1f); |
| 113 | +``` |
| 114 | + |
| 115 | +### Custom Transformers |
| 116 | +```java |
| 117 | +ClassVisitor customTransformer = BytecodeTransformationFactory.createCustomTransformer( |
| 118 | + writer, context, "MyTransformer", |
| 119 | + builder -> builder |
| 120 | + .withInstructionObfuscation(InstructionObfuscator.ObfuscationStrategy.ARITHMETIC, 0.2f) |
| 121 | + .withGarbageInjection(0.1f) |
| 122 | + .build() |
| 123 | +); |
| 124 | +``` |
| 125 | + |
| 126 | +## Creating Your Own Transformer |
| 127 | + |
| 128 | +### Simple Transformer |
| 129 | +```java |
| 130 | +public class MySimpleTransformer extends AbstractTransformer { |
| 131 | + public MySimpleTransformer() { |
| 132 | + super("MySimpleTransformer", 100); |
| 133 | + } |
| 134 | + |
| 135 | + @Override |
| 136 | + public void transform(ClassReader reader, ClassWriter writer, ObfuscationContext context) { |
| 137 | + ClassVisitor visitor = BytecodeTransformationFactory.createConstantObfuscator( |
| 138 | + writer, context, 0.2f); |
| 139 | + reader.accept(visitor, 0); |
| 140 | + } |
| 141 | + |
| 142 | + @Override |
| 143 | + public boolean isEnabled(ObfuscationContext context) { |
| 144 | + return context.getConfig().isObfuscateConditions(); |
| 145 | + } |
| 146 | +} |
| 147 | +``` |
| 148 | + |
| 149 | +### Complex Transformer with Chaining |
| 150 | +```java |
| 151 | +public class MyComplexTransformer extends AbstractTransformer { |
| 152 | + public MyComplexTransformer() { |
| 153 | + super("MyComplexTransformer", 200); |
| 154 | + } |
| 155 | + |
| 156 | + @Override |
| 157 | + public void transform(ClassReader reader, ClassWriter writer, ObfuscationContext context) { |
| 158 | + // Chain multiple transformations |
| 159 | + ClassVisitor chain = writer; |
| 160 | + |
| 161 | + // Add garbage injection |
| 162 | + chain = BytecodeTransformationFactory.createGarbageInjector(chain, context, 0.05f); |
| 163 | + |
| 164 | + // Add instruction obfuscation |
| 165 | + chain = BytecodeTransformationFactory.createInstructionObfuscator( |
| 166 | + chain, context, InstructionObfuscator.ObfuscationStrategy.BITWISE, 0.15f); |
| 167 | + |
| 168 | + // Add constant obfuscation |
| 169 | + chain = BytecodeTransformationFactory.createConstantObfuscator(chain, context, 0.2f); |
| 170 | + |
| 171 | + reader.accept(chain, 0); |
| 172 | + } |
| 173 | + |
| 174 | + @Override |
| 175 | + public boolean isEnabled(ObfuscationContext context) { |
| 176 | + return true; // Always enabled |
| 177 | + } |
| 178 | +} |
| 179 | +``` |
| 180 | + |
| 181 | +## Advanced Usage |
| 182 | + |
| 183 | +### Custom Method Visitor |
| 184 | +```java |
| 185 | +public class MyAdvancedMethodVisitor extends AbstractMethodVisitor { |
| 186 | + private final InstructionObfuscator obfuscator; |
| 187 | + |
| 188 | + public MyAdvancedMethodVisitor(MethodVisitor mv, ObfuscationContext context, |
| 189 | + String className, String methodName, String methodDescriptor) { |
| 190 | + super(mv, context, className, methodName, methodDescriptor); |
| 191 | + this.obfuscator = new InstructionObfuscator(random, InstructionObfuscator.ObfuscationStrategy.MIXED); |
| 192 | + } |
| 193 | + |
| 194 | + @Override |
| 195 | + public void visitInsn(int opcode) { |
| 196 | + // Custom logic for specific opcodes |
| 197 | + if (opcode == Opcodes.RETURN && shouldProcessWithProbability(0.3f)) { |
| 198 | + // Add dummy instructions before return |
| 199 | + BytecodeUtils.pushInteger(super.mv, random.nextInt(1000)); |
| 200 | + super.visitInsn(Opcodes.POP); |
| 201 | + logTransformation("Added dummy instruction before return"); |
| 202 | + } |
| 203 | + |
| 204 | + // Apply obfuscation to constants |
| 205 | + if (BytecodeUtils.isIntegerConstant(opcode) && shouldProcessWithProbability(0.2f)) { |
| 206 | + obfuscator.obfuscateConstant(super.mv, opcode); |
| 207 | + logTransformation("Obfuscated constant"); |
| 208 | + } else { |
| 209 | + super.visitInsn(opcode); |
| 210 | + } |
| 211 | + } |
| 212 | + |
| 213 | + @Override |
| 214 | + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { |
| 215 | + // Custom field access obfuscation |
| 216 | + if (isInPackageScope() && shouldProcessWithProbability(0.1f)) { |
| 217 | + emitNOP(); // Add NOP before field access |
| 218 | + logTransformation("Added NOP before field access"); |
| 219 | + } |
| 220 | + super.visitFieldInsn(opcode, owner, name, descriptor); |
| 221 | + } |
| 222 | + |
| 223 | + @Override |
| 224 | + protected String getTransformerName() { |
| 225 | + return "MyAdvancedTransformer"; |
| 226 | + } |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | +## Best Practices |
| 231 | + |
| 232 | +1. **Chain Transformations**: Use multiple small transformers instead of one large one |
| 233 | +2. **Use Probabilities**: Don't obfuscate every instruction - use reasonable probabilities |
| 234 | +3. **Extend Abstract Classes**: Use `AbstractTransformer`, `AbstractClassVisitor`, and `AbstractMethodVisitor` |
| 235 | +4. **Leverage Utilities**: Use `BytecodeUtils` and `InstructionObfuscator` for common operations |
| 236 | +5. **Log Transformations**: Use `logTransformation()` for debugging and verbose output |
| 237 | +6. **Check Scopes**: Always check if classes/methods are in the obfuscation scope |
| 238 | +7. **Handle Edge Cases**: Use utility methods to skip special methods and fields |
| 239 | + |
| 240 | +## Integration |
| 241 | + |
| 242 | +To use these utilities in your own project, simply: |
| 243 | + |
| 244 | +1. Copy the utility classes from `net.cvs0.utils` |
| 245 | +2. Copy the abstract base classes from `net.cvs0.core` |
| 246 | +3. Adapt the `ObfuscationContext` to your needs, or create your own context interface |
| 247 | +4. Use the factory methods to create transformers quickly |
| 248 | + |
| 249 | +The utilities are designed to be loosely coupled and can work independently of the main obfuscation framework. |
0 commit comments