DataLife Engine > Программирование > Взлом Tanks Mobile
Взлом Tanks Mobile24 августа 2007. Разместил: SlaDER |
|
Автор статьи: BlackFan
Редактор: SlaDER Рассмотрим возможность взлома J2me-игр на примере Tanks Mobile Инструменты:
Получаем файлы *.java ( исходный код игры), которые можно открыть любым текстовым редактором. Рассмотрим содержимое этих файлов. В файле k.java находим такой кусок кода: if(m_aI == 1){ q.m_bSprite.setFrame(2); q.m_bSprite.setPosition(getWidth() - 22, getHeight() - 20); q.m_bSprite.paint(g); q._aStringI("Благодарим вас за регистрацию! Приятной игры!" , g, getWidth() - 15, getWidth() / 2, (getHeight() / 2 + q.m_agI) - 5, 1, true, true); return; } if(m_aI == 2){ q.m_bSprite.setFrame(3); q.m_bSprite.setPosition(3, getHeight() - 20); q.m_bSprite.paint(g); q._aStringI("Неверный ключ. Обратитесь за помощью на сайт www.tanchiki.ru" , g, getWidth() - 15, getWidth() / 2, (getHeight() / 2 + q.m_agI) - 5, 1, true, true); return; } То, что разработчики держали строки типа «Благодарим вас за регистрацию! Приятной игры!» в самом коде, очень облегчило нам задачу поиска, но так будет далеко не во всех играх. Чтобы регистрация прошла необходимо, чтобы переменная m_aI = 1. Ищем все, что связано с изменением этой переменной в файле k.java. И находим такой кусок кода: _L6: int i = Integer.parseInt(m_aString); boolean flag = false; if(q.m_afI == 3) { long l; String s; long l1; l1 = (l1 = Integer.parseInt((s = String.valueOf(l = q.m_aeI)).substring(0, 1)) + Integer.parseInt(s.substring(1, 2)) + Integer.parseInt(s.substring(2, 3)) + Integer.parseInt(s.substring(3, 4)) + Integer.parseInt(s.substring(4, 5)) + Integer.parseInt(s.substring(5, 6)) + Integer.parseInt(s.substring(6, 7))) * 321L + 213L & 255L; if((s = String.valueOf(l = (l = (l = (l = (l = (l ^= 0x1c91bfL) ^ l1) ^ l1 << 8) ^ l1 << 16) << 3) * 3L + 2129L).substring(0, 7)).substring(0, 4).compareTo(m_aString.substring(1, 5)) == 0) flag = true; } if(flag) { m_aI = 1; q._aStringIV("temp", 2, i); q.m_eZ = true; } else { m_aI = 2; } this; goto _L8 Переменная m_aI=1, если flag==true. А переменная flag принимает значение true, если выполняется довольно громоздкая и непонятная проверка ( разработчики постарались В строчках: int i = Integer.parseInt(m_aString); и l1 = (l1 = Integer.parseInt((s = String.valueOf(l = q.m_aeI)).substring(0, 1)) + Integer.parseInt(s.substring(1, 2)) + Integer.parseInt(s.substring(2, 3)) + Integer.parseInt(s.substring(3, 4)) + Integer.parseInt(s.substring(4, 5)) + Integer.parseInt(s.substring(5, 6)) + Integer.parseInt(s.substring(6, 7))) * 321L + 213L & 255L; видим 2 неизвестные переменные: m_aString q.m_aeI Сначала разберемся с q.m_aeI, так как l1 участвует в проверке кода. Открываем q. java и ищем переменную m_ aeI. Мы находим ее только в строчке: public static int m_aeI = 0; Но этого недостаточно, так как получается, что в k.java вызывается переменная из q.java, которая равна нулю… Следовательно, ищем изменение этой переменной в остальных классах. В i.java находим такие строчки: int k; if((k = q._aStringII("temp", 1, 0)) == 0){ k = q._aIII(0xf462b, 0x98967f); k = 0x1c9c380 + k; q._aStringIV("temp", 1, k); } q.m_aeI = k % 0x989680; q.m_afI = (k - k % 0x989680) / 0x989680; obj = String.valueOf(k); obj = ((String) (obj)).substring(0, 4) + " " + ((String) (obj)).substring(4, 8); Смотрим, какое значение получает переменная k при q._aIII(0xf462b, 0x98967f). Открываем q.java и ищем функцию _aIII public static int _aIII(int i, int x){ int i1; return (i1 = Math.abs(m_aRandom.nextInt())) % (x - i) + i; } Исходя из этого переменной k задается случайное значение… Проанализировав получаемые значения k, а так же исходя из этих строчек: obj = String.valueOf(k); obj = ((String) (obj)).substring(0, 4) + " " + ((String) (obj)).substring(4, 8); и q.m_bString = "T" + obj + " " + s; Получаем, что k это первые 8 цифр из 12-значного кода, которые генерируется в игре при первом запуске. Теперь объединяем все воедино и пишем подбор ключа
Kod – первые 8 цифр из кода, который
генерируется при запуске игры //вначале считываем код в переменную kod //далее идет объединенные части из разных классов, которые мы раскопали Kod1 = Kod % 0x989680; obj = String.valueOf(Kod); long l; String s; long l1; boolean progress=true; String Klych ="10000000"; while(progress){ Klych = String.valueOf(Integer.parseInt(Klych)+1); l1 = (l1 = Integer.parseInt((s = String.valueOf(l = Kod1)).substring(0, 1)) + Integer.parseInt(s.substring(1, 2)) + Integer.parseInt(s.substring(2, 3)) + Integer.parseInt(s.substring(3, 4)) + Integer.parseInt(s.substring(4, 5)) + Integer.parseInt(s.substring(5, 6)) + Integer.parseInt(s.substring(6, 7))) * 321L + 213L & 255L; if((s = String.valueOf(l = (l = (l = (l = (l = (l ^= 0x1c91bfL) ^ l1) ^ l1 << 8) ^ l1 << 16) << 3) * 3L + 2129L).substring(0,7)).substring(0,4).compareTo(obj.substring(1, 5)) == 0){ progress=false; //вывод переменной Klych } } Для ускорения перебора можно вынести: l1 = (l1 = Integer.parseInt((s = String.valueOf(l = Kod1)).substring(0, 1)) + ... + 213L & 255L; и String.valueOf(l = (l = (l = (l = (l = (l ^= 0x1c91bfL) ^ l1) ^ l1 << 8) ^ l1 << 16) << 3) * 3L + 2129L).substring(0, 7); за цикл,так же можно установить "шаг перебора" равным 1000. Получаем следующий код: Kod1=Kod % 0x989680; long l; String s; String Klych ="10000000"; long l1; boolean progress=true; l1 = (l1 = Integer.parseInt((s = String.valueOf(l = Kod1)).substring(0, 1)) + Integer.parseInt(s.substring(1, 2)) + Integer.parseInt(s.substring(2, 3)) + Integer.parseInt(s.substring(3, 4)) + Integer.parseInt(s.substring(4, 5)) + Integer.parseInt(s.substring(5, 6)) + Integer.parseInt(s.substring(6, 7))) * 321L + 213L & 255L; s = String.valueOf(l = (l = (l = (l = (l = (l ^= 0x1c91bfL) ^ l1) ^ l1 << 8) ^ l1 << 16) << 3) * 3L + 2129L).substring(0, 7); while(progress){ Klych = String.valueOf(Integer.parseInt(buf)+1000); if ( s.substring(0, 4).compareTo(Klych.substring(1, 5)) == 0){ //вывод Klych progress=false; } } Теперь этот код можно перенести на любой другой язык программирования или оставить в J2ME. Вместе со статьей идут два Key-Gen'а в котором он реализован… ( J2ME и VB.NET) Вот так, просто анализируя код мы создали свой генератор ключей… Генераторы ключей для Tanks Mobile 3.0: Внимание! У вас нет прав, для просмотра скрытого текста. |