Как выполняется обфускация в Java?

Сегодня я столкнулся с запутанным классом (много запутанных классов в банке), и я понятия не имею, как делается этот вид запутывания.

Пример:

  protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)
    throws Exception
  {
    int ☃ = ☃.readableBytes();
    if (☃ < this.c)
    {
      ☃.b(0);
      ☃.writeBytes(☃);
    }
    else
    {
      byte[] ☃ = new byte[☃];
      ☃.readBytes(☃);

      ☃.b(☃.length);

      this.b.setInput(☃, 0, ☃);
      this.b.finish();
      while (!this.b.finished())
      {
        int ☃ = this.b.deflate(this.a);
        ☃.writeBytes(this.a, 0, ☃);
      }
      this.b.reset();
    }
  }

}

Как вы видите выше, все переменные параметров представляют собой снежного человека. Как это можно отменить? Кроме того, как это делается в первую очередь; как JVM может «обработать» их и выполнить код без каких-либо проблем?

Чтобы уточнить, я не собираюсь использовать этот код, он предназначен только для образовательных целей. Я прохожу курс информатики в школе, так как мы изучаем Java и говорим об ограничениях, таких как декомпиляция. Мне интересно узнать больше, поэтому я решил изучить более крупные проекты, особенно серверы. Этот фрагмент кода взят из Spigot server для Minecraft (игра), который является ответвлением Bukkit server для Minecraft, исходный код которого должен был быть открытым.


person fill͡pant͡    schedule 22.06.2015    source источник
comment
Это символ Юникода, как и любой другой символ Юникода. Почему вы ожидаете, что это не сработает?   -  person SLaks    schedule 22.06.2015
comment
Ну, я понимаю вашу точку зрения, я знаю, что это так, и это именно ☃, но я не понимаю, как это можно сделать и отменить... :-) Спасибо.   -  person fill͡pant͡    schedule 23.06.2015
comment
Это точно так же, как любое другое имя переменной. Например, вы можете назвать переменную x. Это просто переменная с именем . Там нет сделанного или отмененного, просто вы можете написать имя переменной с любыми символами, которые вы хотите.   -  person Louis Wasserman    schedule 23.06.2015


Ответы (3)


Прежде всего, вы должны отметить, что это параметры, которые имеют этот юникод, а не методы. Почему это важно? Для параметров не обязательно указывать имена, так как они в основном индексируются по числовой ссылке. Однако его можно указать, и я предполагаю, что большинство сред выполнения Java на самом деле не проверяют это имя, поскольку оно не требуется для выполнения. Наоборот, имена классов, имена методов и имена полей необходимы.

Насчет того, что вы упомянули Spigot, Spigot действительно с открытым исходным кодом. Однако вы, скорее всего, декомпилировали класс, который изначально взят с оригинального сервера Mojang Minecraft, который не имеет открытого исходного кода и действительно запутан.

Изменить: если вы хотите исследовать эти классы, я недавно нашел инструмент под названием Bytecode Viewer, который доступен по адресу https://github.com/Konloch/bytecode-viewer Этот инструмент имеет несколько декомпиляторов, а также некоторые параметры для просмотра более похожей на байт-код версии файла класса. Пример функции, которую я нашел, содержит следующие данные байт-кода:

     <localVar:index=1 , name=☃ , desc=D, sig=null, start=L1, end=L2>
     <localVar:index=3 , name=☃ , desc=D, sig=null, start=L1, end=L2>
     <localVar:index=5 , name=☃ , desc=D, sig=null, start=L1, end=L2>

Действительно, как видно, юникодное имя задано то же самое, но это не имеет значения, так как в конце концов для ссылки на эти переменные используются индексы (1,3,5).

person user254948    schedule 22.06.2015
comment
Действительно, это от net.minecraft.server, но в прошлом запутывание было намного дружелюбнее :-( Предоставленный ресурс - это ИМЕННО то, что мне нужно! Большое спасибо!!! И что это за функция? Пока мне немного трудно читать код, потому что он либо выглядит как значение Unicode, либо как показано выше, но он немного поврежден :3 Спасибо :-) - person fill͡pant͡; 23.06.2015
comment
Уф, я не записал, я думаю, что это был конструктор класса, начинающийся с Биома. Обратите внимание, что в программе есть параметры для изменения отображения/декомпилятора в разделе «Вид», а затем в панели 1-3. - person user254948; 23.06.2015
comment
Быстро посмотрел. этим конкретным классом был BiomeBaseSub. Вы можете попробовать Fernflower, чтобы увидеть читаемый код Java и байт-код на второй панели. Также у него есть возможность не брать имена переменных из отладочной информации класса. - person user254948; 23.06.2015
comment
Я понимаю! Спасибо еще раз! Что я пробовал: -Procyon -> Показывал код, но отображал юникод как параметр -CFR -> деобфусцировал юникоды, но приводил все к классу xD -FernFlower -> Работало, но имена переменных стали: β�ƒ2 Каждое до единого. -Karaktau -> IOException :- ( -Bytecode -> Работал, как вы показали выше -Smali/DEX -> Нечитаемый текст -HEX -> Странно, но я кое-что из этого добился :D Ура! - person fill͡pant͡; 23.06.2015
comment
Спасибо! Я попробовал средство просмотра байт-кода, и с помощью папоротника переменные называются , ☃1, ☃2 и т. д., поэтому вы можете прочитать и понять код :) - person Jofkos; 30.06.2015

protected void a(ChannelHandlerContext ☃, ByteBuf ☃, ByteBuf ☃)

Это недействительно. У вас не может быть нескольких параметров с одним и тем же именем. Возможно, вы не читаете текст Unicode в правильном текстовом формате.

person ControlAltDel    schedule 22.06.2015
comment
Вы действительно можете не компилировать его. Однако это разрешено в байт-коде. - person user254948; 23.06.2015

Ваш текстовый редактор показывает значение символа Юникода.

Я только что протестировал eclipse, и имена с символами юникода приемлемы.

    public String publicationXmlUrl(int \u9090currentPage) {

Но запись со значениями не является:

   public String publicationXmlUrl(int ♥currentPage) {
person Marcos Vasconcelos    schedule 22.06.2015