Как хакать всё что угодно
| |
Nemesis_c | Дата: Среда, 03.08.2011, 02:31 | Сообщение # 1 |
Сообщений: 1148 Статус: Offline
| r57shell:
Эта инструкция нацелена на: тех кто почти нуб в компах. Поводом, для этой статьи получился ответ на эмо-стране вот этот:
Ti_: Quote (r57shell от 10 Января 2010, 20:53:11) изучаю за неделю (это редкость) обычно за день-два. ок напиши книгу как научится прогить за неделю для новичков с нуля, и о том как это легко. а вторую неделю на асм и далее перед ними все пути в ромхакинге открыты. Quote (r57shell от 10 Января 2010, 20:53:11) Для того, чтобы понять, надо именно знать ассэмблер, а вот теперь найди тех, кто его знает. Утверждаю, что большинство тех кто знает ассэмблер - поймут как хакать и без тебя ок все новички знают ассемблер. они поймут без меня я в этом не сомневаюсь. Quote (r57shell от 10 Января 2010, 20:53:11) но в тоже время означает что ты не занимаешься ромхакингом в целом, так как ты не трогаешь код :] ромхакинг взлом ромов, что меняешь не важно. с таким же успехом я могу сказать ты в целом не ромхакер- ты музыку и звук не заменяешь - только код. другое дело что интересный или качественный хак можно сделать только измением кода, исключение - создание новых уровней например которые кодом не являются. (миссия в дюне, трасса в rrr.), а также RRR hack v0004 ). Quote (r57shell от 10 Января 2010, 20:53:11) 1) Одно не другое в смысле что они не одно и то же. ("вода не жидкость" так как жидкость не вода.) 2) Одно не другое в смысле что одно не является частью другого. ("вода жидкость" так как вода же жидкая!!) Надеюсь написал достаточно популярно. напиши 1) и 2) на asm 68k может мне понятнее будет что ты хотел сказать. Quote (r57shell от 10 Января 2010, 20:53:11) да понимаешь ресурс хакинг он уже ромхакинг. romhacking = (resourse hacking) or (graphic hacking) or (code hacking) or (music hacking) or (perevod) or (fcking 100500 hacks mario color) хотя последние 2 я за ромхаки не считаю.
Cсыль на этот пост http://www.emu-land.net/forum....g504772
Содержать эта статья будет в основном теорию. Не торопитесь хакать программы с защитами, лучше потренероваться на простых, в целях моддинга. Хотя я вот первым попробовал сделать кряк к одной программе... Но это я :). Ах да, у меня ничего не вышло. Точнее пол дела сделал, а на самом сложном, сдулся. Это же не тру, когда стока времени убил, а результата не достиг.
Почти нуб должен: - уметь давить названные кнопки,
- уметь двигать мышкой,
- уметь находить клавиатуру,
- кстати находить мышь тоже надо уметь,
- уметь смотреть в монитор, в том числе во все его части,
- уметь переключать окошки, те из которых не дует ветер, или не светит солнце,
- уметь инсталировать софт, и даже уметь запускать его хотябы двойным кликом,
- уметь копировать полные пути файлов,
- уметь копировать пути папок,
- уметь копировать текст,
- уметь находить меню у программ,
- знать арифметику типа 2+2, 3*4,
- знать хотябы часть английского алфавита а именно a-f, A-F,
- ну и уметь читать то, что я написал, не пропуская слов, и в тоже время уметь читать то, что пишу не только я, обязательное требование - опыт работы в блокноте (notepad или его аналогах) не менее месяца!))).
Отмечу на то, что например трей уметь находить от вас не требуется... И второе что отмечу, что это не полный список требований, иначе он будет жутко грамоздким, например ещё надо уметь находить панель пуска.
Итак, начну издалека...
Жили были, блин не то...
В давние времена, снова не то.
В эфире капитал шоу "Поле Чудес". Да блин!
Будем без вступлений. Начну с того, как можно хакать игры. Вопервых, что такое алгоритм? Например, я хочу алгоритм как пожарить картошку (няя обожаю, жрать все хотят... "сначала все борятся с голодом, потом со сном"):
- 1. Найти картошку.
- 2. Найденную картошку (вдруг найдутся те кто не найденную умудрится) почистить.
- 3. Найденную, почищенную картошку помыть. Проще говоря ту, которая получилась после первых двух шагов.
- 4. Найденную, почищенную, помытую картошку(а мазохистам можно и пальцы) порезать.
- 5. Найти сковородку.
- 6. Найденную, почищенную, помытую, порезанную картошку выложить всю в найденную сковородку. Проще говоря, то что получилось после шага 4 положить в результат шага 5.
- 7. Включить газ. (этот шаг тоже можно описать целым алгоритмом, и можно это назвать функцией).
- 8. Поставить на включенный газ сковородку (результат шага 6).
- 9. Выставить газ "на вкус".
- 10. Налить "на вкус" в сковородку масла (не в какую-то левую а именно в ту которую поставили на газ).
- 11. Если картошка готова, перейти к шагу 13. Поджарился низ сковородки? Если да, то перейти к шагу 12, иначе ждать, то есть перейти к шагу 11.
- 12. Перемешать картошку. КОТОРАЯ В СКОВОРОДКЕ, а не в мешке например... И перейти к шагу 11.
- 13. (Мы почти закончили!) Выключить газ. (тот который под сковородкой с готовой котошкой к зохавыванию)
- 14. Ждать пока чуток остынет, а не жрать сразу.
- 15. УрЯ! Картошка готова.
Вроде такой с житейской точки зрения простой алгоритм, а аж 15 шагов смог выделить. В данном случае всё чем оперируем (газ, картошка, сковородка и т. д.) называют операндами. Шаг 11 называют условным переходом, или ветвлением, т.к. в этом месте алгоритм может перейти на разные шаги, то есть пути разветвляются - отсюда название ветвление. Шаги 11-12 называются циклом, который заканчивается при условии что картошка готова. Проверка условия - тоже можно описать целый алгоритм.
Алгоритмы выполняются последовательно - это первое что нужно подчеркнуть, т.к. за счёт этого много чего можно понять, упростить, читерить... А зачем нам алгоритмы? Ими описываются все действия программ. Другими словами, если понять алгоритм, то можно найти и данные которые он использует, и поправить как охото и прочее.
Теперь, мой любимый алгоритм на закуску. "Как убиться абстену": - 1. Ищем стену.
- 2. Найдена стена? Если нет, переходим к шагу 1. Если да, запомнили стену, и где она.
- 3. Ищем голову.
- 4. Найдена голова? Если нет, переходим к шагу 3.
- 5. Голова наша? Если нет, игнорируем эту голову, и переходим к шагу 3.
- 6. Идём к стене которую запомнили на шаге 2.
- 7. Бьёмся об эту стену.
- 8. Вы ещё живы? Тогда продолжайте с шага 7.
- 9. Увы этого шага для вас нет.
Интерпретация этого алгоритма на С++ выгледела бы так (понимание этого не требуется): Code do { wall=FindWall(); } while(!wall); do { head=FindHead(); } while(!head || head.isNotMy); self.goto(wall); do { head.hit(wall); } while(self.stillAlive);
Это далеко не совершенный алгоритм, ябы порекомендовал вот этот, с сокращёнными некоторыми командами (и понимание этого тоже не требуется, это как дополнение):
Code while(self.stillAlive) { while(!(wall=FindWall())); while(!(head=FindHead()) || head.isNotMy); while(self.distanceto(wall)>enough) self.goto(wall); while(self.stillAlive) { if (wall.stillAlive) head.hit(wall); else break; } } while(self.isAlive);
Так, я отвлёкся. Чего я хотел сказать? Я хотел вот такую вещь пропихнуть: алгоритмом может являться любой бред, просто может мы не знаем язык? Например вот это чем не алгоритм?
Code ewewqeqw asdas asdasdas weq zxczxczxqwwe
Может первая строчка означает открыть холодильник, а вторая достать пиво, и третья закрыть холодильник. Теперь, основной момент. Допустим мы ЗНАЕМ, что это ПАЛЮБОМУ (почемуто-неожиданно) алгоритм. И теперь, мы хотим хакнуть того, кто крадёт наше драгоценное пиво. Прежде чем мы его хакнем (по голове лопатой), ещё один момент: все алгоритмы устроенны именно на последовательном выполнении команд, часто конечно потоков команд одновременно может быть несколько. Например одной рукой мы пишем чего препод говорит, а в тоже время слушаем чо он несёт, а третий поток - мысли "ну чо за бред, кому оно надо?"
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 02:54 | Сообщение # 2 |
Сообщений: 1148 Статус: Offline
| r57shell:
Итак, мы знаем что это алгоритм. Мы его исправляем, допустим что-то в первой строчке - и теперь тот кто его выполнял, понять ничего не может. Теперь он либо вообще не делает ничего, либо виснет, либо ещё чего... Для вора пива нам бы и этого было бы достаточно, но допустим мы же хотим оставить всё работоспособным. Зачем? А вдруг алгоритм вора описан среди других нужных алгоритмов, и он ломает всё.
Теперь надо найти разделение между командами, чтобы (спасибо кэп) их отделить. Обычно это определено архитектурой, т.е. это обычно не составляет труда, кроме как если не известно какой язык используется. Но, тут уже, ищите какой язык, или узнавайте разделение другими путями.
Итак, мы знаем что 3 строчки - 3 команды. Сначала обычно я покрайней мере пробую убить команду, если не знаю чего она делает. И затем смотреть баг - чего изменилось. Если все 3 команды убить, то вор не будет вообще открывать холодильник, а если только вторую - то не будет только брать пиво. А если убить только третюю, то холодильник разморозится, а если убрать только первую - возможно опять будет ошибка ("Пиво не найдено, не найдено чего закрывать" ).
Это ещё не всё, вот тут всего 3 команды. Как же уменьшать объём поиска? Для этого существуют отладчики. На счёт отладчиков будет потом.
Теперь моё примерное размышление 8-го класса: раз Windows умеет запускать exe-шники, значит он их понимает. Раз Windows понимает, то и другой может понимать, только надо знать то, что знает Windows, а Windows знает какраз то, как он работает, и exe это его формат, а Windows писали тоже люди, т.е. надо либо от разработчиков узнавать, либо хакать Windows? К счастью информация о exe-шниках открытая. Кому-то может показаться что повезло. Однако, причина проста: есть те люди, которые пишут компиляторы exe-шников + те люди, которые разрабатывают софт, и хотят отлаживать эти же exe-шники. Как же это делать, если exe был бы как чёрный ящик? Тогда бы никто exe кроме Microsoft и не смог делать.
Ещё один основной момент: разработчики хотят всегда чтобы программа/алгоритм был как можно прост. Для чего? Для того чтобы если он поломался, можно было понять где, кто и как. (хреновый аргумент) Лучше скажу так. Разработчики хотят чтобы в алгоритмах/программах было как можно меньше например повторений кода. Для чего? Если баг проявился в одном участке, то надо изменить все повторения, и очень часто, в силу человеческого фактора - заменяются не все повторы (т.к. забываются) и баг остаётся. А если просто надо поменять (например улучшить) участок кода который многократно повторяется? Снова не все повторения могут быть изменены.
Поэтому в качественных программах чаще всего код отвечающий за определённый момент, повторяется не более одного раза. Это нам в плюс: нахождение одного места с созданием юнита влечёт нахождение множества его характеристик. Но не всегда - из-за не тру кода/прогеров. Аналогично переменные(сколько жизни у игрока, сколько денег) - не часто дублируются.
Теперь два подхода.
Первый - чаще всего быстрый: поиск сначала значений, которые связаны с тем, что мы хотим изменить. Про это написано тонны статей, есть тонны прог, типа ArtMoney. Если нашли адрес в памяти - ставим в отладчике breakpoint(точку останова) при чтении с этого адреса из памяти - и перед нами место кода, которое читает из данного адреса (например количество денег). Но не всегда есть возможность ставить такие breakpoint-ы, и даже не всегда есть просто отладчик! Как во втором случае быть - честно, не знаю... Конечно знаю некоторые методы, например заполнение нулями участков бинарника (исполняемого файла), но такие методы настолько долгие, и не факт (для меня), что получится.
Второй - медленнее, может быть в некоторых случаях значительно (незнаю): исследование кода пошагово начиная с какого-то места. Чаще всего со старта программы. Про него немного по подробнее остановимся.
Кроме условных переходов, и циклов. Бывают такие чтукенции как безусловный переход (просто переход к шагу, побарабану, просто хочу и перехожу). И вторая фишка - вызов подпрограммы. Вот фишка состоит именно на понимании второй фишки.
В момент того когда происходит вызов подпрограммы, в памяти (если точнее, в стэке... кто хочет тот гуглит) сохраняется адрес команды, с которой продолжать выполнение ПОСЛЕ выполнения подпрограммы. То есть, когда подпрограмма закончит свои действия, она возвращяется в следуйщюю команду после команды вызова подпрограммы. На этом и играет метод номер два. В первый раз когда проводим отладку, мы как-бы ищем, в какой из подпрограмм произходит нужное нам действие - в дебагере(в отладчике) жмём Step Over - шаг поверх, то есть незаходя внутрь. Это не означает что подпрограмма не будет запущена, просто мы не будем её отлаживать пока она там работает, затем она закончит работу, и отладчик продолжит "свою миссию"
Вроде бы мы же не отлаживаем подпрограммы, а как нам тогда узнавать в какой из них происходит нужное нам действие? Да, кстати, во время отладки мы пытаемся сделать нужное нам действие, или что-то с ним связанное. Например если мы хотим код выстрела, то мы пытаемся начать игру, и затем пытаемся выстрелить.
Во время отладки получается обычно два варьянта:
Первый:
Программа начинает выполнятся без остановки пока вдруг, по понятным или нет нам причинам, она снова ставится в паузу отладчиком. Всё что происходило между паузами - происходило скорее всего в подпрограмме. Но по крайней мере, подпрограмма на это влияла, т.к. без этого выполнения - ничего не происходило. Если действие которое нам нужно не произошло в этот момент, значит не в текущей выполняющейся подпрограмме оно производится. А если например удалось выстрелить (мы хотели найти код выстрела). То данная подпрограмма точно влияет на выстрел.
Второй:
Программа гоняет в цикле, и не даёт "нормальное" пользовательское управление, то есть постоянно стопорится. Значит либо где-то в этом цикле есть подпрограмма или кусок кода, который отвечает за наше искомое действие, или этот цикл просто долгий, и надо его пропустить. Цикл пропускать дело не из лёгких, надо поставить breakpoint-ы на все его возможные "концовки" либо пошагово дождаться конца цикла. Это зависит от тепрения хакающего :).
Ага, теперь мы нашли кусок кода, который содержит данное действие - он находится в подпрограмме, причём, он срабатывает именно в тот момент, когда у нас получилось его сделать (это действие). То есть мы могли несколько раз запускать эту подпрограмму во время отладки, но только в определённый момент она(подпрограмма) сделало искомое действие. Лучше сразу её переименовать какнибудь, для заметок, с учётом того, что скорее всего искомая нам функция (подпрограмма) далеко не эта.
Первый удачный прогон может не сразу получится, теперь нужно сократить до максимума область кода, которая влияет на наше событие. Запускаем снова отладку с того же места, точно также, только теперь обращаем внимание сколько раз запускалась до нужного нам события наша функция переименованная, запомнили.
Третий проход, также с тогоже места начинаем отладку, только теперь в именно тот раз в который происходит действие - заходим внутрь подпрограммы (Step In шаг внутрь) - и теперь если считать что это "состояние" отладчика - начальное, начинаем отлаживать по методу первого прохода, второго, и т.д. пока не сузится объём кода до минимума - желательно одной подпрограммы. Этот алгоритм можно сократить, убрав третий проход, если сразу считать сколько раз какие функции были, или постчитать в отладчике по коду, но с циклами это не проканает.
Тада! Мы нашли чего хотели, если руки не кривые, или если руки у программеров не кривые, или если защит нет.
Если чего-то не получается, то нужно пробовать разные методы, чаще всего придуманные самим. Хорошо ещё использовать весь арсенал прог которые находятся в разпоряжении. В том числе и описания к функциям которые автоматически определил дебагер типо sprintf, CreateWindow, CreateFile.
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 02:56 | Сообщение # 3 |
Сообщений: 1148 Статус: Offline
| r57shell:
Теперь, почему прогерам обычно легче? Они знают что такое алгоритм. Так как они живут в их среде. Редкий программер не отлаживал свои программы (не отлавливал баг). Отловка бага также делается. В зависимости от опыта, мышление подстраивается под логику алгоритмов - пошаговости. Ещё они знают основные приёмы, есть опыт "как я бы сделал". Знают стандартные функции, англецкие слова (у всех разный словарный запас).
Кстати, ещё во время отладки программы, программисты бывает вставляют дополнительные участки кода, которые будут только в нужные моменты довать выполнять строчку (команду) "пустышку" (например nop - no operation - без операции) только для того чтобы на неё поставить breakpoint. А раз эта строчка выполняется только при определённых условиях - то и breakpoint будет выполнятся при определённых условиях. Так можно добится breakpoint-ов по условию.
Итак, чего надо запомнить, ой, плохое слово. Всё что надо осознать! Эмм, я просто выделил всё что надо.
Это было описание основных принципов хаканья того, чего данные у тебя в руках полностью: например обычно игра вся на диске - можешь всю вдоль да поперёк перешерстить, перелопатить.
А на счёт хаканья того, чего нет полностью у тебя в руках, типо сайтов. Не знаю как у других, т.к. не интересовался, но моя стратегия, искать то в чём скорее всего я бы напортачил. То есть в чём легко напортачить. Или те места, где нубы кодеры делают ошибки, например в запросах MySQL на сайтах. Надо ещё помнить что хороший отчёт об ошибке - только наруку хакеру. Нормальные сайты ошибки должны не выдавать, и сохранять в логи, или слать на мыло админу.
Второй метод хаканья того, чего нет под рукой - в момент когда сервер готов "внимать" юзера (принимать данные с него), просто пытаемся ему слать вместо данных либо не возможные с точки зрения сервера данные, либо просто мусор. Если сервер начинает глючить - то значит есть что-то. Если дохнет, то только ждать пока снова поднимут
Можно ещё много методов придумать, и много уже придумано. Большинство методов я описал с целью не совета, а примера.
Итак... это была моральная подготовка, и основные принципы. Теперь, вы должны прокачать свою арифметику.
Для начала... переместимся в двоичную систему отсчёта, где
0=0 1=1 2=10 3=11 4=100 и так далее.
Зачем? Отвечаю: так как на компе основа - двоичка. Теперь то, чему обычно не учат в простой арифметике, а именно битовые операции. Вопервых что такое бит? Это один разряд двоичной записи числа.
Битовых операций бывает много, всяких разных, заразных. Например XOR очень заразная битовая операция, но о ней чуть пожже. Для начала битовое И (AND) - так называемое битовое умножение. Если 1 интерпретировать как true (истина), и 0 как false (ложь), то результат AND - это как вопрос: истино ли первое вместе со вторым? Называется битовое умножение так потому, что его результат можно получить если просто биты перемножить. В C++ битовое И обозначается & (амперсанд). "Таблица истинности":
0&0=0 0&1=0 1&0=0 1&1=1
Теперь перейдём от битовой операции, к побитовой операции, хотя обычно последнюю просто битовой называют. Побитовая операция, это просто результат для каждого разряда числа, битовой его операции. Пример побитового И (AND) умножения: Code 1101011 1010010 = 1000010
Другими словами, бит "останется" только в тех разрядах, где в обоих операндах "есть" в этом разряде бит.
Битовое ИЛИ (OR) или "соединяющее или" называется именно так потому, что результат можно интерпретировать: верно ли что первое или второе? Легче всего запомнить такое его свойство: если в обоих 0 то результат тоже 0, иначе 1. В С++ битовое или обозначается | (вертикальная черта). Побитовое ИЛИ определяется аналогично как побитовое И. Нули остаются только там, где в обоих операндах нули.
Затем XOR (читается "ксор") или "исключающее или" или битовое сложение. Это значит, что результат 1 если или в одном 1, или в другом 1, но не в обоих. Битовым сложением называется потому, что результат можно получить если сложить биты, а потом "переполнение" отсечь. В бите не может хранится больше 1, по этому при результате 10, нужно отсечь переполнение - то есть единицу. Я лично запомнил такое свойство: чтобы получить результат, нужно взять первый бит, и если второй бит 1, то результат (первый бит) инвертировать. Из этого следует свойство побитового XOR: биты меняются только там, где во втором операнде 1. В С++ побитовый XOR обозначается ^ (как рисуют анимешные смайлы ^_^).
Битовое НЕ (NOT). В этот раз всего один операнд. Результатом является инвертированный бит. Побитовый НЕ инвертирует все биты. В С++ побитовый НЕ обозначается ~ (тыльда). Ух, вроде всё с битами... нудное занятие такое описывать. "Таблица истиности" всего разом:
0&0=0 0|0=0 0^0=0 ~0=1 0&1=0 0|1=1 0^1=1 ~1=0 1&0=0 1|0=1 1^0=1 1&1=1 1|1=1 1^1=0
Это не все побитовые операции, ещё некоторые опишу чуть пожже, чтобы разбавить обстоновку.
Теперь, всех обрадую: мало кто записывает в двоичной, так как это очень громоздко (один байт = 8 бит). Поэтому используют шестнадцатиричную систему исчисления (HEX). Самое интересное, то что в HEX многим кажется сложно делать побитовые операции, но я сейчас объясню как это просто делается ).
Вопервых, у нас нет цифр 10,11,12,13,14,15. Их придумали заменять буквами английского алфавита: a,b,c,d,e,f строчными или заглавными. Есть много обозначений, что данное число записано в HEX. В С++ это обозначается префиксом 0x, например 0x42EF21. В ассемблере M68k для этого существует префикс $, например: $42EF21.
Теперь перейдём к быстрому битовому счёту без калькулятора. Максимум, что понадобится может быть, это блокнот, если числа длиной больше байта. Во первых, надо запомнить такие числа: 1, 2, 4, 8 - патамучта это степени двойки. Зачем? Потому, что они в двоичной системе исчисления выглядят как 1, 10, 100, 1000. Во вторых, надо запомнить такие числа: 1, 3, 7, F - патамучта это степени двойки вычесть один. Зачем? Потому, что они в двоичной системе исчисления выглядят как 1, 11, 111, 1111.
Остальные степени двойки, или степени двойки "вычесть один" не надо запоминать, потому что они получаются приписыванием нулей к концу тех числел которые мы уже запомнили. Как так?! А всё очень просто 0x10=16 то есть степень двойки, а степень двойки умножить на степень двойки равна степени двойки. А чтобы получить степень двойки минус один, надо просто вместо нулей приписывать F.
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 02:58 | Сообщение # 4 |
Сообщений: 1148 Статус: Offline
| r57shell:
Теперь чем эти числа нам помогут? Для этого нужно знать как перевести из HEX в двоичную систему. Буду описывать способ, который я нигде не видел. Сразу на примере. Есть число 0x6CF5. Хотим в двоичную! 0x6CF5 > 0x4000 и в тоже время 0x6CF5 < 0x8000 это вроде как очевидно. Из каждого по следствию. Сначала из второго следует то, что в битах которые начиная 0x8000 и далее - пусто. Из первого следует что бит 0x4000 есть, так как еслиб его небыло, то максимум чего можно было бы достичь это 0x3FFF. Один бит нашли, теперь следуйщий. Вычтем из 0x6CF5-0x4000=0x2CF5 чтобы не мешался. Аналогично 0x2CF5 > 0x2000 и в тоже время 0x2CF5 < 0x4000, из чего следует что бит 0x2000 есть. 0x2CF5-0x2000=0хСF5 а это значит что есть бит 0x800. Затем 0xCF5-0х800=0х4F5, а это значит что есть бит 0x200, и так далее. Пишется эти все действия дольше чем в уме срабатывают. Итого биты которые есть: 0x4000, 0x2000, 0x800, 0x400, 0x80, 0x40, 0x20, 0x10, 0x4, 0x1. Замечу одно, что можно было каждую цифру просто отдельно рассмотреть. Теперь навязывается вопрос, а кто будет переводить в двоичную? А зачем?! Кому оно надо?!) Вот такой вот ответ. Так как можно, и я считаю даже нужно просто сопоставлять есть/нету данного бита. Пример битового XOR двух HEX чисел с некоторой инфой которая в голове должна быть, и не надо её писать (то что под цифрами):
Code 24EFC ----- 24888 444 22 1
53FAA ----- 42888 11422 2 1 = 77156 ----- 44144 22 12 11
А теперь без лишнего: 24EFC 53FAA = 77156
Замечу что на двоичное представление каждого числа из примера, понадобилось бы строчки длиной 12. Вот описанные тут методы, я использую.
Зачем нужны ещё битовые операции? Например если охото взять остаток от деления по степени двойки, то просто вычитаем из неё единицу, и делаем битовое И. На битовых операциях обычно делаются все работы с флагами (число в котором каждый бит, или группа битов отвечает за некоторую опцию, свойство). Например как выставить флаг? Ответ сделать логическое или с ним. Как убрать флаг? Сделать сначала логическое или с ним (чтобы выставить, то есть удостовериться что он есть), а затем сделать XOR, или второй варьянт: сделать логический И с числом в котором все биты кроме данного флага (обычно называют маской). Как проверить есть ли флаг? Просто сделать логическое И с ним.
Складывать как HEX числа - также, столбиком!
Есть ещё операция "битовый сдвиг". Все биты, сдвигаются на несколько позиций вправо/влево, отсюда названия: битовый сдвиг впаво, битовый сдвиг влево. Биты не влезающие в число - либо затераются, либо ещё чего, в зависимости от разновидности операции. Легче всего описать эти операции так: битовый сдвиг вправо это деление без остатка на два n раз, битовый сдвиг влево это умножение на два n раз. В C++ битовый сдвиг вправо обозначается >>, а битовый сдвиг влево обозначается <<. Английский варьянт названия: Shift Left, Shift Right. Отсюда названия в ассемблерах многих: shl,shr - в одних. lsl,lsr - в других (Logical Shift Left, Logical Shift Right).
Может кому битовые операции и не пригодятся, но с HEX надо явно дружить. Часто, очень часто бывают переменные так называемые "флаги" (flags), каждый бит которых (или группами) отвечает за свою опцию, или свойство.
Теперь немножко о процессорах. У процессоров есть своя память "личная")). Называются эти ячейки памяти регистрами. Многие операции напрямую с памятью (RAM) процессоры не могут делать, и работают исключительно только с регистрами. Кроме того с регистрами быстрее работать, так как они уже в процессоре, и не надо из памяти читать ничего. Обычно изменение данных выгледит так: считать старое, подшаманить в регистрах, записать новое.
После такого экскурса, я считаю можно смело брать ман по ассемблеру того чего хакаем, + ман по отладчику. И хоть чего-то пытаться делать, а не тупо читать, и ныть "ааа я ничё не могу, ничё не получается", или тупо ждать пока всё на блюдичке покажут, и за вас сделают.
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 03:01 | Сообщение # 5 |
Сообщений: 1148 Статус: Offline
| r57shell:
Пока трешный пример, потом сделаю нормальный, т.к. времени дефицит:
Quote За трэш сэмпл (пример) будет взят пример как о RRR на сеге можно чего узнать. Не буду спойлерить что будет не в треш(мусор) примере. Итак, для хакканья нам понадобится Gens_my (я его так буду называть). Это генс моей сброки, найти его можно на эмостране, в разделе ромхаккинг, на странице дальше третей. Затем IDA Pro + Loader для сеги, непомню как он называется и как его добыть Теперь. у нас на сайте например написано: 732E snake top speed. Это можно узнать разными способами. Короче главное есть адресс, который связан с тем, что мы хотим узнать. А хотим, мы узнать допустим что-то другое связанное с тачками. Теперь открываем IDA кормим ей ром RRR, говорим что это сега А дальше жмём в просмотрщике дизассембла кнопку G, что означает переход по адресу. Вводим 732E, и видим, что там есть ROM:0000732E unk_732E: dc.b 1 ROM:0000732F dc.b 0 ROM:00007330 dc.b 1 ROM:00007331 dc.b 0 ROM:00007332 dc.b 0 ROM:00007333 dc.b 1
Дак вот, unk_732E это IDA назвала так адрес которой 732E. unk - означает unknown неизвестное (know - знать, known - известное). Так как чтобы хакать надо уметь догадываться, то тут должны догадаться что unk_732E это ничто иное как таблица top_speed у игроков. итак, переименуем unk_732E для этого надо на него навести, нажать N, и например ввести char_top_speed. Дальше наводим снова на char_top_speed и жмём X. И тут хрен тебе )). Поидее X - это посомтреть список ссылок, но ида не нашла ссылки, по какой-то причине. Идём другим путём запускаем gens_my, и заходим Tools->Debug (делал эту фичу я). видим Breakpoints добавляем (жмём Add) вводим 732E-7333 это промежуток адресов на которые хотим поставить точку останова ставим галочки read, enabled писать в ром нельзя, поэтому write не используем. теперь открываем ром RRR, запускаем, и играем. Можно для ускорения держать кнопку Tab. И когда трасса начинается, срабатывает Breakpoint в окне дизасма выделен адрес на котором остановилось. это адрес на котором произошло чтение. 7300 у меня остановился на этом адресе. жмём в иде G и вводим 7300. видим код. тут уже переименованный варьянт, но если полазить ручками, то можно догадаться ROM:000072F2 lea $38FA(a4),a1 ; player1 char id ROM:000072F6 clr.w d0 ROM:000072F8 move.b (a1,a0.w),d0 ROM:000072FC lea $51A4(a4),a1 ; car top speed (+char top speed) ROM:00007300 move.b char_top_speed(pc,d0.w),d1 ROM:00007304 add.b d1,(a1,a0.w) ROM:00007308 lea $51A8(a4),a1 ; car acceleration (+char acceleration) ROM:0000730C move.b char_acceleration(pc,d0.w),d1 ROM:00007310 add.b d1,(a1,a0.w) ROM:00007314 lea $51AC(a4),a1 ; car ammortisation speed (+char jumping) ROM:00007318 move.b char_jumping(pc,d0.w),d1 ROM:0000731C add.b d1,(a1,a0.w) ROM:00007320 lea $519A(a4),a1 ; car handling (+char cornering) ROM:00007324 move.b char_cornering(pc,d0.w),d1 ROM:00007328 add.b d1,(a1,a0.w) ROM:0000732C rts как лазить? просто на имя наводим и жмём ENTER. если надо вернуться обратно жмём ESC замечу lea $38FA(a4),a1 - это относительное взятие адреса. означает оно взять адрес a4+38FA, а в RRR регистр a4 всегда равен $FF8000 поэтому player1 char id находится по адресу $FFB8FА. Эти команды ассэмблера - специфика сеги. аналогично специфика сеги, что память которая RAM находится на адресах $FF0000-$FFFFFF ром $000000-$3FFFFF. Но логично писать в ром нельзя и если видно адрес а в него пишется то это полюбому рам, и сдесь если адрес не $400000-$FFFFFF, то видно относительная адресация move.b char_cornering(pc,d0.w),d1 тут аж 3 параметра адресации передвинуть из (pc+d0)+char_cornering в регистр d1
А теперь не трешный пример. Я специально не готовился к нему, буду писать действия, сразу по их развитию. Зачем? Для того чтобы было понятно как чего делается, ато обычно все узнают только результат и всё. Статья будет обновлятся с временью прогресса.
Итак для примера я хочу например помучать Comix Zone, вопервых я слышал, что в нём какой-то неизвестный packer/unpacker графики, и поэтому чисто из спортивного интереса хочу его 1) найти 2) разколупать.
Второе, чтобы было над чем развлечся... 1) сделать более быстрый выпуск самолёта, и без потери жизни. 2) найти читы всем известные, может чего интересного найти чего никто ещё не видел ))).
Итак что нам понадобится: ром "Comix Zone (U) [!].gen", как обычно ида, и моя сборка эмуля, + сборка Gens VKNTrace.
Начнём с самолётика... итак толкаем в IDA ром Comix Zone и выбираем то, что это Genesis... (Можно просто ром в окно иды перетащить). Теперь запускаем ром в моей сборке эмуля. Чтобы зависший звук во время отладки не бесил, и чтобы он работал делаем Sound->Enable включиным, Sound->Volume Control в ноль Master. Начинаем первый левел, и попробуем метод который я ещё не пробовал, как я и говорил - часто методы сам придумываешь. Заходим сразу в Tools->M68k Debug. И жмём Step Into. Если Callstack очень жирный, что аж лагает Step Into жутко, то прийдётся перезапустить эмуль, сброс Callstack-а не предусмотрен пока... Итак отладка у меня о становилась на 1CCA0A, переходим в иде по этому адресу(жмём кнопку G и вводим 1CCA0A) затем жмём превращаем в код (кнопка C):
Code ROM:001CCA0A movea.w d5,a2 ROM:001CCA0C move.w word_FFFF830E(a2),d5 ROM:001CCA10 bpl.w loc_1CCAA4 ROM:001CCA14 addq.w #1,d5 ROM:001CCA16 bne.w loc_1CCAC2 ROM:001CCA1A move.w d4,d5 ROM:001CCA1C lsr.w #3,d5 ROM:001CCA1E movea.w d5,a3 ROM:001CCA20 not.w d4
А в стеке лежит
Code 1CC96E 1CCAFE 1CC96E 1CCAFE 1CC96E 1CCAFE 1CF6BC 1D250C и так далее...
Перейдём на 1CC96E. Превратим в код, это должен получится вызов функции т.к. это Callstack.
Code ROM:001CC96E bsr.s loc_1CC996 ROM:001CC970 movem.w (sp)+,d1-d2 ROM:001CC974 rts
Действительно вызов функции... значит отладчик не бажит (^^)// . Теперь мы знаем что есть такая функция 1CC996 ))), ну покрайней мере участок кода. Теперь тоже самое сделаем с 1CCAFE
Code ROM:001CCAFE bsr.w sub_1CC956 ROM:001CCB02 move (sp),sr ROM:001CCB04 addq.w #1,d0 ROM:001CCB06 dbf d7,loc_1CCAFE ROM:001CCB0A rte
И тоже самое с 1CF6BC
Code ROM:001CF6BC bsr.w sub_1CF95E ROM:001CF6C0 movem.l (sp)+,a0-a1/a6 ROM:001CF6C4 rts
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 03:04 | Сообщение # 6 |
Сообщений: 1148 Статус: Offline
| r57shell:
Теперь важно знать, что если нажать двойным кликом на имя мышкой, то переходит на этот адресс. Например имя sub_1CF95E, перейдёт на его адресс. Также можно навести курсором который как в текстовике бегает в IDA Pro и нажать Enter на клаве, то произойдёт тоже самое (переход по имени). Также есть горячая клавиша ESC - вернуться обратно. Так можно как в папках в тотал командере (Enter/Backspace) рыться в IDA в коде (Enter/ESC). Ах да если же у вас врублен вид "графа" то можно его выключать включать нажатием Space на клавиатуре. Собственно я немного времени убил на копание в коде (Enter/ESC) чисто интересно же... выгледит ужастно. Поподробнее...
Заходим в sub_1CF95E там видим красную стрелочку справа - она означает что возможен переход, а раз дальше кода нет, значит только туда и есть переход, т.е. навозим на loc_1CCACA и жмём снова Enter.
bsr.w sub_1CCBE4
Из того что написано sub_уже можно догадаться что это функция (Subroutine), залазим, видим:
Code ROM:001CCBE4 sub_1CCBE4: ; CODE XREF: ROM:loc_1CCACA ROM:001CCBE4 ; sub_1CF956 ROM:001CCBE4 tst.w (word_FFFF8306).w ROM:001CCBE8 rts ROM:001CCBE8 ; End of function sub_1CCBE4
Ничего интересного, всего одна команда непонятная (даже то, что я знаю, что это проверка значения по адресу FF8306 ничего мне не говорит). Идём назад (ESC) смотрим, что дальше... В итоге подходим к вот этому месту:
Code ROM:001CCAE6 jmp loc_1CCAEA(pc,d4.w) ROM:001CCAEA ROM:001CCAEA loc_1CCAEA: ROM:001CCAEA bra.w loc_1CCAFA ROM:001CCAEE dc.b $60 ; ` ROM:001CCAEF dc.b 0 ROM:001CCAF0 dc.b 0 ROM:001CCAF1 dc.b $1C ROM:001CCAF2 dc.b $60 ; ` ROM:001CCAF3 dc.b 0 ROM:001CCAF4 dc.b 0 ROM:001CCAF5 dc.b $2C ; , ROM:001CCAF6 dc.b $60 ; ` ROM:001CCAF7 dc.b 0 ROM:001CCAF8 dc.b 0 ROM:001CCAF9 dc.b $38 ; 8
Я вроде говорил что всё выполняется последовательно... а тут видно jmp - jump переход короче, причём не указано условие! Тоесть всегда переходит. Значит как можно дойти до bra.w? Смотрим ссылки на loc_1CCAEA (наводим и жмём X), еслиб они были они бы показывались справа от самой метки (loc_1CCAEA). Но заметим что jmp кокраз операнд содержит что-то о loc_1CCAEA. Может он прыгает в относительно этого адреса? может дальше строчки это другие варьянты? Делаем из 1CCAEE код, и действительно канает, делаем из следуйщего... получилось 4 варьянта:
Code ROM:001CCAEA loc_1CCAEA: ROM:001CCAE6 jmp loc_1CCAEA(pc,d4.w) ROM:001CCAEA ROM:001CCAEA loc_1CCAEA: ROM:001CCAEA bra.w loc_1CCAFA ROM:001CCAEE ; --------------------------------------------------------------------------- ROM:001CCAEE bra.w loc_1CCB0C ROM:001CCAF2 ; --------------------------------------------------------------------------- ROM:001CCAF2 bra.w loc_1CCB20 ROM:001CCAF6 ; --------------------------------------------------------------------------- ROM:001CCAF6 bra.w loc_1CCB30
То есть тут аж четыре варьянта перехода, в зависимости от d4.w. Но и это ниочём нам не говорит, только можно найти зависимость самой d4.w и явно его подсовывать, или второй варьянт поставить Breakpoint в отладчике (в данном случае эмуль) и смотреть когда, вызывается... это такой пример как копаться в коде )) даже если не знаешь что-за код)... не охото. Это была демонстрация работы с идой - как копаться в коде. Теперь метод который я хотел попробовать - будим смотреть на стэк, и искать самое длинное одинаковое начало... Не, сделаем проще, возьмём и забьём брейкпоинтами адреса верхних допустим пяти различных адресов Callstack. Делаем. Это у меня:
Code 1CCAFE 1CC96E 1CF6BC 1D250C 2142
|
|
| |
Nemesis_c | Дата: Среда, 03.08.2011, 03:05 | Сообщение # 7 |
Сообщений: 1148 Статус: Offline
| r57shell:
Такс в эмуле (моя сборка) в окне отладчика M68k. Add, вводим 1CCAFE, жмём галочку enabled, жмём галочку pc, жмём OK. И так для всех пяти. Теперь жмём Run (я же после Step Into ничего не нажимал). Сработал 1CCAFE значит он часто выполняется, отключаем бряк с него (жмём в брэйкпоинтах на соответствующюю строчку двойным кликом мыши). Снова жмём Run теперь сработал 1CC96E снова отрубаем... Снова Run. О! игра работает )). Попробуем побегать ). Итак пройдя вторую комнату сработал Breakpoint на 1D205C Похоже это как-то связанно с раздувами тётки из первой комнаты (непомню как её завут). Жмём снова Run останавливает на 1CF6BC. Очень всё это похоже либо на события игры, либо на раздувы тётки )). Снова жмём Run снова можно играть )) Это какраз то о чём я говорил в самом начале - либо постоянно недают контроль (в случае с адресами которые мы сразу отключили) либо дают нормально играть до определённого действия. Но так как отключенные адреса вызываются из под адресов которые поверх - значит мы можетбыть уже очень близко к циклу обработки самой игры. Итак в игре ща у меня открылось две стрелочки, вправо и вниз, я как всегда иду вправо. Ага теперь чётко заметил, убил врага, сказала тётка, и во время открытия стрелок сработал бряк на 1CF6BC. Только теперь от Callstack-а повис нахрен эмуль... надо будет исправить эти косяки со стеком. Короче я пока для себя делаю вывод что всё развлекалово тусит в 1СCAFE и в 1СC96E. Уже хорошо. Пока вырубаю эмуль т.к. уже ппц )) лаги. Перед этим надо не забыть нажать Run. Ах да сохраню базу данных а пока надо поделам...
Итак, вот я тут решил наночь глядя раздуть за комиксзон хаккинг. Прочёл чо раньше писал, вспомнил, что нашел два адресса, на втором адрессе тусит вызов sub_1СC956, стандартная идея: а давайте попробуем убить вызов функции? Поставим в теле функции, которое начинается с адреса 1СC956, первой командой - конец функции (вернуться rts). Если ниже посмотреть там где-нибудь можно найти rts. Например по адрессу 1СC974, переходим по этому адресу в вкладке Hex. Если в этой вкладке текущий адрес не близко к этому адресу, то жмём правой кнопкой мыши в хексдамп, и говорим синхронизировать, теперь надо перейти в окне дизасемблера по адресу 1СC974, и затем снова полезть в вкладку Hex. Короче нужно найти во вкладке Hex данные по адресу 1СC974, там должно быть два байта 4E75 (IDA сама выделит опкод). Эти два байта - определяют команду - operation code (опкод). Длина операндов бывает разная. Опкод полностью содержит информацию об операции, посути это строчка ассемблера. Итак, мы узнали опкод rts, я его уже на изусть знаю )). Теперь мы хотим поставить rts прям в начало функции sub_1СC956. Начало функции находится по адресу 1СC956, поэтому пишем чит Game-Genie: 1СC956:4E75. Проверяем игру. Хохо с самого же начала всё виснет. Значит эта функция либо просто очень часто вызывается, либо очень важна. Убираем чит, чтобы функцию востановить. Раз она важна, можно попробовать убить её куски. смотрим на переходы (стрелками обозначаются). Есть места, где вызывается loc_1CC996, а есть места где идут переходы на loc_1CC994. Ну по адрессу loc_1CC994 ничего интерсного - rts. А вот по адрессу loc_1CC996 производятся какие-то действия, АНИГИЛИРОВАТЬ!! Скидыщь: 1СC996:4E75. Тестим, играть-ся игра играется. И удары и самолётик работает, тока при переходе через страницу - ресетает. Вывод - это не то, что нам нужно. А если конкретнее, то вся sub_1СС956 нам не интересна. Однако если посмотреть дальше чем адрес 1СC996, то прям за кодом этой функции, которую толькочто отрубали, тусит строчка (по адресу 1СCA58):
Code ROM:001CCA58 unk_1CCA58: dc.b $F0 ; ? ; CODE XREF: ROM:001CCA26j ROM:001CCA59 dc.b 0 ROM:001CCA5A dc.b $53 ; S ROM:001CCA5B dc.b $43 ; C ROM:001CCA5C dc.b $52 ; R ROM:001CCA5D dc.b $4F ; O ROM:001CCA5E dc.b $4C ; L ROM:001CCA5F dc.b $4C ; L ROM:001CCA60 dc.b $20 ROM:001CCA61 dc.b $43 ; C ROM:001CCA62 dc.b $41 ; A ROM:001CCA63 dc.b $43 ; C ROM:001CCA64 dc.b $48 ; H ROM:001CCA65 dc.b $45 ; E ROM:001CCA66 dc.b $20 ROM:001CCA67 dc.b $50 ; P ROM:001CCA68 dc.b $52 ; R ROM:001CCA69 dc.b $45 ; E ROM:001CCA6A dc.b $2D ; - ROM:001CCA6B dc.b $47 ; G ROM:001CCA6C dc.b $45 ; E ROM:001CCA6D dc.b $4E ; N ROM:001CCA6E dc.b $20 ROM:001CCA6F dc.b $45 ; E ROM:001CCA70 dc.b $52 ; R ROM:001CCA71 dc.b $52 ; R ROM:001CCA72 dc.b $4F ; O ROM:001CCA73 dc.b $52 ; R ROM:001CCA74 dc.b 0 ROM:001CCA75 dc.b 0
dc.b $F0 похоже какое-то свойство строки. Однако строка "SCROLL CACHE PRE-GEN ERROR". Аха! Не буду вдаваться в подробности, что такое прерывания, однако когда ошибки возникают, в данном случае чтение неизвестного опкода $F0, то вызываются специальные функции - обработчики прерываний (ошибок можно сказать), а в них может быть написано что угодно, в плоть до системных функций типо чтений файлов. Похоже $F0 - параметр прерывания... точнее намёк, на то, что это специальная ошибка, а дальше идёт текст. Теперь для тех, кто не знает английский... Как вы смогли до сюда дочитать?! И всёже переведу текст ошибки. Скрол кэш пре-ген ошибка. Ахаха спасиба кэп )). Короче Скролл это задний фон, кэш - означает, что что-то лежит в памяти, предпросчитано, чтобы быстро отвечать. Pre - означает перед (перед чем-то). Gen - от слова Generation - генерация (спасиба кэп). Короче ошибка о загрузке кэша заднего фона, похоже. Итак я там где-то вверху писал отрывок кода, где типо три случая, если посмотреть куда идут переходы - то код по структуре похож, на тот который мы исследовали. Похоже это четыре направления обновления кэша заднего фона. Первый - обновление влево, в чём мы убедились, остальные - хз, кто хочет, тут пусть проверяет, я не для этого хакаю, однако! Из того, что у нас подруками обновлялка заднего фона - можно попробовать расшифровать формат заднего фона (комиксов). Интрига Интрига. Ща чо-нить ещё придумаем.
Так, теперь надо с loc_1CCACA разобраться. Там ниже четыре случая - с ними разобрались, после каждого по rte - return from exception (возврат из исключения - ошибки). Можно было сразу догадаться, что это обработчик ошибки. Интересно какой )). В самом начале вызов функции sub_1CCBE4, уже обсуждалось как, и тестим. В начале первого левела - чёрный экран, что и следовало ожидать - первую же функцию связанную с задним фоном убили, полюбому страшная ошибка, пробуем вторую, то есть sub_1CF956. Прошел весь первый уровень, не заметил, но потом посмотрел на код, где она вызывается - там переход перед вызовом возможен, а условие задано в sub_1CCBE4, если туда зайти то там обращение к word_FFFF8306. Как я уже говорил, всё, что больше 800000 чтоли, это RAM. Ну что, посмотрим что там? Tools->Ram Watch. New Adress: FF8306, Data Type: Hex, Data Size: 4 bytes. Такие значения чтобы 1) было понятнее, 2) побольше увидить. Из того что там у меня 00008000 следует, что первые два байта равны нулю, вторые не равны нулю. Стандартные проверки идут на ноль/не ноль, отрицательное/положительное... Пробуем поставить 1, то есть Game-Genie: FF8306:0001. Тестим. Хопа - камера зафиксированна, а бегаем как бегали. Похоже этот флаг (переключатель) ставится в конце игры когда показывают главного боса с трубкой базарещего. Итак, итог всего шаманства - пока ничего дельного не сделали. Нашли то, чего нам не нужно. Значит если в стеке видим эти адреса - значит это обновление скрола. Нужно смотреть другие адреса. Продолжаем надеятся на стрек, напомню у меня первые несколько различных адресов были такие:
Code 1CCAFE - обновление заднего слоя (далее "хлам") 1CC96E - хлам 1CF6BC - хлам (просто вызов хлама) 1D250C - пока роем здесь 2142
[продолжение хз когда в продолжении ожидается продолжение (спасиба кэп)]
|
|
| |
|