Code-Verschleierung in Java

Mohammad Irfan 12 Oktober 2023
  1. Was ist Verschleierung?
  2. Code-Verschleierungstechniken
  3. Code-Verschleierungstools für Java
  4. Verschleierung in Java
  5. Zusammenfassung
Code-Verschleierung in Java

Dieses Tutorial führt in die Codeverschleierung in Java ein und listet auch einige Beispielcodes auf, um das Thema zu verstehen.

Verschleierung ist eine Programmiertechnik, die verwendet wird, um unseren Code schwer verständlich zu machen. Dies geschieht, um unseren Quellcode vor böswilligen Benutzern zu schützen. In diesem Tutorial erfahren Sie mehr über die Verschleierung.

Was ist Verschleierung?

  • Verschleierung ist der Prozess, bei dem ein Stück Code weniger lesbar, schwer verständlich und zeitaufwändig gemacht wird.
  • Verschleierung hat keinen Einfluss auf die Ausführung des Codes und der Code wird weiterhin das tun, wofür er gedacht war.
  • Code-Verschleierung wird verwendet, um unseren Code vor Hackern und Angreifern zu schützen. Diese böswilligen Benutzer versuchen möglicherweise, unseren Code zurückzuentwickeln und einige Mängel unseres Codes auszunutzen. Das Verhindern von Reverse-Engineering unseres Codes ist einer der Hauptanwendungsfälle von Verschleierung.
  • Hacker und Angreifer verwenden Verschleierung auch, um zu verhindern, dass Antiviren-Tools ihren feindlichen Code erkennen.

Code-Verschleierungstechniken

Es gibt viele Tools zur Code-Verschleierung, die eine Vielzahl von Techniken verwenden, um Angriffe zu verhindern. Kurz gesagt, Verschleierung verwendet redundante Logik und fügt unerwünschten Code hinzu, um den Leser oder ein Reverse-Engineering-Tool (wie einen Decompiler) in die Irre zu führen.

Lassen Sie uns einige der gängigsten Techniken zur Codeverschleierung besprechen.

  • Umbenennen von Variablen und Methodennamen: Das Umbenennen von Variablen und Methoden in einige schwer lesbare Namen oder die Verwendung nicht druckbarer oder unsichtbarer Zeichen ist eine häufig verwendete Verschleierungstechnik.
  • Ändern des Kontrollflusses: Verschleierungstools ändern oft den Kontrollfluss des Codes. Dadurch führt der Code die gleiche Aufgabe aus, ist jedoch schwer zu befolgen.
  • Verwendung von Dummy-Code: Einige Tools enthalten oft gefälschten Code, der nichts mit der ursprünglichen Logik zu tun hat. Dies erschwert das Reverse-Engineering des Codes.
  • Regelmäßiges Ändern des verschleierten Codes: Wenn wir den verschleierten Code regelmäßig aktualisieren, geht der gesamte Fortschritt des Hackers beim vorherigen Code verloren. Der Angreifer muss mit dem neuen Code von vorne beginnen.
  • Verschlüsselung: Die Verschlüsselung von Daten (wie Strings) verhindert, dass der Hacker die wahre Bedeutung des Codes versteht. Die Entschlüsselung kann durchgeführt werden, wenn der Code ausgeführt werden muss.

Code-Verschleierungstools für Java

Java ist wie jede andere Programmiersprache anfällig für Reverse-Engineering-Angriffe. Für Java stehen Decompiler zur Verfügung, die den kompilierten Java-Bytecode leicht zurückentwickeln können. Im Folgenden sind einige der beliebtesten Java-Obfuscator-Tools aufgeführt.

  • ProGuard
  • JODE
  • JavaGuard
  • RetroGuard
  • jarg
  • yGuard

Verschleierung in Java

Lassen Sie uns den unten gezeigten einfachen Code mit einem Verschleierungstool verschleiern.

public class StringAddition {
  public static void main(String args[]) {
    String s1 = "a";
    String s2 = "b";
    String s3 = s1 + s2;
  }
}

Der Code wird in den folgenden Code verschleiert. Unerwünschte Dummy-Variablen und -Logik werden in den verschleierten Code eingefügt. Die ursprüngliche Codelogik ist schwer zu verstehen.

import b.n;
public class StringAddition {
  private static final String[] d;
  public static void main(final String[] array) {
  Label_0054: {
    break Label_0054;
  Label_0003:
    while (true) {
      final String str = StringAddition.d[Integer.parseInt("1", 22) << 10017];
      try {
        new StringBuilder()
            .append(str)
            .append(StringAddition.d[24 << Integer.parseInt("9k1", 30)])
            .toString();
        return;
        final String x = StringAddition.d[8388608 >>> 4183];
        System.out.println(x);
      }
      // iftrue(Label_0003:, x.hashCode() == 1033634479)
      // monitorenter(array)
      // monitorenter(array)
      catch (EnumConstantNotPresentException i) {
        throw n.i = i;
      }
    }
  }
  }
  static {
    final char[] charArray =
        "\u0e47\u0e59\u0093\u0cc1¥£®£®\u00d1®®®®½£®A\u00da\u00dc®£®®\u00d1®®®\u00c2\u00dc®A\u00da£\u00d1£®®®\u00d1®®\u00c2£\u00d1A\u00da£®\u00dc®®®®\u00d1®\u00c2£®>\u00da£®£\u00d1®®®®\u00d1\u00c2£®A¥£®£®®®®®®½\u00f6\u00d1b\u00f9\u009e\u00d1\u0080\u008d\u008d\u0083\u00d1\u008d\u008d\u00e1\u009d\u00d1b\u00f9\u0080\u009f\u00dc\u008d\u008d\u008d\u0092\u00d1\u008d\u00e1\u0080\u0099>\u00f9\u0080\u008d\u0090\u00d1\u008d\u008d\u008d\u009e\u00d1\u00e1\u0080\u008d}¥\u0080\u008d\u0080\u009a\u00d1\u008d\u008d\u008d\u00df½\u0080\u008db\u00eb\u00dc\u008d\u0080\u008d\u0094\u00d1\u008d\u008d\u008d\u00e9\u00dc\u008db\u00f9\u00dc\u00d1\u00dc\u00d1\u00d1\u00d1\u00d1\u008d\u008d\u0097\u00dc\u008db\u00da£\u008d\u0080\u008d®®\u008d\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u008d®®\u008d\u008d\u00e1£®b\u00f9\u0080®£\u008d\u008d\u008d®®\u008d\u00e1\u0080®A\u00f9\u0080\u008d£®\u008d\u008d\u008d®®\u00e1\u0080\u008dA\u00da\u0080\u008d\u0080®®\u008d\u008d\u008d®\u00c2\u0080\u008db\u00da£®£®®®\u008d\u008d\u00fb½\u0080\u00deA\u00da \u008d\u00d3®®\u00ad\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00de®®\u00ad\u008d\u00de\u00c2£\u00adbª£® \u008d\u00de®®\u00ad\u008d²£®B\u00f9\u00d3®£\u00ad\u008d\u00de®®\u00ad\u00e1\u00d3®A\u00d9\u0080\u00de£®\u00ad\u008d\u00de®®\u00c1\u0080\u00deA\u00da£®£®®\u00ad\u008d\u00fb\u00d1½£®A\u00da\u00dc®£®®\u00d1®®®\u00c2\u00dc®A\u00da£\u00d1£®®®\u00d1®®\u00c2£\u00d1A\u00da£®\u00dc®®®®\u00d1®\u00c2£®>\u00da£®£\u00d1®®®®\u00d1\u00c2£®A¥£®£®\u00d1®®®®½£®A\u00da\u00dc®£®®\u00d1\u00fb\u00d1\u008d\u00e1\u0093\u00d1b\u00f9\u0080\u0093\u00dc\u008d\u008d\u008d\u0097\u00d1\u008d\u00e1\u0080\u0084>\u00f9\u0080\u008d\u008f\u00d1\u008d\u008d\u008d\u0092\u00d1\u00e1\u0080\u008d\u007f¥\u0080\u008d\u0080\u0085\u00d1\u008d\u008d\u008d\u009e½\u0080\u008db\u00f7\u00dc\u008d\u0080\u008d\u00dc\u00d1\u008d\u008d\u008d\u00e9\u00dc\u008db\u00f9\u008e\u00d1\u0080\u008d\u008d\u0098\u00d1\u008d\u008d\u00e1\u009d\u00d1b\u00f9\u0080\u009d\u00dc\u008d\u008d\u00fb\u00d1\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u008d®®\u008d\u008d\u00e1£®b\u00f9\u0080®£\u008d\u008d\u008d®®\u008d\u00e1\u0080®A\u00f9\u0080\u008d£®\u008d\u008d\u008d®®\u00e1\u0080\u008dA\u00da\u0080\u008d\u0080®®\u008d\u008d\u008d®\u00c2\u0080\u008db\u00da£\u008d\u0080\u008d®®\u008d\u008d\u008d\u00c2£\u008db\u00f9£®\u0080\u008d\u00fb\u00d1\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00de®®\u00ad\u008d\u00de\u00c2£\u00adbª£® \u008d\u00de®®\u00ad\u008d²£®B\u00f9\u00d3®£\u00ad\u008d\u00de®®\u00ad\u00e1\u00d3®A\u00d9\u0080\u00de£®\u00ad\u008d\u00de®®\u00c1\u0080\u00deA\u00da \u008d\u00d3®®\u00ad\u008d\u00de®\u00c2 \u008d1\u00da£\u00ad\u0080\u00fb\u00d1\u00fb\u0e59\u0090"
            .toCharArray();
    int n = 64 << 5658;
    final StackTraceElement stackTraceElement;
    final int n2 = (stackTraceElement = new Throwable().getStackTrace()[107 >>> 11463])
                       .getMethodName()
                       .hashCode()
        & Integer.parseInt("171h3c0", 22) - 149806781;
    final char[] charArray2 = stackTraceElement.getClassName().toCharArray();
    final char[] array = charArray;
    final int n3 = 101 >>> 10951;
    ++n;
    d = new String[array[n3] ^ Integer.parseInt("1g1nna6", 28) - 758393825 ^ n2];
    int n4 = 26 >>> Integer.parseInt("gk9", 31);
  Label_0101:
    while (true) {
      int n5;
      final char[] value =
          new char[n5 = (charArray[n++] ^ Integer.parseInt("ifjj061", 22) - 2122795820 ^ n2)];
      int n6 = 72 << 11485;
    Label_0334_Outer:
      while (true) {
      Label_0272: {
        if (n5 <= 0) {
          break Label_0272;
        }
        int n7 = charArray[n];
      Label_0334:
        while (true) {
        Label_0388: {
          switch (charArray2[n % charArray2.length] ^ (0xC999A060 ^ 0xC999A0AE)) {
            case 160: {
              break Label_0334;
            }
            case 162: {
              break Label_0334;
            }
            case 131: {
              break Label_0334;
            }
            case 163: {
              break Label_0334;
            }
            case 167: {
              break Label_0334;
            }
            case 136: {
              break Label_0388;
            }
            case 170: {
              break Label_0388;
            }
            case 186: {
              break Label_0388;
            }
            case 139: {
              break Label_0388;
            }
            case 171: {
              break Label_0388;
            }
          }
          while (true) {
            value[n6] = (char) n7;
            try {
              ++n6;
              ++n;
              --n5;
              // monitorexit(charArray)
              n7 ^= -400944133 + 400944374;
              continue Label_0334_Outer;
              n7 ^= Integer.parseInt("83bdf8k", 22) - 925222572;
              continue Label_0334_Outer;
              continue Label_0334;
              StringAddition.d[n4++] = new String(value).intern();
              // iftrue(Label_0101:, n < charArray.length)
              return;
              n7 ^= Integer.parseInt("6j", 23) << 3840;
              continue Label_0334_Outer;
              n7 ^= 61440 >>> 11787;
              continue Label_0334_Outer;
              n7 ^= 364965749 - 364965616;
            } catch (Throwable t) {
              break;
            }
          }
        } break;
        }
      }
      }
    }
  }
}

Beachten Sie, dass der obige Code möglicherweise nicht direkt in einer IDE ausgeführt wird, da ein Obfuscator auch zusätzliche Dateien und Abhängigkeiten erzeugt, die vor der Ausführung des Programms aufgelöst werden müssen.

Zusammenfassung

Code-Verschleierung wird durchgeführt, um Angriffe aufgrund von Reverse Engineering zu verhindern. Angreifer und Hacker verwenden Verschleierung auch, um Antivirensoftware und andere Schutztools zu täuschen. Beachten Sie, dass das Reverse-Engineering eines Codes durch Code-Obfuscator-Tools nicht unmöglich gemacht wird. Sie machen es sehr schwierig und zeitaufwendig.