Форум » Конструкторское бюро » DISTANT GUNS - взлом игры » Ответить

DISTANT GUNS - взлом игры

Tsushima: Уважаемые господа! Один из наших форумчан, уважаемый SII, смог взломать игру DISTANT GUNS Переношу в этот топ все сообщения связанные с этим.

Ответов - 69, стр: 1 2 All

slab: SII пишет: Не уверен, что это взломщик именно к этой игре - вроде бы что-то ещё существует с таким названием (но, естественно, без продолжения "Русско-японская война на море"). Что же касается нашей игрушки, то её просто так не взломаешь: файлы лицензии анализируются не только в модуле защиты (именно он выводит диалоговое окошко с предложением купить, зарегистрироваться онлайн или оффлайн или запустить оценочную версию), но и в самой игре. Надуть модуль защиты и заставить его запустить игру с просроченной лицензией сложности не составляет - но кампания и бои разблокированы при этом не будут. Поэтому, ИМХО, проще ломать по регистрационным ключам - алгоритм их расчёта достаточно примитивный. А насколько это осуществимо и реально сделать? Помню были подобные варианты лома ключей (keygen) для платных добавлених (самолёты) к Microsoft Flight Simulator 2004....

SII: sp262 пишет: А поподробнее можно?Большой интерес и малые знания в этой области Гм... поподробнее-то можно, да только с "малыми знаниями" проблематично, ибо лень мне объяснять, что такое шестнадцатеричная система счисления, как пользоваться отладчиками и т.п. :) Саму методу обмана игры изложить могу, только вот не уверен, как это воспримут модераторы данного форума. Ну а вкратце суть такова. В экзешнике сама игра и модуль защиты находятся в упакованном виде, но вот набор команд, управляющих работой модуля защиты -- в распакованном. Смещение этого набора (я его для себя называю "управляющей последовательностью") меняется от версии к версии, поскольку меняются размеры экзешника, однако сам модуль защиты остаётся по сути неизменным, и найти последовательность легко в отладчике или в дизассемблере. В этой последовательности нужно заменить группу байтов, которые приказывают модулю защиты проверить контрольную сумму самого экзешника (с такой проверкой он заметит нашу правку и выдаст плакат "exe file corrupted" или что-то в этом роде), а также байты, производящие проверку на работу под отладчиком, на безобидные значения. Правда, команды "нет операции" там не предусмотрено, но вместо неё можно использовать команды, проверяющие отладчик тем способом, на который он не ловится. После выполнения этой процедуры можно смело запускать игру под отладчиком -- плаката про SoftICE больше не возникнет (хотя как раз обнаружение собственно этого отладчика я не блокировал, поскольку при взломе этой игры он мне был не нужен -- он очень мощный, но не слишком удобный, и я использую его редко). Ну а далее я ставил точку останова на процедуру, проверяющую значения регистрационных ключей и проводящую регистрацию игры. Собственно, можно обойтись и без этого, но тогда придётся каким-то образом расшифровывать файл лицензии (как он шифрован, я тоже определил), а затем самостоятельно вычислять необходимые значения регистрационных ключей. Вместо этого я "подсматриваю", какие значения ожидает от меня программа, и прямо в отладчике заношу их в соответствующие ячейки памяти. После этого разрешаю процедуре регистрации выполняться дальше - и она благополучно модифицирует лицензию, указывая, что у меня законная версия игры. Всё, можно наслаждаться (ну или ругаться) игрой :)

SII: slab пишет: А эту крякнутую игру нельзя на другой комп перенести? Будет она на другой машине работать или она конкретно под вашу систему "завязана"? Как мне кажется, лицензия завязана на конфигурацию оборудования, поэтому просто так её не перенесёшь. Кроме того, реально имеется четыре лицензии: две из них находятся в виде файлов (один -- в корневом каталоге игры, другой под другим названием -- в Windows\System32), а вот ещё две тщательно маскируются в реестре, причём их подменить можно только с помощью программы, которую опять-таки надо писать (а это делать лень). Но можно попробовать другой путь. Как известно, с игрой идёт программка для передачи лицензии на другой компьютер: мол, если человек захочет поехать в командировку и там поиграть, то переносит лицензию на свой ноутбук и всё такое. Можем попробовать этот способ: я передаю свою лицензию (она при этом записывается, как я понял, на дискету) и отправляю файл по почте, а Вы у себя пробуете её установить (себе игрушку после этого я "крякну" снова -- мне-то это проблем не составит). Но сработает этот способ или нет, я не знаю...


SII: slab пишет: Был бы вам очень благодарен. И попрошу также поделится инструкциями как эту лицензию на мой комп установить. Факир был пьян и фокус не удался :((( В общем, эта КЮ требует, чтобы дискета, на которую будет записана лицензия, сначала была обработана (видимо, программой для переноса лицензий) на том компьютере, куда она будет переноситься. Но это по вполне понятным причинам невозможно: переносить-то на компьютер, который мне физически недоступен... Так что остаётся только ломать с помощью отладчика или ждать, пока какая-нибудь добрая и, в отличие от меня, не слишком ленивая душа напишет генератор ключей :) Если Вы и другие, кто хочет-таки взломать игрушку, готовы попробовать освоить отладчик, то всю информацию собственно по взлому я дам (что изменять, где ставить точки останова и т.п.). Каким отладчиком пользоваться -- особой разницы нет. Лично я использую в основном старый добрый Turbo Debugger 32 (TD32), входящий в комплект Turbo Assembler 5.0 -- привык к нему (точней, к его предыдущим версиям) ещё со времён ДОСа. Конечно, он слабоват и многие вещи в нём сделать нельзя, но для данной задачи он подходит очень даже хорошо, да и удобен в использовании. Можно попробовать также, например, OllyDbg -- я его посмотрел, вроде бы неплохая вещь, хотя кой-что мне там не понравилось, и осваивать его пока что не стал. Ну а SoftICE -- это супер-пупер-мега-инструмент, который может всё, но вот пользоваться им весьма сложно и неудобно, так что осваивать его лично я не рекомендую (кроме, конечно, тех, кто намерен глубоко заняться изучением дебрей машинного кода :) ). Найти эти инструменты можно на www.cracklab.ru (по крайней мере, раньше они там были). Там же можно попробовать найти какой-нибудь шестнадцатеричный редактор (ведь экзешник игры сначала нужно подправить, чтобы он дал запустить его под отладчиком). sp262 пишет: Пардон,я не настолько мало имел в виду.Но я в основном работал с базами и памятью,а не с отладчиками. Прошу прощения, если обидел. Но дистанционно, как Вы понимаете, уровень собеседника узнать трудно...

SII: slab пишет: А не могли бы вы описать поподробнее сам процесс лома. Как пользоватся шестнадцатеричным редактором (каким например, кстати), куда чего ставить итд. Ну, как пользоваться ентим самым редактором, описывать не буду -- метод научного тыка на что существует? ;) Замечу лишь, что во всех, мне попадавшихся, основное окно выглядит практически одинаково: в левой колонке идут шестнадцатеричные смещения (расстояния или адреса от начала файла), затем - подряд 16 байтов информации из файла в шестнадцатеричном виде, ну а в правой колонке -- те же байты информации, но в символьном виде (чтобы можно было прочитать, например, текстовые строки, а не переводить их вручную из шестнадцатеричного вида в символьный). Ну а что касается процесса лома, то его опишу :) Только сразу замечу: поскольку мы будем вносить изменения в экзешник игры, обязательно снимите с него копию на тот случай, если его запорете: тогда можно будет восстановиться с копии и попробовать сломать повторно.

SII: Сначала нужно отучить игрушку (точнее, её модуль защиты) замечать, что она запущена под отладчиком. Для этого вносим изменения в управляющую последовательность модуля защиты внутри экзешника. Для начала убедимся, что у нас нужная версия экзешника. Насколько помню, последняя была 1.043, длина файла -- 1101312 байтов. Для других версий действия остаются принципиально теми же (если, конечно, не поменяют модуль защиты вообще), меняются лишь смещения байтов в файле, которые нужно корректировать. Если версия та, что нужно, загружаем экзешник в шестнадцатеричный редактор. Модуль защиты в упакованном виде, а также его распаковщик (с выполнения которого, собственно, начинается работа программы) и управляющая последовательность находятся в последней, шестой секции EXE-файла. Местоположение её можно узнать из заголовка файла, но объяснять это я не буду -- сей процесс достаточно долгий, сложный и нудный. Замечу лишь, что структура EXE-файла описана в целом ряде источников, так что те, у кого есть желание, могут разобраться с этим самостоятельно. Это может потребоваться в том случае, если нужно будет сломать нашу игрушку другой версии и с другим размером экзешника, ведь в такой ситуации все смещения в файле изменятся, и потребуется узнать, где же начинается искомая секция. Правда, есть и альтернативный способ, о котором скажу позже. Итак, наша шестая секция в файле находится со смещения F0E00 (все числа здесь и далее даются в шестнадцатеричном виде, если прямо не сказано иное). Начало секции занято маленькой программой-распаковщиком модуля защиты, далее идёт этот самый модуль в упакованном виде, ну а ближе к концу -- управляющая последовательность. Она начинается со смещения 10С086. По этому адресу находится двойное слово 000CDCF3 -- оно указывает модулю защиты размер буфера для распаковки основной программы, т.е. самой игры. (Лирическое отступление. Как известно, один байт -- это 8 бит, но современные процессоры умеют за один раз обрабатывать величины большей разрядности. В частности, часто встречаются слова -- два байта, или 16 бит, и двойные слова -- четыре байта или 32 бита. Микропроцессоры наших персоналок считают, что байты в словах и двойных словах хранятся в порядке "младший-старший", т.е. самый младший байт многобайтовой величины будет находиться в файле или в памяти первым, а самый старший -- последним; некоторые другие микропроцессоры, например, PowerPC, считают наоборот). Ниже я даю пример того, как искомое место файла выглядит в окне редактора: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 0010C080 06 00 00 00 EB C7 F3 DC 0C 00 00 CE 10 00 12 00 0010C090 10 00 00 00 9E C0 10 00 0A 00 01 11 00 00 6C C5 0010C0A0 CB F1 15 EF AF 41 FA B4 82 95 14 FE 88 E9 0F 00 0010C0B0 08 00 00 40 1E 00 01 8B 01 00 74 0B 04 00 04 00 0010C0C0 0B 00 08 00 00 D0 1C 00 A1 6F 00 00 5A 62 01 00 0010C0D0 04 00 0C 00 08 00 00 10 00 00 F3 DC 0C 00 0D BE 0010C0E0 1C 00 04 00 0E 00 05 00 01 09 00 00 00 22 E2 FA 0010C0F0 4A 52 EA 74 36 66 0D 00 05 00 02 08 00 00 00 0E Жирным и наклонным выделяет не редактор, а я -- чтобы проще было искать нужные значения по ходу дальнейшего объяснения. Левый столбец -- это смещения (offset) от начала файла, далее идут 16 байтов. Смещение в левом столбце относится к самому левому (младшему) байту строки. Поэтому для удобства сверху дана строчка со смещениями байтов внутри строки. Например, самый левый байт верхней строчки имеет смещение от начала файла 0010C080, а самый правый -- 0010C08F. Итак, первое выделение жирным -- это уже упомянутое двойное слово, задающее размер буфера. Оно состоит из байтов F3, DC, 0C, 00, которые процессор воспринимает в порядке "младший-страший", т.е. значение этого двойного слова -- 000CDCF3. Его мы менять не должны, оно служит лишь ориентиром, поскольку с него начинается управляющая последовательность модуля защиты. Назначение следующего двойного слова (0010CE00) мне неизвестно: я сломал защиту раньше, чем с ним разобрался :) Далее, со смещения 0010C08E, следует первая управляющая запись -- слово (два байта) со значением 0012 (в файле хранятся в обратном порядке -- 12 00), за которым следуют два двойных слова (00000010 и 0010C09E). Они определяют диапазон памяти, с которым затем модуль защиты будет творить страшное злодеяние :) Три байта по смещению 0010C098 выделены наклонным. Это вторая управляющая запись, состоящая из слова 000A и байта 01. Эта команда помещает значение 01 в ячейку памяти модуля защиты. Менять её не надо, но далее мы будем использовать эту команду для удаления нежелательных команд, ведь один раз ты поместил значение в ячейку или 10 -- роли не играет (конечно, до тех пор, пока значение в этой ячейке не должно быть изменено). Жирное выделение со смещения 0010C09B -- это первая мерзопакость модуля защиты. Это управляющее поле состоит из слова 0011, байта 00 и строки из 16 байтов (значение приводить здесь лень). Данная команда приказывает модулю защиты проверить определённый выше, в первой управляющей записи, интервал памяти на совпадение с контрольной суммой, задаваемой строкой из этих самых 16 байтов. Если мы поменяем файл, но не поменяем эту запись, программа не запустится: нам выдадут плакат "EXE file is corrupted" или что-то в этом роде. Берём на заметку и смотрим, что у нас творится дальше. А дальше, по смещению 0010C0AE, идёт выделенное наклонным слово 000F. Эта управляющая запись приказывает модулю защиты проверить наличие отладчика с помощью выполнения машинной инструкции INT 3 (эта инструкция используется самими отладчиками, и не все способны воспринять её адекватно, если её им подсунула сама программа). Большинство отладчиков достаточно умны, чтобы не попасться на эту ловушку, но она действует на нервы, поэтому мы её лучше отключим, о чём будет сказано позже. Со смещения 0010C0B0 идёт управляющая запись, состоящая из слова 0008, трёх двойных слов и ещё одного слова (всего 16 байт). Команда 0008 приказывает модулю защиты распаковать некоторую часть загруженной в память игрушки, а какую именно -- определяется двойными словами этой команды (последнее слово определяет используемый метод упаковки, коих в модуле защиты предусморено 5 или 6, но реально используются только два). Естественно, столь полезную команду мы не трогаем :) По смещению 0010C0C0 (жирное) -- очередная ловушка для отладчика, слово 000B. Эта команда ловит персонально SoftICE. Я её не отключаю по двум причинам: во-первых, этим отладчиком я пользуюсь редко, когда более удобный TD32 не подходит; а во-вторых, у модуля защиты не предусмотрено команды "нет операции", и в качестве таковой мы должны использовать трёхбайтовую команду 000A 01 (см. вторую управляющую запись) и какую-нибудь двухбайтовую команду ловли отладчиков -- в качестве последней я и выбрал эту. Таким образом, после нашей правки запущенный SoftICE модуль защиты всё равно отловит, но вот другие отладчики не сможет. Далее идёт очередная команда распаковки. Смещение 0010C0D2 (наклонное) -- команда 000C, очередная ловля отладчика с помощью инструкции INT 1. Используемый мною TD32 на эту ловушку попадается, поэтому я её заблокировал. Впрочем, даже если отладчик корректно обработает прерывание, вызываемое этой инструкцией, оно всё равно будет нам действовать на нервы, поэтому его лучше отключить. Далее -- снова распаковка. По смещению 0010C0E4 (жирное) находится команда 000E, ловящая отладчик по наличию имени IsDebuggerPresent. TD32 также попадается на эту ловушку -- её нужно блокировать. Со смещения 0010C0E6 находится команда 0005, за которой следует байт 01, двойное слово 00000009 и строка из 9 байтов (количество байтов в ней задано упомянутым двойным словом). Эта команда в шифрованном виде задаёт имя главного файла лицензии -- DG_RJW.lf (то, что это имя файла лицензии, указано байтом 01; далее встретятся и другие значения). Мы её не трогаем. Наконец, последнее наклонное выделение по смещени 0010C0F6 -- это команда 000D, ловящая отладчик по наличию имени UnhandledExceptionFilter. Не знаю, кто на эту ловушку попадается, но на всякий случай я её также заблокировал. Столь подробно управляющую последовательность я расписал для того, чтобы методу взлома любой желающий мог изменить по своим потребностям. Кроме того, разные версии игры имеют разные управляющие последовательности: в них меняются местами команды ловли отладчика и некоторые другие команды, хотя общая идея и значения самих команд не меняются.

SII: Собственно отучение от обнаружения отладчика заключается в том, что мы должны заменить вредные команды управляющей последовательности на безвредные. Так, почти все двухбайтовые команды проверки на наличие отладчика (000F, 000C, 000E и 000D) я забил командой 000B, которая ловит неактивный у меня SoftICE. Несколько сложней с командой 0011, проверяющей контрольную сумму файла. Можно, конечно, пересчитать контрольную сумму (алгоритм мне известен), но для этого нужно писать программу, а это делать лень O:-) Так что будем её забивать безвредными командами. Длина этой команды -- 19 байт. Мы её забьём несколькими трёхбайтовыми командами 000A 01 (как я уже говорил, несколько этих команд подряд никак не сказываются на работе модуля защиты) и двухбайтовыми 000B. Итог наших манипуляций в редакторе показан ниже: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 0010C080 06 00 00 00 EB C7 F3 DC 0C 00 00 CE 10 00 12 00 0010C090 10 00 00 00 9E C0 10 00 0A 00 01 0A 00 01 0A 00 0010C0A0 01 0A 00 01 0A 00 01 0A 00 01 0B 00 0B 00 0B 00 0010C0B0 08 00 00 40 1E 00 01 8B 01 00 74 0B 04 00 04 00 0010C0C0 0B 00 08 00 00 D0 1C 00 A1 6F 00 00 5A 62 01 00 0010C0D0 04 00 0B 00 08 00 00 10 00 00 F3 DC 0C 00 0D BE 0010C0E0 1C 00 04 00 0B 00 05 00 01 09 00 00 00 22 E2 FA 0010C0F0 4A 52 EA 74 36 66 0B 00 05 00 02 08 00 00 00 0E Жирным показаны изменённые мною команды управляющей последовательности. Сделав замену, запускаем игрушку сначала просто так, а затем и под отладчиком -- всё должно благополучно запуститься, и мы должны радостно лицезреть окошко с предложением раскошелиться на покупку законной версии игры :)

SII: А вот далее начинаются главные сложности. Нужно запустить игрушку под отладчиком, понаставить точек останова и заставить её сделать то, что нужно нам, а не что хочется ей. Итак, регистрация. Запускаем отладчик и загружаем в него игрушку. Ставим аппаратную точку останова (hardware breakpoint) на выбор инструкции (instruction fetch) в цикле проверки регистрационного ключа № 1. В данной версии игры проверяемая нами инструкция будет находиться по адресу 015A2F6E. Обычные программные точки останова не годятся, поскольку на момент запуска игры эта область памяти игре ещё не принадлежит -- она выделяется динамически (в ходе работы игры), и в неё распаковывается код модуля защиты. TD32 позволяет поставить аппаратную точку останова на область памяти, ещё не принадлежащую программе, а вот OllyDbg -- нет (SoftICE позволяет что угодно и как угодно, но мы его не используем -- это слишком сложный инструмент). Поэтому в TD32 просто ставим точку останова (меню Breakpoints, пункт меню Hardware breakpoint..., в открывающемся окошке выбираем Cycle: Fetch instruction, Address match: Equal, и в поле Address value вводим значение 015A2F6Eh (буква h в конце говорит отладчику, что число шестнадцатеричное -- одним из недостатков TD32 является то, что он не всегда способен сам понять, что же ему ввели). В случае с OllyDbg придётся действовать обманным путём. Сначала ставим точку останова (хоть программную, хоть аппаратную) на инструкцию по адресу, например, 00F2D133 -- она находится ещё внутри программки-распаковщика модуля защиты, поэтому присутствует в памяти изначально. Запускаем игрушку, она доходит до этого места и останавливается. В регистре EAX, если память не изменяет, в этот момент находится адрес начала управляющей последовательности модуля защиты в памяти -- той самой, что мы корректировали раньше. Теперь удаляем поставленную точку останова и ставим аппаратную на указанный выше адрес 015A2F6E -- к этому моменту модуль защиты уже распакован. Точную последовательность действий с меню не скажу -- смотреть лень, а наизусть не помню (как уже говорил, с OllyDbg я практически не работал, хотя и собираюсь покопаться с ним поглубже -- может, он займёт у меня нишу между TD32 и SoftICE: первый со многими задачами не справляется, а второй слишком сложный и неудобный, хотя и справляется со всем). Итак, у нас стоит аппаратная точка останова на цикле, осуществляющем проверку регистрационного ключа № 1. Для знающих Си привожу текст функции, которая осуществляет эту проверку (дизассемблировано мною, поэтому имена переменных условные): int CheckKey1(int Key1, int UserCode1, int UserCode2, int Lic_6A5) { int esi, ecx, edx, ebx, eax; esi = Lic_6A5 + 52; if (UserCode2 < 1) UserCode2 = 1; ecx = UserCode1 >> 15; edx = ecx & 0xFF00; ecx = (((UserCode1 >> 19) & 0xF) + 510) * 264; ebx = ((UserCode1 >> 8) & 0x1F) * 243; edx |= UserCode1 & 0xFF; eax = ((UserCode1 >> 13) & 0x3F) * 68; ecx += ebx + eax; eax = edx + esi * 2; ebx = esi + eax + UserCode2; edx += ebx * 2 + esi; esi = ecx * 2; ecx = (ecx * 31) + edx; do { edx = ecx & 0x7FFFFFFF; if (edx == Key1) return eax; // Вот сюда мы и влепили нашу точку останова ecx += esi; eax++; } while (eax <= 50); return 0; } Эта функция получает на входе четыре значения: ключ №1, введённый пользователем (Key1), два "пользовательских кода" (UserCode1 и 2) и некое двойное слово из файла лицензии (Lic_6A5). Сразу скажу, что файл лицензии зашифрован, поэтому просто так оттуда это значение не извлечёшь, хотя процедура шифрования мне известна, поэтому, если б не лень, написал бы программу, читающую лицензию самостоятельно :))) UserCode2 всегда остаётся один и тот же -- похоже, он зависит от конфигурации компьютера и т.п. вещей и обеспечивает невозможность переноса игры. А вот UserCode1 генерируется достаточно случайным образом. Смысл действий этой функции таков. Сначала она занимается арифметико-логическим онанизмом над значениями UserCode и Lic_6A5 и получает в итоге некое эталонное число (оно находится в ecx -- эта переменная мною названа так потому, что в реальном машинном коде значение этого числа находится в регистре процессора ECX). Далее в цикле это число сравнивается с Key1, причём предварительно у эталонного числа сбрасывается старший бит (он отвечает за знак числа: когда он равен 0, число неотрицательно). Этот сброс выполняется одновременно с пересылкой эталонного числа в регистр EDX (edx = ecx & 0x7FFFFFFF), а сравнение выполняется оператором if (edx == Key1) return eax. Замечу, что EAX -- это ещё один регистр процессора. В этом цикле он увеличивается на единицу каждый раз, когда сравнение прошло неуспешно, при этом значение эталонного числа (ECX) увеличивается на некую другую величину, находящуюся в ESI. Так повторяется до тех пор, пока эталонное число не совпадёт со значением ключа (в этом случае функция возвратит значение EAX, т.е. номер итерации цикла, на которой сравнение было успешным), либо когда число итераций цикла не превысит 50. Последнее означает, что был введён вообще неверный ключ. Итак, поставив точку останова, запускаем игру (в TD32 нажимаем F9). Она благополучно выводит плакат про покупку и всё такое и ждёт, что же мы выберем. Ну а мы выбираем ручную регистрацию (не онлайновую). Она демонстрирует окошко с двумя пользовательскими кодами (User Code) и полями для ввода двух ключей. Вводим от балды любые числа и жмём ОК. Срабатывает наша точка останова, и мы оказываемся в середине приведённого выше цикла по адресу 015A2F6E на инструкции сравнения CMP EDX, [EBP+8]. В EDX в этот момент лежит очередное эталонное значение, ну а в двойном слове памяти по адресу EBP+8 (т.е. по адресу, равному сумме содержимого регистра EBP и значения 8) -- введённая нами белиберда под названием "ключ № 1". Естественно, сравнение будет неудачным (на допустимое значение ключа можно попасть разве что случайно). Наша задача -- определить эталонное значение для 31-й (десятичное) итерации цикла. Текущий номер итерации, напомню, находится в регистре EAX. Итак, мы остановились, при этом в EAX, если память не изменяет, находится 00000001, а нам нужно 0000001F (это шестнадцатеричный эквивалент десятичного 31). Убираем аппаратную точку останова -- она мешает TD32 продолжать работу (насчёт других отладчиков не знаю) и заменяем её на обычную программную (в TD32 выполняем Breakpoints -> Toggle или F2, стоя в этот момент на команде CMP). Снова запускаем игру, нажав F9 (в TD32 -- в других отладчиках разбирайтесь сами, что-нибудь вроде Run). Вновь останавливаемся на этой же инструкции, только в EAX будет уже 00000002, а в EDX -- новое эталонное значение. Продолжаем сию процедуру до тех пор, пока в EAX не появится значение 0000001F. Всё, мы дошли до нужного момента. В EDX сейчас лежит именно то значение, которое нам требуется (и программу вычисления которого мне лень писать). Тщательно записываем его, после чего приказываем отладчику выполнить одну команду (Step, в TD32 нажимаем F8). Строчка-курсор, показывающая, где в программе мы находимся, переползает на следующую команду -- JZ 15A2F7D или что-нибудь в этом роде; вместо JZ может показывать JE -- это одна и та же команда, означает "переход по нулю" или "переход по равенству". Ну а признаком этого самого нуля или равенства служит так называемый флаг ZF (Zero Flag). Когда он сброшен (равен нулю), он показывает, что предыдущая операция дала ненулевой результат (в случае инструкции сравнения CMP -- что сравниваемые значения не равны), ну а когда установлен (равен единице) -- что был получен ноль или обнаружено равенство. У нас он почти наверняка равен нулю, ведь значение ключа мы вводили от балды. Чтобы, однако, произошёл переход, как будто мы ввели правильный ключ № 1, мы должны поменять значение этого флажка. В TD32 флажки находятся в самой правой колонке экрана, только их обозначения даны без буквы F, например: C=0, Z=0 и т.д. Становимся на поле флажка Z и жмём на пробел, что меняет его значение на противоположное: получаем Z=1. Вновь жмём на F8, и жестоко обманутая нами программа послушно выполняет переход на адрес 15A2F7D, где находится инструкция POP ESI. Снова жмём F8 (POP EBP), опять F8 (RETN 10H) и опять F8. Нас выносит наружу, из функции проверки значения ключа № 1 в вызвавшую её функцию, управляющую диалоговым окном регистрации. В этот момент мы находимся на инструкции PUSH 7F00H, расположенной по адресу 15AFEAE, а в регистре EAX у нас находится 0000001F. Строчкой выше располагается инструкция CALL 15A2EF6 -- именно она вызывает функцию проверки ключа, а ещё выше -- PUSH [EBP+0Ch], которая передаёт функции проверки введённое нами значение ключа. Наша задача -- подменить это значение на найденное эталонное.

SII: Значение ключа 1 располагается в так называемом стеке по адресу [EBP+0Ch]. Изменить его в TD32 можно в нижней левой части экрана, где отображаются данные в памяти. Щёлкаем там сначала левой (чтобы туда перейти), а затем правой кнопкой мыши, во всплывающем меню выбираем Display as -> Long (т.е. показывать всё длинными или двойными словами). После этого жмём Ctrl+G. Появляется окошко с предложением ввести адрес ячейки. Вводим: EBP+0Ch. Отладчик переходит к искомому адресу, только показывает его, естественно, не как сумму регистра и константы, а уже в итоговом виде (при желании можем просуммировать содержимое регистра с 0C самостоятельно -- получим то же самое). Точный адрес назвать не могу: у меня версия уже "зарегистрированная", и повторить регистрацию не могу, разве что сносить игрушку и ставить заново, а это лень :) Став, таким образом, на двойное слово, содержащее введённый нами ключ (оно будет в левом верхнем углу окна данных, и на нём будет мигать курсор), впечатываем на его место эталонное значение, которое было в EDX в тот момент, когда в EAX мы получили 0000001F. При нажатии на первый символ вводимого значения открывается окошко, в котором всё значение и вводится. Поскольку оно шестнадцатеричное, в конце добавляем h, например: 7A35489Dh. Убеждаемся, что новое значение -- правильное (что мы не допустили ошибок при вводе). Ключ № 1 определяет, какую лицензию мы получаем или что ещё должно быть сделано с лицензией. Как мы видели, в конечном счёте он имеет всего 50 допустимых значений, каждое из которых обозначает определённую операцию. Операция 31 - это зарегистрировать стандартную лицензионную игру; несколько других значений я тоже определил (например, 29, похоже, устанавливает период, в течение которого будет работать оценочная версия), остальные было разбирать лень. А вот что делает ключ № 2, я так толком и не понял. Похоже, его назначение зависит от того, какое действие выполняется. В частности, для некоторых действий он не используется вовсе. Если мне память не изменяет, правильное значение ключа № 2 устанавливать не требуется, хотя при регистрации стандартной лицензии он и используется. Насколько помню, я поступил так: поставил точку останова на адрес 15A2EF3, где находится инструкция RETN 8, осуществляющая выход из функции проверки этого ключа, и запускал программу (F9). Когда выполнение здесь останавливалось, я заменял находящееся в регистре EAX значение на 00003FFF -- это максимальная величина, которая может быть получена при обработке ключа № 2, и снова запускал программу. Вот для интересующихся текст функции, обрабатывающей ключ № 2: int CheckKey2(int Key2, int UserCode2) { int edx, esi; esi = 0; edx = 0; if ((Key2 & 0xC2842429) != 0x42042021) return -1; if ((UserCode2 & 1) != 0) edx = 0x100000; if ((UserCode2 & 2) != 0) edx |= 0x10000000; if ((UserCode2 & 4) != 0) edx |= 0x200; if ((UserCode2 & 8) != 0) edx |= 2; if ((UserCode2 & 0x10) != 0) edx |= 0x80; if ((UserCode2 & 0x20) != 0) edx |= 0x1000; if ((UserCode2 & 0x40) != 0) edx |= 0x200000; if ((UserCode2 & 0x80) != 0) edx |= 0x10000; if ((Key2 & 0x10311282) != edx) return -1; if ((Key2 & 0x20000) != 0) esi = 1; if ((Key2 & 0x400000) != 0) esi |= 2; if ((Key2 & 0x10) != 0) esi |= 4; if ((Key2 & 4) != 0) esi |= 8; if ((Key2 & 0x20000000) != 0) esi |= 0x10; if ((Key2 & 0x100) != 0) esi |= 0x20; if ((Key2 & 0x4000) != 0) esi |= 0x40; if ((Key2 & 0x80000) != 0) esi |= 0x80; if ((Key2 & 0x8000000) != 0) esi |= 0x100; if ((Key2 & 0x8000) != 0) esi |= 0x200; if ((Key2 & 0x1000000) != 0) esi |= 0x400; if ((Key2 & 0x40) != 0) esi |= 0x800; if ((Key2 & 0x800) != 0) esi |= 0x1000; if ((Key2 & 0x4000000) != 0) esi |= 0x2000; return esi; } Напомню, что UserCode2 -- это не всегда именно тот код, что отображается в диалоговом окне, иначе бы из этой функции было бы легко получить программку, рассчитывающую искомое значение. Сама проверка ключей выполняется несколько раз (кажется, дважды), но ключ № 1 нам достаточно отследить только первый раз, ведь мы подменяем его значение на правильное, а вот ключ № 2 надо ловить каждый раз, поскольку его значение мы не меняем. Достигается это тем, что после определения нужного значения ключа № 1 мы удаляем точку останова с команды сравнения, а вот для ключа № 2 мы точку останова оставляем, каждый раз заменяя значение в EAX на 3FFF.

SII: Собственно, на этом взлом закончен. Если всё сделано правильно и я нигде в описании не ошибся, мы должны получить лицензионную игрушку (стандартная лицензия). Ежели у кого-то что-то не будет получаться -- обращайтесь по аське 308303999 или пишите на форуме, постараюсь помочь :) Пы.Сы. Затратил на написание этих постов столько времени, что точно успел бы написать программку генерации ключей. Тем более что всё основное для неё есть -- и обе функции проверки ключей, и функция чтения и декодирования файла лицензии (она большая, поэтому здесь её не привожу). Может, побороть-таки свою лень? :)))

Silent: Чего то не получается запустить Защиту против отладчика снял. Запускаю отладчик и загружаю в него DG. Ставлю аппаратную точку останова SII пишет: Поэтому в TD32 просто ставим точку останова (меню Breakpoints, пункт меню Hardware breakpoint..., в открывающемся окошке выбираем Cycle: Fetch instruction, Address match: Equal, и в поле Address value вводим значение 015A2F6Eh Запускаю DG SII пишет: Она благополучно выводит плакат про покупку и всё такое и ждёт, что же мы выберем. Ну а мы выбираем ручную регистрацию (не онлайновую). Она демонстрирует окошко с двумя пользовательскими кодами (User Code) и полями для ввода двух ключей. Вводим от балды любые числа и жмём ОК. А дальше, DG выдает окно Registration Error с надписью RegKey1 was not entered correctly. Please try again. Жмем ОК и попадаем снова на ввод ключей и т.д. Вроде как точка останова не срабатывает? Запускал и через Olly SII пишет: В случае с OllyDbg придётся действовать обманным путём. Сначала ставим точку останова (хоть программную, хоть аппаратную) на инструкцию по адресу, например, 00F2D133 -- она находится ещё внутри программки-распаковщика модуля защиты, поэтому присутствует в памяти изначально. Запускаем игрушку, она доходит до этого места и останавливается. В регистре EAX, если память не изменяет, в этот момент находится адрес начала управляющей последовательности модуля защиты в памяти -- той самой, что мы корректировали раньше. Теперь удаляем поставленную точку останова и ставим аппаратную на указанный выше адрес 015A2F6E -- к этому моменту модуль защиты уже распакован. Но при попытке перейти к адресу 015A2F6E, Olly выдаёт No memory on the specified address Вообщем чего то я не то делаю

SII: Silent пишет: Вроде как точка останова не срабатывает? Да, не срабатывает, что странно... Тут есть две возможные причины: либо Вы что-то неправильно делаете, либо у Вас модуль защиты выполняется в других адресах. На последнее наводит и то, что: Но при попытке перейти к адресу 015A2F6E, Olly выдаёт No memory on the specified address Дело заключается в следующем. Сам модуль защиты в игрушке находится в запакованном виде. Сначала, при запуске игры, управление получает небольшая программка-распаковщик. Адрес точки входа в неё в моей версии -- 00F2D030 (именно на этом адресе будет стоять отладчик сразу после того, как в него загружена игрушка). Если у Вас это не так, то у Вас какая-то другая версия игры, что маловероятно, ведь Вы успешно отключили защиту от отладчика. На всякий случай проверьте, этот ли адрес является стартовым. Далее, поставьте точку останова (любую) на адрес 00F2D146. Там находится команда CALL EAX, которая передаёт управление модулю защиты. В регистре EAX находится адрес перехода -- у меня он равен 015839B0. В этом случае адрес, с которого распакован в память модуль защиты, -- 01580000, ну а тот адрес, на который надо ставить точку останова при регистрации игрушки, получается прибавлением к этому базовому адресу значения 00022F6E. Если же у Вас в EAX находится другое значение, то это значит, что игрушка по каким-то причинам получила от операционки для распаковки модуля защиты другую область памяти. Младшие четыре цифры адреса должны остаться теми же самыми - 39B0, а вот старшие будут соответствовать базовому адресу в Вашем случае. Тогда нужно устанавливать точку останова в соответствии с Вашим базовым адресом. Например, если упомянутая CALL EAX выполняется при EAX = 025039B0, то точку останова надо ставить на 02522F6E (соответственно и другие точки останова ставятся с учётом иного базового адреса). Что же касается указанного Вами поведения OllyDbg, то он тем и отличается от TD32, что не умеет ставить аппаратные точки останова на области памяти, которые ещё не выделены для нужд программы, буфер же для распаковки модуля защиты получается уже в ходе работы программки-распаковщика (вызов операционки для получения буфера производится командой CALL по адресу 00F2D08C; после возврата, т.е. к следующей команде, в регистре EAX будет находиться адрес начала выделенной области -- в моём случае это 01580000). Поэтому складывается впечатление, что у Вас буфер выделен где-то в другом месте, поэтому OllyDbg и не ставит точку останова. Ну а TD32 ставит, только управление туда не передаётся...

Silent: Всё уря, я запустил её Спасибо SII Это помогло SII пишет: Далее, поставьте точку останова (любую) на адрес 00F2D146. Там находится команда CALL EAX, которая передаёт управление модулю защиты. В регистре EAX находится адрес перехода -- у меня он равен 015839B0. В этом случае адрес, с которого распакован в память модуль защиты, -- 01580000, ну а тот адрес, на который надо ставить точку останова при регистрации игрушки, получается прибавлением к этому базовому адресу значения 00022F6E. Если же у Вас в EAX находится другое значение, то это значит, что игрушка по каким-то причинам получила от операционки для распаковки модуля защиты другую область памяти. Младшие четыре цифры адреса должны остаться теми же самыми - 39B0, а вот старшие будут соответствовать базовому адресу в Вашем случае. Тогда нужно устанавливать точку останова в соответствии с Вашим базовым адресом. Например, если упомянутая CALL EAX выполняется при EAX = 025039B0, то точку останова надо ставить на 02522F6E (соответственно и другие точки останова ставятся с учётом иного базового адреса). Действительно у меня адрес для точки останова оказался 01582F6E, для ключа 1 и 01582EF3, для ключа 2 С Уважением Сергей

SII: Krom Kruah пишет: Конечно сравнять Бородино с Ушакова - невежество, да и Ослябя с 229 мм гарвеевского нижн. пояса - примерно еквивалентна Бородинских 194-203 мм крупп (при том - хуже и по площади и по оконечностями и вообще) Ну, что у "Бородино" пояс всего 194 мм, я читал, но, честно говоря, думал, что это компенсировано чем-то другим, например, значительно большей забронированной площадью борта. Я, правда, не помню его водоизмещение, а справочника под рукой нет (я в состоянии очередного переезда, поэтому все книги в запакованном виде хранятся на "складе" -- у приятеля в гараже), но если оно не существенно меньше, чем у "Цесаревича", то непонятно, зачем снижали толщину брони: скорость, по сути, та же, вооружение -- такое же... Silent пишет: Действительно у меня адрес для точки останова оказался 01582F6E, для ключа 1 и 01582EF3, для ключа 2 Получается, эта нехорошая редиска выделила память с адреса 01560000, а не 01580000, как у меня? Что ж, Виндуза -- система загадочная, кроме того, у меня стоит не ХРюша, а 2003 сервер. Может, из-за этого. Хотя, вообще говоря, она хоть при каждом запуске может менять адреса динамически выделяемых блоков -- это сугубо личное дело системы.

SII: В общем, вроде как сделал дурацкий генератор этих идиотских регистрационных ключей. Правда, не знаю, куда его выложить :) Принимаются предложения, а ещё лучше -- помощь в его выкладывании.

SII: Пока писал генератор, нашёл пару ошибок в приведённых выше функциях -- не заметил пару мелочей при дизассемблировании :) В процессе отладки генератора, естественно, всё устранил :) Генератор выслал на указанный адрес. По внешнему виду претензии не принимаются -- терпеть не могу украшать программы :-! У меня и ещё как минимум одного человека (Voskudo) отработал нормально.

Tsushima: SII пишет: Генератор выслал на указанный адрес Генератор получил. Выложу к ночи как только найду подходящий хостинг, чтоб не было если что претензий от обладателей авторского права.

Voskudo: Подтверждаю, всё работает. Только бы пропатчить теперь. Уважаемому SII от меня огромное спасибо. И +1.

SII: Voskudo пишет: Только бы пропатчить теперь Боюсь, что в "зарегистрированной" таким способом игре автоматическое обновление работать не будет. Единственный способ -- ставить и регистрировать оценочную версию, с её помощью скачивать обновления, устанавливать их, а потом уже пользоваться генератором. Обновления под названием update.exe закачиваются в корневой каталог игры, а удаляются оттуда только после их установки. Таким образом, если в промежутке между окончанием скачивания и нажатием "ОК" для установки заглянуть в этот каталог, их оттуда можно будет переписать в безопасное место на будущее, что я и сделал. Только не просите меня разобраться в механизме скачивания обновлений: уж это мне точно будет лень делать :))) Потому что куда проще раз в три месяца сносить игру и ставить оценочную версию. Да, кстати, чтобы игру действительно снести, надо не только дать отработать её процедуре удаления (Uninstall -- слова "инсталляция" применительно к программам в русском литературном языке не существует, а английских кАлек (или калЕк -- кому как больше нравится) я предпочитаю избегать), но и вручную удалить файл R8GHGJG.ocx из Windows\System32, а также два раздела реестра: HKLM\SOFTWARE\Classes\CLSID\{cad4b499-2050-4661-886b-c689fc0b457b} и HKLM\SOFTWARE\Classes\CLSID\{12810-c8ab7556-e424-4b3a-b2b0-283d1bc75db6} (надеюсь, очепяток в этих именах не допустил). Только после этого удастся нормально поставить свежую оценочную версию.

Sandro: SII Все уже снес и готов к новой установке!!! Большое спасибо! Уже куда - нибудь выкладывайте! Если не получится выложить, кто-нибудь, пожаласта сбросьте на alessandro(a)pochtamt.ru

Tsushima: Генератор ключей Комментарии от SII Для использования необходимо распаковать программу в корневой каталог игры (она использует в своей работе файл лицензий -- читает из него два значения), запустить ручную регистрацию игры и ввести пользовательские коды (User Code 1 и 2) в соответствующие поля генератора, после чего нажать на "Генерацию". На выходе получаем два ключа (Key 1 и 2), которые вводим в игру. Ещё два поля ввода -- CK1 и CK2 -- не трогаем. Они служат для экспериментов. Суть в том, что ключи 1 и 2 в игре перерабатываются в два значения, которые я назвал соотвественно CK1 и CK2, и именно эти значения определяют, что будет сделано с игрой при вводе данных значений ключей. В частности, при CK1 = 31 происходит регистрация стандартной лицензии игры. Другие значения CK1 регистрируют, например, оценочную ("триальную") версию и т.п. Всего предусмотрено, если память не изменяет, 37 возможных значений CK1, начиная с 1. Назначение CK2 мне неизвестно, диапазон значений -- от 1 до 16383. Похоже, при некоторых значениях CK1 это значение используется, например, для определения предельного срока использования игры и т.п. вещей. Генератор, опираясь на значения пользовательских кодов, а также двух полей из лицензии (два самых верхних нередактируемых поля), генерирует значения ключей, необходимых для получения указанных значений CK1 и CK2.

Vova: спасибо, все работает!

sp262: Ура! Все встало и пашет. Большой-пребольшой спасыб! и + А может кто еще и ТТХ в игре сможет того? Хотя если они в EXE,то навряд ли.А жаль.

Anton: Спасибо, работает!

Sandro: Спасибо SII пркрасно заработало! P.S. "Кореец" - героическая посудина! Сначала сбежал от "Асамы" сотоварищи, потом бился с 8 истребителями 2 отряда и 4 из них изничтожил, потом бился с 1 и2 отрядами япского флота и только тогда погиб!!! Вечная слава героям!!!

slab: Огромнейшее спасибо. Программисты наши- великие люди!!!

fon_der_Palen: Ну Вы просто возвращаете к жизни!!!

Lorak: Низкий Поклон За Работу! Сам пробовал но не вышло :( Есть еще люди в наших улусах... побежал играть :)

inteceptor: Спасибо!!!

slab: Извиняюсь за глупый вопрос- а как можно удалить файлы игры из реестра?

Voskudo: вручную удалить файл R8GHGJG.ocx из Windows\System32, а также два раздела реестра: HKLM\SOFTWARE\Classes\CLSID\{cad4b499-2050-4661-886b-c689fc0b457b} и HKLM\SOFTWARE\Classes\CLSID\{12810-c8ab7556-e424-4b3a-b2b0-283d1bc75db6}

Sandro: Voskudo пишет: Извиняюсь за глупый вопрос пуск-выполнить-regedit дальше ищите в списочке указанные адреса и кнопкой делет их сносите

SII: slab пишет: Извиняюсь за глупый вопрос- а как можно удалить файлы игры из реестра? Не файлы игры, а разделы реестра. Файлы удаляются из каталогов диска :)

Павел не первый: Runtime Error! И на этом всё заканчивается... Не побился ли файл?

Gorout: Павел не первый пишет: Runtime Error! И на этом всё заканчивается... Не побился ли файл? А Вы точно генератор ключей запускали из каталога игры?

Alex-NN: Скачал и установил "Distans Guns" на свой рабочий ноутбук L5Gx Processor: Intel(R) Pentium(R) 4 CPU 3.00GHz (2 CPUs) Memory: 512MB RAM, ATI MOBILITY RADEON 9700 AGP, 128.0 MB Оценочная версия - грузится нормально, при попытке в меню выбрать Ulsan - "синий экран смерти", полный висяк, и сброс только "волшебной кнопкой " После установки ключа и попытке загрузить любое сражение или кампанию - аналогичные последствия. Снос(с чисткой реестра) и повторная установка версии+патча+ключа результата не дает. Та же самая версия с патчем и ключем была успешно установлена на комп. соседа. Есть ли рекомендации по укрощению моего ноутбука ?

SII: Alex-NN пишет: Есть ли рекомендации по укрощению моего ноутбука ? Выкинуть в мусорку и установить на нормальный комп :) Ну а вообще, какая система и последний ли ДиректХ стоит? (точней, не последний, а последний из серии 9 - т.е. DirectX9.0c вроде как). Ну и обновить драйвера для видео.

Alex-NN: ну, не так, что бы совсем безнадежно. ------------------ System Information ------------------ Time of this report: 4/5/2007, 12:11:25 Machine name: USER4 Operating System: Windows XP Professional (5.1, Build 2600) Service Pack 2 (2600.xpsp_sp2_rtm.040803-2158) Language: Russian (Regional Setting: Russian) System Manufacturer: ASUSTeK Computer Inc. System Model: L5Gx BIOS: Default System BIOS Processor: Intel(R) Pentium(R) 4 CPU 3.00GHz (2 CPUs) Memory: 512MB RAM Page File: 301MB used, 948MB available Windows Dir: C:\WINDOWS DirectX Version: DirectX 9.0c (4.09.0000.0904) DX Setup Parameters: Not found DxDiag Version: 5.03.2600.2180 32bit Unicode Дрова для видюхи-последние.

павел не первый: Было тоже самое на материнке I875 от Gigabit. Причём проблема именно в плате, остальное не трогал. Поле замены платы- всё ок. Видимо игра несовместима с некоторыми железками.

Вова: Господа, мне нужна ваша помощь! У меня не запускается генератор ключей, ХР выдает ошибку Visual C++ ... Просьба: сгенерите кому не трудно соответствующие данные и вышлите мне на почту vova1941@rambler.ru, либо просто напишите сюда (если это не нарушает правила форума). Жду с нетерпением



полная версия страницы