Globalne opcje obfuskacji. Wyłączone, spowodują zignorowanie adnotacji @Obfuscate w kodzie źródłowym. |
System.out.println("1");
System.out.println("2");
System.out.println("3");
|
int JOWCN_FGIWJIGTWJ_JSDAO = 0;
JOWCN_FGIWJIGTWJ_JSDAO = 1148643996;
while (JOWCN_FGIWJIGTWJ_JSDAO != 1421874931) {
switch(JOWCN_FGIWJIGTWJ_JSDAO) {
case 797943348:
System.out.println("3");
JOWCN_FGIWJIGTWJ_JSDAO += 623931583;
break;
case 1148643996:
System.out.println("1");
JOWCN_FGIWJIGTWJ_JSDAO -= 911757835;
break;
case 236886161:
System.out.println("2");
JOWCN_FGIWJIGTWJ_JSDAO -= -561057187;
break;
}
|
Przeczytaj co to ścieżka wykonywania kodu.
|
int myNum = 5;
float myFloatNum = 5.99f;
char myLetter = 'D';
boolean myBool = true;
String myText = "Java Obfuscator";
|
int ap9axcpArl_nyapT__QpnQOl_ = 5;
float var_3897 = 5.99f;
char aAqktfgaaaqRjhiouqlSwoqgob = 'D';
boolean nVdbxytrOhipcleakh = true;
String MUQJO_OGIEHC = "Java Obfuscator";
|
Wszystkie odwołania do przemianowanych zmiennych są automatycznie poprawiane.
|
public int calc(double numArray[]) {...}
|
public int SqcFsxe(double[] numArray) {...}
|
Wszystkie odwołania do przemianowanych metod są automatycznie poprawiane. Nazwa punktu wejściowego main() pozostaje niezmieniona. Nazwy metod oznaczone adnotacją @Override nie są zmieniane.
|
public static int methodNum1(int param)
{...}
public static int methodNum2(int param)
{...}
public static int methodNum3(int param)
{...}
|
public static int methodNum2(int param)
{...}
public static int methodNum3(int param)
{...}
public static int methodNum1(int param)
{...}
|
Kolejnośc metod w kodzie źródłowym Java nie ma znaczenia.
|
int[] ports = { 21, 80, 443 };
System.out.println(ports[0]);
|
int[] ports = { 43668, 43701, 43874 };
for (int i = 0; i < ports.length; i++) {
ports[i] ^= 0xAAAA;
}
System.out.println(ports[0]);
|
Zawartość tablic liczb całkowitych jest przechowywana w zaszyfrowanej postaci i dekodowana w czasie działania programu.
|
double[] scale = { 1.5, 2.75 };
return scale[1];
|
long[] data = { 4609434218613702656L, 4613374868287651840L };
double[] scale = new double[data.length];
for (int i = 0; i < data.length; i++) {
scale[i] = Double.longBitsToDouble(data[i] ^ 0x55AA55AA55AA55AAL);
}
return scale[1];
|
Stałe z tablic typu double są ukrywane jako zakodowane wzorce bitów i odtwarzane podczas działania programu.
|
char[] token = { 'A', 'P', 'I' };
return token[2];
|
char[] token = { 0x1A, 0x0B, 0x12 };
for (int i = 0; i < token.length; i++) {
token[i] = (char) (token[i] ^ 0x5B);
}
return token[2];
|
Literały tablic znaków są zastępowane zaszyfrowanymi wartościami i przywracane dopiero przez wygenerowany kod dekodujący.
|
String[] roles = { "admin", "guest" };
return roles[0];
|
String[] roles = { "\u4708\u470d\u4704\u4700\u4707",
"\u470e\u471c\u470c\u471a\u471b" };
for (int j = 0; j < roles.length; j++) {
char[] var_8 = roles[j].toCharArray();
for (int var_8i = 0; var_8i < var_8.length; var_8i++) {
var_8[var_8i] = (char) ((var_8[var_8i] ^ 18257) & 0xFFFF);
}
roles[j] = new String(var_8);
}
return roles[0];
|
Elementy tablic ciągów tekstowych są szyfrowane niezależnie i odtwarzane przez wygenerowany kod uruchamiany w czasie działania.
|
public static int method(int param) {
int a = 1;
int b = a + 2;
int c = 0;
if (b > 3) return c;
return 4;
}
|
public static int method(int param) {
int a = (int) (681.57415 - Math.cbrt(315229127.95597));
int b = a + (int) (2.76739 - Math.acos(0.71973));
int c = (int) (-1.20690 + Math.tan(0.87887));
if (b > (int) (-1.85887 + Math.log10(72255.55488)))
return c;
return (int) Math.min(6525.74776, 4.00000);
}
|
Wykorzystanych jest ponad 15 funkcji matematycznych z klasy java.lang.Math.*.
|
System.out.println("Java Obfuscator Online");
|
System.out.println("Hel".concat("lo, World!");
|
Wybrane literały są dzielone na fragmenty i składane z powrotem przez zagnieżdżone wywołania String.concat, co dodaje pośrednie wyrażenia do analizy przed opcjonalnym polimorficznym szyfrowaniem stringów.
|
System.out.println("Java Obfuscator Online");
|
String var_127 = "";
int[] var_1774 = { 0xFB5F, 0xF9EF, 0xF89F, 0xF9EF,
0xFDFF, 0xFB0F, 0xF9DF, 0xF99F,
0xF8AF, 0xF8CF, 0xF9CF, 0xF9EF,
0xF8BF, 0xF90F, 0xF8DF, 0xFDFF,
0xFB0F, 0xF91F, 0xF93F, 0xF96F,
0xF91F, 0xF9AF };
for (int hGrz = 0, x = 0; hGrz < 22; hGrz++) {
x = var_1774[hGrz];
x ^= 0xFFFF;
x = ((x << 12) | ((x & 0xFFFF) >> 4)) & 0xFFFF;
var_127 += (char) (x & 0xFFFF);
}
System.out.println(var_127);
|
Polimorficzne szyfrowanie ciągów tekstowych wykorzystuje silnik z naszego innego rozwiązania StringEncrypt.
|
public static int method(int param) {
int a = 1;
int b = a + 2;
int c = 0;
if (b > 3) return c;
return 4;
}
|
public static int method(int param) {
int[] IFNMDK = { 0, 3, 2, 4, 1 };
int a = IFNMDK[4];
int b = a + IFNMDK[2];
int c = IFNMDK[0];
if (b > IFNMDK[1])
return c;
return IFNMDK[3];
}
|
To sprawia, że analiza jest trudniejsza, ponieważ wymaga wyszukiwania po indeksach w tabeli każdej wartości numerycznej. Jako dodatkowa obfuskacja, wygenerowane tablicy są losowo zadeklarowane jako tablice o typie double np. double[] IFNMDK = { 0.49128, 3.33891, 2.00013, 4.32255, 1.99981 };
|
public static double method(double param) {
double a = 1.1;
double b = a + 2.2;
double c = 0.0;
if (b > 3.3) return c;
return 4.4;
}
|
public static double method(double param) {
double[] xnn_dji_34 = { 0.0, 3.3, 2.2, 4.4, 1.1 };
double a = xnn_dji_34[4];
double b = a + xnn_dji_34[2];
double c = xnn_dji_34[0];
if (b > xnn_dji_34[1])
return c;
return xnn_dji_34[3];
}
|
To sprawia, że analiza jest trudniejsza, ponieważ wymaga wyszukiwania po indeksach w tabeli każdej wartości numerycznej.
|
double price = 19.95;
double tax = price * 0.23;
|
double price = Math.min(19.95000, 824.22341);
double tax = price * (20.53912 - Math.sin(0.58974));
|
Ta opcja zamienia literały zmiennoprzecinkowe na równoważne wyrażenia oparte o wywołania Math.*, dzięki czemu stałe nie są widoczne jako proste wartości numeryczne.
|
String name = "Admin";
System.out.println(name);
|
String name = new String(new char[] {
'A', 'd', 'm', 'i', 'n'
});
System.out.println(name);
|
Prosty magazyn znaków zamienia literały tekstowe na obiekty String tworzone w czasie działania z tablic znaków.
|
int retries = 7;
int zero = 0;
|
int retries = (int)(Math.sqrt(49.0));
int zero = (int)(Math.sin(0.0));
|
Literały całkowite są zapisywane jako rzutowania z równoważnych obliczeń zmiennoprzecinkowych, takich jak pierwiastki lub funkcje trygonometryczne.
|
int sum(int a, int b) {
return a + b;
}
|
static long QxRf7mz(long acc, int s) {
long u = acc + (long) ((s & 0x7fff) + 1);
return u ^ (long) Long.numberOfLeadingZeros((s | 1));
}
static long pBk2NwV(long acc, int s) {
long h = Long.rotateLeft(acc ^ (long) Integer.reverse(s), (s & 63));
return Long.reverseBytes(h) ^ (long) (s << 1);
}
int sum(int a, int b) {
long v = QxRf7mz(0L, -402184);
v = pBk2NwV(v, 881022);
v = QxRf7mz(v, -15023);
if (Long.compare(v, -8372144055286123915L) == 0) {
int hxP9 = 0; }
return a + b;
}
|
Obfuscator dodaje statyczne metody mieszające, wywołuje ich łańcuchy wewnątrz metod i emituje warunki, które nie powinny się wykonać, zwiększając ilość kodu analizowanego przez dekompilator.
|
boolean enabled = true;
boolean locked = false;
|
boolean enabled = (Integer.signum(8471) > 0);
boolean locked = (Character.isDigit('x'));
|
Proste literały true i false są zastępowane równoważnymi porównaniami lub wywołaniami metod, które zachowują ten sam wynik logiczny.
|
value += 10;
return value;
|
try {
value += 10;
} finally {
Integer.toHexString(1392).length();
}
return value;
|
Wybrane bezpieczne instrukcje są opakowywane w bloki try/finally z nieszkodliwym kodem no-op w sekcji finally, co dodaje szum do przepływu sterowania bez zmiany działania programu.
|