Niestety autor klas poolingu był podejrzliwy i uczynił większość klas klasami finalnymi, przez to nie mogłem użyć mojej ulubionej techniki polegającej na nadpisaniu klasy i założenia breakpointów w metodach które chciałem obserwować...
I wtedy przyszło olśnienie ;-) A co gdyby "wstrzyknąć" swój kod do środka klasy "wroga" i zmusić ją do pracy na moją korzyść? ;-)
Na klasach poolingu tego jeszcze nie zrobiłem, ale idea wydaje się być słuszna. Szczególnie skuteczna powinna być w przypadku klas, które agregują lub są wrapperami dla klas które dziedziczą po czymś dostępnym, lub rozszerzają coś dostępnego.
Wyobraźmy sobie, że mamy kod interfejsu:
package org.przemelek.hack.secure;
public interface Form {
public void login(String user,String password);
}
SecureForm
, która jest "tajna" i finalną klasę opakowującą SecureForm
o nazwie SpecialForm
, która to klasa używa naszej tajnej klasy.package org.przemelek.hack.secure;
final class SecureForm implements Form {
protected SecureForm() {
System.out.println("Secure object created");
}
public void login(String user, String password) {
System.out.println("Secure login");
}
}
package org.przemelek.hack.secure;
public final class SpecialForm implements Form {
private Form form;
public SpecialForm() {
form = new SecureForm();
}
public void login(String user, String password) {
form.login(user, password);
}
}
I w tym momencie z pomocą przychodzą nam odbicia ;-)
package org.przemelek.hack;
import java.lang.reflect.Field;
import org.przemelek.hack.secure.Form;
import org.przemelek.hack.secure.SpecialForm;
public class Hack {
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Form form = new SpecialForm();
Field formField = SpecialForm.class.getDeclaredField("form");
formField.setAccessible(true);
final Form oldForm = (Form)formField.get(form);
formField.set(form, new Form() {
public void login(String user, String password) {
System.out.println("Hacked login :-)");
System.out.println("user:"+user+" password:"+password);
oldForm.login(user, password);
}
});
form.login("test", "tost");
}
}
Przez odbicia prosimy o zadeklarowane pole form, zapamiętujemy jego wartość, następnie tworzymy klasę anonimową na podstawie znanego nam interfejsu Form, i podmieniamy jej instancją wartość pola form.
I już działa ;-)
Gdy gdziekolwiek w naszym kodzie, czy kodzie biblioteki którą hackujemy nastąpi wywołanie metody login(String,String) z klasy SpecialForm wywołany zostanie także nasz kod :-) Sztuczki tropiciela błędów, part 2
Sztuczki tropiciela błędów, part 1
Podobne postybeta
Sztuczki tropiciela błędów, part 4
Sztuczki tropiciela błędów, part 2 ;-)
Niecne wykorzystanie refleksji... czyli jak poszukać tekstu w drzewie obiektów? ;-)
Ile to jest 1+1 w Java'ie?
PKO BP to jednak nie umie w płatności..
Brak komentarzy:
Prześlij komentarz