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 54890 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.


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

Tweetnij o tym

Wyślij Tweeta 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.