Más contenido relacionado La actualidad más candente (20) Similar a Binary patching for fun and profit @ JUG.ru, 25.02.2012 (20) Más de Anton Arhipov (20) Binary patching for fun and profit @ JUG.ru, 25.02.20122. Binary Patching
Ninja.class Ninja.class’
10101010101 10101010101
11000101010 11100001010
10101010001 10101010001
00010001110 00010001110
11011101011 11011101110
a.k.a instrumentation
3. Binary Patching
ClassLoader
Application
MyClass.class
New code:
1001010010010
Transformer
0101011001010
MyObject
4. Why?
• Programming model (AOP, ORM)
• Tooling (profilers, coverage)
• Legacy integration
… or maybe you’re just bored?
5. How?
• Add –javaagent to hook into class loading
process
• Implement ClassFileTransformer
• Use bytecode manipulation libraries
(Javassist, cglib, asm) to add any custom logic
java.lang.instrument
9. j.l.instrument.ClassFileTransformer
new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className,
Class<?>classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass(new
ByteArrayInputStream(classfileBuffer));
transformClass(ct, cp);
return ct.toBytecode();
}
}
10. j.l.instrument.ClassFileTransformer
new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className,
Class<?>classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass(new
ByteArrayInputStream(classfileBuffer));
transformClass(ct, cp);
return ct.toBytecode();
}
}
11. j.l.instrument.ClassFileTransformer
new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className,
Class<?>classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass(new
ByteArrayInputStream(classfileBuffer));
transformClass(ct, cp);
return ct.toBytecode();
}
}
12. j.l.instrument.ClassFileTransformer
new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className,
Class<?>classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer){
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.makeClass(new
ByteArrayInputStream(classfileBuffer));
transformClass(ct, cp);
return ct.toBytecode();
}
}
14. Javassist
• Bytecode manipulation made easy
• Source-level and bytecode-level API
• Uses the vocabulary of Java language
• On-the-fly compilation of the injected code
• http://www.jboss.org/javassist
15. Adding Interfaces
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.get("org.geecon.Alarm");
ct.addInterface(cp.get(Listener.class.getName()));
ct.addMethod(CtNewMethod.make("public void fire(){ alert(); }", ct));
public class Alarm { public interface Listener {
void alert() {} void fire();
} }
16. Adding Interfaces
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.get("org.geecon.Alarm");
ct.addInterface(cp.get(Listener.class.getName()));
ct.addMethod(CtNewMethod.make("public void fire(){ alert(); }", ct));
public class Alarm { public interface Listener {
void alert() {} void fire();
} }
17. Adding Interfaces
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.get("org.geecon.Alarm");
ct.addInterface(cp.get(Listener.class.getName()));
ct.addMethod(CtNewMethod.make("public void fire(){ alert(); }", ct));
public class Alarm { public interface Listener {
void alert() {} void fire();
} }
18. Adding Interfaces
ClassPool cp = ClassPool.getDefault();
CtClass ct = cp.get("org.geecon.Alarm");
ct.addInterface(cp.get(Listener.class.getName()));
ct.addMethod(CtNewMethod.make("public void fire(){ alert(); }", ct));
public class Alarm { public interface Listener {
void alert() {} void fire();
} }
19. Simple AOP
ProxyFactory pf = new ProxyFactory();
pf.setSuperclass(Notifier.class);
pf.setFilter(new MethodFilter() { … });
Notifier notifier = (Notifier) pf.createClass().newInstance();
((ProxyObject) notifier).setHandler(new MethodHandler() { … });
System.out.println("calling on()");
notifier.on(); public class Notifier {
System.out.println("calling off()"); public void on(){ }
notifier.off();
@Pointcut
public void off(){}
}
20. Intercept Statements
ClassPool pool = ClassPool.getDefault();
CtClass ct = pool.get("org.geecon.PaymentMachine");
ct.getDeclaredMethod("process")
.instrument(new ExprEditor() {
public void edit(NewExpr e)
throws CannotCompileException {
e.replace("$_ = $proceed($$);");
}
});
22. IDEs Containers Frameworks
Build Tools
More at http://www.jrebel.com/features