JObfuscator — Obfuskacja Kodów Źródłowych Javy

JObfuscator umożliwia obfuskację kodów źródłowych i algorytmów w Javie w celu ich ochrony przed inżynierią wsteczną, dekompilacją oraz kradzieżą technologii. JObfuscator był już użyty 60694 razy!

Kod źródłowy w Javie

Kod Javy po obfuskacji

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.

void run(int step) {
  counter += step + 1;
}
private static final class JxHub_m7 {
  private static String catMethods(Class<?> z) {
    java.lang.reflect.Method[] ms = z.getDeclaredMethods();
    java.util.Arrays.sort(ms, java.util.Comparator.comparing(
      java.lang.reflect.Method::getName));
    StringBuilder sb = new StringBuilder();
    for (java.lang.reflect.Method m : ms) {
      sb.append(m.getName()).append('|')
        .append(m.getParameterTypes().length).append('\n');
    }
    return sb.toString();
  }
}
void run(int step) {
  if (!JxHub_m7.verify(getClass())) { step ^= 9; }
  counter += step + 1;
}

Ostatnia faza obfuskacji, dodająca sprawdzanie zobfuskowanego kodu poprzez refleksję (getDeclaredMethods, katalog pól). Jeśli zmienione zostaną np. typy danych (np. przy próbie deobfuskacji), działanie programu zostanie celowo zaburzone. Wyłącz tę opcję, jeśli planujesz dodatkową obfuskację bytecodu (ProGuard, R8, DashO itd.) — zmiana nazw i kolejności w pliku .class unieważnia zapisane sumy kontrolne.


Jak otrzymać darmowy kod aktywacyjny?

Tutaj znajdziesz kilka sposobów, dzięki którym możesz otrzymać kod aktywacyjny z 500 kredytami użycia

Pencil

Napisz artykuł

Napisz artykuł na blogu czy na stronie o JObfuscatorze ze zrzutami ekranu, przykładowymi kodami źródłowymi oraz odnośnikiem do strony produktu.

X

Napisz o tym

Wyślij wpis o JObfuscatorze do swoich fanów wraz z linkiem do strony produktu, użyj hasztagów #jobfuscator #java #obfuscator oraz #obfuscation.

Pencil

Zgłoś błąd

Zgłoś błąd i jeśli będę w stanie go potwierdzić, otrzymasz darmowy kod aktywacyjny w ramach podziękowanie.

Idea

Zasugeruj pomysł na obfuskację

Jeśli masz pomysł jak udoskonalić obecne metody obfuskacji lub wprowadzić nowe techniki, skontaktuj się ze mną przedstawiając wszelkie szczegóły.

Skorzystaj z formularza kontaktowego, aby ze mną porozmawiać.

Masz pytania?

Jeśli masz jakieś pytania dotyczące obfuskatora JObfuscator, masz jakieś uwagi, coś jest niejasne, napisz do mnie, chętnie odpowiem na każde Twoje pytanie.