Как стать автором
Обновить

Комментарии 22

Кат-кат-кат
А в чем же основная проблема статьи? Просто я не понимаю пока что вашего жаргона «кат-кат». Хотелось бы исправить это так, чтобы все было, как положено.
Хабракат: <habracut />. Вставить после первой картинки. Чтобы не разуплотняло главную страницу.
Основная проблема статьи в том, что она целиком на главной )
Теперь можно ставить на огромное поле 1 мину и с первого раза пытаться ее поймать. Получится снайпер.
Так кто мешает, «Исследование игры-головоломки «Сапёр» (часть 3): отключение функции автоперемещения мины на первом клике. Теперь можно почувствовать себя настоящим сапёром взорваться сразу!»
Asen, это намёк!
А мина там именно перемещается после клика? А не всё поле генерируется после того, как игрок кликнул по первой клетке.
В XP-версии перемещалась, я когда-то находил адреса, по которым хранится собственно игровое поле, и это было отчетливо видно.
Не знал о существовании программы Cheat Engine, а благодаря вашим статьям узнал — спасибо!
inc [rcx+18]

Пробуем изменить данную команду так, чтобы при открытии новой клетки поля прибавлялась не единица, а, например, максимальное целое число типа INTEGER, т.е 4294967295 ( HEX = FFFFFFFF ):

Как можно наблюдать, переполнение буфера работает в нашу пользу, но не в полной мере

Но где же здесь переполнение буфера? Похоже что это был счётчик открытых пустых клеток (я так и не понял этого из вашего рассказа), но какой смысл несут его странные значения?

Для начала давайте представим архитектуру любого стандартного приложения. Получится примерно следующее:

1) Подключение библиотек, используемых в программе
2) Описания классов и реализация их методов
3) Точка входа. (В си, например, это функция main() )

Давайте сначала представим архитектуру любого стандартного города. Получится примерно следующее:

1) Завоз материалов для строительства
2) Чертежи домов
3) Вокзал (в Питере, например, это Московский вокзал).
Переполнение целочисленного буфера изображено на слайде, который тремя ниже того, который вы привели. Под «странным значением» вы подразумеваете максимальное целое число типа INT?
Переполнение целочисленного буфера изображено на слайде

Я бы на таком слайде ожидал увидеть дамп памяти, в котором отмечены границы буфера (кстати, какого?) и указано что было перезаписано в результате его переполнения.

максимальное целое число типа INT?

Я уж не знаю, что вы называете типом INT, когда у вас 64-битная система, а дизассемблер не пишет ни dword ptr ни qword ptr.
Мне сначала показалось, что система ваша 32-битная, но тогда прибавление 0xffffffff равносильно вычитанию единицы.
А так, ну число какое-то, большое…
При чём здесь переполнение буфера?
Просто фраза красивая, видимо.
Переполнение целочисленного буфера. Иначе же, что это по вашему? Где-то в игре присутствует переменная-счетчик типа INTEGER, которую мы пытаемся переполнить.
Я вам выше привёл ссылку на то, что обычно называют переполнением буфера.
В двух словах, переполнение буфера — это непреднамеренная запись программой данных в свою память. Непреднамеренная, потому что программа намеревалась записать данные в определённый массив/буфер, но в силу ошибок обработки адресов/индексов массива промахнулась мимо целевого буфера и переписала другие данные.

Целочисленные переполнения — это отдельный класс проблем, он может быть связан с буферами, а может быть не связан с ними. Вот я думаю, что если бы сапёр пытался писать в память, адрес которой отличается на 4Г от того, что он ожидал, он бы грохнулся с сегфолтом, а поскольку этого не произошло я и высказал сомнение, что имеет место переполнение буфера.
Вообщето все результаты сапера хранятся в обычном текстовом файлике, который можно поправить руками и вуаля вы открыли все мины за 1 сек. Помню когда то мой отец(любитель этой игры), долго возмащался что я задень побил его годовой рекорд))
Объясните лучше, как в подобных ситуациях быть?
Скриншоты
Речь о правом нижнем угле.
image
image
Если вы использовали «переполнение буфера», то, как я уже говорил, данный способ не может гаранировать 100% победы. Вероятность победы прямопропорциональна количеству открытых клеток при первом клике по полю. Т.е чем больше клеток удалось открыть, тем большая вероятность отсеивания большего количества мин. В данном случае отсеивается не менее 50% клеток поля, а вместе с ними и 50% всех мин( об этом сказано с статье и видно из вашего скрина ). Далее же придется полагаться на свой опыт в игре и удачу, так как способ, основанный на переполнении буфера, лишь упрощает процесс игры, а не полностью его решает :)
Вы молодец, что занялись подобного рода развлечениями. Копаться в дизассемблированном коде игр приятно и, иногда, небесполезно. Читать об этом тоже занятно, тем более, что пишите вы интересно. Продолжайте изыскания, пишите еще.

Теперь о том что плохо.
В первой части вашей статьи написана ерунда. Код, на который вы обратили внимание (inc[rcx + 0x18]), действительно подсчитывает количество открытых клеток. Но, во-первых, когда вы заменяете его на (add[rcx + 0x18], 0xFFFFFFFF) не происходит никакого переполнения буфера, просто вместо прибавления единички, она отнимается. Зато, благодаря тому, что вы варварски затираете две инструкции, (xor edx, edx и mov r13, r10) происходит небольшой побочный эффект. Кстати, попробуйте, убрать только mov r13, r10, тоже интересно получается. Во-вторых, этот счетчик открытых клеток служит только для одного: определять когда игра закончилась. Это происходит так:
(if (board->width) * (board->height) == board->openedFields + board->numMines) {
board->gameWin();
}
так что, изменяя эту ячейку памяти, вы абсолютно ни на что не влияете.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации