LINUX.ORG.RU

Декомпиляция Java

 


0

3

Такое вообще возможно?
Я с жавой почти не знаком, но есть академический интерес заглянуть внутрь одной проги.
Пробовал JD и что то еще - на выходе куча файлов а.сlass, a$a.class, a$a$a.class и т.д.
Часть пустые, в других белиберда.
Это я что-то не так делаю?

Компилировать обратно не надо.

★★★

Если скомпилированные файлы не обфусцированы — не просто возможно, но и очень легко, исходники восстанавливаются практически вплоть до имён переменных (а если есть отладочная информация, то и с ними).

Это я что-то не так делаю?

Скорее всего.

Legioner ★★★★★ ()
Последнее исправление: Legioner (всего исправлений: 1)

А ты думал, что тебе из jar исходники нормально восстановятся? Лучше всего декомпилировать при помощи плагина в intellij idea. Но всё равно нормального исходника ты не получишь, + очень мало программ можно декомпилировать не нарушая лицензию.

peregrine ★★★★★ ()
Ответ на: комментарий от yirk

Декомпилировать и посмотреть на результат

Midael ★★★★★ ()

а.сlass, a$a.class, a$a$a.class

Это ProGuard скорей всего, оно читабельно. Но если проект большой и классов много, то ты просто с ума сойдешь во всех этих a-классах.
Вот что нашлось, не факт что может и оно вообще работает.

anonymous_sama ★★★★★ ()
Последнее исправление: anonymous_sama (всего исправлений: 1)

Возможно. Из того что более-менее реально работает - cfr/jd (из гита).

а.сlass — почищены имена классов. Если внутри белиберда - скорее всего декомпилятор не умееет новые конструкции, или обфускация.

vasily_pupkin ★★★★★ ()

очень хорошо восстанавливаются class файлы скомпилированные 1.4.2 и меньше. 1.5, 1.6 и 1.7 хуже. сложные 1.8 с лямдами очень плохо. лучше jd к сожалению ничего нет.

vtVitus ★★★★★ ()

а.сlass, a$a.class, a$a$a.class

Поздравляю, то что ты декомпилишь пропустили через обфускатор, логику работы понять до сих пор возможно, но разбирать все придется руками. Если с жабой (и косяками её декомплеров) не знаком, то вряд ли что-то поймешь.

ya-betmen ★★★★★ ()
Ответ на: комментарий от a1batross

Все намного проще. Если об этом никто не узнает, то можно декомпилировать что угодно, как угодно и для чего угодно.

anonymous ()

Посоветую Процион, самый продвинутый из доступных, на мой взгляд.

ruzisufaka ()
Ответ на: комментарий от peregrine

Лучше всего декомпилировать при помощи плагина в intellij idea.

Кто это сказал? Fernflower не особо фичастый декомпилятор, есть ещё CFR и JADX.

EXL ★★★★★ ()
Ответ на: комментарий от migesok

JD херня, не?

Нет.

Берём идейку, fernflower и рандомное, простое Java-приложение.

java -jar fernflower.jar -dgs=true ../MIDlets-JARs/stack_attack_2_pro_color_915.jar ../MIDlets-JARs/StackAttack-Decompiled/

Открываем класс a.java:

...
   public static int a(String param0, d param1) {
      // $FF: Couldn't be decompiled
   }

   public static String a(int param0, String param1) {
      // $FF: Couldn't be decompiled
   }
...

Ладно. Берём в правую руку старый-добрый JD, декомпилируем тот же самый мидлет, открываем тот же самый класс:

...
  public static int a(String paramString, d paramd)
  {
    System.gc();
    int m = 0;
    if (paramd.d(paramString) == true) {
      return 0;
    }
    HttpConnection localHttpConnection = null;
    InputStream localInputStream = null;
    StringBuffer localStringBuffer = new StringBuffer("");
    String str2 = c(paramString);
    try
    {
      str3 = System.getProperty("com.siemens.IMEI").trim();
      str4 = "http://139.23.38.140/hs/user.asp?imei=" + str3 + "&nick=" + str2 + "&appid=001AEE0A&mnc=" + System.getProperty("com.siemens.MNC") + "&mcc=" + System.getProperty("com.siemens.MCC");
      int i1 = 256;
      localInputStream = (localHttpConnection = (HttpConnection)Connector.open(str4)).openInputStream();
      int i2;
      while (((i2 = localInputStream.read()) != -1) && (i1 > 0))
      {
        localStringBuffer.append((char)i2);
        i1--;
      }
      if (i1 == 0)
      {
        int i3 = -3;
        return i3;
      }
    }
    catch (Exception localException5)
    {
      m = -3;
    }
    finally
    {
      try
      {
        if (localInputStream != null) {
          localInputStream.close();
        }
      }
      catch (Exception localException8) {}
      try
      {
        if (localHttpConnection != null) {
          localHttpConnection.close();
        }
      }
      catch (Exception localException9) {}
      System.gc();
    }
    if (m == -3) {
      return -3;
    }
    String str1 = localStringBuffer.toString();
    String str3 = "registration successful";
    String str4 = "alternative nick:";
    if (str1.startsWith(str4))
    {
      n = b(str1.substring(str4.length()));
      return -2;
    }
    if (str1.compareTo(str3) == 0)
    {
      paramd.b(paramString);
      paramd.a();
      return 0;
    }
    return -1;
  }

   public static String a(int paramInt, String paramString)
  {
    System.gc();
    paramString = paramString.trim();
    HttpConnection localHttpConnection = null;
    InputStream localInputStream = null;
    StringBuffer localStringBuffer = new StringBuffer("");
    String str2 = c(paramString);
    for (String str3 = Integer.toHexString(paramInt ^ 0xFEC17A11); str3.length() < 8; str3 = "0" + str3) {}
    int m = 0;
    try
    {
      String str4 = System.getProperty("com.siemens.IMEI").trim();
      localInputStream = (localHttpConnection = (HttpConnection)Connector.open(str5 = "http://139.23.38.140/hs/hs.asp?appid=001AEE0A&imei=" + str4 + "&nick=" + str2 + "&hs=" + str3)).openInputStream();
      int i1;
      while ((i1 = localInputStream.read()) != -1)
      {
        localStringBuffer.append((char)i1);
        m++;
      }
    }
    catch (Exception localException3)
    {
      String str5 = "Broken";
      return str5;
    }
    finally
    {
      try
      {
        if (localInputStream != null) {
          localInputStream.close();
        }
      }
      catch (Exception localException6) {}
      try
      {
        if (localHttpConnection != null) {
          localHttpConnection.close();
        }
      }
      catch (Exception localException7) {}
    }
    if (m > 260) {
      return "Broken";
    }
    String str1 = localStringBuffer.toString();
    System.gc();
    return str1;
  }
...

Та-дам! Всё декомпилировалось как нужно.

Закрываем идейку и их говноподелку fernflower и выбрасываем её на помойку.

EXL ★★★★★ ()
Ответ на: комментарий от EXL

Воу, братан, кинь джарку или подскажи, где достать? Меня тема дико интересует, хочу понять, что там такого хитрого, что fernflower не понимает.

Я как-то пытался обмануть fernflower разными хитро подстроенными класс-файлами, но пока он меня громил в сухую. Ржака была, когда я составил метод с ациклическим control-flow графом не сводимым напрямую к if-ам, а он выплюнул пачку labeled-break-ов из блоков. Я даже не знал, что в Java так можно.

migesok ()
Ответ на: комментарий от migesok

Не знаю, чего там fernflower не понимает, но говорит он при декомпиляции следующее:

INFO:  Decompiling class a
WARN:           Heavily obfuscated exception ranges found!
ERROR:          Method a (Ljava/lang/String;Ld;)I couldn't be decompiled.
java.lang.RuntimeException: parsing failure!
        at org.jetbrains.java.decompiler.modules.decompiler.DomHelper.parseGraph(DomHelper.java:217)
        at org.jetbrains.java.decompiler.main.rels.MethodProcessorRunnable.codeToJava(MethodProcessorRunnable.java:122)
        at org.jetbrains.java.decompiler.main.rels.ClassWrapper.init(ClassWrapper.java:86)
        at org.jetbrains.java.decompiler.main.ClassesProcessor.initWrappers(ClassesProcessor.java:303)
        at org.jetbrains.java.decompiler.main.ClassesProcessor.writeClass(ClassesProcessor.java:250)
        at org.jetbrains.java.decompiler.main.Fernflower.getClassContent(Fernflower.java:87)
        at org.jetbrains.java.decompiler.struct.ContextUnit.save(ContextUnit.java:147)
        at org.jetbrains.java.decompiler.struct.StructContext.saveContext(StructContext.java:72)
        at org.jetbrains.java.decompiler.main.Fernflower.decompileContext(Fernflower.java:54)
        at org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.decompileContext(ConsoleDecompiler.java:135)
        at org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(ConsoleDecompiler.java:96)
WARN:           Heavily obfuscated exception ranges found!
ERROR:          Statement cannot be decomposed although reducible!
ERROR:          Method a (ILjava/lang/String;)Ljava/lang/String; couldn't be decompiled.
java.lang.RuntimeException: parsing failure!
        at org.jetbrains.java.decompiler.modules.decompiler.DomHelper.parseGraph(DomHelper.java:217)
        at org.jetbrains.java.decompiler.main.rels.MethodProcessorRunnable.codeToJava(MethodProcessorRunnable.java:122)
        at org.jetbrains.java.decompiler.main.rels.ClassWrapper.init(ClassWrapper.java:86)
        at org.jetbrains.java.decompiler.main.ClassesProcessor.initWrappers(ClassesProcessor.java:303)
        at org.jetbrains.java.decompiler.main.ClassesProcessor.writeClass(ClassesProcessor.java:250)
        at org.jetbrains.java.decompiler.main.Fernflower.getClassContent(Fernflower.java:87)
        at org.jetbrains.java.decompiler.struct.ContextUnit.save(ContextUnit.java:147)
        at org.jetbrains.java.decompiler.struct.StructContext.saveContext(StructContext.java:72)
        at org.jetbrains.java.decompiler.main.Fernflower.decompileContext(Fernflower.java:54)
        at org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.decompileContext(ConsoleDecompiler.java:135)
        at org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(ConsoleDecompiler.java:96)
INFO:  ... done

Вот только откуда там Heavily obfuscated exception ranges found — я не знаю.

JAR'ка из 2002 или 2003 года, лови: http://rgho.st/6YhkyRRkY

EXL ★★★★★ ()
Ответ на: комментарий от EXL

JEB пока что самое лучше что есть на рынке,и стоит конечно за штуку баксов

anonymous ()
Ответ на: комментарий от migesok

а он выплюнул пачку labeled-break-ов из блоков. Я даже не знал, что в Java так можно.

Скорее всего, твой метод таким образом и скомпилировался в байткод, поэтому заслуги fernflower здесь нету.

unlog1c ★★★ ()
Ответ на: комментарий от unlog1c

Не, там чистое совпадение было. Я взял CFG из статьи про алгоритм превращения goto-шек в высокоуровневые структуры и накидал сам руками байткод по нему. Теперь начинаю думать, нельзя ли любую лапшу из переходов внутри метода выразить в виде labeled-break-ов.

migesok ()
Ответ на: комментарий от migesok

Алгоритм из статьи в таком случае может реструктурировать условия переходов, чтобы получить if-ы, я думал fernflower делает так же. А хер.

migesok ()
Ответ на: комментарий от EXL

Ох, мать, заглянул в код fernflower, а там, как-будто пионэры писали:

https://github.com/fesh0r/fernflower/blob/master/src/org/jetbrains/java/decom...

          //					try {
          //						DotExporter.toDotFile(general, new File("c:\\Temp\\stat1.dot"));
          //					} catch(Exception ex) {ex.printStackTrace();}

Ещё сразу в глаза бросается куча FixMe для каких-то нереализованных корнер-кейсов. Выглядит как-то несерьёзно.

migesok ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.