Защищенная ява программа

Помогите разобраться с защитой и способом ее обхода.
 
+
-
edit
 

Milldi

втянувшийся
Имеем следующий код.
Это скрипт квеста Ла2 на ява.
Исходный код был обработан обсфукатором который заменяет имена классов и методов на абстрактные А,B,C но не все.

Строковые перменные шифруются.
code text
  1. package quests._001_LettersOfLove;
  2.  
  3. import java.io.PrintStream;
  4. import ru.l2f.extensions.scripts.ScriptFile;
  5. import ru.l2f.gameserver.model.L2Player;
  6. import ru.l2f.gameserver.model.instances.L2NpcInstance;
  7. import ru.l2f.gameserver.model.quest.Quest;
  8. import ru.l2f.gameserver.model.quest.QuestState;
  9.  
  10. public class _001_LettersOfLove extends Quest
  11.     implements ScriptFile
  12. {
  13.  
  14.     public void onLoad()
  15.     {
  16.         System.out.println(z[4]);
  17.     }
  18.  
  19.     public void onReload()
  20.     {
  21.     }
  22.  
  23.     public void onShutdown()
  24.     {
  25.     }
  26.  
  27.     public _001_LettersOfLove()
  28.     {
  29.         super(1, z[1], z[0], false);
  30.         addStartNpc(30048);
  31.         addTalkId(30006);
  32.         addTalkId(30033);
  33.         addQuestItem(687);
  34.         addQuestItem(688);
  35.         addQuestItem(1079);
  36.         addQuestItem(1080);
  37.     }
  38.  
  39.     public String onEvent(String s, QuestState queststate)
  40.     {
  41.         if(s.equalsIgnoreCase(z[3]))
  42.         {
  43.             queststate.set(z[2], "1");
  44.             queststate.setState(_fld0402);
  45.             queststate.giveItems(687, 1L, false);
  46.             queststate.playSound(SOUND_ACCEPT);
  47.         }
  48.         return s;
  49.     }
  50.  
  51.     public String onTalk(L2NpcInstance l2npcinstance, QuestState queststate)
  52.     {
  53.         String s = z[16];
  54.         int i = l2npcinstance.getNpcId();
  55.         int j = queststate.getInt(z[2]);
  56.         switch(i)
  57.         {
  58.         default:
  59.             break;
  60.  
  61.         case 30048:
  62.             if(j == 0)
  63.             {
  64.                 if(queststate.getPlayer().getLevel() >= 2)
  65.                 {
  66.                     s = z[5];
  67.                 } else
  68.                 {
  69.                     s = z[15];
  70.                     queststate.exitCurrentQuest(true);
  71.                 }
  72.                 break;
  73.             }
  74.             if(j == 1)
  75.             {
  76.                 s = z[8];
  77.                 break;
  78.             }
  79.             if(j == 2 && queststate.getQuestItemsCount(688) == 1L)
  80.             {
  81.                 s = z[14];
  82.                 queststate.takeItems(688, -1L);
  83.                 queststate.giveItems(1079, 1L, false);
  84.                 queststate.set(z[2], "3");
  85.                 queststate.playSound(SOUND_MIDDLE);
  86.                 break;
  87.             }
  88.             if(j == 3)
  89.             {
  90.                 s = z[10];
  91.                 break;
  92.             }
  93.             if(j == 4 && queststate.getQuestItemsCount(1080) == 1L)
  94.             {
  95.                 s = z[12];
  96.                 queststate.takeItems(1080, -1L);
  97.                 queststate.giveItems(906, 1L, false);
  98.                 queststate.unset(z[2]);
  99.                 queststate.playSound(SOUND_FINISH);
  100.                 queststate.exitCurrentQuest(false);
  101.             }
  102.             break;
  103.  
  104.         case 30006:
  105.             if(j == 1 && queststate.getQuestItemsCount(688) == 0L && queststate.getQuestItemsCount(687) > 0L)
  106.             {
  107.                 s = z[6];
  108.                 queststate.takeItems(687, -1L);
  109.                 queststate.giveItems(688, 1L, false);
  110.                 queststate.set(z[2], "2");
  111.                 queststate.playSound(SOUND_MIDDLE);
  112.                 break;
  113.             }
  114.             if(j == 2 && queststate.getQuestItemsCount(688) > 0L)
  115.             {
  116.                 s = z[9];
  117.                 break;
  118.             }
  119.             if(j > 2 && (queststate.getQuestItemsCount(1080) > 0L || queststate.getQuestItemsCount(1079) > 0L))
  120.                 s = z[13];
  121.             break;
  122.  
  123.         case 30033:
  124.             if(j == 3 && queststate.getQuestItemsCount(1079) == 1L)
  125.             {
  126.                 s = z[7];
  127.                 queststate.takeItems(1079, -1L);
  128.                 queststate.giveItems(1080, 1L, false);
  129.                 queststate.set(z[2], "4");
  130.                 queststate.playSound(SOUND_MIDDLE);
  131.                 break;
  132.             }
  133.             if(j == 4)
  134.                 s = z[11];
  135.             break;
  136.         }
  137.         return s;
  138.     }
  139.  
  140.     public final int DARIN = 30048;
  141.     public final int ROXXY = 30006;
  142.     public final int BAULRO = 30033;
  143.     public final short DARINGS_LETTER = 687;
  144.     public final short RAPUNZELS_KERCHIEF = 688;
  145.     public final short DARINGS_RECEIPT = 1079;
  146.     public final short BAULS_POTION = 1080;
  147.     public final short NECKLACE = 906;
  148.     private static final String z[];
  149.  
  150.     static
  151.     {
  152.         String as[];
  153.         as = new String[17];
  154.         as[0] = "WW(\034\036iA|\007\035;~3\036\036";
  155.         as[1] = "D\002lY$WW(\034\036iA\023\0167tD9";
  156.         as[2] = "x]2\f";
  157.         as[3] = "(\002l\\C6\002jF\023o_";
  158.         as[4] = "W]=\f\036\177\022\r\035\036hFfHK+\003fH7~F(\r\th\0223\016[W]*\r";
  159.         as[5] = "(\002l\\C6\002nF\023o_";
  160.         as[6] = "(\002lXM6\002mF\023o_";
  161.         as[7] = "(\002l[H6\002mF\023o_";
  162.         as[8] = "(\002l\\C6\002kF\023o_";
  163.         as[9] = "(\002lXM6\002nF\023o_";
  164.         as[10] = "(\002l\\C6\002eF\023o_";
  165.         as[11] = "(\002l[H6\002nF\023o_";
  166.         as[12] = "(\002l\\C6\003lF\023o_";
  167.         as[13] = "(\002lXM6\002oF\023o_";
  168.         as[14] = "(\002l\\C6\002dF\023o_";
  169.         as[15] = "(\002l\\C6\002lF\023o_";
  170.         as[16] = "u]-\035\036hF";
  171.         z = as;
  172.         break MISSING_BLOCK_LABEL_257;
  173.         local;
  174.         toCharArray();
  175.         JVM INSTR dup ;
  176.         JVM INSTR arraylength .length;
  177.         JVM INSTR swap ;
  178.         int i = 0;
  179.           goto _L1
  180. _L3:
  181.         JVM INSTR dup ;
  182.         i;
  183.         JVM INSTR dup2 ;
  184.         JVM INSTR caload ;
  185.         byte byte0;
  186.         switch(i % 5)
  187.         {
  188.         case 0: // '\0'
  189.             byte0 = 0x1b;
  190.             break;
  191.  
  192.         case 1: // '\001'
  193.             byte0 = 50;
  194.             break;
  195.  
  196.         case 2: // '\002'
  197.             byte0 = 92;
  198.             break;
  199.  
  200.         case 3: // '\003'
  201.             byte0 = 104;
  202.             break;
  203.  
  204.         default:
  205.             byte0 = 123;
  206.             break;
  207.         }
  208.         byte0;
  209.         JVM INSTR ixor ;
  210.         (char);
  211.         JVM INSTR castore ;
  212.         i++;
  213. _L1:
  214.         JVM INSTR swap ;
  215.         JVM INSTR dup_x1 ;
  216.         i;
  217.         JVM INSTR icmpgt 170;
  218.            goto _L2 _L3
  219. _L2:
  220.         JVM INSTR new #123 <Class String>;
  221.         JVM INSTR dup_x1 ;
  222.         JVM INSTR swap ;
  223.         String();
  224.         intern();
  225.         JVM INSTR swap ;
  226.         JVM INSTR pop ;
  227.         JVM INSTR ret 0;
  228.     }
  229. }


как я понял при шифровании строковых переменных они заменяются на элементы массива строк (z) а сами строковые переменные шифруются и заносятся в мвссив (as) При загрузке класса элемты массива (as) расшифровываются и присваиваются создаваемому массиву строк (Z)

В общем надо как то их расшифровать. В принципе анализируя код можно и самому догадаться что именно зашифровано потому что в основном это имена файлов в каталоге одноименном с классом который зашифрован.

данный код получен декомпиляцией jad'ом к сожалению шифрование переменных приводит к большой задержке по переосу квеста на сборку сервера скомпилированную без шифрования.

последнии строки кода я так понимю команды JVM для расшифровки строк при загрузке класса.

так вот суть вопроса можно ли каким либо образом расшифровать зачения элемтов массива (as)?
 

tarasv

опытный

Milldi> так вот суть вопроса можно ли каким либо образом расшифровать зачения элемтов массива (as)?

Можно двумя способами:
Банальным - загрузить класс и получить у него значения уже рассшифрованных строк.
Тривиальным - перевести байткод расшифровщика назад в java и запустить.

Letters of Love
_001_LettersOfLove
cond
30048-06.htm
Loaded Quest: 001: Letters of Love
30048-02.htm
30006-01.htm
30033-01.htm
30048-07.htm
30006-02.htm
30048-09.htm
30033-02.htm
30048-10.htm
30006-03.htm
30048-08.htm
30048-00.htm
noquest
 7.07.0
+
-
edit
 

Milldi

втянувшийся
а можно с примером? что то где то мысль верная крутится но ускользает.
 

tarasv

опытный

Milldi> а можно с примером? что то где то мысль верная крутится но ускользает.

Получается чтото вроде
code text
  1. byte byte0;
  2. for (String a : as) {
  3.     StringBuilder sb = new StringBuilder();
  4.     for (int i = 0; i < a.length(); i++) {
  5.         switch (i % 5) {
  6.         case 0: // '\0'
  7.             byte0 = 0x1b;
  8.             break;
  9.  
  10.         case 1: // '\001'
  11.             byte0 = 50;
  12.             break;
  13.  
  14.         case 2: // '\002'
  15.             byte0 = 92;
  16.             break;
  17.  
  18.         case 3: // '\003'
  19.             byte0 = 104;
  20.             break;
  21.  
  22.         default:
  23.             byte0 = 123;
  24.             break;
  25.         }
  26.         sb.append((char) (byte0 ^ a.charAt(i)));
  27.     }
  28.     System.out.println(sb.toString());
  29. }


Только учтите что ключ шифрования случайный и генерируется обфурскатором для каждого обрабатываемого класса отдельно.
 7.07.0
+
-
edit
 

Milldi

втянувшийся
Ок спасибо все догнал. Про то что ключ везде разный я уже понял.
:) блин я так в 3 раза быстрее квесты перенесу спасибо большое.
 

в начало страницы | новое
 
Поиск
Поддержка
Поддержи форум!
ЯндексЯндекс. ДеньгиХочу такую же кнопку
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru